summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCsaba Hruska <csaba.hruska@gmail.com>2015-09-16 01:00:41 +0200
committerCsaba Hruska <csaba.hruska@gmail.com>2015-09-16 01:00:41 +0200
commit030fb57e15c35baaee7d4d30e012d3e51e4d871c (patch)
treea577bbb015d0e524f68d69c5676486ee5cea7f5d
parent4cf104ca45b4f3f278b3cc8275a9690be3c23fe2 (diff)
add C++ lib
-rw-r--r--lib/RT.cpp23
-rw-r--r--lib/RT.hpp37
-rw-r--r--lib/json.hpp7307
-rw-r--r--templates/data.cpp.ede42
-rw-r--r--templates/data.hpp.ede19
5 files changed, 7368 insertions, 60 deletions
diff --git a/lib/RT.cpp b/lib/RT.cpp
new file mode 100644
index 0000000..b8a1aea
--- /dev/null
+++ b/lib/RT.cpp
@@ -0,0 +1,23 @@
1#include "RT.hpp"
2
3template<> json toJSON<String>(String &v) {
4 return json(v);
5}
6
7template<> json toJSON<Float>(Float &v) {
8 return json(v);
9}
10
11template<> json toJSON<bool>(bool &v) {
12 return json(v);
13}
14
15template<> json toJSON<int>(int &v) {
16 return json(v);
17}
18
19template<> json toJSON<unsigned int>(unsigned int &v) {
20 return json(v);
21}
22
23
diff --git a/lib/RT.hpp b/lib/RT.hpp
new file mode 100644
index 0000000..1d90f7c
--- /dev/null
+++ b/lib/RT.hpp
@@ -0,0 +1,37 @@
1#ifndef HEADER_RT_H
2#define HEADER_RT_H
3
4#include <vector>
5#include <map>
6#include <string>
7
8#include "json.hpp"
9
10using json = nlohmann::json;
11
12typedef int Int;
13typedef int Int32;
14typedef unsigned int Word;
15typedef unsigned int Word32;
16typedef float Float;
17typedef bool Bool;
18typedef std::string String;
19
20template<typename T>
21json toJSON(T &v);
22
23template<typename any>
24json toJSON(std::vector<any> &v) {
25 json obj = json::array();
26 for (any i : v) {
27 obj.push_back(toJSON(i));
28 }
29 return obj;
30}
31
32template<typename k, typename v>
33json toJSON(std::map<k,v> &value) {
34 return json();
35}
36
37#endif \ No newline at end of file
diff --git a/lib/json.hpp b/lib/json.hpp
new file mode 100644
index 0000000..bdea958
--- /dev/null
+++ b/lib/json.hpp
@@ -0,0 +1,7307 @@
1/*!
2@mainpage
3
4These pages contain the API documentation of JSON for Modern C++, a C++11
5header-only JSON class.
6
7Class @ref nlohmann::basic_json is a good entry point for the documentation.
8
9@copyright The code is licensed under the [MIT
10 License](http://opensource.org/licenses/MIT):
11 <br>
12 Copyright &copy; 2013-2015 Niels Lohmann.
13 <br>
14 Permission is hereby granted, free of charge, to any person
15 obtaining a copy of this software and associated documentation files
16 (the "Software"), to deal in the Software without restriction,
17 including without limitation the rights to use, copy, modify, merge,
18 publish, distribute, sublicense, and/or sell copies of the Software,
19 and to permit persons to whom the Software is furnished to do so,
20 subject to the following conditions:
21 <br>
22 The above copyright notice and this permission notice shall be
23 included in all copies or substantial portions of the Software.
24 <br>
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 SOFTWARE.
33
34@author [Niels Lohmann](http://nlohmann.me)
35@see https://github.com/nlohmann/json to download the source code
36*/
37
38#ifndef NLOHMANN_JSON_HPP
39#define NLOHMANN_JSON_HPP
40
41#include <algorithm>
42#include <array>
43#include <ciso646>
44#include <cmath>
45#include <cstdio>
46#include <functional>
47#include <initializer_list>
48#include <iomanip>
49#include <iostream>
50#include <iterator>
51#include <limits>
52#include <map>
53#include <memory>
54#include <sstream>
55#include <string>
56#include <type_traits>
57#include <utility>
58#include <vector>
59
60// enable ssize_t on MinGW
61#ifdef __GNUC__
62 #ifdef __MINGW32__
63 #include <sys/types.h>
64 #endif
65#endif
66
67// enable ssize_t for MSVC
68#ifdef _MSC_VER
69 #include <basetsd.h>
70 using ssize_t = SSIZE_T;
71#endif
72
73/*!
74@brief namespace for Niels Lohmann
75@see https://github.com/nlohmann
76*/
77namespace nlohmann
78{
79
80
81/*!
82@brief unnamed namespace with internal helper functions
83*/
84namespace
85{
86/*!
87@brief Helper to determine whether there's a key_type for T.
88@sa http://stackoverflow.com/a/7728728/266378
89*/
90template<typename T>
91struct has_mapped_type
92{
93 private:
94 template<typename C> static char test(typename C::mapped_type*);
95 template<typename C> static int test(...);
96 public:
97 enum { value = sizeof(test<T>(0)) == sizeof(char) };
98};
99
100/// "equality" comparison for floating point numbers
101template<typename T>
102static bool approx(const T a, const T b)
103{
104 return not (a > b or a < b);
105}
106}
107
108/*!
109@brief a class to store JSON values
110
111@tparam ObjectType type for JSON objects (@c std::map by default; will be used
112in @ref object_t)
113@tparam ArrayType type for JSON arrays (@c std::vector by default; will be used
114in @ref array_t)
115@tparam StringType type for JSON strings and object keys (@c std::string by
116default; will be used in @ref string_t)
117@tparam BooleanType type for JSON booleans (@c `bool` by default; will be used
118in @ref boolean_t)
119@tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by
120default; will be used in @ref number_integer_t)
121@tparam NumberFloatType type for JSON floating-point numbers (@c `double` by
122default; will be used in @ref number_float_t)
123@tparam AllocatorType type of the allocator to use (@c `std::allocator` by
124default)
125
126@requirement The class satisfies the following concept requirements:
127- Basic
128 - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
129 JSON values can be default constructed. The result will be a JSON null value.
130 - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
131 A JSON value can be constructed from an rvalue argument.
132 - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
133 A JSON value can be copy-constrcuted from an lvalue expression.
134 - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
135 A JSON value van be assigned from an rvalue argument.
136 - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
137 A JSON value can be copy-assigned from an lvalue expression.
138 - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
139 JSON values can be destructed.
140- Layout
141 - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
142 JSON values have
143 [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
144 All non-static data members are private and standard layout types, the class
145 has no virtual functions or (virtual) base classes.
146- Library-wide
147 - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
148 JSON values can be compared with `==`, see @ref
149 operator==(const_reference,const_reference).
150 - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
151 JSON values can be compared with `<`, see @ref
152 operator<(const_reference,const_reference).
153 - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
154 Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
155 other compatible types, using unqualified function call @ref swap().
156 - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
157 JSON values can be compared against `std::nullptr_t` objects which are used
158 to model the `null` value.
159- Container
160 - [Container](http://en.cppreference.com/w/cpp/concept/Container):
161 JSON values can be used like STL containers and provide iterator access.
162 - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
163 JSON values can be used like STL containers and provide reverse iterator
164 access.
165
166@internal
167@note ObjectType trick from http://stackoverflow.com/a/9860911
168@endinternal
169
170@see RFC 7159 <http://rfc7159.net/rfc7159>
171*/
172template <
173 template<typename U, typename V, typename... Args> class ObjectType = std::map,
174 template<typename U, typename... Args> class ArrayType = std::vector,
175 class StringType = std::string,
176 class BooleanType = bool,
177 class NumberIntegerType = int64_t,
178 class NumberFloatType = double,
179 template<typename U> class AllocatorType = std::allocator
180 >
181class basic_json
182{
183 private:
184 /// workaround type for MSVC
185 using basic_json_t = basic_json<ObjectType,
186 ArrayType,
187 StringType,
188 BooleanType,
189 NumberIntegerType,
190 NumberFloatType,
191 AllocatorType>;
192
193 public:
194
195 /////////////////////
196 // container types //
197 /////////////////////
198
199 /// @name container types
200 /// @{
201
202 /// the type of elements in a basic_json container
203 using value_type = basic_json;
204
205 /// the type of an element reference
206 using reference = value_type&;
207
208 /// the type of an element const reference
209 using const_reference = const value_type&;
210
211 /// a type to represent differences between iterators
212 using difference_type = std::ptrdiff_t;
213
214 /// a type to represent container sizes
215 using size_type = std::size_t;
216
217 /// the allocator type
218 using allocator_type = AllocatorType<basic_json>;
219
220 /// the type of an element pointer
221 using pointer = typename std::allocator_traits<allocator_type>::pointer;
222 /// the type of an element const pointer
223 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
224
225 // forward declaration
226 template<typename Base> class json_reverse_iterator;
227
228 /// an iterator for a basic_json container
229 class iterator;
230 /// a const iterator for a basic_json container
231 class const_iterator;
232 /// a reverse iterator for a basic_json container
233 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
234 /// a const reverse iterator for a basic_json container
235 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
236
237 /// @}
238
239
240 /*!
241 @brief returns the allocator associated with the container
242 */
243 static allocator_type get_allocator()
244 {
245 return allocator_type();
246 }
247
248
249 ///////////////////////////
250 // JSON value data types //
251 ///////////////////////////
252
253 /// @name JSON value data types
254 /// @{
255
256 /*!
257 @brief a type for an object
258
259 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
260 > An object is an unordered collection of zero or more name/value pairs,
261 > where a name is a string and a value is a string, number, boolean, null,
262 > object, or array.
263
264 To store objects in C++, a type is defined by the template parameters @a
265 ObjectType which chooses the container (e.g., `std::map` or
266 `std::unordered_map`), @a StringType which chooses the type of the keys or
267 names, and @a AllocatorType which chooses the allocator to use.
268
269 #### Default type
270
271 With the default values for @a ObjectType (`std::map`), @a StringType
272 (`std::string`), and @a AllocatorType (`std::allocator`), the default value
273 for @a object_t is:
274
275 @code {.cpp}
276 std::map<
277 std::string, // key_type
278 basic_json, // value_type
279 std::less<std::string>, // key_compare
280 std::allocator<std::pair<const std::string, basic_json>> // allocator_type
281 >
282 @endcode
283
284 #### Behavior
285
286 The choice of @a object_t influences the behavior of the JSON class. With
287 the default type, objects have the following behavior:
288
289 - When all names are unique, objects will be interoperable in the sense
290 that all software implementations receiving that object will agree on the
291 name-value mappings.
292 - When the names within an object are not unique, later stored name/value
293 pairs overwrite previously stored name/value pairs, leaving the used
294 names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will
295 be treated as equal and both stored as `{"key": 1}`.
296 - Internally, name/value pairs are stored in lexicographical order of the
297 names. Objects will also be serialized (see @ref dump) in this order. For
298 instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and
299 serialized as `{"a": 2, "b": 1}`.
300 - When comparing objects, the order of the name/value pairs is irrelevant.
301 This makes objects interoperable in the sense that they will not be
302 affected by these differences. For instance, `{"b": 1, "a": 2}` and
303 `{"a": 2, "b": 1}` will be treated as equal.
304
305 #### Limits
306
307 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
308 > An implementation may set limits on the maximum depth of nesting.
309
310 In this class, the object's limit of nesting is not constraint explicitly.
311 However, a maximum depth of nesting may be introduced by the compiler or
312 runtime environment. A theoretical limit can be queried by calling the @ref
313 max_size function of a JSON object.
314
315 #### Storage
316
317 Objects are stored as pointers in a `basic_json` type. That is, for any
318 access to object values, a pointer of type `object_t*` must be dereferenced.
319
320 @sa array_t
321 */
322 using object_t = ObjectType<StringType,
323 basic_json,
324 std::less<StringType>,
325 AllocatorType<std::pair<const StringType,
326 basic_json>>>;
327
328 /*!
329 @brief a type for an array
330
331 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
332 > An array is an ordered sequence of zero or more values.
333
334 To store objects in C++, a type is defined by the template parameters @a
335 ArrayType which chooses the container (e.g., `std::vector` or `std::list`)
336 and @a AllocatorType which chooses the allocator to use.
337
338 #### Default type
339
340 With the default values for @a ArrayType (`std::vector`) and @a
341 AllocatorType (`std::allocator`), the default value for @a array_t is:
342
343 @code {.cpp}
344 std::vector<
345 basic_json, // value_type
346 std::allocator<basic_json> // allocator_type
347 >
348 @endcode
349
350 #### Limits
351
352 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
353 > An implementation may set limits on the maximum depth of nesting.
354
355 In this class, the array's limit of nesting is not constraint explicitly.
356 However, a maximum depth of nesting may be introduced by the compiler or
357 runtime environment. A theoretical limit can be queried by calling the @ref
358 max_size function of a JSON array.
359
360 #### Storage
361
362 Arrays are stored as pointers in a `basic_json` type. That is, for any
363 access to array values, a pointer of type `array_t*` must be dereferenced.
364 */
365 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
366
367 /*!
368 @brief a type for a string
369
370 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
371 > A string is a sequence of zero or more Unicode characters.
372
373 To store objects in C++, a type is defined by the template parameters @a
374 StringType which chooses the container (e.g., `std::string`) to use.
375
376 Unicode values are split by the JSON class into byte-sized characters
377 during deserialization.
378
379 #### Default type
380
381 With the default values for @a StringType (`std::string`), the default
382 value for @a string_t is:
383
384 @code {.cpp}
385 std::string
386 @endcode
387
388 #### String comparison
389
390 [RFC 7159](http://rfc7159.net/rfc7159) states:
391 > Software implementations are typically required to test names of object
392 > members for equality. Implementations that transform the textual
393 > representation into sequences of Unicode code units and then perform the
394 > comparison numerically, code unit by code unit, are interoperable in the
395 > sense that implementations will agree in all cases on equality or
396 > inequality of two strings. For example, implementations that compare
397 > strings with escaped characters unconverted may incorrectly find that
398 > `"a\\b"` and `"a\u005Cb"` are not equal.
399
400 This implementation is interoperable as it does compare strings code unit
401 by code unit.
402
403 #### Storage
404
405 String values are stored as pointers in a `basic_json` type. That is, for
406 any access to string values, a pointer of type `string_t*` must be
407 dereferenced.
408 */
409 using string_t = StringType;
410
411 /*!
412 @brief a type for a boolean
413
414 [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
415 type which differentiates the two literals `true` and `false`.
416
417 To store objects in C++, a type is defined by the template parameter @a
418 BooleanType which chooses the type to use.
419
420 #### Default type
421
422 With the default values for @a BooleanType (`bool`), the default value for
423 @a boolean_t is:
424
425 @code {.cpp}
426 bool
427 @endcode
428
429 #### Storage
430
431 Boolean values are stored directly inside a `basic_json` type.
432 */
433 using boolean_t = BooleanType;
434
435 /*!
436 @brief a type for a number (integer)
437
438 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
439 > The representation of numbers is similar to that used in most programming
440 > languages. A number is represented in base 10 using decimal digits. It
441 > contains an integer component that may be prefixed with an optional minus
442 > sign, which may be followed by a fraction part and/or an exponent part.
443 > Leading zeros are not allowed. (...) Numeric values that cannot be
444 > represented in the grammar below (such as Infinity and NaN) are not
445 > permitted.
446
447 This description includes both integer and floating-point numbers. However,
448 C++ allows more precise storage if it is known whether the number is an
449 integer or a floating-point number. Therefore, two different types, @ref
450 number_integer_t and @ref number_float_t are used.
451
452 To store integer numbers in C++, a type is defined by the template
453 parameter @a NumberIntegerType which chooses the type to use.
454
455 #### Default type
456
457 With the default values for @a NumberIntegerType (`int64_t`), the default
458 value for @a number_integer_t is:
459
460 @code {.cpp}
461 int64_t
462 @endcode
463
464 #### Default behavior
465
466 - The restrictions about leading zeros is not enforced in C++. Instead,
467 leading zeros in integer literals lead to an interpretation as octal
468 number. Internally, the value will be stored as decimal number. For
469 instance, the C++ integer literal `010` will be serialized to `8`. During
470 deserialization, leading zeros yield an error.
471 - Not-a-number (NaN) values will be serialized to `null`.
472
473 #### Limits
474
475 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
476 > An implementation may set limits on the range and precision of numbers.
477
478 When the default type is used, the maximal integer number that can be
479 stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
480 that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
481 that are out of range will yield over/underflow when used in a constructor.
482 During deserialization, too large or small integer numbers will be
483 automatically be stored as @ref number_float_t.
484
485 [RFC 7159](http://rfc7159.net/rfc7159) further states:
486 > Note that when such software is used, numbers that are integers and are
487 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
488 > that implementations will agree exactly on their numeric values.
489
490 As this range is a subrange of the exactly supported range [INT64_MIN,
491 INT64_MAX], this class's integer type is interoperable.
492
493 #### Storage
494
495 Integer number values are stored directly inside a `basic_json` type.
496 */
497 using number_integer_t = NumberIntegerType;
498
499 /*!
500 @brief a type for a number (floating-point)
501
502 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
503 > The representation of numbers is similar to that used in most programming
504 > languages. A number is represented in base 10 using decimal digits. It
505 > contains an integer component that may be prefixed with an optional minus
506 > sign, which may be followed by a fraction part and/or an exponent part.
507 > Leading zeros are not allowed. (...) Numeric values that cannot be
508 > represented in the grammar below (such as Infinity and NaN) are not
509 > permitted.
510
511 This description includes both integer and floating-point numbers. However,
512 C++ allows more precise storage if it is known whether the number is an
513 integer or a floating-point number. Therefore, two different types, @ref
514 number_integer_t and @ref number_float_t are used.
515
516 To store floating-point numbers in C++, a type is defined by the template
517 parameter @a NumberFloatType which chooses the type to use.
518
519 #### Default type
520
521 With the default values for @a NumberFloatType (`double`), the default
522 value for @a number_float_t is:
523
524 @code {.cpp}
525 double
526 @endcode
527
528 #### Default behavior
529
530 - The restrictions about leading zeros is not enforced in C++. Instead,
531 leading zeros in floating-point literals will be ignored. Internally, the
532 value will be stored as decimal number. For instance, the C++
533 floating-point literal `01.2` will be serialized to `1.2`. During
534 deserialization, leading zeros yield an error.
535 - Not-a-number (NaN) values will be serialized to `null`.
536
537 #### Limits
538
539 [RFC 7159](http://rfc7159.net/rfc7159) states:
540 > This specification allows implementations to set limits on the range and
541 > precision of numbers accepted. Since software that implements IEEE
542 > 754-2008 binary64 (double precision) numbers is generally available and
543 > widely used, good interoperability can be achieved by implementations that
544 > expect no more precision or range than these provide, in the sense that
545 > implementations will approximate JSON numbers within the expected
546 > precision.
547
548 This implementation does exactly follow this approach, as it uses double
549 precision floating-point numbers. Note values smaller than
550 `-1.79769313486232e+308` and values greather than `1.79769313486232e+308`
551 will be stored as NaN internally and be serialized to `null`.
552
553 #### Storage
554
555 Floating-point number values are stored directly inside a `basic_json` type.
556 */
557 using number_float_t = NumberFloatType;
558
559 /// @}
560
561
562 ///////////////////////////
563 // JSON type enumeration //
564 ///////////////////////////
565
566 /*!
567 @brief the JSON type enumeration
568
569 This enumeration collects the different JSON types. It is internally used
570 to distinguish the stored values, and the functions is_null, is_object,
571 is_array, is_string, is_boolean, is_number, and is_discarded rely on it.
572 */
573 enum class value_t : uint8_t
574 {
575 null, ///< null value
576 object, ///< object (unordered set of name/value pairs)
577 array, ///< array (ordered collection of values)
578 string, ///< string value
579 boolean, ///< boolean value
580 number_integer, ///< number value (integer)
581 number_float, ///< number value (floating-point)
582 discarded ///< discarded by the the parser callback function
583 };
584
585
586 private:
587 ////////////////////////
588 // JSON value storage //
589 ////////////////////////
590
591 /// a JSON value
592 union json_value
593 {
594 /// object (stored with pointer to save storage)
595 object_t* object;
596 /// array (stored with pointer to save storage)
597 array_t* array;
598 /// string (stored with pointer to save storage)
599 string_t* string;
600 /// boolean
601 boolean_t boolean;
602 /// number (integer)
603 number_integer_t number_integer;
604 /// number (floating-point)
605 number_float_t number_float;
606
607 /// default constructor (for null values)
608 json_value() noexcept = default;
609 /// constructor for booleans
610 json_value(boolean_t v) noexcept : boolean(v) {}
611 /// constructor for numbers (integer)
612 json_value(number_integer_t v) noexcept : number_integer(v) {}
613 /// constructor for numbers (floating-point)
614 json_value(number_float_t v) noexcept : number_float(v) {}
615 /// constructor for empty values of a given type
616 json_value(value_t t)
617 {
618 switch (t)
619 {
620 case (value_t::null):
621 case (value_t::discarded):
622 {
623 break;
624 }
625
626 case (value_t::object):
627 {
628 AllocatorType<object_t> alloc;
629 object = alloc.allocate(1);
630 alloc.construct(object);
631 break;
632 }
633
634 case (value_t::array):
635 {
636 AllocatorType<array_t> alloc;
637 array = alloc.allocate(1);
638 alloc.construct(array);
639 break;
640 }
641
642 case (value_t::string):
643 {
644 AllocatorType<string_t> alloc;
645 string = alloc.allocate(1);
646 alloc.construct(string, "");
647 break;
648 }
649
650 case (value_t::boolean):
651 {
652 boolean = boolean_t(false);
653 break;
654 }
655
656 case (value_t::number_integer):
657 {
658 number_integer = number_integer_t(0);
659 break;
660 }
661
662 case (value_t::number_float):
663 {
664 number_float = number_float_t(0.0);
665 break;
666 }
667 }
668 }
669
670 /// constructor for strings
671 json_value(const string_t& value)
672 {
673 AllocatorType<string_t> alloc;
674 string = alloc.allocate(1);
675 alloc.construct(string, value);
676 }
677
678 /// constructor for objects
679 json_value(const object_t& value)
680 {
681 AllocatorType<object_t> alloc;
682 object = alloc.allocate(1);
683 alloc.construct(object, value);
684 }
685
686 /// constructor for arrays
687 json_value(const array_t& value)
688 {
689 AllocatorType<array_t> alloc;
690 array = alloc.allocate(1);
691 alloc.construct(array, value);
692 }
693 };
694
695
696 public:
697 //////////////////////////
698 // JSON parser callback //
699 //////////////////////////
700
701 /*!
702 @brief JSON callback events
703
704 This enumeration lists the parser events that can trigger calling a
705 callback function of type @ref parser_callback_t during parsing.
706 */
707 enum class parse_event_t : uint8_t
708 {
709 /// the parser read `{` and started to process a JSON object
710 object_start,
711 /// the parser read `}` and finished processing a JSON object
712 object_end,
713 /// the parser read `[` and started to process a JSON array
714 array_start,
715 /// the parser read `]` and finished processing a JSON array
716 array_end,
717 /// the parser read a key of a value in an object
718 key,
719 /// the parser finished reading a JSON value
720 value
721 };
722
723 /*!
724 @brief per-element parser callback type
725
726 With a parser callback function, the result of parsing a JSON text can be
727 influenced. When passed to @ref parse(std::istream&, parser_callback_t) or
728 @ref parse(const string_t&, parser_callback_t), it is called on certain
729 events (passed as @ref parse_event_t via parameter @a event) with a set
730 recursion depth @a depth and context JSON value @a parsed. The return value
731 of the callback function is a boolean indicating whether the element that
732 emitted the callback shall be kept or not.
733
734 We distinguish six scenarios (determined by the event type) in which the
735 callback function can be called. The following table describes the values
736 of the parameters @a depth, @a event, and @a parsed.
737
738 parameter @a event | description | parameter @a depth | parameter @a parsed
739 ------------------ | ----------- | ------------------ | -------------------
740 parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
741 parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
742 parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
743 parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
744 parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
745 parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
746
747 Discarding a value (i.e., returning `false`) has different effects depending on the
748 context in which function was called:
749
750 - Discarded values in structured types are skipped. That is, the parser
751 will behave as if the discarded value was never read.
752 - In case a value outside a structured type is skipped, it is replaced with
753 `null`. This case happens if the top-level element is skipped.
754
755 @param[in] depth the depth of the recursion during parsing
756
757 @param[in] event an event of type parse_event_t indicating the context in
758 the callback function has been called
759
760 @param[in,out] parsed the current intermediate parse result; note that
761 writing to this value has no effect for parse_event_t::key events
762
763 @return Whether the JSON value which called the function during parsing
764 should be kept (`true`) or not (`false`). In the latter case, it is either
765 skipped completely or replaced by an empty discarded object.
766
767 @sa @ref parse(std::istream&, parser_callback_t) or
768 @ref parse(const string_t&, parser_callback_t) for examples
769 */
770 using parser_callback_t = std::function<bool(
771 int depth, parse_event_t event, basic_json& parsed)>;
772
773
774 //////////////////
775 // constructors //
776 //////////////////
777
778 /*!
779 @brief create an empty value with a given type
780
781 Create an empty JSON value with a given type. The value will be default
782 initialized with an empty value which depends on the type:
783
784 Value type | initial value
785 ----------- | -------------
786 null | `null`
787 boolean | `false`
788 string | `""`
789 number | `0`
790 object | `{}`
791 array | `[]`
792
793 @param[in] value the type of the value to create
794
795 @complexity Constant.
796
797 @throw std::bad_alloc if allocation for object, array, or string value
798 fails
799
800 @liveexample{The following code shows the constructor for different @ref
801 value_t values,basic_json__value_t}
802 */
803 basic_json(const value_t value)
804 : m_type(value), m_value(value)
805 {}
806
807 /*!
808 @brief create a null object (implicitly)
809
810 Create a `null` JSON value. This is the implicit version of the `null`
811 value constructor as it takes no parameters.
812
813 @complexity Constant.
814
815 @requirement This function satisfies the Container requirements:
816 - The complexity is constant.
817 - As postcondition, it holds: `basic_json().empty() == true`.
818
819 @liveexample{The following code shows the constructor for a `null` JSON
820 value.,basic_json}
821
822 @sa basic_json(std::nullptr_t)
823 */
824 basic_json() noexcept = default;
825
826 /*!
827 @brief create a null object (explicitly)
828
829 Create a `null` JSON value. This is the explicitly version of the `null`
830 value constructor as it takes a null pointer as parameter. It allows to
831 create `null` values by explicitly assigning a @c nullptr to a JSON value.
832 The passed null pointer itself is not read - it is only used to choose the
833 right constructor.
834
835 @complexity Constant.
836
837 @liveexample{The following code shows the constructor with null pointer
838 parameter.,basic_json__nullptr_t}
839
840 @sa basic_json()
841 */
842 basic_json(std::nullptr_t) noexcept
843 : basic_json(value_t::null)
844 {}
845
846 /*!
847 @brief create an object (explicit)
848
849 Create an object JSON value with a given content.
850
851 @param[in] value a value for the object
852
853 @complexity Linear in the size of the passed @a value.
854
855 @throw std::bad_alloc if allocation for object value fails
856
857 @liveexample{The following code shows the constructor with an @ref object_t
858 parameter.,basic_json__object_t}
859
860 @sa basic_json(const CompatibleObjectType&)
861 */
862 basic_json(const object_t& value)
863 : m_type(value_t::object), m_value(value)
864 {}
865
866 /*!
867 @brief create an object (implicit)
868
869 Create an object JSON value with a given content. This constructor allows
870 any type that can be used to construct values of type @ref object_t.
871 Examples include the types `std::map` and `std::unordered_map`.
872
873 @tparam CompatibleObjectType an object type whose `key_type` and
874 `value_type` is compatible to @ref object_t
875
876 @param[in] value a value for the object
877
878 @complexity Linear in the size of the passed @a value.
879
880 @throw std::bad_alloc if allocation for object value fails
881
882 @liveexample{The following code shows the constructor with several
883 compatible object type parameters.,basic_json__CompatibleObjectType}
884
885 @sa basic_json(const object_t&)
886 */
887 template <class CompatibleObjectType, typename
888 std::enable_if<
889 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
890 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
891 = 0>
892 basic_json(const CompatibleObjectType& value)
893 : m_type(value_t::object)
894 {
895 AllocatorType<object_t> alloc;
896 m_value.object = alloc.allocate(1);
897 using std::begin;
898 using std::end;
899 alloc.construct(m_value.object, begin(value), end(value));
900 }
901
902 /*!
903 @brief create an array (explicit)
904
905 Create an array JSON value with a given content.
906
907 @param[in] value a value for the array
908
909 @complexity Linear in the size of the passed @a value.
910
911 @throw std::bad_alloc if allocation for array value fails
912
913 @liveexample{The following code shows the constructor with an @ref array_t
914 parameter.,basic_json__array_t}
915
916 @sa basic_json(const CompatibleArrayType&)
917 */
918 basic_json(const array_t& value)
919 : m_type(value_t::array), m_value(value)
920 {}
921
922 /*!
923 @brief create an array (implicit)
924
925 Create an array JSON value with a given content. This constructor allows
926 any type that can be used to construct values of type @ref array_t.
927 Examples include the types `std::vector`, `std::list`, and `std::set`.
928
929 @tparam CompatibleArrayType an object type whose `value_type` is compatible
930 to @ref array_t
931
932 @param[in] value a value for the array
933
934 @complexity Linear in the size of the passed @a value.
935
936 @throw std::bad_alloc if allocation for array value fails
937
938 @liveexample{The following code shows the constructor with several
939 compatible array type parameters.,basic_json__CompatibleArrayType}
940
941 @sa basic_json(const array_t&)
942 */
943 template <class CompatibleArrayType, typename
944 std::enable_if<
945 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
946 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
947 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
948 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
949 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
950 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
951 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
952 = 0>
953 basic_json(const CompatibleArrayType& value)
954 : m_type(value_t::array)
955 {
956 AllocatorType<array_t> alloc;
957 m_value.array = alloc.allocate(1);
958 using std::begin;
959 using std::end;
960 alloc.construct(m_value.array, begin(value), end(value));
961 }
962
963 /*!
964 @brief create a string (explicit)
965
966 Create an string JSON value with a given content.
967
968 @param[in] value a value for the string
969
970 @complexity Linear in the size of the passed @a value.
971
972 @throw std::bad_alloc if allocation for string value fails
973
974 @liveexample{The following code shows the constructor with an @ref string_t
975 parameter.,basic_json__string_t}
976
977 @sa basic_json(const typename string_t::value_type*)
978 @sa basic_json(const CompatibleStringType&)
979 */
980 basic_json(const string_t& value)
981 : m_type(value_t::string), m_value(value)
982 {}
983
984 /*!
985 @brief create a string (explicit)
986
987 Create a string JSON value with a given content.
988
989 @param[in] value a literal value for the string
990
991 @complexity Linear in the size of the passed @a value.
992
993 @throw std::bad_alloc if allocation for string value fails
994
995 @liveexample{The following code shows the constructor with string literal
996 parameter.,basic_json__string_t_value_type}
997
998 @sa basic_json(const string_t&)
999 @sa basic_json(const CompatibleStringType&)
1000 */
1001 basic_json(const typename string_t::value_type* value)
1002 : basic_json(string_t(value))
1003 {}
1004
1005 /*!
1006 @brief create a string (implicit)
1007
1008 Create a string JSON value with a given content.
1009
1010 @param[in] value a value for the string
1011
1012 @tparam CompatibleStringType an string type which is compatible to @ref
1013 string_t
1014
1015 @complexity Linear in the size of the passed @a value.
1016
1017 @throw std::bad_alloc if allocation for string value fails
1018
1019 @liveexample{The following code shows the construction of a string value
1020 from a compatible type.,basic_json__CompatibleStringType}
1021
1022 @sa basic_json(const string_t&)
1023 */
1024 template <class CompatibleStringType, typename
1025 std::enable_if<
1026 std::is_constructible<string_t, CompatibleStringType>::value, int>::type
1027 = 0>
1028 basic_json(const CompatibleStringType& value)
1029 : basic_json(string_t(value))
1030 {}
1031
1032 /*!
1033 @brief create a boolean (explicit)
1034
1035 Creates a JSON boolean type from a given value.
1036
1037 @param[in] value a boolean value to store
1038
1039 @complexity Constant.
1040
1041 @liveexample{The example below demonstrates boolean
1042 values.,basic_json__boolean_t}
1043 */
1044 basic_json(boolean_t value)
1045 : m_type(value_t::boolean), m_value(value)
1046 {}
1047
1048 /*!
1049 @brief create an integer number (explicit)
1050
1051 Create an interger number JSON value with a given content.
1052
1053 @tparam T helper type to compare number_integer_t and int (not visible in)
1054 the interface.
1055
1056 @param[in] value an integer to create a JSON number from
1057
1058 @note This constructor would have the same signature as @ref
1059 basic_json(const int value), so we need to switch this one off in case
1060 number_integer_t is the same as int. This is done via the helper type @a T.
1061
1062 @complexity Constant.
1063
1064 @liveexample{The example below shows the construction of a JSON integer
1065 number value.,basic_json__number_integer_t}
1066
1067 @sa basic_json(const int)
1068 */
1069 template<typename T,
1070 typename std::enable_if<
1071 not (std::is_same<T, int>::value)
1072 and std::is_same<T, number_integer_t>::value
1073 , int>::type = 0>
1074 basic_json(const number_integer_t value)
1075 : m_type(value_t::number_integer), m_value(value)
1076 {}
1077
1078 /*!
1079 @brief create an integer number from an enum type (explicit)
1080
1081 Create an integer number JSON value with a given content.
1082
1083 @param[in] value an integer to create a JSON number from
1084
1085 @note This constructor allows to pass enums directly to a constructor. As
1086 C++ has no way of specifying the type of an anonymous enum explicitly, we
1087 can only rely on the fact that such values implicitly convert to int. As
1088 int may already be the same type of number_integer_t, we may need to switch
1089 off the constructor @ref basic_json(const number_integer_t).
1090
1091 @complexity Constant.
1092
1093 @liveexample{The example below shows the construction of a JSON integer
1094 number value from an anonymous enum.,basic_json__const_int}
1095
1096 @sa basic_json(const number_integer_t)
1097 */
1098 basic_json(const int value)
1099 : m_type(value_t::number_integer),
1100 m_value(static_cast<number_integer_t>(value))
1101 {}
1102
1103 /*!
1104 @brief create an integer number (implicit)
1105
1106 Create an integer number JSON value with a given content. This constructor
1107 allows any type that can be used to construct values of type @ref
1108 number_integer_t. Examples may include the types `int`, `int32_t`, or
1109 `short`.
1110
1111 @tparam CompatibleNumberIntegerType an integer type which is compatible to
1112 @ref number_integer_t.
1113
1114 @param[in] value an integer to create a JSON number from
1115
1116 @complexity Constant.
1117
1118 @liveexample{The example below shows the construction of several JSON
1119 integer number values from compatible
1120 types.,basic_json__CompatibleIntegerNumberType}
1121
1122 @sa basic_json(const number_integer_t)
1123 */
1124 template<typename CompatibleNumberIntegerType, typename
1125 std::enable_if<
1126 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1127 std::numeric_limits<CompatibleNumberIntegerType>::is_integer, CompatibleNumberIntegerType>::type
1128 = 0>
1129 basic_json(const CompatibleNumberIntegerType value) noexcept
1130 : m_type(value_t::number_integer),
1131 m_value(static_cast<number_integer_t>(value))
1132 {}
1133
1134 /*!
1135 @brief create a floating-point number (explicit)
1136
1137 Create a floating-point number JSON value with a given content.
1138
1139 @param[in] value a floating-point value to create a JSON number from
1140
1141 @note RFC 7159 <http://www.rfc-editor.org/rfc/rfc7159.txt>, section 6
1142 disallows NaN values:
1143 > Numeric values that cannot be represented in the grammar below (such
1144 > as Infinity and NaN) are not permitted.
1145 In case the parameter @a value is not a number, a JSON null value is
1146 created instead.
1147
1148 @complexity Constant.
1149
1150 @liveexample{The following example creates several floating-point
1151 values.,basic_json__number_float_t}
1152 */
1153 basic_json(const number_float_t value)
1154 : m_type(value_t::number_float), m_value(value)
1155 {
1156 // replace infinity and NAN by null
1157 if (not std::isfinite(value))
1158 {
1159 m_type = value_t::null;
1160 m_value = json_value();
1161 }
1162 }
1163
1164 /*!
1165 @brief create an floating-point number (implicit)
1166
1167 Create an floating-point number JSON value with a given content. This
1168 constructor allows any type that can be used to construct values of type
1169 @ref number_float_t. Examples may include the types `float`.
1170
1171 @tparam CompatibleNumberFloatType a floating-point type which is compatible
1172 to @ref number_float_t.
1173
1174 @param[in] value a floating-point to create a JSON number from
1175
1176 @note RFC 7159 <http://www.rfc-editor.org/rfc/rfc7159.txt>, section 6
1177 disallows NaN values:
1178 > Numeric values that cannot be represented in the grammar below (such
1179 > as Infinity and NaN) are not permitted.
1180 In case the parameter @a value is not a number, a JSON null value is
1181 created instead.
1182
1183 @complexity Constant.
1184
1185 @liveexample{The example below shows the construction of several JSON
1186 floating-point number values from compatible
1187 types.,basic_json__CompatibleNumberFloatType}
1188
1189 @sa basic_json(const number_float_t)
1190 */
1191 template<typename CompatibleNumberFloatType, typename = typename
1192 std::enable_if<
1193 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1194 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1195 >
1196 basic_json(const CompatibleNumberFloatType value) noexcept
1197 : basic_json(number_float_t(value))
1198 {}
1199
1200 /*!
1201 @brief create a container (array or object) from an initializer list
1202
1203 Creates a JSON value of type array or object from the passed initializer
1204 list @a init. In case @a type_deduction is `true` (default), the type of
1205 the JSON value to be created is deducted from the initializer list @a init
1206 according to the following rules:
1207
1208 1. If the list is empty, an empty JSON object value `{}` is created.
1209 2. If the list consists of pairs whose first element is a string, a JSON
1210 object value is created where the first elements of the pairs are treated
1211 as keys and the second elements are as values.
1212 3. In all other cases, an array is created.
1213
1214 The rules aim to create the best fit between a C++ initializer list and
1215 JSON values. The ratioinale is as follows:
1216
1217 1. The empty initializer list is written as `{}` which is exactly an empty
1218 JSON object.
1219 2. C++ has now way of describing mapped types other than to list a list of
1220 pairs. As JSON requires that keys must be of type string, rule 2 is the
1221 weakest constraint one can pose on initializer lists to interpret them as
1222 an object.
1223 3. In all other cases, the initializer list could not be interpreted as
1224 JSON object type, so interpreting it as JSON array type is safe.
1225
1226 With the rules described above, the following JSON values cannot be
1227 expressed by an initializer list:
1228
1229 - the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)
1230 with an empty initializer list in this case
1231 - arrays whose elements satisfy rule 2: use @ref
1232 array(std::initializer_list<basic_json>) with the same initializer list
1233 in this case
1234
1235 @note When used without parentheses around an empty initializer list, @ref
1236 basic_json() is called instead of this function, yielding the JSON null
1237 value.
1238
1239 @param[in] init initializer list with JSON values
1240
1241 @param[in] type_deduction internal parameter; when set to `true`, the type
1242 of the JSON value is deducted from the initializer list @a init; when set
1243 to `false`, the type provided via @a manual_type is forced. This mode is
1244 used by the functions @ref array(std::initializer_list<basic_json>) and
1245 @ref object(std::initializer_list<basic_json>).
1246
1247 @param[in] manual_type internal parameter; when @a type_deduction is set to
1248 `false`, the created JSON value will use the provided type (only @ref
1249 value_t::array and @ref value_t::object are valid); when @a type_deduction
1250 is set to `true`, this parameter has no effect
1251
1252 @throw std::domain_error if @a type_deduction is `false`, @a manual_type is
1253 `value_t::object`, but @a init contains an element which is not a pair
1254 whose first element is a string
1255
1256 @complexity Linear in the size of the initializer list @a init.
1257
1258 @liveexample{The example below shows how JSON values are created from
1259 initializer lists,basic_json__list_init_t}
1260
1261 @sa basic_json array(std::initializer_list<basic_json>) - create a JSON
1262 array value from an initializer list
1263 @sa basic_json object(std::initializer_list<basic_json>) - create a JSON
1264 object value from an initializer list
1265 */
1266 basic_json(std::initializer_list<basic_json> init,
1267 bool type_deduction = true,
1268 value_t manual_type = value_t::array)
1269 {
1270 // the initializer list could describe an object
1271 bool is_object = true;
1272
1273 // check if each element is an array with two elements whose first element
1274 // is a string
1275 for (const auto& element : init)
1276 {
1277 if (element.m_type != value_t::array or element.size() != 2
1278 or element[0].m_type != value_t::string)
1279 {
1280 // we found an element that makes it impossible to use the
1281 // initializer list as object
1282 is_object = false;
1283 break;
1284 }
1285 }
1286
1287 // adjust type if type deduction is not wanted
1288 if (not type_deduction)
1289 {
1290 // if array is wanted, do not create an object though possible
1291 if (manual_type == value_t::array)
1292 {
1293 is_object = false;
1294 }
1295
1296 // if object is wanted but impossible, throw an exception
1297 if (manual_type == value_t::object and not is_object)
1298 {
1299 throw std::domain_error("cannot create object from initializer list");
1300 }
1301 }
1302
1303 if (is_object)
1304 {
1305 // the initializer list is a list of pairs -> create object
1306 m_type = value_t::object;
1307 m_value = value_t::object;
1308
1309 for (auto& element : init)
1310 {
1311 m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
1312 }
1313 }
1314 else
1315 {
1316 // the initializer list describes an array -> create array
1317 m_type = value_t::array;
1318 AllocatorType<array_t> alloc;
1319 m_value.array = alloc.allocate(1);
1320 alloc.construct(m_value.array, std::move(init));
1321 }
1322 }
1323
1324 /*!
1325 @brief explicitly create an array from an initializer list
1326
1327 Creates a JSON array value from a given initializer list. That is, given a
1328 list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
1329 initializer list is empty, the empty array `[]` is created.
1330
1331 @note This function is only needed to express two edge cases that cannot be
1332 realized with the initializer list constructor (@ref
1333 basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases
1334 are:
1335 1. creating an array whose elements are all pairs whose first element is a
1336 string - in this case, the initializer list constructor would create an
1337 object, taking the first elements as keys
1338 2. creating an empty array - passing the empty initializer list to the
1339 initializer list constructor yields an empty object
1340
1341 @param[in] init initializer list with JSON values to create an array from
1342 (optional)
1343
1344 @return JSON array value
1345
1346 @complexity Linear in the size of @a init.
1347
1348 @liveexample{The following code shows an example for the @ref array
1349 function.,array}
1350
1351 @sa basic_json(std::initializer_list<basic_json>, bool, value_t) - create a
1352 JSON value from an initializer list
1353 @sa basic_json object(std::initializer_list<basic_json>) - create a JSON
1354 object value from an initializer list
1355 */
1356 static basic_json array(std::initializer_list<basic_json> init =
1357 std::initializer_list<basic_json>())
1358 {
1359 return basic_json(init, false, value_t::array);
1360 }
1361
1362 /*!
1363 @brief explicitly create an object from an initializer list
1364
1365 Creates a JSON object value from a given initializer list. The initializer
1366 lists elements must be pairs, and their first elments must be strings. If
1367 the initializer list is empty, the empty object `{}` is created.
1368
1369 @note This function is only added for symmetry reasons. In contrast to the
1370 related function @ref basic_json array(std::initializer_list<basic_json>),
1371 there are no cases which can only be expressed by this function. That is,
1372 any initializer list @a init can also be passed to the initializer list
1373 constructor @ref basic_json(std::initializer_list<basic_json>, bool,
1374 value_t).
1375
1376 @param[in] init initializer list to create an object from (optional)
1377
1378 @return JSON object value
1379
1380 @throw std::domain_error if @a init is not a pair whose first elements are
1381 strings; thrown by @ref basic_json(std::initializer_list<basic_json>, bool,
1382 value_t)
1383
1384 @complexity Linear in the size of @a init.
1385
1386 @liveexample{The following code shows an example for the @ref object
1387 function.,object}
1388
1389 @sa basic_json(std::initializer_list<basic_json>, bool, value_t) - create a
1390 JSON value from an initializer list
1391 @sa basic_json array(std::initializer_list<basic_json>) - create a JSON
1392 array value from an initializer list
1393 */
1394 static basic_json object(std::initializer_list<basic_json> init =
1395 std::initializer_list<basic_json>())
1396 {
1397 return basic_json(init, false, value_t::object);
1398 }
1399
1400 /*!
1401 @brief construct an array with count copies of given value
1402
1403 Constructs a JSON array value by creating @a count copies of a passed
1404 value. In case @a count is `0`, an empty array is created. As postcondition,
1405 `std::distance(begin(),end()) == count` holds.
1406
1407 @param[in] count the number of JSON copies of @a value to create
1408 @param[in] value the JSON value to copy
1409
1410 @complexity Linear in @a count.
1411
1412 @liveexample{The following code shows examples for the @ref
1413 basic_json(size_type\, const basic_json&)
1414 constructor.,basic_json__size_type_basic_json}
1415 */
1416 basic_json(size_type count, const basic_json& value)
1417 : m_type(value_t::array)
1418 {
1419 AllocatorType<array_t> alloc;
1420 m_value.array = alloc.allocate(1);
1421 alloc.construct(m_value.array, count, value);
1422 }
1423
1424 /*!
1425 @brief construct a JSON container given an iterator range
1426
1427 Constructs the JSON value with the contents of the range `[first, last)`.
1428 The semantics depends on the different types a JSON value can have:
1429 - In case of primitive types (number, boolean, or string), @a first must
1430 be `begin()` and @a last must be `end()`. In this case, the value is
1431 copied. Otherwise, std::out_of_range is thrown.
1432 - In case of structured types (array, object), the constructor behaves
1433 as similar versions for `std::vector`.
1434 - In case of a null type, std::domain_error is thrown.
1435
1436 @tparam InputIT an input iterator type (@ref iterator or @ref
1437 const_iterator)
1438
1439 @param[in] first begin of the range to copy from (included)
1440 @param[in] last end of the range to copy from (excluded)
1441
1442 @throw std::domain_error if iterators are not compatible; that is, do not
1443 belong to the same JSON value
1444 @throw std::out_of_range if iterators are for a primitive type (number,
1445 boolean, or string) where an out of range error can be detected easily
1446 @throw std::bad_alloc if allocation for object, array, or string fails
1447 @throw std::domain_error if called with a null value
1448
1449 @complexity Linear in distance between @a first and @a last.
1450
1451 @liveexample{The example below shows several ways to create JSON values by
1452 specifying a subrange with iterators.,basic_json__InputIt_InputIt}
1453 */
1454 template <class InputIT, typename
1455 std::enable_if<
1456 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1457 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1458 , int>::type
1459 = 0>
1460 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1461 {
1462 // make sure iterator fits the current value
1463 if (first.m_object != last.m_object)
1464 {
1465 throw std::domain_error("iterators are not compatible");
1466 }
1467
1468 // check if iterator range is complete for primitive values
1469 switch (m_type)
1470 {
1471 case value_t::number_integer:
1472 case value_t::number_float:
1473 case value_t::boolean:
1474 case value_t::string:
1475 {
1476 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1477 {
1478 throw std::out_of_range("iterators out of range");
1479 }
1480 break;
1481 }
1482
1483 default:
1484 {
1485 break;
1486 }
1487 }
1488
1489 switch (m_type)
1490 {
1491 case value_t::number_integer:
1492 {
1493 m_value.number_integer = first.m_object->m_value.number_integer;
1494 break;
1495 }
1496
1497 case value_t::number_float:
1498 {
1499 m_value.number_float = first.m_object->m_value.number_float;
1500 break;
1501 }
1502
1503 case value_t::boolean:
1504 {
1505 m_value.boolean = first.m_object->m_value.boolean;
1506 break;
1507 }
1508
1509 case value_t::string:
1510 {
1511 m_value = *first.m_object->m_value.string;
1512 break;
1513 }
1514
1515 case value_t::object:
1516 {
1517 AllocatorType<object_t> alloc;
1518 m_value.object = alloc.allocate(1);
1519 alloc.construct(m_value.object, first.m_it.object_iterator, last.m_it.object_iterator);
1520 break;
1521 }
1522
1523 case value_t::array:
1524 {
1525 AllocatorType<array_t> alloc;
1526 m_value.array = alloc.allocate(1);
1527 alloc.construct(m_value.array, first.m_it.array_iterator, last.m_it.array_iterator);
1528 break;
1529 }
1530
1531 default:
1532 {
1533 throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
1534 }
1535 }
1536 }
1537
1538 ///////////////////////////////////////
1539 // other constructors and destructor //
1540 ///////////////////////////////////////
1541
1542 /*!
1543 @brief copy constructor
1544
1545 Creates a copy of a given JSON value.
1546
1547 @param[in] other the JSON value to copy
1548
1549 @complexity Linear in the size of @a other.
1550
1551 @requirement This function satisfies the Container requirements:
1552 - The complexity is linear.
1553 - As postcondition, it holds: `other == basic_json(other)`.
1554
1555 @throw std::bad_alloc if allocation for object, array, or string fails.
1556
1557 @liveexample{The following code shows an example for the copy
1558 constructor.,basic_json__basic_json}
1559 */
1560 basic_json(const basic_json& other)
1561 : m_type(other.m_type)
1562 {
1563 switch (m_type)
1564 {
1565 case (value_t::null):
1566 case (value_t::discarded):
1567 {
1568 break;
1569 }
1570
1571 case (value_t::object):
1572 {
1573 m_value = *other.m_value.object;
1574 break;
1575 }
1576
1577 case (value_t::array):
1578 {
1579 m_value = *other.m_value.array;
1580 break;
1581 }
1582
1583 case (value_t::string):
1584 {
1585 m_value = *other.m_value.string;
1586 break;
1587 }
1588
1589 case (value_t::boolean):
1590 {
1591 m_value = other.m_value.boolean;
1592 break;
1593 }
1594
1595 case (value_t::number_integer):
1596 {
1597 m_value = other.m_value.number_integer;
1598 break;
1599 }
1600
1601 case (value_t::number_float):
1602 {
1603 m_value = other.m_value.number_float;
1604 break;
1605 }
1606 }
1607 }
1608
1609 /*!
1610 @brief move constructor
1611
1612 Move constructor. Constructs a JSON value with the contents of the given
1613 value @a other using move semantics. It "steals" the resources from @a
1614 other and leaves it as JSON null value.
1615
1616 @param[in,out] other value to move to this object
1617
1618 @post @a other is a JSON null value
1619
1620 @complexity Constant.
1621
1622 @liveexample{The code below shows the move constructor explicitly called
1623 via std::move.,basic_json__moveconstructor}
1624 */
1625 basic_json(basic_json&& other) noexcept
1626 : m_type(std::move(other.m_type)),
1627 m_value(std::move(other.m_value))
1628 {
1629 // invalidate payload
1630 other.m_type = value_t::null;
1631 other.m_value = {};
1632 }
1633
1634 /*!
1635 @brief copy assignment
1636
1637 Copy assignment operator. Copies a JSON value via the "copy and swap"
1638 strategy: It is expressed in terms of the copy constructor, destructor, and
1639 the swap() member function.
1640
1641 @param[in] other value to copy from
1642
1643 @complexity Linear.
1644
1645 @requirement This function satisfies the Container requirements:
1646 - The complexity is linear.
1647
1648 @liveexample{The code below shows and example for the copy assignment. It
1649 creates a copy of value `a` which is then swapped with `b`. Finally\, the
1650 copy of `a` (which is the null value after the swap) is
1651 destroyed.,basic_json__copyassignment}
1652 */
1653 reference& operator=(basic_json other) noexcept (
1654 std::is_nothrow_move_constructible<value_t>::value and
1655 std::is_nothrow_move_assignable<value_t>::value and
1656 std::is_nothrow_move_constructible<json_value>::value and
1657 std::is_nothrow_move_assignable<json_value>::value
1658 )
1659 {
1660 using std::swap;
1661 std::swap(m_type, other.m_type);
1662 std::swap(m_value, other.m_value);
1663 return *this;
1664 }
1665
1666 /*!
1667 @brief destructor
1668
1669 Destroys the JSON value and frees all allocated memory.
1670
1671 @complexity Linear.
1672
1673 @requirement This function satisfies the Container requirements:
1674 - The complexity is linear.
1675 - All stored elements are destroyed and all memory is freed.
1676 */
1677 ~basic_json()
1678 {
1679 switch (m_type)
1680 {
1681 case (value_t::object):
1682 {
1683 AllocatorType<object_t> alloc;
1684 alloc.destroy(m_value.object);
1685 alloc.deallocate(m_value.object, 1);
1686 m_value.object = nullptr;
1687 break;
1688 }
1689
1690 case (value_t::array):
1691 {
1692 AllocatorType<array_t> alloc;
1693 alloc.destroy(m_value.array);
1694 alloc.deallocate(m_value.array, 1);
1695 m_value.array = nullptr;
1696 break;
1697 }
1698
1699 case (value_t::string):
1700 {
1701 AllocatorType<string_t> alloc;
1702 alloc.destroy(m_value.string);
1703 alloc.deallocate(m_value.string, 1);
1704 m_value.string = nullptr;
1705 break;
1706 }
1707
1708 default:
1709 {
1710 // all other types need no specific destructor
1711 break;
1712 }
1713 }
1714 }
1715
1716
1717 public:
1718 ///////////////////////
1719 // object inspection //
1720 ///////////////////////
1721
1722 /// @name object inspection
1723 /// @{
1724
1725 /*!
1726 @brief serialization
1727
1728 Serialization function for JSON values. The function tries to mimick
1729 Python's @p json.dumps() function, and currently supports its @p indent
1730 parameter.
1731
1732 @param[in] indent if indent is nonnegative, then array elements and object
1733 members will be pretty-printed with that indent level. An indent level of 0
1734 will only insert newlines. -1 (the default) selects the most compact
1735 representation
1736
1737 @return string containing the serialization of the JSON value
1738
1739 @complexity Linear.
1740
1741 @liveexample{The following example shows the effect of different @a indent
1742 parameters to the result of the serializaion.,dump}
1743
1744 @see https://docs.python.org/2/library/json.html#json.dump
1745 */
1746 string_t dump(const int indent = -1) const
1747 {
1748 std::stringstream ss;
1749
1750 if (indent >= 0)
1751 {
1752 dump(ss, true, static_cast<unsigned int>(indent));
1753 }
1754 else
1755 {
1756 dump(ss, false, 0);
1757 }
1758
1759 return ss.str();
1760 }
1761
1762 /*!
1763 @brief return the type of the JSON value (explicit)
1764
1765 Return the type of the JSON value as a value from the @ref value_t
1766 enumeration.
1767
1768 @return the type of the JSON value
1769
1770 @complexity Constant.
1771
1772 @liveexample{The following code exemplifies @ref type() for all JSON
1773 types.,type}
1774 */
1775 value_t type() const noexcept
1776 {
1777 return m_type;
1778 }
1779
1780 /*!
1781 @brief return whether type is primitive
1782
1783 This function returns true iff the JSON type is primitive (string, number,
1784 boolean, or null).
1785
1786 @return `true` if type is primitive (string, number, boolean, or null),
1787 `false` otherwise.
1788
1789 @complexity Constant.
1790
1791 @liveexample{The following code exemplifies @ref is_primitive for all JSON
1792 types.,is_primitive}
1793 */
1794 bool is_primitive() const noexcept
1795 {
1796 return is_null() or is_string() or is_boolean() or is_number();
1797 }
1798
1799 /*!
1800 @brief return whether type is structured
1801
1802 This function returns true iff the JSON type is structured (array or
1803 object).
1804
1805 @return `true` if type is structured (array or object), `false` otherwise.
1806
1807 @complexity Constant.
1808
1809 @liveexample{The following code exemplifies @ref is_structured for all JSON
1810 types.,is_structured}
1811 */
1812 bool is_structured() const noexcept
1813 {
1814 return is_array() or is_object();
1815 }
1816
1817 /*!
1818 @brief return whether value is null
1819
1820 This function returns true iff the JSON value is null.
1821
1822 @return `true` if type is null, `false` otherwise.
1823
1824 @complexity Constant.
1825
1826 @liveexample{The following code exemplifies @ref is_null for all JSON
1827 types.,is_null}
1828 */
1829 bool is_null() const noexcept
1830 {
1831 return m_type == value_t::null;
1832 }
1833
1834 /*!
1835 @brief return whether value is a boolean
1836
1837 This function returns true iff the JSON value is a boolean.
1838
1839 @return `true` if type is boolean, `false` otherwise.
1840
1841 @complexity Constant.
1842
1843 @liveexample{The following code exemplifies @ref is_boolean for all JSON
1844 types.,is_boolean}
1845 */
1846 bool is_boolean() const noexcept
1847 {
1848 return m_type == value_t::boolean;
1849 }
1850
1851 /*!
1852 @brief return whether value is a number
1853
1854 This function returns true iff the JSON value is a number. This includes
1855 both integer and floating-point values.
1856
1857 @return `true` if type is number, `false` otherwise.
1858
1859 @complexity Constant.
1860
1861 @liveexample{The following code exemplifies @ref is_number for all JSON
1862 types.,is_number}
1863 */
1864 bool is_number() const noexcept
1865 {
1866 return is_number_integer() or is_number_float();
1867 }
1868
1869 /*!
1870 @brief return whether value is an integer number
1871
1872 This function returns true iff the JSON value is an integer number. This
1873 excludes floating-point values.
1874
1875 @return `true` if type is an integer number, `false` otherwise.
1876
1877 @complexity Constant.
1878
1879 @liveexample{The following code exemplifies @ref is_number_integer for all
1880 JSON types.,is_number_integer}
1881 */
1882 bool is_number_integer() const noexcept
1883 {
1884 return m_type == value_t::number_integer;
1885 }
1886
1887 /*!
1888 @brief return whether value is a floating-point number
1889
1890 This function returns true iff the JSON value is a floating-point number.
1891 This excludes integer values.
1892
1893 @return `true` if type is a floating-point number, `false` otherwise.
1894
1895 @complexity Constant.
1896
1897 @liveexample{The following code exemplifies @ref is_number_float for all
1898 JSON types.,is_number_float}
1899 */
1900 bool is_number_float() const noexcept
1901 {
1902 return m_type == value_t::number_float;
1903 }
1904
1905 /*!
1906 @brief return whether value is an object
1907
1908 This function returns true iff the JSON value is an object.
1909
1910 @return `true` if type is object, `false` otherwise.
1911
1912 @complexity Constant.
1913
1914 @liveexample{The following code exemplifies @ref is_object for all JSON
1915 types.,is_object}
1916 */
1917 bool is_object() const noexcept
1918 {
1919 return m_type == value_t::object;
1920 }
1921
1922 /*!
1923 @brief return whether value is an array
1924
1925 This function returns true iff the JSON value is an array.
1926
1927 @return `true` if type is array, `false` otherwise.
1928
1929 @complexity Constant.
1930
1931 @liveexample{The following code exemplifies @ref is_array for all JSON
1932 types.,is_array}
1933 */
1934 bool is_array() const noexcept
1935 {
1936 return m_type == value_t::array;
1937 }
1938
1939 /*!
1940 @brief return whether value is a string
1941
1942 This function returns true iff the JSON value is a string.
1943
1944 @return `true` if type is string, `false` otherwise.
1945
1946 @complexity Constant.
1947
1948 @liveexample{The following code exemplifies @ref is_string for all JSON
1949 types.,is_string}
1950 */
1951 bool is_string() const noexcept
1952 {
1953 return m_type == value_t::string;
1954 }
1955
1956 /*!
1957 @brief return whether value is discarded
1958
1959 This function returns true iff the JSON value was discarded during parsing
1960 with a callback function (see @ref parser_callback_t).
1961
1962 @note This function will always be `false` for JSON values after parsing.
1963 That is, discarded values can only occur during parsing, but will be
1964 removed when inside a structured value or replaced by null in other cases.
1965
1966 @return `true` if type is discarded, `false` otherwise.
1967
1968 @complexity Constant.
1969
1970 @liveexample{The following code exemplifies @ref is_discarded for all JSON
1971 types.,is_discarded}
1972 */
1973 bool is_discarded() const noexcept
1974 {
1975 return m_type == value_t::discarded;
1976 }
1977
1978 /*!
1979 @brief return the type of the JSON value (implicit)
1980
1981 Implicitly return the type of the JSON value as a value from the @ref
1982 value_t enumeration.
1983
1984 @return the type of the JSON value
1985
1986 @complexity Constant.
1987
1988 @liveexample{The following code exemplifies the value_t operator for all
1989 JSON types.,operator__value_t}
1990 */
1991 operator value_t() const noexcept
1992 {
1993 return m_type;
1994 }
1995
1996 /// @}
1997
1998 private:
1999 //////////////////
2000 // value access //
2001 //////////////////
2002
2003 /// get an object (explicit)
2004 template <class T, typename
2005 std::enable_if<
2006 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2007 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2008 , int>::type = 0>
2009 T get_impl(T*) const
2010 {
2011 switch (m_type)
2012 {
2013 case (value_t::object):
2014 {
2015 return T(m_value.object->begin(), m_value.object->end());
2016 }
2017 default:
2018 {
2019 throw std::domain_error("type must be object, but is " + type_name());
2020 }
2021 }
2022 }
2023
2024 /// get an object (explicit)
2025 object_t get_impl(object_t*) const
2026 {
2027 switch (m_type)
2028 {
2029 case (value_t::object):
2030 {
2031 return *(m_value.object);
2032 }
2033 default:
2034 {
2035 throw std::domain_error("type must be object, but is " + type_name());
2036 }
2037 }
2038 }
2039
2040 /// get an array (explicit)
2041 template <class T, typename
2042 std::enable_if<
2043 std::is_convertible<basic_json_t, typename T::value_type>::value and
2044 not std::is_same<basic_json_t, typename T::value_type>::value and
2045 not std::is_arithmetic<T>::value and
2046 not std::is_convertible<std::string, T>::value and
2047 not has_mapped_type<T>::value
2048 , int>::type = 0>
2049 T get_impl(T*) const
2050 {
2051 switch (m_type)
2052 {
2053 case (value_t::array):
2054 {
2055 T to_vector;
2056 std::transform(m_value.array->begin(), m_value.array->end(),
2057 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2058 {
2059 return i.get<typename T::value_type>();
2060 });
2061 return to_vector;
2062 }
2063 default:
2064 {
2065 throw std::domain_error("type must be array, but is " + type_name());
2066 }
2067 }
2068 }
2069
2070 /// get an array (explicit)
2071 template <class T, typename
2072 std::enable_if<
2073 std::is_convertible<basic_json_t, T>::value and
2074 not std::is_same<basic_json_t, T>::value
2075 , int>::type = 0>
2076 std::vector<T> get_impl(std::vector<T>*) const
2077 {
2078 switch (m_type)
2079 {
2080 case (value_t::array):
2081 {
2082 std::vector<T> to_vector;
2083 to_vector.reserve(m_value.array->size());
2084 std::transform(m_value.array->begin(), m_value.array->end(),
2085 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2086 {
2087 return i.get<T>();
2088 });
2089 return to_vector;
2090 }
2091 default:
2092 {
2093 throw std::domain_error("type must be array, but is " + type_name());
2094 }
2095 }
2096 }
2097
2098 /// get an array (explicit)
2099 template <class T, typename
2100 std::enable_if<
2101 std::is_same<basic_json, typename T::value_type>::value and
2102 not has_mapped_type<T>::value
2103 , int>::type = 0>
2104 T get_impl(T*) const
2105 {
2106 switch (m_type)
2107 {
2108 case (value_t::array):
2109 {
2110 return T(m_value.array->begin(), m_value.array->end());
2111 }
2112 default:
2113 {
2114 throw std::domain_error("type must be array, but is " + type_name());
2115 }
2116 }
2117 }
2118
2119 /// get an array (explicit)
2120 array_t get_impl(array_t*) const
2121 {
2122 switch (m_type)
2123 {
2124 case (value_t::array):
2125 {
2126 return *(m_value.array);
2127 }
2128 default:
2129 {
2130 throw std::domain_error("type must be array, but is " + type_name());
2131 }
2132 }
2133 }
2134
2135 /// get a string (explicit)
2136 template <typename T, typename
2137 std::enable_if<
2138 std::is_convertible<string_t, T>::value
2139 , int>::type = 0>
2140 T get_impl(T*) const
2141 {
2142 switch (m_type)
2143 {
2144 case (value_t::string):
2145 {
2146 return *m_value.string;
2147 }
2148 default:
2149 {
2150 throw std::domain_error("type must be string, but is " + type_name());
2151 }
2152 }
2153 }
2154
2155 /// get a number (explicit)
2156 template<typename T, typename
2157 std::enable_if<
2158 std::is_arithmetic<T>::value
2159 , int>::type = 0>
2160 T get_impl(T*) const
2161 {
2162 switch (m_type)
2163 {
2164 case (value_t::number_integer):
2165 {
2166 return static_cast<T>(m_value.number_integer);
2167 }
2168 case (value_t::number_float):
2169 {
2170 return static_cast<T>(m_value.number_float);
2171 }
2172 default:
2173 {
2174 throw std::domain_error("type must be number, but is " + type_name());
2175 }
2176 }
2177 }
2178
2179 /// get a boolean (explicit)
2180 boolean_t get_impl(boolean_t*) const
2181 {
2182 switch (m_type)
2183 {
2184 case (value_t::boolean):
2185 {
2186 return m_value.boolean;
2187 }
2188 default:
2189 {
2190 throw std::domain_error("type must be boolean, but is " + type_name());
2191 }
2192 }
2193 }
2194
2195 /// get a pointer to the value (object)
2196 object_t* get_impl_ptr(object_t*) noexcept
2197 {
2198 return is_object() ? m_value.object : nullptr;
2199 }
2200
2201 /// get a pointer to the value (object)
2202 const object_t* get_impl_ptr(const object_t*) const noexcept
2203 {
2204 return is_object() ? m_value.object : nullptr;
2205 }
2206
2207 /// get a pointer to the value (array)
2208 array_t* get_impl_ptr(array_t*) noexcept
2209 {
2210 return is_array() ? m_value.array : nullptr;
2211 }
2212
2213 /// get a pointer to the value (array)
2214 const array_t* get_impl_ptr(const array_t*) const noexcept
2215 {
2216 return is_array() ? m_value.array : nullptr;
2217 }
2218
2219 /// get a pointer to the value (string)
2220 string_t* get_impl_ptr(string_t*) noexcept
2221 {
2222 return is_string() ? m_value.string : nullptr;
2223 }
2224
2225 /// get a pointer to the value (string)
2226 const string_t* get_impl_ptr(const string_t*) const noexcept
2227 {
2228 return is_string() ? m_value.string : nullptr;
2229 }
2230
2231 /// get a pointer to the value (boolean)
2232 boolean_t* get_impl_ptr(boolean_t*) noexcept
2233 {
2234 return is_boolean() ? &m_value.boolean : nullptr;
2235 }
2236
2237 /// get a pointer to the value (boolean)
2238 const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
2239 {
2240 return is_boolean() ? &m_value.boolean : nullptr;
2241 }
2242
2243 /// get a pointer to the value (integer number)
2244 number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2245 {
2246 return is_number_integer() ? &m_value.number_integer : nullptr;
2247 }
2248
2249 /// get a pointer to the value (integer number)
2250 const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
2251 {
2252 return is_number_integer() ? &m_value.number_integer : nullptr;
2253 }
2254
2255 /// get a pointer to the value (floating-point number)
2256 number_float_t* get_impl_ptr(number_float_t*) noexcept
2257 {
2258 return is_number_float() ? &m_value.number_float : nullptr;
2259 }
2260
2261 /// get a pointer to the value (floating-point number)
2262 const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
2263 {
2264 return is_number_float() ? &m_value.number_float : nullptr;
2265 }
2266
2267 public:
2268
2269 /// @name value access
2270 /// @{
2271
2272 /*!
2273 @brief get a value (explicit)
2274
2275 Explicit type conversion between the JSON value and a compatible value.
2276
2277 @tparam ValueType non-pointer type compatible to the JSON value, for
2278 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
2279 `std::vector` types for JSON arrays
2280
2281 @return copy of the JSON value, converted to type @a ValueType
2282
2283 @throw std::domain_error in case passed type @a ValueType is incompatible
2284 to JSON
2285
2286 @complexity Linear in the size of the JSON value.
2287
2288 @liveexample{The example below shows serveral conversions from JSON values
2289 to other types. There a few things to note: (1) Floating-point numbers can
2290 be converted to integers\, (2) A JSON array can be converted to a standard
2291 `std::vector<short>`\, (3) A JSON object can be converted to C++
2292 assiciative containers such as `std::unordered_map<std::string\,
2293 json>`.,get__ValueType_const}
2294
2295 @internal
2296 The idea of using a casted null pointer to choose the correct
2297 implementation is from <http://stackoverflow.com/a/8315197/266378>.
2298 @endinternal
2299
2300 @sa @ref operator ValueType() const for implicit conversion
2301 @sa @ref get() for pointer-member access
2302 */
2303 template<typename ValueType, typename
2304 std::enable_if<
2305 not std::is_pointer<ValueType>::value
2306 , int>::type = 0>
2307 ValueType get() const
2308 {
2309 return get_impl(static_cast<ValueType*>(nullptr));
2310 }
2311
2312 /*!
2313 @brief get a pointer value (explicit)
2314
2315 Explicit pointer access to the internally stored JSON value. No copies are
2316 made.
2317
2318 @warning Writing data to the pointee of the result yields an undefined
2319 state.
2320
2321 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
2322 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
2323 number_float_t.
2324
2325 @return pointer to the internally stored JSON value if the requested pointer
2326 type @a PointerType fits to the JSON value; `nullptr` otherwise
2327
2328 @complexity Constant.
2329
2330 @liveexample{The example below shows how pointers to internal values of a
2331 JSON value can be requested. Note that no type conversions are made and a
2332 `nullptr` is returned if the value and the requested pointer type does not
2333 match.,get__PointerType}
2334
2335 @sa @ref get_ptr() for explicit pointer-member access
2336 */
2337 template<typename PointerType, typename
2338 std::enable_if<
2339 std::is_pointer<PointerType>::value
2340 , int>::type = 0>
2341 PointerType get() noexcept
2342 {
2343 // delegate the call to get_ptr
2344 return get_ptr<PointerType>();
2345 }
2346
2347 /*!
2348 @brief get a pointer value (explicit)
2349 @copydoc get()
2350 */
2351 template<typename PointerType, typename
2352 std::enable_if<
2353 std::is_pointer<PointerType>::value
2354 , int>::type = 0>
2355 const PointerType get() const noexcept
2356 {
2357 // delegate the call to get_ptr
2358 return get_ptr<PointerType>();
2359 }
2360
2361 /*!
2362 @brief get a pointer value (implicit)
2363
2364 Implict pointer access to the internally stored JSON value. No copies are
2365 made.
2366
2367 @warning Writing data to the pointee of the result yields an undefined
2368 state.
2369
2370 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
2371 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
2372 number_float_t.
2373
2374 @return pointer to the internally stored JSON value if the requested pointer
2375 type @a PointerType fits to the JSON value; `nullptr` otherwise
2376
2377 @complexity Constant.
2378
2379 @liveexample{The example below shows how pointers to internal values of a
2380 JSON value can be requested. Note that no type conversions are made and a
2381 `nullptr` is returned if the value and the requested pointer type does not
2382 match.,get_ptr}
2383 */
2384 template<typename PointerType, typename
2385 std::enable_if<
2386 std::is_pointer<PointerType>::value
2387 , int>::type = 0>
2388 PointerType get_ptr() noexcept
2389 {
2390 // delegate the call to get_impl_ptr<>()
2391 return get_impl_ptr(static_cast<PointerType>(nullptr));
2392 }
2393
2394 /*!
2395 @brief get a pointer value (implicit)
2396 @copydoc get_ptr()
2397 */
2398 template<typename PointerType, typename
2399 std::enable_if<
2400 std::is_pointer<PointerType>::value
2401 and std::is_const<PointerType>::value
2402 , int>::type = 0>
2403 const PointerType get_ptr() const noexcept
2404 {
2405 // delegate the call to get_impl_ptr<>() const
2406 return get_impl_ptr(static_cast<const PointerType>(nullptr));
2407 }
2408
2409 /*!
2410 @brief get a value (implicit)
2411
2412 Implict type conversion between the JSON value and a compatible value. The
2413 call is realized by calling @ref get() const.
2414
2415 @tparam ValueType non-pointer type compatible to the JSON value, for
2416 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
2417 `std::vector` types for JSON arrays
2418
2419 @return copy of the JSON value, converted to type @a ValueType
2420
2421 @throw std::domain_error in case passed type @a ValueType is incompatible
2422 to JSON, thrown by @ref get() const
2423
2424 @complexity Linear in the size of the JSON value.
2425
2426 @liveexample{The example below shows serveral conversions from JSON values
2427 to other types. There a few things to note: (1) Floating-point numbers can
2428 be converted to integers\, (2) A JSON array can be converted to a standard
2429 `std::vector<short>`\, (3) A JSON object can be converted to C++
2430 assiciative containers such as `std::unordered_map<std::string\,
2431 json>`.,operator__ValueType}
2432 */
2433 template<typename ValueType, typename
2434 std::enable_if<
2435 not std::is_pointer<ValueType>::value
2436 , int>::type = 0>
2437 operator ValueType() const
2438 {
2439 // delegate the call to get<>() const
2440 return get<ValueType>();
2441 }
2442
2443 /// @}
2444
2445
2446 ////////////////////
2447 // element access //
2448 ////////////////////
2449
2450 /// @name element access
2451 /// @{
2452
2453 /*!
2454 @brief access specified array element with bounds checking
2455
2456 Returns a reference to the element at specified location @a idx, with
2457 bounds checking.
2458
2459 @param[in] idx index of the element to access
2460
2461 @return reference to the element at index @a idx
2462
2463 @throw std::domain_error if JSON is not an array
2464 @throw std::out_of_range if the index @a idx is out of range of the array;
2465 that is, `idx >= size()`
2466
2467 @complexity Constant.
2468
2469 @liveexample{The example below shows how array elements can be read and
2470 written using at.,at__size_type}
2471 */
2472 reference at(size_type idx)
2473 {
2474 // at only works for arrays
2475 if (m_type != value_t::array)
2476 {
2477 throw std::domain_error("cannot use at() with " + type_name());
2478 }
2479
2480 return m_value.array->at(idx);
2481 }
2482
2483 /*!
2484 @brief access specified array element with bounds checking
2485
2486 Returns a const reference to the element at specified location @a idx, with
2487 bounds checking.
2488
2489 @param[in] idx index of the element to access
2490
2491 @return const reference to the element at index @a idx
2492
2493 @throw std::domain_error if JSON is not an array
2494 @throw std::out_of_range if the index @a idx is out of range of the array;
2495 that is, `idx >= size()`
2496
2497 @complexity Constant.
2498
2499 @liveexample{The example below shows how array elements can be read using
2500 at.,at__size_type_const}
2501 */
2502 const_reference at(size_type idx) const
2503 {
2504 // at only works for arrays
2505 if (m_type != value_t::array)
2506 {
2507 throw std::domain_error("cannot use at() with " + type_name());
2508 }
2509
2510 return m_value.array->at(idx);
2511 }
2512
2513 /*!
2514 @brief access specified object element with bounds checking
2515
2516 Returns a reference to the element at with specified key @a key, with
2517 bounds checking.
2518
2519 @param[in] key key of the element to access
2520
2521 @return reference to the element at key @a key
2522
2523 @throw std::domain_error if JSON is not an object
2524 @throw std::out_of_range if the key @a key is is not stored in the object;
2525 that is, `find(key) == end()`
2526
2527 @complexity Logarithmic in the size of the container.
2528
2529 @liveexample{The example below shows how object elements can be read and
2530 written using at.,at__object_t_key_type}
2531 */
2532 reference at(const typename object_t::key_type& key)
2533 {
2534 // at only works for objects
2535 if (m_type != value_t::object)
2536 {
2537 throw std::domain_error("cannot use at() with " + type_name());
2538 }
2539
2540 return m_value.object->at(key);
2541 }
2542
2543 /*!
2544 @brief access specified object element with bounds checking
2545
2546 Returns a const reference to the element at with specified key @a key, with
2547 bounds checking.
2548
2549 @param[in] key key of the element to access
2550
2551 @return const reference to the element at key @a key
2552
2553 @throw std::domain_error if JSON is not an object
2554 @throw std::out_of_range if the key @a key is is not stored in the object;
2555 that is, `find(key) == end()`
2556
2557 @complexity Logarithmic in the size of the container.
2558
2559 @liveexample{The example below shows how object elements can be read using
2560 at.,at__object_t_key_type_const}
2561 */
2562 const_reference at(const typename object_t::key_type& key) const
2563 {
2564 // at only works for objects
2565 if (m_type != value_t::object)
2566 {
2567 throw std::domain_error("cannot use at() with " + type_name());
2568 }
2569
2570 return m_value.object->at(key);
2571 }
2572
2573 /*!
2574 @brief access specified array element
2575
2576 Returns a reference to the element at specified location @a idx.
2577
2578 @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
2579 then the array is silently filled up with `null` values to make `idx` a
2580 valid reference to the last stored element.
2581
2582 @param[in] idx index of the element to access
2583
2584 @return reference to the element at index @a idx
2585
2586 @throw std::domain_error if JSON is not an array or null
2587
2588 @complexity Constant if @a idx is in the range of the array. Otherwise
2589 linear in `idx - size()`.
2590
2591 @liveexample{The example below shows how array elements can be read and
2592 written using [] operator. Note the addition of `null`
2593 values.,operatorarray__size_type}
2594 */
2595 reference operator[](size_type idx)
2596 {
2597 // implicitly convert null to object
2598 if (m_type == value_t::null)
2599 {
2600 m_type = value_t::array;
2601 AllocatorType<array_t> alloc;
2602 m_value.array = alloc.allocate(1);
2603 alloc.construct(m_value.array);
2604 }
2605
2606 // [] only works for arrays
2607 if (m_type != value_t::array)
2608 {
2609 throw std::domain_error("cannot use operator[] with " + type_name());
2610 }
2611
2612 for (size_t i = m_value.array->size(); i <= idx; ++i)
2613 {
2614 m_value.array->push_back(basic_json());
2615 }
2616
2617 return m_value.array->operator[](idx);
2618 }
2619
2620 /*!
2621 @brief access specified array element
2622
2623 Returns a const reference to the element at specified location @a idx.
2624
2625 @param[in] idx index of the element to access
2626
2627 @return const reference to the element at index @a idx
2628
2629 @throw std::domain_error if JSON is not an array
2630
2631 @complexity Constant.
2632
2633 @liveexample{The example below shows how array elements can be read using
2634 the [] operator.,operatorarray__size_type_const}
2635 */
2636 const_reference operator[](size_type idx) const
2637 {
2638 // at only works for arrays
2639 if (m_type != value_t::array)
2640 {
2641 throw std::domain_error("cannot use operator[] with " + type_name());
2642 }
2643
2644 return m_value.array->operator[](idx);
2645 }
2646
2647 /*!
2648 @brief access specified object element
2649
2650 Returns a reference to the element at with specified key @a key.
2651
2652 @note If @a key is not found in the object, then it is silently added to
2653 the object and filled with a `null` value to make `key` a valid reference.
2654 In case the value was `null` before, it is converted to an object.
2655
2656 @param[in] key key of the element to access
2657
2658 @return reference to the element at key @a key
2659
2660 @throw std::domain_error if JSON is not an object or null
2661
2662 @complexity Logarithmic in the size of the container.
2663
2664 @liveexample{The example below shows how object elements can be read and
2665 written using the [] operator.,operatorarray__key_type}
2666 */
2667 reference operator[](const typename object_t::key_type& key)
2668 {
2669 // implicitly convert null to object
2670 if (m_type == value_t::null)
2671 {
2672 m_type = value_t::object;
2673 AllocatorType<object_t> alloc;
2674 m_value.object = alloc.allocate(1);
2675 alloc.construct(m_value.object);
2676 }
2677
2678 // [] only works for objects
2679 if (m_type != value_t::object)
2680 {
2681 throw std::domain_error("cannot use operator[] with " + type_name());
2682 }
2683
2684 return m_value.object->operator[](key);
2685 }
2686
2687 /*!
2688 @brief access specified object element
2689
2690 Returns a reference to the element at with specified key @a key.
2691
2692 @param[in] key key of the element to access
2693
2694 @return reference to the element at key @a key
2695
2696 @throw std::domain_error if JSON is not an object or null
2697
2698 @complexity Logarithmic in the size of the container.
2699
2700 @liveexample{The example below shows how object elements can be read using
2701 the [] operator.,operatorarray__key_type_const}
2702 */
2703 const_reference operator[](const typename object_t::key_type& key) const
2704 {
2705 // at only works for objects
2706 if (m_type != value_t::object)
2707 {
2708 throw std::domain_error("cannot use operator[] with " + type_name());
2709 }
2710
2711 return m_value.object->operator[](key);
2712 }
2713
2714 /*!
2715 @brief access specified object element
2716
2717 Returns a reference to the element at with specified key @a key.
2718
2719 @note If @a key is not found in the object, then it is silently added to
2720 the object and filled with a `null` value to make `key` a valid reference.
2721 In case the value was `null` before, it is converted to an object.
2722
2723 @note This function is required for compatibility reasons with Clang.
2724
2725 @param[in] key key of the element to access
2726
2727 @return reference to the element at key @a key
2728
2729 @throw std::domain_error if JSON is not an object or null
2730
2731 @complexity Logarithmic in the size of the container.
2732
2733 @liveexample{The example below shows how object elements can be read and
2734 written using the [] operator.,operatorarray__key_type}
2735 */
2736 template<typename T, std::size_t n>
2737 reference operator[](const T (&key)[n])
2738 {
2739 // implicitly convert null to object
2740 if (m_type == value_t::null)
2741 {
2742 m_type = value_t::object;
2743 m_value = value_t::object;
2744 }
2745
2746 // at only works for objects
2747 if (m_type != value_t::object)
2748 {
2749 throw std::domain_error("cannot use operator[] with " + type_name());
2750 }
2751
2752 return m_value.object->operator[](key);
2753 }
2754
2755 /*!
2756 @brief access specified object element
2757
2758 Returns a reference to the element at with specified key @a key.
2759
2760 @note This function is required for compatibility reasons with Clang.
2761
2762 @param[in] key key of the element to access
2763
2764 @return reference to the element at key @a key
2765
2766 @throw std::domain_error if JSON is not an object or null
2767
2768 @complexity Logarithmic in the size of the container.
2769
2770 @liveexample{The example below shows how object elements can be read using
2771 the [] operator.,operatorarray__key_type_const}
2772 */
2773 template<typename T, std::size_t n>
2774 const_reference operator[](const T (&key)[n]) const
2775 {
2776 // at only works for objects
2777 if (m_type != value_t::object)
2778 {
2779 throw std::domain_error("cannot use operator[] with " + type_name());
2780 }
2781
2782 return m_value.object->operator[](key);
2783 }
2784
2785 /*!
2786 @brief access the first element
2787
2788 Returns a reference to the first element in the container. For a JSON
2789 container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
2790
2791 @return In case of a structured type (array or object), a reference to the
2792 first element is returned. In cast of number, string, or boolean values, a
2793 reference to the value is returned.
2794
2795 @complexity Constant.
2796
2797 @note Calling `front` on an empty container is undefined.
2798
2799 @throw std::out_of_range when called on null value
2800
2801 @liveexample{The following code shows an example for @ref front.,front}
2802 */
2803 reference front()
2804 {
2805 return *begin();
2806 }
2807
2808 /*!
2809 @copydoc basic_json::front()
2810 */
2811 const_reference front() const
2812 {
2813 return *cbegin();
2814 }
2815
2816 /*!
2817 @brief access the last element
2818
2819 Returns a reference to the last element in the container. For a JSON
2820 container `c`, the expression `c.back()` is equivalent to `{ auto tmp =
2821 c.end(); --tmp; return *tmp; }`.
2822
2823 @return In case of a structured type (array or object), a reference to the
2824 last element is returned. In cast of number, string, or boolean values, a
2825 reference to the value is returned.
2826
2827 @complexity Constant.
2828
2829 @note Calling `back` on an empty container is undefined.
2830
2831 @throw std::out_of_range when called on null value.
2832
2833 @liveexample{The following code shows an example for @ref back.,back}
2834 */
2835 reference back()
2836 {
2837 auto tmp = end();
2838 --tmp;
2839 return *tmp;
2840 }
2841
2842 /*!
2843 @copydoc basic_json::back()
2844 */
2845 const_reference back() const
2846 {
2847 auto tmp = cend();
2848 --tmp;
2849 return *tmp;
2850 }
2851
2852 /*!
2853 @brief remove element given an iterator
2854
2855 Removes the element specified by iterator @a pos. Invalidates iterators and
2856 references at or after the point of the erase, including the end()
2857 iterator. The iterator @a pos must be valid and dereferenceable. Thus the
2858 end() iterator (which is valid, but is not dereferencable) cannot be used
2859 as a value for @a pos.
2860
2861 If called on a primitive type other than null, the resulting JSON value
2862 will be `null`.
2863
2864 @param[in] pos iterator to the element to remove
2865 @return Iterator following the last removed element. If the iterator @a pos
2866 refers to the last element, the end() iterator is returned.
2867
2868 @tparam InteratorType an @ref iterator or @ref const_iterator
2869
2870 @throw std::domain_error if called on a `null` value
2871 @throw std::domain_error if called on an iterator which does not belong to
2872 the current JSON value
2873 @throw std::out_of_range if called on a primitive type with invalid iterator
2874 (i.e., any iterator which is not end())
2875
2876 @complexity The complexity depends on the type:
2877 - objects: amortized constant
2878 - arrays: linear in distance between pos and the end of the container
2879 - strings: linear in the length of the string
2880 - other types: constant
2881
2882 @liveexample{The example shows the result of erase for different JSON
2883 types.,erase__IteratorType}
2884 */
2885 template <class InteratorType, typename
2886 std::enable_if<
2887 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
2888 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
2889 , int>::type
2890 = 0>
2891 InteratorType erase(InteratorType pos)
2892 {
2893 // make sure iterator fits the current value
2894 if (this != pos.m_object)
2895 {
2896 throw std::domain_error("iterator does not fit current value");
2897 }
2898
2899 InteratorType result = end();
2900
2901 switch (m_type)
2902 {
2903 case value_t::number_integer:
2904 case value_t::number_float:
2905 case value_t::boolean:
2906 case value_t::string:
2907 {
2908 if (not pos.m_it.primitive_iterator.is_begin())
2909 {
2910 throw std::out_of_range("iterator out of range");
2911 }
2912
2913 if (m_type == value_t::string)
2914 {
2915 delete m_value.string;
2916 m_value.string = nullptr;
2917 }
2918
2919 m_type = value_t::null;
2920 break;
2921 }
2922
2923 case value_t::object:
2924 {
2925 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
2926 break;
2927 }
2928
2929 case value_t::array:
2930 {
2931 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
2932 break;
2933 }
2934
2935 default:
2936 {
2937 throw std::domain_error("cannot use erase() with " + type_name());
2938 }
2939 }
2940
2941 return result;
2942 }
2943
2944 /*!
2945 @brief remove elements given an iterator range
2946
2947 Removes the element specified by the range `[first; last)`. Invalidates
2948 iterators and references at or after the point of the erase, including the
2949 end() iterator. The iterator @a first does not need to be dereferenceable
2950 if `first == last`: erasing an empty range is a no-op.
2951
2952 If called on a primitive type other than null, the resulting JSON value
2953 will be `null`.
2954
2955 @param[in] first iterator to the beginning of the range to remove
2956 @param[in] last iterator past the end of the range to remove
2957 @return Iterator following the last removed element. If the iterator @a
2958 second refers to the last element, the end() iterator is returned.
2959
2960 @tparam InteratorType an @ref iterator or @ref const_iterator
2961
2962 @throw std::domain_error if called on a `null` value
2963 @throw std::domain_error if called on iterators which does not belong to
2964 the current JSON value
2965 @throw std::out_of_range if called on a primitive type with invalid iterators
2966 (i.e., if `first != begin()` and `last != end()`)
2967
2968 @complexity The complexity depends on the type:
2969 - objects: `log(size()) + std::distance(first, last)`
2970 - arrays: linear in the distance between @a first and @a last, plus linear
2971 in the distance between @a last and end of the container
2972 - strings: linear in the length of the string
2973 - other types: constant
2974
2975 @liveexample{The example shows the result of erase for different JSON
2976 types.,erase__IteratorType_IteratorType}
2977 */
2978 template <class InteratorType, typename
2979 std::enable_if<
2980 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
2981 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
2982 , int>::type
2983 = 0>
2984 InteratorType erase(InteratorType first, InteratorType last)
2985 {
2986 // make sure iterator fits the current value
2987 if (this != first.m_object or this != last.m_object)
2988 {
2989 throw std::domain_error("iterators do not fit current value");
2990 }
2991
2992 InteratorType result = end();
2993
2994 switch (m_type)
2995 {
2996 case value_t::number_integer:
2997 case value_t::number_float:
2998 case value_t::boolean:
2999 case value_t::string:
3000 {
3001 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3002 {
3003 throw std::out_of_range("iterators out of range");
3004 }
3005
3006 if (m_type == value_t::string)
3007 {
3008 delete m_value.string;
3009 m_value.string = nullptr;
3010 }
3011
3012 m_type = value_t::null;
3013 break;
3014 }
3015
3016 case value_t::object:
3017 {
3018 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3019 last.m_it.object_iterator);
3020 break;
3021 }
3022
3023 case value_t::array:
3024 {
3025 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3026 last.m_it.array_iterator);
3027 break;
3028 }
3029
3030 default:
3031 {
3032 throw std::domain_error("cannot use erase with " + type_name());
3033 }
3034 }
3035
3036 return result;
3037 }
3038
3039 /*!
3040 @brief remove element from a JSON object given a key
3041
3042 Removes elements from a JSON object with the key value @a key.
3043
3044 @param[in] key value of the elements to remove
3045
3046 @return Number of elements removed. If ObjectType is the default `std::map`
3047 type, the return value will always be `0` (@a key was not found) or `1` (@a
3048 key was found).
3049
3050 @throw std::domain_error when called on a type other than JSON object
3051
3052 @complexity `log(size()) + count(key)`
3053
3054 @liveexample{The example shows the effect of erase.,erase__key_type}
3055 */
3056 size_type erase(const typename object_t::key_type& key)
3057 {
3058 // this erase only works for objects
3059 if (m_type != value_t::object)
3060 {
3061 throw std::domain_error("cannot use erase() with " + type_name());
3062 }
3063
3064 return m_value.object->erase(key);
3065 }
3066
3067 /*!
3068 @brief remove element from a JSON array given an index
3069
3070 Removes element from a JSON array at the index @a idx.
3071
3072 @param[in] idx index of the element to remove
3073
3074 @throw std::domain_error when called on a type other than JSON array
3075 @throw std::out_of_range when `idx >= size()`
3076
3077 @complexity Linear in distance between @a idx and the end of the container.
3078
3079 @liveexample{The example shows the effect of erase.,erase__size_type}
3080 */
3081 void erase(const size_type idx)
3082 {
3083 // this erase only works for arrays
3084 if (m_type != value_t::array)
3085 {
3086 throw std::domain_error("cannot use erase() with " + type_name());
3087 }
3088
3089 if (idx >= size())
3090 {
3091 throw std::out_of_range("index out of range");
3092 }
3093
3094 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
3095 }
3096
3097 /*!
3098 @brief find an element in a JSON object
3099
3100 Finds an element in a JSON object with key equivalent to @a key. If the
3101 element is not found or the JSON value is not an object, end() is returned.
3102
3103 @param[in] key key value of the element to search for
3104
3105 @return Iterator to an element with key equivalent to @a key. If no such
3106 element is found, past-the-end (see end()) iterator is returned.
3107
3108 @complexity Logarithmic in the size of the JSON object.
3109
3110 @liveexample{The example shows how find is used.,find__key_type}
3111 */
3112 iterator find(typename object_t::key_type key)
3113 {
3114 auto result = end();
3115
3116 if (m_type == value_t::object)
3117 {
3118 result.m_it.object_iterator = m_value.object->find(key);
3119 }
3120
3121 return result;
3122 }
3123
3124 /*!
3125 @brief find an element in a JSON object
3126 @copydoc find(typename object_t::key_type)
3127 */
3128 const_iterator find(typename object_t::key_type key) const
3129 {
3130 auto result = cend();
3131
3132 if (m_type == value_t::object)
3133 {
3134 result.m_it.object_iterator = m_value.object->find(key);
3135 }
3136
3137 return result;
3138 }
3139
3140 /*!
3141 @brief returns the number of occurrences of a key in a JSON object
3142
3143 Returns the number of elements with key @a key. If ObjectType is the
3144 default `std::map` type, the return value will always be `0` (@a key was
3145 not found) or `1` (@a key was found).
3146
3147 @param[in] key key value of the element to count
3148
3149 @return Number of elements with key @a key. If the JSON value is not an
3150 object, the return value will be `0`.
3151
3152 @complexity Logarithmic in the size of the JSON object.
3153
3154 @liveexample{The example shows how count is used.,count}
3155 */
3156 size_type count(typename object_t::key_type key) const
3157 {
3158 // return 0 for all nonobject types
3159 return (m_type == value_t::object) ? m_value.object->count(key) : 0;
3160 }
3161
3162 /// @}
3163
3164
3165 ///////////////
3166 // iterators //
3167 ///////////////
3168
3169 /// @name iterators
3170 /// @{
3171
3172 /*!
3173 @brief returns an iterator to the first element
3174
3175 Returns an iterator to the first element.
3176
3177 @image html range-begin-end.svg "Illustration from cppreference.com"
3178
3179 @return iterator to the first element
3180
3181 @complexity Constant.
3182
3183 @requirement This function satisfies the Container requirements:
3184 - The complexity is constant.
3185
3186 @liveexample{The following code shows an example for @ref begin.,begin}
3187 */
3188 iterator begin()
3189 {
3190 iterator result(this);
3191 result.set_begin();
3192 return result;
3193 }
3194
3195 /*!
3196 @copydoc basic_json::cbegin()
3197 */
3198 const_iterator begin() const
3199 {
3200 return cbegin();
3201 }
3202
3203 /*!
3204 @brief returns a const iterator to the first element
3205
3206 Returns a const iterator to the first element.
3207
3208 @image html range-begin-end.svg "Illustration from cppreference.com"
3209
3210 @return const iterator to the first element
3211
3212 @complexity Constant.
3213
3214 @requirement This function satisfies the Container requirements:
3215 - The complexity is constant.
3216 - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
3217
3218 @liveexample{The following code shows an example for @ref cbegin.,cbegin}
3219 */
3220 const_iterator cbegin() const
3221 {
3222 const_iterator result(this);
3223 result.set_begin();
3224 return result;
3225 }
3226
3227 /*!
3228 @brief returns an iterator to one past the last element
3229
3230 Returns an iterator to one past the last element.
3231
3232 @image html range-begin-end.svg "Illustration from cppreference.com"
3233
3234 @return iterator one past the last element
3235
3236 @complexity Constant.
3237
3238 @requirement This function satisfies the Container requirements:
3239 - The complexity is constant.
3240
3241 @liveexample{The following code shows an example for @ref end.,end}
3242 */
3243 iterator end()
3244 {
3245 iterator result(this);
3246 result.set_end();
3247 return result;
3248 }
3249
3250 /*!
3251 @copydoc basic_json::cend()
3252 */
3253 const_iterator end() const
3254 {
3255 return cend();
3256 }
3257
3258 /*!
3259 @brief returns a const iterator to one past the last element
3260
3261 Returns a const iterator to one past the last element.
3262
3263 @image html range-begin-end.svg "Illustration from cppreference.com"
3264
3265 @return const iterator one past the last element
3266
3267 @complexity Constant.
3268
3269 @requirement This function satisfies the Container requirements:
3270 - The complexity is constant.
3271 - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
3272
3273 @liveexample{The following code shows an example for @ref cend.,cend}
3274 */
3275 const_iterator cend() const
3276 {
3277 const_iterator result(this);
3278 result.set_end();
3279 return result;
3280 }
3281
3282 /*!
3283 @brief returns an iterator to the reverse-beginning
3284
3285 Returns an iterator to the reverse-beginning; that is, the last element.
3286
3287 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
3288
3289 @complexity Constant.
3290
3291 @requirement This function satisfies the ReversibleContainer requirements:
3292 - The complexity is constant.
3293 - Has the semantics of `reverse_iterator(end())`.
3294
3295 @liveexample{The following code shows an example for @ref rbegin.,rbegin}
3296 */
3297 reverse_iterator rbegin()
3298 {
3299 return reverse_iterator(end());
3300 }
3301
3302 /*!
3303 @copydoc basic_json::crbegin()
3304 */
3305 const_reverse_iterator rbegin() const
3306 {
3307 return crbegin();
3308 }
3309
3310 /*!
3311 @brief returns an iterator to the reverse-end
3312
3313 Returns an iterator to the reverse-end; that is, one before the first
3314 element.
3315
3316 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
3317
3318 @complexity Constant.
3319
3320 @requirement This function satisfies the ReversibleContainer requirements:
3321 - The complexity is constant.
3322 - Has the semantics of `reverse_iterator(begin())`.
3323
3324 @liveexample{The following code shows an example for @ref rend.,rend}
3325 */
3326 reverse_iterator rend()
3327 {
3328 return reverse_iterator(begin());
3329 }
3330
3331 /*!
3332 @copydoc basic_json::crend()
3333 */
3334 const_reverse_iterator rend() const
3335 {
3336 return crend();
3337 }
3338
3339 /*!
3340 @brief returns a const reverse iterator to the last element
3341
3342 Returns a const iterator to the reverse-beginning; that is, the last
3343 element.
3344
3345 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
3346
3347 @complexity Constant.
3348
3349 @requirement This function satisfies the ReversibleContainer requirements:
3350 - The complexity is constant.
3351 - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
3352
3353 @liveexample{The following code shows an example for @ref crbegin.,crbegin}
3354 */
3355 const_reverse_iterator crbegin() const
3356 {
3357 return const_reverse_iterator(cend());
3358 }
3359
3360 /*!
3361 @brief returns a const reverse iterator to one before the first
3362
3363 Returns a const reverse iterator to the reverse-end; that is, one before
3364 the first element.
3365
3366 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
3367
3368 @complexity Constant.
3369
3370 @requirement This function satisfies the ReversibleContainer requirements:
3371 - The complexity is constant.
3372 - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
3373
3374 @liveexample{The following code shows an example for @ref crend.,crend}
3375 */
3376 const_reverse_iterator crend() const
3377 {
3378 return const_reverse_iterator(cbegin());
3379 }
3380
3381 /// @}
3382
3383
3384 //////////////
3385 // capacity //
3386 //////////////
3387
3388 /// @name capacity
3389 /// @{
3390
3391 /*!
3392 @brief checks whether the container is empty
3393
3394 Checks if a JSON value has no elements.
3395
3396 @return The return value depends on the different types and is
3397 defined as follows:
3398 Value type | return value
3399 ----------- | -------------
3400 null | @c true
3401 boolean | @c false
3402 string | @c false
3403 number | @c false
3404 object | result of function object_t::empty()
3405 array | result of function array_t::empty()
3406
3407 @complexity Constant, as long as @ref array_t and @ref object_t satisfy the
3408 Container concept; that is, their empty() functions have
3409 constant complexity.
3410
3411 @requirement This function satisfies the Container requirements:
3412 - The complexity is constant.
3413 - Has the semantics of `begin() == end()`.
3414
3415 @liveexample{The following code uses @ref empty to check if a @ref json
3416 object contains any elements.,empty}
3417 */
3418 bool empty() const noexcept
3419 {
3420 switch (m_type)
3421 {
3422 case (value_t::null):
3423 {
3424 return true;
3425 }
3426
3427 case (value_t::array):
3428 {
3429 return m_value.array->empty();
3430 }
3431
3432 case (value_t::object):
3433 {
3434 return m_value.object->empty();
3435 }
3436
3437 default:
3438 {
3439 // all other types are nonempty
3440 return false;
3441 }
3442 }
3443 }
3444
3445 /*!
3446 @brief returns the number of elements
3447
3448 Returns the number of elements in a JSON value.
3449
3450 @return The return value depends on the different types and is
3451 defined as follows:
3452 Value type | return value
3453 ----------- | -------------
3454 null | @c 0
3455 boolean | @c 1
3456 string | @c 1
3457 number | @c 1
3458 object | result of function object_t::size()
3459 array | result of function array_t::size()
3460
3461 @complexity Constant, as long as @ref array_t and @ref object_t satisfy the
3462 Container concept; that is, their size() functions have
3463 constant complexity.
3464
3465 @requirement This function satisfies the Container requirements:
3466 - The complexity is constant.
3467 - Has the semantics of `std::distance(begin(), end())`.
3468
3469 @liveexample{The following code calls @ref size on the different value
3470 types.,size}
3471 */
3472 size_type size() const noexcept
3473 {
3474 switch (m_type)
3475 {
3476 case (value_t::null):
3477 {
3478 return 0;
3479 }
3480
3481 case (value_t::array):
3482 {
3483 return m_value.array->size();
3484 }
3485
3486 case (value_t::object):
3487 {
3488 return m_value.object->size();
3489 }
3490
3491 default:
3492 {
3493 // all other types have size 1
3494 return 1;
3495 }
3496 }
3497 }
3498
3499 /*!
3500 @brief returns the maximum possible number of elements
3501
3502 Returns the maximum number of elements a JSON value is able to hold due to
3503 system or library implementation limitations, i.e. `std::distance(begin(),
3504 end())` for the JSON value.
3505
3506 @return The return value depends on the different types and is
3507 defined as follows:
3508 Value type | return value
3509 ----------- | -------------
3510 null | @c 0 (same as size())
3511 boolean | @c 1 (same as size())
3512 string | @c 1 (same as size())
3513 number | @c 1 (same as size())
3514 object | result of function object_t::max_size()
3515 array | result of function array_t::max_size()
3516
3517 @complexity Constant, as long as @ref array_t and @ref object_t satisfy the
3518 Container concept; that is, their max_size() functions have
3519 constant complexity.
3520
3521 @requirement This function satisfies the Container requirements:
3522 - The complexity is constant.
3523 - Has the semantics of returning `b.size()` where `b` is the largest
3524 possible JSON value.
3525
3526 @liveexample{The following code calls @ref max_size on the different value
3527 types. Note the output is implementation specific.,max_size}
3528 */
3529 size_type max_size() const noexcept
3530 {
3531 switch (m_type)
3532 {
3533 case (value_t::array):
3534 {
3535 return m_value.array->max_size();
3536 }
3537
3538 case (value_t::object):
3539 {
3540 return m_value.object->max_size();
3541 }
3542
3543 default:
3544 {
3545 // all other types have max_size() == size()
3546 return size();
3547 }
3548 }
3549 }
3550
3551 /// @}
3552
3553
3554 ///////////////
3555 // modifiers //
3556 ///////////////
3557
3558 /// @name modifiers
3559 /// @{
3560
3561 /*!
3562 @brief clears the contents
3563
3564 Clears the content of a JSON value and resets it to the default value as
3565 if @ref basic_json(value_t) would have been called:
3566
3567 Value type | initial value
3568 ----------- | -------------
3569 null | `null`
3570 boolean | `false`
3571 string | `""`
3572 number | `0`
3573 object | `{}`
3574 array | `[]`
3575
3576 @note Floating-point numbers are set to `0.0` which will be serialized to
3577 `0`. The vale type remains @ref number_float_t.
3578
3579 @complexity Linear in the size of the JSON value.
3580
3581 @liveexample{The example below shows the effect of @ref clear to different
3582 JSON types.,clear}
3583 */
3584 void clear() noexcept
3585 {
3586 switch (m_type)
3587 {
3588 case (value_t::null):
3589 case (value_t::discarded):
3590 {
3591 break;
3592 }
3593
3594 case (value_t::number_integer):
3595 {
3596 m_value.number_integer = 0;
3597 break;
3598 }
3599
3600 case (value_t::number_float):
3601 {
3602 m_value.number_float = 0.0;
3603 break;
3604 }
3605
3606 case (value_t::boolean):
3607 {
3608 m_value.boolean = false;
3609 break;
3610 }
3611
3612 case (value_t::string):
3613 {
3614 m_value.string->clear();
3615 break;
3616 }
3617
3618 case (value_t::array):
3619 {
3620 m_value.array->clear();
3621 break;
3622 }
3623
3624 case (value_t::object):
3625 {
3626 m_value.object->clear();
3627 break;
3628 }
3629 }
3630 }
3631
3632 /*!
3633 @brief add an object to an array
3634
3635 Appends the given element @a value to the end of the JSON value. If the
3636 function is called on a JSON null value, an empty array is created before
3637 appending @a value.
3638
3639 @param value the value to add to the JSON array
3640
3641 @throw std::domain_error when called on a type other than JSON array or null
3642
3643 @complexity Amortized constant.
3644
3645 @liveexample{The example shows how `push_back` and `+=` can be used to add
3646 elements to a JSON array. Note how the `null` value was silently converted
3647 to a JSON array.,push_back}
3648 */
3649 void push_back(basic_json&& value)
3650 {
3651 // push_back only works for null objects or arrays
3652 if (not(m_type == value_t::null or m_type == value_t::array))
3653 {
3654 throw std::domain_error("cannot use push_back() with " + type_name());
3655 }
3656
3657 // transform null object into an array
3658 if (m_type == value_t::null)
3659 {
3660 m_type = value_t::array;
3661 m_value = value_t::array;
3662 }
3663
3664 // add element to array (move semantics)
3665 m_value.array->push_back(std::move(value));
3666 // invalidate object
3667 value.m_type = value_t::null;
3668 }
3669
3670 /*!
3671 @brief add an object to an array
3672 @copydoc push_back(basic_json&&)
3673 */
3674 reference operator+=(basic_json&& value)
3675 {
3676 push_back(std::move(value));
3677 return *this;
3678 }
3679
3680 /*!
3681 @brief add an object to an array
3682 @copydoc push_back(basic_json&&)
3683 */
3684 void push_back(const basic_json& value)
3685 {
3686 // push_back only works for null objects or arrays
3687 if (not(m_type == value_t::null or m_type == value_t::array))
3688 {
3689 throw std::domain_error("cannot use push_back() with " + type_name());
3690 }
3691
3692 // transform null object into an array
3693 if (m_type == value_t::null)
3694 {
3695 m_type = value_t::array;
3696 m_value = value_t::array;
3697 }
3698
3699 // add element to array
3700 m_value.array->push_back(value);
3701 }
3702
3703 /*!
3704 @brief add an object to an array
3705 @copydoc push_back(basic_json&&)
3706 */
3707 reference operator+=(const basic_json& value)
3708 {
3709 push_back(value);
3710 return *this;
3711 }
3712
3713 /*!
3714 @brief add an object to an object
3715
3716 Inserts the given element @a value to the JSON object. If the function is
3717 called on a JSON null value, an empty object is created before inserting @a
3718 value.
3719
3720 @param[in] value the value to add to the JSON object
3721
3722 @throw std::domain_error when called on a type other than JSON object or
3723 null
3724
3725 @complexity Logarithmic in the size of the container, O(log(`size()`)).
3726
3727 @liveexample{The example shows how `push_back` and `+=` can be used to add
3728 elements to a JSON object. Note how the `null` value was silently converted
3729 to a JSON object.,push_back__object_t__value}
3730 */
3731 void push_back(const typename object_t::value_type& value)
3732 {
3733 // push_back only works for null objects or objects
3734 if (not(m_type == value_t::null or m_type == value_t::object))
3735 {
3736 throw std::domain_error("cannot use push_back() with " + type_name());
3737 }
3738
3739 // transform null object into an object
3740 if (m_type == value_t::null)
3741 {
3742 m_type = value_t::object;
3743 m_value = value_t::object;
3744 }
3745
3746 // add element to array
3747 m_value.object->insert(value);
3748 }
3749
3750 /*!
3751 @brief add an object to an object
3752 @copydoc push_back(const typename object_t::value_type&)
3753 */
3754 reference operator+=(const typename object_t::value_type& value)
3755 {
3756 push_back(value);
3757 return operator[](value.first);
3758 }
3759
3760 /*!
3761 @brief inserts element
3762
3763 Inserts element @a value before iterator @a pos.
3764
3765 @param[in] pos iterator before which the content will be inserted; may be
3766 the end() iterator
3767 @param[in] value element to insert
3768 @return iterator pointing to the inserted @a value.
3769
3770 @throw std::domain_error if called on JSON values other than arrays
3771 @throw std::domain_error if @a pos is not an iterator of *this
3772
3773 @complexity Constant plus linear in the distance between pos and end of the
3774 container.
3775
3776 @liveexample{The example shows how insert is used.,insert}
3777 */
3778 iterator insert(const_iterator pos, const basic_json& value)
3779 {
3780 // insert only works for arrays
3781 if (m_type != value_t::array)
3782 {
3783 throw std::domain_error("cannot use insert() with " + type_name());
3784 }
3785
3786 // check if iterator pos fits to this JSON value
3787 if (pos.m_object != this)
3788 {
3789 throw std::domain_error("iterator does not fit current value");
3790 }
3791
3792 // insert to array and return iterator
3793 iterator result(this);
3794 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, value);
3795 return result;
3796 }
3797
3798 /*!
3799 @brief inserts element
3800 @copydoc insert(const_iterator, const basic_json&)
3801 */
3802 iterator insert(const_iterator pos, basic_json&& value)
3803 {
3804 return insert(pos, value);
3805 }
3806
3807 /*!
3808 @brief inserts elements
3809
3810 Inserts @a count copies of @a value before iterator @a pos.
3811
3812 @param[in] pos iterator before which the content will be inserted; may be
3813 the end() iterator
3814 @param[in] count number of copies of @a value to insert
3815 @param[in] value element to insert
3816 @return iterator pointing to the first element inserted, or @a pos if
3817 `count==0`
3818
3819 @throw std::domain_error if called on JSON values other than arrays
3820 @throw std::domain_error if @a pos is not an iterator of *this
3821
3822 @complexity Linear in @a count plus linear in the distance between @a pos
3823 and end of the container.
3824
3825 @liveexample{The example shows how insert is used.,insert__count}
3826 */
3827 iterator insert(const_iterator pos, size_type count, const basic_json& value)
3828 {
3829 // insert only works for arrays
3830 if (m_type != value_t::array)
3831 {
3832 throw std::domain_error("cannot use insert() with " + type_name());
3833 }
3834
3835 // check if iterator pos fits to this JSON value
3836 if (pos.m_object != this)
3837 {
3838 throw std::domain_error("iterator does not fit current value");
3839 }
3840
3841 // insert to array and return iterator
3842 iterator result(this);
3843 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, count, value);
3844 return result;
3845 }
3846
3847 /*!
3848 @brief inserts elements
3849
3850 Inserts elements from range `[first, last)` before iterator @a pos.
3851
3852 @param[in] pos iterator before which the content will be inserted; may be
3853 the end() iterator
3854 @param[in] first begin of the range of elements to insert
3855 @param[in] last end of the range of elements to insert
3856
3857 @throw std::domain_error if called on JSON values other than arrays
3858 @throw std::domain_error if @a pos is not an iterator of *this
3859 @throw std::domain_error if @a first and @a last do not belong to the same
3860 JSON value
3861 @throw std::domain_error if @a first or @a last are iterators into
3862 container for which insert is called
3863 @return iterator pointing to the first element inserted, or @a pos if
3864 `first==last`
3865
3866 @complexity Linear in `std::distance(first, last)` plus linear in the
3867 distance between @a pos and end of the container.
3868
3869 @liveexample{The example shows how insert is used.,insert__range}
3870 */
3871 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
3872 {
3873 // insert only works for arrays
3874 if (m_type != value_t::array)
3875 {
3876 throw std::domain_error("cannot use insert() with " + type_name());
3877 }
3878
3879 // check if iterator pos fits to this JSON value
3880 if (pos.m_object != this)
3881 {
3882 throw std::domain_error("iterator does not fit current value");
3883 }
3884
3885 if (first.m_object != last.m_object)
3886 {
3887 throw std::domain_error("iterators does not fit");
3888 }
3889
3890 if (first.m_object == this or last.m_object == this)
3891 {
3892 throw std::domain_error("passed iterators may not belong to container");
3893 }
3894
3895 // insert to array and return iterator
3896 iterator result(this);
3897 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator,
3898 first.m_it.array_iterator, last.m_it.array_iterator);
3899 return result;
3900 }
3901
3902 /*!
3903 @brief inserts elements
3904
3905 Inserts elements from initializer list @a ilist before iterator @a pos.
3906
3907 @param[in] pos iterator before which the content will be inserted; may be
3908 the end() iterator
3909 @param[in] ilist initializer list to insert the values from
3910
3911 @throw std::domain_error if called on JSON values other than arrays
3912 @throw std::domain_error if @a pos is not an iterator of *this
3913 @return iterator pointing to the first element inserted, or @a pos if
3914 `ilist` is empty
3915
3916 @complexity Linear in `ilist.size()` plus linear in the distance between @a
3917 pos and end of the container.
3918
3919 @liveexample{The example shows how insert is used.,insert__ilist}
3920 */
3921 iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
3922 {
3923 // insert only works for arrays
3924 if (m_type != value_t::array)
3925 {
3926 throw std::domain_error("cannot use insert() with " + type_name());
3927 }
3928
3929 // check if iterator pos fits to this JSON value
3930 if (pos.m_object != this)
3931 {
3932 throw std::domain_error("iterator does not fit current value");
3933 }
3934
3935 // insert to array and return iterator
3936 iterator result(this);
3937 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
3938 return result;
3939 }
3940
3941 /*!
3942 @brief exchanges the values
3943
3944 Exchanges the contents of the JSON value with those of @a other. Does not
3945 invoke any move, copy, or swap operations on individual elements. All
3946 iterators and references remain valid. The past-the-end iterator is
3947 invalidated.
3948
3949 @param[in,out] other JSON value to exchange the contents with
3950
3951 @complexity Constant.
3952
3953 @liveexample{The example below shows how JSON arrays can be
3954 swapped.,swap__reference}
3955 */
3956 void swap(reference other) noexcept (
3957 std::is_nothrow_move_constructible<value_t>::value and
3958 std::is_nothrow_move_assignable<value_t>::value and
3959 std::is_nothrow_move_constructible<json_value>::value and
3960 std::is_nothrow_move_assignable<json_value>::value
3961 )
3962 {
3963 std::swap(m_type, other.m_type);
3964 std::swap(m_value, other.m_value);
3965 }
3966
3967 /*!
3968 @brief exchanges the values
3969
3970 Exchanges the contents of a JSON array with those of @a other. Does not
3971 invoke any move, copy, or swap operations on individual elements. All
3972 iterators and references remain valid. The past-the-end iterator is
3973 invalidated.
3974
3975 @param[in,out] other array to exchange the contents with
3976
3977 @throw std::domain_error when JSON value is not an array
3978
3979 @complexity Constant.
3980
3981 @liveexample{The example below shows how JSON values can be
3982 swapped.,swap__array_t}
3983 */
3984 void swap(array_t& other)
3985 {
3986 // swap only works for arrays
3987 if (m_type != value_t::array)
3988 {
3989 throw std::domain_error("cannot use swap() with " + type_name());
3990 }
3991
3992 // swap arrays
3993 std::swap(*(m_value.array), other);
3994 }
3995
3996 /*!
3997 @brief exchanges the values
3998
3999 Exchanges the contents of a JSON object with those of @a other. Does not
4000 invoke any move, copy, or swap operations on individual elements. All
4001 iterators and references remain valid. The past-the-end iterator is
4002 invalidated.
4003
4004 @param[in,out] other object to exchange the contents with
4005
4006 @throw std::domain_error when JSON value is not an object
4007
4008 @complexity Constant.
4009
4010 @liveexample{The example below shows how JSON values can be
4011 swapped.,swap__object_t}
4012 */
4013 void swap(object_t& other)
4014 {
4015 // swap only works for objects
4016 if (m_type != value_t::object)
4017 {
4018 throw std::domain_error("cannot use swap() with " + type_name());
4019 }
4020
4021 // swap objects
4022 std::swap(*(m_value.object), other);
4023 }
4024
4025 /*!
4026 @brief exchanges the values
4027
4028 Exchanges the contents of a JSON string with those of @a other. Does not
4029 invoke any move, copy, or swap operations on individual elements. All
4030 iterators and references remain valid. The past-the-end iterator is
4031 invalidated.
4032
4033 @param[in,out] other string to exchange the contents with
4034
4035 @throw std::domain_error when JSON value is not a string
4036
4037 @complexity Constant.
4038
4039 @liveexample{The example below shows how JSON values can be
4040 swapped.,swap__string_t}
4041 */
4042 void swap(string_t& other)
4043 {
4044 // swap only works for strings
4045 if (m_type != value_t::string)
4046 {
4047 throw std::domain_error("cannot use swap() with " + type_name());
4048 }
4049
4050 // swap strings
4051 std::swap(*(m_value.string), other);
4052 }
4053
4054 /// @}
4055
4056
4057 //////////////////////////////////////////
4058 // lexicographical comparison operators //
4059 //////////////////////////////////////////
4060
4061 /// @name lexicographical comparison operators
4062 /// @{
4063
4064 private:
4065 /*!
4066 @brief comparison operator for JSON types
4067
4068 Returns an ordering that is similar to Python:
4069 - order: null < boolean < number < object < array < string
4070 - furthermore, each type is not smaller than itself
4071 */
4072 friend bool operator<(const value_t lhs, const value_t rhs)
4073 {
4074 static constexpr std::array<uint8_t, 7> order = {{
4075 0, // null
4076 3, // object
4077 4, // array
4078 5, // string
4079 1, // boolean
4080 2, // integer
4081 2 // float
4082 }
4083 };
4084
4085 // discarded values are not comparable
4086 if (lhs == value_t::discarded or rhs == value_t::discarded)
4087 {
4088 return false;
4089 }
4090
4091 return order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
4092 }
4093
4094 public:
4095 /*!
4096 @brief comparison: equal
4097
4098 Compares two JSON values for equality according to the following rules:
4099 - Two JSON values are equal if (1) they are from the same type and (2)
4100 their stored values are the same.
4101 - Integer and floating-point numbers are automatically converted before
4102 comparison. Floating-point numbers are compared indirectly: two
4103 floating-point numbers `f1` and `f2` are considered equal if neither
4104 `f1 > f2` nor `f2 > f1` holds.
4105 - Two JSON null values are equal.
4106
4107 @param[in] lhs first JSON value to consider
4108 @param[in] rhs second JSON value to consider
4109 @return whether the values @a lhs and @a rhs are equal
4110
4111 @complexity Linear.
4112
4113 @liveexample{The example demonstrates comparing several JSON
4114 types.,operator__equal}
4115 */
4116 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
4117 {
4118 const auto lhs_type = lhs.type();
4119 const auto rhs_type = rhs.type();
4120
4121 if (lhs_type == rhs_type)
4122 {
4123 switch (lhs_type)
4124 {
4125 case (value_t::array):
4126 return *lhs.m_value.array == *rhs.m_value.array;
4127 case (value_t::object):
4128 return *lhs.m_value.object == *rhs.m_value.object;
4129 case (value_t::null):
4130 return true;
4131 case (value_t::string):
4132 return *lhs.m_value.string == *rhs.m_value.string;
4133 case (value_t::boolean):
4134 return lhs.m_value.boolean == rhs.m_value.boolean;
4135 case (value_t::number_integer):
4136 return lhs.m_value.number_integer == rhs.m_value.number_integer;
4137 case (value_t::number_float):
4138 return approx(lhs.m_value.number_float, rhs.m_value.number_float);
4139 case (value_t::discarded):
4140 return false;
4141 }
4142 }
4143 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4144 {
4145 return approx(static_cast<number_float_t>(lhs.m_value.number_integer),
4146 rhs.m_value.number_float);
4147 }
4148 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4149 {
4150 return approx(lhs.m_value.number_float,
4151 static_cast<number_float_t>(rhs.m_value.number_integer));
4152 }
4153 return false;
4154 }
4155
4156 /*!
4157 @brief comparison: equal
4158
4159 The functions compares the given JSON value against a null pointer. As the
4160 null pointer can be used to initialize a JSON value to null, a comparison
4161 of JSON value @a v with a null pointer should be equivalent to call
4162 `v.is_null()`.
4163
4164 @param[in] v JSON value to consider
4165 @return whether @a v is null
4166
4167 @complexity Constant.
4168
4169 @liveexample{The example compares several JSON types to the null pointer.
4170 ,operator__equal__nullptr_t}
4171 */
4172 friend bool operator==(const_reference v, std::nullptr_t) noexcept
4173 {
4174 return v.is_null();
4175 }
4176
4177 /*!
4178 @brief comparison: equal
4179 @copydoc operator==(const_reference, std::nullptr_t)
4180 */
4181 friend bool operator==(std::nullptr_t, const_reference v) noexcept
4182 {
4183 return v.is_null();
4184 }
4185
4186 /*!
4187 @brief comparison: not equal
4188
4189 Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
4190
4191 @param[in] lhs first JSON value to consider
4192 @param[in] rhs second JSON value to consider
4193 @return whether the values @a lhs and @a rhs are not equal
4194
4195 @complexity Linear.
4196
4197 @liveexample{The example demonstrates comparing several JSON
4198 types.,operator__notequal}
4199 */
4200 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
4201 {
4202 return not (lhs == rhs);
4203 }
4204
4205 /*!
4206 @brief comparison: not equal
4207
4208 The functions compares the given JSON value against a null pointer. As the
4209 null pointer can be used to initialize a JSON value to null, a comparison
4210 of JSON value @a v with a null pointer should be equivalent to call
4211 `not v.is_null()`.
4212
4213 @param[in] v JSON value to consider
4214 @return whether @a v is not null
4215
4216 @complexity Constant.
4217
4218 @liveexample{The example compares several JSON types to the null pointer.
4219 ,operator__notequal__nullptr_t}
4220 */
4221 friend bool operator!=(const_reference v, std::nullptr_t) noexcept
4222 {
4223 return not v.is_null();
4224 }
4225
4226 /*!
4227 @brief comparison: not equal
4228 @copydoc operator!=(const_reference, std::nullptr_t)
4229 */
4230 friend bool operator!=(std::nullptr_t, const_reference v) noexcept
4231 {
4232 return not v.is_null();
4233 }
4234
4235 /*!
4236 @brief comparison: less than
4237
4238 Compares whether one JSON value @a lhs is less than another JSON value @a
4239 rhs according to the following rules:
4240 - If @a lhs and @a rhs have the same type, the values are compared using
4241 the default `<` operator.
4242 - Integer and floating-point numbers are automatically converted before
4243 comparison
4244 - In case @a lhs and @a rhs have different types, the values are ignored
4245 and the order of the types is considered, see
4246 @ref operator<(const value_t, const value_t).
4247
4248 @param[in] lhs first JSON value to consider
4249 @param[in] rhs second JSON value to consider
4250 @return whether @a lhs is less than @a rhs
4251
4252 @complexity Linear.
4253
4254 @liveexample{The example demonstrates comparing several JSON
4255 types.,operator__less}
4256 */
4257 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
4258 {
4259 const auto lhs_type = lhs.type();
4260 const auto rhs_type = rhs.type();
4261
4262 if (lhs_type == rhs_type)
4263 {
4264 switch (lhs_type)
4265 {
4266 case (value_t::array):
4267 return *lhs.m_value.array < *rhs.m_value.array;
4268 case (value_t::object):
4269 return *lhs.m_value.object < *rhs.m_value.object;
4270 case (value_t::null):
4271 return false;
4272 case (value_t::string):
4273 return *lhs.m_value.string < *rhs.m_value.string;
4274 case (value_t::boolean):
4275 return lhs.m_value.boolean < rhs.m_value.boolean;
4276 case (value_t::number_integer):
4277 return lhs.m_value.number_integer < rhs.m_value.number_integer;
4278 case (value_t::number_float):
4279 return lhs.m_value.number_float < rhs.m_value.number_float;
4280 case (value_t::discarded):
4281 return false;
4282 }
4283 }
4284 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
4285 {
4286 return static_cast<number_float_t>(lhs.m_value.number_integer) <
4287 rhs.m_value.number_float;
4288 }
4289 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
4290 {
4291 return lhs.m_value.number_float <
4292 static_cast<number_float_t>(rhs.m_value.number_integer);
4293 }
4294
4295 // We only reach this line if we cannot compare values. In that case,
4296 // we compare types. Note we have to call the operator explicitly,
4297 // because MSVC has problems otherwise.
4298 return operator<(lhs_type, rhs_type);
4299 }
4300
4301 /*!
4302 @brief comparison: less than or equal
4303
4304 Compares whether one JSON value @a lhs is less than or equal to another
4305 JSON value by calculating `not (rhs < lhs)`.
4306
4307 @param[in] lhs first JSON value to consider
4308 @param[in] rhs second JSON value to consider
4309 @return whether @a lhs is less than or equal to @a rhs
4310
4311 @complexity Linear.
4312
4313 @liveexample{The example demonstrates comparing several JSON
4314 types.,operator__greater}
4315 */
4316 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
4317 {
4318 return not (rhs < lhs);
4319 }
4320
4321 /*!
4322 @brief comparison: greater than
4323
4324 Compares whether one JSON value @a lhs is greater than another
4325 JSON value by calculating `not (lhs <= rhs)`.
4326
4327 @param[in] lhs first JSON value to consider
4328 @param[in] rhs second JSON value to consider
4329 @return whether @a lhs is greater than to @a rhs
4330
4331 @complexity Linear.
4332
4333 @liveexample{The example demonstrates comparing several JSON
4334 types.,operator__lessequal}
4335 */
4336 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
4337 {
4338 return not (lhs <= rhs);
4339 }
4340
4341 /*!
4342 @brief comparison: greater than or equal
4343
4344 Compares whether one JSON value @a lhs is greater than or equal to another
4345 JSON value by calculating `not (lhs < rhs)`.
4346
4347 @param[in] lhs first JSON value to consider
4348 @param[in] rhs second JSON value to consider
4349 @return whether @a lhs is greater than or equal to @a rhs
4350
4351 @complexity Linear.
4352
4353 @liveexample{The example demonstrates comparing several JSON
4354 types.,operator__greaterequal}
4355 */
4356 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
4357 {
4358 return not (lhs < rhs);
4359 }
4360
4361 /// @}
4362
4363
4364 ///////////////////
4365 // serialization //
4366 ///////////////////
4367
4368 /// @name serialization
4369 /// @{
4370
4371 /*!
4372 @brief serialize to stream
4373
4374 Serialize the given JSON value @a j to the output stream @a o. The JSON
4375 value will be serialized using the @ref dump member function. The
4376 indentation of the output can be controlled with the member variable
4377 `width` of the output stream @a o. For instance, using the manipulator
4378 `std::setw(4)` on @a o sets the indentation level to `4` and the
4379 serialization result is the same as calling `dump(4)`.
4380
4381 @param[in,out] o stream to serialize to
4382 @param[in] j JSON value to serialize
4383
4384 @return the stream @a o
4385
4386 @complexity Linear.
4387
4388 @liveexample{The example below shows the serialization with different
4389 parameters to `width` to adjust the indentation level.,operator_serialize}
4390 */
4391 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4392 {
4393 // read width member and use it as indentation parameter if nonzero
4394 const bool pretty_print = (o.width() > 0);
4395 const auto indentation = (pretty_print ? o.width() : 0);
4396
4397 // reset width to 0 for subsequent calls to this stream
4398 o.width(0);
4399
4400 // do the actual serialization
4401 j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
4402 return o;
4403 }
4404
4405 /*!
4406 @brief serialize to stream
4407 @copydoc operator<<(std::ostream&, const basic_json&)
4408 */
4409 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4410 {
4411 return o << j;
4412 }
4413
4414 /// @}
4415
4416
4417 /////////////////////
4418 // deserialization //
4419 /////////////////////
4420
4421 /// @name deserialization
4422 /// @{
4423
4424 /*!
4425 @brief deserialize from string
4426
4427 @param[in] s string to read a serialized JSON value from
4428 @param[in] cb a parser callback function of type @ref parser_callback_t
4429 which is used to control the deserialization by filtering unwanted values
4430 (optional)
4431
4432 @return result of the deserialization
4433
4434 @complexity Linear in the length of the input. The parser is a predictive
4435 LL(1) parser. The complexity can be higher if the parser callback function
4436 @a cb has a super-linear complexity.
4437
4438 @liveexample{The example below demonstrates the parse function with and
4439 without callback function.,parse__string__parser_callback_t}
4440
4441 @sa parse(std::istream&, parser_callback_t) for a version that reads from
4442 an input stream
4443 */
4444 static basic_json parse(const string_t& s, parser_callback_t cb = nullptr)
4445 {
4446 return parser(s, cb).parse();
4447 }
4448
4449 /*!
4450 @brief deserialize from stream
4451
4452 @param[in,out] i stream to read a serialized JSON value from
4453 @param[in] cb a parser callback function of type @ref parser_callback_t
4454 which is used to control the deserialization by filtering unwanted values
4455 (optional)
4456
4457 @return result of the deserialization
4458
4459 @complexity Linear in the length of the input. The parser is a predictive
4460 LL(1) parser. The complexity can be higher if the parser callback function
4461 @a cb has a super-linear complexity.
4462
4463 @liveexample{The example below demonstrates the parse function with and
4464 without callback function.,parse__istream__parser_callback_t}
4465
4466 @sa parse(const string_t&, parser_callback_t) for a version that reads
4467 from a string
4468 */
4469 static basic_json parse(std::istream& i, parser_callback_t cb = nullptr)
4470 {
4471 return parser(i, cb).parse();
4472 }
4473
4474 /*!
4475 @brief deserialize from stream
4476
4477 Deserializes an input stream to a JSON value.
4478
4479 @param[in,out] i input stream to read a serialized JSON value from
4480 @param[in,out] j JSON value to write the deserialized input to
4481
4482 @throw std::invalid_argument in case of parse errors
4483
4484 @complexity Linear in the length of the input. The parser is a predictive
4485 LL(1) parser.
4486
4487 @liveexample{The example below shows how a JSON value is constructed by
4488 reading a serialization from a stream.,operator_deserialize}
4489
4490 @sa parse(std::istream&, parser_callback_t) for a variant with a parser
4491 callback function to filter values while parsing
4492 */
4493 friend std::istream& operator<<(basic_json& j, std::istream& i)
4494 {
4495 j = parser(i).parse();
4496 return i;
4497 }
4498
4499 /*!
4500 @brief deserialize from stream
4501 @copydoc operator<<(basic_json&, std::istream&)
4502 */
4503 friend std::istream& operator>>(std::istream& i, basic_json& j)
4504 {
4505 j = parser(i).parse();
4506 return i;
4507 }
4508
4509 /// @}
4510
4511
4512 private:
4513 ///////////////////////////
4514 // convenience functions //
4515 ///////////////////////////
4516
4517 /// return the type as string
4518 string_t type_name() const
4519 {
4520 switch (m_type)
4521 {
4522 case (value_t::null):
4523 {
4524 return "null";
4525 }
4526
4527 case (value_t::object):
4528 {
4529 return "object";
4530 }
4531
4532 case (value_t::array):
4533 {
4534 return "array";
4535 }
4536
4537 case (value_t::string):
4538 {
4539 return "string";
4540 }
4541
4542 case (value_t::boolean):
4543 {
4544 return "boolean";
4545 }
4546
4547 case (value_t::discarded):
4548 {
4549 return "discarded";
4550 }
4551
4552 default:
4553 {
4554 return "number";
4555 }
4556 }
4557 }
4558
4559 /*!
4560 @brief calculates the extra space to escape a JSON string
4561
4562 @param[in] s the string to escape
4563 @return the number of characters required to escape string @a s
4564
4565 @complexity Linear in the length of string @a s.
4566 */
4567 static std::size_t extra_space(const string_t& s) noexcept
4568 {
4569 std::size_t result = 0;
4570
4571 for (const auto& c : s)
4572 {
4573 switch (c)
4574 {
4575 case '"':
4576 case '\\':
4577 case '\b':
4578 case '\f':
4579 case '\n':
4580 case '\r':
4581 case '\t':
4582 {
4583 // from c (1 byte) to \x (2 bytes)
4584 result += 1;
4585 break;
4586 }
4587
4588 default:
4589 {
4590 if (c >= 0x00 and c <= 0x1f)
4591 {
4592 // from c (1 byte) to \uxxxx (6 bytes)
4593 result += 5;
4594 }
4595 break;
4596 }
4597 }
4598 }
4599
4600 return result;
4601 }
4602
4603 /*!
4604 @brief escape a string
4605
4606 Escape a string by replacing certain special characters by a sequence of an
4607 escape character (backslash) and another character and other control
4608 characters by a sequence of "\u" followed by a four-digit hex
4609 representation.
4610
4611 @param[in] s the string to escape
4612 @return the escaped string
4613
4614 @complexity Linear in the length of string @a s.
4615 */
4616 static string_t escape_string(const string_t& s) noexcept
4617 {
4618 const auto space = extra_space(s);
4619 if (space == 0)
4620 {
4621 return s;
4622 }
4623
4624 // create a result string of necessary size
4625 string_t result(s.size() + space, '\\');
4626 std::size_t pos = 0;
4627
4628 for (const auto& c : s)
4629 {
4630 switch (c)
4631 {
4632 // quotation mark (0x22)
4633 case '"':
4634 {
4635 result[pos + 1] = '"';
4636 pos += 2;
4637 break;
4638 }
4639
4640 // reverse solidus (0x5c)
4641 case '\\':
4642 {
4643 // nothing to change
4644 pos += 2;
4645 break;
4646 }
4647
4648 // backspace (0x08)
4649 case '\b':
4650 {
4651 result[pos + 1] = 'b';
4652 pos += 2;
4653 break;
4654 }
4655
4656 // formfeed (0x0c)
4657 case '\f':
4658 {
4659 result[pos + 1] = 'f';
4660 pos += 2;
4661 break;
4662 }
4663
4664 // newline (0x0a)
4665 case '\n':
4666 {
4667 result[pos + 1] = 'n';
4668 pos += 2;
4669 break;
4670 }
4671
4672 // carriage return (0x0d)
4673 case '\r':
4674 {
4675 result[pos + 1] = 'r';
4676 pos += 2;
4677 break;
4678 }
4679
4680 // horizontal tab (0x09)
4681 case '\t':
4682 {
4683 result[pos + 1] = 't';
4684 pos += 2;
4685 break;
4686 }
4687
4688 default:
4689 {
4690 if (c >= 0x00 and c <= 0x1f)
4691 {
4692 // print character c as \uxxxx
4693 sprintf(&result[pos + 1], "u%04x", int(c));
4694 pos += 6;
4695 // overwrite trailing null character
4696 result[pos] = '\\';
4697 }
4698 else
4699 {
4700 // all other characters are added as-is
4701 result[pos++] = c;
4702 }
4703 break;
4704 }
4705 }
4706 }
4707
4708 return result;
4709 }
4710
4711 /*!
4712 @brief internal implementation of the serialization function
4713
4714 This function is called by the public member function dump and organizes
4715 the serializaion internally. The indentation level is propagated as
4716 additional parameter. In case of arrays and objects, the function is called
4717 recursively. Note that
4718
4719 - strings and object keys are escaped using escape_string()
4720 - integer numbers are converted implictly via operator<<
4721 - floating-point numbers are converted to a string using "%g" format
4722
4723 @param[out] o stream to write to
4724 @param[in] pretty_print whether the output shall be pretty-printed
4725 @param[in] indent_step the indent level
4726 @param[in] current_indent the current indent level (only used internally)
4727 */
4728 void dump(std::ostream& o, const bool pretty_print, const unsigned int indent_step,
4729 const unsigned int current_indent = 0) const
4730 {
4731 // variable to hold indentation for recursive calls
4732 unsigned int new_indent = current_indent;
4733
4734 switch (m_type)
4735 {
4736 case (value_t::object):
4737 {
4738 if (m_value.object->empty())
4739 {
4740 o << "{}";
4741 return;
4742 }
4743
4744 o << "{";
4745
4746 // increase indentation
4747 if (pretty_print)
4748 {
4749 new_indent += indent_step;
4750 o << "\n";
4751 }
4752
4753 for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
4754 {
4755 if (i != m_value.object->cbegin())
4756 {
4757 o << (pretty_print ? ",\n" : ",");
4758 }
4759 o << string_t(new_indent, ' ') << "\""
4760 << escape_string(i->first) << "\":"
4761 << (pretty_print ? " " : "");
4762 i->second.dump(o, pretty_print, indent_step, new_indent);
4763 }
4764
4765 // decrease indentation
4766 if (pretty_print)
4767 {
4768 new_indent -= indent_step;
4769 o << "\n";
4770 }
4771
4772 o << string_t(new_indent, ' ') + "}";
4773 return;
4774 }
4775
4776 case (value_t::array):
4777 {
4778 if (m_value.array->empty())
4779 {
4780 o << "[]";
4781 return;
4782 }
4783
4784 o << "[";
4785
4786 // increase indentation
4787 if (pretty_print)
4788 {
4789 new_indent += indent_step;
4790 o << "\n";
4791 }
4792
4793 for (auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
4794 {
4795 if (i != m_value.array->cbegin())
4796 {
4797 o << (pretty_print ? ",\n" : ",");
4798 }
4799 o << string_t(new_indent, ' ');
4800 i->dump(o, pretty_print, indent_step, new_indent);
4801 }
4802
4803 // decrease indentation
4804 if (pretty_print)
4805 {
4806 new_indent -= indent_step;
4807 o << "\n";
4808 }
4809
4810 o << string_t(new_indent, ' ') << "]";
4811 return;
4812 }
4813
4814 case (value_t::string):
4815 {
4816 o << string_t("\"") << escape_string(*m_value.string) << "\"";
4817 return;
4818 }
4819
4820 case (value_t::boolean):
4821 {
4822 o << (m_value.boolean ? "true" : "false");
4823 return;
4824 }
4825
4826 case (value_t::number_integer):
4827 {
4828 o << m_value.number_integer;
4829 return;
4830 }
4831
4832 case (value_t::number_float):
4833 {
4834 // 15 digits of precision allows round-trip IEEE 754
4835 // string->double->string; to be safe, we read this value from
4836 // std::numeric_limits<number_float_t>::digits10
4837 o << std::setprecision(std::numeric_limits<number_float_t>::digits10) << m_value.number_float;
4838 return;
4839 }
4840
4841 case (value_t::discarded):
4842 {
4843 o << "<discarded>";
4844 return;
4845 }
4846
4847 default:
4848 {
4849 o << "null";
4850 return;
4851 }
4852 }
4853 }
4854
4855 private:
4856 //////////////////////
4857 // member variables //
4858 //////////////////////
4859
4860 /// the type of the current element
4861 value_t m_type = value_t::null;
4862
4863 /// the value of the current element
4864 json_value m_value = {};
4865
4866
4867 private:
4868 ///////////////
4869 // iterators //
4870 ///////////////
4871
4872 /*!
4873 @brief an iterator for primitive JSON types
4874
4875 This class models an iterator for primitive JSON types (boolean, number,
4876 string). It's only purpose is to allow the iterator/const_iterator classes
4877 to "iterate" over primitive values. Internally, the iterator is modeled by
4878 a `difference_type` variable. Value begin_value (`0`) models the begin,
4879 end_value (`1`) models past the end.
4880 */
4881 class primitive_iterator_t
4882 {
4883 public:
4884 /// set iterator to a defined beginning
4885 void set_begin()
4886 {
4887 m_it = begin_value;
4888 }
4889
4890 /// set iterator to a defined past the end
4891 void set_end()
4892 {
4893 m_it = end_value;
4894 }
4895
4896 /// return whether the iterator can be dereferenced
4897 bool is_begin() const
4898 {
4899 return (m_it == begin_value);
4900 }
4901
4902 /// return whether the iterator is at end
4903 bool is_end() const
4904 {
4905 return (m_it == end_value);
4906 }
4907
4908 /// return reference to the value to change and compare
4909 operator difference_type& ()
4910 {
4911 return m_it;
4912 }
4913
4914 /// return value to compare
4915 operator difference_type () const
4916 {
4917 return m_it;
4918 }
4919
4920 private:
4921 static constexpr difference_type begin_value = 0;
4922 static constexpr difference_type end_value = begin_value + 1;
4923
4924 /// iterator as signed integer type
4925 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::min();
4926 };
4927
4928 /*!
4929 @brief an iterator value
4930
4931 @note This structure could easily be a union, but MSVC currently does not
4932 allow unions members with complex constructors, see
4933 https://github.com/nlohmann/json/pull/105.
4934 */
4935 struct internal_iterator
4936 {
4937 /// iterator for JSON objects
4938 typename object_t::iterator object_iterator;
4939 /// iterator for JSON arrays
4940 typename array_t::iterator array_iterator;
4941 /// generic iterator for all other types
4942 primitive_iterator_t primitive_iterator;
4943
4944 /// create an uninitialized internal_iterator
4945 internal_iterator()
4946 : object_iterator(), array_iterator(), primitive_iterator()
4947 {}
4948 };
4949
4950 public:
4951 /*!
4952 @brief a const random access iterator for the @ref basic_json class
4953
4954 This class implements a const iterator for the @ref basic_json class. From
4955 this class, the @ref iterator class is derived.
4956
4957 @requirement The class satisfies the following concept requirements:
4958 - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
4959 The iterator that can be moved to point (forward and backward) to any
4960 element in constant time.
4961 */
4962 class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
4963 {
4964 /// allow basic_json to access private members
4965 friend class basic_json;
4966
4967 public:
4968 /// the type of the values when the iterator is dereferenced
4969 using value_type = typename basic_json::value_type;
4970 /// a type to represent differences between iterators
4971 using difference_type = typename basic_json::difference_type;
4972 /// defines a pointer to the type iterated over (value_type)
4973 using pointer = typename basic_json::const_pointer;
4974 /// defines a reference to the type iterated over (value_type)
4975 using reference = typename basic_json::const_reference;
4976 /// the category of the iterator
4977 using iterator_category = std::bidirectional_iterator_tag;
4978
4979 /// default constructor
4980 const_iterator() = default;
4981
4982 /// constructor for a given JSON instance
4983 const_iterator(pointer object) : m_object(object)
4984 {
4985 switch (m_object->m_type)
4986 {
4987 case (basic_json::value_t::object):
4988 {
4989 m_it.object_iterator = typename object_t::iterator();
4990 break;
4991 }
4992 case (basic_json::value_t::array):
4993 {
4994 m_it.array_iterator = typename array_t::iterator();
4995 break;
4996 }
4997 default:
4998 {
4999 m_it.primitive_iterator = primitive_iterator_t();
5000 break;
5001 }
5002 }
5003 }
5004
5005 /// copy constructor given a nonconst iterator
5006 const_iterator(const iterator& other) : m_object(other.m_object)
5007 {
5008 switch (m_object->m_type)
5009 {
5010 case (basic_json::value_t::object):
5011 {
5012 m_it.object_iterator = other.m_it.object_iterator;
5013 break;
5014 }
5015
5016 case (basic_json::value_t::array):
5017 {
5018 m_it.array_iterator = other.m_it.array_iterator;
5019 break;
5020 }
5021
5022 default:
5023 {
5024 m_it.primitive_iterator = other.m_it.primitive_iterator;
5025 break;
5026 }
5027 }
5028 }
5029
5030 /// copy constructor
5031 const_iterator(const const_iterator& other) noexcept
5032 : m_object(other.m_object), m_it(other.m_it)
5033 {}
5034
5035 /// copy assignment
5036 const_iterator& operator=(const_iterator other) noexcept(
5037 std::is_nothrow_move_constructible<pointer>::value and
5038 std::is_nothrow_move_assignable<pointer>::value and
5039 std::is_nothrow_move_constructible<internal_iterator>::value and
5040 std::is_nothrow_move_assignable<internal_iterator>::value
5041 )
5042 {
5043 std::swap(m_object, other.m_object);
5044 std::swap(m_it, other.m_it);
5045 return *this;
5046 }
5047
5048 private:
5049 /// set the iterator to the first value
5050 void set_begin()
5051 {
5052 switch (m_object->m_type)
5053 {
5054 case (basic_json::value_t::object):
5055 {
5056 m_it.object_iterator = m_object->m_value.object->begin();
5057 break;
5058 }
5059
5060 case (basic_json::value_t::array):
5061 {
5062 m_it.array_iterator = m_object->m_value.array->begin();
5063 break;
5064 }
5065
5066 case (basic_json::value_t::null):
5067 {
5068 // set to end so begin()==end() is true: null is empty
5069 m_it.primitive_iterator.set_end();
5070 break;
5071 }
5072
5073 default:
5074 {
5075 m_it.primitive_iterator.set_begin();
5076 break;
5077 }
5078 }
5079 }
5080
5081 /// set the iterator past the last value
5082 void set_end()
5083 {
5084 switch (m_object->m_type)
5085 {
5086 case (basic_json::value_t::object):
5087 {
5088 m_it.object_iterator = m_object->m_value.object->end();
5089 break;
5090 }
5091
5092 case (basic_json::value_t::array):
5093 {
5094 m_it.array_iterator = m_object->m_value.array->end();
5095 break;
5096 }
5097
5098 default:
5099 {
5100 m_it.primitive_iterator.set_end();
5101 break;
5102 }
5103 }
5104 }
5105
5106 public:
5107 /// return a reference to the value pointed to by the iterator
5108 reference operator*() const
5109 {
5110 switch (m_object->m_type)
5111 {
5112 case (basic_json::value_t::object):
5113 {
5114 return m_it.object_iterator->second;
5115 }
5116
5117 case (basic_json::value_t::array):
5118 {
5119 return *m_it.array_iterator;
5120 }
5121
5122 case (basic_json::value_t::null):
5123 {
5124 throw std::out_of_range("cannot get value");
5125 }
5126
5127 default:
5128 {
5129 if (m_it.primitive_iterator.is_begin())
5130 {
5131 return *m_object;
5132 }
5133 else
5134 {
5135 throw std::out_of_range("cannot get value");
5136 }
5137 }
5138 }
5139 }
5140
5141 /// dereference the iterator
5142 pointer operator->() const
5143 {
5144 switch (m_object->m_type)
5145 {
5146 case (basic_json::value_t::object):
5147 {
5148 return &(m_it.object_iterator->second);
5149 }
5150
5151 case (basic_json::value_t::array):
5152 {
5153 return &*m_it.array_iterator;
5154 }
5155
5156 default:
5157 {
5158 if (m_it.primitive_iterator.is_begin())
5159 {
5160 return m_object;
5161 }
5162 else
5163 {
5164 throw std::out_of_range("cannot get value");
5165 }
5166 }
5167 }
5168 }
5169
5170 /// post-increment (it++)
5171 const_iterator operator++(int)
5172 {
5173 auto result = *this;
5174 ++(*this);
5175
5176 return result;
5177 }
5178
5179 /// pre-increment (++it)
5180 const_iterator& operator++()
5181 {
5182 switch (m_object->m_type)
5183 {
5184 case (basic_json::value_t::object):
5185 {
5186 ++m_it.object_iterator;
5187 break;
5188 }
5189
5190 case (basic_json::value_t::array):
5191 {
5192 ++m_it.array_iterator;
5193 break;
5194 }
5195
5196 default:
5197 {
5198 ++m_it.primitive_iterator;
5199 break;
5200 }
5201 }
5202
5203 return *this;
5204 }
5205
5206 /// post-decrement (it--)
5207 const_iterator operator--(int)
5208 {
5209 auto result = *this;
5210 --(*this);
5211
5212 return result;
5213 }
5214
5215 /// pre-decrement (--it)
5216 const_iterator& operator--()
5217 {
5218 switch (m_object->m_type)
5219 {
5220 case (basic_json::value_t::object):
5221 {
5222 --m_it.object_iterator;
5223 break;
5224 }
5225
5226 case (basic_json::value_t::array):
5227 {
5228 --m_it.array_iterator;
5229 break;
5230 }
5231
5232 default:
5233 {
5234 --m_it.primitive_iterator;
5235 break;
5236 }
5237 }
5238
5239 return *this;
5240 }
5241
5242 /// comparison: equal
5243 bool operator==(const const_iterator& other) const
5244 {
5245 // if objects are not the same, the comparison is undefined
5246 if (m_object != other.m_object)
5247 {
5248 throw std::domain_error("cannot compare iterators of different containers");
5249 }
5250
5251 switch (m_object->m_type)
5252 {
5253 case (basic_json::value_t::object):
5254 {
5255 return (m_it.object_iterator == other.m_it.object_iterator);
5256 }
5257
5258 case (basic_json::value_t::array):
5259 {
5260 return (m_it.array_iterator == other.m_it.array_iterator);
5261 }
5262
5263 default:
5264 {
5265 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5266 }
5267 }
5268 }
5269
5270 /// comparison: not equal
5271 bool operator!=(const const_iterator& other) const
5272 {
5273 return not operator==(other);
5274 }
5275
5276 /// comparison: smaller
5277 bool operator<(const const_iterator& other) const
5278 {
5279 // if objects are not the same, the comparison is undefined
5280 if (m_object != other.m_object)
5281 {
5282 throw std::domain_error("cannot compare iterators of different containers");
5283 }
5284
5285 switch (m_object->m_type)
5286 {
5287 case (basic_json::value_t::object):
5288 {
5289 throw std::domain_error("cannot use operator< for object iterators");
5290 }
5291
5292 case (basic_json::value_t::array):
5293 {
5294 return (m_it.array_iterator < other.m_it.array_iterator);
5295 }
5296
5297 default:
5298 {
5299 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5300 }
5301 }
5302 }
5303
5304 /// comparison: less than or equal
5305 bool operator<=(const const_iterator& other) const
5306 {
5307 return not other.operator < (*this);
5308 }
5309
5310 /// comparison: greater than
5311 bool operator>(const const_iterator& other) const
5312 {
5313 return not operator<=(other);
5314 }
5315
5316 /// comparison: greater than or equal
5317 bool operator>=(const const_iterator& other) const
5318 {
5319 return not operator<(other);
5320 }
5321
5322 /// add to iterator
5323 const_iterator& operator+=(difference_type i)
5324 {
5325 switch (m_object->m_type)
5326 {
5327 case (basic_json::value_t::object):
5328 {
5329 throw std::domain_error("cannot use operator+= for object iterators");
5330 }
5331
5332 case (basic_json::value_t::array):
5333 {
5334 m_it.array_iterator += i;
5335 break;
5336 }
5337
5338 default:
5339 {
5340 m_it.primitive_iterator += i;
5341 break;
5342 }
5343 }
5344
5345 return *this;
5346 }
5347
5348 /// subtract from iterator
5349 const_iterator& operator-=(difference_type i)
5350 {
5351 return operator+=(-i);
5352 }
5353
5354 /// add to iterator
5355 const_iterator operator+(difference_type i)
5356 {
5357 auto result = *this;
5358 result += i;
5359 return result;
5360 }
5361
5362 /// subtract from iterator
5363 const_iterator operator-(difference_type i)
5364 {
5365 auto result = *this;
5366 result -= i;
5367 return result;
5368 }
5369
5370 /// return difference
5371 difference_type operator-(const const_iterator& other) const
5372 {
5373 switch (m_object->m_type)
5374 {
5375 case (basic_json::value_t::object):
5376 {
5377 throw std::domain_error("cannot use operator- for object iterators");
5378 }
5379
5380 case (basic_json::value_t::array):
5381 {
5382 return m_it.array_iterator - other.m_it.array_iterator;
5383 }
5384
5385 default:
5386 {
5387 return m_it.primitive_iterator - other.m_it.primitive_iterator;
5388 }
5389 }
5390 }
5391
5392 /// access to successor
5393 reference operator[](difference_type n) const
5394 {
5395 switch (m_object->m_type)
5396 {
5397 case (basic_json::value_t::object):
5398 {
5399 throw std::domain_error("cannot use operator[] for object iterators");
5400 }
5401
5402 case (basic_json::value_t::array):
5403 {
5404 return *(m_it.array_iterator + n);
5405 }
5406
5407 case (basic_json::value_t::null):
5408 {
5409 throw std::out_of_range("cannot get value");
5410 }
5411
5412 default:
5413 {
5414 if (m_it.primitive_iterator == -n)
5415 {
5416 return *m_object;
5417 }
5418 else
5419 {
5420 throw std::out_of_range("cannot get value");
5421 }
5422 }
5423 }
5424 }
5425
5426 /// return the key of an object iterator
5427 typename object_t::key_type key() const
5428 {
5429 switch (m_object->m_type)
5430 {
5431 case (basic_json::value_t::object):
5432 {
5433 return m_it.object_iterator->first;
5434 }
5435
5436 default:
5437 {
5438 throw std::domain_error("cannot use key() for non-object iterators");
5439 }
5440 }
5441 }
5442
5443 /// return the value of an iterator
5444 reference value() const
5445 {
5446 return operator*();
5447 }
5448
5449 private:
5450 /// associated JSON instance
5451 pointer m_object = nullptr;
5452 /// the actual iterator of the associated instance
5453 internal_iterator m_it = internal_iterator();
5454 };
5455
5456 /*!
5457 @brief a mutable random access iterator for the @ref basic_json class
5458
5459 @requirement The class satisfies the following concept requirements:
5460 - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
5461 The iterator that can be moved to point (forward and backward) to any
5462 element in constant time.
5463 - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
5464 It is possible to write to the pointed-to element.
5465 */
5466 class iterator : public const_iterator
5467 {
5468 public:
5469 using base_iterator = const_iterator;
5470 using pointer = typename basic_json::pointer;
5471 using reference = typename basic_json::reference;
5472
5473 /// default constructor
5474 iterator() = default;
5475
5476 /// constructor for a given JSON instance
5477 iterator(pointer object) noexcept : base_iterator(object)
5478 {}
5479
5480 /// copy constructor
5481 iterator(const iterator& other) noexcept
5482 : base_iterator(other)
5483 {}
5484
5485 /// copy assignment
5486 iterator& operator=(iterator other) noexcept(
5487 std::is_nothrow_move_constructible<pointer>::value and
5488 std::is_nothrow_move_assignable<pointer>::value and
5489 std::is_nothrow_move_constructible<internal_iterator>::value and
5490 std::is_nothrow_move_assignable<internal_iterator>::value
5491 )
5492 {
5493 base_iterator::operator=(other);
5494 return *this;
5495 }
5496
5497 /// return a reference to the value pointed to by the iterator
5498 reference operator*()
5499 {
5500 return const_cast<reference>(base_iterator::operator*());
5501 }
5502
5503 /// dereference the iterator
5504 pointer operator->()
5505 {
5506 return const_cast<pointer>(base_iterator::operator->());
5507 }
5508
5509 /// post-increment (it++)
5510 iterator operator++(int)
5511 {
5512 iterator result = *this;
5513 base_iterator::operator++();
5514 return result;
5515 }
5516
5517 /// pre-increment (++it)
5518 iterator& operator++()
5519 {
5520 base_iterator::operator++();
5521 return *this;
5522 }
5523
5524 /// post-decrement (it--)
5525 iterator operator--(int)
5526 {
5527 iterator result = *this;
5528 base_iterator::operator--();
5529 return result;
5530 }
5531
5532 /// pre-decrement (--it)
5533 iterator& operator--()
5534 {
5535 base_iterator::operator--();
5536 return *this;
5537 }
5538
5539 /// add to iterator
5540 iterator& operator+=(difference_type i)
5541 {
5542 base_iterator::operator+=(i);
5543 return *this;
5544 }
5545
5546 /// subtract from iterator
5547 iterator& operator-=(difference_type i)
5548 {
5549 base_iterator::operator-=(i);
5550 return *this;
5551 }
5552
5553 /// add to iterator
5554 iterator operator+(difference_type i)
5555 {
5556 auto result = *this;
5557 result += i;
5558 return result;
5559 }
5560
5561 /// subtract from iterator
5562 iterator operator-(difference_type i)
5563 {
5564 auto result = *this;
5565 result -= i;
5566 return result;
5567 }
5568
5569 difference_type operator-(const iterator& other) const
5570 {
5571 return base_iterator::operator-(other);
5572 }
5573
5574 /// access to successor
5575 reference operator[](difference_type n) const
5576 {
5577 return const_cast<reference>(base_iterator::operator[](n));
5578 }
5579
5580 /// return the value of an iterator
5581 reference value() const
5582 {
5583 return const_cast<reference>(base_iterator::value());
5584 }
5585 };
5586
5587 /*!
5588 @brief a template for a reverse iterator class
5589
5590 @tparam Base the base iterator type to reverse. Valid types are @ref
5591 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
5592 create @ref const_reverse_iterator).
5593
5594 @requirement The class satisfies the following concept requirements:
5595 - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
5596 The iterator that can be moved to point (forward and backward) to any
5597 element in constant time.
5598 - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
5599 It is possible to write to the pointed-to element (only if @a Base is
5600 @ref iterator).
5601 */
5602 template<typename Base>
5603 class json_reverse_iterator : public std::reverse_iterator<Base>
5604 {
5605 public:
5606 /// shortcut to the reverse iterator adaptor
5607 using base_iterator = std::reverse_iterator<Base>;
5608 /// the reference type for the pointed-to element
5609 using reference = typename Base::reference;
5610
5611 /// create reverse iterator from iterator
5612 json_reverse_iterator(const typename base_iterator::iterator_type& it)
5613 : base_iterator(it) {}
5614
5615 /// create reverse iterator from base class
5616 json_reverse_iterator(const base_iterator& it) : base_iterator(it) {}
5617
5618 /// post-increment (it++)
5619 json_reverse_iterator operator++(int)
5620 {
5621 return base_iterator::operator++(1);
5622 }
5623
5624 /// pre-increment (++it)
5625 json_reverse_iterator& operator++()
5626 {
5627 base_iterator::operator++();
5628 return *this;
5629 }
5630
5631 /// post-decrement (it--)
5632 json_reverse_iterator operator--(int)
5633 {
5634 return base_iterator::operator--(1);
5635 }
5636
5637 /// pre-decrement (--it)
5638 json_reverse_iterator& operator--()
5639 {
5640 base_iterator::operator--();
5641 return *this;
5642 }
5643
5644 /// add to iterator
5645 json_reverse_iterator& operator+=(difference_type i)
5646 {
5647 base_iterator::operator+=(i);
5648 return *this;
5649 }
5650
5651 /// add to iterator
5652 json_reverse_iterator operator+(difference_type i) const
5653 {
5654 auto result = *this;
5655 result += i;
5656 return result;
5657 }
5658
5659 /// subtract from iterator
5660 json_reverse_iterator operator-(difference_type i) const
5661 {
5662 auto result = *this;
5663 result -= i;
5664 return result;
5665 }
5666
5667 /// return difference
5668 difference_type operator-(const json_reverse_iterator& other) const
5669 {
5670 return this->base() - other.base();
5671 }
5672
5673 /// access to successor
5674 reference operator[](difference_type n) const
5675 {
5676 return *(this->operator+(n));
5677 }
5678
5679 /// return the key of an object iterator
5680 typename object_t::key_type key() const
5681 {
5682 auto it = --this->base();
5683 return it.key();
5684 }
5685
5686 /// return the value of an iterator
5687 reference value() const
5688 {
5689 auto it = --this->base();
5690 return it.operator * ();
5691 }
5692 };
5693
5694 /*!
5695 @brief wrapper to access iterator member functions in range-based for
5696
5697 This class allows to access @ref key() and @ref value() during range-based
5698 for loops. In these loops, a reference to the JSON values is returned, so
5699 there is no access to the underlying iterator.
5700 */
5701 class iterator_wrapper
5702 {
5703 private:
5704 /// the container to iterate
5705 basic_json& container;
5706 /// the type of the iterator to use while iteration
5707 using json_iterator = decltype(std::begin(container));
5708
5709 /// internal iterator wrapper
5710 class iterator_wrapper_internal
5711 {
5712 private:
5713 /// the iterator
5714 json_iterator anchor;
5715 /// an index for arrays
5716 size_t array_index = 0;
5717
5718 public:
5719 /// construct wrapper given an iterator
5720 iterator_wrapper_internal(json_iterator i) : anchor(i)
5721 {}
5722
5723 /// dereference operator (needed for range-based for)
5724 iterator_wrapper_internal& operator*()
5725 {
5726 return *this;
5727 }
5728
5729 /// increment operator (needed for range-based for)
5730 iterator_wrapper_internal& operator++()
5731 {
5732 ++anchor;
5733 ++array_index;
5734
5735 return *this;
5736 }
5737
5738 /// inequality operator (needed for range-based for)
5739 bool operator!= (const iterator_wrapper_internal& o)
5740 {
5741 return anchor != o.anchor;
5742 }
5743
5744 /// stream operator
5745 friend std::ostream& operator<<(std::ostream& o, const iterator_wrapper_internal& w)
5746 {
5747 return o << w.value();
5748 }
5749
5750 /// return key of the iterator
5751 typename basic_json::string_t key() const
5752 {
5753 switch (anchor.m_object->type())
5754 {
5755 /// use integer array index as key
5756 case (value_t::array):
5757 {
5758 return std::to_string(array_index);
5759 }
5760
5761 /// use key from the object
5762 case (value_t::object):
5763 {
5764 return anchor.key();
5765 }
5766
5767 /// use an empty key for all primitive types
5768 default:
5769 {
5770 return "";
5771 }
5772 }
5773 }
5774
5775 /// return value of the iterator
5776 typename json_iterator::reference value() const
5777 {
5778 return anchor.value();
5779 }
5780 };
5781
5782 public:
5783 /// construct iterator wrapper from a container
5784 iterator_wrapper(basic_json& cont)
5785 : container(cont)
5786 {}
5787
5788 /// return iterator begin (needed for range-based for)
5789 iterator_wrapper_internal begin()
5790 {
5791 return iterator_wrapper_internal(container.begin());
5792 }
5793
5794 /// return iterator end (needed for range-based for)
5795 iterator_wrapper_internal end()
5796 {
5797 return iterator_wrapper_internal(container.end());
5798 }
5799 };
5800
5801 private:
5802 //////////////////////
5803 // lexer and parser //
5804 //////////////////////
5805
5806 /*!
5807 @brief lexical analysis
5808
5809 This class organizes the lexical analysis during JSON deserialization. The
5810 core of it is a scanner generated by re2c <http://re2c.org> that processes
5811 a buffer and recognizes tokens according to RFC 7159.
5812 */
5813 class lexer
5814 {
5815 public:
5816 /// token types for the parser
5817 enum class token_type
5818 {
5819 uninitialized, ///< indicating the scanner is uninitialized
5820 literal_true, ///< the "true" literal
5821 literal_false, ///< the "false" literal
5822 literal_null, ///< the "null" literal
5823 value_string, ///< a string - use get_string() for actual value
5824 value_number, ///< a number - use get_number() for actual value
5825 begin_array, ///< the character for array begin "["
5826 begin_object, ///< the character for object begin "{"
5827 end_array, ///< the character for array end "]"
5828 end_object, ///< the character for object end "}"
5829 name_separator, ///< the name separator ":"
5830 value_separator, ///< the value separator ","
5831 parse_error, ///< indicating a parse error
5832 end_of_input ///< indicating the end of the input buffer
5833 };
5834
5835 /// the char type to use in the lexer
5836 using lexer_char_t = unsigned char;
5837
5838 /// constructor with a given buffer
5839 explicit lexer(const string_t& s) noexcept
5840 : m_stream(nullptr), m_buffer(s)
5841 {
5842 m_content = reinterpret_cast<const lexer_char_t*>(s.c_str());
5843 m_start = m_cursor = m_content;
5844 m_limit = m_content + s.size();
5845 }
5846 explicit lexer(std::istream* s) noexcept
5847 : m_stream(s), m_buffer()
5848 {
5849 getline(*m_stream, m_buffer);
5850 m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
5851 m_start = m_cursor = m_content;
5852 m_limit = m_content + m_buffer.size();
5853 }
5854
5855 /// default constructor
5856 lexer() = default;
5857
5858 // switch of unwanted functions
5859 lexer(const lexer&) = delete;
5860 lexer operator=(const lexer&) = delete;
5861
5862 /*!
5863 @brief create a string from a Unicode code point
5864
5865 @param[in] codepoint1 the code point (can be high surrogate)
5866 @param[in] codepoint2 the code point (can be low surrogate or 0)
5867 @return string representation of the code point
5868 @throw std::out_of_range if code point is >0x10ffff
5869 @throw std::invalid_argument if the low surrogate is invalid
5870
5871 @see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
5872 */
5873 static string_t to_unicode(const std::size_t codepoint1,
5874 const std::size_t codepoint2 = 0)
5875 {
5876 string_t result;
5877
5878 // calculate the codepoint from the given code points
5879 std::size_t codepoint = codepoint1;
5880
5881 // check if codepoint1 is a high surrogate
5882 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
5883 {
5884 // check if codepoint2 is a low surrogate
5885 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
5886 {
5887 codepoint =
5888 // high surrogate occupies the most significant 22 bits
5889 (codepoint1 << 10)
5890 // low surrogate occupies the least significant 15 bits
5891 + codepoint2
5892 // there is still the 0xD800, 0xDC00 and 0x10000 noise
5893 // in the result so we have to substract with:
5894 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
5895 - 0x35FDC00;
5896 }
5897 else
5898 {
5899 throw std::invalid_argument("missing or wrong low surrogate");
5900 }
5901 }
5902
5903 if (codepoint < 0x80)
5904 {
5905 // 1-byte characters: 0xxxxxxx (ASCII)
5906 result.append(1, static_cast<typename string_t::value_type>(codepoint));
5907 }
5908 else if (codepoint <= 0x7ff)
5909 {
5910 // 2-byte characters: 110xxxxx 10xxxxxx
5911 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
5912 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
5913 }
5914 else if (codepoint <= 0xffff)
5915 {
5916 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
5917 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
5918 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
5919 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
5920 }
5921 else if (codepoint <= 0x10ffff)
5922 {
5923 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5924 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
5925 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
5926 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
5927 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
5928 }
5929 else
5930 {
5931 throw std::out_of_range("code points above 0x10FFFF are invalid");
5932 }
5933
5934 return result;
5935 }
5936
5937 /// return name of values of type token_type
5938 static std::string token_type_name(token_type t)
5939 {
5940 switch (t)
5941 {
5942 case (token_type::uninitialized):
5943 return "<uninitialized>";
5944 case (token_type::literal_true):
5945 return "true literal";
5946 case (token_type::literal_false):
5947 return "false literal";
5948 case (token_type::literal_null):
5949 return "null literal";
5950 case (token_type::value_string):
5951 return "string literal";
5952 case (token_type::value_number):
5953 return "number literal";
5954 case (token_type::begin_array):
5955 return "[";
5956 case (token_type::begin_object):
5957 return "{";
5958 case (token_type::end_array):
5959 return "]";
5960 case (token_type::end_object):
5961 return "}";
5962 case (token_type::name_separator):
5963 return ":";
5964 case (token_type::value_separator):
5965 return ",";
5966 case (token_type::end_of_input):
5967 return "<end of input>";
5968 default:
5969 return "<parse error>";
5970 }
5971 }
5972
5973 /*!
5974 This function implements a scanner for JSON. It is specified using
5975 regular expressions that try to follow RFC 7159 as close as possible.
5976 These regular expressions are then translated into a deterministic
5977 finite automaton (DFA) by the tool re2c <http://re2c.org>. As a result,
5978 the translated code for this function consists of a large block of code
5979 with goto jumps.
5980
5981 @return the class of the next token read from the buffer
5982 */
5983 token_type scan() noexcept
5984 {
5985 // pointer for backtracking information
5986 m_marker = nullptr;
5987
5988 // remember the begin of the token
5989 m_start = m_cursor;
5990
5991
5992 {
5993 lexer_char_t yych;
5994 unsigned int yyaccept = 0;
5995 static const unsigned char yybm[] =
5996 {
5997 0, 0, 0, 0, 0, 0, 0, 0,
5998 0, 32, 32, 0, 0, 32, 0, 0,
5999 64, 64, 64, 64, 64, 64, 64, 64,
6000 64, 64, 64, 64, 64, 64, 64, 64,
6001 96, 64, 0, 64, 64, 64, 64, 64,
6002 64, 64, 64, 64, 64, 64, 64, 64,
6003 192, 192, 192, 192, 192, 192, 192, 192,
6004 192, 192, 64, 64, 64, 64, 64, 64,
6005 64, 64, 64, 64, 64, 64, 64, 64,
6006 64, 64, 64, 64, 64, 64, 64, 64,
6007 64, 64, 64, 64, 64, 64, 64, 64,
6008 64, 64, 64, 64, 0, 64, 64, 64,
6009 64, 64, 64, 64, 64, 64, 64, 64,
6010 64, 64, 64, 64, 64, 64, 64, 64,
6011 64, 64, 64, 64, 64, 64, 64, 64,
6012 64, 64, 64, 64, 64, 64, 64, 64,
6013 64, 64, 64, 64, 64, 64, 64, 64,
6014 64, 64, 64, 64, 64, 64, 64, 64,
6015 64, 64, 64, 64, 64, 64, 64, 64,
6016 64, 64, 64, 64, 64, 64, 64, 64,
6017 64, 64, 64, 64, 64, 64, 64, 64,
6018 64, 64, 64, 64, 64, 64, 64, 64,
6019 64, 64, 64, 64, 64, 64, 64, 64,
6020 64, 64, 64, 64, 64, 64, 64, 64,
6021 64, 64, 64, 64, 64, 64, 64, 64,
6022 64, 64, 64, 64, 64, 64, 64, 64,
6023 64, 64, 64, 64, 64, 64, 64, 64,
6024 64, 64, 64, 64, 64, 64, 64, 64,
6025 64, 64, 64, 64, 64, 64, 64, 64,
6026 64, 64, 64, 64, 64, 64, 64, 64,
6027 64, 64, 64, 64, 64, 64, 64, 64,
6028 64, 64, 64, 64, 64, 64, 64, 64,
6029 };
6030
6031 if ((m_limit - m_cursor) < 5)
6032 {
6033 yyfill(); // LCOV_EXCL_LINE;
6034 }
6035 yych = *m_cursor;
6036 if (yych <= '9')
6037 {
6038 if (yych <= ' ')
6039 {
6040 if (yych <= '\n')
6041 {
6042 if (yych <= 0x00)
6043 {
6044 goto basic_json_parser_27;
6045 }
6046 if (yych <= 0x08)
6047 {
6048 goto basic_json_parser_29;
6049 }
6050 if (yych >= '\n')
6051 {
6052 goto basic_json_parser_4;
6053 }
6054 }
6055 else
6056 {
6057 if (yych == '\r')
6058 {
6059 goto basic_json_parser_2;
6060 }
6061 if (yych <= 0x1F)
6062 {
6063 goto basic_json_parser_29;
6064 }
6065 }
6066 }
6067 else
6068 {
6069 if (yych <= ',')
6070 {
6071 if (yych == '"')
6072 {
6073 goto basic_json_parser_26;
6074 }
6075 if (yych <= '+')
6076 {
6077 goto basic_json_parser_29;
6078 }
6079 goto basic_json_parser_14;
6080 }
6081 else
6082 {
6083 if (yych <= '-')
6084 {
6085 goto basic_json_parser_22;
6086 }
6087 if (yych <= '/')
6088 {
6089 goto basic_json_parser_29;
6090 }
6091 if (yych <= '0')
6092 {
6093 goto basic_json_parser_23;
6094 }
6095 goto basic_json_parser_25;
6096 }
6097 }
6098 }
6099 else
6100 {
6101 if (yych <= 'm')
6102 {
6103 if (yych <= '\\')
6104 {
6105 if (yych <= ':')
6106 {
6107 goto basic_json_parser_16;
6108 }
6109 if (yych == '[')
6110 {
6111 goto basic_json_parser_6;
6112 }
6113 goto basic_json_parser_29;
6114 }
6115 else
6116 {
6117 if (yych <= ']')
6118 {
6119 goto basic_json_parser_8;
6120 }
6121 if (yych == 'f')
6122 {
6123 goto basic_json_parser_21;
6124 }
6125 goto basic_json_parser_29;
6126 }
6127 }
6128 else
6129 {
6130 if (yych <= 'z')
6131 {
6132 if (yych <= 'n')
6133 {
6134 goto basic_json_parser_18;
6135 }
6136 if (yych == 't')
6137 {
6138 goto basic_json_parser_20;
6139 }
6140 goto basic_json_parser_29;
6141 }
6142 else
6143 {
6144 if (yych <= '{')
6145 {
6146 goto basic_json_parser_10;
6147 }
6148 if (yych == '}')
6149 {
6150 goto basic_json_parser_12;
6151 }
6152 goto basic_json_parser_29;
6153 }
6154 }
6155 }
6156basic_json_parser_2:
6157 ++m_cursor;
6158 yych = *m_cursor;
6159 goto basic_json_parser_5;
6160basic_json_parser_3:
6161 {
6162 return scan();
6163 }
6164basic_json_parser_4:
6165 ++m_cursor;
6166 if (m_limit <= m_cursor)
6167 {
6168 yyfill(); // LCOV_EXCL_LINE;
6169 }
6170 yych = *m_cursor;
6171basic_json_parser_5:
6172 if (yybm[0 + yych] & 32)
6173 {
6174 goto basic_json_parser_4;
6175 }
6176 goto basic_json_parser_3;
6177basic_json_parser_6:
6178 ++m_cursor;
6179 {
6180 return token_type::begin_array;
6181 }
6182basic_json_parser_8:
6183 ++m_cursor;
6184 {
6185 return token_type::end_array;
6186 }
6187basic_json_parser_10:
6188 ++m_cursor;
6189 {
6190 return token_type::begin_object;
6191 }
6192basic_json_parser_12:
6193 ++m_cursor;
6194 {
6195 return token_type::end_object;
6196 }
6197basic_json_parser_14:
6198 ++m_cursor;
6199 {
6200 return token_type::value_separator;
6201 }
6202basic_json_parser_16:
6203 ++m_cursor;
6204 {
6205 return token_type::name_separator;
6206 }
6207basic_json_parser_18:
6208 yyaccept = 0;
6209 yych = *(m_marker = ++m_cursor);
6210 if (yych == 'u')
6211 {
6212 goto basic_json_parser_59;
6213 }
6214basic_json_parser_19:
6215 {
6216 return token_type::parse_error;
6217 }
6218basic_json_parser_20:
6219 yyaccept = 0;
6220 yych = *(m_marker = ++m_cursor);
6221 if (yych == 'r')
6222 {
6223 goto basic_json_parser_55;
6224 }
6225 goto basic_json_parser_19;
6226basic_json_parser_21:
6227 yyaccept = 0;
6228 yych = *(m_marker = ++m_cursor);
6229 if (yych == 'a')
6230 {
6231 goto basic_json_parser_50;
6232 }
6233 goto basic_json_parser_19;
6234basic_json_parser_22:
6235 yych = *++m_cursor;
6236 if (yych <= '/')
6237 {
6238 goto basic_json_parser_19;
6239 }
6240 if (yych <= '0')
6241 {
6242 goto basic_json_parser_49;
6243 }
6244 if (yych <= '9')
6245 {
6246 goto basic_json_parser_40;
6247 }
6248 goto basic_json_parser_19;
6249basic_json_parser_23:
6250 yyaccept = 1;
6251 yych = *(m_marker = ++m_cursor);
6252 if (yych <= 'D')
6253 {
6254 if (yych == '.')
6255 {
6256 goto basic_json_parser_42;
6257 }
6258 }
6259 else
6260 {
6261 if (yych <= 'E')
6262 {
6263 goto basic_json_parser_43;
6264 }
6265 if (yych == 'e')
6266 {
6267 goto basic_json_parser_43;
6268 }
6269 }
6270basic_json_parser_24:
6271 {
6272 return token_type::value_number;
6273 }
6274basic_json_parser_25:
6275 yyaccept = 1;
6276 yych = *(m_marker = ++m_cursor);
6277 goto basic_json_parser_41;
6278basic_json_parser_26:
6279 yyaccept = 0;
6280 yych = *(m_marker = ++m_cursor);
6281 if (yych <= 0x0F)
6282 {
6283 goto basic_json_parser_19;
6284 }
6285 goto basic_json_parser_31;
6286basic_json_parser_27:
6287 ++m_cursor;
6288 {
6289 return token_type::end_of_input;
6290 }
6291basic_json_parser_29:
6292 yych = *++m_cursor;
6293 goto basic_json_parser_19;
6294basic_json_parser_30:
6295 ++m_cursor;
6296 if (m_limit <= m_cursor)
6297 {
6298 yyfill(); // LCOV_EXCL_LINE;
6299 }
6300 yych = *m_cursor;
6301basic_json_parser_31:
6302 if (yybm[0 + yych] & 64)
6303 {
6304 goto basic_json_parser_30;
6305 }
6306 if (yych <= 0x0F)
6307 {
6308 goto basic_json_parser_32;
6309 }
6310 if (yych <= '"')
6311 {
6312 goto basic_json_parser_34;
6313 }
6314 goto basic_json_parser_33;
6315basic_json_parser_32:
6316 m_cursor = m_marker;
6317 if (yyaccept == 0)
6318 {
6319 goto basic_json_parser_19;
6320 }
6321 else
6322 {
6323 goto basic_json_parser_24;
6324 }
6325basic_json_parser_33:
6326 ++m_cursor;
6327 if (m_limit <= m_cursor)
6328 {
6329 yyfill(); // LCOV_EXCL_LINE;
6330 }
6331 yych = *m_cursor;
6332 if (yych <= 'e')
6333 {
6334 if (yych <= '/')
6335 {
6336 if (yych == '"')
6337 {
6338 goto basic_json_parser_30;
6339 }
6340 if (yych <= '.')
6341 {
6342 goto basic_json_parser_32;
6343 }
6344 goto basic_json_parser_30;
6345 }
6346 else
6347 {
6348 if (yych <= '\\')
6349 {
6350 if (yych <= '[')
6351 {
6352 goto basic_json_parser_32;
6353 }
6354 goto basic_json_parser_30;
6355 }
6356 else
6357 {
6358 if (yych == 'b')
6359 {
6360 goto basic_json_parser_30;
6361 }
6362 goto basic_json_parser_32;
6363 }
6364 }
6365 }
6366 else
6367 {
6368 if (yych <= 'q')
6369 {
6370 if (yych <= 'f')
6371 {
6372 goto basic_json_parser_30;
6373 }
6374 if (yych == 'n')
6375 {
6376 goto basic_json_parser_30;
6377 }
6378 goto basic_json_parser_32;
6379 }
6380 else
6381 {
6382 if (yych <= 's')
6383 {
6384 if (yych <= 'r')
6385 {
6386 goto basic_json_parser_30;
6387 }
6388 goto basic_json_parser_32;
6389 }
6390 else
6391 {
6392 if (yych <= 't')
6393 {
6394 goto basic_json_parser_30;
6395 }
6396 if (yych <= 'u')
6397 {
6398 goto basic_json_parser_36;
6399 }
6400 goto basic_json_parser_32;
6401 }
6402 }
6403 }
6404basic_json_parser_34:
6405 ++m_cursor;
6406 {
6407 return token_type::value_string;
6408 }
6409basic_json_parser_36:
6410 ++m_cursor;
6411 if (m_limit <= m_cursor)
6412 {
6413 yyfill(); // LCOV_EXCL_LINE;
6414 }
6415 yych = *m_cursor;
6416 if (yych <= '@')
6417 {
6418 if (yych <= '/')
6419 {
6420 goto basic_json_parser_32;
6421 }
6422 if (yych >= ':')
6423 {
6424 goto basic_json_parser_32;
6425 }
6426 }
6427 else
6428 {
6429 if (yych <= 'F')
6430 {
6431 goto basic_json_parser_37;
6432 }
6433 if (yych <= '`')
6434 {
6435 goto basic_json_parser_32;
6436 }
6437 if (yych >= 'g')
6438 {
6439 goto basic_json_parser_32;
6440 }
6441 }
6442basic_json_parser_37:
6443 ++m_cursor;
6444 if (m_limit <= m_cursor)
6445 {
6446 yyfill(); // LCOV_EXCL_LINE;
6447 }
6448 yych = *m_cursor;
6449 if (yych <= '@')
6450 {
6451 if (yych <= '/')
6452 {
6453 goto basic_json_parser_32;
6454 }
6455 if (yych >= ':')
6456 {
6457 goto basic_json_parser_32;
6458 }
6459 }
6460 else
6461 {
6462 if (yych <= 'F')
6463 {
6464 goto basic_json_parser_38;
6465 }
6466 if (yych <= '`')
6467 {
6468 goto basic_json_parser_32;
6469 }
6470 if (yych >= 'g')
6471 {
6472 goto basic_json_parser_32;
6473 }
6474 }
6475basic_json_parser_38:
6476 ++m_cursor;
6477 if (m_limit <= m_cursor)
6478 {
6479 yyfill(); // LCOV_EXCL_LINE;
6480 }
6481 yych = *m_cursor;
6482 if (yych <= '@')
6483 {
6484 if (yych <= '/')
6485 {
6486 goto basic_json_parser_32;
6487 }
6488 if (yych >= ':')
6489 {
6490 goto basic_json_parser_32;
6491 }
6492 }
6493 else
6494 {
6495 if (yych <= 'F')
6496 {
6497 goto basic_json_parser_39;
6498 }
6499 if (yych <= '`')
6500 {
6501 goto basic_json_parser_32;
6502 }
6503 if (yych >= 'g')
6504 {
6505 goto basic_json_parser_32;
6506 }
6507 }
6508basic_json_parser_39:
6509 ++m_cursor;
6510 if (m_limit <= m_cursor)
6511 {
6512 yyfill(); // LCOV_EXCL_LINE;
6513 }
6514 yych = *m_cursor;
6515 if (yych <= '@')
6516 {
6517 if (yych <= '/')
6518 {
6519 goto basic_json_parser_32;
6520 }
6521 if (yych <= '9')
6522 {
6523 goto basic_json_parser_30;
6524 }
6525 goto basic_json_parser_32;
6526 }
6527 else
6528 {
6529 if (yych <= 'F')
6530 {
6531 goto basic_json_parser_30;
6532 }
6533 if (yych <= '`')
6534 {
6535 goto basic_json_parser_32;
6536 }
6537 if (yych <= 'f')
6538 {
6539 goto basic_json_parser_30;
6540 }
6541 goto basic_json_parser_32;
6542 }
6543basic_json_parser_40:
6544 yyaccept = 1;
6545 m_marker = ++m_cursor;
6546 if ((m_limit - m_cursor) < 3)
6547 {
6548 yyfill(); // LCOV_EXCL_LINE;
6549 }
6550 yych = *m_cursor;
6551basic_json_parser_41:
6552 if (yybm[0 + yych] & 128)
6553 {
6554 goto basic_json_parser_40;
6555 }
6556 if (yych <= 'D')
6557 {
6558 if (yych != '.')
6559 {
6560 goto basic_json_parser_24;
6561 }
6562 }
6563 else
6564 {
6565 if (yych <= 'E')
6566 {
6567 goto basic_json_parser_43;
6568 }
6569 if (yych == 'e')
6570 {
6571 goto basic_json_parser_43;
6572 }
6573 goto basic_json_parser_24;
6574 }
6575basic_json_parser_42:
6576 yych = *++m_cursor;
6577 if (yych <= '/')
6578 {
6579 goto basic_json_parser_32;
6580 }
6581 if (yych <= '9')
6582 {
6583 goto basic_json_parser_47;
6584 }
6585 goto basic_json_parser_32;
6586basic_json_parser_43:
6587 yych = *++m_cursor;
6588 if (yych <= ',')
6589 {
6590 if (yych != '+')
6591 {
6592 goto basic_json_parser_32;
6593 }
6594 }
6595 else
6596 {
6597 if (yych <= '-')
6598 {
6599 goto basic_json_parser_44;
6600 }
6601 if (yych <= '/')
6602 {
6603 goto basic_json_parser_32;
6604 }
6605 if (yych <= '9')
6606 {
6607 goto basic_json_parser_45;
6608 }
6609 goto basic_json_parser_32;
6610 }
6611basic_json_parser_44:
6612 yych = *++m_cursor;
6613 if (yych <= '/')
6614 {
6615 goto basic_json_parser_32;
6616 }
6617 if (yych >= ':')
6618 {
6619 goto basic_json_parser_32;
6620 }
6621basic_json_parser_45:
6622 ++m_cursor;
6623 if (m_limit <= m_cursor)
6624 {
6625 yyfill(); // LCOV_EXCL_LINE;
6626 }
6627 yych = *m_cursor;
6628 if (yych <= '/')
6629 {
6630 goto basic_json_parser_24;
6631 }
6632 if (yych <= '9')
6633 {
6634 goto basic_json_parser_45;
6635 }
6636 goto basic_json_parser_24;
6637basic_json_parser_47:
6638 yyaccept = 1;
6639 m_marker = ++m_cursor;
6640 if ((m_limit - m_cursor) < 3)
6641 {
6642 yyfill(); // LCOV_EXCL_LINE;
6643 }
6644 yych = *m_cursor;
6645 if (yych <= 'D')
6646 {
6647 if (yych <= '/')
6648 {
6649 goto basic_json_parser_24;
6650 }
6651 if (yych <= '9')
6652 {
6653 goto basic_json_parser_47;
6654 }
6655 goto basic_json_parser_24;
6656 }
6657 else
6658 {
6659 if (yych <= 'E')
6660 {
6661 goto basic_json_parser_43;
6662 }
6663 if (yych == 'e')
6664 {
6665 goto basic_json_parser_43;
6666 }
6667 goto basic_json_parser_24;
6668 }
6669basic_json_parser_49:
6670 yyaccept = 1;
6671 yych = *(m_marker = ++m_cursor);
6672 if (yych <= 'D')
6673 {
6674 if (yych == '.')
6675 {
6676 goto basic_json_parser_42;
6677 }
6678 goto basic_json_parser_24;
6679 }
6680 else
6681 {
6682 if (yych <= 'E')
6683 {
6684 goto basic_json_parser_43;
6685 }
6686 if (yych == 'e')
6687 {
6688 goto basic_json_parser_43;
6689 }
6690 goto basic_json_parser_24;
6691 }
6692basic_json_parser_50:
6693 yych = *++m_cursor;
6694 if (yych != 'l')
6695 {
6696 goto basic_json_parser_32;
6697 }
6698 yych = *++m_cursor;
6699 if (yych != 's')
6700 {
6701 goto basic_json_parser_32;
6702 }
6703 yych = *++m_cursor;
6704 if (yych != 'e')
6705 {
6706 goto basic_json_parser_32;
6707 }
6708 ++m_cursor;
6709 {
6710 return token_type::literal_false;
6711 }
6712basic_json_parser_55:
6713 yych = *++m_cursor;
6714 if (yych != 'u')
6715 {
6716 goto basic_json_parser_32;
6717 }
6718 yych = *++m_cursor;
6719 if (yych != 'e')
6720 {
6721 goto basic_json_parser_32;
6722 }
6723 ++m_cursor;
6724 {
6725 return token_type::literal_true;
6726 }
6727basic_json_parser_59:
6728 yych = *++m_cursor;
6729 if (yych != 'l')
6730 {
6731 goto basic_json_parser_32;
6732 }
6733 yych = *++m_cursor;
6734 if (yych != 'l')
6735 {
6736 goto basic_json_parser_32;
6737 }
6738 ++m_cursor;
6739 {
6740 return token_type::literal_null;
6741 }
6742 }
6743
6744
6745 }
6746
6747 /// append data from the stream to the internal buffer
6748 void yyfill() noexcept
6749 {
6750 if (not m_stream or not * m_stream)
6751 {
6752 return;
6753 }
6754
6755 const ssize_t offset_start = m_start - m_content;
6756 const ssize_t offset_marker = m_marker - m_start;
6757 const ssize_t offset_cursor = m_cursor - m_start;
6758
6759 m_buffer.erase(0, static_cast<size_t>(offset_start));
6760 std::string line;
6761 std::getline(*m_stream, line);
6762 m_buffer += "\n" + line; // add line with newline symbol
6763
6764 m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
6765 m_start = m_content;
6766 m_marker = m_start + offset_marker;
6767 m_cursor = m_start + offset_cursor;
6768 m_limit = m_start + m_buffer.size() - 1;
6769 }
6770
6771 /// return string representation of last read token
6772 string_t get_token() const noexcept
6773 {
6774 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
6775 static_cast<size_t>(m_cursor - m_start));
6776 }
6777
6778 /*!
6779 @brief return string value for string tokens
6780
6781 The function iterates the characters between the opening and closing
6782 quotes of the string value. The complete string is the range
6783 [m_start,m_cursor). Consequently, we iterate from m_start+1 to
6784 m_cursor-1.
6785
6786 We differentiate two cases:
6787
6788 1. Escaped characters. In this case, a new character is constructed
6789 according to the nature of the escape. Some escapes create new
6790 characters (e.g., @c "\\n" is replaced by @c "\n"), some are copied
6791 as is (e.g., @c "\\\\"). Furthermore, Unicode escapes of the shape
6792 @c "\\uxxxx" need special care. In this case, to_unicode takes care
6793 of the construction of the values.
6794 2. Unescaped characters are copied as is.
6795
6796 @return string value of current token without opening and closing quotes
6797 @throw std::out_of_range if to_unicode fails
6798 */
6799 string_t get_string() const
6800 {
6801 string_t result;
6802 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
6803
6804 // iterate the result between the quotes
6805 for (const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
6806 {
6807 // process escaped characters
6808 if (*i == '\\')
6809 {
6810 // read next character
6811 ++i;
6812
6813 switch (*i)
6814 {
6815 // the default escapes
6816 case 't':
6817 {
6818 result += "\t";
6819 break;
6820 }
6821 case 'b':
6822 {
6823 result += "\b";
6824 break;
6825 }
6826 case 'f':
6827 {
6828 result += "\f";
6829 break;
6830 }
6831 case 'n':
6832 {
6833 result += "\n";
6834 break;
6835 }
6836 case 'r':
6837 {
6838 result += "\r";
6839 break;
6840 }
6841 case '\\':
6842 {
6843 result += "\\";
6844 break;
6845 }
6846 case '/':
6847 {
6848 result += "/";
6849 break;
6850 }
6851 case '"':
6852 {
6853 result += "\"";
6854 break;
6855 }
6856
6857 // unicode
6858 case 'u':
6859 {
6860 // get code xxxx from uxxxx
6861 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
6862 4).c_str(), nullptr, 16);
6863
6864 // check if codepoint is a high surrogate
6865 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
6866 {
6867 // make sure there is a subsequent unicode
6868 if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
6869 {
6870 throw std::invalid_argument("missing low surrogate");
6871 }
6872
6873 // get code yyyy from uxxxx\uyyyy
6874 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
6875 (i + 7), 4).c_str(), nullptr, 16);
6876 result += to_unicode(codepoint, codepoint2);
6877 // skip the next 11 characters (xxxx\uyyyy)
6878 i += 11;
6879 }
6880 else
6881 {
6882 // add unicode character(s)
6883 result += to_unicode(codepoint);
6884 // skip the next four characters (xxxx)
6885 i += 4;
6886 }
6887 break;
6888 }
6889 }
6890 }
6891 else
6892 {
6893 // all other characters are just copied to the end of the
6894 // string
6895 result.append(1, static_cast<typename string_t::value_type>(*i));
6896 }
6897 }
6898
6899 return result;
6900 }
6901
6902 /*!
6903 @brief return number value for number tokens
6904
6905 This function translates the last token into a floating point number.
6906 The pointer m_begin points to the beginning of the parsed number. We
6907 pass this pointer to std::strtod which sets endptr to the first
6908 character past the converted number. If this pointer is not the same as
6909 m_cursor, then either more or less characters have been used during the
6910 comparison. This can happen for inputs like "01" which will be treated
6911 like number 0 followed by number 1.
6912
6913 @return the result of the number conversion or NAN if the conversion
6914 read past the current token. The latter case needs to be treated by the
6915 caller function.
6916
6917 @throw std::range_error if passed value is out of range
6918 */
6919 long double get_number() const
6920 {
6921 // conversion
6922 typename string_t::value_type* endptr;
6923 const auto float_val = std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start),
6924 &endptr);
6925
6926 // return float_val if the whole number was translated and NAN
6927 // otherwise
6928 return (reinterpret_cast<lexer_char_t*>(endptr) == m_cursor) ? float_val : NAN;
6929 }
6930
6931 private:
6932 /// optional input stream
6933 std::istream* m_stream;
6934 /// the buffer
6935 string_t m_buffer;
6936 /// the buffer pointer
6937 const lexer_char_t* m_content = nullptr;
6938 /// pointer to the beginning of the current symbol
6939 const lexer_char_t* m_start = nullptr;
6940 /// pointer for backtracking information
6941 const lexer_char_t* m_marker = nullptr;
6942 /// pointer to the current symbol
6943 const lexer_char_t* m_cursor = nullptr;
6944 /// pointer to the end of the buffer
6945 const lexer_char_t* m_limit = nullptr;
6946 };
6947
6948 /*!
6949 @brief syntax analysis
6950 */
6951 class parser
6952 {
6953 public:
6954 /// constructor for strings
6955 parser(const string_t& s, parser_callback_t cb = nullptr)
6956 : callback(cb), m_lexer(s)
6957 {
6958 // read first token
6959 get_token();
6960 }
6961
6962 /// a parser reading from an input stream
6963 parser(std::istream& _is, parser_callback_t cb = nullptr)
6964 : callback(cb), m_lexer(&_is)
6965 {
6966 // read first token
6967 get_token();
6968 }
6969
6970 /// public parser interface
6971 basic_json parse()
6972 {
6973 basic_json result = parse_internal(true);
6974
6975 expect(lexer::token_type::end_of_input);
6976
6977 // return parser result and replace it with null in case the
6978 // top-level value was discarded by the callback function
6979 return result.is_discarded() ? basic_json() : result;
6980 }
6981
6982 private:
6983 /// the actual parser
6984 basic_json parse_internal(bool keep)
6985 {
6986 auto result = basic_json(value_t::discarded);
6987
6988 switch (last_token)
6989 {
6990 case (lexer::token_type::begin_object):
6991 {
6992 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
6993 {
6994 // explicitly set result to object to cope with {}
6995 result.m_type = value_t::object;
6996 result.m_value = json_value(value_t::object);
6997 }
6998
6999 // read next token
7000 get_token();
7001
7002 // closing } -> we are done
7003 if (last_token == lexer::token_type::end_object)
7004 {
7005 get_token();
7006 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7007 {
7008 result = basic_json(value_t::discarded);
7009 }
7010 return result;
7011 }
7012
7013 // no comma is expected here
7014 unexpect(lexer::token_type::value_separator);
7015
7016 // otherwise: parse key-value pairs
7017 do
7018 {
7019 // ugly, but could be fixed with loop reorganization
7020 if (last_token == lexer::token_type::value_separator)
7021 {
7022 get_token();
7023 }
7024
7025 // store key
7026 expect(lexer::token_type::value_string);
7027 const auto key = m_lexer.get_string();
7028
7029 bool keep_tag = false;
7030 if (keep)
7031 {
7032 if (callback)
7033 {
7034 basic_json k(key);
7035 keep_tag = callback(depth, parse_event_t::key, k);
7036 }
7037 else
7038 {
7039 keep_tag = true;
7040 }
7041 }
7042
7043 // parse separator (:)
7044 get_token();
7045 expect(lexer::token_type::name_separator);
7046
7047 // parse and add value
7048 get_token();
7049 auto value = parse_internal(keep);
7050 if (keep and keep_tag and not value.is_discarded())
7051 {
7052 result[key] = std::move(value);
7053 }
7054 }
7055 while (last_token == lexer::token_type::value_separator);
7056
7057 // closing }
7058 expect(lexer::token_type::end_object);
7059 get_token();
7060 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
7061 {
7062 result = basic_json(value_t::discarded);
7063 }
7064
7065 return result;
7066 }
7067
7068 case (lexer::token_type::begin_array):
7069 {
7070 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
7071 {
7072 // explicitly set result to object to cope with []
7073 result.m_type = value_t::array;
7074 result.m_value = json_value(value_t::array);
7075 }
7076
7077 // read next token
7078 get_token();
7079
7080 // closing ] -> we are done
7081 if (last_token == lexer::token_type::end_array)
7082 {
7083 get_token();
7084 if (callback and not callback(--depth, parse_event_t::array_end, result))
7085 {
7086 result = basic_json(value_t::discarded);
7087 }
7088 return result;
7089 }
7090
7091 // no comma is expected here
7092 unexpect(lexer::token_type::value_separator);
7093
7094 // otherwise: parse values
7095 do
7096 {
7097 // ugly, but could be fixed with loop reorganization
7098 if (last_token == lexer::token_type::value_separator)
7099 {
7100 get_token();
7101 }
7102
7103 // parse value
7104 auto value = parse_internal(keep);
7105 if (keep and not value.is_discarded())
7106 {
7107 result.push_back(std::move(value));
7108 }
7109 }
7110 while (last_token == lexer::token_type::value_separator);
7111
7112 // closing ]
7113 expect(lexer::token_type::end_array);
7114 get_token();
7115 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
7116 {
7117 result = basic_json(value_t::discarded);
7118 }
7119
7120 return result;
7121 }
7122
7123 case (lexer::token_type::literal_null):
7124 {
7125 get_token();
7126 result.m_type = value_t::null;
7127 break;
7128 }
7129
7130 case (lexer::token_type::value_string):
7131 {
7132 const auto s = m_lexer.get_string();
7133 get_token();
7134 result = basic_json(s);
7135 break;
7136 }
7137
7138 case (lexer::token_type::literal_true):
7139 {
7140 get_token();
7141 result.m_type = value_t::boolean;
7142 result.m_value = true;
7143 break;
7144 }
7145
7146 case (lexer::token_type::literal_false):
7147 {
7148 get_token();
7149 result.m_type = value_t::boolean;
7150 result.m_value = false;
7151 break;
7152 }
7153
7154 case (lexer::token_type::value_number):
7155 {
7156 auto float_val = m_lexer.get_number();
7157
7158 // NAN is returned if token could not be translated
7159 // completely
7160 if (std::isnan(float_val))
7161 {
7162 throw std::invalid_argument(std::string("parse error - ") +
7163 m_lexer.get_token() + " is not a number");
7164 }
7165
7166 get_token();
7167
7168 // check if conversion loses precision
7169 const auto int_val = static_cast<number_integer_t>(float_val);
7170 if (approx(float_val, static_cast<long double>(int_val)))
7171 {
7172 // we basic_json not lose precision -> return int
7173 result.m_type = value_t::number_integer;
7174 result.m_value = int_val;
7175 }
7176 else
7177 {
7178 // we would lose precision -> returnfloat
7179 result.m_type = value_t::number_float;
7180 result.m_value = static_cast<number_float_t>(float_val);
7181 }
7182 break;
7183 }
7184
7185 default:
7186 {
7187 // the last token was unexpected
7188 unexpect(last_token);
7189 }
7190 }
7191
7192 if (keep and callback and not callback(depth, parse_event_t::value, result))
7193 {
7194 result = basic_json(value_t::discarded);
7195 }
7196 return result;
7197 }
7198
7199 /// get next token from lexer
7200 typename lexer::token_type get_token()
7201 {
7202 last_token = m_lexer.scan();
7203 return last_token;
7204 }
7205
7206 void expect(typename lexer::token_type t) const
7207 {
7208 if (t != last_token)
7209 {
7210 std::string error_msg = "parse error - unexpected \'";
7211 error_msg += m_lexer.get_token();
7212 error_msg += "\' (" + lexer::token_type_name(last_token);
7213 error_msg += "); expected " + lexer::token_type_name(t);
7214 throw std::invalid_argument(error_msg);
7215 }
7216 }
7217
7218 void unexpect(typename lexer::token_type t) const
7219 {
7220 if (t == last_token)
7221 {
7222 std::string error_msg = "parse error - unexpected \'";
7223 error_msg += m_lexer.get_token();
7224 error_msg += "\' (";
7225 error_msg += lexer::token_type_name(last_token) + ")";
7226 throw std::invalid_argument(error_msg);
7227 }
7228 }
7229
7230 private:
7231 /// current level of recursion
7232 int depth = 0;
7233 /// callback function
7234 parser_callback_t callback;
7235 /// the type of the last read token
7236 typename lexer::token_type last_token = lexer::token_type::uninitialized;
7237 /// the lexer
7238 lexer m_lexer;
7239 };
7240};
7241
7242
7243/////////////
7244// presets //
7245/////////////
7246
7247/*!
7248@brief default JSON class
7249
7250This type is the default specialization of the @ref basic_json class which uses
7251the standard template types.
7252*/
7253using json = basic_json<>;
7254}
7255
7256
7257/////////////////////////
7258// nonmember functions //
7259/////////////////////////
7260
7261// specialization of std::swap, and std::hash
7262namespace std
7263{
7264/*!
7265@brief exchanges the values of two JSON objects
7266*/
7267template <>
7268inline void swap(nlohmann::json& j1,
7269 nlohmann::json& j2) noexcept(
7270 is_nothrow_move_constructible<nlohmann::json>::value and
7271 is_nothrow_move_assignable<nlohmann::json>::value
7272 )
7273{
7274 j1.swap(j2);
7275}
7276
7277/// hash value for JSON objects
7278template <>
7279struct hash<nlohmann::json>
7280{
7281 /// return a hash value for a JSON object
7282 std::size_t operator()(const nlohmann::json& j) const
7283 {
7284 // a naive hashing via the string representation
7285 const auto& h = hash<nlohmann::json::string_t>();
7286 return h(j.dump());
7287 }
7288};
7289}
7290
7291/*!
7292@brief user-defined string literal for JSON values
7293
7294This operator implements a user-defined string literal for JSON objects. It can
7295be used by adding \p "_json" to a string literal and returns a JSON object if
7296no parse error occurred.
7297
7298@param[in] s a string representation of a JSON object
7299@return a JSON object
7300*/
7301inline nlohmann::json operator "" _json(const char* s, std::size_t)
7302{
7303 return nlohmann::json::parse(reinterpret_cast<nlohmann::json::string_t::value_type*>
7304 (const_cast<char*>(s)));
7305}
7306
7307#endif
diff --git a/templates/data.cpp.ede b/templates/data.cpp.ede
index 8e106a6..a7447d6 100644
--- a/templates/data.cpp.ede
+++ b/templates/data.cpp.ede
@@ -3,40 +3,6 @@
3 3
4#include "{{ moduleName }}.hpp" 4#include "{{ moduleName }}.hpp"
5 5
6template<> json toJSON<String>(String &v) {
7 return json(v);
8}
9
10template<> json toJSON<Float>(Float &v) {
11 return json(v);
12}
13
14template<> json toJSON<bool>(bool &v) {
15 return json(v);
16}
17
18template<> json toJSON<int>(int &v) {
19 return json(v);
20}
21
22template<> json toJSON<unsigned int>(unsigned int &v) {
23 return json(v);
24}
25
26template<typename any>
27json toJSON(std::vector<any> &v) {
28 json obj = json::array();
29 for (any i : v) {
30 obj.push_back(toJSON(i));
31 }
32 return obj;
33}
34
35template<typename k, typename v>
36json toJSON(std::map<k,v> &value) {
37 return json();
38}
39
40{% for t in definitions %} 6{% for t in definitions %}
41template<> json toJSON<{{ t.value.dataName }}>({{ t.value.dataName }} &v) { 7template<> json toJSON<{{ t.value.dataName }}>({{ t.value.dataName }} &v) {
42 json obj; 8 json obj;
@@ -53,11 +19,3 @@ template<> json toJSON<{{ t.value.dataName }}>({{ t.value.dataName }} &v) {
53 return obj; 19 return obj;
54} 20}
55{% endfor %} 21{% endfor %}
56
57{#
58{% for c in t.value.constructors %}
59json data::{{ c.value.name }}::toJSON() {
60 return obj;
61}
62{% endif %}{% endfor %}{% endfor %}
63#} \ No newline at end of file
diff --git a/templates/data.hpp.ede b/templates/data.hpp.ede
index 10e1ff4..0dcb02c 100644
--- a/templates/data.hpp.ede
+++ b/templates/data.hpp.ede
@@ -4,24 +4,7 @@
4#ifndef HEADER_{{ moduleName }}_H 4#ifndef HEADER_{{ moduleName }}_H
5#define HEADER_{{ moduleName }}_H 5#define HEADER_{{ moduleName }}_H
6 6
7#include <vector> 7#include "RT.hpp"
8#include <map>
9#include <string>
10
11#include "json.hpp"
12
13typedef int Int;
14typedef int Int32;
15typedef unsigned int Word;
16typedef unsigned int Word32;
17typedef float Float;
18typedef bool Bool;
19typedef std::string String;
20
21using json = nlohmann::json;
22
23template<typename T>
24json toJSON(T &v);
25 8
26{% for m in imports %} 9{% for m in imports %}
27#include "{{ m.value }}.hpp" 10#include "{{ m.value }}.hpp"