29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 42 #include <initializer_list> 54 #include <type_traits> 59 #if defined(__clang__) 60 #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 61 #if CLANG_VERSION < 30400 62 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 64 #elif defined(__GNUC__) 65 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 66 #if GCC_VERSION < 40900 67 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 73 #pragma GCC diagnostic push 74 #pragma GCC diagnostic ignored "-Wfloat-equal" 78 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 79 #define JSON_DEPRECATED __attribute__((deprecated)) 80 #elif defined(_MSC_VER) 81 #define JSON_DEPRECATED __declspec(deprecated) 83 #define JSON_DEPRECATED 112 struct has_mapped_type
115 template<
typename C>
static char test(
typename C::mapped_type*);
116 template<
typename C>
static char (&test(...))[2];
118 static constexpr
bool value =
sizeof(test<T>(0)) == 1;
133 struct DecimalSeparator : std::numpunct<char>
135 char do_decimal_point()
const 222 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
223 template<
typename U,
typename... Args>
class ArrayType = std::vector,
224 class StringType = std::string,
225 class BooleanType = bool,
226 class NumberIntegerType = std::int64_t,
227 class NumberUnsignedType = std::uint64_t,
228 class NumberFloatType = double,
229 template<
typename U>
class AllocatorType = std::allocator
236 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
270 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
272 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
387 using object_t = ObjectType<StringType,
389 std::less<StringType>,
390 AllocatorType<std::pair<
const StringType,
437 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
769 template<
typename T,
typename... Args>
770 static T* create(Args&& ... args)
772 AllocatorType<T> alloc;
773 auto deleter = [&](T * object)
775 alloc.deallocate(
object, 1);
777 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
778 alloc.construct(
object.
get(), std::forward<Args>(args)...);
779 assert(
object.
get() !=
nullptr);
780 return object.release();
829 json_value() =
default;
831 json_value(
boolean_t v) noexcept : boolean(v) {}
843 case value_t::object:
845 object = create<object_t>();
851 array = create<array_t>();
855 case value_t::string:
857 string = create<string_t>(
"");
861 case value_t::boolean:
867 case value_t::number_integer:
873 case value_t::number_unsigned:
879 case value_t::number_float:
895 string = create<string_t>(value);
901 object = create<object_t>(value);
905 json_value(
const array_t& value)
907 array = create<array_t>(value);
920 void assert_invariant()
const 922 assert(m_type != value_t::object or m_value.object !=
nullptr);
923 assert(m_type != value_t::array or m_value.array !=
nullptr);
924 assert(m_type != value_t::string or m_value.string !=
nullptr);
1012 basic_json& parsed)>;
1064 : m_type(value_type), m_value(value_type)
1113 : m_type(
value_t::object), m_value(val)
1144 template<
class CompatibleObjectType,
typename std::enable_if<
1145 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1146 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1152 m_value.object = create<object_t>(begin(val), end(val));
1176 : m_type(
value_t::array), m_value(val)
1207 template<
class CompatibleArrayType,
typename std::enable_if<
1208 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1209 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1210 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1211 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1212 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1213 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1214 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1220 m_value.array = create<array_t>(begin(val), end(val));
1246 : m_type(
value_t::string), m_value(val)
1300 template<
class CompatibleStringType,
typename std::enable_if<
1301 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1323 : m_type(value_t::boolean), m_value(val)
1351 template<
typename T,
typename std::enable_if<
1352 not (std::is_same<T, int>::value) and
1353 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1355 : m_type(value_t::number_integer), m_value(val)
1386 : m_type(value_t::number_integer),
1387 m_value(static_cast<number_integer_t>(val))
1417 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1418 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1419 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1420 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1421 CompatibleNumberIntegerType>::type = 0>
1423 : m_type(value_t::number_integer),
1424 m_value(static_cast<number_integer_t>(val))
1446 template<
typename T,
typename std::enable_if<
1447 not (std::is_same<T, int>::value) and
1448 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1450 : m_type(value_t::number_unsigned), m_value(val)
1475 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1476 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1477 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1478 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1479 CompatibleNumberUnsignedType>::type = 0>
1481 : m_type(value_t::number_unsigned),
1482 m_value(static_cast<number_unsigned_t>(val))
1512 : m_type(value_t::number_float), m_value(val)
1515 if (not std::isfinite(val))
1517 m_type = value_t::null;
1518 m_value = json_value();
1555 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1556 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1557 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1634 bool type_deduction =
true,
1635 value_t manual_type = value_t::array)
1639 bool is_an_object = std::all_of(init.begin(), init.end(),
1642 return element.is_array() and element.size() == 2 and element[0].is_string();
1646 if (not type_deduction)
1649 if (manual_type == value_t::array)
1651 is_an_object =
false;
1655 if (manual_type == value_t::object and not is_an_object)
1657 throw std::domain_error(
"cannot create object from initializer list");
1664 m_type = value_t::object;
1665 m_value = value_t::object;
1667 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1669 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1675 m_type = value_t::array;
1676 m_value.array = create<array_t>(init);
1717 std::initializer_list<basic_json>())
1719 return basic_json(init,
false, value_t::array);
1757 std::initializer_list<basic_json>())
1759 return basic_json(init,
false, value_t::object);
1783 m_value.array = create<array_t>(cnt, val);
1824 template<
class InputIT,
typename std::enable_if<
1825 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1826 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1829 assert(first.m_object !=
nullptr);
1830 assert(last.m_object !=
nullptr);
1833 if (first.m_object != last.m_object)
1835 throw std::domain_error(
"iterators are not compatible");
1839 m_type = first.m_object->m_type;
1844 case value_t::boolean:
1845 case value_t::number_float:
1846 case value_t::number_integer:
1847 case value_t::number_unsigned:
1848 case value_t::string:
1850 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1852 throw std::out_of_range(
"iterators out of range");
1865 case value_t::number_integer:
1867 m_value.number_integer = first.m_object->m_value.number_integer;
1871 case value_t::number_unsigned:
1873 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1877 case value_t::number_float:
1879 m_value.number_float = first.m_object->m_value.number_float;
1883 case value_t::boolean:
1885 m_value.boolean = first.m_object->m_value.boolean;
1889 case value_t::string:
1891 m_value = *first.m_object->m_value.string;
1895 case value_t::object:
1897 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1901 case value_t::array:
1903 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1909 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1947 *
this = parser(i, cb).parse();
1978 : m_type(other.m_type)
1981 other.assert_invariant();
1985 case value_t::object:
1987 m_value = *other.m_value.object;
1991 case value_t::array:
1993 m_value = *other.m_value.array;
1997 case value_t::string:
1999 m_value = *other.m_value.string;
2003 case value_t::boolean:
2005 m_value = other.m_value.boolean;
2009 case value_t::number_integer:
2011 m_value = other.m_value.number_integer;
2015 case value_t::number_unsigned:
2017 m_value = other.m_value.number_unsigned;
2021 case value_t::number_float:
2023 m_value = other.m_value.number_float;
2055 : m_type(
std::move(other.m_type)),
2056 m_value(
std::move(other.m_value))
2059 other.assert_invariant();
2062 other.m_type = value_t::null;
2092 std::is_nothrow_move_constructible<value_t>::value and
2093 std::is_nothrow_move_assignable<value_t>::value and
2094 std::is_nothrow_move_constructible<json_value>::value and
2095 std::is_nothrow_move_assignable<json_value>::value
2099 other.assert_invariant();
2102 swap(m_type, other.m_type);
2103 swap(m_value, other.m_value);
2130 case value_t::object:
2132 AllocatorType<object_t> alloc;
2133 alloc.destroy(m_value.object);
2134 alloc.deallocate(m_value.object, 1);
2138 case value_t::array:
2140 AllocatorType<array_t> alloc;
2141 alloc.destroy(m_value.array);
2142 alloc.deallocate(m_value.array, 1);
2146 case value_t::string:
2148 AllocatorType<string_t> alloc;
2149 alloc.destroy(m_value.string);
2150 alloc.deallocate(m_value.string, 1);
2198 std::stringstream ss;
2200 const static std::locale loc(std::locale(),
new DecimalSeparator);
2207 ss.precision(std::numeric_limits<double>::digits10);
2211 dump(ss,
true, static_cast<unsigned int>(indent));
2271 return is_null() or is_string() or is_boolean() or is_number();
2298 return is_array() or is_object();
2320 return m_type == value_t::null;
2342 return m_type == value_t::boolean;
2372 return is_number_integer() or is_number_float();
2401 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2429 return m_type == value_t::number_unsigned;
2457 return m_type == value_t::number_float;
2479 return m_type == value_t::object;
2501 return m_type == value_t::array;
2523 return m_type == value_t::string;
2550 return m_type == value_t::discarded;
2584 template<
class T,
typename std::enable_if<
2585 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2586 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2587 T get_impl(T*)
const 2591 return T(m_value.object->begin(), m_value.object->end());
2595 throw std::domain_error(
"type must be object, but is " + type_name());
2604 return *(m_value.object);
2608 throw std::domain_error(
"type must be object, but is " + type_name());
2613 template<
class T,
typename std::enable_if<
2614 std::is_convertible<basic_json_t, typename T::value_type>::value and
2615 not std::is_same<basic_json_t, typename T::value_type>::value and
2616 not std::is_arithmetic<T>::value and
2617 not std::is_convertible<std::string, T>::value and
2618 not has_mapped_type<T>::value,
int>::type = 0>
2619 T get_impl(T*)
const 2624 std::transform(m_value.array->begin(), m_value.array->end(),
2625 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2627 return i.
get<
typename T::value_type>();
2633 throw std::domain_error(
"type must be array, but is " + type_name());
2638 template<
class T,
typename std::enable_if<
2639 std::is_convertible<basic_json_t, T>::value and
2640 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2641 std::vector<T> get_impl(std::vector<T>*)
const 2645 std::vector<T> to_vector;
2646 to_vector.reserve(m_value.array->size());
2647 std::transform(m_value.array->begin(), m_value.array->end(),
2648 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2656 throw std::domain_error(
"type must be array, but is " + type_name());
2661 template<
class T,
typename std::enable_if<
2662 std::is_same<basic_json, typename T::value_type>::value and
2663 not has_mapped_type<T>::value,
int>::type = 0>
2664 T get_impl(T*)
const 2668 return T(m_value.array->begin(), m_value.array->end());
2672 throw std::domain_error(
"type must be array, but is " + type_name());
2681 return *(m_value.array);
2685 throw std::domain_error(
"type must be array, but is " + type_name());
2690 template<
typename T,
typename std::enable_if<
2691 std::is_convertible<string_t, T>::value,
int>::type = 0>
2692 T get_impl(T*)
const 2696 return *m_value.string;
2700 throw std::domain_error(
"type must be string, but is " + type_name());
2705 template<
typename T,
typename std::enable_if<
2706 std::is_arithmetic<T>::value,
int>::type = 0>
2707 T get_impl(T*)
const 2711 case value_t::number_integer:
2713 return static_cast<T
>(m_value.number_integer);
2716 case value_t::number_unsigned:
2718 return static_cast<T
>(m_value.number_unsigned);
2721 case value_t::number_float:
2723 return static_cast<T
>(m_value.number_float);
2728 throw std::domain_error(
"type must be number, but is " + type_name());
2738 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2744 return is_object() ? m_value.object :
nullptr;
2750 return is_object() ? m_value.object :
nullptr;
2756 return is_array() ? m_value.array :
nullptr;
2760 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2762 return is_array() ? m_value.array :
nullptr;
2768 return is_string() ? m_value.string :
nullptr;
2774 return is_string() ? m_value.string :
nullptr;
2780 return is_boolean() ? &m_value.boolean :
nullptr;
2786 return is_boolean() ? &m_value.boolean :
nullptr;
2792 return is_number_integer() ? &m_value.number_integer :
nullptr;
2798 return is_number_integer() ? &m_value.number_integer :
nullptr;
2804 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2810 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2816 return is_number_float() ? &m_value.number_float :
nullptr;
2822 return is_number_float() ? &m_value.number_float :
nullptr;
2836 template<
typename ReferenceType,
typename ThisType>
2837 static ReferenceType get_ref_impl(ThisType& obj)
2840 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2843 auto ptr = obj.template get_ptr<PointerType>();
2851 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2895 template<
typename ValueType,
typename std::enable_if<
2896 not std::is_pointer<ValueType>::value,
int>::type = 0>
2897 ValueType
get()
const 2899 return get_impl(static_cast<ValueType*>(
nullptr));
2929 template<
typename PointerType,
typename std::enable_if<
2930 std::is_pointer<PointerType>::value,
int>::type = 0>
2931 PointerType
get() noexcept
2934 return get_ptr<PointerType>();
2941 template<
typename PointerType,
typename std::enable_if<
2942 std::is_pointer<PointerType>::value,
int>::type = 0>
2943 constexpr
const PointerType
get()
const noexcept
2946 return get_ptr<PointerType>();
2975 template<
typename PointerType,
typename std::enable_if<
2976 std::is_pointer<PointerType>::value,
int>::type = 0>
2980 using pointee_t =
typename std::remove_const<
typename 2981 std::remove_pointer<
typename 2982 std::remove_const<PointerType>::type>::type>::type;
2985 std::is_same<object_t, pointee_t>::value
2986 or std::is_same<array_t, pointee_t>::value
2987 or std::is_same<string_t, pointee_t>::value
2988 or std::is_same<boolean_t, pointee_t>::value
2989 or std::is_same<number_integer_t, pointee_t>::value
2990 or std::is_same<number_unsigned_t, pointee_t>::value
2991 or std::is_same<number_float_t, pointee_t>::value
2992 ,
"incompatible pointer type");
2995 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3002 template<
typename PointerType,
typename std::enable_if<
3003 std::is_pointer<PointerType>::value and
3004 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3005 constexpr
const PointerType
get_ptr() const noexcept
3008 using pointee_t =
typename std::remove_const<
typename 3009 std::remove_pointer<
typename 3010 std::remove_const<PointerType>::type>::type>::type;
3013 std::is_same<object_t, pointee_t>::value
3014 or std::is_same<array_t, pointee_t>::value
3015 or std::is_same<string_t, pointee_t>::value
3016 or std::is_same<boolean_t, pointee_t>::value
3017 or std::is_same<number_integer_t, pointee_t>::value
3018 or std::is_same<number_unsigned_t, pointee_t>::value
3019 or std::is_same<number_float_t, pointee_t>::value
3020 ,
"incompatible pointer type");
3023 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3052 template<
typename ReferenceType,
typename std::enable_if<
3053 std::is_reference<ReferenceType>::value,
int>::type = 0>
3057 return get_ref_impl<ReferenceType>(*this);
3064 template<
typename ReferenceType,
typename std::enable_if<
3065 std::is_reference<ReferenceType>::value and
3066 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3070 return get_ref_impl<ReferenceType>(*this);
3101 template <
typename ValueType,
typename std::enable_if <
3102 not std::is_pointer<ValueType>::value and
3103 not std::is_same<ValueType, typename string_t::value_type>::value
3104 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3105 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3108 operator ValueType()
const 3111 return get<ValueType>();
3154 return m_value.
array->
at(idx);
3156 catch (std::out_of_range&)
3159 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3164 throw std::domain_error(
"cannot use at() with " + type_name());
3197 return m_value.
array->
at(idx);
3199 catch (std::out_of_range&)
3202 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3207 throw std::domain_error(
"cannot use at() with " + type_name());
3246 catch (std::out_of_range&)
3249 throw std::out_of_range(
"key '" + key +
"' not found");
3254 throw std::domain_error(
"cannot use at() with " + type_name());
3293 catch (std::out_of_range&)
3296 throw std::out_of_range(
"key '" + key +
"' not found");
3301 throw std::domain_error(
"cannot use at() with " + type_name());
3335 m_type = value_t::array;
3336 m_value.
array = create<array_t>();
3344 if (idx >= m_value.array->size())
3346 m_value.array->insert(m_value.array->end(),
3347 idx - m_value.array->size() + 1,
3351 return m_value.array->operator[](idx);
3355 throw std::domain_error(
"cannot use operator[] with " + type_name());
3383 return m_value.
array->operator[](idx);
3387 throw std::domain_error(
"cannot use operator[] with " + type_name());
3423 m_type = value_t::object;
3424 m_value.
object = create<object_t>();
3431 return m_value.object->operator[](key);
3435 throw std::domain_error(
"cannot use operator[] with " + type_name());
3474 assert(m_value.object->find(key) != m_value.object->end());
3479 throw std::domain_error(
"cannot use operator[] with " + type_name());
3510 template<
typename T, std::
size_t n>
3513 return operator[](static_cast<const T>(key));
3545 template<
typename T, std::
size_t n>
3548 return operator[](static_cast<const T>(key));
3578 template<
typename T>
3584 m_type = value_t::object;
3585 m_value = value_t::object;
3592 return m_value.object->operator[](key);
3596 throw std::domain_error(
"cannot use operator[] with " + type_name());
3630 template<
typename T>
3636 assert(m_value.object->find(key) != m_value.object->end());
3641 throw std::domain_error(
"cannot use operator[] with " + type_name());
3693 template<
class ValueType,
typename std::enable_if<
3694 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3695 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3701 const auto it = find(key);
3708 return default_value;
3713 throw std::domain_error(
"cannot use value() with " + type_name());
3721 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3723 return value(key,
string_t(default_value));
3767 template<
class ValueType,
typename std::enable_if<
3768 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3777 return ptr.get_checked(
this);
3779 catch (std::out_of_range&)
3781 return default_value;
3786 throw std::domain_error(
"cannot use value() with " + type_name());
3796 return value(ptr,
string_t(default_value));
3929 template<
class IteratorType,
typename std::enable_if<
3930 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3931 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3936 if (
this != pos.m_object)
3938 throw std::domain_error(
"iterator does not fit current value");
3941 IteratorType result = end();
3945 case value_t::boolean:
3946 case value_t::number_float:
3947 case value_t::number_integer:
3948 case value_t::number_unsigned:
3949 case value_t::string:
3951 if (not pos.m_it.primitive_iterator.is_begin())
3953 throw std::out_of_range(
"iterator out of range");
3958 AllocatorType<string_t> alloc;
3959 alloc.destroy(m_value.string);
3960 alloc.deallocate(m_value.string, 1);
3961 m_value.string =
nullptr;
3964 m_type = value_t::null;
3969 case value_t::object:
3971 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3975 case value_t::array:
3977 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3983 throw std::domain_error(
"cannot use erase() with " + type_name());
4036 template<
class IteratorType,
typename std::enable_if<
4037 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4038 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4040 IteratorType
erase(IteratorType first, IteratorType last)
4043 if (
this != first.m_object or
this != last.m_object)
4045 throw std::domain_error(
"iterators do not fit current value");
4048 IteratorType result = end();
4052 case value_t::boolean:
4053 case value_t::number_float:
4054 case value_t::number_integer:
4055 case value_t::number_unsigned:
4056 case value_t::string:
4058 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4060 throw std::out_of_range(
"iterators out of range");
4065 AllocatorType<string_t> alloc;
4066 alloc.destroy(m_value.string);
4067 alloc.deallocate(m_value.string, 1);
4068 m_value.string =
nullptr;
4071 m_type = value_t::null;
4076 case value_t::object:
4078 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4079 last.m_it.object_iterator);
4083 case value_t::array:
4085 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4086 last.m_it.array_iterator);
4092 throw std::domain_error(
"cannot use erase() with " + type_name());
4133 return m_value.object->erase(key);
4137 throw std::domain_error(
"cannot use erase() with " + type_name());
4172 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4175 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4179 throw std::domain_error(
"cannot use erase() with " + type_name());
4213 auto result = end();
4217 result.m_it.object_iterator = m_value.object->find(key);
4229 auto result = cend();
4233 result.m_it.object_iterator = m_value.object->find(key);
4260 return is_object() ? m_value.object->count(key) : 0;
4548 template<
typename IteratorType>
class iteration_proxy;
4564 return iteration_proxy<iterator>(cont);
4572 return iteration_proxy<const_iterator>(cont);
4632 case value_t::array:
4635 return m_value.array->empty();
4638 case value_t::object:
4641 return m_value.object->empty();
4700 case value_t::array:
4703 return m_value.array->size();
4706 case value_t::object:
4709 return m_value.object->size();
4760 case value_t::array:
4763 return m_value.array->max_size();
4766 case value_t::object:
4769 return m_value.object->max_size();
4819 case value_t::number_integer:
4821 m_value.number_integer = 0;
4825 case value_t::number_unsigned:
4827 m_value.number_unsigned = 0;
4831 case value_t::number_float:
4833 m_value.number_float = 0.0;
4837 case value_t::boolean:
4839 m_value.boolean =
false;
4843 case value_t::string:
4845 m_value.string->clear();
4849 case value_t::array:
4851 m_value.array->clear();
4855 case value_t::object:
4857 m_value.object->clear();
4891 if (not(is_null() or is_array()))
4893 throw std::domain_error(
"cannot use push_back() with " + type_name());
4899 m_type = value_t::array;
4900 m_value = value_t::array;
4905 m_value.array->push_back(std::move(val));
4907 val.m_type = value_t::null;
4916 push_back(std::move(val));
4927 if (not(is_null() or is_array()))
4929 throw std::domain_error(
"cannot use push_back() with " + type_name());
4935 m_type = value_t::array;
4936 m_value = value_t::array;
4941 m_value.array->push_back(val);
4977 if (not(is_null() or is_object()))
4979 throw std::domain_error(
"cannot use push_back() with " + type_name());
4985 m_type = value_t::object;
4986 m_value = value_t::object;
4991 m_value.object->insert(val);
5031 if (is_object() and init.size() == 2 and init.begin()->is_string())
5033 const string_t key = *init.begin();
5034 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5080 if (pos.m_object !=
this)
5082 throw std::domain_error(
"iterator does not fit current value");
5087 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5092 throw std::domain_error(
"cannot use insert() with " + type_name());
5102 return insert(pos, val);
5135 if (pos.m_object !=
this)
5137 throw std::domain_error(
"iterator does not fit current value");
5142 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5147 throw std::domain_error(
"cannot use insert() with " + type_name());
5186 throw std::domain_error(
"cannot use insert() with " + type_name());
5190 if (pos.m_object !=
this)
5192 throw std::domain_error(
"iterator does not fit current value");
5196 if (first.m_object != last.m_object)
5198 throw std::domain_error(
"iterators do not fit");
5201 if (first.m_object ==
this or last.m_object ==
this)
5203 throw std::domain_error(
"passed iterators may not belong to container");
5208 result.m_it.array_iterator = m_value.array->insert(
5209 pos.m_it.array_iterator,
5210 first.m_it.array_iterator,
5211 last.m_it.array_iterator);
5244 throw std::domain_error(
"cannot use insert() with " + type_name());
5248 if (pos.m_object !=
this)
5250 throw std::domain_error(
"iterator does not fit current value");
5255 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5277 std::is_nothrow_move_constructible<value_t>::value and
5278 std::is_nothrow_move_assignable<value_t>::value and
5279 std::is_nothrow_move_constructible<json_value>::value and
5280 std::is_nothrow_move_assignable<json_value>::value
5283 std::swap(m_type, other.m_type);
5284 std::swap(m_value, other.m_value);
5313 std::swap(*(m_value.array), other);
5317 throw std::domain_error(
"cannot use swap() with " + type_name());
5346 std::swap(*(m_value.object), other);
5350 throw std::domain_error(
"cannot use swap() with " + type_name());
5379 std::swap(*(m_value.string), other);
5383 throw std::domain_error(
"cannot use swap() with " + type_name());
5409 static constexpr std::array<uint8_t, 8> order = {{
5422 if (lhs == value_t::discarded or rhs == value_t::discarded)
5427 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5456 const auto lhs_type = lhs.type();
5457 const auto rhs_type = rhs.type();
5459 if (lhs_type == rhs_type)
5463 case value_t::array:
5465 return *lhs.m_value.array == *rhs.m_value.array;
5467 case value_t::object:
5469 return *lhs.m_value.object == *rhs.m_value.object;
5475 case value_t::string:
5477 return *lhs.m_value.string == *rhs.m_value.string;
5479 case value_t::boolean:
5481 return lhs.m_value.boolean == rhs.m_value.boolean;
5483 case value_t::number_integer:
5485 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5487 case value_t::number_unsigned:
5489 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5491 case value_t::number_float:
5493 return lhs.m_value.number_float == rhs.m_value.number_float;
5501 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5503 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5505 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5507 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5509 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5511 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5513 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5515 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5517 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5519 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5521 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5523 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5579 return not (lhs == rhs);
5611 return not v.is_null();
5640 const auto lhs_type = lhs.type();
5641 const auto rhs_type = rhs.type();
5643 if (lhs_type == rhs_type)
5647 case value_t::array:
5649 return *lhs.m_value.array < *rhs.m_value.array;
5651 case value_t::object:
5653 return *lhs.m_value.object < *rhs.m_value.object;
5659 case value_t::string:
5661 return *lhs.m_value.string < *rhs.m_value.string;
5663 case value_t::boolean:
5665 return lhs.m_value.boolean < rhs.m_value.boolean;
5667 case value_t::number_integer:
5669 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5671 case value_t::number_unsigned:
5673 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5675 case value_t::number_float:
5677 return lhs.m_value.number_float < rhs.m_value.number_float;
5685 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5687 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5689 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5691 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5693 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5695 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5697 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5699 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5701 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5703 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5705 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5707 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5713 return operator<(lhs_type, rhs_type);
5735 return not (rhs < lhs);
5757 return not (lhs <= rhs);
5779 return not (lhs < rhs);
5821 const bool pretty_print = (o.width() > 0);
5822 const auto indentation = (pretty_print ? o.width() : 0);
5828 const auto old_locale = o.imbue(std::locale(std::locale(),
new DecimalSeparator));
5835 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5838 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5841 o.imbue(old_locale);
5842 o.precision(old_precision);
5892 template<
class T, std::
size_t N>
5897 return parse(std::begin(array), std::end(array), cb);
5927 template<
typename CharPT,
typename std::enable_if<
5928 std::is_pointer<CharPT>::value and
5929 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5930 sizeof(
typename std::remove_pointer<CharPT>::type) == 1,
int>::type = 0>
5934 return parser(reinterpret_cast<const char*>(s), cb).
parse();
5964 return parser(i, cb).
parse();
5973 return parser(i, cb).
parse();
6017 template<
class IteratorType,
typename std::enable_if<
6019 std::random_access_iterator_tag,
6020 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6026 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6027 [&first](std::pair<bool, int> res, decltype(*first) val)
6029 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6034 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6035 "each element in the iterator range must have the size of 1 byte");
6039 if (std::distance(first, last) <= 0)
6041 return parser(
"").parse();
6044 return parser(first, last, cb).parse();
6087 template<
class ContiguousContainer,
typename std::enable_if<
6088 not std::is_pointer<ContiguousContainer>::value and
6090 std::random_access_iterator_tag,
6091 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6097 return parse(std::begin(c), std::end(c), cb);
6125 j = parser(i).
parse();
6135 j = parser(i).
parse();
6159 std::string type_name()
const 6165 case value_t::object:
6167 case value_t::array:
6169 case value_t::string:
6171 case value_t::boolean:
6173 case value_t::discarded:
6188 static std::size_t extra_space(
const string_t& s) noexcept
6190 return std::accumulate(s.begin(), s.end(),
size_t{},
6191 [](
size_t res,
typename string_t::value_type c)
6209 if (c >= 0x00 and c <= 0x1f)
6238 const auto space = extra_space(s);
6245 string_t result(s.size() + space,
'\\');
6246 std::size_t pos = 0;
6248 for (
const auto& c : s)
6255 result[pos + 1] =
'"';
6271 result[pos + 1] =
'b';
6279 result[pos + 1] =
'f';
6287 result[pos + 1] =
'n';
6295 result[pos + 1] =
'r';
6303 result[pos + 1] =
't';
6310 if (c >= 0x00 and c <= 0x1f)
6314 static const char hexify[16] =
6316 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
6317 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 6322 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
6360 void dump(std::ostream& o,
6361 const bool pretty_print,
6362 const unsigned int indent_step,
6363 const unsigned int current_indent = 0)
const 6366 unsigned int new_indent = current_indent;
6370 case value_t::object:
6372 if (m_value.object->empty())
6383 new_indent += indent_step;
6387 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6389 if (i != m_value.object->cbegin())
6391 o << (pretty_print ?
",\n" :
",");
6393 o <<
string_t(new_indent,
' ') <<
"\"" 6394 << escape_string(i->first) <<
"\":" 6395 << (pretty_print ?
" " :
"");
6396 i->second.dump(o, pretty_print, indent_step, new_indent);
6402 new_indent -= indent_step;
6406 o <<
string_t(new_indent,
' ') +
"}";
6410 case value_t::array:
6412 if (m_value.array->empty())
6423 new_indent += indent_step;
6427 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6429 if (i != m_value.array->cbegin())
6431 o << (pretty_print ?
",\n" :
",");
6434 i->dump(o, pretty_print, indent_step, new_indent);
6440 new_indent -= indent_step;
6444 o <<
string_t(new_indent,
' ') <<
"]";
6448 case value_t::string:
6450 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6454 case value_t::boolean:
6456 o << (m_value.boolean ?
"true" :
"false");
6460 case value_t::number_integer:
6462 o << m_value.number_integer;
6466 case value_t::number_unsigned:
6468 o << m_value.number_unsigned;
6472 case value_t::number_float:
6474 if (m_value.number_float == 0)
6477 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6481 o << m_value.number_float;
6486 case value_t::discarded:
6506 value_t m_type = value_t::null;
6509 json_value m_value = {};
6526 class primitive_iterator_t
6530 void set_begin() noexcept
6536 void set_end() noexcept
6542 constexpr
bool is_begin()
const noexcept
6544 return (m_it == begin_value);
6548 constexpr
bool is_end()
const noexcept
6550 return (m_it == end_value);
6570 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6580 struct internal_iterator
6583 typename object_t::iterator object_iterator;
6585 typename array_t::iterator array_iterator;
6587 primitive_iterator_t primitive_iterator;
6590 internal_iterator() noexcept
6591 : object_iterator(), array_iterator(), primitive_iterator()
6596 template<
typename IteratorType>
6597 class iteration_proxy
6601 class iteration_proxy_internal
6605 IteratorType anchor;
6607 size_t array_index = 0;
6610 explicit iteration_proxy_internal(IteratorType it) noexcept
6615 iteration_proxy_internal& operator*()
6621 iteration_proxy_internal& operator++()
6630 bool operator!= (
const iteration_proxy_internal& o)
const 6632 return anchor != o.anchor;
6638 assert(anchor.m_object !=
nullptr);
6640 switch (anchor.m_object->type())
6643 case value_t::array:
6645 return std::to_string(array_index);
6649 case value_t::object:
6651 return anchor.key();
6663 typename IteratorType::reference value()
const 6665 return anchor.value();
6670 typename IteratorType::reference container;
6674 explicit iteration_proxy(
typename IteratorType::reference cont)
6679 iteration_proxy_internal begin() noexcept
6681 return iteration_proxy_internal(container.begin());
6685 iteration_proxy_internal end() noexcept
6687 return iteration_proxy_internal(container.end());
6711 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6740 assert(m_object !=
nullptr);
6742 switch (m_object->m_type)
6746 m_it.object_iterator =
typename object_t::iterator();
6752 m_it.array_iterator =
typename array_t::iterator();
6758 m_it.primitive_iterator = primitive_iterator_t();
6770 : m_object(other.m_object)
6772 if (m_object !=
nullptr)
6774 switch (m_object->m_type)
6778 m_it.object_iterator = other.m_it.object_iterator;
6784 m_it.array_iterator = other.m_it.array_iterator;
6790 m_it.primitive_iterator = other.m_it.primitive_iterator;
6803 : m_object(other.m_object), m_it(other.m_it)
6812 std::is_nothrow_move_constructible<pointer>::value and
6813 std::is_nothrow_move_assignable<pointer>::value and
6814 std::is_nothrow_move_constructible<internal_iterator>::value and
6815 std::is_nothrow_move_assignable<internal_iterator>::value
6818 std::swap(m_object, other.m_object);
6819 std::swap(m_it, other.m_it);
6828 void set_begin() noexcept
6830 assert(m_object !=
nullptr);
6832 switch (m_object->m_type)
6836 m_it.object_iterator = m_object->m_value.object->begin();
6842 m_it.array_iterator = m_object->m_value.array->begin();
6849 m_it.primitive_iterator.set_end();
6855 m_it.primitive_iterator.set_begin();
6865 void set_end() noexcept
6867 assert(m_object !=
nullptr);
6869 switch (m_object->m_type)
6873 m_it.object_iterator = m_object->m_value.object->end();
6879 m_it.array_iterator = m_object->m_value.array->end();
6885 m_it.primitive_iterator.set_end();
6898 assert(m_object !=
nullptr);
6900 switch (m_object->m_type)
6904 assert(m_it.object_iterator != m_object->m_value.object->end());
6905 return m_it.object_iterator->second;
6910 assert(m_it.array_iterator != m_object->m_value.array->end());
6911 return *m_it.array_iterator;
6916 throw std::out_of_range(
"cannot get value");
6921 if (m_it.primitive_iterator.is_begin())
6927 throw std::out_of_range(
"cannot get value");
6939 assert(m_object !=
nullptr);
6941 switch (m_object->m_type)
6945 assert(m_it.object_iterator != m_object->m_value.object->end());
6946 return &(m_it.object_iterator->second);
6951 assert(m_it.array_iterator != m_object->m_value.array->end());
6952 return &*m_it.array_iterator;
6957 if (m_it.primitive_iterator.is_begin())
6963 throw std::out_of_range(
"cannot get value");
6975 auto result = *
this;
6986 assert(m_object !=
nullptr);
6988 switch (m_object->m_type)
6992 std::advance(m_it.object_iterator, 1);
6998 std::advance(m_it.array_iterator, 1);
7004 ++m_it.primitive_iterator;
7018 auto result = *
this;
7029 assert(m_object !=
nullptr);
7031 switch (m_object->m_type)
7035 std::advance(m_it.object_iterator, -1);
7041 std::advance(m_it.array_iterator, -1);
7047 --m_it.primitive_iterator;
7062 if (m_object != other.m_object)
7064 throw std::domain_error(
"cannot compare iterators of different containers");
7067 assert(m_object !=
nullptr);
7069 switch (m_object->m_type)
7073 return (m_it.object_iterator == other.m_it.object_iterator);
7078 return (m_it.array_iterator == other.m_it.array_iterator);
7083 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7094 return not operator==(other);
7104 if (m_object != other.m_object)
7106 throw std::domain_error(
"cannot compare iterators of different containers");
7109 assert(m_object !=
nullptr);
7111 switch (m_object->m_type)
7115 throw std::domain_error(
"cannot compare order of object iterators");
7120 return (m_it.array_iterator < other.m_it.array_iterator);
7125 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7136 return not other.operator < (*this);
7145 return not operator<=(other);
7154 return not operator<(other);
7163 assert(m_object !=
nullptr);
7165 switch (m_object->m_type)
7169 throw std::domain_error(
"cannot use offsets with object iterators");
7174 std::advance(m_it.array_iterator, i);
7180 m_it.primitive_iterator += i;
7194 return operator+=(-i);
7203 auto result = *
this;
7214 auto result = *
this;
7225 assert(m_object !=
nullptr);
7227 switch (m_object->m_type)
7231 throw std::domain_error(
"cannot use offsets with object iterators");
7236 return m_it.array_iterator - other.m_it.array_iterator;
7241 return m_it.primitive_iterator - other.m_it.primitive_iterator;
7252 assert(m_object !=
nullptr);
7254 switch (m_object->m_type)
7258 throw std::domain_error(
"cannot use operator[] for object iterators");
7263 return *std::next(m_it.array_iterator, n);
7268 throw std::out_of_range(
"cannot get value");
7273 if (m_it.primitive_iterator == -n)
7279 throw std::out_of_range(
"cannot get value");
7289 typename object_t::key_type
key()
const 7291 assert(m_object !=
nullptr);
7293 if (m_object->is_object())
7295 return m_it.object_iterator->first;
7299 throw std::domain_error(
"cannot use key() for non-object iterators");
7316 internal_iterator m_it = internal_iterator();
7353 std::is_nothrow_move_constructible<pointer>::value and
7354 std::is_nothrow_move_assignable<pointer>::value and
7355 std::is_nothrow_move_constructible<internal_iterator>::value and
7356 std::is_nothrow_move_assignable<internal_iterator>::value
7359 base_iterator::operator=(other);
7366 return const_cast<reference>(base_iterator::operator*());
7372 return const_cast<pointer>(base_iterator::operator->());
7379 base_iterator::operator++();
7386 base_iterator::operator++();
7394 base_iterator::operator--();
7401 base_iterator::operator--();
7408 base_iterator::operator+=(i);
7415 base_iterator::operator-=(i);
7422 auto result = *
this;
7430 auto result = *
this;
7438 return base_iterator::operator-(other);
7444 return const_cast<reference>(base_iterator::operator[](n));
7450 return const_cast<reference>(base_iterator::value());
7471 template<
typename Base>
7493 return base_iterator::operator++(1);
7499 base_iterator::operator++();
7506 return base_iterator::operator--(1);
7512 base_iterator::operator--();
7519 base_iterator::operator+=(i);
7526 auto result = *
this;
7534 auto result = *
this;
7542 return this->base() - other.base();
7548 return *(this->operator+(n));
7552 typename object_t::key_type
key()
const 7554 auto it = --this->base();
7561 auto it = --this->base();
7562 return it.operator * ();
7583 enum class token_type
7602 using lexer_char_t =
unsigned char;
7605 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
7608 assert(m_content !=
nullptr);
7609 m_start = m_cursor = m_content;
7610 m_limit = m_content + len;
7614 explicit lexer(std::istream& s)
7615 : m_stream(&s), m_line_buffer()
7623 lexer(
const lexer&) =
delete;
7624 lexer operator=(
const lexer&) =
delete;
7649 static string_t to_unicode(
const std::size_t codepoint1,
7650 const std::size_t codepoint2 = 0)
7653 std::size_t codepoint = codepoint1;
7656 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7659 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7673 throw std::invalid_argument(
"missing or wrong low surrogate");
7679 if (codepoint < 0x80)
7682 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7684 else if (codepoint <= 0x7ff)
7687 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7688 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7690 else if (codepoint <= 0xffff)
7693 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7694 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7695 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7697 else if (codepoint <= 0x10ffff)
7700 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7701 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7702 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7703 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7707 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7714 static std::string token_type_name(
const token_type t)
7718 case token_type::uninitialized:
7719 return "<uninitialized>";
7720 case token_type::literal_true:
7721 return "true literal";
7722 case token_type::literal_false:
7723 return "false literal";
7724 case token_type::literal_null:
7725 return "null literal";
7726 case token_type::value_string:
7727 return "string literal";
7728 case token_type::value_number:
7729 return "number literal";
7730 case token_type::begin_array:
7732 case token_type::begin_object:
7734 case token_type::end_array:
7736 case token_type::end_object:
7738 case token_type::name_separator:
7740 case token_type::value_separator:
7742 case token_type::parse_error:
7743 return "<parse error>";
7744 case token_type::end_of_input:
7745 return "end of input";
7749 return "unknown token";
7784 assert(m_start !=
nullptr);
7789 unsigned int yyaccept = 0;
7790 static const unsigned char yybm[] = {
7791 0, 0, 0, 0, 0, 0, 0, 0,
7792 0, 32, 32, 0, 0, 32, 0, 0,
7793 0, 0, 0, 0, 0, 0, 0, 0,
7794 0, 0, 0, 0, 0, 0, 0, 0,
7795 160, 128, 0, 128, 128, 128, 128, 128,
7796 128, 128, 128, 128, 128, 128, 128, 128,
7797 192, 192, 192, 192, 192, 192, 192, 192,
7798 192, 192, 128, 128, 128, 128, 128, 128,
7799 128, 128, 128, 128, 128, 128, 128, 128,
7800 128, 128, 128, 128, 128, 128, 128, 128,
7801 128, 128, 128, 128, 128, 128, 128, 128,
7802 128, 128, 128, 128, 0, 128, 128, 128,
7803 128, 128, 128, 128, 128, 128, 128, 128,
7804 128, 128, 128, 128, 128, 128, 128, 128,
7805 128, 128, 128, 128, 128, 128, 128, 128,
7806 128, 128, 128, 128, 128, 128, 128, 128,
7807 128, 128, 128, 128, 128, 128, 128, 128,
7808 128, 128, 128, 128, 128, 128, 128, 128,
7809 128, 128, 128, 128, 128, 128, 128, 128,
7810 128, 128, 128, 128, 128, 128, 128, 128,
7811 128, 128, 128, 128, 128, 128, 128, 128,
7812 128, 128, 128, 128, 128, 128, 128, 128,
7813 128, 128, 128, 128, 128, 128, 128, 128,
7814 128, 128, 128, 128, 128, 128, 128, 128,
7815 128, 128, 128, 128, 128, 128, 128, 128,
7816 128, 128, 128, 128, 128, 128, 128, 128,
7817 128, 128, 128, 128, 128, 128, 128, 128,
7818 128, 128, 128, 128, 128, 128, 128, 128,
7819 128, 128, 128, 128, 128, 128, 128, 128,
7820 128, 128, 128, 128, 128, 128, 128, 128,
7821 128, 128, 128, 128, 128, 128, 128, 128,
7822 128, 128, 128, 128, 128, 128, 128, 128,
7824 if ((m_limit - m_cursor) < 5) fill_line_buffer();
7826 if (yybm[0+yych] & 32) {
7827 goto basic_json_parser_6;
7832 if (yych <= 0x00)
goto basic_json_parser_2;
7833 if (yych <=
'!')
goto basic_json_parser_4;
7834 goto basic_json_parser_9;
7836 if (yych <=
'+')
goto basic_json_parser_4;
7837 if (yych <=
',')
goto basic_json_parser_10;
7838 goto basic_json_parser_12;
7842 if (yych <=
'/')
goto basic_json_parser_4;
7843 if (yych <=
'0')
goto basic_json_parser_13;
7844 goto basic_json_parser_15;
7846 if (yych <=
':')
goto basic_json_parser_17;
7847 if (yych ==
'[')
goto basic_json_parser_19;
7848 goto basic_json_parser_4;
7854 if (yych <=
']')
goto basic_json_parser_21;
7855 if (yych <=
'e')
goto basic_json_parser_4;
7856 goto basic_json_parser_23;
7858 if (yych ==
'n')
goto basic_json_parser_24;
7859 if (yych <=
's')
goto basic_json_parser_4;
7860 goto basic_json_parser_25;
7864 if (yych ==
'{')
goto basic_json_parser_26;
7865 goto basic_json_parser_4;
7867 if (yych <=
'}')
goto basic_json_parser_28;
7868 if (yych == 0xEF)
goto basic_json_parser_30;
7869 goto basic_json_parser_4;
7873 basic_json_parser_2:
7875 { last_token_type = token_type::end_of_input;
break; }
7876 basic_json_parser_4:
7878 basic_json_parser_5:
7879 { last_token_type = token_type::parse_error;
break; }
7880 basic_json_parser_6:
7882 if (m_limit <= m_cursor) fill_line_buffer();
7884 if (yybm[0+yych] & 32) {
7885 goto basic_json_parser_6;
7888 basic_json_parser_9:
7890 yych = *(m_marker = ++m_cursor);
7891 if (yych <= 0x1F)
goto basic_json_parser_5;
7892 goto basic_json_parser_32;
7893 basic_json_parser_10:
7895 { last_token_type = token_type::value_separator;
break; }
7896 basic_json_parser_12:
7898 if (yych <=
'/')
goto basic_json_parser_5;
7899 if (yych <=
'0')
goto basic_json_parser_13;
7900 if (yych <=
'9')
goto basic_json_parser_15;
7901 goto basic_json_parser_5;
7902 basic_json_parser_13:
7904 yych = *(m_marker = ++m_cursor);
7906 if (yych ==
'.')
goto basic_json_parser_37;
7908 if (yych <=
'E')
goto basic_json_parser_38;
7909 if (yych ==
'e')
goto basic_json_parser_38;
7911 basic_json_parser_14:
7912 { last_token_type = token_type::value_number;
break; }
7913 basic_json_parser_15:
7915 m_marker = ++m_cursor;
7916 if ((m_limit - m_cursor) < 3) fill_line_buffer();
7918 if (yybm[0+yych] & 64) {
7919 goto basic_json_parser_15;
7922 if (yych ==
'.')
goto basic_json_parser_37;
7923 goto basic_json_parser_14;
7925 if (yych <=
'E')
goto basic_json_parser_38;
7926 if (yych ==
'e')
goto basic_json_parser_38;
7927 goto basic_json_parser_14;
7929 basic_json_parser_17:
7931 { last_token_type = token_type::name_separator;
break; }
7932 basic_json_parser_19:
7934 { last_token_type = token_type::begin_array;
break; }
7935 basic_json_parser_21:
7937 { last_token_type = token_type::end_array;
break; }
7938 basic_json_parser_23:
7940 yych = *(m_marker = ++m_cursor);
7941 if (yych ==
'a')
goto basic_json_parser_39;
7942 goto basic_json_parser_5;
7943 basic_json_parser_24:
7945 yych = *(m_marker = ++m_cursor);
7946 if (yych ==
'u')
goto basic_json_parser_40;
7947 goto basic_json_parser_5;
7948 basic_json_parser_25:
7950 yych = *(m_marker = ++m_cursor);
7951 if (yych ==
'r')
goto basic_json_parser_41;
7952 goto basic_json_parser_5;
7953 basic_json_parser_26:
7955 { last_token_type = token_type::begin_object;
break; }
7956 basic_json_parser_28:
7958 { last_token_type = token_type::end_object;
break; }
7959 basic_json_parser_30:
7961 yych = *(m_marker = ++m_cursor);
7962 if (yych == 0xBB)
goto basic_json_parser_42;
7963 goto basic_json_parser_5;
7964 basic_json_parser_31:
7966 if (m_limit <= m_cursor) fill_line_buffer();
7968 basic_json_parser_32:
7969 if (yybm[0+yych] & 128) {
7970 goto basic_json_parser_31;
7972 if (yych <= 0x1F)
goto basic_json_parser_33;
7973 if (yych <=
'"')
goto basic_json_parser_34;
7974 goto basic_json_parser_36;
7975 basic_json_parser_33:
7976 m_cursor = m_marker;
7977 if (yyaccept == 0) {
7978 goto basic_json_parser_5;
7980 goto basic_json_parser_14;
7982 basic_json_parser_34:
7984 { last_token_type = token_type::value_string;
break; }
7985 basic_json_parser_36:
7987 if (m_limit <= m_cursor) fill_line_buffer();
7991 if (yych ==
'"')
goto basic_json_parser_31;
7992 if (yych <=
'.')
goto basic_json_parser_33;
7993 goto basic_json_parser_31;
7996 if (yych <=
'[')
goto basic_json_parser_33;
7997 goto basic_json_parser_31;
7999 if (yych ==
'b')
goto basic_json_parser_31;
8000 goto basic_json_parser_33;
8005 if (yych <=
'f')
goto basic_json_parser_31;
8006 if (yych ==
'n')
goto basic_json_parser_31;
8007 goto basic_json_parser_33;
8010 if (yych <=
'r')
goto basic_json_parser_31;
8011 goto basic_json_parser_33;
8013 if (yych <=
't')
goto basic_json_parser_31;
8014 if (yych <=
'u')
goto basic_json_parser_43;
8015 goto basic_json_parser_33;
8019 basic_json_parser_37:
8021 if (yych <=
'/')
goto basic_json_parser_33;
8022 if (yych <=
'9')
goto basic_json_parser_44;
8023 goto basic_json_parser_33;
8024 basic_json_parser_38:
8027 if (yych ==
'+')
goto basic_json_parser_46;
8028 goto basic_json_parser_33;
8030 if (yych <=
'-')
goto basic_json_parser_46;
8031 if (yych <=
'/')
goto basic_json_parser_33;
8032 if (yych <=
'9')
goto basic_json_parser_47;
8033 goto basic_json_parser_33;
8035 basic_json_parser_39:
8037 if (yych ==
'l')
goto basic_json_parser_49;
8038 goto basic_json_parser_33;
8039 basic_json_parser_40:
8041 if (yych ==
'l')
goto basic_json_parser_50;
8042 goto basic_json_parser_33;
8043 basic_json_parser_41:
8045 if (yych ==
'u')
goto basic_json_parser_51;
8046 goto basic_json_parser_33;
8047 basic_json_parser_42:
8049 if (yych == 0xBF)
goto basic_json_parser_52;
8050 goto basic_json_parser_33;
8051 basic_json_parser_43:
8053 if (m_limit <= m_cursor) fill_line_buffer();
8056 if (yych <=
'/')
goto basic_json_parser_33;
8057 if (yych <=
'9')
goto basic_json_parser_54;
8058 goto basic_json_parser_33;
8060 if (yych <=
'F')
goto basic_json_parser_54;
8061 if (yych <=
'`')
goto basic_json_parser_33;
8062 if (yych <=
'f')
goto basic_json_parser_54;
8063 goto basic_json_parser_33;
8065 basic_json_parser_44:
8067 m_marker = ++m_cursor;
8068 if ((m_limit - m_cursor) < 3) fill_line_buffer();
8071 if (yych <=
'/')
goto basic_json_parser_14;
8072 if (yych <=
'9')
goto basic_json_parser_44;
8073 goto basic_json_parser_14;
8075 if (yych <=
'E')
goto basic_json_parser_38;
8076 if (yych ==
'e')
goto basic_json_parser_38;
8077 goto basic_json_parser_14;
8079 basic_json_parser_46:
8081 if (yych <=
'/')
goto basic_json_parser_33;
8082 if (yych >=
':')
goto basic_json_parser_33;
8083 basic_json_parser_47:
8085 if (m_limit <= m_cursor) fill_line_buffer();
8087 if (yych <=
'/')
goto basic_json_parser_14;
8088 if (yych <=
'9')
goto basic_json_parser_47;
8089 goto basic_json_parser_14;
8090 basic_json_parser_49:
8092 if (yych ==
's')
goto basic_json_parser_55;
8093 goto basic_json_parser_33;
8094 basic_json_parser_50:
8096 if (yych ==
'l')
goto basic_json_parser_56;
8097 goto basic_json_parser_33;
8098 basic_json_parser_51:
8100 if (yych ==
'e')
goto basic_json_parser_58;
8101 goto basic_json_parser_33;
8102 basic_json_parser_52:
8105 basic_json_parser_54:
8107 if (m_limit <= m_cursor) fill_line_buffer();
8110 if (yych <=
'/')
goto basic_json_parser_33;
8111 if (yych <=
'9')
goto basic_json_parser_60;
8112 goto basic_json_parser_33;
8114 if (yych <=
'F')
goto basic_json_parser_60;
8115 if (yych <=
'`')
goto basic_json_parser_33;
8116 if (yych <=
'f')
goto basic_json_parser_60;
8117 goto basic_json_parser_33;
8119 basic_json_parser_55:
8121 if (yych ==
'e')
goto basic_json_parser_61;
8122 goto basic_json_parser_33;
8123 basic_json_parser_56:
8125 { last_token_type = token_type::literal_null;
break; }
8126 basic_json_parser_58:
8128 { last_token_type = token_type::literal_true;
break; }
8129 basic_json_parser_60:
8131 if (m_limit <= m_cursor) fill_line_buffer();
8134 if (yych <=
'/')
goto basic_json_parser_33;
8135 if (yych <=
'9')
goto basic_json_parser_63;
8136 goto basic_json_parser_33;
8138 if (yych <=
'F')
goto basic_json_parser_63;
8139 if (yych <=
'`')
goto basic_json_parser_33;
8140 if (yych <=
'f')
goto basic_json_parser_63;
8141 goto basic_json_parser_33;
8143 basic_json_parser_61:
8145 { last_token_type = token_type::literal_false;
break; }
8146 basic_json_parser_63:
8148 if (m_limit <= m_cursor) fill_line_buffer();
8151 if (yych <=
'/')
goto basic_json_parser_33;
8152 if (yych <=
'9')
goto basic_json_parser_31;
8153 goto basic_json_parser_33;
8155 if (yych <=
'F')
goto basic_json_parser_31;
8156 if (yych <=
'`')
goto basic_json_parser_33;
8157 if (yych <=
'f')
goto basic_json_parser_31;
8158 goto basic_json_parser_33;
8164 return last_token_type;
8195 void fill_line_buffer()
8198 const auto offset_start = m_start - m_content;
8200 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8202 const auto offset_cursor = m_cursor - m_start;
8205 if (m_stream ==
nullptr or m_stream->eof())
8208 m_line_buffer.clear();
8209 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8211 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8217 m_line_buffer.append(5,
'\0');
8222 m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8225 std::getline(*m_stream, line);
8227 m_line_buffer +=
"\n" + line;
8231 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.c_str());
8232 assert(m_content !=
nullptr);
8233 m_start = m_content;
8234 m_marker = m_start + offset_marker;
8235 m_cursor = m_start + offset_cursor;
8236 m_limit = m_start + m_line_buffer.size();
8242 assert(m_start !=
nullptr);
8243 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8244 static_cast<size_t>(m_cursor - m_start));
8306 assert(m_cursor - m_start >= 2);
8309 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8312 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8368 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8369 4).c_str(),
nullptr, 16);
8372 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8375 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8377 throw std::invalid_argument(
"missing low surrogate");
8381 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8382 (i + 7), 4).c_str(),
nullptr, 16);
8383 result += to_unicode(codepoint, codepoint2);
8390 result += to_unicode(codepoint);
8402 result.append(1, static_cast<typename string_t::value_type>(*i));
8424 long double str_to_float_t(
long double* ,
char** endptr)
const 8426 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8444 double str_to_float_t(
double* ,
char** endptr)
const 8446 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8464 float str_to_float_t(
float* ,
char** endptr)
const 8466 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8492 assert(m_start !=
nullptr);
8494 const lexer::lexer_char_t* curptr = m_start;
8508 type = value_t::number_integer;
8509 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8514 type = value_t::number_unsigned;
8515 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8519 for (; curptr < m_cursor; curptr++)
8522 if (*curptr < '0' || *curptr >
'9')
8527 type = value_t::number_float;
8532 type = value_t::number_float;
8537 if (type != value_t::number_float)
8540 auto temp = value * 10 + *curptr -
'0';
8543 if (temp < value || temp > max)
8546 type = value_t::number_float;
8557 if (type == value_t::number_unsigned)
8559 result.m_value.number_unsigned = value;
8561 else if (type == value_t::number_integer)
8568 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8572 result.m_type = type;
8577 std::istream* m_stream =
nullptr;
8581 const lexer_char_t* m_content =
nullptr;
8583 const lexer_char_t* m_start =
nullptr;
8585 const lexer_char_t* m_marker =
nullptr;
8587 const lexer_char_t* m_cursor =
nullptr;
8589 const lexer_char_t* m_limit =
nullptr;
8591 token_type last_token_type = token_type::end_of_input;
8605 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
8610 : callback(cb), m_lexer(is)
8614 template<
class IteratorType,
typename std::enable_if<
8615 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
8618 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
8620 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
8621 static_cast<size_t>(std::distance(first, last)))
8631 result.assert_invariant();
8633 expect(lexer::token_type::end_of_input);
8644 auto result =
basic_json(value_t::discarded);
8648 case lexer::token_type::begin_object:
8650 if (keep and (not callback
8651 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
8654 result.m_type = value_t::object;
8655 result.m_value = value_t::object;
8662 if (last_token == lexer::token_type::end_object)
8665 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8673 unexpect(lexer::token_type::value_separator);
8679 if (last_token == lexer::token_type::value_separator)
8685 expect(lexer::token_type::value_string);
8686 const auto key = m_lexer.get_string();
8688 bool keep_tag =
false;
8694 keep_tag = callback(depth, parse_event_t::key, k);
8704 expect(lexer::token_type::name_separator);
8708 auto value = parse_internal(keep);
8709 if (keep and keep_tag and not value.is_discarded())
8711 result[key] = std::move(value);
8714 while (last_token == lexer::token_type::value_separator);
8717 expect(lexer::token_type::end_object);
8719 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8727 case lexer::token_type::begin_array:
8729 if (keep and (not callback
8730 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
8733 result.m_type = value_t::array;
8734 result.m_value = value_t::array;
8741 if (last_token == lexer::token_type::end_array)
8744 if (callback and not callback(--depth, parse_event_t::array_end, result))
8752 unexpect(lexer::token_type::value_separator);
8758 if (last_token == lexer::token_type::value_separator)
8764 auto value = parse_internal(keep);
8765 if (keep and not value.is_discarded())
8767 result.push_back(std::move(value));
8770 while (last_token == lexer::token_type::value_separator);
8773 expect(lexer::token_type::end_array);
8775 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8783 case lexer::token_type::literal_null:
8786 result.m_type = value_t::null;
8790 case lexer::token_type::value_string:
8792 const auto s = m_lexer.get_string();
8798 case lexer::token_type::literal_true:
8801 result.m_type = value_t::boolean;
8802 result.m_value =
true;
8806 case lexer::token_type::literal_false:
8809 result.m_type = value_t::boolean;
8810 result.m_value =
false;
8814 case lexer::token_type::value_number:
8816 m_lexer.get_number(result);
8824 unexpect(last_token);
8828 if (keep and callback and not callback(depth, parse_event_t::value, result))
8836 typename lexer::token_type get_token()
8838 last_token = m_lexer.scan();
8842 void expect(
typename lexer::token_type t)
const 8844 if (t != last_token)
8846 std::string error_msg =
"parse error - unexpected ";
8847 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
8849 lexer::token_type_name(last_token));
8850 error_msg +=
"; expected " + lexer::token_type_name(t);
8851 throw std::invalid_argument(error_msg);
8855 void unexpect(
typename lexer::token_type t)
const 8857 if (t == last_token)
8859 std::string error_msg =
"parse error - unexpected ";
8860 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
8862 lexer::token_type_name(last_token));
8863 throw std::invalid_argument(error_msg);
8873 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8919 : reference_tokens(split(s))
8937 std::string to_string()
const noexcept
8939 return std::accumulate(reference_tokens.begin(),
8940 reference_tokens.end(), std::string{},
8941 [](
const std::string & a,
const std::string & b)
8943 return a +
"/" + escape(b);
8948 operator std::string()
const 8955 std::string pop_back()
8959 throw std::domain_error(
"JSON pointer has no parent");
8962 auto last = reference_tokens.back();
8963 reference_tokens.pop_back();
8968 bool is_root()
const 8970 return reference_tokens.empty();
8977 throw std::domain_error(
"JSON pointer has no parent");
8981 result.reference_tokens = {reference_tokens[0]};
8996 for (
const auto& reference_token : reference_tokens)
8998 switch (result->m_type)
9002 if (reference_token ==
"0")
9005 result = &result->operator[](0);
9010 result = &result->operator[](reference_token);
9015 case value_t::object:
9018 result = &result->operator[](reference_token);
9022 case value_t::array:
9025 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9038 throw std::domain_error(
"invalid value to unflatten");
9061 for (
const auto& reference_token : reference_tokens)
9063 switch (ptr->m_type)
9065 case value_t::object:
9068 ptr = &ptr->operator[](reference_token);
9072 case value_t::array:
9075 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9077 throw std::domain_error(
"array index must not begin with '0'");
9080 if (reference_token ==
"-")
9083 ptr = &ptr->operator[](ptr->m_value.array->size());
9088 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9095 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9105 for (
const auto& reference_token : reference_tokens)
9107 switch (ptr->m_type)
9109 case value_t::object:
9112 ptr = &ptr->
at(reference_token);
9116 case value_t::array:
9118 if (reference_token ==
"-")
9121 throw std::out_of_range(
"array index '-' (" +
9122 std::to_string(ptr->m_value.array->size()) +
9123 ") is out of range");
9127 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9129 throw std::domain_error(
"array index must not begin with '0'");
9133 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9139 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9157 for (
const auto& reference_token : reference_tokens)
9159 switch (ptr->m_type)
9161 case value_t::object:
9164 ptr = &ptr->operator[](reference_token);
9168 case value_t::array:
9170 if (reference_token ==
"-")
9173 throw std::out_of_range(
"array index '-' (" +
9174 std::to_string(ptr->m_value.array->size()) +
9175 ") is out of range");
9179 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9181 throw std::domain_error(
"array index must not begin with '0'");
9185 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9191 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9201 for (
const auto& reference_token : reference_tokens)
9203 switch (ptr->m_type)
9205 case value_t::object:
9208 ptr = &ptr->
at(reference_token);
9212 case value_t::array:
9214 if (reference_token ==
"-")
9217 throw std::out_of_range(
"array index '-' (" +
9218 std::to_string(ptr->m_value.array->size()) +
9219 ") is out of range");
9223 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9225 throw std::domain_error(
"array index must not begin with '0'");
9229 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9235 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9244 static std::vector<std::string> split(
const std::string& reference_string)
9246 std::vector<std::string> result;
9249 if (reference_string.empty())
9255 if (reference_string[0] !=
'/')
9257 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9265 size_t slash = reference_string.find_first_of(
"/", 1),
9274 slash = reference_string.find_first_of(
"/", start))
9278 auto reference_token = reference_string.substr(start, slash - start);
9281 for (
size_t pos = reference_token.find_first_of(
"~");
9282 pos != std::string::npos;
9283 pos = reference_token.find_first_of(
"~", pos + 1))
9285 assert(reference_token[pos] ==
'~');
9288 if (pos == reference_token.size() - 1 or
9289 (reference_token[pos + 1] !=
'0' and
9290 reference_token[pos + 1] !=
'1'))
9292 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9297 unescape(reference_token);
9298 result.push_back(reference_token);
9319 static void replace_substring(std::string& s,
9320 const std::string& f,
9321 const std::string& t)
9323 assert(not f.empty());
9326 size_t pos = s.find(f);
9327 pos != std::string::npos;
9328 s.replace(pos, f.size(), t),
9329 pos = s.find(f, pos + t.size())
9334 static std::string escape(std::string s)
9337 replace_substring(s,
"~",
"~0");
9338 replace_substring(s,
"/",
"~1");
9343 static void unescape(std::string& s)
9346 replace_substring(s,
"~1",
"/");
9348 replace_substring(s,
"~0",
"~");
9358 static void flatten(
const std::string& reference_string,
9362 switch (value.m_type)
9364 case value_t::array:
9366 if (value.m_value.array->empty())
9369 result[reference_string] =
nullptr;
9374 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9376 flatten(reference_string +
"/" + std::to_string(i),
9377 value.m_value.array->operator[](i), result);
9383 case value_t::object:
9385 if (value.m_value.object->empty())
9388 result[reference_string] =
nullptr;
9393 for (
const auto& element : *value.m_value.object)
9395 flatten(reference_string +
"/" + escape(element.first),
9396 element.second, result);
9405 result[reference_string] = value;
9420 throw std::domain_error(
"only objects can be unflattened");
9426 for (
const auto& element : *value.m_value.object)
9428 if (not element.second.is_primitive())
9430 throw std::domain_error(
"values in object must be primitive");
9438 json_pointer(element.first).get_and_create(result) = element.second;
9446 std::vector<std::string> reference_tokens {};
9491 return ptr.get_unchecked(
this);
9518 return ptr.get_unchecked(
this);
9543 return ptr.get_checked(
this);
9568 return ptr.get_checked(
this);
9596 json_pointer::flatten(
"", *
this, result);
9629 return json_pointer::unflatten(*
this);
9683 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9685 const auto get_op = [](
const std::string op)
9689 return patch_operations::add;
9693 return patch_operations::remove;
9695 if (op ==
"replace")
9697 return patch_operations::replace;
9701 return patch_operations::move;
9705 return patch_operations::copy;
9709 return patch_operations::test;
9712 return patch_operations::invalid;
9727 if (top_pointer != ptr)
9729 result.
at(top_pointer);
9733 const auto last_path = ptr.pop_back();
9736 switch (parent.m_type)
9739 case value_t::object:
9742 parent[last_path] = val;
9746 case value_t::array:
9748 if (last_path ==
"-")
9755 const auto idx = std::stoi(last_path);
9756 if (static_cast<size_type>(idx) > parent.
size())
9759 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9780 const auto operation_remove = [&result](
json_pointer & ptr)
9783 const auto last_path = ptr.pop_back();
9790 auto it = parent.
find(last_path);
9791 if (it != parent.
end())
9797 throw std::out_of_range(
"key '" + last_path +
"' not found");
9803 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9811 throw std::invalid_argument(
"JSON patch must be an array of objects");
9815 for (
const auto& val : json_patch)
9818 const auto get_value = [&val](
const std::string & op,
9819 const std::string & member,
9823 auto it = val.m_value.object->find(member);
9826 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9829 if (it == val.m_value.object->end())
9831 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9835 if (string_type and not it->second.is_string())
9837 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9845 if (not val.is_object())
9847 throw std::invalid_argument(
"JSON patch must be an array of objects");
9851 const std::string op = get_value(
"op",
"op",
true);
9852 const std::string path = get_value(op,
"path",
true);
9857 case patch_operations::add:
9859 operation_add(ptr, get_value(
"add",
"value",
false));
9863 case patch_operations::remove:
9865 operation_remove(ptr);
9869 case patch_operations::replace:
9872 result.
at(ptr) = get_value(
"replace",
"value",
false);
9876 case patch_operations::move:
9878 const std::string from_path = get_value(
"move",
"from",
true);
9888 operation_remove(from_ptr);
9889 operation_add(ptr, v);
9893 case patch_operations::copy:
9895 const std::string from_path = get_value(
"copy",
"from",
true);;
9899 result[ptr] = result.
at(from_ptr);
9903 case patch_operations::test:
9905 bool success =
false;
9910 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9912 catch (std::out_of_range&)
9920 throw std::domain_error(
"unsuccessful: " + val.dump());
9926 case patch_operations::invalid:
9930 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9972 const std::string& path =
"")
9978 if (source == target)
9983 if (source.
type() != target.
type())
9995 switch (source.
type())
9997 case value_t::array:
10001 while (i < source.
size() and i < target.
size())
10004 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10005 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10014 while (i < source.
size())
10018 result.insert(result.begin() + end_index, object(
10021 {
"path", path +
"/" + std::to_string(i)}
10027 while (i < target.
size())
10032 {
"path", path +
"/" + std::to_string(i)},
10033 {
"value", target[i]}
10041 case value_t::object:
10044 for (
auto it = source.
begin(); it != source.
end(); ++it)
10047 const auto key = json_pointer::escape(it.key());
10049 if (target.
find(it.key()) != target.
end())
10052 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10053 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10058 result.push_back(
object(
10061 {
"path", path +
"/" + key}
10067 for (
auto it = target.
begin(); it != target.
end(); ++it)
10069 if (source.
find(it.key()) == source.
end())
10072 const auto key = json_pointer::escape(it.key());
10076 {
"path", path +
"/" + key},
10077 {
"value", it.value()}
10137 is_nothrow_move_constructible<nlohmann::json>::value and
10138 is_nothrow_move_assignable<nlohmann::json>::value
10156 const auto& h = hash<nlohmann::json::string_t>();
10174 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10197 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10198 #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
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)
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
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
const_reference operator[](size_type idx) const
access specified array element
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
reference value() const
return the value of an iterator
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
bool operator==(const const_iterator &other) const
comparison: equal
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
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
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
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
BooleanType boolean_t
a type for a boolean
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
reference operator+=(const typename object_t::value_type &val)
add an object to an object
reference operator*() const
return a reference to the value pointed to by the iterator
basic_json(const typename string_t::value_type *val)
create a string (explicit)
reference operator[](difference_type n) const
access to successor
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)
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
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
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
reference value() const
return the value of an iterator
constexpr bool is_object() const noexcept
return whether value is an object
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
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_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
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)
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
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
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
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
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
reference operator[](difference_type n) const
access to successor
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
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_reference operator[](T *key) const
read-only access specified object element
json_reverse_iterator operator+(difference_type i) const
add to iterator
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
object_t::key_type key() const
return the key of an object iterator
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
const_reference at(size_type idx) const
access specified array element with bounds checking
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
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)
bool operator<(const const_iterator &other) const
comparison: smaller
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
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
const_iterator & operator--()
pre-decrement (–it)
string_t dump(const int indent=-1) const
serialization
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
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
difference_type operator-(const const_iterator &other) const
return difference
value_type & reference
the type of an element reference
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
size_type size() const noexcept
returns the number of elements
difference_type operator-(const iterator &other) const
return difference
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
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference front() const
access the first element
bool operator>(const const_iterator &other) const
comparison: greater than
pointer operator->() const
dereference the iterator
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
ValueType get() const
get a value (explicit)
void swap(array_t &other)
exchanges the values
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
typename Base::reference reference
the reference type for the pointed-to element
const_reference back() const
access the last 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)
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
ReferenceType get_ref() const
get a reference value (implicit)
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
reference operator*() const
return a reference to the value pointed to by the iterator
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
friend class basic_json
allow basic_json to access private members
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)
bool operator<=(const const_iterator &other) const
comparison: less than or equal
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
const_iterator & operator++()
pre-increment (++it)
pointer operator->() const
dereference the iterator
constexpr bool is_number() const noexcept
return whether value is a number
reference value() const
return the value of an iterator
const_iterator begin() const noexcept
returns a const iterator to the first element
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
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
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
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
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
object_t::key_type key() const
return the key of an object iterator
reference operator+=(basic_json &&val)
add an object to an array
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
reference operator[](difference_type n) const
access to successor
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
bool operator!=(const const_iterator &other) const
comparison: not equal
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
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)
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
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.