29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 43 #include <initializer_list> 55 #include <type_traits> 60 #if defined(__clang__) 61 #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 62 #if CLANG_VERSION < 30400 63 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 65 #elif defined(__GNUC__) 66 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 67 #if GCC_VERSION < 40900 68 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 73 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 74 #pragma GCC diagnostic push 75 #pragma GCC diagnostic ignored "-Wfloat-equal" 79 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 80 #define JSON_DEPRECATED __attribute__((deprecated)) 81 #elif defined(_MSC_VER) 82 #define JSON_DEPRECATED __declspec(deprecated) 84 #define JSON_DEPRECATED 113 struct has_mapped_type
116 template <
typename U,
typename =
typename U::mapped_type>
117 static int detect(U&&);
119 static void detect(...);
121 static constexpr
bool value =
122 std::is_integral<decltype(detect(std::declval<T>()))>::value;
206 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
207 template<
typename U,
typename... Args>
class ArrayType = std::vector,
208 class StringType = std::string,
209 class BooleanType = bool,
210 class NumberIntegerType = std::int64_t,
211 class NumberUnsignedType = std::uint64_t,
212 class NumberFloatType = double,
213 template<
typename U>
class AllocatorType = std::allocator
220 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
254 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
256 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
371 using object_t = ObjectType<StringType,
373 std::less<StringType>,
374 AllocatorType<std::pair<
const StringType,
421 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
753 template<
typename T,
typename... Args>
754 static T* create(Args&& ... args)
756 AllocatorType<T> alloc;
757 auto deleter = [&](T * object)
759 alloc.deallocate(
object, 1);
761 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
762 alloc.construct(
object.
get(), std::forward<Args>(args)...);
763 assert(
object.
get() !=
nullptr);
764 return object.release();
813 json_value() =
default;
815 json_value(
boolean_t v) noexcept : boolean(v) {}
827 case value_t::object:
829 object = create<object_t>();
835 array = create<array_t>();
839 case value_t::string:
841 string = create<string_t>(
"");
845 case value_t::boolean:
851 case value_t::number_integer:
857 case value_t::number_unsigned:
863 case value_t::number_float:
879 string = create<string_t>(value);
885 object = create<object_t>(value);
889 json_value(
const array_t& value)
891 array = create<array_t>(value);
904 void assert_invariant()
const 906 assert(m_type != value_t::object or m_value.object !=
nullptr);
907 assert(m_type != value_t::array or m_value.array !=
nullptr);
908 assert(m_type != value_t::string or m_value.string !=
nullptr);
996 basic_json& parsed)>;
1048 : m_type(value_type), m_value(value_type)
1097 : m_type(
value_t::object), m_value(val)
1128 template<
class CompatibleObjectType,
typename std::enable_if<
1129 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1130 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1136 m_value.object = create<object_t>(begin(val), end(val));
1160 : m_type(
value_t::array), m_value(val)
1191 template<
class CompatibleArrayType,
typename std::enable_if<
1192 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1193 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1194 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1195 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1196 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1197 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1198 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1204 m_value.array = create<array_t>(begin(val), end(val));
1230 : m_type(
value_t::string), m_value(val)
1284 template<
class CompatibleStringType,
typename std::enable_if<
1285 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1307 : m_type(value_t::boolean), m_value(val)
1335 template<
typename T,
typename std::enable_if<
1336 not (std::is_same<T, int>::value) and
1337 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1339 : m_type(value_t::number_integer), m_value(val)
1370 : m_type(value_t::number_integer),
1371 m_value(static_cast<number_integer_t>(val))
1401 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1402 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1403 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1404 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1405 CompatibleNumberIntegerType>::type = 0>
1407 : m_type(value_t::number_integer),
1408 m_value(static_cast<number_integer_t>(val))
1430 template<
typename T,
typename std::enable_if<
1431 not (std::is_same<T, int>::value) and
1432 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1434 : m_type(value_t::number_unsigned), m_value(val)
1459 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1460 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1461 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1462 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1463 CompatibleNumberUnsignedType>::type = 0>
1465 : m_type(value_t::number_unsigned),
1466 m_value(static_cast<number_unsigned_t>(val))
1496 : m_type(value_t::number_float), m_value(val)
1499 if (not std::isfinite(val))
1501 m_type = value_t::null;
1502 m_value = json_value();
1539 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1540 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1541 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1618 bool type_deduction =
true,
1619 value_t manual_type = value_t::array)
1623 bool is_an_object = std::all_of(init.begin(), init.end(),
1626 return element.is_array() and element.size() == 2 and element[0].is_string();
1630 if (not type_deduction)
1633 if (manual_type == value_t::array)
1635 is_an_object =
false;
1639 if (manual_type == value_t::object and not is_an_object)
1641 throw std::domain_error(
"cannot create object from initializer list");
1648 m_type = value_t::object;
1649 m_value = value_t::object;
1651 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1653 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1659 m_type = value_t::array;
1660 m_value.array = create<array_t>(init);
1701 std::initializer_list<basic_json>())
1703 return basic_json(init,
false, value_t::array);
1741 std::initializer_list<basic_json>())
1743 return basic_json(init,
false, value_t::object);
1767 m_value.array = create<array_t>(cnt, val);
1808 template<
class InputIT,
typename std::enable_if<
1809 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1810 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1813 assert(first.m_object !=
nullptr);
1814 assert(last.m_object !=
nullptr);
1817 if (first.m_object != last.m_object)
1819 throw std::domain_error(
"iterators are not compatible");
1823 m_type = first.m_object->m_type;
1828 case value_t::boolean:
1829 case value_t::number_float:
1830 case value_t::number_integer:
1831 case value_t::number_unsigned:
1832 case value_t::string:
1834 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1836 throw std::out_of_range(
"iterators out of range");
1849 case value_t::number_integer:
1851 m_value.number_integer = first.m_object->m_value.number_integer;
1855 case value_t::number_unsigned:
1857 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1861 case value_t::number_float:
1863 m_value.number_float = first.m_object->m_value.number_float;
1867 case value_t::boolean:
1869 m_value.boolean = first.m_object->m_value.boolean;
1873 case value_t::string:
1875 m_value = *first.m_object->m_value.string;
1879 case value_t::object:
1881 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1885 case value_t::array:
1887 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1893 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1931 *
this = parser(i, cb).parse();
1962 : m_type(other.m_type)
1965 other.assert_invariant();
1969 case value_t::object:
1971 m_value = *other.m_value.object;
1975 case value_t::array:
1977 m_value = *other.m_value.array;
1981 case value_t::string:
1983 m_value = *other.m_value.string;
1987 case value_t::boolean:
1989 m_value = other.m_value.boolean;
1993 case value_t::number_integer:
1995 m_value = other.m_value.number_integer;
1999 case value_t::number_unsigned:
2001 m_value = other.m_value.number_unsigned;
2005 case value_t::number_float:
2007 m_value = other.m_value.number_float;
2039 : m_type(
std::move(other.m_type)),
2040 m_value(
std::move(other.m_value))
2043 other.assert_invariant();
2046 other.m_type = value_t::null;
2076 std::is_nothrow_move_constructible<value_t>::value and
2077 std::is_nothrow_move_assignable<value_t>::value and
2078 std::is_nothrow_move_constructible<json_value>::value and
2079 std::is_nothrow_move_assignable<json_value>::value
2083 other.assert_invariant();
2086 swap(m_type, other.m_type);
2087 swap(m_value, other.m_value);
2114 case value_t::object:
2116 AllocatorType<object_t> alloc;
2117 alloc.destroy(m_value.object);
2118 alloc.deallocate(m_value.object, 1);
2122 case value_t::array:
2124 AllocatorType<array_t> alloc;
2125 alloc.destroy(m_value.array);
2126 alloc.deallocate(m_value.array, 1);
2130 case value_t::string:
2132 AllocatorType<string_t> alloc;
2133 alloc.destroy(m_value.string);
2134 alloc.deallocate(m_value.string, 1);
2182 std::stringstream ss;
2184 ss.imbue(std::locale::classic());
2190 ss.precision(std::numeric_limits<double>::digits10);
2194 dump(ss,
true, static_cast<unsigned int>(indent));
2254 return is_null() or is_string() or is_boolean() or is_number();
2281 return is_array() or is_object();
2303 return m_type == value_t::null;
2325 return m_type == value_t::boolean;
2355 return is_number_integer() or is_number_float();
2384 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2412 return m_type == value_t::number_unsigned;
2440 return m_type == value_t::number_float;
2462 return m_type == value_t::object;
2484 return m_type == value_t::array;
2506 return m_type == value_t::string;
2533 return m_type == value_t::discarded;
2567 template<
class T,
typename std::enable_if<
2568 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2569 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2570 T get_impl(T*)
const 2574 return T(m_value.object->begin(), m_value.object->end());
2578 throw std::domain_error(
"type must be object, but is " + type_name());
2587 return *(m_value.object);
2591 throw std::domain_error(
"type must be object, but is " + type_name());
2596 template<
class T,
typename std::enable_if<
2597 std::is_convertible<basic_json_t, typename T::value_type>::value and
2598 not std::is_same<basic_json_t, typename T::value_type>::value and
2599 not std::is_arithmetic<T>::value and
2600 not std::is_convertible<std::string, T>::value and
2601 not has_mapped_type<T>::value,
int>::type = 0>
2602 T get_impl(T*)
const 2607 std::transform(m_value.array->begin(), m_value.array->end(),
2608 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2610 return i.
get<
typename T::value_type>();
2616 throw std::domain_error(
"type must be array, but is " + type_name());
2621 template<
class T,
typename std::enable_if<
2622 std::is_convertible<basic_json_t, T>::value and
2623 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2624 std::vector<T> get_impl(std::vector<T>*)
const 2628 std::vector<T> to_vector;
2629 to_vector.reserve(m_value.array->size());
2630 std::transform(m_value.array->begin(), m_value.array->end(),
2631 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2639 throw std::domain_error(
"type must be array, but is " + type_name());
2644 template<
class T,
typename std::enable_if<
2645 std::is_same<basic_json, typename T::value_type>::value and
2646 not has_mapped_type<T>::value,
int>::type = 0>
2647 T get_impl(T*)
const 2651 return T(m_value.array->begin(), m_value.array->end());
2655 throw std::domain_error(
"type must be array, but is " + type_name());
2664 return *(m_value.array);
2668 throw std::domain_error(
"type must be array, but is " + type_name());
2673 template<
typename T,
typename std::enable_if<
2674 std::is_convertible<string_t, T>::value,
int>::type = 0>
2675 T get_impl(T*)
const 2679 return *m_value.string;
2683 throw std::domain_error(
"type must be string, but is " + type_name());
2688 template<
typename T,
typename std::enable_if<
2689 std::is_arithmetic<T>::value,
int>::type = 0>
2690 T get_impl(T*)
const 2694 case value_t::number_integer:
2696 return static_cast<T
>(m_value.number_integer);
2699 case value_t::number_unsigned:
2701 return static_cast<T
>(m_value.number_unsigned);
2704 case value_t::number_float:
2706 return static_cast<T
>(m_value.number_float);
2711 throw std::domain_error(
"type must be number, but is " + type_name());
2721 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2727 return is_object() ? m_value.object :
nullptr;
2733 return is_object() ? m_value.object :
nullptr;
2739 return is_array() ? m_value.array :
nullptr;
2743 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2745 return is_array() ? m_value.array :
nullptr;
2751 return is_string() ? m_value.string :
nullptr;
2757 return is_string() ? m_value.string :
nullptr;
2763 return is_boolean() ? &m_value.boolean :
nullptr;
2769 return is_boolean() ? &m_value.boolean :
nullptr;
2775 return is_number_integer() ? &m_value.number_integer :
nullptr;
2781 return is_number_integer() ? &m_value.number_integer :
nullptr;
2787 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2793 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2799 return is_number_float() ? &m_value.number_float :
nullptr;
2805 return is_number_float() ? &m_value.number_float :
nullptr;
2819 template<
typename ReferenceType,
typename ThisType>
2820 static ReferenceType get_ref_impl(ThisType& obj)
2823 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2826 auto ptr = obj.template get_ptr<PointerType>();
2834 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2878 template<
typename ValueType,
typename std::enable_if<
2879 not std::is_pointer<ValueType>::value,
int>::type = 0>
2880 ValueType
get()
const 2882 return get_impl(static_cast<ValueType*>(
nullptr));
2912 template<
typename PointerType,
typename std::enable_if<
2913 std::is_pointer<PointerType>::value,
int>::type = 0>
2914 PointerType
get() noexcept
2917 return get_ptr<PointerType>();
2924 template<
typename PointerType,
typename std::enable_if<
2925 std::is_pointer<PointerType>::value,
int>::type = 0>
2926 constexpr
const PointerType
get()
const noexcept
2929 return get_ptr<PointerType>();
2958 template<
typename PointerType,
typename std::enable_if<
2959 std::is_pointer<PointerType>::value,
int>::type = 0>
2963 using pointee_t =
typename std::remove_const<
typename 2964 std::remove_pointer<
typename 2965 std::remove_const<PointerType>::type>::type>::type;
2968 std::is_same<object_t, pointee_t>::value
2969 or std::is_same<array_t, pointee_t>::value
2970 or std::is_same<string_t, pointee_t>::value
2971 or std::is_same<boolean_t, pointee_t>::value
2972 or std::is_same<number_integer_t, pointee_t>::value
2973 or std::is_same<number_unsigned_t, pointee_t>::value
2974 or std::is_same<number_float_t, pointee_t>::value
2975 ,
"incompatible pointer type");
2978 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2985 template<
typename PointerType,
typename std::enable_if<
2986 std::is_pointer<PointerType>::value and
2987 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
2988 constexpr
const PointerType
get_ptr() const noexcept
2991 using pointee_t =
typename std::remove_const<
typename 2992 std::remove_pointer<
typename 2993 std::remove_const<PointerType>::type>::type>::type;
2996 std::is_same<object_t, pointee_t>::value
2997 or std::is_same<array_t, pointee_t>::value
2998 or std::is_same<string_t, pointee_t>::value
2999 or std::is_same<boolean_t, pointee_t>::value
3000 or std::is_same<number_integer_t, pointee_t>::value
3001 or std::is_same<number_unsigned_t, pointee_t>::value
3002 or std::is_same<number_float_t, pointee_t>::value
3003 ,
"incompatible pointer type");
3006 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3035 template<
typename ReferenceType,
typename std::enable_if<
3036 std::is_reference<ReferenceType>::value,
int>::type = 0>
3040 return get_ref_impl<ReferenceType>(*this);
3047 template<
typename ReferenceType,
typename std::enable_if<
3048 std::is_reference<ReferenceType>::value and
3049 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3053 return get_ref_impl<ReferenceType>(*this);
3084 template <
typename ValueType,
typename std::enable_if <
3085 not std::is_pointer<ValueType>::value and
3086 not std::is_same<ValueType, typename string_t::value_type>::value
3087 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3088 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3091 operator ValueType()
const 3094 return get<ValueType>();
3137 return m_value.
array->
at(idx);
3139 catch (std::out_of_range&)
3142 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3147 throw std::domain_error(
"cannot use at() with " + type_name());
3180 return m_value.
array->
at(idx);
3182 catch (std::out_of_range&)
3185 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3190 throw std::domain_error(
"cannot use at() with " + type_name());
3229 catch (std::out_of_range&)
3232 throw std::out_of_range(
"key '" + key +
"' not found");
3237 throw std::domain_error(
"cannot use at() with " + type_name());
3276 catch (std::out_of_range&)
3279 throw std::out_of_range(
"key '" + key +
"' not found");
3284 throw std::domain_error(
"cannot use at() with " + type_name());
3318 m_type = value_t::array;
3319 m_value.
array = create<array_t>();
3327 if (idx >= m_value.array->size())
3329 m_value.array->insert(m_value.array->end(),
3330 idx - m_value.array->size() + 1,
3334 return m_value.array->operator[](idx);
3338 throw std::domain_error(
"cannot use operator[] with " + type_name());
3366 return m_value.
array->operator[](idx);
3370 throw std::domain_error(
"cannot use operator[] with " + type_name());
3406 m_type = value_t::object;
3407 m_value.
object = create<object_t>();
3414 return m_value.object->operator[](key);
3418 throw std::domain_error(
"cannot use operator[] with " + type_name());
3457 assert(m_value.object->find(key) != m_value.object->end());
3462 throw std::domain_error(
"cannot use operator[] with " + type_name());
3493 template<
typename T, std::
size_t n>
3496 return operator[](static_cast<const T>(key));
3528 template<
typename T, std::
size_t n>
3531 return operator[](static_cast<const T>(key));
3561 template<
typename T>
3567 m_type = value_t::object;
3568 m_value = value_t::object;
3575 return m_value.object->operator[](key);
3579 throw std::domain_error(
"cannot use operator[] with " + type_name());
3613 template<
typename T>
3619 assert(m_value.object->find(key) != m_value.object->end());
3624 throw std::domain_error(
"cannot use operator[] with " + type_name());
3676 template<
class ValueType,
typename std::enable_if<
3677 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3678 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3684 const auto it = find(key);
3691 return default_value;
3696 throw std::domain_error(
"cannot use value() with " + type_name());
3704 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3706 return value(key,
string_t(default_value));
3750 template<
class ValueType,
typename std::enable_if<
3751 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3760 return ptr.get_checked(
this);
3762 catch (std::out_of_range&)
3764 return default_value;
3769 throw std::domain_error(
"cannot use value() with " + type_name());
3779 return value(ptr,
string_t(default_value));
3912 template<
class IteratorType,
typename std::enable_if<
3913 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3914 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3919 if (
this != pos.m_object)
3921 throw std::domain_error(
"iterator does not fit current value");
3924 IteratorType result = end();
3928 case value_t::boolean:
3929 case value_t::number_float:
3930 case value_t::number_integer:
3931 case value_t::number_unsigned:
3932 case value_t::string:
3934 if (not pos.m_it.primitive_iterator.is_begin())
3936 throw std::out_of_range(
"iterator out of range");
3941 AllocatorType<string_t> alloc;
3942 alloc.destroy(m_value.string);
3943 alloc.deallocate(m_value.string, 1);
3944 m_value.string =
nullptr;
3947 m_type = value_t::null;
3952 case value_t::object:
3954 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3958 case value_t::array:
3960 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3966 throw std::domain_error(
"cannot use erase() with " + type_name());
4019 template<
class IteratorType,
typename std::enable_if<
4020 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4021 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4023 IteratorType
erase(IteratorType first, IteratorType last)
4026 if (
this != first.m_object or
this != last.m_object)
4028 throw std::domain_error(
"iterators do not fit current value");
4031 IteratorType result = end();
4035 case value_t::boolean:
4036 case value_t::number_float:
4037 case value_t::number_integer:
4038 case value_t::number_unsigned:
4039 case value_t::string:
4041 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4043 throw std::out_of_range(
"iterators out of range");
4048 AllocatorType<string_t> alloc;
4049 alloc.destroy(m_value.string);
4050 alloc.deallocate(m_value.string, 1);
4051 m_value.string =
nullptr;
4054 m_type = value_t::null;
4059 case value_t::object:
4061 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4062 last.m_it.object_iterator);
4066 case value_t::array:
4068 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4069 last.m_it.array_iterator);
4075 throw std::domain_error(
"cannot use erase() with " + type_name());
4116 return m_value.object->erase(key);
4120 throw std::domain_error(
"cannot use erase() with " + type_name());
4155 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4158 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4162 throw std::domain_error(
"cannot use erase() with " + type_name());
4196 auto result = end();
4200 result.m_it.object_iterator = m_value.object->find(key);
4212 auto result = cend();
4216 result.m_it.object_iterator = m_value.object->find(key);
4243 return is_object() ? m_value.object->count(key) : 0;
4531 template<
typename IteratorType>
class iteration_proxy;
4547 return iteration_proxy<iterator>(cont);
4555 return iteration_proxy<const_iterator>(cont);
4615 case value_t::array:
4618 return m_value.array->empty();
4621 case value_t::object:
4624 return m_value.object->empty();
4683 case value_t::array:
4686 return m_value.array->size();
4689 case value_t::object:
4692 return m_value.object->size();
4743 case value_t::array:
4746 return m_value.array->max_size();
4749 case value_t::object:
4752 return m_value.object->max_size();
4802 case value_t::number_integer:
4804 m_value.number_integer = 0;
4808 case value_t::number_unsigned:
4810 m_value.number_unsigned = 0;
4814 case value_t::number_float:
4816 m_value.number_float = 0.0;
4820 case value_t::boolean:
4822 m_value.boolean =
false;
4826 case value_t::string:
4828 m_value.string->clear();
4832 case value_t::array:
4834 m_value.array->clear();
4838 case value_t::object:
4840 m_value.object->clear();
4874 if (not(is_null() or is_array()))
4876 throw std::domain_error(
"cannot use push_back() with " + type_name());
4882 m_type = value_t::array;
4883 m_value = value_t::array;
4888 m_value.array->push_back(std::move(val));
4890 val.m_type = value_t::null;
4899 push_back(std::move(val));
4910 if (not(is_null() or is_array()))
4912 throw std::domain_error(
"cannot use push_back() with " + type_name());
4918 m_type = value_t::array;
4919 m_value = value_t::array;
4924 m_value.array->push_back(val);
4960 if (not(is_null() or is_object()))
4962 throw std::domain_error(
"cannot use push_back() with " + type_name());
4968 m_type = value_t::object;
4969 m_value = value_t::object;
4974 m_value.object->insert(val);
5014 if (is_object() and init.size() == 2 and init.begin()->is_string())
5016 const string_t key = *init.begin();
5017 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5056 template<
class... Args>
5060 if (not(is_null() or is_array()))
5062 throw std::domain_error(
"cannot use emplace_back() with " + type_name());
5068 m_type = value_t::array;
5069 m_value = value_t::array;
5074 m_value.array->emplace_back(std::forward<Args>(args)...);
5104 template<
class... Args>
5105 std::pair<iterator, bool>
emplace(Args&& ... args)
5108 if (not(is_null() or is_object()))
5110 throw std::domain_error(
"cannot use emplace() with " + type_name());
5116 m_type = value_t::object;
5117 m_value = value_t::object;
5122 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5125 it.m_it.object_iterator = res.first;
5128 return {it, res.second};
5159 if (pos.m_object !=
this)
5161 throw std::domain_error(
"iterator does not fit current value");
5166 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5171 throw std::domain_error(
"cannot use insert() with " + type_name());
5181 return insert(pos, val);
5214 if (pos.m_object !=
this)
5216 throw std::domain_error(
"iterator does not fit current value");
5221 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5226 throw std::domain_error(
"cannot use insert() with " + type_name());
5265 throw std::domain_error(
"cannot use insert() with " + type_name());
5269 if (pos.m_object !=
this)
5271 throw std::domain_error(
"iterator does not fit current value");
5275 if (first.m_object != last.m_object)
5277 throw std::domain_error(
"iterators do not fit");
5280 if (first.m_object ==
this or last.m_object ==
this)
5282 throw std::domain_error(
"passed iterators may not belong to container");
5287 result.m_it.array_iterator = m_value.array->insert(
5288 pos.m_it.array_iterator,
5289 first.m_it.array_iterator,
5290 last.m_it.array_iterator);
5323 throw std::domain_error(
"cannot use insert() with " + type_name());
5327 if (pos.m_object !=
this)
5329 throw std::domain_error(
"iterator does not fit current value");
5334 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5356 std::is_nothrow_move_constructible<value_t>::value and
5357 std::is_nothrow_move_assignable<value_t>::value and
5358 std::is_nothrow_move_constructible<json_value>::value and
5359 std::is_nothrow_move_assignable<json_value>::value
5362 std::swap(m_type, other.m_type);
5363 std::swap(m_value, other.m_value);
5392 std::swap(*(m_value.array), other);
5396 throw std::domain_error(
"cannot use swap() with " + type_name());
5425 std::swap(*(m_value.object), other);
5429 throw std::domain_error(
"cannot use swap() with " + type_name());
5458 std::swap(*(m_value.string), other);
5462 throw std::domain_error(
"cannot use swap() with " + type_name());
5488 static constexpr std::array<uint8_t, 8> order = {{
5501 if (lhs == value_t::discarded or rhs == value_t::discarded)
5506 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5535 const auto lhs_type = lhs.type();
5536 const auto rhs_type = rhs.type();
5538 if (lhs_type == rhs_type)
5542 case value_t::array:
5544 return *lhs.m_value.array == *rhs.m_value.array;
5546 case value_t::object:
5548 return *lhs.m_value.object == *rhs.m_value.object;
5554 case value_t::string:
5556 return *lhs.m_value.string == *rhs.m_value.string;
5558 case value_t::boolean:
5560 return lhs.m_value.boolean == rhs.m_value.boolean;
5562 case value_t::number_integer:
5564 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5566 case value_t::number_unsigned:
5568 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5570 case value_t::number_float:
5572 return lhs.m_value.number_float == rhs.m_value.number_float;
5580 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5582 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5584 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5586 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5588 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5590 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5592 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5594 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5596 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5598 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5600 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5602 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5658 return not (lhs == rhs);
5690 return not v.is_null();
5719 const auto lhs_type = lhs.type();
5720 const auto rhs_type = rhs.type();
5722 if (lhs_type == rhs_type)
5726 case value_t::array:
5728 return *lhs.m_value.array < *rhs.m_value.array;
5730 case value_t::object:
5732 return *lhs.m_value.object < *rhs.m_value.object;
5738 case value_t::string:
5740 return *lhs.m_value.string < *rhs.m_value.string;
5742 case value_t::boolean:
5744 return lhs.m_value.boolean < rhs.m_value.boolean;
5746 case value_t::number_integer:
5748 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5750 case value_t::number_unsigned:
5752 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5754 case value_t::number_float:
5756 return lhs.m_value.number_float < rhs.m_value.number_float;
5764 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5766 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5768 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5770 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5772 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5774 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5776 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5778 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5780 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5782 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5784 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5786 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5792 return operator<(lhs_type, rhs_type);
5814 return not (rhs < lhs);
5836 return not (lhs <= rhs);
5858 return not (lhs < rhs);
5900 const bool pretty_print = (o.width() > 0);
5901 const auto indentation = (pretty_print ? o.width() : 0);
5907 const auto old_locale = o.imbue(std::locale::classic());
5914 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5917 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5920 o.imbue(old_locale);
5921 o.precision(old_precision);
5971 template<
class T, std::
size_t N>
5976 return parse(std::begin(array), std::end(array), cb);
6006 template<
typename CharPT,
typename std::enable_if<
6007 std::is_pointer<CharPT>::value and
6008 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
6009 sizeof(
typename std::remove_pointer<CharPT>::type) == 1,
int>::type = 0>
6013 return parser(reinterpret_cast<const char*>(s), cb).
parse();
6043 return parser(i, cb).
parse();
6052 return parser(i, cb).
parse();
6096 template<
class IteratorType,
typename std::enable_if<
6098 std::random_access_iterator_tag,
6099 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6105 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6106 [&first](std::pair<bool, int> res, decltype(*first) val)
6108 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6113 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6114 "each element in the iterator range must have the size of 1 byte");
6118 if (std::distance(first, last) <= 0)
6120 return parser(
"").parse();
6123 return parser(first, last, cb).parse();
6166 template<
class ContiguousContainer,
typename std::enable_if<
6167 not std::is_pointer<ContiguousContainer>::value and
6169 std::random_access_iterator_tag,
6170 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6176 return parse(std::begin(c), std::end(c), cb);
6204 j = parser(i).
parse();
6214 j = parser(i).
parse();
6238 std::string type_name()
const 6244 case value_t::object:
6246 case value_t::array:
6248 case value_t::string:
6250 case value_t::boolean:
6252 case value_t::discarded:
6267 static std::size_t extra_space(
const string_t& s) noexcept
6269 return std::accumulate(s.begin(), s.end(),
size_t{},
6270 [](
size_t res,
typename string_t::value_type c)
6288 if (c >= 0x00 and c <= 0x1f)
6317 const auto space = extra_space(s);
6324 string_t result(s.size() + space,
'\\');
6325 std::size_t pos = 0;
6327 for (
const auto& c : s)
6334 result[pos + 1] =
'"';
6350 result[pos + 1] =
'b';
6358 result[pos + 1] =
'f';
6366 result[pos + 1] =
'n';
6374 result[pos + 1] =
'r';
6382 result[pos + 1] =
't';
6389 if (c >= 0x00 and c <= 0x1f)
6393 static const char hexify[16] =
6395 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
6396 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 6401 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
6439 void dump(std::ostream& o,
6440 const bool pretty_print,
6441 const unsigned int indent_step,
6442 const unsigned int current_indent = 0)
const 6445 unsigned int new_indent = current_indent;
6449 case value_t::object:
6451 if (m_value.object->empty())
6462 new_indent += indent_step;
6466 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6468 if (i != m_value.object->cbegin())
6470 o << (pretty_print ?
",\n" :
",");
6472 o <<
string_t(new_indent,
' ') <<
"\"" 6473 << escape_string(i->first) <<
"\":" 6474 << (pretty_print ?
" " :
"");
6475 i->second.dump(o, pretty_print, indent_step, new_indent);
6481 new_indent -= indent_step;
6485 o <<
string_t(new_indent,
' ') +
"}";
6489 case value_t::array:
6491 if (m_value.array->empty())
6502 new_indent += indent_step;
6506 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6508 if (i != m_value.array->cbegin())
6510 o << (pretty_print ?
",\n" :
",");
6513 i->dump(o, pretty_print, indent_step, new_indent);
6519 new_indent -= indent_step;
6523 o <<
string_t(new_indent,
' ') <<
"]";
6527 case value_t::string:
6529 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6533 case value_t::boolean:
6535 o << (m_value.boolean ?
"true" :
"false");
6539 case value_t::number_integer:
6541 o << m_value.number_integer;
6545 case value_t::number_unsigned:
6547 o << m_value.number_unsigned;
6551 case value_t::number_float:
6553 if (m_value.number_float == 0)
6556 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6560 o << m_value.number_float;
6565 case value_t::discarded:
6585 value_t m_type = value_t::null;
6588 json_value m_value = {};
6605 class primitive_iterator_t
6609 void set_begin() noexcept
6615 void set_end() noexcept
6621 constexpr
bool is_begin()
const noexcept
6623 return (m_it == begin_value);
6627 constexpr
bool is_end()
const noexcept
6629 return (m_it == end_value);
6649 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6659 struct internal_iterator
6662 typename object_t::iterator object_iterator;
6664 typename array_t::iterator array_iterator;
6666 primitive_iterator_t primitive_iterator;
6669 internal_iterator() noexcept
6670 : object_iterator(), array_iterator(), primitive_iterator()
6675 template<
typename IteratorType>
6676 class iteration_proxy
6680 class iteration_proxy_internal
6684 IteratorType anchor;
6686 size_t array_index = 0;
6689 explicit iteration_proxy_internal(IteratorType it) noexcept
6694 iteration_proxy_internal& operator*()
6700 iteration_proxy_internal& operator++()
6709 bool operator!= (
const iteration_proxy_internal& o)
const 6711 return anchor != o.anchor;
6717 assert(anchor.m_object !=
nullptr);
6719 switch (anchor.m_object->type())
6722 case value_t::array:
6724 return std::to_string(array_index);
6728 case value_t::object:
6730 return anchor.key();
6742 typename IteratorType::reference value()
const 6744 return anchor.value();
6749 typename IteratorType::reference container;
6753 explicit iteration_proxy(
typename IteratorType::reference cont)
6758 iteration_proxy_internal begin() noexcept
6760 return iteration_proxy_internal(container.begin());
6764 iteration_proxy_internal end() noexcept
6766 return iteration_proxy_internal(container.end());
6790 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6819 assert(m_object !=
nullptr);
6821 switch (m_object->m_type)
6825 m_it.object_iterator =
typename object_t::iterator();
6831 m_it.array_iterator =
typename array_t::iterator();
6837 m_it.primitive_iterator = primitive_iterator_t();
6849 : m_object(other.m_object)
6851 if (m_object !=
nullptr)
6853 switch (m_object->m_type)
6857 m_it.object_iterator = other.m_it.object_iterator;
6863 m_it.array_iterator = other.m_it.array_iterator;
6869 m_it.primitive_iterator = other.m_it.primitive_iterator;
6882 : m_object(other.m_object), m_it(other.m_it)
6891 std::is_nothrow_move_constructible<pointer>::value and
6892 std::is_nothrow_move_assignable<pointer>::value and
6893 std::is_nothrow_move_constructible<internal_iterator>::value and
6894 std::is_nothrow_move_assignable<internal_iterator>::value
6897 std::swap(m_object, other.m_object);
6898 std::swap(m_it, other.m_it);
6907 void set_begin() noexcept
6909 assert(m_object !=
nullptr);
6911 switch (m_object->m_type)
6915 m_it.object_iterator = m_object->m_value.object->begin();
6921 m_it.array_iterator = m_object->m_value.array->begin();
6928 m_it.primitive_iterator.set_end();
6934 m_it.primitive_iterator.set_begin();
6944 void set_end() noexcept
6946 assert(m_object !=
nullptr);
6948 switch (m_object->m_type)
6952 m_it.object_iterator = m_object->m_value.object->end();
6958 m_it.array_iterator = m_object->m_value.array->end();
6964 m_it.primitive_iterator.set_end();
6977 assert(m_object !=
nullptr);
6979 switch (m_object->m_type)
6983 assert(m_it.object_iterator != m_object->m_value.object->end());
6984 return m_it.object_iterator->second;
6989 assert(m_it.array_iterator != m_object->m_value.array->end());
6990 return *m_it.array_iterator;
6995 throw std::out_of_range(
"cannot get value");
7000 if (m_it.primitive_iterator.is_begin())
7006 throw std::out_of_range(
"cannot get value");
7018 assert(m_object !=
nullptr);
7020 switch (m_object->m_type)
7024 assert(m_it.object_iterator != m_object->m_value.object->end());
7025 return &(m_it.object_iterator->second);
7030 assert(m_it.array_iterator != m_object->m_value.array->end());
7031 return &*m_it.array_iterator;
7036 if (m_it.primitive_iterator.is_begin())
7042 throw std::out_of_range(
"cannot get value");
7054 auto result = *
this;
7065 assert(m_object !=
nullptr);
7067 switch (m_object->m_type)
7071 std::advance(m_it.object_iterator, 1);
7077 std::advance(m_it.array_iterator, 1);
7083 ++m_it.primitive_iterator;
7097 auto result = *
this;
7108 assert(m_object !=
nullptr);
7110 switch (m_object->m_type)
7114 std::advance(m_it.object_iterator, -1);
7120 std::advance(m_it.array_iterator, -1);
7126 --m_it.primitive_iterator;
7141 if (m_object != other.m_object)
7143 throw std::domain_error(
"cannot compare iterators of different containers");
7146 assert(m_object !=
nullptr);
7148 switch (m_object->m_type)
7152 return (m_it.object_iterator == other.m_it.object_iterator);
7157 return (m_it.array_iterator == other.m_it.array_iterator);
7162 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7173 return not operator==(other);
7183 if (m_object != other.m_object)
7185 throw std::domain_error(
"cannot compare iterators of different containers");
7188 assert(m_object !=
nullptr);
7190 switch (m_object->m_type)
7194 throw std::domain_error(
"cannot compare order of object iterators");
7199 return (m_it.array_iterator < other.m_it.array_iterator);
7204 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7215 return not other.operator < (*this);
7224 return not operator<=(other);
7233 return not operator<(other);
7242 assert(m_object !=
nullptr);
7244 switch (m_object->m_type)
7248 throw std::domain_error(
"cannot use offsets with object iterators");
7253 std::advance(m_it.array_iterator, i);
7259 m_it.primitive_iterator += i;
7273 return operator+=(-i);
7282 auto result = *
this;
7293 auto result = *
this;
7304 assert(m_object !=
nullptr);
7306 switch (m_object->m_type)
7310 throw std::domain_error(
"cannot use offsets with object iterators");
7315 return m_it.array_iterator - other.m_it.array_iterator;
7320 return m_it.primitive_iterator - other.m_it.primitive_iterator;
7331 assert(m_object !=
nullptr);
7333 switch (m_object->m_type)
7337 throw std::domain_error(
"cannot use operator[] for object iterators");
7342 return *std::next(m_it.array_iterator, n);
7347 throw std::out_of_range(
"cannot get value");
7352 if (m_it.primitive_iterator == -n)
7358 throw std::out_of_range(
"cannot get value");
7368 typename object_t::key_type
key()
const 7370 assert(m_object !=
nullptr);
7372 if (m_object->is_object())
7374 return m_it.object_iterator->first;
7378 throw std::domain_error(
"cannot use key() for non-object iterators");
7395 internal_iterator m_it = internal_iterator();
7432 std::is_nothrow_move_constructible<pointer>::value and
7433 std::is_nothrow_move_assignable<pointer>::value and
7434 std::is_nothrow_move_constructible<internal_iterator>::value and
7435 std::is_nothrow_move_assignable<internal_iterator>::value
7438 base_iterator::operator=(other);
7445 return const_cast<reference>(base_iterator::operator*());
7451 return const_cast<pointer>(base_iterator::operator->());
7458 base_iterator::operator++();
7465 base_iterator::operator++();
7473 base_iterator::operator--();
7480 base_iterator::operator--();
7487 base_iterator::operator+=(i);
7494 base_iterator::operator-=(i);
7501 auto result = *
this;
7509 auto result = *
this;
7517 return base_iterator::operator-(other);
7523 return const_cast<reference>(base_iterator::operator[](n));
7529 return const_cast<reference>(base_iterator::value());
7550 template<
typename Base>
7572 return base_iterator::operator++(1);
7578 base_iterator::operator++();
7585 return base_iterator::operator--(1);
7591 base_iterator::operator--();
7598 base_iterator::operator+=(i);
7605 auto result = *
this;
7613 auto result = *
this;
7621 return this->base() - other.base();
7627 return *(this->operator+(n));
7631 typename object_t::key_type
key()
const 7633 auto it = --this->base();
7640 auto it = --this->base();
7641 return it.operator * ();
7662 enum class token_type
7681 using lexer_char_t =
unsigned char;
7684 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
7687 assert(m_content !=
nullptr);
7688 m_start = m_cursor = m_content;
7689 m_limit = m_content + len;
7693 explicit lexer(std::istream& s)
7694 : m_stream(&s), m_line_buffer()
7699 throw std::invalid_argument(
"stream error: " + std::string(strerror(errno)));
7706 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
7708 m_line_buffer[0] =
' ';
7709 m_line_buffer[1] =
' ';
7710 m_line_buffer[2] =
' ';
7716 lexer(
const lexer&) =
delete;
7717 lexer operator=(
const lexer&) =
delete;
7742 static string_t to_unicode(
const std::size_t codepoint1,
7743 const std::size_t codepoint2 = 0)
7746 std::size_t codepoint = codepoint1;
7749 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7752 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7766 throw std::invalid_argument(
"missing or wrong low surrogate");
7772 if (codepoint < 0x80)
7775 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7777 else if (codepoint <= 0x7ff)
7780 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7781 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7783 else if (codepoint <= 0xffff)
7786 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7787 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7788 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7790 else if (codepoint <= 0x10ffff)
7793 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7794 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7795 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7796 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7800 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7807 static std::string token_type_name(
const token_type t)
7811 case token_type::uninitialized:
7812 return "<uninitialized>";
7813 case token_type::literal_true:
7814 return "true literal";
7815 case token_type::literal_false:
7816 return "false literal";
7817 case token_type::literal_null:
7818 return "null literal";
7819 case token_type::value_string:
7820 return "string literal";
7821 case token_type::value_number:
7822 return "number literal";
7823 case token_type::begin_array:
7825 case token_type::begin_object:
7827 case token_type::end_array:
7829 case token_type::end_object:
7831 case token_type::name_separator:
7833 case token_type::value_separator:
7835 case token_type::parse_error:
7836 return "<parse error>";
7837 case token_type::end_of_input:
7838 return "end of input";
7842 return "unknown token";
7877 assert(m_start !=
nullptr);
7882 unsigned int yyaccept = 0;
7883 static const unsigned char yybm[] =
7885 0, 0, 0, 0, 0, 0, 0, 0,
7886 0, 32, 32, 0, 0, 32, 0, 0,
7887 0, 0, 0, 0, 0, 0, 0, 0,
7888 0, 0, 0, 0, 0, 0, 0, 0,
7889 160, 128, 0, 128, 128, 128, 128, 128,
7890 128, 128, 128, 128, 128, 128, 128, 128,
7891 192, 192, 192, 192, 192, 192, 192, 192,
7892 192, 192, 128, 128, 128, 128, 128, 128,
7893 128, 128, 128, 128, 128, 128, 128, 128,
7894 128, 128, 128, 128, 128, 128, 128, 128,
7895 128, 128, 128, 128, 128, 128, 128, 128,
7896 128, 128, 128, 128, 0, 128, 128, 128,
7897 128, 128, 128, 128, 128, 128, 128, 128,
7898 128, 128, 128, 128, 128, 128, 128, 128,
7899 128, 128, 128, 128, 128, 128, 128, 128,
7900 128, 128, 128, 128, 128, 128, 128, 128,
7901 0, 0, 0, 0, 0, 0, 0, 0,
7902 0, 0, 0, 0, 0, 0, 0, 0,
7903 0, 0, 0, 0, 0, 0, 0, 0,
7904 0, 0, 0, 0, 0, 0, 0, 0,
7905 0, 0, 0, 0, 0, 0, 0, 0,
7906 0, 0, 0, 0, 0, 0, 0, 0,
7907 0, 0, 0, 0, 0, 0, 0, 0,
7908 0, 0, 0, 0, 0, 0, 0, 0,
7909 0, 0, 0, 0, 0, 0, 0, 0,
7910 0, 0, 0, 0, 0, 0, 0, 0,
7911 0, 0, 0, 0, 0, 0, 0, 0,
7912 0, 0, 0, 0, 0, 0, 0, 0,
7913 0, 0, 0, 0, 0, 0, 0, 0,
7914 0, 0, 0, 0, 0, 0, 0, 0,
7915 0, 0, 0, 0, 0, 0, 0, 0,
7916 0, 0, 0, 0, 0, 0, 0, 0,
7918 if ((m_limit - m_cursor) < 5)
7920 fill_line_buffer(5);
7923 if (yybm[0 + yych] & 32)
7925 goto basic_json_parser_6;
7935 goto basic_json_parser_2;
7939 goto basic_json_parser_4;
7941 goto basic_json_parser_9;
7947 goto basic_json_parser_4;
7951 goto basic_json_parser_10;
7953 goto basic_json_parser_12;
7962 goto basic_json_parser_4;
7966 goto basic_json_parser_13;
7968 goto basic_json_parser_15;
7974 goto basic_json_parser_17;
7978 goto basic_json_parser_4;
7980 goto basic_json_parser_19;
7992 goto basic_json_parser_21;
7994 goto basic_json_parser_4;
8000 goto basic_json_parser_23;
8004 goto basic_json_parser_4;
8006 goto basic_json_parser_24;
8015 goto basic_json_parser_25;
8017 goto basic_json_parser_4;
8023 goto basic_json_parser_26;
8027 goto basic_json_parser_28;
8029 goto basic_json_parser_4;
8033 basic_json_parser_2:
8036 last_token_type = token_type::end_of_input;
8039 basic_json_parser_4:
8041 basic_json_parser_5:
8043 last_token_type = token_type::parse_error;
8046 basic_json_parser_6:
8048 if (m_limit <= m_cursor)
8050 fill_line_buffer(1);
8053 if (yybm[0 + yych] & 32)
8055 goto basic_json_parser_6;
8060 basic_json_parser_9:
8062 yych = *(m_marker = ++m_cursor);
8065 goto basic_json_parser_5;
8069 goto basic_json_parser_31;
8073 goto basic_json_parser_5;
8077 goto basic_json_parser_31;
8079 goto basic_json_parser_5;
8080 basic_json_parser_10:
8083 last_token_type = token_type::value_separator;
8086 basic_json_parser_12:
8090 goto basic_json_parser_5;
8094 goto basic_json_parser_13;
8098 goto basic_json_parser_15;
8100 goto basic_json_parser_5;
8101 basic_json_parser_13:
8103 yych = *(m_marker = ++m_cursor);
8108 goto basic_json_parser_43;
8115 goto basic_json_parser_44;
8119 goto basic_json_parser_44;
8122 basic_json_parser_14:
8124 last_token_type = token_type::value_number;
8127 basic_json_parser_15:
8129 m_marker = ++m_cursor;
8130 if ((m_limit - m_cursor) < 3)
8132 fill_line_buffer(3);
8135 if (yybm[0 + yych] & 64)
8137 goto basic_json_parser_15;
8143 goto basic_json_parser_43;
8145 goto basic_json_parser_14;
8151 goto basic_json_parser_44;
8155 goto basic_json_parser_44;
8157 goto basic_json_parser_14;
8159 basic_json_parser_17:
8162 last_token_type = token_type::name_separator;
8165 basic_json_parser_19:
8168 last_token_type = token_type::begin_array;
8171 basic_json_parser_21:
8174 last_token_type = token_type::end_array;
8177 basic_json_parser_23:
8179 yych = *(m_marker = ++m_cursor);
8182 goto basic_json_parser_45;
8184 goto basic_json_parser_5;
8185 basic_json_parser_24:
8187 yych = *(m_marker = ++m_cursor);
8190 goto basic_json_parser_46;
8192 goto basic_json_parser_5;
8193 basic_json_parser_25:
8195 yych = *(m_marker = ++m_cursor);
8198 goto basic_json_parser_47;
8200 goto basic_json_parser_5;
8201 basic_json_parser_26:
8204 last_token_type = token_type::begin_object;
8207 basic_json_parser_28:
8210 last_token_type = token_type::end_object;
8213 basic_json_parser_30:
8215 if (m_limit <= m_cursor)
8217 fill_line_buffer(1);
8220 basic_json_parser_31:
8221 if (yybm[0 + yych] & 128)
8223 goto basic_json_parser_30;
8231 goto basic_json_parser_32;
8235 goto basic_json_parser_33;
8237 goto basic_json_parser_35;
8243 goto basic_json_parser_32;
8247 goto basic_json_parser_36;
8249 goto basic_json_parser_37;
8258 goto basic_json_parser_39;
8260 goto basic_json_parser_38;
8266 goto basic_json_parser_40;
8270 goto basic_json_parser_41;
8274 goto basic_json_parser_42;
8278 basic_json_parser_32:
8279 m_cursor = m_marker;
8282 goto basic_json_parser_5;
8286 goto basic_json_parser_14;
8288 basic_json_parser_33:
8291 last_token_type = token_type::value_string;
8294 basic_json_parser_35:
8296 if (m_limit <= m_cursor)
8298 fill_line_buffer(1);
8307 goto basic_json_parser_30;
8311 goto basic_json_parser_32;
8313 goto basic_json_parser_30;
8321 goto basic_json_parser_32;
8323 goto basic_json_parser_30;
8329 goto basic_json_parser_30;
8331 goto basic_json_parser_32;
8341 goto basic_json_parser_30;
8345 goto basic_json_parser_30;
8347 goto basic_json_parser_32;
8355 goto basic_json_parser_30;
8357 goto basic_json_parser_32;
8363 goto basic_json_parser_30;
8367 goto basic_json_parser_48;
8369 goto basic_json_parser_32;
8373 basic_json_parser_36:
8375 if (m_limit <= m_cursor)
8377 fill_line_buffer(1);
8382 goto basic_json_parser_32;
8386 goto basic_json_parser_30;
8388 goto basic_json_parser_32;
8389 basic_json_parser_37:
8391 if (m_limit <= m_cursor)
8393 fill_line_buffer(1);
8398 goto basic_json_parser_32;
8402 goto basic_json_parser_36;
8404 goto basic_json_parser_32;
8405 basic_json_parser_38:
8407 if (m_limit <= m_cursor)
8409 fill_line_buffer(1);
8414 goto basic_json_parser_32;
8418 goto basic_json_parser_36;
8420 goto basic_json_parser_32;
8421 basic_json_parser_39:
8423 if (m_limit <= m_cursor)
8425 fill_line_buffer(1);
8430 goto basic_json_parser_32;
8434 goto basic_json_parser_36;
8436 goto basic_json_parser_32;
8437 basic_json_parser_40:
8439 if (m_limit <= m_cursor)
8441 fill_line_buffer(1);
8446 goto basic_json_parser_32;
8450 goto basic_json_parser_38;
8452 goto basic_json_parser_32;
8453 basic_json_parser_41:
8455 if (m_limit <= m_cursor)
8457 fill_line_buffer(1);
8462 goto basic_json_parser_32;
8466 goto basic_json_parser_38;
8468 goto basic_json_parser_32;
8469 basic_json_parser_42:
8471 if (m_limit <= m_cursor)
8473 fill_line_buffer(1);
8478 goto basic_json_parser_32;
8482 goto basic_json_parser_38;
8484 goto basic_json_parser_32;
8485 basic_json_parser_43:
8489 goto basic_json_parser_32;
8493 goto basic_json_parser_49;
8495 goto basic_json_parser_32;
8496 basic_json_parser_44:
8502 goto basic_json_parser_51;
8504 goto basic_json_parser_32;
8510 goto basic_json_parser_51;
8514 goto basic_json_parser_32;
8518 goto basic_json_parser_52;
8520 goto basic_json_parser_32;
8522 basic_json_parser_45:
8526 goto basic_json_parser_54;
8528 goto basic_json_parser_32;
8529 basic_json_parser_46:
8533 goto basic_json_parser_55;
8535 goto basic_json_parser_32;
8536 basic_json_parser_47:
8540 goto basic_json_parser_56;
8542 goto basic_json_parser_32;
8543 basic_json_parser_48:
8545 if (m_limit <= m_cursor)
8547 fill_line_buffer(1);
8554 goto basic_json_parser_32;
8558 goto basic_json_parser_57;
8560 goto basic_json_parser_32;
8566 goto basic_json_parser_57;
8570 goto basic_json_parser_32;
8574 goto basic_json_parser_57;
8576 goto basic_json_parser_32;
8578 basic_json_parser_49:
8580 m_marker = ++m_cursor;
8581 if ((m_limit - m_cursor) < 3)
8583 fill_line_buffer(3);
8590 goto basic_json_parser_14;
8594 goto basic_json_parser_49;
8596 goto basic_json_parser_14;
8602 goto basic_json_parser_44;
8606 goto basic_json_parser_44;
8608 goto basic_json_parser_14;
8610 basic_json_parser_51:
8614 goto basic_json_parser_32;
8618 goto basic_json_parser_32;
8620 basic_json_parser_52:
8622 if (m_limit <= m_cursor)
8624 fill_line_buffer(1);
8629 goto basic_json_parser_14;
8633 goto basic_json_parser_52;
8635 goto basic_json_parser_14;
8636 basic_json_parser_54:
8640 goto basic_json_parser_58;
8642 goto basic_json_parser_32;
8643 basic_json_parser_55:
8647 goto basic_json_parser_59;
8649 goto basic_json_parser_32;
8650 basic_json_parser_56:
8654 goto basic_json_parser_61;
8656 goto basic_json_parser_32;
8657 basic_json_parser_57:
8659 if (m_limit <= m_cursor)
8661 fill_line_buffer(1);
8668 goto basic_json_parser_32;
8672 goto basic_json_parser_63;
8674 goto basic_json_parser_32;
8680 goto basic_json_parser_63;
8684 goto basic_json_parser_32;
8688 goto basic_json_parser_63;
8690 goto basic_json_parser_32;
8692 basic_json_parser_58:
8696 goto basic_json_parser_64;
8698 goto basic_json_parser_32;
8699 basic_json_parser_59:
8702 last_token_type = token_type::literal_null;
8705 basic_json_parser_61:
8708 last_token_type = token_type::literal_true;
8711 basic_json_parser_63:
8713 if (m_limit <= m_cursor)
8715 fill_line_buffer(1);
8722 goto basic_json_parser_32;
8726 goto basic_json_parser_66;
8728 goto basic_json_parser_32;
8734 goto basic_json_parser_66;
8738 goto basic_json_parser_32;
8742 goto basic_json_parser_66;
8744 goto basic_json_parser_32;
8746 basic_json_parser_64:
8749 last_token_type = token_type::literal_false;
8752 basic_json_parser_66:
8754 if (m_limit <= m_cursor)
8756 fill_line_buffer(1);
8763 goto basic_json_parser_32;
8767 goto basic_json_parser_30;
8769 goto basic_json_parser_32;
8775 goto basic_json_parser_30;
8779 goto basic_json_parser_32;
8783 goto basic_json_parser_30;
8785 goto basic_json_parser_32;
8791 return last_token_type;
8822 void fill_line_buffer(
size_t n = 0)
8825 assert(m_line_buffer.empty()
8826 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
8829 assert(m_line_buffer.empty()
8830 or m_limit == m_content + m_line_buffer.size());
8833 assert(m_content <= m_start);
8834 assert(m_start <= m_cursor);
8835 assert(m_cursor <= m_limit);
8836 assert(m_marker ==
nullptr or m_marker <= m_limit);
8839 const size_t num_processed_chars =
static_cast<size_t>(m_start - m_content);
8841 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8843 const auto offset_cursor = m_cursor - m_start;
8846 if (m_stream ==
nullptr or m_stream->eof())
8851 m_line_buffer.assign(m_start, m_limit);
8855 m_line_buffer.append(1,
'\x00');
8858 m_line_buffer.append(n - 1,
'\x01');
8864 m_line_buffer.erase(0, num_processed_chars);
8866 m_line_buffer_tmp.clear();
8867 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
8870 m_line_buffer += m_line_buffer_tmp;
8871 m_line_buffer.push_back(
'\n');
8875 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
8876 assert(m_content !=
nullptr);
8877 m_start = m_content;
8878 m_marker = m_start + offset_marker;
8879 m_cursor = m_start + offset_cursor;
8880 m_limit = m_start + m_line_buffer.size();
8886 assert(m_start !=
nullptr);
8887 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8888 static_cast<size_t>(m_cursor - m_start));
8950 assert(m_cursor - m_start >= 2);
8953 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8956 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8959 auto e = std::find(i, m_cursor - 1,
'\\');
8963 for (
auto k = i; k < e; k++)
8965 result.push_back(static_cast<typename string_t::value_type>(*k));
9023 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
9024 4).c_str(),
nullptr, 16);
9027 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
9030 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
9032 throw std::invalid_argument(
"missing low surrogate");
9036 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
9037 (i + 7), 4).c_str(),
nullptr, 16);
9038 result += to_unicode(codepoint, codepoint2);
9042 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
9045 throw std::invalid_argument(
"missing high surrogate");
9050 result += to_unicode(codepoint);
9078 long double str_to_float_t(
long double* ,
char** endptr)
const 9080 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9098 double str_to_float_t(
double* ,
char** endptr)
const 9100 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9118 float str_to_float_t(
float* ,
char** endptr)
const 9120 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
9146 assert(m_start !=
nullptr);
9148 const lexer::lexer_char_t* curptr = m_start;
9162 type = value_t::number_integer;
9163 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
9168 type = value_t::number_unsigned;
9169 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
9173 for (; curptr < m_cursor; curptr++)
9176 if (*curptr < '0' || *curptr >
'9')
9181 type = value_t::number_float;
9186 type = value_t::number_float;
9191 if (type != value_t::number_float)
9194 auto temp = value * 10 + *curptr -
'0';
9197 if (temp < value || temp > max)
9200 type = value_t::number_float;
9211 if (type == value_t::number_unsigned)
9213 result.m_value.number_unsigned = value;
9215 else if (type == value_t::number_integer)
9222 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
9225 if (not std::isfinite(result.m_value.number_float))
9227 type = value_t::null;
9228 result.m_value = basic_json::json_value();
9233 result.m_type = type;
9238 std::istream* m_stream =
nullptr;
9244 const lexer_char_t* m_content =
nullptr;
9246 const lexer_char_t* m_start =
nullptr;
9248 const lexer_char_t* m_marker =
nullptr;
9250 const lexer_char_t* m_cursor =
nullptr;
9252 const lexer_char_t* m_limit =
nullptr;
9254 token_type last_token_type = token_type::end_of_input;
9268 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
9273 : callback(cb), m_lexer(is)
9277 template<
class IteratorType,
typename std::enable_if<
9278 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9281 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
9283 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9284 static_cast<size_t>(std::distance(first, last)))
9294 result.assert_invariant();
9296 expect(lexer::token_type::end_of_input);
9307 auto result =
basic_json(value_t::discarded);
9311 case lexer::token_type::begin_object:
9313 if (keep and (not callback
9314 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9317 result.m_type = value_t::object;
9318 result.m_value = value_t::object;
9325 if (last_token == lexer::token_type::end_object)
9328 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9336 unexpect(lexer::token_type::value_separator);
9342 if (last_token == lexer::token_type::value_separator)
9348 expect(lexer::token_type::value_string);
9349 const auto key = m_lexer.get_string();
9351 bool keep_tag =
false;
9357 keep_tag = callback(depth, parse_event_t::key, k);
9367 expect(lexer::token_type::name_separator);
9371 auto value = parse_internal(keep);
9372 if (keep and keep_tag and not value.is_discarded())
9374 result[key] = std::move(value);
9377 while (last_token == lexer::token_type::value_separator);
9380 expect(lexer::token_type::end_object);
9382 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9390 case lexer::token_type::begin_array:
9392 if (keep and (not callback
9393 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9396 result.m_type = value_t::array;
9397 result.m_value = value_t::array;
9404 if (last_token == lexer::token_type::end_array)
9407 if (callback and not callback(--depth, parse_event_t::array_end, result))
9415 unexpect(lexer::token_type::value_separator);
9421 if (last_token == lexer::token_type::value_separator)
9427 auto value = parse_internal(keep);
9428 if (keep and not value.is_discarded())
9430 result.push_back(std::move(value));
9433 while (last_token == lexer::token_type::value_separator);
9436 expect(lexer::token_type::end_array);
9438 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9446 case lexer::token_type::literal_null:
9449 result.m_type = value_t::null;
9453 case lexer::token_type::value_string:
9455 const auto s = m_lexer.get_string();
9461 case lexer::token_type::literal_true:
9464 result.m_type = value_t::boolean;
9465 result.m_value =
true;
9469 case lexer::token_type::literal_false:
9472 result.m_type = value_t::boolean;
9473 result.m_value =
false;
9477 case lexer::token_type::value_number:
9479 m_lexer.get_number(result);
9487 unexpect(last_token);
9491 if (keep and callback and not callback(depth, parse_event_t::value, result))
9499 typename lexer::token_type get_token()
9501 last_token = m_lexer.scan();
9505 void expect(
typename lexer::token_type t)
const 9507 if (t != last_token)
9509 std::string error_msg =
"parse error - unexpected ";
9510 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9512 lexer::token_type_name(last_token));
9513 error_msg +=
"; expected " + lexer::token_type_name(t);
9514 throw std::invalid_argument(error_msg);
9518 void unexpect(
typename lexer::token_type t)
const 9520 if (t == last_token)
9522 std::string error_msg =
"parse error - unexpected ";
9523 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9525 lexer::token_type_name(last_token));
9526 throw std::invalid_argument(error_msg);
9536 typename lexer::token_type last_token = lexer::token_type::uninitialized;
9582 : reference_tokens(split(s))
9600 std::string to_string()
const noexcept
9602 return std::accumulate(reference_tokens.begin(),
9603 reference_tokens.end(), std::string{},
9604 [](
const std::string & a,
const std::string & b)
9606 return a +
"/" + escape(b);
9611 operator std::string()
const 9618 std::string pop_back()
9622 throw std::domain_error(
"JSON pointer has no parent");
9625 auto last = reference_tokens.back();
9626 reference_tokens.pop_back();
9631 bool is_root()
const 9633 return reference_tokens.empty();
9640 throw std::domain_error(
"JSON pointer has no parent");
9644 result.reference_tokens = {reference_tokens[0]};
9659 for (
const auto& reference_token : reference_tokens)
9661 switch (result->m_type)
9665 if (reference_token ==
"0")
9668 result = &result->operator[](0);
9673 result = &result->operator[](reference_token);
9678 case value_t::object:
9681 result = &result->operator[](reference_token);
9685 case value_t::array:
9688 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9701 throw std::domain_error(
"invalid value to unflatten");
9730 for (
const auto& reference_token : reference_tokens)
9733 if (ptr->m_type == value_t::null)
9736 const bool nums = std::all_of(reference_token.begin(),
9737 reference_token.end(),
9740 return std::isdigit(x);
9745 if (nums or reference_token ==
"-")
9747 *ptr = value_t::array;
9751 *ptr = value_t::object;
9755 switch (ptr->m_type)
9757 case value_t::object:
9760 ptr = &ptr->operator[](reference_token);
9764 case value_t::array:
9767 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9769 throw std::domain_error(
"array index must not begin with '0'");
9772 if (reference_token ==
"-")
9775 ptr = &ptr->operator[](ptr->m_value.array->size());
9780 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9787 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9797 for (
const auto& reference_token : reference_tokens)
9799 switch (ptr->m_type)
9801 case value_t::object:
9804 ptr = &ptr->
at(reference_token);
9808 case value_t::array:
9810 if (reference_token ==
"-")
9813 throw std::out_of_range(
"array index '-' (" +
9814 std::to_string(ptr->m_value.array->size()) +
9815 ") is out of range");
9819 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9821 throw std::domain_error(
"array index must not begin with '0'");
9825 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9831 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9849 for (
const auto& reference_token : reference_tokens)
9851 switch (ptr->m_type)
9853 case value_t::object:
9856 ptr = &ptr->operator[](reference_token);
9860 case value_t::array:
9862 if (reference_token ==
"-")
9865 throw std::out_of_range(
"array index '-' (" +
9866 std::to_string(ptr->m_value.array->size()) +
9867 ") is out of range");
9871 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9873 throw std::domain_error(
"array index must not begin with '0'");
9877 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9883 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9893 for (
const auto& reference_token : reference_tokens)
9895 switch (ptr->m_type)
9897 case value_t::object:
9900 ptr = &ptr->
at(reference_token);
9904 case value_t::array:
9906 if (reference_token ==
"-")
9909 throw std::out_of_range(
"array index '-' (" +
9910 std::to_string(ptr->m_value.array->size()) +
9911 ") is out of range");
9915 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9917 throw std::domain_error(
"array index must not begin with '0'");
9921 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9927 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9936 static std::vector<std::string> split(
const std::string& reference_string)
9938 std::vector<std::string> result;
9941 if (reference_string.empty())
9947 if (reference_string[0] !=
'/')
9949 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9957 size_t slash = reference_string.find_first_of(
"/", 1),
9966 slash = reference_string.find_first_of(
"/", start))
9970 auto reference_token = reference_string.substr(start, slash - start);
9973 for (
size_t pos = reference_token.find_first_of(
"~");
9974 pos != std::string::npos;
9975 pos = reference_token.find_first_of(
"~", pos + 1))
9977 assert(reference_token[pos] ==
'~');
9980 if (pos == reference_token.size() - 1 or
9981 (reference_token[pos + 1] !=
'0' and
9982 reference_token[pos + 1] !=
'1'))
9984 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9989 unescape(reference_token);
9990 result.push_back(reference_token);
10011 static void replace_substring(std::string& s,
10012 const std::string& f,
10013 const std::string& t)
10015 assert(not f.empty());
10018 size_t pos = s.find(f);
10019 pos != std::string::npos;
10020 s.replace(pos, f.size(), t),
10021 pos = s.find(f, pos + t.size())
10026 static std::string escape(std::string s)
10029 replace_substring(s,
"~",
"~0");
10030 replace_substring(s,
"/",
"~1");
10035 static void unescape(std::string& s)
10038 replace_substring(s,
"~1",
"/");
10040 replace_substring(s,
"~0",
"~");
10050 static void flatten(
const std::string& reference_string,
10054 switch (value.m_type)
10056 case value_t::array:
10058 if (value.m_value.array->empty())
10061 result[reference_string] =
nullptr;
10066 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
10068 flatten(reference_string +
"/" + std::to_string(i),
10069 value.m_value.array->operator[](i), result);
10075 case value_t::object:
10077 if (value.m_value.object->empty())
10080 result[reference_string] =
nullptr;
10085 for (
const auto& element : *value.m_value.object)
10087 flatten(reference_string +
"/" + escape(element.first),
10088 element.second, result);
10097 result[reference_string] = value;
10112 throw std::domain_error(
"only objects can be unflattened");
10118 for (
const auto& element : *value.m_value.object)
10120 if (not element.second.is_primitive())
10122 throw std::domain_error(
"values in object must be primitive");
10130 json_pointer(element.first).get_and_create(result) = element.second;
10138 std::vector<std::string> reference_tokens {};
10183 return ptr.get_unchecked(
this);
10210 return ptr.get_unchecked(
this);
10235 return ptr.get_checked(
this);
10260 return ptr.get_checked(
this);
10288 json_pointer::flatten(
"", *
this, result);
10321 return json_pointer::unflatten(*
this);
10375 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
10377 const auto get_op = [](
const std::string op)
10381 return patch_operations::add;
10383 if (op ==
"remove")
10385 return patch_operations::remove;
10387 if (op ==
"replace")
10389 return patch_operations::replace;
10393 return patch_operations::move;
10397 return patch_operations::copy;
10401 return patch_operations::test;
10404 return patch_operations::invalid;
10419 if (top_pointer != ptr)
10421 result.
at(top_pointer);
10425 const auto last_path = ptr.pop_back();
10428 switch (parent.m_type)
10430 case value_t::null:
10431 case value_t::object:
10434 parent[last_path] = val;
10438 case value_t::array:
10440 if (last_path ==
"-")
10447 const auto idx = std::stoi(last_path);
10448 if (static_cast<size_type>(idx) > parent.
size())
10451 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
10472 const auto operation_remove = [&result](
json_pointer & ptr)
10475 const auto last_path = ptr.pop_back();
10482 auto it = parent.
find(last_path);
10483 if (it != parent.
end())
10489 throw std::out_of_range(
"key '" + last_path +
"' not found");
10495 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
10503 throw std::invalid_argument(
"JSON patch must be an array of objects");
10507 for (
const auto& val : json_patch)
10510 const auto get_value = [&val](
const std::string & op,
10511 const std::string & member,
10515 auto it = val.m_value.object->find(member);
10518 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
10521 if (it == val.m_value.object->end())
10523 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
10527 if (string_type and not it->second.is_string())
10529 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
10537 if (not val.is_object())
10539 throw std::invalid_argument(
"JSON patch must be an array of objects");
10543 const std::string op = get_value(
"op",
"op",
true);
10544 const std::string path = get_value(op,
"path",
true);
10547 switch (get_op(op))
10549 case patch_operations::add:
10551 operation_add(ptr, get_value(
"add",
"value",
false));
10555 case patch_operations::remove:
10557 operation_remove(ptr);
10561 case patch_operations::replace:
10564 result.
at(ptr) = get_value(
"replace",
"value",
false);
10568 case patch_operations::move:
10570 const std::string from_path = get_value(
"move",
"from",
true);
10580 operation_remove(from_ptr);
10581 operation_add(ptr, v);
10585 case patch_operations::copy:
10587 const std::string from_path = get_value(
"copy",
"from",
true);;
10591 result[ptr] = result.
at(from_ptr);
10595 case patch_operations::test:
10597 bool success =
false;
10602 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
10604 catch (std::out_of_range&)
10612 throw std::domain_error(
"unsuccessful: " + val.dump());
10618 case patch_operations::invalid:
10622 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
10664 const std::string& path =
"")
10670 if (source == target)
10675 if (source.
type() != target.
type())
10687 switch (source.
type())
10689 case value_t::array:
10693 while (i < source.
size() and i < target.
size())
10696 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10697 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10706 while (i < source.
size())
10710 result.insert(result.begin() + end_index, object(
10713 {
"path", path +
"/" + std::to_string(i)}
10719 while (i < target.
size())
10724 {
"path", path +
"/" + std::to_string(i)},
10725 {
"value", target[i]}
10733 case value_t::object:
10736 for (
auto it = source.
begin(); it != source.
end(); ++it)
10739 const auto key = json_pointer::escape(it.key());
10741 if (target.
find(it.key()) != target.
end())
10744 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10745 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10750 result.push_back(
object(
10753 {
"path", path +
"/" + key}
10759 for (
auto it = target.
begin(); it != target.
end(); ++it)
10761 if (source.
find(it.key()) == source.
end())
10764 const auto key = json_pointer::escape(it.key());
10768 {
"path", path +
"/" + key},
10769 {
"value", it.value()}
10829 is_nothrow_move_constructible<nlohmann::json>::value and
10830 is_nothrow_move_assignable<nlohmann::json>::value
10848 const auto& h = hash<nlohmann::json::string_t>();
10867 inline nlohmann::json operator "" _json(
const char* s, std::size_t n)
10891 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10892 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
size_type max_size() const noexcept
returns the maximum possible number of elements
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
constexpr bool is_array() const noexcept
return whether value is an array
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
basic_json(const value_t value_type)
create an empty value with a given type
basic_json(const array_t &val)
create an array (explicit)
reference value() const
return the value of an iterator
const_iterator end() const noexcept
returns a const iterator to one past the last element
constexpr bool is_primitive() const noexcept
return whether type is primitive
constexpr bool is_null() const noexcept
return whether value is null
ValueType get() const
get a value (explicit)
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
constexpr bool is_structured() const noexcept
return whether type is structured
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
const_reference operator[](size_type idx) const
access specified array element
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
json_reverse_iterator operator--(int)
post-decrement (it–)
reference operator[](T *(&key)[n])
access specified object element
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
iterator & operator+=(difference_type i)
add to iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
const_iterator operator-(difference_type i)
subtract from iterator
BooleanType boolean_t
a type for a boolean
reference operator+=(const typename object_t::value_type &val)
add an object to an object
basic_json(const typename string_t::value_type *val)
create a string (explicit)
object_t::key_type key() const
return the key of an object iterator
iterator find(typename object_t::key_type key)
find an element in a JSON object
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
basic_json(const string_t &val)
create a string (explicit)
reference operator*() const
return a reference to the value pointed to by the iterator
void push_back(const basic_json &val)
add an object to an array
void erase(const size_type idx)
remove element from a JSON array given an index
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
reference front()
access the first element
void swap(object_t &other)
exchanges the values
const_iterator & operator+=(difference_type i)
add to iterator
a class to store JSON values
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
constexpr bool is_object() const noexcept
return whether value is an object
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
NumberIntegerType number_integer_t
a type for a number (integer)
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
const_iterator operator+(difference_type i)
add to iterator
a mutable random access iterator for the basic_json class
const_iterator operator++(int)
post-increment (it++)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
pointer operator->() const
dereference the iterator
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
const_reference front() const
access the first element
void emplace_back(Args &&... args)
add an object to an array
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
PointerType get_ptr() noexcept
get a pointer value (implicit)
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference back()
access the last element
const value_type & const_reference
the type of an element const reference
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
void push_back(const typename object_t::value_type &val)
add an object to an object
bool empty() const noexcept
checks whether the container is empty
void push_back(std::initializer_list< basic_json > init)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
IteratorType erase(IteratorType pos)
remove element given an iterator
static allocator_type get_allocator()
returns the allocator associated with the container
json_reverse_iterator operator+(difference_type i) const
add to iterator
string_t dump(const int indent=-1) const
serialization
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
std::size_t size_type
a type to represent container sizes
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
object_t::key_type key() const
return the key of an object iterator
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
iterator & operator++()
pre-increment (++it)
iterator operator++(int)
post-increment (it++)
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
basic_json(basic_json &&other) noexcept
move constructor
const_iterator operator--(int)
post-decrement (it–)
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
object (unordered set of name/value pairs)
iterator operator--(int)
post-decrement (it–)
iterator operator-(difference_type i)
subtract from iterator
const_iterator & operator--()
pre-decrement (–it)
basic_json value_type
the type of elements in a basic_json container
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
AllocatorType< basic_json > allocator_type
the allocator type
StringType string_t
a type for a string
reference operator+=(const basic_json &val)
add an object to an array
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
value_type & reference
the type of an element reference
pointer operator->() const
dereference the iterator
ReferenceType get_ref() const
get a reference value (implicit)
reference value() const
return the value of an iterator
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
size_type size() const noexcept
returns the number of elements
iterator(const iterator &other) noexcept
copy constructor
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
constexpr bool is_string() const noexcept
return whether value is a string
void swap(string_t &other)
exchanges the values
reference operator[](difference_type n) const
access to successor
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference at(size_type idx) const
access specified array element with bounds checking
reference value() const
return the value of an iterator
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
const_reference operator[](T *key) const
read-only access specified object element
NumberFloatType number_float_t
a type for a number (floating-point)
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
std::ptrdiff_t difference_type
a type to represent differences between iterators
difference_type operator-(const const_iterator &other) const
return difference
void swap(array_t &other)
exchanges the values
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
reference operator[](difference_type n) const
access to successor
typename Base::reference reference
the reference type for the pointed-to element
void push_back(basic_json &&val)
add an object to an array
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
difference_type operator-(const iterator &other) const
return difference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
bool operator!=(const const_iterator &other) const
comparison: not equal
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
bool operator==(const const_iterator &other) const
comparison: equal
bool operator<=(const const_iterator &other) const
comparison: less than or equal
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
friend class basic_json
allow basic_json to access private members
reference operator[](difference_type n) const
access to successor
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
iterator operator+(difference_type i)
add to iterator
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_reference back() const
access the last element
const_iterator & operator++()
pre-increment (++it)
constexpr bool is_number() const noexcept
return whether value is a number
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
const_iterator begin() const noexcept
returns a const iterator to the first element
bool operator>(const const_iterator &other) const
comparison: greater than
std::bidirectional_iterator_tag iterator_category
the category of the iterator
basic_json(boolean_t val) noexcept
create a boolean (explicit)
iterator end() noexcept
returns an iterator to one past the last element
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
iterator begin() noexcept
returns an iterator to the first element
const_iterator cend() const noexcept
returns a const iterator to one past the last element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
reference operator[](const typename object_t::key_type &key)
access specified object element
reference operator+=(basic_json &&val)
add an object to an array
a const random access iterator for the basic_json class
a template for a reverse iterator class
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
json_reverse_iterator operator++(int)
post-increment (it++)
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](size_type idx)
access specified array element
json_reverse_iterator & operator+=(difference_type i)
add to iterator
reference at(size_type idx)
access specified array element with bounds checking
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const object_t &val)
create an object (explicit)
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
const_iterator(const const_iterator &other) noexcept
copy constructor
iterator & operator--()
pre-decrement (–it)
reference operator*() const
return a reference to the value pointed to by the iterator
iterator insert(const_iterator pos, basic_json &&val)
inserts element
ReferenceType get_ref()
get a reference value (implicit)
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const CompatibleStringType &val)
create a string (implicit)
basic_json(const basic_json &other)
copy constructor
bool operator<(const const_iterator &other) const
comparison: smaller
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.