diff --git a/src/json.hpp b/src/json.hpp
index 7e174d720..e2bbf839c 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1,36 +1,32 @@
/*!
@mainpage
-
These pages contain the API documentation of JSON for Modern C++, a C++11
header-only JSON class.
-
Class @ref nlohmann::basic_json is a good entry point for the documentation.
-
@copyright The code is licensed under the [MIT
- License](http://opensource.org/licenses/MIT):
-
- Copyright © 2013-2015 Niels Lohmann.
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-
+License](http://opensource.org/licenses/MIT):
+
+Copyright © 2013-2015 Niels Lohmann.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
@author [Niels Lohmann](http://nlohmann.me)
@see https://github.com/nlohmann/json to download the source code
*/
@@ -59,15 +55,15 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
// enable ssize_t on MinGW
#ifdef __GNUC__
- #ifdef __MINGW32__
- #include
- #endif
+#ifdef __MINGW32__
+#include
+#endif
#endif
// enable ssize_t for MSVC
#ifdef _MSC_VER
- #include
- using ssize_t = SSIZE_T;
+#include
+using ssize_t = SSIZE_T;
#endif
/*!
@@ -78,1398 +74,1178 @@ namespace nlohmann
{
-/*!
-@brief unnamed namespace with internal helper functions
-*/
-namespace
-{
-/*!
-@brief Helper to determine whether there's a key_type for T.
-@sa http://stackoverflow.com/a/7728728/266378
-*/
-template
-struct has_mapped_type
-{
- private:
- template static char test(typename C::mapped_type*);
- template static int test(...);
- public:
- enum { value = sizeof(test(0)) == sizeof(char) };
-};
+ /*!
+ @brief unnamed namespace with internal helper functions
+ */
+ namespace
+ {
+ /*!
+ @brief Helper to determine whether there's a key_type for T.
+ @sa http://stackoverflow.com/a/7728728/266378
+ */
+ template
+ struct has_mapped_type
+ {
+ private:
+ template static char test( typename C::mapped_type* );
+ template static int test( ... );
+ public:
+ enum { value = sizeof( test( 0 ) ) == sizeof( char ) };
+ };
-/// "equality" comparison for floating point numbers
-template
-static bool approx(const T a, const T b)
-{
- return not (a > b or a < b);
-}
-}
+ /// "equality" comparison for floating point numbers
+ template
+ static bool approx( const T a, const T b )
+ {
+ return not ( a > b or a < b );
+ }
+ }
-/*!
-@brief a class to store JSON values
-
-@tparam ObjectType type for JSON objects (@c std::map by default; will be used
-in @ref object_t)
-@tparam ArrayType type for JSON arrays (@c std::vector by default; will be used
-in @ref array_t)
-@tparam StringType type for JSON strings and object keys (@c std::string by
-default; will be used in @ref string_t)
-@tparam BooleanType type for JSON booleans (@c `bool` by default; will be used
-in @ref boolean_t)
-@tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by
-default; will be used in @ref number_integer_t)
-@tparam NumberFloatType type for JSON floating-point numbers (@c `double` by
-default; will be used in @ref number_float_t)
-@tparam AllocatorType type of the allocator to use (@c `std::allocator` by
-default)
-
-@requirement The class satisfies the following concept requirements:
-- Basic
- - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
- JSON values can be default constructed. The result will be a JSON null value.
- - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
- A JSON value can be constructed from an rvalue argument.
- - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
- A JSON value can be copy-constrcuted from an lvalue expression.
- - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
- A JSON value van be assigned from an rvalue argument.
- - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
- A JSON value can be copy-assigned from an lvalue expression.
- - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
- JSON values can be destructed.
-- Layout
- - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
- JSON values have
- [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
- All non-static data members are private and standard layout types, the class
- has no virtual functions or (virtual) base classes.
-- Library-wide
- - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
- JSON values can be compared with `==`, see @ref
- operator==(const_reference,const_reference).
- - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
- JSON values can be compared with `<`, see @ref
- operator<(const_reference,const_reference).
- - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
- Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
- other compatible types, using unqualified function call @ref swap().
- - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
- JSON values can be compared against `std::nullptr_t` objects which are used
- to model the `null` value.
-- Container
- - [Container](http://en.cppreference.com/w/cpp/concept/Container):
- JSON values can be used like STL containers and provide iterator access.
- - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
- JSON values can be used like STL containers and provide reverse iterator
- access.
-
-@internal
-@note ObjectType trick from http://stackoverflow.com/a/9860911
-@endinternal
-
-@see RFC 7159
-*/
-template <
- template class ObjectType = std::map,
- template class ArrayType = std::vector,
+ /*!
+ @brief a class to store JSON values
+ @tparam ObjectType type for JSON objects (@c std::map by default; will be used
+ in @ref object_t)
+ @tparam ArrayType type for JSON arrays (@c std::vector by default; will be used
+ in @ref array_t)
+ @tparam StringType type for JSON strings and object keys (@c std::string by
+ default; will be used in @ref string_t)
+ @tparam BooleanType type for JSON booleans (@c `bool` by default; will be used
+ in @ref boolean_t)
+ @tparam NumberIntegerType type for JSON integer numbers (@c `int64_t` by
+ default; will be used in @ref number_integer_t)
+ @tparam NumberFloatType type for JSON floating-point numbers (@c `double` by
+ default; will be used in @ref number_float_t)
+ @tparam AllocatorType type of the allocator to use (@c `std::allocator` by
+ default)
+ @requirement The class satisfies the following concept requirements:
+ - Basic
+ - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
+ JSON values can be default constructed. The result will be a JSON null value.
+ - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
+ A JSON value can be constructed from an rvalue argument.
+ - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
+ A JSON value can be copy-constrcuted from an lvalue expression.
+ - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
+ A JSON value van be assigned from an rvalue argument.
+ - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
+ A JSON value can be copy-assigned from an lvalue expression.
+ - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
+ JSON values can be destructed.
+ - Layout
+ - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
+ JSON values have
+ [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+ All non-static data members are private and standard layout types, the class
+ has no virtual functions or (virtual) base classes.
+ - Library-wide
+ - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
+ JSON values can be compared with `==`, see @ref
+ operator==(const_reference,const_reference).
+ - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
+ JSON values can be compared with `<`, see @ref
+ operator<(const_reference,const_reference).
+ - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
+ Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
+ other compatible types, using unqualified function call @ref swap().
+ - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
+ JSON values can be compared against `std::nullptr_t` objects which are used
+ to model the `null` value.
+ - Container
+ - [Container](http://en.cppreference.com/w/cpp/concept/Container):
+ JSON values can be used like STL containers and provide iterator access.
+ - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
+ JSON values can be used like STL containers and provide reverse iterator
+ access.
+ @internal
+ @note ObjectType trick from http://stackoverflow.com/a/9860911
+ @endinternal
+ @see RFC 7159
+ */
+ template <
+ template class ObjectType = std::map,
+ template class ArrayType = std::vector,
class StringType = std::string,
class BooleanType = bool,
class NumberIntegerType = int64_t,
class NumberFloatType = double,
- template class AllocatorType = std::allocator
+ template class AllocatorType = std::allocator
>
-class basic_json
-{
- private:
- /// workaround type for MSVC
- using basic_json_t = basic_json;
-
- public:
-
- /////////////////////
- // container types //
- /////////////////////
-
- /// @name container types
- /// @{
-
- /// the type of elements in a basic_json container
- using value_type = basic_json;
-
- /// the type of an element reference
- using reference = value_type&;
-
- /// the type of an element const reference
- using const_reference = const value_type&;
-
- /// a type to represent differences between iterators
- using difference_type = std::ptrdiff_t;
-
- /// a type to represent container sizes
- using size_type = std::size_t;
-
- /// the allocator type
- using allocator_type = AllocatorType;
-
- /// the type of an element pointer
- using pointer = typename std::allocator_traits::pointer;
- /// the type of an element const pointer
- using const_pointer = typename std::allocator_traits::const_pointer;
-
- // forward declaration
- template class json_reverse_iterator;
-
- /// an iterator for a basic_json container
- class iterator;
- /// a const iterator for a basic_json container
- class const_iterator;
- /// a reverse iterator for a basic_json container
- using reverse_iterator = json_reverse_iterator;
- /// a const reverse iterator for a basic_json container
- using const_reverse_iterator = json_reverse_iterator;
-
- /// @}
-
-
- /*!
- @brief returns the allocator associated with the container
- */
- static allocator_type get_allocator()
+ class basic_json
{
- return allocator_type();
- }
+ private:
+ /// workaround type for MSVC
+ using basic_json_t = basic_json;
+ public:
- ///////////////////////////
- // JSON value data types //
- ///////////////////////////
+ /////////////////////
+ // container types //
+ /////////////////////
- /// @name JSON value data types
- /// @{
+ /// @name container types
+ /// @{
- /*!
- @brief a type for an object
+ /// the type of elements in a basic_json container
+ using value_type = basic_json;
- [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
- > An object is an unordered collection of zero or more name/value pairs,
- > where a name is a string and a value is a string, number, boolean, null,
- > object, or array.
+ /// the type of an element reference
+ using reference = value_type&;
- To store objects in C++, a type is defined by the template parameters @a
- ObjectType which chooses the container (e.g., `std::map` or
- `std::unordered_map`), @a StringType which chooses the type of the keys or
- names, and @a AllocatorType which chooses the allocator to use.
+ /// the type of an element const reference
+ using const_reference = const value_type&;
- #### Default type
+ /// a type to represent differences between iterators
+ using difference_type = std::ptrdiff_t;
- With the default values for @a ObjectType (`std::map`), @a StringType
- (`std::string`), and @a AllocatorType (`std::allocator`), the default value
- for @a object_t is:
+ /// a type to represent container sizes
+ using size_type = std::size_t;
- @code {.cpp}
- std::map<
- std::string, // key_type
- basic_json, // value_type
- std::less, // key_compare
- std::allocator> // allocator_type
- >
- @endcode
+ /// the allocator type
+ using allocator_type = AllocatorType;
- #### Behavior
+ /// the type of an element pointer
+ using pointer = typename std::allocator_traits::pointer;
+ /// the type of an element const pointer
+ using const_pointer = typename std::allocator_traits::const_pointer;
- The choice of @a object_t influences the behavior of the JSON class. With
- the default type, objects have the following behavior:
+ // forward declaration
+ template class json_reverse_iterator;
- - When all names are unique, objects will be interoperable in the sense
- that all software implementations receiving that object will agree on the
- name-value mappings.
- - When the names within an object are not unique, later stored name/value
- pairs overwrite previously stored name/value pairs, leaving the used
- names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will
- be treated as equal and both stored as `{"key": 1}`.
- - Internally, name/value pairs are stored in lexicographical order of the
- names. Objects will also be serialized (see @ref dump) in this order. For
- instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and
- serialized as `{"a": 2, "b": 1}`.
- - When comparing objects, the order of the name/value pairs is irrelevant.
- This makes objects interoperable in the sense that they will not be
- affected by these differences. For instance, `{"b": 1, "a": 2}` and
- `{"a": 2, "b": 1}` will be treated as equal.
+ /// an iterator for a basic_json container
+ class iterator;
+ /// a const iterator for a basic_json container
+ class const_iterator;
+ /// a reverse iterator for a basic_json container
+ using reverse_iterator = json_reverse_iterator;
+ /// a const reverse iterator for a basic_json container
+ using const_reverse_iterator = json_reverse_iterator;
- #### Limits
+ /// @}
- [RFC 7159](http://rfc7159.net/rfc7159) specifies:
- > An implementation may set limits on the maximum depth of nesting.
- In this class, the object's limit of nesting is not constraint explicitly.
- However, a maximum depth of nesting may be introduced by the compiler or
- runtime environment. A theoretical limit can be queried by calling the @ref
- max_size function of a JSON object.
-
- #### Storage
-
- Objects are stored as pointers in a `basic_json` type. That is, for any
- access to object values, a pointer of type `object_t*` must be dereferenced.
-
- @sa array_t
- */
- using object_t = ObjectType,
- AllocatorType>>;
-
- /*!
- @brief a type for an array
-
- [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
- > An array is an ordered sequence of zero or more values.
-
- To store objects in C++, a type is defined by the template parameters @a
- ArrayType which chooses the container (e.g., `std::vector` or `std::list`)
- and @a AllocatorType which chooses the allocator to use.
-
- #### Default type
-
- With the default values for @a ArrayType (`std::vector`) and @a
- AllocatorType (`std::allocator`), the default value for @a array_t is:
-
- @code {.cpp}
- std::vector<
- basic_json, // value_type
- std::allocator // allocator_type
- >
- @endcode
-
- #### Limits
-
- [RFC 7159](http://rfc7159.net/rfc7159) specifies:
- > An implementation may set limits on the maximum depth of nesting.
-
- In this class, the array's limit of nesting is not constraint explicitly.
- However, a maximum depth of nesting may be introduced by the compiler or
- runtime environment. A theoretical limit can be queried by calling the @ref
- max_size function of a JSON array.
-
- #### Storage
-
- Arrays are stored as pointers in a `basic_json` type. That is, for any
- access to array values, a pointer of type `array_t*` must be dereferenced.
- */
- using array_t = ArrayType>;
-
- /*!
- @brief a type for a string
-
- [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
- > A string is a sequence of zero or more Unicode characters.
-
- To store objects in C++, a type is defined by the template parameters @a
- StringType which chooses the container (e.g., `std::string`) to use.
-
- Unicode values are split by the JSON class into byte-sized characters
- during deserialization.
-
- #### Default type
-
- With the default values for @a StringType (`std::string`), the default
- value for @a string_t is:
-
- @code {.cpp}
- std::string
- @endcode
-
- #### String comparison
-
- [RFC 7159](http://rfc7159.net/rfc7159) states:
- > Software implementations are typically required to test names of object
- > members for equality. Implementations that transform the textual
- > representation into sequences of Unicode code units and then perform the
- > comparison numerically, code unit by code unit, are interoperable in the
- > sense that implementations will agree in all cases on equality or
- > inequality of two strings. For example, implementations that compare
- > strings with escaped characters unconverted may incorrectly find that
- > `"a\\b"` and `"a\u005Cb"` are not equal.
-
- This implementation is interoperable as it does compare strings code unit
- by code unit.
-
- #### Storage
-
- String values are stored as pointers in a `basic_json` type. That is, for
- any access to string values, a pointer of type `string_t*` must be
- dereferenced.
- */
- using string_t = StringType;
-
- /*!
- @brief a type for a boolean
-
- [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
- type which differentiates the two literals `true` and `false`.
-
- To store objects in C++, a type is defined by the template parameter @a
- BooleanType which chooses the type to use.
-
- #### Default type
-
- With the default values for @a BooleanType (`bool`), the default value for
- @a boolean_t is:
-
- @code {.cpp}
- bool
- @endcode
-
- #### Storage
-
- Boolean values are stored directly inside a `basic_json` type.
- */
- using boolean_t = BooleanType;
-
- /*!
- @brief a type for a number (integer)
-
- [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
- > The representation of numbers is similar to that used in most programming
- > languages. A number is represented in base 10 using decimal digits. It
- > contains an integer component that may be prefixed with an optional minus
- > sign, which may be followed by a fraction part and/or an exponent part.
- > Leading zeros are not allowed. (...) Numeric values that cannot be
- > represented in the grammar below (such as Infinity and NaN) are not
- > permitted.
-
- This description includes both integer and floating-point numbers. However,
- C++ allows more precise storage if it is known whether the number is an
- integer or a floating-point number. Therefore, two different types, @ref
- number_integer_t and @ref number_float_t are used.
-
- To store integer numbers in C++, a type is defined by the template
- parameter @a NumberIntegerType which chooses the type to use.
-
- #### Default type
-
- With the default values for @a NumberIntegerType (`int64_t`), the default
- value for @a number_integer_t is:
-
- @code {.cpp}
- int64_t
- @endcode
-
- #### Default behavior
-
- - The restrictions about leading zeros is not enforced in C++. Instead,
- leading zeros in integer literals lead to an interpretation as octal
- number. Internally, the value will be stored as decimal number. For
- instance, the C++ integer literal `010` will be serialized to `8`. During
- deserialization, leading zeros yield an error.
- - Not-a-number (NaN) values will be serialized to `null`.
-
- #### Limits
-
- [RFC 7159](http://rfc7159.net/rfc7159) specifies:
- > An implementation may set limits on the range and precision of numbers.
-
- When the default type is used, the maximal integer number that can be
- stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
- that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
- that are out of range will yield over/underflow when used in a constructor.
- During deserialization, too large or small integer numbers will be
- automatically be stored as @ref number_float_t.
-
- [RFC 7159](http://rfc7159.net/rfc7159) further states:
- > Note that when such software is used, numbers that are integers and are
- > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
- > that implementations will agree exactly on their numeric values.
-
- As this range is a subrange of the exactly supported range [INT64_MIN,
- INT64_MAX], this class's integer type is interoperable.
-
- #### Storage
-
- Integer number values are stored directly inside a `basic_json` type.
- */
- using number_integer_t = NumberIntegerType;
-
- /*!
- @brief a type for a number (floating-point)
-
- [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
- > The representation of numbers is similar to that used in most programming
- > languages. A number is represented in base 10 using decimal digits. It
- > contains an integer component that may be prefixed with an optional minus
- > sign, which may be followed by a fraction part and/or an exponent part.
- > Leading zeros are not allowed. (...) Numeric values that cannot be
- > represented in the grammar below (such as Infinity and NaN) are not
- > permitted.
-
- This description includes both integer and floating-point numbers. However,
- C++ allows more precise storage if it is known whether the number is an
- integer or a floating-point number. Therefore, two different types, @ref
- number_integer_t and @ref number_float_t are used.
-
- To store floating-point numbers in C++, a type is defined by the template
- parameter @a NumberFloatType which chooses the type to use.
-
- #### Default type
-
- With the default values for @a NumberFloatType (`double`), the default
- value for @a number_float_t is:
-
- @code {.cpp}
- double
- @endcode
-
- #### Default behavior
-
- - The restrictions about leading zeros is not enforced in C++. Instead,
- leading zeros in floating-point literals will be ignored. Internally, the
- value will be stored as decimal number. For instance, the C++
- floating-point literal `01.2` will be serialized to `1.2`. During
- deserialization, leading zeros yield an error.
- - Not-a-number (NaN) values will be serialized to `null`.
-
- #### Limits
-
- [RFC 7159](http://rfc7159.net/rfc7159) states:
- > This specification allows implementations to set limits on the range and
- > precision of numbers accepted. Since software that implements IEEE
- > 754-2008 binary64 (double precision) numbers is generally available and
- > widely used, good interoperability can be achieved by implementations that
- > expect no more precision or range than these provide, in the sense that
- > implementations will approximate JSON numbers within the expected
- > precision.
-
- This implementation does exactly follow this approach, as it uses double
- precision floating-point numbers. Note values smaller than
- `-1.79769313486232e+308` and values greather than `1.79769313486232e+308`
- will be stored as NaN internally and be serialized to `null`.
-
- #### Storage
-
- Floating-point number values are stored directly inside a `basic_json` type.
- */
- using number_float_t = NumberFloatType;
-
- /// @}
-
-
- ///////////////////////////
- // JSON type enumeration //
- ///////////////////////////
-
- /*!
- @brief the JSON type enumeration
-
- This enumeration collects the different JSON types. It is internally used
- to distinguish the stored values, and the functions is_null, is_object,
- is_array, is_string, is_boolean, is_number, and is_discarded rely on it.
- */
- enum class value_t : uint8_t
- {
- null, ///< null value
- object, ///< object (unordered set of name/value pairs)
- array, ///< array (ordered collection of values)
- string, ///< string value
- boolean, ///< boolean value
- number_integer, ///< number value (integer)
- number_float, ///< number value (floating-point)
- discarded ///< discarded by the the parser callback function
- };
-
-
- private:
- /// helper for exception-safe object creation
- template
- static T* create( Args&& ... args )
- {
- AllocatorType alloc;
- auto deleter = [&](T * object)
+ /*!
+ @brief returns the allocator associated with the container
+ */
+ static allocator_type get_allocator()
{
- alloc.deallocate(object, 1);
+ return allocator_type();
+ }
+
+
+ ///////////////////////////
+ // JSON value data types //
+ ///////////////////////////
+
+ /// @name JSON value data types
+ /// @{
+
+ /*!
+ @brief a type for an object
+ [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
+ > An object is an unordered collection of zero or more name/value pairs,
+ > where a name is a string and a value is a string, number, boolean, null,
+ > object, or array.
+ To store objects in C++, a type is defined by the template parameters @a
+ ObjectType which chooses the container (e.g., `std::map` or
+ `std::unordered_map`), @a StringType which chooses the type of the keys or
+ names, and @a AllocatorType which chooses the allocator to use.
+ #### Default type
+ With the default values for @a ObjectType (`std::map`), @a StringType
+ (`std::string`), and @a AllocatorType (`std::allocator`), the default value
+ for @a object_t is:
+ @code {.cpp}
+ std::map<
+ std::string, // key_type
+ basic_json, // value_type
+ std::less, // key_compare
+ std::allocator> // allocator_type
+ >
+ @endcode
+ #### Behavior
+ The choice of @a object_t influences the behavior of the JSON class. With
+ the default type, objects have the following behavior:
+ - When all names are unique, objects will be interoperable in the sense
+ that all software implementations receiving that object will agree on the
+ name-value mappings.
+ - When the names within an object are not unique, later stored name/value
+ pairs overwrite previously stored name/value pairs, leaving the used
+ names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will
+ be treated as equal and both stored as `{"key": 1}`.
+ - Internally, name/value pairs are stored in lexicographical order of the
+ names. Objects will also be serialized (see @ref dump) in this order. For
+ instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored and
+ serialized as `{"a": 2, "b": 1}`.
+ - When comparing objects, the order of the name/value pairs is irrelevant.
+ This makes objects interoperable in the sense that they will not be
+ affected by these differences. For instance, `{"b": 1, "a": 2}` and
+ `{"a": 2, "b": 1}` will be treated as equal.
+ #### Limits
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the maximum depth of nesting.
+ In this class, the object's limit of nesting is not constraint explicitly.
+ However, a maximum depth of nesting may be introduced by the compiler or
+ runtime environment. A theoretical limit can be queried by calling the @ref
+ max_size function of a JSON object.
+ #### Storage
+ Objects are stored as pointers in a `basic_json` type. That is, for any
+ access to object values, a pointer of type `object_t*` must be dereferenced.
+ @sa array_t
+ */
+ using object_t = ObjectType,
+ AllocatorType> >;
+
+ /*!
+ @brief a type for an array
+ [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
+ > An array is an ordered sequence of zero or more values.
+ To store objects in C++, a type is defined by the template parameters @a
+ ArrayType which chooses the container (e.g., `std::vector` or `std::list`)
+ and @a AllocatorType which chooses the allocator to use.
+ #### Default type
+ With the default values for @a ArrayType (`std::vector`) and @a
+ AllocatorType (`std::allocator`), the default value for @a array_t is:
+ @code {.cpp}
+ std::vector<
+ basic_json, // value_type
+ std::allocator // allocator_type
+ >
+ @endcode
+ #### Limits
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the maximum depth of nesting.
+ In this class, the array's limit of nesting is not constraint explicitly.
+ However, a maximum depth of nesting may be introduced by the compiler or
+ runtime environment. A theoretical limit can be queried by calling the @ref
+ max_size function of a JSON array.
+ #### Storage
+ Arrays are stored as pointers in a `basic_json` type. That is, for any
+ access to array values, a pointer of type `array_t*` must be dereferenced.
+ */
+ using array_t = ArrayType>;
+
+ /*!
+ @brief a type for a string
+ [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
+ > A string is a sequence of zero or more Unicode characters.
+ To store objects in C++, a type is defined by the template parameters @a
+ StringType which chooses the container (e.g., `std::string`) to use.
+ Unicode values are split by the JSON class into byte-sized characters
+ during deserialization.
+ #### Default type
+ With the default values for @a StringType (`std::string`), the default
+ value for @a string_t is:
+ @code {.cpp}
+ std::string
+ @endcode
+ #### String comparison
+ [RFC 7159](http://rfc7159.net/rfc7159) states:
+ > Software implementations are typically required to test names of object
+ > members for equality. Implementations that transform the textual
+ > representation into sequences of Unicode code units and then perform the
+ > comparison numerically, code unit by code unit, are interoperable in the
+ > sense that implementations will agree in all cases on equality or
+ > inequality of two strings. For example, implementations that compare
+ > strings with escaped characters unconverted may incorrectly find that
+ > `"a\\b"` and `"a\u005Cb"` are not equal.
+ This implementation is interoperable as it does compare strings code unit
+ by code unit.
+ #### Storage
+ String values are stored as pointers in a `basic_json` type. That is, for
+ any access to string values, a pointer of type `string_t*` must be
+ dereferenced.
+ */
+ using string_t = StringType;
+
+ /*!
+ @brief a type for a boolean
+ [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
+ type which differentiates the two literals `true` and `false`.
+ To store objects in C++, a type is defined by the template parameter @a
+ BooleanType which chooses the type to use.
+ #### Default type
+ With the default values for @a BooleanType (`bool`), the default value for
+ @a boolean_t is:
+ @code {.cpp}
+ bool
+ @endcode
+ #### Storage
+ Boolean values are stored directly inside a `basic_json` type.
+ */
+ using boolean_t = BooleanType;
+
+ /*!
+ @brief a type for a number (integer)
+ [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+ > The representation of numbers is similar to that used in most programming
+ > languages. A number is represented in base 10 using decimal digits. It
+ > contains an integer component that may be prefixed with an optional minus
+ > sign, which may be followed by a fraction part and/or an exponent part.
+ > Leading zeros are not allowed. (...) Numeric values that cannot be
+ > represented in the grammar below (such as Infinity and NaN) are not
+ > permitted.
+ This description includes both integer and floating-point numbers. However,
+ C++ allows more precise storage if it is known whether the number is an
+ integer or a floating-point number. Therefore, two different types, @ref
+ number_integer_t and @ref number_float_t are used.
+ To store integer numbers in C++, a type is defined by the template
+ parameter @a NumberIntegerType which chooses the type to use.
+ #### Default type
+ With the default values for @a NumberIntegerType (`int64_t`), the default
+ value for @a number_integer_t is:
+ @code {.cpp}
+ int64_t
+ @endcode
+ #### Default behavior
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in integer literals lead to an interpretation as octal
+ number. Internally, the value will be stored as decimal number. For
+ instance, the C++ integer literal `010` will be serialized to `8`. During
+ deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+ #### Limits
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the range and precision of numbers.
+ When the default type is used, the maximal integer number that can be
+ stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
+ that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
+ that are out of range will yield over/underflow when used in a constructor.
+ During deserialization, too large or small integer numbers will be
+ automatically be stored as @ref number_float_t.
+ [RFC 7159](http://rfc7159.net/rfc7159) further states:
+ > Note that when such software is used, numbers that are integers and are
+ > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+ > that implementations will agree exactly on their numeric values.
+ As this range is a subrange of the exactly supported range [INT64_MIN,
+ INT64_MAX], this class's integer type is interoperable.
+ #### Storage
+ Integer number values are stored directly inside a `basic_json` type.
+ */
+ using number_integer_t = NumberIntegerType;
+
+ /*!
+ @brief a type for a number (floating-point)
+ [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+ > The representation of numbers is similar to that used in most programming
+ > languages. A number is represented in base 10 using decimal digits. It
+ > contains an integer component that may be prefixed with an optional minus
+ > sign, which may be followed by a fraction part and/or an exponent part.
+ > Leading zeros are not allowed. (...) Numeric values that cannot be
+ > represented in the grammar below (such as Infinity and NaN) are not
+ > permitted.
+ This description includes both integer and floating-point numbers. However,
+ C++ allows more precise storage if it is known whether the number is an
+ integer or a floating-point number. Therefore, two different types, @ref
+ number_integer_t and @ref number_float_t are used.
+ To store floating-point numbers in C++, a type is defined by the template
+ parameter @a NumberFloatType which chooses the type to use.
+ #### Default type
+ With the default values for @a NumberFloatType (`double`), the default
+ value for @a number_float_t is:
+ @code {.cpp}
+ double
+ @endcode
+ #### Default behavior
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in floating-point literals will be ignored. Internally, the
+ value will be stored as decimal number. For instance, the C++
+ floating-point literal `01.2` will be serialized to `1.2`. During
+ deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+ #### Limits
+ [RFC 7159](http://rfc7159.net/rfc7159) states:
+ > This specification allows implementations to set limits on the range and
+ > precision of numbers accepted. Since software that implements IEEE
+ > 754-2008 binary64 (double precision) numbers is generally available and
+ > widely used, good interoperability can be achieved by implementations that
+ > expect no more precision or range than these provide, in the sense that
+ > implementations will approximate JSON numbers within the expected
+ > precision.
+ This implementation does exactly follow this approach, as it uses double
+ precision floating-point numbers. Note values smaller than
+ `-1.79769313486232e+308` and values greather than `1.79769313486232e+308`
+ will be stored as NaN internally and be serialized to `null`.
+ #### Storage
+ Floating-point number values are stored directly inside a `basic_json` type.
+ */
+ using number_float_t = NumberFloatType;
+
+ /// @}
+
+
+ ///////////////////////////
+ // JSON type enumeration //
+ ///////////////////////////
+
+ /*!
+ @brief the JSON type enumeration
+ This enumeration collects the different JSON types. It is internally used
+ to distinguish the stored values, and the functions is_null, is_object,
+ is_array, is_string, is_boolean, is_number, and is_discarded rely on it.
+ */
+ enum class value_t : uint8_t
+ {
+ null, ///< null value
+ object, ///< object (unordered set of name/value pairs)
+ array, ///< array (ordered collection of values)
+ string, ///< string value
+ boolean, ///< boolean value
+ number_integer, ///< number value (integer)
+ number_float, ///< number value (floating-point)
+ discarded ///< discarded by the the parser callback function
};
- std::unique_ptr object(alloc.allocate(1), deleter);
- alloc.construct(object.get(), std::forward(args)...);
- return object.release();
- }
- ////////////////////////
- // JSON value storage //
- ////////////////////////
- /// a JSON value
- union json_value
- {
- /// object (stored with pointer to save storage)
- object_t* object;
- /// array (stored with pointer to save storage)
- array_t* array;
- /// string (stored with pointer to save storage)
- string_t* string;
- /// boolean
- boolean_t boolean;
- /// number (integer)
- number_integer_t number_integer;
- /// number (floating-point)
- number_float_t number_float;
-
- /// default constructor (for null values)
- json_value() noexcept = default;
- /// constructor for booleans
- json_value(boolean_t v) noexcept : boolean(v) {}
- /// constructor for numbers (integer)
- json_value(number_integer_t v) noexcept : number_integer(v) {}
- /// constructor for numbers (floating-point)
- json_value(number_float_t v) noexcept : number_float(v) {}
- /// constructor for empty values of a given type
- json_value(value_t t)
+ private:
+ /// helper for exception-safe object creation
+ template
+ static T* create( Args&& ... args )
{
- switch (t)
+ AllocatorType alloc;
+ auto deleter = [&] ( T * object )
{
- case (value_t::null):
- case (value_t::discarded):
+ alloc.deallocate( object, 1 );
+ };
+ std::unique_ptr object( alloc.allocate( 1 ), deleter );
+ alloc.construct( object.get(), std::forward( args )... );
+ return object.release();
+ }
+
+ ////////////////////////
+ // JSON value storage //
+ ////////////////////////
+
+ /// a JSON value
+ union json_value
+ {
+ /// object (stored with pointer to save storage)
+ object_t* object;
+ /// array (stored with pointer to save storage)
+ array_t* array;
+ /// string (stored with pointer to save storage)
+ string_t* string;
+ /// boolean
+ boolean_t boolean;
+ /// number (integer)
+ number_integer_t number_integer;
+ /// number (floating-point)
+ number_float_t number_float;
+
+ /// default constructor (for null values)
+ json_value() noexcept = default;
+ /// constructor for booleans
+ json_value( boolean_t v ) noexcept : boolean( v ) {}
+ /// constructor for numbers (integer)
+ json_value( number_integer_t v ) noexcept : number_integer( v ) {}
+ /// constructor for numbers (floating-point)
+ json_value( number_float_t v ) noexcept : number_float( v ) {}
+ /// constructor for empty values of a given type
+ json_value( value_t t )
+ {
+ switch ( t )
+ {
+ case ( value_t::null ) :
+ case ( value_t::discarded ) :
{
break;
}
- case (value_t::object):
+ case ( value_t::object ) :
{
object = create();
break;
}
- case (value_t::array):
+ case ( value_t::array ) :
{
array = create();
break;
}
- case (value_t::string):
+ case ( value_t::string ) :
{
- string = create("");
+ string = create( "" );
break;
}
- case (value_t::boolean):
+ case ( value_t::boolean ) :
{
- boolean = boolean_t(false);
+ boolean = boolean_t( false );
break;
}
- case (value_t::number_integer):
+ case ( value_t::number_integer ) :
{
- number_integer = number_integer_t(0);
+ number_integer = number_integer_t( 0 );
break;
}
- case (value_t::number_float):
+ case ( value_t::number_float ) :
{
- number_float = number_float_t(0.0);
+ number_float = number_float_t( 0.0 );
+ break;
+ }
+ }
+ }
+
+ /// constructor for strings
+ json_value( const string_t& value )
+ {
+ string = create( value );
+ }
+
+ /// constructor for objects
+ json_value( const object_t& value )
+ {
+ object = create( value );
+ }
+
+ /// constructor for arrays
+ json_value( const array_t& value )
+ {
+ array = create( value );
+ }
+ };
+
+
+ public:
+ //////////////////////////
+ // JSON parser callback //
+ //////////////////////////
+
+ /*!
+ @brief JSON callback events
+ This enumeration lists the parser events that can trigger calling a
+ callback function of type @ref parser_callback_t during parsing.
+ */
+ enum class parse_event_t : uint8_t
+ {
+ /// the parser read `{` and started to process a JSON object
+ object_start,
+ /// the parser read `}` and finished processing a JSON object
+ object_end,
+ /// the parser read `[` and started to process a JSON array
+ array_start,
+ /// the parser read `]` and finished processing a JSON array
+ array_end,
+ /// the parser read a key of a value in an object
+ key,
+ /// the parser finished reading a JSON value
+ value
+ };
+
+ /*!
+ @brief per-element parser callback type
+ With a parser callback function, the result of parsing a JSON text can be
+ influenced. When passed to @ref parse(std::istream&, parser_callback_t) or
+ @ref parse(const string_t&, parser_callback_t), it is called on certain
+ events (passed as @ref parse_event_t via parameter @a event) with a set
+ recursion depth @a depth and context JSON value @a parsed. The return value
+ of the callback function is a boolean indicating whether the element that
+ emitted the callback shall be kept or not.
+ We distinguish six scenarios (determined by the event type) in which the
+ callback function can be called. The following table describes the values
+ of the parameters @a depth, @a event, and @a parsed.
+ parameter @a event | description | parameter @a depth | parameter @a parsed
+ ------------------ | ----------- | ------------------ | -------------------
+ 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
+ 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
+ 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
+ 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
+ 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
+ parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
+ Discarding a value (i.e., returning `false`) has different effects depending on the
+ context in which function was called:
+ - Discarded values in structured types are skipped. That is, the parser
+ will behave as if the discarded value was never read.
+ - In case a value outside a structured type is skipped, it is replaced with
+ `null`. This case happens if the top-level element is skipped.
+ @param[in] depth the depth of the recursion during parsing
+ @param[in] event an event of type parse_event_t indicating the context in
+ the callback function has been called
+ @param[in,out] parsed the current intermediate parse result; note that
+ writing to this value has no effect for parse_event_t::key events
+ @return Whether the JSON value which called the function during parsing
+ should be kept (`true`) or not (`false`). In the latter case, it is either
+ skipped completely or replaced by an empty discarded object.
+ @sa @ref parse(std::istream&, parser_callback_t) or
+ @ref parse(const string_t&, parser_callback_t) for examples
+ */
+ using parser_callback_t = std::function;
+
+
+ //////////////////
+ // constructors //
+ //////////////////
+
+ /*!
+ @brief create an empty value with a given type
+ Create an empty JSON value with a given type. The value will be default
+ initialized with an empty value which depends on the type:
+ Value type | initial value
+ ----------- | -------------
+ null | `null`
+ boolean | `false`
+ string | `""`
+ number | `0`
+ object | `{}`
+ array | `[]`
+ @param[in] value the type of the value to create
+ @complexity Constant.
+ @throw std::bad_alloc if allocation for object, array, or string value
+ fails
+ @liveexample{The following code shows the constructor for different @ref
+ value_t values,basic_json__value_t}
+ */
+ basic_json( const value_t value )
+ : m_type( value ), m_value( value )
+ {}
+
+ /*!
+ @brief create a null object (implicitly)
+ Create a `null` JSON value. This is the implicit version of the `null`
+ value constructor as it takes no parameters.
+ @complexity Constant.
+ @requirement This function satisfies the Container requirements:
+ - The complexity is constant.
+ - As postcondition, it holds: `basic_json().empty() == true`.
+ @liveexample{The following code shows the constructor for a `null` JSON
+ value.,basic_json}
+ @sa basic_json(std::nullptr_t)
+ */
+ basic_json() noexcept = default;
+
+ /*!
+ @brief create a null object (explicitly)
+ Create a `null` JSON value. This is the explicitly version of the `null`
+ value constructor as it takes a null pointer as parameter. It allows to
+ create `null` values by explicitly assigning a @c nullptr to a JSON value.
+ The passed null pointer itself is not read - it is only used to choose the
+ right constructor.
+ @complexity Constant.
+ @liveexample{The following code shows the constructor with null pointer
+ parameter.,basic_json__nullptr_t}
+ @sa basic_json()
+ */
+ basic_json( std::nullptr_t ) noexcept
+ : basic_json( value_t::null )
+ {}
+
+ /*!
+ @brief create an object (explicit)
+ Create an object JSON value with a given content.
+ @param[in] value a value for the object
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for object value fails
+ @liveexample{The following code shows the constructor with an @ref object_t
+ parameter.,basic_json__object_t}
+ @sa basic_json(const CompatibleObjectType&)
+ */
+ basic_json( const object_t& value )
+ : m_type( value_t::object ), m_value( value )
+ {}
+
+ /*!
+ @brief create an object (implicit)
+ Create an object JSON value with a given content. This constructor allows
+ any type that can be used to construct values of type @ref object_t.
+ Examples include the types `std::map` and `std::unordered_map`.
+ @tparam CompatibleObjectType an object type whose `key_type` and
+ `value_type` is compatible to @ref object_t
+ @param[in] value a value for the object
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for object value fails
+ @liveexample{The following code shows the constructor with several
+ compatible object type parameters.,basic_json__CompatibleObjectType}
+ @sa basic_json(const object_t&)
+ */
+ template ::value and
+ std::is_constructible::value, int>::type
+ = 0>
+ basic_json( const CompatibleObjectType& value )
+ : m_type( value_t::object )
+ {
+ using std::begin;
+ using std::end;
+ m_value.object = create( begin( value ), end( value ) );
+ }
+
+ /*!
+ @brief create an array (explicit)
+ Create an array JSON value with a given content.
+ @param[in] value a value for the array
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for array value fails
+ @liveexample{The following code shows the constructor with an @ref array_t
+ parameter.,basic_json__array_t}
+ @sa basic_json(const CompatibleArrayType&)
+ */
+ basic_json( const array_t& value )
+ : m_type( value_t::array ), m_value( value )
+ {}
+
+ /*!
+ @brief create an array (implicit)
+ Create an array JSON value with a given content. This constructor allows
+ any type that can be used to construct values of type @ref array_t.
+ Examples include the types `std::vector`, `std::list`, and `std::set`.
+ @tparam CompatibleArrayType an object type whose `value_type` is compatible
+ to @ref array_t
+ @param[in] value a value for the array
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for array value fails
+ @liveexample{The following code shows the constructor with several
+ compatible array type parameters.,basic_json__CompatibleArrayType}
+ @sa basic_json(const array_t&)
+ */
+ template ::value and
+ not std::is_same::value and
+ not std::is_same::value and
+ not std::is_same::value and
+ not std::is_same::value and
+ not std::is_same::value and
+ std::is_constructible::value, int>::type
+ = 0>
+ basic_json( const CompatibleArrayType& value )
+ : m_type( value_t::array )
+ {
+ using std::begin;
+ using std::end;
+ m_value.array = create( begin( value ), end( value ) );
+ }
+
+ /*!
+ @brief create a string (explicit)
+ Create an string JSON value with a given content.
+ @param[in] value a value for the string
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for string value fails
+ @liveexample{The following code shows the constructor with an @ref string_t
+ parameter.,basic_json__string_t}
+ @sa basic_json(const typename string_t::value_type*)
+ @sa basic_json(const CompatibleStringType&)
+ */
+ basic_json( const string_t& value )
+ : m_type( value_t::string ), m_value( value )
+ {}
+
+ /*!
+ @brief create a string (explicit)
+ Create a string JSON value with a given content.
+ @param[in] value a literal value for the string
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for string value fails
+ @liveexample{The following code shows the constructor with string literal
+ parameter.,basic_json__string_t_value_type}
+ @sa basic_json(const string_t&)
+ @sa basic_json(const CompatibleStringType&)
+ */
+ basic_json( const typename string_t::value_type* value )
+ : basic_json( string_t( value ) )
+ {}
+
+ /*!
+ @brief create a string (implicit)
+ Create a string JSON value with a given content.
+ @param[in] value a value for the string
+ @tparam CompatibleStringType an string type which is compatible to @ref
+ string_t
+ @complexity Linear in the size of the passed @a value.
+ @throw std::bad_alloc if allocation for string value fails
+ @liveexample{The following code shows the construction of a string value
+ from a compatible type.,basic_json__CompatibleStringType}
+ @sa basic_json(const string_t&)
+ */
+ template ::value, int>::type
+ = 0>
+ basic_json( const CompatibleStringType& value )
+ : basic_json( string_t( value ) )
+ {}
+
+ /*!
+ @brief create a boolean (explicit)
+ Creates a JSON boolean type from a given value.
+ @param[in] value a boolean value to store
+ @complexity Constant.
+ @liveexample{The example below demonstrates boolean
+ values.,basic_json__boolean_t}
+ */
+ basic_json( boolean_t value )
+ : m_type( value_t::boolean ), m_value( value )
+ {}
+
+ /*!
+ @brief create an integer number (explicit)
+ Create an interger number JSON value with a given content.
+ @tparam T helper type to compare number_integer_t and int (not visible in)
+ the interface.
+ @param[in] value an integer to create a JSON number from
+ @note This constructor would have the same signature as @ref
+ basic_json(const int value), so we need to switch this one off in case
+ number_integer_t is the same as int. This is done via the helper type @a T.
+ @complexity Constant.
+ @liveexample{The example below shows the construction of a JSON integer
+ number value.,basic_json__number_integer_t}
+ @sa basic_json(const int)
+ */
+ template::value )
+ and std::is_same::value
+ , int>::type = 0>
+ basic_json( const number_integer_t value )
+ : m_type( value_t::number_integer ), m_value( value )
+ {}
+
+ /*!
+ @brief create an integer number from an enum type (explicit)
+ Create an integer number JSON value with a given content.
+ @param[in] value an integer to create a JSON number from
+ @note This constructor allows to pass enums directly to a constructor. As
+ C++ has no way of specifying the type of an anonymous enum explicitly, we
+ can only rely on the fact that such values implicitly convert to int. As
+ int may already be the same type of number_integer_t, we may need to switch
+ off the constructor @ref basic_json(const number_integer_t).
+ @complexity Constant.
+ @liveexample{The example below shows the construction of a JSON integer
+ number value from an anonymous enum.,basic_json__const_int}
+ @sa basic_json(const number_integer_t)
+ */
+ basic_json( const int value )
+ : m_type( value_t::number_integer ),
+ m_value( static_cast( value ) )
+ {}
+
+ /*!
+ @brief create an integer number (implicit)
+ Create an integer number JSON value with a given content. This constructor
+ allows any type that can be used to construct values of type @ref
+ number_integer_t. Examples may include the types `int`, `int32_t`, or
+ `short`.
+ @tparam CompatibleNumberIntegerType an integer type which is compatible to
+ @ref number_integer_t.
+ @param[in] value an integer to create a JSON number from
+ @complexity Constant.
+ @liveexample{The example below shows the construction of several JSON
+ integer number values from compatible
+ types.,basic_json__CompatibleIntegerNumberType}
+ @sa basic_json(const number_integer_t)
+ */
+ template::value and
+ std::numeric_limits::is_integer, CompatibleNumberIntegerType>::type
+ = 0>
+ basic_json( const CompatibleNumberIntegerType value ) noexcept
+ : m_type( value_t::number_integer ),
+ m_value( static_cast( value ) )
+ {}
+
+ /*!
+ @brief create a floating-point number (explicit)
+ Create a floating-point number JSON value with a given content.
+ @param[in] value a floating-point value to create a JSON number from
+ @note RFC 7159 , section 6
+ disallows NaN values:
+ > Numeric values that cannot be represented in the grammar below (such
+ > as Infinity and NaN) are not permitted.
+ In case the parameter @a value is not a number, a JSON null value is
+ created instead.
+ @complexity Constant.
+ @liveexample{The following example creates several floating-point
+ values.,basic_json__number_float_t}
+ */
+ basic_json( const number_float_t value )
+ : m_type( value_t::number_float ), m_value( value )
+ {
+ // replace infinity and NAN by null
+ if ( not std::isfinite( value ) )
+ {
+ m_type = value_t::null;
+ m_value = json_value();
+ }
+ }
+
+ /*!
+ @brief create an floating-point number (implicit)
+ Create an floating-point number JSON value with a given content. This
+ constructor allows any type that can be used to construct values of type
+ @ref number_float_t. Examples may include the types `float`.
+ @tparam CompatibleNumberFloatType a floating-point type which is compatible
+ to @ref number_float_t.
+ @param[in] value a floating-point to create a JSON number from
+ @note RFC 7159 , section 6
+ disallows NaN values:
+ > Numeric values that cannot be represented in the grammar below (such
+ > as Infinity and NaN) are not permitted.
+ In case the parameter @a value is not a number, a JSON null value is
+ created instead.
+ @complexity Constant.
+ @liveexample{The example below shows the construction of several JSON
+ floating-point number values from compatible
+ types.,basic_json__CompatibleNumberFloatType}
+ @sa basic_json(const number_float_t)
+ */
+ template::value and
+ std::is_floating_point::value>::type
+ >
+ basic_json( const CompatibleNumberFloatType value ) noexcept
+ : basic_json( number_float_t( value ) )
+ {}
+
+ /*!
+ @brief create a container (array or object) from an initializer list
+ Creates a JSON value of type array or object from the passed initializer
+ list @a init. In case @a type_deduction is `true` (default), the type of
+ the JSON value to be created is deducted from the initializer list @a init
+ according to the following rules:
+ 1. If the list is empty, an empty JSON object value `{}` is created.
+ 2. If the list consists of pairs whose first element is a string, a JSON
+ object value is created where the first elements of the pairs are treated
+ as keys and the second elements are as values.
+ 3. In all other cases, an array is created.
+ The rules aim to create the best fit between a C++ initializer list and
+ JSON values. The ratioinale is as follows:
+ 1. The empty initializer list is written as `{}` which is exactly an empty
+ JSON object.
+ 2. C++ has now way of describing mapped types other than to list a list of
+ pairs. As JSON requires that keys must be of type string, rule 2 is the
+ weakest constraint one can pose on initializer lists to interpret them as
+ an object.
+ 3. In all other cases, the initializer list could not be interpreted as
+ JSON object type, so interpreting it as JSON array type is safe.
+ With the rules described above, the following JSON values cannot be
+ expressed by an initializer list:
+ - the empty array (`[]`): use @ref array(std::initializer_list)
+ with an empty initializer list in this case
+ - arrays whose elements satisfy rule 2: use @ref
+ array(std::initializer_list) with the same initializer list
+ in this case
+ @note When used without parentheses around an empty initializer list, @ref
+ basic_json() is called instead of this function, yielding the JSON null
+ value.
+ @param[in] init initializer list with JSON values
+ @param[in] type_deduction internal parameter; when set to `true`, the type
+ of the JSON value is deducted from the initializer list @a init; when set
+ to `false`, the type provided via @a manual_type is forced. This mode is
+ used by the functions @ref array(std::initializer_list) and
+ @ref object(std::initializer_list).
+ @param[in] manual_type internal parameter; when @a type_deduction is set to
+ `false`, the created JSON value will use the provided type (only @ref
+ value_t::array and @ref value_t::object are valid); when @a type_deduction
+ is set to `true`, this parameter has no effect
+ @throw std::domain_error if @a type_deduction is `false`, @a manual_type is
+ `value_t::object`, but @a init contains an element which is not a pair
+ whose first element is a string
+ @complexity Linear in the size of the initializer list @a init.
+ @liveexample{The example below shows how JSON values are created from
+ initializer lists,basic_json__list_init_t}
+ @sa basic_json array(std::initializer_list) - create a JSON
+ array value from an initializer list
+ @sa basic_json object(std::initializer_list) - create a JSON
+ object value from an initializer list
+ */
+ basic_json( std::initializer_list init,
+ bool type_deduction = true,
+ value_t manual_type = value_t::array )
+ {
+ // the initializer list could describe an object
+ bool is_object = true;
+
+ // check if each element is an array with two elements whose first element
+ // is a string
+ for ( const auto& element : init )
+ {
+ if ( element.m_type != value_t::array or element.size() != 2
+ or element[0].m_type != value_t::string )
+ {
+ // we found an element that makes it impossible to use the
+ // initializer list as object
+ is_object = false;
break;
}
}
- }
- /// constructor for strings
- json_value(const string_t& value)
- {
- string = create(value);
- }
-
- /// constructor for objects
- json_value(const object_t& value)
- {
- object = create(value);
- }
-
- /// constructor for arrays
- json_value(const array_t& value)
- {
- array = create(value);
- }
- };
-
-
- public:
- //////////////////////////
- // JSON parser callback //
- //////////////////////////
-
- /*!
- @brief JSON callback events
-
- This enumeration lists the parser events that can trigger calling a
- callback function of type @ref parser_callback_t during parsing.
- */
- enum class parse_event_t : uint8_t
- {
- /// the parser read `{` and started to process a JSON object
- object_start,
- /// the parser read `}` and finished processing a JSON object
- object_end,
- /// the parser read `[` and started to process a JSON array
- array_start,
- /// the parser read `]` and finished processing a JSON array
- array_end,
- /// the parser read a key of a value in an object
- key,
- /// the parser finished reading a JSON value
- value
- };
-
- /*!
- @brief per-element parser callback type
-
- With a parser callback function, the result of parsing a JSON text can be
- influenced. When passed to @ref parse(std::istream&, parser_callback_t) or
- @ref parse(const string_t&, parser_callback_t), it is called on certain
- events (passed as @ref parse_event_t via parameter @a event) with a set
- recursion depth @a depth and context JSON value @a parsed. The return value
- of the callback function is a boolean indicating whether the element that
- emitted the callback shall be kept or not.
-
- We distinguish six scenarios (determined by the event type) in which the
- callback function can be called. The following table describes the values
- of the parameters @a depth, @a event, and @a parsed.
-
- parameter @a event | description | parameter @a depth | parameter @a parsed
- ------------------ | ----------- | ------------------ | -------------------
- 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
- 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
- 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
- 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
- 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
- parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
-
- Discarding a value (i.e., returning `false`) has different effects depending on the
- context in which function was called:
-
- - Discarded values in structured types are skipped. That is, the parser
- will behave as if the discarded value was never read.
- - In case a value outside a structured type is skipped, it is replaced with
- `null`. This case happens if the top-level element is skipped.
-
- @param[in] depth the depth of the recursion during parsing
-
- @param[in] event an event of type parse_event_t indicating the context in
- the callback function has been called
-
- @param[in,out] parsed the current intermediate parse result; note that
- writing to this value has no effect for parse_event_t::key events
-
- @return Whether the JSON value which called the function during parsing
- should be kept (`true`) or not (`false`). In the latter case, it is either
- skipped completely or replaced by an empty discarded object.
-
- @sa @ref parse(std::istream&, parser_callback_t) or
- @ref parse(const string_t&, parser_callback_t) for examples
- */
- using parser_callback_t = std::function;
-
-
- //////////////////
- // constructors //
- //////////////////
-
- /*!
- @brief create an empty value with a given type
-
- Create an empty JSON value with a given type. The value will be default
- initialized with an empty value which depends on the type:
-
- Value type | initial value
- ----------- | -------------
- null | `null`
- boolean | `false`
- string | `""`
- number | `0`
- object | `{}`
- array | `[]`
-
- @param[in] value the type of the value to create
-
- @complexity Constant.
-
- @throw std::bad_alloc if allocation for object, array, or string value
- fails
-
- @liveexample{The following code shows the constructor for different @ref
- value_t values,basic_json__value_t}
- */
- basic_json(const value_t value)
- : m_type(value), m_value(value)
- {}
-
- /*!
- @brief create a null object (implicitly)
-
- Create a `null` JSON value. This is the implicit version of the `null`
- value constructor as it takes no parameters.
-
- @complexity Constant.
-
- @requirement This function satisfies the Container requirements:
- - The complexity is constant.
- - As postcondition, it holds: `basic_json().empty() == true`.
-
- @liveexample{The following code shows the constructor for a `null` JSON
- value.,basic_json}
-
- @sa basic_json(std::nullptr_t)
- */
- basic_json() noexcept = default;
-
- /*!
- @brief create a null object (explicitly)
-
- Create a `null` JSON value. This is the explicitly version of the `null`
- value constructor as it takes a null pointer as parameter. It allows to
- create `null` values by explicitly assigning a @c nullptr to a JSON value.
- The passed null pointer itself is not read - it is only used to choose the
- right constructor.
-
- @complexity Constant.
-
- @liveexample{The following code shows the constructor with null pointer
- parameter.,basic_json__nullptr_t}
-
- @sa basic_json()
- */
- basic_json(std::nullptr_t) noexcept
- : basic_json(value_t::null)
- {}
-
- /*!
- @brief create an object (explicit)
-
- Create an object JSON value with a given content.
-
- @param[in] value a value for the object
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for object value fails
-
- @liveexample{The following code shows the constructor with an @ref object_t
- parameter.,basic_json__object_t}
-
- @sa basic_json(const CompatibleObjectType&)
- */
- basic_json(const object_t& value)
- : m_type(value_t::object), m_value(value)
- {}
-
- /*!
- @brief create an object (implicit)
-
- Create an object JSON value with a given content. This constructor allows
- any type that can be used to construct values of type @ref object_t.
- Examples include the types `std::map` and `std::unordered_map`.
-
- @tparam CompatibleObjectType an object type whose `key_type` and
- `value_type` is compatible to @ref object_t
-
- @param[in] value a value for the object
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for object value fails
-
- @liveexample{The following code shows the constructor with several
- compatible object type parameters.,basic_json__CompatibleObjectType}
-
- @sa basic_json(const object_t&)
- */
- template ::value and
- std::is_constructible::value, int>::type
- = 0>
- basic_json(const CompatibleObjectType& value)
- : m_type(value_t::object)
- {
- using std::begin;
- using std::end;
- m_value.object = create(begin(value), end(value));
- }
-
- /*!
- @brief create an array (explicit)
-
- Create an array JSON value with a given content.
-
- @param[in] value a value for the array
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for array value fails
-
- @liveexample{The following code shows the constructor with an @ref array_t
- parameter.,basic_json__array_t}
-
- @sa basic_json(const CompatibleArrayType&)
- */
- basic_json(const array_t& value)
- : m_type(value_t::array), m_value(value)
- {}
-
- /*!
- @brief create an array (implicit)
-
- Create an array JSON value with a given content. This constructor allows
- any type that can be used to construct values of type @ref array_t.
- Examples include the types `std::vector`, `std::list`, and `std::set`.
-
- @tparam CompatibleArrayType an object type whose `value_type` is compatible
- to @ref array_t
-
- @param[in] value a value for the array
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for array value fails
-
- @liveexample{The following code shows the constructor with several
- compatible array type parameters.,basic_json__CompatibleArrayType}
-
- @sa basic_json(const array_t&)
- */
- template ::value and
- not std::is_same::value and
- not std::is_same::value and
- not std::is_same::value and
- not std::is_same::value and
- not std::is_same::value and
- std::is_constructible::value, int>::type
- = 0>
- basic_json(const CompatibleArrayType& value)
- : m_type(value_t::array)
- {
- using std::begin;
- using std::end;
- m_value.array = create(begin(value), end(value));
- }
-
- /*!
- @brief create a string (explicit)
-
- Create an string JSON value with a given content.
-
- @param[in] value a value for the string
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for string value fails
-
- @liveexample{The following code shows the constructor with an @ref string_t
- parameter.,basic_json__string_t}
-
- @sa basic_json(const typename string_t::value_type*)
- @sa basic_json(const CompatibleStringType&)
- */
- basic_json(const string_t& value)
- : m_type(value_t::string), m_value(value)
- {}
-
- /*!
- @brief create a string (explicit)
-
- Create a string JSON value with a given content.
-
- @param[in] value a literal value for the string
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for string value fails
-
- @liveexample{The following code shows the constructor with string literal
- parameter.,basic_json__string_t_value_type}
-
- @sa basic_json(const string_t&)
- @sa basic_json(const CompatibleStringType&)
- */
- basic_json(const typename string_t::value_type* value)
- : basic_json(string_t(value))
- {}
-
- /*!
- @brief create a string (implicit)
-
- Create a string JSON value with a given content.
-
- @param[in] value a value for the string
-
- @tparam CompatibleStringType an string type which is compatible to @ref
- string_t
-
- @complexity Linear in the size of the passed @a value.
-
- @throw std::bad_alloc if allocation for string value fails
-
- @liveexample{The following code shows the construction of a string value
- from a compatible type.,basic_json__CompatibleStringType}
-
- @sa basic_json(const string_t&)
- */
- template ::value, int>::type
- = 0>
- basic_json(const CompatibleStringType& value)
- : basic_json(string_t(value))
- {}
-
- /*!
- @brief create a boolean (explicit)
-
- Creates a JSON boolean type from a given value.
-
- @param[in] value a boolean value to store
-
- @complexity Constant.
-
- @liveexample{The example below demonstrates boolean
- values.,basic_json__boolean_t}
- */
- basic_json(boolean_t value)
- : m_type(value_t::boolean), m_value(value)
- {}
-
- /*!
- @brief create an integer number (explicit)
-
- Create an interger number JSON value with a given content.
-
- @tparam T helper type to compare number_integer_t and int (not visible in)
- the interface.
-
- @param[in] value an integer to create a JSON number from
-
- @note This constructor would have the same signature as @ref
- basic_json(const int value), so we need to switch this one off in case
- number_integer_t is the same as int. This is done via the helper type @a T.
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of a JSON integer
- number value.,basic_json__number_integer_t}
-
- @sa basic_json(const int)
- */
- template::value)
- and std::is_same::value
- , int>::type = 0>
- basic_json(const number_integer_t value)
- : m_type(value_t::number_integer), m_value(value)
- {}
-
- /*!
- @brief create an integer number from an enum type (explicit)
-
- Create an integer number JSON value with a given content.
-
- @param[in] value an integer to create a JSON number from
-
- @note This constructor allows to pass enums directly to a constructor. As
- C++ has no way of specifying the type of an anonymous enum explicitly, we
- can only rely on the fact that such values implicitly convert to int. As
- int may already be the same type of number_integer_t, we may need to switch
- off the constructor @ref basic_json(const number_integer_t).
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of a JSON integer
- number value from an anonymous enum.,basic_json__const_int}
-
- @sa basic_json(const number_integer_t)
- */
- basic_json(const int value)
- : m_type(value_t::number_integer),
- m_value(static_cast(value))
- {}
-
- /*!
- @brief create an integer number (implicit)
-
- Create an integer number JSON value with a given content. This constructor
- allows any type that can be used to construct values of type @ref
- number_integer_t. Examples may include the types `int`, `int32_t`, or
- `short`.
-
- @tparam CompatibleNumberIntegerType an integer type which is compatible to
- @ref number_integer_t.
-
- @param[in] value an integer to create a JSON number from
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of several JSON
- integer number values from compatible
- types.,basic_json__CompatibleIntegerNumberType}
-
- @sa basic_json(const number_integer_t)
- */
- template::value and
- std::numeric_limits::is_integer, CompatibleNumberIntegerType>::type
- = 0>
- basic_json(const CompatibleNumberIntegerType value) noexcept
- : m_type(value_t::number_integer),
- m_value(static_cast(value))
- {}
-
- /*!
- @brief create a floating-point number (explicit)
-
- Create a floating-point number JSON value with a given content.
-
- @param[in] value a floating-point value to create a JSON number from
-
- @note RFC 7159 , section 6
- disallows NaN values:
- > Numeric values that cannot be represented in the grammar below (such
- > as Infinity and NaN) are not permitted.
- In case the parameter @a value is not a number, a JSON null value is
- created instead.
-
- @complexity Constant.
-
- @liveexample{The following example creates several floating-point
- values.,basic_json__number_float_t}
- */
- basic_json(const number_float_t value)
- : m_type(value_t::number_float), m_value(value)
- {
- // replace infinity and NAN by null
- if (not std::isfinite(value))
- {
- m_type = value_t::null;
- m_value = json_value();
- }
- }
-
- /*!
- @brief create an floating-point number (implicit)
-
- Create an floating-point number JSON value with a given content. This
- constructor allows any type that can be used to construct values of type
- @ref number_float_t. Examples may include the types `float`.
-
- @tparam CompatibleNumberFloatType a floating-point type which is compatible
- to @ref number_float_t.
-
- @param[in] value a floating-point to create a JSON number from
-
- @note RFC 7159 , section 6
- disallows NaN values:
- > Numeric values that cannot be represented in the grammar below (such
- > as Infinity and NaN) are not permitted.
- In case the parameter @a value is not a number, a JSON null value is
- created instead.
-
- @complexity Constant.
-
- @liveexample{The example below shows the construction of several JSON
- floating-point number values from compatible
- types.,basic_json__CompatibleNumberFloatType}
-
- @sa basic_json(const number_float_t)
- */
- template::value and
- std::is_floating_point::value>::type
- >
- basic_json(const CompatibleNumberFloatType value) noexcept
- : basic_json(number_float_t(value))
- {}
-
- /*!
- @brief create a container (array or object) from an initializer list
-
- Creates a JSON value of type array or object from the passed initializer
- list @a init. In case @a type_deduction is `true` (default), the type of
- the JSON value to be created is deducted from the initializer list @a init
- according to the following rules:
-
- 1. If the list is empty, an empty JSON object value `{}` is created.
- 2. If the list consists of pairs whose first element is a string, a JSON
- object value is created where the first elements of the pairs are treated
- as keys and the second elements are as values.
- 3. In all other cases, an array is created.
-
- The rules aim to create the best fit between a C++ initializer list and
- JSON values. The ratioinale is as follows:
-
- 1. The empty initializer list is written as `{}` which is exactly an empty
- JSON object.
- 2. C++ has now way of describing mapped types other than to list a list of
- pairs. As JSON requires that keys must be of type string, rule 2 is the
- weakest constraint one can pose on initializer lists to interpret them as
- an object.
- 3. In all other cases, the initializer list could not be interpreted as
- JSON object type, so interpreting it as JSON array type is safe.
-
- With the rules described above, the following JSON values cannot be
- expressed by an initializer list:
-
- - the empty array (`[]`): use @ref array(std::initializer_list)
- with an empty initializer list in this case
- - arrays whose elements satisfy rule 2: use @ref
- array(std::initializer_list) with the same initializer list
- in this case
-
- @note When used without parentheses around an empty initializer list, @ref
- basic_json() is called instead of this function, yielding the JSON null
- value.
-
- @param[in] init initializer list with JSON values
-
- @param[in] type_deduction internal parameter; when set to `true`, the type
- of the JSON value is deducted from the initializer list @a init; when set
- to `false`, the type provided via @a manual_type is forced. This mode is
- used by the functions @ref array(std::initializer_list) and
- @ref object(std::initializer_list).
-
- @param[in] manual_type internal parameter; when @a type_deduction is set to
- `false`, the created JSON value will use the provided type (only @ref
- value_t::array and @ref value_t::object are valid); when @a type_deduction
- is set to `true`, this parameter has no effect
-
- @throw std::domain_error if @a type_deduction is `false`, @a manual_type is
- `value_t::object`, but @a init contains an element which is not a pair
- whose first element is a string
-
- @complexity Linear in the size of the initializer list @a init.
-
- @liveexample{The example below shows how JSON values are created from
- initializer lists,basic_json__list_init_t}
-
- @sa basic_json array(std::initializer_list) - create a JSON
- array value from an initializer list
- @sa basic_json object(std::initializer_list) - create a JSON
- object value from an initializer list
- */
- basic_json(std::initializer_list init,
- bool type_deduction = true,
- value_t manual_type = value_t::array)
- {
- // the initializer list could describe an object
- bool is_object = true;
-
- // check if each element is an array with two elements whose first element
- // is a string
- for (const auto& element : init)
- {
- if (element.m_type != value_t::array or element.size() != 2
- or element[0].m_type != value_t::string)
+ // adjust type if type deduction is not wanted
+ if ( not type_deduction )
{
- // we found an element that makes it impossible to use the
- // initializer list as object
- is_object = false;
- break;
+ // if array is wanted, do not create an object though possible
+ if ( manual_type == value_t::array )
+ {
+ is_object = false;
+ }
+
+ // if object is wanted but impossible, throw an exception
+ if ( manual_type == value_t::object and not is_object )
+ {
+ throw std::domain_error( "cannot create object from initializer list" );
+ }
+ }
+
+ if ( is_object )
+ {
+ // the initializer list is a list of pairs -> create object
+ m_type = value_t::object;
+ m_value = value_t::object;
+
+ for ( auto& element : init )
+ {
+ m_value.object->emplace( std::move( *( element[0].m_value.string ) ), std::move( element[1] ) );
+ }
+ }
+ else
+ {
+ // the initializer list describes an array -> create array
+ m_type = value_t::array;
+ m_value.array = create( std::move( init ) );
}
}
- // adjust type if type deduction is not wanted
- if (not type_deduction)
+ /*!
+ @brief explicitly create an array from an initializer list
+ Creates a JSON array value from a given initializer list. That is, given a
+ list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
+ initializer list is empty, the empty array `[]` is created.
+ @note This function is only needed to express two edge cases that cannot be
+ realized with the initializer list constructor (@ref
+ basic_json(std::initializer_list, bool, value_t)). These cases
+ are:
+ 1. creating an array whose elements are all pairs whose first element is a
+ string - in this case, the initializer list constructor would create an
+ object, taking the first elements as keys
+ 2. creating an empty array - passing the empty initializer list to the
+ initializer list constructor yields an empty object
+ @param[in] init initializer list with JSON values to create an array from
+ (optional)
+ @return JSON array value
+ @complexity Linear in the size of @a init.
+ @liveexample{The following code shows an example for the @ref array
+ function.,array}
+ @sa basic_json(std::initializer_list, bool, value_t) - create a
+ JSON value from an initializer list
+ @sa basic_json object(std::initializer_list) - create a JSON
+ object value from an initializer list
+ */
+ static basic_json array( std::initializer_list init =
+ std::initializer_list() )
{
- // if array is wanted, do not create an object though possible
- if (manual_type == value_t::array)
+ return basic_json( init, false, value_t::array );
+ }
+
+ /*!
+ @brief explicitly create an object from an initializer list
+ Creates a JSON object value from a given initializer list. The initializer
+ lists elements must be pairs, and their first elments must be strings. If
+ the initializer list is empty, the empty object `{}` is created.
+ @note This function is only added for symmetry reasons. In contrast to the
+ related function @ref basic_json array(std::initializer_list),
+ there are no cases which can only be expressed by this function. That is,
+ any initializer list @a init can also be passed to the initializer list
+ constructor @ref basic_json(std::initializer_list, bool,
+ value_t).
+ @param[in] init initializer list to create an object from (optional)
+ @return JSON object value
+ @throw std::domain_error if @a init is not a pair whose first elements are
+ strings; thrown by @ref basic_json(std::initializer_list, bool,
+ value_t)
+ @complexity Linear in the size of @a init.
+ @liveexample{The following code shows an example for the @ref object
+ function.,object}
+ @sa basic_json(std::initializer_list, bool, value_t) - create a
+ JSON value from an initializer list
+ @sa basic_json array(std::initializer_list) - create a JSON
+ array value from an initializer list
+ */
+ static basic_json object( std::initializer_list init =
+ std::initializer_list() )
+ {
+ return basic_json( init, false, value_t::object );
+ }
+
+ /*!
+ @brief construct an array with count copies of given value
+ Constructs a JSON array value by creating @a count copies of a passed
+ value. In case @a count is `0`, an empty array is created. As postcondition,
+ `std::distance(begin(),end()) == count` holds.
+ @param[in] count the number of JSON copies of @a value to create
+ @param[in] value the JSON value to copy
+ @complexity Linear in @a count.
+ @liveexample{The following code shows examples for the @ref
+ basic_json(size_type\, const basic_json&)
+ constructor.,basic_json__size_type_basic_json}
+ */
+ basic_json( size_type count, const basic_json& value )
+ : m_type( value_t::array )
+ {
+ m_value.array = create( count, value );
+ }
+
+ /*!
+ @brief construct a JSON container given an iterator range
+ Constructs the JSON value with the contents of the range `[first, last)`.
+ The semantics depends on the different types a JSON value can have:
+ - In case of primitive types (number, boolean, or string), @a first must
+ be `begin()` and @a last must be `end()`. In this case, the value is
+ copied. Otherwise, std::out_of_range is thrown.
+ - In case of structured types (array, object), the constructor behaves
+ as similar versions for `std::vector`.
+ - In case of a null type, std::domain_error is thrown.
+ @tparam InputIT an input iterator type (@ref iterator or @ref
+ const_iterator)
+ @param[in] first begin of the range to copy from (included)
+ @param[in] last end of the range to copy from (excluded)
+ @throw std::domain_error if iterators are not compatible; that is, do not
+ belong to the same JSON value
+ @throw std::out_of_range if iterators are for a primitive type (number,
+ boolean, or string) where an out of range error can be detected easily
+ @throw std::bad_alloc if allocation for object, array, or string fails
+ @throw std::domain_error if called with a null value
+ @complexity Linear in distance between @a first and @a last.
+ @liveexample{The example below shows several ways to create JSON values by
+ specifying a subrange with iterators.,basic_json__InputIt_InputIt}
+ */
+ template ::value or
+ std::is_same::value
+ , int>::type
+ = 0>
+ basic_json( InputIT first, InputIT last ) : m_type( first.m_object->m_type )
+ {
+ // make sure iterator fits the current value
+ if ( first.m_object != last.m_object )
{
- is_object = false;
+ throw std::domain_error( "iterators are not compatible" );
}
- // if object is wanted but impossible, throw an exception
- if (manual_type == value_t::object and not is_object)
+ // check if iterator range is complete for primitive values
+ switch ( m_type )
{
- throw std::domain_error("cannot create object from initializer list");
- }
- }
-
- if (is_object)
- {
- // the initializer list is a list of pairs -> create object
- m_type = value_t::object;
- m_value = value_t::object;
-
- for (auto& element : init)
- {
- m_value.object->emplace(std::move(*(element[0].m_value.string)), std::move(element[1]));
- }
- }
- else
- {
- // the initializer list describes an array -> create array
- m_type = value_t::array;
- m_value.array = create(std::move(init));
- }
- }
-
- /*!
- @brief explicitly create an array from an initializer list
-
- Creates a JSON array value from a given initializer list. That is, given a
- list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
- initializer list is empty, the empty array `[]` is created.
-
- @note This function is only needed to express two edge cases that cannot be
- realized with the initializer list constructor (@ref
- basic_json(std::initializer_list, bool, value_t)). These cases
- are:
- 1. creating an array whose elements are all pairs whose first element is a
- string - in this case, the initializer list constructor would create an
- object, taking the first elements as keys
- 2. creating an empty array - passing the empty initializer list to the
- initializer list constructor yields an empty object
-
- @param[in] init initializer list with JSON values to create an array from
- (optional)
-
- @return JSON array value
-
- @complexity Linear in the size of @a init.
-
- @liveexample{The following code shows an example for the @ref array
- function.,array}
-
- @sa basic_json(std::initializer_list, bool, value_t) - create a
- JSON value from an initializer list
- @sa basic_json object(std::initializer_list) - create a JSON
- object value from an initializer list
- */
- static basic_json array(std::initializer_list init =
- std::initializer_list())
- {
- return basic_json(init, false, value_t::array);
- }
-
- /*!
- @brief explicitly create an object from an initializer list
-
- Creates a JSON object value from a given initializer list. The initializer
- lists elements must be pairs, and their first elments must be strings. If
- the initializer list is empty, the empty object `{}` is created.
-
- @note This function is only added for symmetry reasons. In contrast to the
- related function @ref basic_json array(std::initializer_list),
- there are no cases which can only be expressed by this function. That is,
- any initializer list @a init can also be passed to the initializer list
- constructor @ref basic_json(std::initializer_list, bool,
- value_t).
-
- @param[in] init initializer list to create an object from (optional)
-
- @return JSON object value
-
- @throw std::domain_error if @a init is not a pair whose first elements are
- strings; thrown by @ref basic_json(std::initializer_list, bool,
- value_t)
-
- @complexity Linear in the size of @a init.
-
- @liveexample{The following code shows an example for the @ref object
- function.,object}
-
- @sa basic_json(std::initializer_list, bool, value_t) - create a
- JSON value from an initializer list
- @sa basic_json array(std::initializer_list) - create a JSON
- array value from an initializer list
- */
- static basic_json object(std::initializer_list init =
- std::initializer_list())
- {
- return basic_json(init, false, value_t::object);
- }
-
- /*!
- @brief construct an array with count copies of given value
-
- Constructs a JSON array value by creating @a count copies of a passed
- value. In case @a count is `0`, an empty array is created. As postcondition,
- `std::distance(begin(),end()) == count` holds.
-
- @param[in] count the number of JSON copies of @a value to create
- @param[in] value the JSON value to copy
-
- @complexity Linear in @a count.
-
- @liveexample{The following code shows examples for the @ref
- basic_json(size_type\, const basic_json&)
- constructor.,basic_json__size_type_basic_json}
- */
- basic_json(size_type count, const basic_json& value)
- : m_type(value_t::array)
- {
- m_value.array = create(count, value);
- }
-
- /*!
- @brief construct a JSON container given an iterator range
-
- Constructs the JSON value with the contents of the range `[first, last)`.
- The semantics depends on the different types a JSON value can have:
- - In case of primitive types (number, boolean, or string), @a first must
- be `begin()` and @a last must be `end()`. In this case, the value is
- copied. Otherwise, std::out_of_range is thrown.
- - In case of structured types (array, object), the constructor behaves
- as similar versions for `std::vector`.
- - In case of a null type, std::domain_error is thrown.
-
- @tparam InputIT an input iterator type (@ref iterator or @ref
- const_iterator)
-
- @param[in] first begin of the range to copy from (included)
- @param[in] last end of the range to copy from (excluded)
-
- @throw std::domain_error if iterators are not compatible; that is, do not
- belong to the same JSON value
- @throw std::out_of_range if iterators are for a primitive type (number,
- boolean, or string) where an out of range error can be detected easily
- @throw std::bad_alloc if allocation for object, array, or string fails
- @throw std::domain_error if called with a null value
-
- @complexity Linear in distance between @a first and @a last.
-
- @liveexample{The example below shows several ways to create JSON values by
- specifying a subrange with iterators.,basic_json__InputIt_InputIt}
- */
- template ::value or
- std::is_same::value
- , int>::type
- = 0>
- basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
- {
- // make sure iterator fits the current value
- if (first.m_object != last.m_object)
- {
- throw std::domain_error("iterators are not compatible");
- }
-
- // check if iterator range is complete for primitive values
- switch (m_type)
- {
case value_t::number_integer:
case value_t::number_float:
case value_t::boolean:
case value_t::string:
{
- if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
+ if ( not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end() )
{
- throw std::out_of_range("iterators out of range");
+ throw std::out_of_range( "iterators out of range" );
}
break;
}
@@ -1478,10 +1254,10 @@ class basic_json
{
break;
}
- }
+ }
- switch (m_type)
- {
+ switch ( m_type )
+ {
case value_t::number_integer:
{
m_value.number_integer = first.m_object->m_value.number_integer;
@@ -1508,187 +1284,168 @@ class basic_json
case value_t::object:
{
- m_value.object = create(first.m_it.object_iterator, last.m_it.object_iterator);
+ m_value.object = create( first.m_it.object_iterator, last.m_it.object_iterator );
break;
}
case value_t::array:
{
- m_value.array = create(first.m_it.array_iterator, last.m_it.array_iterator);
+ m_value.array = create( first.m_it.array_iterator, last.m_it.array_iterator );
break;
}
default:
{
- throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
+ throw std::domain_error( "cannot use construct with iterators from " + first.m_object->type_name() );
+ }
}
}
- }
- ///////////////////////////////////////
- // other constructors and destructor //
- ///////////////////////////////////////
+ ///////////////////////////////////////
+ // other constructors and destructor //
+ ///////////////////////////////////////
- /*!
- @brief copy constructor
-
- Creates a copy of a given JSON value.
-
- @param[in] other the JSON value to copy
-
- @complexity Linear in the size of @a other.
-
- @requirement This function satisfies the Container requirements:
- - The complexity is linear.
- - As postcondition, it holds: `other == basic_json(other)`.
-
- @throw std::bad_alloc if allocation for object, array, or string fails.
-
- @liveexample{The following code shows an example for the copy
- constructor.,basic_json__basic_json}
- */
- basic_json(const basic_json& other)
- : m_type(other.m_type)
- {
- switch (m_type)
+ /*!
+ @brief copy constructor
+ Creates a copy of a given JSON value.
+ @param[in] other the JSON value to copy
+ @complexity Linear in the size of @a other.
+ @requirement This function satisfies the Container requirements:
+ - The complexity is linear.
+ - As postcondition, it holds: `other == basic_json(other)`.
+ @throw std::bad_alloc if allocation for object, array, or string fails.
+ @liveexample{The following code shows an example for the copy
+ constructor.,basic_json__basic_json}
+ */
+ basic_json( const basic_json& other )
+ : m_type( other.m_type )
{
- case (value_t::null):
- case (value_t::discarded):
+ switch ( m_type )
+ {
+ case ( value_t::null ) :
+ case ( value_t::discarded ) :
{
break;
}
- case (value_t::object):
+ case ( value_t::object ) :
{
m_value = *other.m_value.object;
break;
}
- case (value_t::array):
+ case ( value_t::array ) :
{
m_value = *other.m_value.array;
break;
}
- case (value_t::string):
+ case ( value_t::string ) :
{
m_value = *other.m_value.string;
break;
}
- case (value_t::boolean):
+ case ( value_t::boolean ) :
{
m_value = other.m_value.boolean;
break;
}
- case (value_t::number_integer):
+ case ( value_t::number_integer ) :
{
m_value = other.m_value.number_integer;
break;
}
- case (value_t::number_float):
+ case ( value_t::number_float ) :
{
m_value = other.m_value.number_float;
break;
}
+ }
}
- }
- /*!
- @brief move constructor
-
- Move constructor. Constructs a JSON value with the contents of the given
- value @a other using move semantics. It "steals" the resources from @a
- other and leaves it as JSON null value.
-
- @param[in,out] other value to move to this object
-
- @post @a other is a JSON null value
-
- @complexity Constant.
-
- @liveexample{The code below shows the move constructor explicitly called
- via std::move.,basic_json__moveconstructor}
- */
- basic_json(basic_json&& other) noexcept
- : m_type(std::move(other.m_type)),
- m_value(std::move(other.m_value))
- {
- // invalidate payload
- other.m_type = value_t::null;
- other.m_value = {};
- }
-
- /*!
- @brief copy assignment
-
- Copy assignment operator. Copies a JSON value via the "copy and swap"
- strategy: It is expressed in terms of the copy constructor, destructor, and
- the swap() member function.
-
- @param[in] other value to copy from
-
- @complexity Linear.
-
- @requirement This function satisfies the Container requirements:
- - The complexity is linear.
-
- @liveexample{The code below shows and example for the copy assignment. It
- creates a copy of value `a` which is then swapped with `b`. Finally\, the
- copy of `a` (which is the null value after the swap) is
- destroyed.,basic_json__copyassignment}
- */
- reference& operator=(basic_json other) noexcept (
- std::is_nothrow_move_constructible::value and
- std::is_nothrow_move_assignable::value and
- std::is_nothrow_move_constructible::value and
- std::is_nothrow_move_assignable::value
- )
- {
- using std::swap;
- swap(m_type, other.m_type);
- swap(m_value, other.m_value);
- return *this;
- }
-
- /*!
- @brief destructor
-
- Destroys the JSON value and frees all allocated memory.
-
- @complexity Linear.
-
- @requirement This function satisfies the Container requirements:
- - The complexity is linear.
- - All stored elements are destroyed and all memory is freed.
- */
- ~basic_json()
- {
- switch (m_type)
+ /*!
+ @brief move constructor
+ Move constructor. Constructs a JSON value with the contents of the given
+ value @a other using move semantics. It "steals" the resources from @a
+ other and leaves it as JSON null value.
+ @param[in,out] other value to move to this object
+ @post @a other is a JSON null value
+ @complexity Constant.
+ @liveexample{The code below shows the move constructor explicitly called
+ via std::move.,basic_json__moveconstructor}
+ */
+ basic_json( basic_json&& other ) noexcept
+ : m_type( std::move( other.m_type ) ),
+ m_value( std::move( other.m_value ) )
{
- case (value_t::object):
+ // invalidate payload
+ other.m_type = value_t::null;
+ other.m_value = { };
+ }
+
+ /*!
+ @brief copy assignment
+ Copy assignment operator. Copies a JSON value via the "copy and swap"
+ strategy: It is expressed in terms of the copy constructor, destructor, and
+ the swap() member function.
+ @param[in] other value to copy from
+ @complexity Linear.
+ @requirement This function satisfies the Container requirements:
+ - The complexity is linear.
+ @liveexample{The code below shows and example for the copy assignment. It
+ creates a copy of value `a` which is then swapped with `b`. Finally\, the
+ copy of `a` (which is the null value after the swap) is
+ destroyed.,basic_json__copyassignment}
+ */
+ reference& operator=( basic_json other ) noexcept (
+ std::is_nothrow_move_constructible::value and
+ std::is_nothrow_move_assignable::value and
+ std::is_nothrow_move_constructible::value and
+ std::is_nothrow_move_assignable::value
+ )
+ {
+ using std::swap;
+ swap( m_type, other.m_type );
+ swap( m_value, other.m_value );
+ return *this;
+ }
+
+ /*!
+ @brief destructor
+ Destroys the JSON value and frees all allocated memory.
+ @complexity Linear.
+ @requirement This function satisfies the Container requirements:
+ - The complexity is linear.
+ - All stored elements are destroyed and all memory is freed.
+ */
+ ~basic_json()
+ {
+ switch ( m_type )
+ {
+ case ( value_t::object ) :
{
AllocatorType alloc;
- alloc.destroy(m_value.object);
- alloc.deallocate(m_value.object, 1);
+ alloc.destroy( m_value.object );
+ alloc.deallocate( m_value.object, 1 );
break;
}
- case (value_t::array):
+ case ( value_t::array ) :
{
AllocatorType alloc;
- alloc.destroy(m_value.array);
- alloc.deallocate(m_value.array, 1);
+ alloc.destroy( m_value.array );
+ alloc.deallocate( m_value.array, 1 );
break;
}
- case (value_t::string):
+ case ( value_t::string ) :
{
AllocatorType alloc;
- alloc.destroy(m_value.string);
- alloc.deallocate(m_value.string, 1);
+ alloc.destroy( m_value.string );
+ alloc.deallocate( m_value.string, 1 );
break;
}
@@ -1697,1203 +1454,1033 @@ class basic_json
// all other types need no specific destructor
break;
}
- }
- }
-
-
- public:
- ///////////////////////
- // object inspection //
- ///////////////////////
-
- /// @name object inspection
- /// @{
-
- /*!
- @brief serialization
-
- Serialization function for JSON values. The function tries to mimick
- Python's @p json.dumps() function, and currently supports its @p indent
- parameter.
-
- @param[in] indent if indent is nonnegative, then array elements and object
- members will be pretty-printed with that indent level. An indent level of 0
- will only insert newlines. -1 (the default) selects the most compact
- representation
-
- @return string containing the serialization of the JSON value
-
- @complexity Linear.
-
- @liveexample{The following example shows the effect of different @a indent
- parameters to the result of the serializaion.,dump}
-
- @see https://docs.python.org/2/library/json.html#json.dump
- */
- string_t dump(const int indent = -1) const
- {
- std::stringstream ss;
-
- if (indent >= 0)
- {
- dump(ss, true, static_cast(indent));
- }
- else
- {
- dump(ss, false, 0);
+ }
}
- return ss.str();
- }
- /*!
- @brief return the type of the JSON value (explicit)
-
- Return the type of the JSON value as a value from the @ref value_t
- enumeration.
-
- @return the type of the JSON value
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref type() for all JSON
- types.,type}
- */
- value_t type() const noexcept
- {
- return m_type;
- }
-
- /*!
- @brief return whether type is primitive
-
- This function returns true iff the JSON type is primitive (string, number,
- boolean, or null).
-
- @return `true` if type is primitive (string, number, boolean, or null),
- `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_primitive for all JSON
- types.,is_primitive}
- */
- bool is_primitive() const noexcept
- {
- return is_null() or is_string() or is_boolean() or is_number();
- }
-
- /*!
- @brief return whether type is structured
-
- This function returns true iff the JSON type is structured (array or
- object).
-
- @return `true` if type is structured (array or object), `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_structured for all JSON
- types.,is_structured}
- */
- bool is_structured() const noexcept
- {
- return is_array() or is_object();
- }
-
- /*!
- @brief return whether value is null
-
- This function returns true iff the JSON value is null.
-
- @return `true` if type is null, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_null for all JSON
- types.,is_null}
- */
- bool is_null() const noexcept
- {
- return m_type == value_t::null;
- }
-
- /*!
- @brief return whether value is a boolean
-
- This function returns true iff the JSON value is a boolean.
-
- @return `true` if type is boolean, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_boolean for all JSON
- types.,is_boolean}
- */
- bool is_boolean() const noexcept
- {
- return m_type == value_t::boolean;
- }
-
- /*!
- @brief return whether value is a number
-
- This function returns true iff the JSON value is a number. This includes
- both integer and floating-point values.
-
- @return `true` if type is number, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_number for all JSON
- types.,is_number}
- */
- bool is_number() const noexcept
- {
- return is_number_integer() or is_number_float();
- }
-
- /*!
- @brief return whether value is an integer number
-
- This function returns true iff the JSON value is an integer number. This
- excludes floating-point values.
-
- @return `true` if type is an integer number, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_number_integer for all
- JSON types.,is_number_integer}
- */
- bool is_number_integer() const noexcept
- {
- return m_type == value_t::number_integer;
- }
-
- /*!
- @brief return whether value is a floating-point number
-
- This function returns true iff the JSON value is a floating-point number.
- This excludes integer values.
-
- @return `true` if type is a floating-point number, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_number_float for all
- JSON types.,is_number_float}
- */
- bool is_number_float() const noexcept
- {
- return m_type == value_t::number_float;
- }
-
- /*!
- @brief return whether value is an object
-
- This function returns true iff the JSON value is an object.
-
- @return `true` if type is object, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_object for all JSON
- types.,is_object}
- */
- bool is_object() const noexcept
- {
- return m_type == value_t::object;
- }
-
- /*!
- @brief return whether value is an array
-
- This function returns true iff the JSON value is an array.
-
- @return `true` if type is array, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_array for all JSON
- types.,is_array}
- */
- bool is_array() const noexcept
- {
- return m_type == value_t::array;
- }
-
- /*!
- @brief return whether value is a string
-
- This function returns true iff the JSON value is a string.
-
- @return `true` if type is string, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_string for all JSON
- types.,is_string}
- */
- bool is_string() const noexcept
- {
- return m_type == value_t::string;
- }
-
- /*!
- @brief return whether value is discarded
-
- This function returns true iff the JSON value was discarded during parsing
- with a callback function (see @ref parser_callback_t).
-
- @note This function will always be `false` for JSON values after parsing.
- That is, discarded values can only occur during parsing, but will be
- removed when inside a structured value or replaced by null in other cases.
-
- @return `true` if type is discarded, `false` otherwise.
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies @ref is_discarded for all JSON
- types.,is_discarded}
- */
- bool is_discarded() const noexcept
- {
- return m_type == value_t::discarded;
- }
-
- /*!
- @brief return the type of the JSON value (implicit)
-
- Implicitly return the type of the JSON value as a value from the @ref
- value_t enumeration.
-
- @return the type of the JSON value
-
- @complexity Constant.
-
- @liveexample{The following code exemplifies the value_t operator for all
- JSON types.,operator__value_t}
- */
- operator value_t() const noexcept
- {
- return m_type;
- }
-
- /// @}
-
- private:
- //////////////////
- // value access //
- //////////////////
-
- /// get an object (explicit)
- template ::value and
- std::is_convertible::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- switch (m_type)
+ public:
+ ///////////////////////
+ // object inspection //
+ ///////////////////////
+
+ /// @name object inspection
+ /// @{
+
+ /*!
+ @brief serialization
+ Serialization function for JSON values. The function tries to mimick
+ Python's @p json.dumps() function, and currently supports its @p indent
+ parameter.
+ @param[in] indent if indent is nonnegative, then array elements and object
+ members will be pretty-printed with that indent level. An indent level of 0
+ will only insert newlines. -1 (the default) selects the most compact
+ representation
+ @return string containing the serialization of the JSON value
+ @complexity Linear.
+ @liveexample{The following example shows the effect of different @a indent
+ parameters to the result of the serializaion.,dump}
+ @see https://docs.python.org/2/library/json.html#json.dump
+ */
+ string_t dump( const int indent = -1 ) const
{
- case (value_t::object):
+ std::stringstream ss;
+
+ if ( indent >= 0 )
{
- return T(m_value.object->begin(), m_value.object->end());
+ dump( ss, true, static_cast( indent ) );
+ }
+ else
+ {
+ dump( ss, false, 0 );
+ }
+
+ return ss.str();
+ }
+
+ /*!
+ @brief return the type of the JSON value (explicit)
+ Return the type of the JSON value as a value from the @ref value_t
+ enumeration.
+ @return the type of the JSON value
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref type() for all JSON
+ types.,type}
+ */
+ value_t type() const noexcept
+ {
+ return m_type;
+ }
+
+ /*!
+ @brief return whether type is primitive
+ This function returns true iff the JSON type is primitive (string, number,
+ boolean, or null).
+ @return `true` if type is primitive (string, number, boolean, or null),
+ `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_primitive for all JSON
+ types.,is_primitive}
+ */
+ bool is_primitive() const noexcept
+ {
+ return is_null() or is_string() or is_boolean() or is_number();
+ }
+
+ /*!
+ @brief return whether type is structured
+ This function returns true iff the JSON type is structured (array or
+ object).
+ @return `true` if type is structured (array or object), `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_structured for all JSON
+ types.,is_structured}
+ */
+ bool is_structured() const noexcept
+ {
+ return is_array() or is_object();
+ }
+
+ /*!
+ @brief return whether value is null
+ This function returns true iff the JSON value is null.
+ @return `true` if type is null, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_null for all JSON
+ types.,is_null}
+ */
+ bool is_null() const noexcept
+ {
+ return m_type == value_t::null;
+ }
+
+ /*!
+ @brief return whether value is a boolean
+ This function returns true iff the JSON value is a boolean.
+ @return `true` if type is boolean, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_boolean for all JSON
+ types.,is_boolean}
+ */
+ bool is_boolean() const noexcept
+ {
+ return m_type == value_t::boolean;
+ }
+
+ /*!
+ @brief return whether value is a number
+ This function returns true iff the JSON value is a number. This includes
+ both integer and floating-point values.
+ @return `true` if type is number, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_number for all JSON
+ types.,is_number}
+ */
+ bool is_number() const noexcept
+ {
+ return is_number_integer() or is_number_float();
+ }
+
+ /*!
+ @brief return whether value is an integer number
+ This function returns true iff the JSON value is an integer number. This
+ excludes floating-point values.
+ @return `true` if type is an integer number, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_number_integer for all
+ JSON types.,is_number_integer}
+ */
+ bool is_number_integer() const noexcept
+ {
+ return m_type == value_t::number_integer;
+ }
+
+ /*!
+ @brief return whether value is a floating-point number
+ This function returns true iff the JSON value is a floating-point number.
+ This excludes integer values.
+ @return `true` if type is a floating-point number, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_number_float for all
+ JSON types.,is_number_float}
+ */
+ bool is_number_float() const noexcept
+ {
+ return m_type == value_t::number_float;
+ }
+
+ /*!
+ @brief return whether value is an object
+ This function returns true iff the JSON value is an object.
+ @return `true` if type is object, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_object for all JSON
+ types.,is_object}
+ */
+ bool is_object() const noexcept
+ {
+ return m_type == value_t::object;
+ }
+
+ /*!
+ @brief return whether value is an array
+ This function returns true iff the JSON value is an array.
+ @return `true` if type is array, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_array for all JSON
+ types.,is_array}
+ */
+ bool is_array() const noexcept
+ {
+ return m_type == value_t::array;
+ }
+
+ /*!
+ @brief return whether value is a string
+ This function returns true iff the JSON value is a string.
+ @return `true` if type is string, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_string for all JSON
+ types.,is_string}
+ */
+ bool is_string() const noexcept
+ {
+ return m_type == value_t::string;
+ }
+
+ /*!
+ @brief return whether value is discarded
+ This function returns true iff the JSON value was discarded during parsing
+ with a callback function (see @ref parser_callback_t).
+ @note This function will always be `false` for JSON values after parsing.
+ That is, discarded values can only occur during parsing, but will be
+ removed when inside a structured value or replaced by null in other cases.
+ @return `true` if type is discarded, `false` otherwise.
+ @complexity Constant.
+ @liveexample{The following code exemplifies @ref is_discarded for all JSON
+ types.,is_discarded}
+ */
+ bool is_discarded() const noexcept
+ {
+ return m_type == value_t::discarded;
+ }
+
+ /*!
+ @brief return the type of the JSON value (implicit)
+ Implicitly return the type of the JSON value as a value from the @ref
+ value_t enumeration.
+ @return the type of the JSON value
+ @complexity Constant.
+ @liveexample{The following code exemplifies the value_t operator for all
+ JSON types.,operator__value_t}
+ */
+ operator value_t() const noexcept
+ {
+ return m_type;
+ }
+
+ /// @}
+
+ private:
+ //////////////////
+ // value access //
+ //////////////////
+
+ /// get an object (explicit)
+ template ::value and
+ std::is_convertible::value
+ , int>::type = 0>
+ T get_impl( T* ) const
+ {
+ switch ( m_type )
+ {
+ case ( value_t::object ) :
+ {
+ return T( m_value.object->begin(), m_value.object->end() );
}
default:
{
- throw std::domain_error("type must be object, but is " + type_name());
+ throw std::domain_error( "type must be object, but is " + type_name() );
+ }
}
}
- }
- /// get an object (explicit)
- object_t get_impl(object_t*) const
- {
- switch (m_type)
+ /// get an object (explicit)
+ object_t get_impl( object_t* ) const
{
- case (value_t::object):
+ switch ( m_type )
{
- return *(m_value.object);
+ case ( value_t::object ) :
+ {
+ return *( m_value.object );
}
default:
{
- throw std::domain_error("type must be object, but is " + type_name());
+ throw std::domain_error( "type must be object, but is " + type_name() );
+ }
}
}
- }
- /// get an array (explicit)
- template ::value and
- not std::is_same::value and
- not std::is_arithmetic::value and
- not std::is_convertible::value and
- not has_mapped_type::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- switch (m_type)
+ /// get an array (explicit)
+ template ::value and
+ not std::is_same::value and
+ not std::is_arithmetic::value and
+ not std::is_convertible::value and
+ not has_mapped_type::value
+ , int>::type = 0>
+ T get_impl( T* ) const
{
- case (value_t::array):
+ switch ( m_type )
+ {
+ case ( value_t::array ) :
{
T to_vector;
- std::transform(m_value.array->begin(), m_value.array->end(),
- std::inserter(to_vector, to_vector.end()), [](basic_json i)
+ std::transform( m_value.array->begin(), m_value.array->end(),
+ std::inserter( to_vector, to_vector.end() ), [] ( basic_json i )
{
return i.get();
- });
+ } );
return to_vector;
}
default:
{
- throw std::domain_error("type must be array, but is " + type_name());
+ throw std::domain_error( "type must be array, but is " + type_name() );
+ }
}
}
- }
- /// get an array (explicit)
- template ::value and
- not std::is_same::value
- , int>::type = 0>
- std::vector get_impl(std::vector*) const
- {
- switch (m_type)
+ /// get an array (explicit)
+ template ::value and
+ not std::is_same::value
+ , int>::type = 0>
+ std::vector get_impl( std::vector* ) const
{
- case (value_t::array):
+ switch ( m_type )
+ {
+ case ( value_t::array ) :
{
std::vector to_vector;
- to_vector.reserve(m_value.array->size());
- std::transform(m_value.array->begin(), m_value.array->end(),
- std::inserter(to_vector, to_vector.end()), [](basic_json i)
+ to_vector.reserve( m_value.array->size() );
+ std::transform( m_value.array->begin(), m_value.array->end(),
+ std::inserter( to_vector, to_vector.end() ), [] ( basic_json i )
{
return i.get();
- });
+ } );
return to_vector;
}
default:
{
- throw std::domain_error("type must be array, but is " + type_name());
+ throw std::domain_error( "type must be array, but is " + type_name() );
+ }
}
}
- }
- /// get an array (explicit)
- template ::value and
- not has_mapped_type::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- switch (m_type)
+ /// get an array (explicit)
+ template ::value and
+ not has_mapped_type::value
+ , int>::type = 0>
+ T get_impl( T* ) const
{
- case (value_t::array):
+ switch ( m_type )
{
- return T(m_value.array->begin(), m_value.array->end());
+ case ( value_t::array ) :
+ {
+ return T( m_value.array->begin(), m_value.array->end() );
}
default:
{
- throw std::domain_error("type must be array, but is " + type_name());
+ throw std::domain_error( "type must be array, but is " + type_name() );
+ }
}
}
- }
- /// get an array (explicit)
- array_t get_impl(array_t*) const
- {
- switch (m_type)
+ /// get an array (explicit)
+ array_t get_impl( array_t* ) const
{
- case (value_t::array):
+ switch ( m_type )
{
- return *(m_value.array);
+ case ( value_t::array ) :
+ {
+ return *( m_value.array );
}
default:
{
- throw std::domain_error("type must be array, but is " + type_name());
+ throw std::domain_error( "type must be array, but is " + type_name() );
+ }
}
}
- }
- /// get a string (explicit)
- template ::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- switch (m_type)
+ /// get a string (explicit)
+ template ::value
+ , int>::type = 0>
+ T get_impl( T* ) const
{
- case (value_t::string):
+ switch ( m_type )
+ {
+ case ( value_t::string ) :
{
return *m_value.string;
}
default:
{
- throw std::domain_error("type must be string, but is " + type_name());
+ throw std::domain_error( "type must be string, but is " + type_name() );
+ }
}
}
- }
- /// get a number (explicit)
- template::value
- , int>::type = 0>
- T get_impl(T*) const
- {
- switch (m_type)
+ /// get a number (explicit)
+ template::value
+ , int>::type = 0>
+ T get_impl( T* ) const
{
- case (value_t::number_integer):
+ switch ( m_type )
{
- return static_cast(m_value.number_integer);
+ case ( value_t::number_integer ) :
+ {
+ return static_cast( m_value.number_integer );
}
- case (value_t::number_float):
+ case ( value_t::number_float ) :
{
- return static_cast(m_value.number_float);
+ return static_cast( m_value.number_float );
}
default:
{
- throw std::domain_error("type must be number, but is " + type_name());
+ throw std::domain_error( "type must be number, but is " + type_name() );
+ }
}
}
- }
- /// get a boolean (explicit)
- boolean_t get_impl(boolean_t*) const
- {
- switch (m_type)
+ /// get a boolean (explicit)
+ boolean_t get_impl( boolean_t* ) const
{
- case (value_t::boolean):
+ switch ( m_type )
+ {
+ case ( value_t::boolean ) :
{
return m_value.boolean;
}
default:
{
- throw std::domain_error("type must be boolean, but is " + type_name());
+ throw std::domain_error( "type must be boolean, but is " + type_name() );
+ }
}
}
- }
- /// get a pointer to the value (object)
- object_t* get_impl_ptr(object_t*) noexcept
- {
- return is_object() ? m_value.object : nullptr;
- }
-
- /// get a pointer to the value (object)
- const object_t* get_impl_ptr(const object_t*) const noexcept
- {
- return is_object() ? m_value.object : nullptr;
- }
-
- /// get a pointer to the value (array)
- array_t* get_impl_ptr(array_t*) noexcept
- {
- return is_array() ? m_value.array : nullptr;
- }
-
- /// get a pointer to the value (array)
- const array_t* get_impl_ptr(const array_t*) const noexcept
- {
- return is_array() ? m_value.array : nullptr;
- }
-
- /// get a pointer to the value (string)
- string_t* get_impl_ptr(string_t*) noexcept
- {
- return is_string() ? m_value.string : nullptr;
- }
-
- /// get a pointer to the value (string)
- const string_t* get_impl_ptr(const string_t*) const noexcept
- {
- return is_string() ? m_value.string : nullptr;
- }
-
- /// get a pointer to the value (boolean)
- boolean_t* get_impl_ptr(boolean_t*) noexcept
- {
- return is_boolean() ? &m_value.boolean : nullptr;
- }
-
- /// get a pointer to the value (boolean)
- const boolean_t* get_impl_ptr(const boolean_t*) const noexcept
- {
- return is_boolean() ? &m_value.boolean : nullptr;
- }
-
- /// get a pointer to the value (integer number)
- number_integer_t* get_impl_ptr(number_integer_t*) noexcept
- {
- return is_number_integer() ? &m_value.number_integer : nullptr;
- }
-
- /// get a pointer to the value (integer number)
- const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept
- {
- return is_number_integer() ? &m_value.number_integer : nullptr;
- }
-
- /// get a pointer to the value (floating-point number)
- number_float_t* get_impl_ptr(number_float_t*) noexcept
- {
- return is_number_float() ? &m_value.number_float : nullptr;
- }
-
- /// get a pointer to the value (floating-point number)
- const number_float_t* get_impl_ptr(const number_float_t*) const noexcept
- {
- return is_number_float() ? &m_value.number_float : nullptr;
- }
-
- public:
-
- /// @name value access
- /// @{
-
- /*!
- @brief get a value (explicit)
-
- Explicit type conversion between the JSON value and a compatible value.
-
- @tparam ValueType non-pointer type compatible to the JSON value, for
- instance `int` for JSON integer numbers, `bool` for JSON booleans, or
- `std::vector` types for JSON arrays
-
- @return copy of the JSON value, converted to type @a ValueType
-
- @throw std::domain_error in case passed type @a ValueType is incompatible
- to JSON
-
- @complexity Linear in the size of the JSON value.
-
- @liveexample{The example below shows serveral conversions from JSON values
- to other types. There a few things to note: (1) Floating-point numbers can
- be converted to integers\, (2) A JSON array can be converted to a standard
- `std::vector`\, (3) A JSON object can be converted to C++
- assiciative containers such as `std::unordered_map`.,get__ValueType_const}
-
- @internal
- The idea of using a casted null pointer to choose the correct
- implementation is from .
- @endinternal
-
- @sa @ref operator ValueType() const for implicit conversion
- @sa @ref get() for pointer-member access
- */
- template::value
- , int>::type = 0>
- ValueType get() const
- {
- return get_impl(static_cast(nullptr));
- }
-
- /*!
- @brief get a pointer value (explicit)
-
- Explicit pointer access to the internally stored JSON value. No copies are
- made.
-
- @warning Writing data to the pointee of the result yields an undefined
- state.
-
- @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
- object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
- number_float_t.
-
- @return pointer to the internally stored JSON value if the requested pointer
- type @a PointerType fits to the JSON value; `nullptr` otherwise
-
- @complexity Constant.
-
- @liveexample{The example below shows how pointers to internal values of a
- JSON value can be requested. Note that no type conversions are made and a
- `nullptr` is returned if the value and the requested pointer type does not
- match.,get__PointerType}
-
- @sa @ref get_ptr() for explicit pointer-member access
- */
- template::value
- , int>::type = 0>
- PointerType get() noexcept
- {
- // delegate the call to get_ptr
- return get_ptr();
- }
-
- /*!
- @brief get a pointer value (explicit)
- @copydoc get()
- */
- template::value
- , int>::type = 0>
- const PointerType get() const noexcept
- {
- // delegate the call to get_ptr
- return get_ptr();
- }
-
- /*!
- @brief get a pointer value (implicit)
-
- Implict pointer access to the internally stored JSON value. No copies are
- made.
-
- @warning Writing data to the pointee of the result yields an undefined
- state.
-
- @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
- object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
- number_float_t.
-
- @return pointer to the internally stored JSON value if the requested pointer
- type @a PointerType fits to the JSON value; `nullptr` otherwise
-
- @complexity Constant.
-
- @liveexample{The example below shows how pointers to internal values of a
- JSON value can be requested. Note that no type conversions are made and a
- `nullptr` is returned if the value and the requested pointer type does not
- match.,get_ptr}
- */
- template::value
- , int>::type = 0>
- PointerType get_ptr() noexcept
- {
- // delegate the call to get_impl_ptr<>()
- return get_impl_ptr(static_cast(nullptr));
- }
-
- /*!
- @brief get a pointer value (implicit)
- @copydoc get_ptr()
- */
- template::value
- and std::is_const::value
- , int>::type = 0>
- const PointerType get_ptr() const noexcept
- {
- // delegate the call to get_impl_ptr<>() const
- return get_impl_ptr(static_cast(nullptr));
- }
-
- /*!
- @brief get a value (implicit)
-
- Implict type conversion between the JSON value and a compatible value. The
- call is realized by calling @ref get() const.
-
- @tparam ValueType non-pointer type compatible to the JSON value, for
- instance `int` for JSON integer numbers, `bool` for JSON booleans, or
- `std::vector` types for JSON arrays
-
- @return copy of the JSON value, converted to type @a ValueType
-
- @throw std::domain_error in case passed type @a ValueType is incompatible
- to JSON, thrown by @ref get() const
-
- @complexity Linear in the size of the JSON value.
-
- @liveexample{The example below shows serveral conversions from JSON values
- to other types. There a few things to note: (1) Floating-point numbers can
- be converted to integers\, (2) A JSON array can be converted to a standard
- `std::vector`\, (3) A JSON object can be converted to C++
- assiciative containers such as `std::unordered_map`.,operator__ValueType}
- */
- template::value
- , int>::type = 0>
- operator ValueType() const
- {
- // delegate the call to get<>() const
- return get();
- }
-
- /// @}
-
-
- ////////////////////
- // element access //
- ////////////////////
-
- /// @name element access
- /// @{
-
- /*!
- @brief access specified array element with bounds checking
-
- Returns a reference to the element at specified location @a idx, with
- bounds checking.
-
- @param[in] idx index of the element to access
-
- @return reference to the element at index @a idx
-
- @throw std::domain_error if JSON is not an array
- @throw std::out_of_range if the index @a idx is out of range of the array;
- that is, `idx >= size()`
-
- @complexity Constant.
-
- @liveexample{The example below shows how array elements can be read and
- written using at.,at__size_type}
- */
- reference at(size_type idx)
- {
- // at only works for arrays
- if (m_type != value_t::array)
+ /// get a pointer to the value (object)
+ object_t* get_impl_ptr( object_t* ) noexcept
{
- throw std::domain_error("cannot use at() with " + type_name());
+ return is_object() ? m_value.object : nullptr;
}
- return m_value.array->at(idx);
- }
-
- /*!
- @brief access specified array element with bounds checking
-
- Returns a const reference to the element at specified location @a idx, with
- bounds checking.
-
- @param[in] idx index of the element to access
-
- @return const reference to the element at index @a idx
-
- @throw std::domain_error if JSON is not an array
- @throw std::out_of_range if the index @a idx is out of range of the array;
- that is, `idx >= size()`
-
- @complexity Constant.
-
- @liveexample{The example below shows how array elements can be read using
- at.,at__size_type_const}
- */
- const_reference at(size_type idx) const
- {
- // at only works for arrays
- if (m_type != value_t::array)
+ /// get a pointer to the value (object)
+ const object_t* get_impl_ptr( const object_t* ) const noexcept
{
- throw std::domain_error("cannot use at() with " + type_name());
+ return is_object() ? m_value.object : nullptr;
}
- return m_value.array->at(idx);
- }
-
- /*!
- @brief access specified object element with bounds checking
-
- Returns a reference to the element at with specified key @a key, with
- bounds checking.
-
- @param[in] key key of the element to access
-
- @return reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object
- @throw std::out_of_range if the key @a key is is not stored in the object;
- that is, `find(key) == end()`
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read and
- written using at.,at__object_t_key_type}
- */
- reference at(const typename object_t::key_type& key)
- {
- // at only works for objects
- if (m_type != value_t::object)
+ /// get a pointer to the value (array)
+ array_t* get_impl_ptr( array_t* ) noexcept
{
- throw std::domain_error("cannot use at() with " + type_name());
+ return is_array() ? m_value.array : nullptr;
}
- return m_value.object->at(key);
- }
-
- /*!
- @brief access specified object element with bounds checking
-
- Returns a const reference to the element at with specified key @a key, with
- bounds checking.
-
- @param[in] key key of the element to access
-
- @return const reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object
- @throw std::out_of_range if the key @a key is is not stored in the object;
- that is, `find(key) == end()`
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read using
- at.,at__object_t_key_type_const}
- */
- const_reference at(const typename object_t::key_type& key) const
- {
- // at only works for objects
- if (m_type != value_t::object)
+ /// get a pointer to the value (array)
+ const array_t* get_impl_ptr( const array_t* ) const noexcept
{
- throw std::domain_error("cannot use at() with " + type_name());
+ return is_array() ? m_value.array : nullptr;
}
- return m_value.object->at(key);
- }
-
- /*!
- @brief access specified array element
-
- Returns a reference to the element at specified location @a idx.
-
- @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
- then the array is silently filled up with `null` values to make `idx` a
- valid reference to the last stored element.
-
- @param[in] idx index of the element to access
-
- @return reference to the element at index @a idx
-
- @throw std::domain_error if JSON is not an array or null
-
- @complexity Constant if @a idx is in the range of the array. Otherwise
- linear in `idx - size()`.
-
- @liveexample{The example below shows how array elements can be read and
- written using [] operator. Note the addition of `null`
- values.,operatorarray__size_type}
- */
- reference operator[](size_type idx)
- {
- // implicitly convert null to object
- if (m_type == value_t::null)
+ /// get a pointer to the value (string)
+ string_t* get_impl_ptr( string_t* ) noexcept
{
- m_type = value_t::array;
- m_value.array = create();
+ return is_string() ? m_value.string : nullptr;
}
- // [] only works for arrays
- if (m_type != value_t::array)
+ /// get a pointer to the value (string)
+ const string_t* get_impl_ptr( const string_t* ) const noexcept
{
- throw std::domain_error("cannot use operator[] with " + type_name());
+ return is_string() ? m_value.string : nullptr;
}
- for (size_t i = m_value.array->size(); i <= idx; ++i)
+ /// get a pointer to the value (boolean)
+ boolean_t* get_impl_ptr( boolean_t* ) noexcept
{
- m_value.array->push_back(basic_json());
+ return is_boolean() ? &m_value.boolean : nullptr;
}
- return m_value.array->operator[](idx);
- }
-
- /*!
- @brief access specified array element
-
- Returns a const reference to the element at specified location @a idx.
-
- @param[in] idx index of the element to access
-
- @return const reference to the element at index @a idx
-
- @throw std::domain_error if JSON is not an array
-
- @complexity Constant.
-
- @liveexample{The example below shows how array elements can be read using
- the [] operator.,operatorarray__size_type_const}
- */
- const_reference operator[](size_type idx) const
- {
- // at only works for arrays
- if (m_type != value_t::array)
+ /// get a pointer to the value (boolean)
+ const boolean_t* get_impl_ptr( const boolean_t* ) const noexcept
{
- throw std::domain_error("cannot use operator[] with " + type_name());
+ return is_boolean() ? &m_value.boolean : nullptr;
}
- return m_value.array->operator[](idx);
- }
-
- /*!
- @brief access specified object element
-
- Returns a reference to the element at with specified key @a key.
-
- @note If @a key is not found in the object, then it is silently added to
- the object and filled with a `null` value to make `key` a valid reference.
- In case the value was `null` before, it is converted to an object.
-
- @param[in] key key of the element to access
-
- @return reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object or null
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read and
- written using the [] operator.,operatorarray__key_type}
- */
- reference operator[](const typename object_t::key_type& key)
- {
- // implicitly convert null to object
- if (m_type == value_t::null)
+ /// get a pointer to the value (integer number)
+ number_integer_t* get_impl_ptr( number_integer_t* ) noexcept
{
- m_type = value_t::object;
- m_value.object = create();
+ return is_number_integer() ? &m_value.number_integer : nullptr;
}
- // [] only works for objects
- if (m_type != value_t::object)
+ /// get a pointer to the value (integer number)
+ const number_integer_t* get_impl_ptr( const number_integer_t* ) const noexcept
{
- throw std::domain_error("cannot use operator[] with " + type_name());
+ return is_number_integer() ? &m_value.number_integer : nullptr;
}
- return m_value.object->operator[](key);
- }
-
- /*!
- @brief access specified object element
-
- Returns a reference to the element at with specified key @a key.
-
- @param[in] key key of the element to access
-
- @return reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object or null
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read using
- the [] operator.,operatorarray__key_type_const}
- */
- const_reference operator[](const typename object_t::key_type& key) const
- {
- // at only works for objects
- if (m_type != value_t::object)
+ /// get a pointer to the value (floating-point number)
+ number_float_t* get_impl_ptr( number_float_t* ) noexcept
{
- throw std::domain_error("cannot use operator[] with " + type_name());
+ return is_number_float() ? &m_value.number_float : nullptr;
}
- return m_value.object->operator[](key);
- }
-
- /*!
- @brief access specified object element
-
- Returns a reference to the element at with specified key @a key.
-
- @note If @a key is not found in the object, then it is silently added to
- the object and filled with a `null` value to make `key` a valid reference.
- In case the value was `null` before, it is converted to an object.
-
- @note This function is required for compatibility reasons with Clang.
-
- @param[in] key key of the element to access
-
- @return reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object or null
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read and
- written using the [] operator.,operatorarray__key_type}
- */
- template
- reference operator[](const T (&key)[n])
- {
- // implicitly convert null to object
- if (m_type == value_t::null)
+ /// get a pointer to the value (floating-point number)
+ const number_float_t* get_impl_ptr( const number_float_t* ) const noexcept
{
- m_type = value_t::object;
- m_value = value_t::object;
+ return is_number_float() ? &m_value.number_float : nullptr;
}
- // at only works for objects
- if (m_type != value_t::object)
+ public:
+
+ /// @name value access
+ /// @{
+
+ /*!
+ @brief get a value (explicit)
+ Explicit type conversion between the JSON value and a compatible value.
+ @tparam ValueType non-pointer type compatible to the JSON value, for
+ instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+ `std::vector` types for JSON arrays
+ @return copy of the JSON value, converted to type @a ValueType
+ @throw std::domain_error in case passed type @a ValueType is incompatible
+ to JSON
+ @complexity Linear in the size of the JSON value.
+ @liveexample{The example below shows serveral conversions from JSON values
+ to other types. There a few things to note: (1) Floating-point numbers can
+ be converted to integers\, (2) A JSON array can be converted to a standard
+ `std::vector`\, (3) A JSON object can be converted to C++
+ assiciative containers such as `std::unordered_map`.,get__ValueType_const}
+ @internal
+ The idea of using a casted null pointer to choose the correct
+ implementation is from .
+ @endinternal
+ @sa @ref operator ValueType() const for implicit conversion
+ @sa @ref get() for pointer-member access
+ */
+ template::value
+ , int>::type = 0>
+ ValueType get() const
{
- throw std::domain_error("cannot use operator[] with " + type_name());
+ return get_impl( static_cast( nullptr ) );
}
- return m_value.object->operator[](key);
- }
-
- /*!
- @brief access specified object element
-
- Returns a reference to the element at with specified key @a key.
-
- @note This function is required for compatibility reasons with Clang.
-
- @param[in] key key of the element to access
-
- @return reference to the element at key @a key
-
- @throw std::domain_error if JSON is not an object or null
-
- @complexity Logarithmic in the size of the container.
-
- @liveexample{The example below shows how object elements can be read using
- the [] operator.,operatorarray__key_type_const}
- */
- template
- const_reference operator[](const T (&key)[n]) const
- {
- // at only works for objects
- if (m_type != value_t::object)
+ /*!
+ @brief get a pointer value (explicit)
+ Explicit pointer access to the internally stored JSON value. No copies are
+ made.
+ @warning Writing data to the pointee of the result yields an undefined
+ state.
+ @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+ object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
+ number_float_t.
+ @return pointer to the internally stored JSON value if the requested pointer
+ type @a PointerType fits to the JSON value; `nullptr` otherwise
+ @complexity Constant.
+ @liveexample{The example below shows how pointers to internal values of a
+ JSON value can be requested. Note that no type conversions are made and a
+ `nullptr` is returned if the value and the requested pointer type does not
+ match.,get__PointerType}
+ @sa @ref get_ptr() for explicit pointer-member access
+ */
+ template::value
+ , int>::type = 0>
+ PointerType get() noexcept
{
- throw std::domain_error("cannot use operator[] with " + type_name());
+ // delegate the call to get_ptr
+ return get_ptr();
}
- return m_value.object->operator[](key);
- }
-
- /*!
- @brief access the first element
-
- Returns a reference to the first element in the container. For a JSON
- container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
-
- @return In case of a structured type (array or object), a reference to the
- first element is returned. In cast of number, string, or boolean values, a
- reference to the value is returned.
-
- @complexity Constant.
-
- @note Calling `front` on an empty container is undefined.
-
- @throw std::out_of_range when called on null value
-
- @liveexample{The following code shows an example for @ref front.,front}
- */
- reference front()
- {
- return *begin();
- }
-
- /*!
- @copydoc basic_json::front()
- */
- const_reference front() const
- {
- return *cbegin();
- }
-
- /*!
- @brief access the last element
-
- Returns a reference to the last element in the container. For a JSON
- container `c`, the expression `c.back()` is equivalent to `{ auto tmp =
- c.end(); --tmp; return *tmp; }`.
-
- @return In case of a structured type (array or object), a reference to the
- last element is returned. In cast of number, string, or boolean values, a
- reference to the value is returned.
-
- @complexity Constant.
-
- @note Calling `back` on an empty container is undefined.
-
- @throw std::out_of_range when called on null value.
-
- @liveexample{The following code shows an example for @ref back.,back}
- */
- reference back()
- {
- auto tmp = end();
- --tmp;
- return *tmp;
- }
-
- /*!
- @copydoc basic_json::back()
- */
- const_reference back() const
- {
- auto tmp = cend();
- --tmp;
- return *tmp;
- }
-
- /*!
- @brief remove element given an iterator
-
- Removes the element specified by iterator @a pos. Invalidates iterators and
- references at or after the point of the erase, including the end()
- iterator. The iterator @a pos must be valid and dereferenceable. Thus the
- end() iterator (which is valid, but is not dereferencable) cannot be used
- as a value for @a pos.
-
- If called on a primitive type other than null, the resulting JSON value
- will be `null`.
-
- @param[in] pos iterator to the element to remove
- @return Iterator following the last removed element. If the iterator @a pos
- refers to the last element, the end() iterator is returned.
-
- @tparam InteratorType an @ref iterator or @ref const_iterator
-
- @throw std::domain_error if called on a `null` value
- @throw std::domain_error if called on an iterator which does not belong to
- the current JSON value
- @throw std::out_of_range if called on a primitive type with invalid iterator
- (i.e., any iterator which is not end())
-
- @complexity The complexity depends on the type:
- - objects: amortized constant
- - arrays: linear in distance between pos and the end of the container
- - strings: linear in the length of the string
- - other types: constant
-
- @liveexample{The example shows the result of erase for different JSON
- types.,erase__IteratorType}
- */
- template ::value or
- std::is_same::value
- , int>::type
- = 0>
- InteratorType erase(InteratorType pos)
- {
- // make sure iterator fits the current value
- if (this != pos.m_object)
+ /*!
+ @brief get a pointer value (explicit)
+ @copydoc get()
+ */
+ template::value
+ , int>::type = 0>
+ const PointerType get() const noexcept
{
- throw std::domain_error("iterator does not fit current value");
+ // delegate the call to get_ptr
+ return get_ptr();
}
- InteratorType result = end();
-
- switch (m_type)
+ /*!
+ @brief get a pointer value (implicit)
+ Implict pointer access to the internally stored JSON value. No copies are
+ made.
+ @warning Writing data to the pointee of the result yields an undefined
+ state.
+ @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+ object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or @ref
+ number_float_t.
+ @return pointer to the internally stored JSON value if the requested pointer
+ type @a PointerType fits to the JSON value; `nullptr` otherwise
+ @complexity Constant.
+ @liveexample{The example below shows how pointers to internal values of a
+ JSON value can be requested. Note that no type conversions are made and a
+ `nullptr` is returned if the value and the requested pointer type does not
+ match.,get_ptr}
+ */
+ template::value
+ , int>::type = 0>
+ PointerType get_ptr() noexcept
{
+ // delegate the call to get_impl_ptr<>()
+ return get_impl_ptr( static_cast( nullptr ) );
+ }
+
+ /*!
+ @brief get a pointer value (implicit)
+ @copydoc get_ptr()
+ */
+ template::value
+ and std::is_const::value
+ , int>::type = 0>
+ const PointerType get_ptr() const noexcept
+ {
+ // delegate the call to get_impl_ptr<>() const
+ return get_impl_ptr( static_cast( nullptr ) );
+ }
+
+ /*!
+ @brief get a value (implicit)
+ Implict type conversion between the JSON value and a compatible value. The
+ call is realized by calling @ref get() const.
+ @tparam ValueType non-pointer type compatible to the JSON value, for
+ instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+ `std::vector` types for JSON arrays
+ @return copy of the JSON value, converted to type @a ValueType
+ @throw std::domain_error in case passed type @a ValueType is incompatible
+ to JSON, thrown by @ref get() const
+ @complexity Linear in the size of the JSON value.
+ @liveexample{The example below shows serveral conversions from JSON values
+ to other types. There a few things to note: (1) Floating-point numbers can
+ be converted to integers\, (2) A JSON array can be converted to a standard
+ `std::vector`\, (3) A JSON object can be converted to C++
+ assiciative containers such as `std::unordered_map`.,operator__ValueType}
+ */
+ template::value
+ , int>::type = 0>
+ operator ValueType() const
+ {
+ // delegate the call to get<>() const
+ return get();
+ }
+
+ /// @}
+
+
+ ////////////////////
+ // element access //
+ ////////////////////
+
+ /// @name element access
+ /// @{
+
+ /*!
+ @brief access specified array element with bounds checking
+ Returns a reference to the element at specified location @a idx, with
+ bounds checking.
+ @param[in] idx index of the element to access
+ @return reference to the element at index @a idx
+ @throw std::domain_error if JSON is not an array
+ @throw std::out_of_range if the index @a idx is out of range of the array;
+ that is, `idx >= size()`
+ @complexity Constant.
+ @liveexample{The example below shows how array elements can be read and
+ written using at.,at__size_type}
+ */
+ reference at( size_type idx )
+ {
+ // at only works for arrays
+ if ( m_type != value_t::array )
+ {
+ throw std::domain_error( "cannot use at() with " + type_name() );
+ }
+
+ return m_value.array->at( idx );
+ }
+
+ /*!
+ @brief access specified array element with bounds checking
+ Returns a const reference to the element at specified location @a idx, with
+ bounds checking.
+ @param[in] idx index of the element to access
+ @return const reference to the element at index @a idx
+ @throw std::domain_error if JSON is not an array
+ @throw std::out_of_range if the index @a idx is out of range of the array;
+ that is, `idx >= size()`
+ @complexity Constant.
+ @liveexample{The example below shows how array elements can be read using
+ at.,at__size_type_const}
+ */
+ const_reference at( size_type idx ) const
+ {
+ // at only works for arrays
+ if ( m_type != value_t::array )
+ {
+ throw std::domain_error( "cannot use at() with " + type_name() );
+ }
+
+ return m_value.array->at( idx );
+ }
+
+ /*!
+ @brief access specified object element with bounds checking
+ Returns a reference to the element at with specified key @a key, with
+ bounds checking.
+ @param[in] key key of the element to access
+ @return reference to the element at key @a key
+ @throw std::domain_error if JSON is not an object
+ @throw std::out_of_range if the key @a key is is not stored in the object;
+ that is, `find(key) == end()`
+ @complexity Logarithmic in the size of the container.
+ @liveexample{The example below shows how object elements can be read and
+ written using at.,at__object_t_key_type}
+ */
+ reference at( const typename object_t::key_type& key )
+ {
+ // at only works for objects
+ if ( m_type != value_t::object )
+ {
+ throw std::domain_error( "cannot use at() with " + type_name() );
+ }
+
+ return m_value.object->at( key );
+ }
+
+ /*!
+ @brief access specified object element with bounds checking
+ Returns a const reference to the element at with specified key @a key, with
+ bounds checking.
+ @param[in] key key of the element to access
+ @return const reference to the element at key @a key
+ @throw std::domain_error if JSON is not an object
+ @throw std::out_of_range if the key @a key is is not stored in the object;
+ that is, `find(key) == end()`
+ @complexity Logarithmic in the size of the container.
+ @liveexample{The example below shows how object elements can be read using
+ at.,at__object_t_key_type_const}
+ */
+ const_reference at( const typename object_t::key_type& key ) const
+ {
+ // at only works for objects
+ if ( m_type != value_t::object )
+ {
+ throw std::domain_error( "cannot use at() with " + type_name() );
+ }
+
+ return m_value.object->at( key );
+ }
+
+ /*!
+ @brief access specified array element
+ Returns a reference to the element at specified location @a idx.
+ @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
+ then the array is silently filled up with `null` values to make `idx` a
+ valid reference to the last stored element.
+ @param[in] idx index of the element to access
+ @return reference to the element at index @a idx
+ @throw std::domain_error if JSON is not an array or null
+ @complexity Constant if @a idx is in the range of the array. Otherwise
+ linear in `idx - size()`.
+ @liveexample{The example below shows how array elements can be read and
+ written using [] operator. Note the addition of `null`
+ values.,operatorarray__size_type}
+ */
+ reference operator[]( size_type idx )
+ {
+ // implicitly convert null to object
+ if ( m_type == value_t::null )
+ {
+ m_type = value_t::array;
+ m_value.array = create