Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitHub Actions <action@github.com>2020-06-28 14:43:45 +0300
committerGitHub Actions <action@github.com>2020-06-28 14:43:45 +0300
commitd999f29d0ac659887cfed67cfbde14f671b3254b (patch)
tree2bbc1eea1729f9a8aa775a09d1d9948d2e50b17c
parent87a5a56e6acd268cc8018c0e9dd6ae23fed276f9 (diff)
Upstream release v2.0.3v2.0.3
-rw-r--r--README.md2
-rw-r--r--include/nlohmann/json.hpp702
2 files changed, 430 insertions, 274 deletions
diff --git a/README.md b/README.md
index 97cc275..749c310 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ include(FetchContent)
FetchContent_Declare(json
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohman_json
- GIT_TAG v2.0.2)
+ GIT_TAG v2.0.3)
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index 878fb89..25a9dbc 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 2.0.2
+| | |__ | | | | | | version 2.0.3
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -37,6 +37,7 @@ SOFTWARE.
#include <cstddef>
#include <cstdint>
#include <cstdlib>
+#include <cstring>
#include <functional>
#include <initializer_list>
#include <iomanip>
@@ -73,6 +74,15 @@ SOFTWARE.
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+// allow for portable deprecation warnings
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+ #define JSON_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+ #define JSON_DEPRECATED __declspec(deprecated)
+#else
+ #define JSON_DEPRECATED
+#endif
+
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@@ -950,7 +960,7 @@ class basic_json
With a parser callback function, the result of parsing a JSON text can be
influenced. When passed to @ref parse(std::istream&, const
- parser_callback_t) or @ref parse(const string_t&, const parser_callback_t),
+ parser_callback_t) or @ref parse(const char*, const 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
@@ -993,7 +1003,7 @@ class basic_json
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
+ @ref parse(const char*, parser_callback_t) for examples
@since version 1.0.0
*/
@@ -1057,40 +1067,10 @@ class basic_json
}
/*!
- @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.
-
- @note The class invariant is satisfied, because it poses no requirements
- for null values.
-
- @complexity Constant.
-
- @exceptionsafety No-throw guarantee: this constructor never throws
- exceptions.
-
- @requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/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 @ref basic_json(std::nullptr_t) -- create a `null` value
-
- @since version 1.0.0
- */
- basic_json() = default;
-
- /*!
- @brief create a null object (explicitly)
+ @brief create a null object
- 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 `nullptr` to a JSON value.
+ Create a `null` JSON value. It either takes a null pointer as parameter
+ (explicitly creating `null`) or no parameter (implicitly creating `null`).
The passed null pointer itself is not read -- it is only used to choose
the right constructor.
@@ -1099,15 +1079,12 @@ class basic_json
@exceptionsafety No-throw guarantee: this constructor never throws
exceptions.
- @liveexample{The following code shows the constructor with null pointer
- parameter.,basic_json__nullptr_t}
-
- @sa @ref basic_json() -- default constructor (implicitly creating a `null`
- value)
+ @liveexample{The following code shows the constructor with and without a
+ null pointer parameter.,basic_json__nullptr_t}
@since version 1.0.0
*/
- basic_json(std::nullptr_t) noexcept
+ basic_json(std::nullptr_t = nullptr) noexcept
: basic_json(value_t::null)
{
assert_invariant();
@@ -1164,11 +1141,9 @@ class basic_json
@since version 1.0.0
*/
- template <class CompatibleObjectType, typename
- std::enable_if<
- std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
- std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
- = 0>
+ template<class CompatibleObjectType, typename std::enable_if<
+ std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
+ std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
basic_json(const CompatibleObjectType& val)
: m_type(value_t::object)
{
@@ -1229,16 +1204,14 @@ class basic_json
@since version 1.0.0
*/
- template <class CompatibleArrayType, typename
- std::enable_if<
- not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
- not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
- not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
- not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
- not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
- not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
- std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
- = 0>
+ template<class CompatibleArrayType, typename std::enable_if<
+ not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
+ not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
+ not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
+ not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
+ not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
+ not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
+ std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
basic_json(const CompatibleArrayType& val)
: m_type(value_t::array)
{
@@ -1324,10 +1297,8 @@ class basic_json
@since version 1.0.0
*/
- template <class CompatibleStringType, typename
- std::enable_if<
- std::is_constructible<string_t, CompatibleStringType>::value, int>::type
- = 0>
+ template<class CompatibleStringType, typename std::enable_if<
+ std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
basic_json(const CompatibleStringType& val)
: basic_json(string_t(val))
{
@@ -1377,12 +1348,9 @@ class basic_json
@since version 1.0.0
*/
- template<typename T,
- typename std::enable_if<
- not (std::is_same<T, int>::value)
- and std::is_same<T, number_integer_t>::value
- , int>::type
- = 0>
+ template<typename T, typename std::enable_if<
+ not (std::is_same<T, int>::value) and
+ std::is_same<T, number_integer_t>::value, int>::type = 0>
basic_json(const number_integer_t val) noexcept
: m_type(value_t::number_integer), m_value(val)
{
@@ -1446,13 +1414,11 @@ class basic_json
@since version 1.0.0
*/
- template<typename CompatibleNumberIntegerType, typename
- std::enable_if<
+ template<typename CompatibleNumberIntegerType, typename std::enable_if<
std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
- CompatibleNumberIntegerType>::type
- = 0>
+ CompatibleNumberIntegerType>::type = 0>
basic_json(const CompatibleNumberIntegerType val) noexcept
: m_type(value_t::number_integer),
m_value(static_cast<number_integer_t>(val))
@@ -1477,12 +1443,9 @@ class basic_json
@since version 2.0.0
*/
- template<typename T,
- typename std::enable_if<
- not (std::is_same<T, int>::value)
- and std::is_same<T, number_unsigned_t>::value
- , int>::type
- = 0>
+ template<typename T, typename std::enable_if<
+ not (std::is_same<T, int>::value) and
+ std::is_same<T, number_unsigned_t>::value, int>::type = 0>
basic_json(const number_unsigned_t val) noexcept
: m_type(value_t::number_unsigned), m_value(val)
{
@@ -1509,13 +1472,11 @@ class basic_json
@since version 2.0.0
*/
- template <typename CompatibleNumberUnsignedType, typename
- std::enable_if <
- std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
- std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
- not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
- CompatibleNumberUnsignedType>::type
- = 0>
+ template<typename CompatibleNumberUnsignedType, typename std::enable_if <
+ std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
+ std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
+ not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
+ CompatibleNumberUnsignedType>::type = 0>
basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val))
@@ -1591,11 +1552,9 @@ class basic_json
@since version 1.0.0
*/
- template<typename CompatibleNumberFloatType, typename = typename
- std::enable_if<
+ template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
- std::is_floating_point<CompatibleNumberFloatType>::value>::type
- >
+ std::is_floating_point<CompatibleNumberFloatType>::value>::type>
basic_json(const CompatibleNumberFloatType val) noexcept
: basic_json(number_float_t(val))
{
@@ -1843,7 +1802,8 @@ class basic_json
@param[in] first begin of the range to copy from (included)
@param[in] last end of the range to copy from (excluded)
- @pre Iterators @a first and @a last must be initialized.
+ @pre Iterators @a first and @a last must be initialized. **This
+ precondition is enforced with an assertion.**
@throw std::domain_error if iterators are not compatible; that is, do not
belong to the same JSON value; example: `"iterators are not compatible"`
@@ -1861,12 +1821,9 @@ class basic_json
@since version 1.0.0
*/
- template <class InputIT, typename
- std::enable_if<
- std::is_same<InputIT, typename basic_json_t::iterator>::value or
- std::is_same<InputIT, typename basic_json_t::const_iterator>::value
- , int>::type
- = 0>
+ template<class InputIT, typename std::enable_if<
+ std::is_same<InputIT, typename basic_json_t::iterator>::value or
+ std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
basic_json(InputIT first, InputIT last)
{
assert(first.m_object != nullptr);
@@ -1970,12 +1927,21 @@ class basic_json
@note A UTF-8 byte order mark is silently ignored.
+ @deprecated This constructor is deprecated and will be removed in version
+ 3.0.0 to unify the interface of the library. Deserialization will be
+ done by stream operators or by calling one of the `parse` functions,
+ e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls
+ like `json j(i);` for an input stream @a i need to be replaced by
+ `json j = json::parse(i);`. See the example below.
+
@liveexample{The example below demonstrates constructing a JSON value from
a `std::stringstream` with and without callback
function.,basic_json__istream}
- @since version 2.0.0
+ @since version 2.0.0, deprecated in version 2.0.3, to be removed in
+ version 3.0.0
*/
+ JSON_DEPRECATED
explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
{
*this = parser(i, cb).parse();
@@ -2231,7 +2197,8 @@ class basic_json
{
std::stringstream ss;
// fix locale problems
- ss.imbue(std::locale(std::locale(), new DecimalSeparator));
+ const static std::locale loc(std::locale(), new DecimalSeparator);
+ ss.imbue(loc);
// 6, 15 or 16 digits of precision allows round-trip IEEE 754
// string->float->string, string->double->string or string->long
@@ -2614,11 +2581,9 @@ class basic_json
//////////////////
/// get an object (explicit)
- template <class T, typename
- std::enable_if<
- std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
- std::is_convertible<basic_json_t, typename T::mapped_type>::value
- , int>::type = 0>
+ template<class T, typename std::enable_if<
+ std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
+ std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
T get_impl(T*) const
{
if (is_object())
@@ -2645,14 +2610,12 @@ class basic_json
}
/// get an array (explicit)
- template <class T, typename
- std::enable_if<
- std::is_convertible<basic_json_t, typename T::value_type>::value and
- not std::is_same<basic_json_t, typename T::value_type>::value and
- not std::is_arithmetic<T>::value and
- not std::is_convertible<std::string, T>::value and
- not has_mapped_type<T>::value
- , int>::type = 0>
+ template<class T, typename std::enable_if<
+ std::is_convertible<basic_json_t, typename T::value_type>::value and
+ not std::is_same<basic_json_t, typename T::value_type>::value and
+ not std::is_arithmetic<T>::value and
+ not std::is_convertible<std::string, T>::value and
+ not has_mapped_type<T>::value, int>::type = 0>
T get_impl(T*) const
{
if (is_array())
@@ -2672,11 +2635,9 @@ class basic_json
}
/// get an array (explicit)
- template <class T, typename
- std::enable_if<
- std::is_convertible<basic_json_t, T>::value and
- not std::is_same<basic_json_t, T>::value
- , int>::type = 0>
+ template<class T, typename std::enable_if<
+ std::is_convertible<basic_json_t, T>::value and
+ not std::is_same<basic_json_t, T>::value, int>::type = 0>
std::vector<T> get_impl(std::vector<T>*) const
{
if (is_array())
@@ -2697,11 +2658,9 @@ class basic_json
}
/// get an array (explicit)
- template <class T, typename
- std::enable_if<
- std::is_same<basic_json, typename T::value_type>::value and
- not has_mapped_type<T>::value
- , int>::type = 0>
+ template<class T, typename std::enable_if<
+ std::is_same<basic_json, typename T::value_type>::value and
+ not has_mapped_type<T>::value, int>::type = 0>
T get_impl(T*) const
{
if (is_array())
@@ -2728,10 +2687,8 @@ class basic_json
}
/// get a string (explicit)
- template <typename T, typename
- std::enable_if<
- std::is_convertible<string_t, T>::value
- , int>::type = 0>
+ template<typename T, typename std::enable_if<
+ std::is_convertible<string_t, T>::value, int>::type = 0>
T get_impl(T*) const
{
if (is_string())
@@ -2745,10 +2702,8 @@ class basic_json
}
/// get a number (explicit)
- template<typename T, typename
- std::enable_if<
- std::is_arithmetic<T>::value
- , int>::type = 0>
+ template<typename T, typename std::enable_if<
+ std::is_arithmetic<T>::value, int>::type = 0>
T get_impl(T*) const
{
switch (m_type)
@@ -2937,10 +2892,8 @@ class basic_json
@since version 1.0.0
*/
- template<typename ValueType, typename
- std::enable_if<
- not std::is_pointer<ValueType>::value
- , int>::type = 0>
+ template<typename ValueType, typename std::enable_if<
+ not std::is_pointer<ValueType>::value, int>::type = 0>
ValueType get() const
{
return get_impl(static_cast<ValueType*>(nullptr));
@@ -2973,10 +2926,8 @@ class basic_json
@since version 1.0.0
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
PointerType get() noexcept
{
// delegate the call to get_ptr
@@ -2987,10 +2938,8 @@ class basic_json
@brief get a pointer value (explicit)
@copydoc get()
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
constexpr const PointerType get() const noexcept
{
// delegate the call to get_ptr
@@ -3023,10 +2972,8 @@ class basic_json
@since version 1.0.0
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
PointerType get_ptr() noexcept
{
// get the type of the PointerType (remove pointer and const)
@@ -3052,11 +2999,9 @@ class basic_json
@brief get a pointer value (implicit)
@copydoc get_ptr()
*/
- template<typename PointerType, typename
- std::enable_if<
- std::is_pointer<PointerType>::value
- and std::is_const<typename std::remove_pointer<PointerType>::type>::value
- , int>::type = 0>
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value and
+ std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
constexpr const PointerType get_ptr() const noexcept
{
// get the type of the PointerType (remove pointer and const)
@@ -3104,10 +3049,8 @@ class basic_json
@since version 1.1.0
*/
- template<typename ReferenceType, typename
- std::enable_if<
- std::is_reference<ReferenceType>::value
- , int>::type = 0>
+ template<typename ReferenceType, typename std::enable_if<
+ std::is_reference<ReferenceType>::value, int>::type = 0>
ReferenceType get_ref()
{
// delegate call to get_ref_impl
@@ -3118,11 +3061,9 @@ class basic_json
@brief get a reference value (implicit)
@copydoc get_ref()
*/
- template<typename ReferenceType, typename
- std::enable_if<
- std::is_reference<ReferenceType>::value
- and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
- , int>::type = 0>
+ template<typename ReferenceType, typename std::enable_if<
+ std::is_reference<ReferenceType>::value and
+ std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
ReferenceType get_ref() const
{
// delegate call to get_ref_impl
@@ -3157,10 +3098,9 @@ class basic_json
@since version 1.0.0
*/
- template < typename ValueType, typename
- std::enable_if <
- not std::is_pointer<ValueType>::value
- and not std::is_same<ValueType, typename string_t::value_type>::value
+ template < typename ValueType, typename std::enable_if <
+ not std::is_pointer<ValueType>::value and
+ not std::is_same<ValueType, typename string_t::value_type>::value
#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif
@@ -3509,6 +3449,9 @@ class basic_json
@return const reference to the element at key @a key
+ @pre The element with key @a key must exist. **This precondition is
+ enforced with an assertion.**
+
@throw std::domain_error if JSON is not an object; example: `"cannot use
operator[] with null"`
@@ -3667,6 +3610,9 @@ class basic_json
@return const reference to the element at key @a key
+ @pre The element with key @a key must exist. **This precondition is
+ enforced with an assertion.**
+
@throw std::domain_error if JSON is not an object; example: `"cannot use
operator[] with null"`
@@ -3744,10 +3690,8 @@ class basic_json
@since version 1.0.0
*/
- template <class ValueType, typename
- std::enable_if<
- std::is_convertible<basic_json_t, ValueType>::value
- , int>::type = 0>
+ template<class ValueType, typename std::enable_if<
+ std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
ValueType value(const typename object_t::key_type& key, ValueType default_value) const
{
// at only works for objects
@@ -3820,10 +3764,8 @@ class basic_json
@since version 2.0.2
*/
- template <class ValueType, typename
- std::enable_if<
- std::is_convertible<basic_json_t, ValueType>::value
- , int>::type = 0>
+ template<class ValueType, typename std::enable_if<
+ std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
ValueType value(const json_pointer& ptr, ValueType default_value) const
{
// at only works for objects
@@ -3867,7 +3809,8 @@ class basic_json
@complexity Constant.
@pre The JSON value must not be `null` (would throw `std::out_of_range`)
- or an empty array or object (undefined behavior, guarded by assertions).
+ or an empty array or object (undefined behavior, **guarded by
+ assertions**).
@post The JSON value remains unchanged.
@throw std::out_of_range when called on `null` value
@@ -3909,7 +3852,8 @@ class basic_json
@complexity Constant.
@pre The JSON value must not be `null` (would throw `std::out_of_range`)
- or an empty array or object (undefined behavior, guarded by assertions).
+ or an empty array or object (undefined behavior, **guarded by
+ assertions**).
@post The JSON value remains unchanged.
@throw std::out_of_range when called on `null` value.
@@ -3951,7 +3895,7 @@ class basic_json
@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
+ @tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
@@ -3973,7 +3917,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType}
- @sa @ref erase(InteratorType, InteratorType) -- removes the elements in
+ @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@@ -3982,13 +3926,11 @@ class basic_json
@since version 1.0.0
*/
- template <class InteratorType, typename
- std::enable_if<
- std::is_same<InteratorType, typename basic_json_t::iterator>::value or
- std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
- , int>::type
- = 0>
- InteratorType erase(InteratorType pos)
+ template<class IteratorType, typename std::enable_if<
+ std::is_same<IteratorType, typename basic_json_t::iterator>::value or
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
+ = 0>
+ IteratorType erase(IteratorType pos)
{
// make sure iterator fits the current value
if (this != pos.m_object)
@@ -3996,7 +3938,7 @@ class basic_json
throw std::domain_error("iterator does not fit current value");
}
- InteratorType result = end();
+ IteratorType result = end();
switch (m_type)
{
@@ -4060,7 +4002,7 @@ class basic_json
@return Iterator following the last removed element. If the iterator @a
second refers to the last element, the `end()` iterator is returned.
- @tparam InteratorType an @ref iterator or @ref const_iterator
+ @tparam IteratorType an @ref iterator or @ref const_iterator
@post Invalidates iterators and references at or after the point of the
erase, including the `end()` iterator.
@@ -4083,7 +4025,7 @@ class basic_json
@liveexample{The example shows the result of `erase()` for different JSON
types.,erase__IteratorType_IteratorType}
- @sa @ref erase(InteratorType) -- removes the element at a given position
+ @sa @ref erase(IteratorType) -- removes the element at a given position
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@sa @ref erase(const size_type) -- removes the element from an array at
@@ -4091,13 +4033,11 @@ class basic_json
@since version 1.0.0
*/
- template <class InteratorType, typename
- std::enable_if<
- std::is_same<InteratorType, typename basic_json_t::iterator>::value or
- std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
- , int>::type
- = 0>
- InteratorType erase(InteratorType first, InteratorType last)
+ template<class IteratorType, typename std::enable_if<
+ std::is_same<IteratorType, typename basic_json_t::iterator>::value or
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
+ = 0>
+ IteratorType erase(IteratorType first, IteratorType last)
{
// make sure iterator fits the current value
if (this != first.m_object or this != last.m_object)
@@ -4105,7 +4045,7 @@ class basic_json
throw std::domain_error("iterators do not fit current value");
}
- InteratorType result = end();
+ IteratorType result = end();
switch (m_type)
{
@@ -4177,8 +4117,8 @@ class basic_json
@liveexample{The example shows the effect of `erase()`.,erase__key_type}
- @sa @ref erase(InteratorType) -- removes the element at a given position
- @sa @ref erase(InteratorType, InteratorType) -- removes the elements in
+ @sa @ref erase(IteratorType) -- removes the element at a given position
+ @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const size_type) -- removes the element from an array at
the given index
@@ -4214,8 +4154,8 @@ class basic_json
@liveexample{The example shows the effect of `erase()`.,erase__size_type}
- @sa @ref erase(InteratorType) -- removes the element at a given position
- @sa @ref erase(InteratorType, InteratorType) -- removes the elements in
+ @sa @ref erase(IteratorType) -- removes the element at a given position
+ @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
the given range
@sa @ref erase(const typename object_t::key_type&) -- removes the element
from an object at the given key
@@ -5923,9 +5863,45 @@ class basic_json
/// @{
/*!
- @brief deserialize from string
+ @brief deserialize from an array
+
+ This function reads from an array of 1-byte values.
+
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @param[in] array array to read from
+ @param[in] cb a parser callback function of type @ref parser_callback_t
+ which is used to control the deserialization by filtering unwanted values
+ (optional)
+
+ @return result of the deserialization
- @param[in] s string to read a serialized JSON value from
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the parser callback function
+ @a cb has a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from an array.,parse__array__parser_callback_t}
+
+ @since version 2.0.3
+ */
+ template<class T, std::size_t N>
+ static basic_json parse(T (&array)[N],
+ const parser_callback_t cb = nullptr)
+ {
+ // delegate the call to the iterator-range parse overload
+ return parse(std::begin(array), std::end(array), cb);
+ }
+
+ /*!
+ @brief deserialize from string literal
+
+ @tparam CharT character/literal type with size of 1 byte
+ @param[in] s string literal to read a serialized JSON value from
@param[in] cb a parser callback function of type @ref parser_callback_t
which is used to control the deserialization by filtering unwanted values
(optional)
@@ -5937,6 +5913,8 @@ class basic_json
@a cb has a super-linear complexity.
@note A UTF-8 byte order mark is silently ignored.
+ @note String containers like `std::string` or @ref string_t can be parsed
+ with @ref parse(const ContiguousContainer&, const parser_callback_t)
@liveexample{The example below demonstrates the `parse()` function with
and without callback function.,parse__string__parser_callback_t}
@@ -5944,12 +5922,16 @@ class basic_json
@sa @ref parse(std::istream&, const parser_callback_t) for a version that
reads from an input stream
- @since version 1.0.0
+ @since version 1.0.0 (originally for @ref string_t)
*/
- static basic_json parse(const string_t& s,
+ template<typename CharPT, typename std::enable_if<
+ std::is_pointer<CharPT>::value and
+ std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
+ sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
+ static basic_json parse(const CharPT s,
const parser_callback_t cb = nullptr)
{
- return parser(s, cb).parse();
+ return parser(reinterpret_cast<const char*>(s), cb).parse();
}
/*!
@@ -5971,7 +5953,7 @@ class basic_json
@liveexample{The example below demonstrates the `parse()` function with
and without callback function.,parse__istream__parser_callback_t}
- @sa @ref parse(const string_t&, const parser_callback_t) for a version
+ @sa @ref parse(const char*, const parser_callback_t) for a version
that reads from a string
@since version 1.0.0
@@ -5992,6 +5974,130 @@ class basic_json
}
/*!
+ @brief deserialize from an iterator range with contiguous storage
+
+ This function reads from an iterator range of a container with contiguous
+ storage of 1-byte values. Compatible container types include
+ `std::vector`, `std::string`, `std::array`, `std::valarray`, and
+ `std::initializer_list`. Furthermore, C-style arrays can be used with
+ `std::begin()`/`std::end()`. User-defined containers can be used as long
+ as they implement random-access iterators and a contiguous storage.
+
+ @pre The iterator range is contiguous. Violating this precondition yields
+ undefined behavior. **This precondition is enforced with an assertion.**
+ @pre Each element in the range has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @warning There is no way to enforce all preconditions at compile-time. If
+ the function is called with noncompliant iterators and with
+ assertions switched off, the behavior is undefined and will most
+ likely yield segmentation violation.
+
+ @tparam IteratorType iterator of container with contiguous storage
+ @param[in] first begin of the range to parse (included)
+ @param[in] last end of the range to parse (excluded)
+ @param[in] cb a parser callback function of type @ref parser_callback_t
+ which is used to control the deserialization by filtering unwanted values
+ (optional)
+
+ @return result of the deserialization
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the parser callback function
+ @a cb has a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from an iterator range.,parse__iteratortype__parser_callback_t}
+
+ @since version 2.0.3
+ */
+ template<class IteratorType, typename std::enable_if<
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+ static basic_json parse(IteratorType first, IteratorType last,
+ const parser_callback_t cb = nullptr)
+ {
+ // assertion to check that the iterator range is indeed contiguous,
+ // see http://stackoverflow.com/a/35008842/266378 for more discussion
+ assert(std::accumulate(first, last, std::make_pair<bool, int>(true, 0),
+ [&first](std::pair<bool, int> res, decltype(*first) val)
+ {
+ res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
+ return res;
+ }).first);
+
+ // assertion to check that each element is 1 byte long
+ static_assert(sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
+ "each element in the iterator range must have the size of 1 byte");
+
+ // if iterator range is empty, create a parser with an empty string
+ // to generate "unexpected EOF" error message
+ if (std::distance(first, last) <= 0)
+ {
+ return parser("").parse();
+ }
+
+ return parser(first, last, cb).parse();
+ }
+
+ /*!
+ @brief deserialize from a container with contiguous storage
+
+ This function reads from a container with contiguous storage of 1-byte
+ values. Compatible container types include `std::vector`, `std::string`,
+ `std::array`, and `std::initializer_list`. User-defined containers can be
+ used as long as they implement random-access iterators and a contiguous
+ storage.
+
+ @pre The container storage is contiguous. Violating this precondition
+ yields undefined behavior. **This precondition is enforced with an
+ assertion.**
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @warning There is no way to enforce all preconditions at compile-time. If
+ the function is called with a noncompliant container and with
+ assertions switched off, the behavior is undefined and will most
+ likely yield segmentation violation.
+
+ @tparam ContiguousContainer container type with contiguous storage
+ @param[in] c container to read from
+ @param[in] cb a parser callback function of type @ref parser_callback_t
+ which is used to control the deserialization by filtering unwanted values
+ (optional)
+
+ @return result of the deserialization
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the parser callback function
+ @a cb has a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
+
+ @since version 2.0.3
+ */
+ template<class ContiguousContainer, typename std::enable_if<
+ not std::is_pointer<ContiguousContainer>::value and
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
+ , int>::type = 0>
+ static basic_json parse(const ContiguousContainer& c,
+ const parser_callback_t cb = nullptr)
+ {
+ // delegate the call to the iterator-range parse overload
+ return parse(std::begin(c), std::end(c), cb);
+ }
+
+ /*!
@brief deserialize from stream
Deserializes an input stream to a JSON value.
@@ -6044,7 +6150,7 @@ class basic_json
Returns the type name as string to be used in error messages - usually to
indicate that a function was called on a wrong JSON type.
- @return basically a string representation of a the @ref m_type member
+ @return basically a string representation of a the @a m_type member
@complexity Constant.
@@ -6592,8 +6698,8 @@ class basic_json
@note An iterator is called *initialized* when a pointer to a JSON value
has been set (e.g., by a constructor or a copy assignment). If the
iterator is default-constructed, it is *uninitialized* and most
- methods are undefined. The library uses assertions to detect calls
- on uninitialized iterators.
+ methods are undefined. **The library uses assertions to detect calls
+ on uninitialized iterators.**
@requirement The class satisfies the following concept requirements:
- [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
@@ -7495,32 +7601,25 @@ class basic_json
/// the char type to use in the lexer
using lexer_char_t = unsigned char;
- /// constructor with a given buffer
- explicit lexer(const string_t& s) noexcept
- : m_stream(nullptr), m_buffer(s)
+ /// a lexer from a buffer with given length
+ lexer(const lexer_char_t* buff, const size_t len) noexcept
+ : m_content(buff)
{
- m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
assert(m_content != nullptr);
m_start = m_cursor = m_content;
- m_limit = m_content + s.size();
+ m_limit = m_content + len;
}
- /// constructor with a given stream
- explicit lexer(std::istream* s) noexcept
- : m_stream(s), m_buffer()
+ /// a lexer from an input stream
+ explicit lexer(std::istream& s)
+ : m_stream(&s), m_line_buffer()
{
- assert(m_stream != nullptr);
- std::getline(*m_stream, m_buffer);
- m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
- assert(m_content != nullptr);
- m_start = m_cursor = m_content;
- m_limit = m_content + m_buffer.size();
+ // fill buffer
+ fill_line_buffer();
}
- /// default constructor
- lexer() = default;
-
- // switch off unwanted functions
+ // switch off unwanted functions (due to pointer members)
+ lexer() = delete;
lexer(const lexer&) = delete;
lexer operator=(const lexer&) = delete;
@@ -7673,7 +7772,7 @@ class basic_json
infinite sequence of whitespace or byte-order-marks. This contradicts
the assumption of finite input, q.e.d.
*/
- token_type scan() noexcept
+ token_type scan()
{
while (true)
{
@@ -7725,7 +7824,7 @@ class basic_json
};
if ((m_limit - m_cursor) < 5)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yybm[0 + yych] & 32)
@@ -7859,7 +7958,7 @@ basic_json_parser_6:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yybm[0 + yych] & 32)
@@ -7929,7 +8028,7 @@ basic_json_parser_15:
m_marker = ++m_cursor;
if ((m_limit - m_cursor) < 3)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yybm[0 + yych] & 64)
@@ -8022,7 +8121,7 @@ basic_json_parser_31:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
basic_json_parser_32:
@@ -8059,7 +8158,7 @@ basic_json_parser_36:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= 'e')
@@ -8203,7 +8302,7 @@ basic_json_parser_43:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= '@')
@@ -8239,7 +8338,7 @@ basic_json_parser_44:
m_marker = ++m_cursor;
if ((m_limit - m_cursor) < 3)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= 'D')
@@ -8280,7 +8379,7 @@ basic_json_parser_47:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= '/')
@@ -8322,7 +8421,7 @@ basic_json_parser_54:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= '@')
@@ -8376,7 +8475,7 @@ basic_json_parser_60:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= '@')
@@ -8417,7 +8516,7 @@ basic_json_parser_63:
++m_cursor;
if (m_limit <= m_cursor)
{
- yyfill(); // LCOV_EXCL_LINE;
+ fill_line_buffer();
}
yych = *m_cursor;
if (yych <= '@')
@@ -8455,30 +8554,76 @@ basic_json_parser_63:
return last_token_type;
}
- /// append data from the stream to the internal buffer
- void yyfill() noexcept
+ /*!
+ @brief append data from the stream to the line buffer
+
+ This function is called by the scan() function when the end of the
+ buffer (`m_limit`) is reached and the `m_cursor` pointer cannot be
+ incremented without leaving the limits of the line buffer. Note re2c
+ decides when to call this function.
+
+ If the lexer reads from contiguous storage, there is no trailing null
+ byte. Therefore, this function must make sure to add these padding
+ null bytes.
+
+ If the lexer reads from an input stream, this function reads the next
+ line of the input.
+
+ @pre
+ p p p p p p u u u u u x . . . . . .
+ ^ ^ ^ ^
+ m_content m_start | m_limit
+ m_cursor
+
+ @post
+ u u u u u x x x x x x x . . . . . .
+ ^ ^ ^
+ | m_cursor m_limit
+ m_start
+ m_content
+ */
+ void fill_line_buffer()
{
- if (m_stream == nullptr or not * m_stream)
- {
- return;
- }
-
+ // number of processed characters (p)
const auto offset_start = m_start - m_content;
- const auto offset_marker = m_marker - m_start;
+ // offset for m_marker wrt. to m_start
+ const auto offset_marker = (m_marker == nullptr) ? 0 : m_marker - m_start;
+ // number of unprocessed characters (u)
const auto offset_cursor = m_cursor - m_start;
- m_buffer.erase(0, static_cast<size_t>(offset_start));
- std::string line;
- assert(m_stream != nullptr);
- std::getline(*m_stream, line);
- m_buffer += "\n" + line; // add line with newline symbol
+ // no stream is used or end of file is reached
+ if (m_stream == nullptr or not * m_stream)
+ {
+ // copy unprocessed characters to line buffer
+ m_line_buffer.clear();
+ for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
+ {
+ m_line_buffer.append(1, static_cast<const char>(*m_cursor));
+ }
- m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str());
+ // append 5 characters (size of longest keyword "false") to
+ // make sure that there is sufficient space between m_cursor
+ // and m_limit
+ m_line_buffer.append(5, '\0');
+ }
+ else
+ {
+ // delete processed characters from line buffer
+ m_line_buffer.erase(0, static_cast<size_t>(offset_start));
+ // read next line from input stream
+ std::string line;
+ std::getline(*m_stream, line);
+ // add line with newline symbol to the line buffer
+ m_line_buffer += "\n" + line;
+ }
+
+ // set pointers
+ m_content = reinterpret_cast<const lexer_char_t*>(m_line_buffer.c_str());
assert(m_content != nullptr);
m_start = m_content;
m_marker = m_start + offset_marker;
m_cursor = m_start + offset_cursor;
- m_limit = m_start + m_buffer.size() - 1;
+ m_limit = m_start + m_line_buffer.size();
}
/// return string representation of last read token
@@ -8820,8 +8965,8 @@ basic_json_parser_63:
private:
/// optional input stream
std::istream* m_stream = nullptr;
- /// the buffer
- string_t m_buffer;
+ /// line buffer buffer for m_stream
+ string_t m_line_buffer {};
/// the buffer pointer
const lexer_char_t* m_content = nullptr;
/// pointer to the beginning of the current symbol
@@ -8844,25 +8989,34 @@ basic_json_parser_63:
class parser
{
public:
- /// constructor for strings
- parser(const string_t& s, const parser_callback_t cb = nullptr) noexcept
- : callback(cb), m_lexer(s)
- {
- // read first token
- get_token();
- }
+ /// a parser reading from a string literal
+ parser(const char* buff, const parser_callback_t cb = nullptr)
+ : callback(cb),
+ m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
+ {}
/// a parser reading from an input stream
- parser(std::istream& _is, const parser_callback_t cb = nullptr) noexcept
- : callback(cb), m_lexer(&_is)
- {
- // read first token
- get_token();
- }
+ parser(std::istream& is, const parser_callback_t cb = nullptr)
+ : callback(cb), m_lexer(is)
+ {}
+
+ /// a parser reading from an iterator range with contiguous storage
+ template<class IteratorType, typename std::enable_if<
+ std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
+ , int>::type
+ = 0>
+ parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr)
+ : callback(cb),
+ m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
+ static_cast<size_t>(std::distance(first, last)))
+ {}
/// public parser interface
basic_json parse()
{
+ // read first token
+ get_token();
+
basic_json result = parse_internal(true);
result.assert_invariant();
@@ -8883,7 +9037,8 @@ basic_json_parser_63:
{
case lexer::token_type::begin_object:
{
- if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
+ if (keep and (not callback
+ or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
{
// explicitly set result to object to cope with {}
result.m_type = value_t::object;
@@ -8961,7 +9116,8 @@ basic_json_parser_63:
case lexer::token_type::begin_array:
{
- if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
+ if (keep and (not callback
+ or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
{
// explicitly set result to object to cope with []
result.m_type = value_t::array;
@@ -9067,7 +9223,7 @@ basic_json_parser_63:
}
/// get next token from lexer
- typename lexer::token_type get_token() noexcept
+ typename lexer::token_type get_token()
{
last_token = m_lexer.scan();
return last_token;
@@ -9475,7 +9631,7 @@ basic_json_parser_63:
}
/// split the string input to reference tokens
- static std::vector<std::string> split(std::string reference_string)
+ static std::vector<std::string> split(const std::string& reference_string)
{
std::vector<std::string> result;
@@ -10203,7 +10359,7 @@ basic_json_parser_63:
*/
static basic_json diff(const basic_json& source,
const basic_json& target,
- std::string path = "")
+ const std::string& path = "")
{
// the patch
basic_json result(value_t::array);
@@ -10365,7 +10521,7 @@ namespace std
@since version 1.0.0
*/
-template <>
+template<>
inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value and
@@ -10376,7 +10532,7 @@ inline void swap(nlohmann::json& j1,
}
/// hash value for JSON objects
-template <>
+template<>
struct hash<nlohmann::json>
{
/*!
@@ -10407,7 +10563,7 @@ if no parse error occurred.
*/
inline nlohmann::json operator "" _json(const char* s, std::size_t)
{
- return nlohmann::json::parse(reinterpret_cast<const nlohmann::json::string_t::value_type*>(s));
+ return nlohmann::json::parse(s);
}
/*!