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);
5602 return not v.is_null();
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[] =
7792 0, 0, 0, 0, 0, 0, 0, 0,
7793 0, 32, 32, 0, 0, 32, 0, 0,
7794 0, 0, 0, 0, 0, 0, 0, 0,
7795 0, 0, 0, 0, 0, 0, 0, 0,
7796 160, 128, 0, 128, 128, 128, 128, 128,
7797 128, 128, 128, 128, 128, 128, 128, 128,
7798 192, 192, 192, 192, 192, 192, 192, 192,
7799 192, 192, 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, 128, 128, 128, 128,
7803 128, 128, 128, 128, 0, 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,
7823 128, 128, 128, 128, 128, 128, 128, 128,
7825 if ((m_limit - m_cursor) < 5)
7830 if (yybm[0 + yych] & 32)
7832 goto basic_json_parser_6;
7842 goto basic_json_parser_2;
7846 goto basic_json_parser_4;
7848 goto basic_json_parser_9;
7854 goto basic_json_parser_4;
7858 goto basic_json_parser_10;
7860 goto basic_json_parser_12;
7869 goto basic_json_parser_4;
7873 goto basic_json_parser_13;
7875 goto basic_json_parser_15;
7881 goto basic_json_parser_17;
7885 goto basic_json_parser_19;
7887 goto basic_json_parser_4;
7899 goto basic_json_parser_21;
7903 goto basic_json_parser_4;
7905 goto basic_json_parser_23;
7911 goto basic_json_parser_24;
7915 goto basic_json_parser_4;
7917 goto basic_json_parser_25;
7926 goto basic_json_parser_26;
7928 goto basic_json_parser_4;
7934 goto basic_json_parser_28;
7938 goto basic_json_parser_30;
7940 goto basic_json_parser_4;
7944 basic_json_parser_2:
7947 last_token_type = token_type::end_of_input;
7950 basic_json_parser_4:
7952 basic_json_parser_5:
7954 last_token_type = token_type::parse_error;
7957 basic_json_parser_6:
7959 if (m_limit <= m_cursor)
7964 if (yybm[0 + yych] & 32)
7966 goto basic_json_parser_6;
7971 basic_json_parser_9:
7973 yych = *(m_marker = ++m_cursor);
7976 goto basic_json_parser_5;
7978 goto basic_json_parser_32;
7979 basic_json_parser_10:
7982 last_token_type = token_type::value_separator;
7985 basic_json_parser_12:
7989 goto basic_json_parser_5;
7993 goto basic_json_parser_13;
7997 goto basic_json_parser_15;
7999 goto basic_json_parser_5;
8000 basic_json_parser_13:
8002 yych = *(m_marker = ++m_cursor);
8007 goto basic_json_parser_37;
8014 goto basic_json_parser_38;
8018 goto basic_json_parser_38;
8021 basic_json_parser_14:
8023 last_token_type = token_type::value_number;
8026 basic_json_parser_15:
8028 m_marker = ++m_cursor;
8029 if ((m_limit - m_cursor) < 3)
8034 if (yybm[0 + yych] & 64)
8036 goto basic_json_parser_15;
8042 goto basic_json_parser_37;
8044 goto basic_json_parser_14;
8050 goto basic_json_parser_38;
8054 goto basic_json_parser_38;
8056 goto basic_json_parser_14;
8058 basic_json_parser_17:
8061 last_token_type = token_type::name_separator;
8064 basic_json_parser_19:
8067 last_token_type = token_type::begin_array;
8070 basic_json_parser_21:
8073 last_token_type = token_type::end_array;
8076 basic_json_parser_23:
8078 yych = *(m_marker = ++m_cursor);
8081 goto basic_json_parser_39;
8083 goto basic_json_parser_5;
8084 basic_json_parser_24:
8086 yych = *(m_marker = ++m_cursor);
8089 goto basic_json_parser_40;
8091 goto basic_json_parser_5;
8092 basic_json_parser_25:
8094 yych = *(m_marker = ++m_cursor);
8097 goto basic_json_parser_41;
8099 goto basic_json_parser_5;
8100 basic_json_parser_26:
8103 last_token_type = token_type::begin_object;
8106 basic_json_parser_28:
8109 last_token_type = token_type::end_object;
8112 basic_json_parser_30:
8114 yych = *(m_marker = ++m_cursor);
8117 goto basic_json_parser_42;
8119 goto basic_json_parser_5;
8120 basic_json_parser_31:
8122 if (m_limit <= m_cursor)
8127 basic_json_parser_32:
8128 if (yybm[0 + yych] & 128)
8130 goto basic_json_parser_31;
8134 goto basic_json_parser_33;
8138 goto basic_json_parser_34;
8140 goto basic_json_parser_36;
8141 basic_json_parser_33:
8142 m_cursor = m_marker;
8145 goto basic_json_parser_5;
8149 goto basic_json_parser_14;
8151 basic_json_parser_34:
8154 last_token_type = token_type::value_string;
8157 basic_json_parser_36:
8159 if (m_limit <= m_cursor)
8170 goto basic_json_parser_31;
8174 goto basic_json_parser_33;
8176 goto basic_json_parser_31;
8184 goto basic_json_parser_33;
8186 goto basic_json_parser_31;
8192 goto basic_json_parser_31;
8194 goto basic_json_parser_33;
8204 goto basic_json_parser_31;
8208 goto basic_json_parser_31;
8210 goto basic_json_parser_33;
8218 goto basic_json_parser_31;
8220 goto basic_json_parser_33;
8226 goto basic_json_parser_31;
8230 goto basic_json_parser_43;
8232 goto basic_json_parser_33;
8236 basic_json_parser_37:
8240 goto basic_json_parser_33;
8244 goto basic_json_parser_44;
8246 goto basic_json_parser_33;
8247 basic_json_parser_38:
8253 goto basic_json_parser_46;
8255 goto basic_json_parser_33;
8261 goto basic_json_parser_46;
8265 goto basic_json_parser_33;
8269 goto basic_json_parser_47;
8271 goto basic_json_parser_33;
8273 basic_json_parser_39:
8277 goto basic_json_parser_49;
8279 goto basic_json_parser_33;
8280 basic_json_parser_40:
8284 goto basic_json_parser_50;
8286 goto basic_json_parser_33;
8287 basic_json_parser_41:
8291 goto basic_json_parser_51;
8293 goto basic_json_parser_33;
8294 basic_json_parser_42:
8298 goto basic_json_parser_52;
8300 goto basic_json_parser_33;
8301 basic_json_parser_43:
8303 if (m_limit <= m_cursor)
8312 goto basic_json_parser_33;
8316 goto basic_json_parser_54;
8318 goto basic_json_parser_33;
8324 goto basic_json_parser_54;
8328 goto basic_json_parser_33;
8332 goto basic_json_parser_54;
8334 goto basic_json_parser_33;
8336 basic_json_parser_44:
8338 m_marker = ++m_cursor;
8339 if ((m_limit - m_cursor) < 3)
8348 goto basic_json_parser_14;
8352 goto basic_json_parser_44;
8354 goto basic_json_parser_14;
8360 goto basic_json_parser_38;
8364 goto basic_json_parser_38;
8366 goto basic_json_parser_14;
8368 basic_json_parser_46:
8372 goto basic_json_parser_33;
8376 goto basic_json_parser_33;
8378 basic_json_parser_47:
8380 if (m_limit <= m_cursor)
8387 goto basic_json_parser_14;
8391 goto basic_json_parser_47;
8393 goto basic_json_parser_14;
8394 basic_json_parser_49:
8398 goto basic_json_parser_55;
8400 goto basic_json_parser_33;
8401 basic_json_parser_50:
8405 goto basic_json_parser_56;
8407 goto basic_json_parser_33;
8408 basic_json_parser_51:
8412 goto basic_json_parser_58;
8414 goto basic_json_parser_33;
8415 basic_json_parser_52:
8420 basic_json_parser_54:
8422 if (m_limit <= m_cursor)
8431 goto basic_json_parser_33;
8435 goto basic_json_parser_60;
8437 goto basic_json_parser_33;
8443 goto basic_json_parser_60;
8447 goto basic_json_parser_33;
8451 goto basic_json_parser_60;
8453 goto basic_json_parser_33;
8455 basic_json_parser_55:
8459 goto basic_json_parser_61;
8461 goto basic_json_parser_33;
8462 basic_json_parser_56:
8465 last_token_type = token_type::literal_null;
8468 basic_json_parser_58:
8471 last_token_type = token_type::literal_true;
8474 basic_json_parser_60:
8476 if (m_limit <= m_cursor)
8485 goto basic_json_parser_33;
8489 goto basic_json_parser_63;
8491 goto basic_json_parser_33;
8497 goto basic_json_parser_63;
8501 goto basic_json_parser_33;
8505 goto basic_json_parser_63;
8507 goto basic_json_parser_33;
8509 basic_json_parser_61:
8512 last_token_type = token_type::literal_false;
8515 basic_json_parser_63:
8517 if (m_limit <= m_cursor)
8526 goto basic_json_parser_33;
8530 goto basic_json_parser_31;
8532 goto basic_json_parser_33;
8538 goto basic_json_parser_31;
8542 goto basic_json_parser_33;
8546 goto basic_json_parser_31;
8548 goto basic_json_parser_33;
8554 return last_token_type;
8585 void fill_line_buffer()
8588 const auto offset_start = m_start - m_content;
8590 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8592 const auto offset_cursor = m_cursor - m_start;
8595 if (m_stream ==
nullptr or m_stream->eof())
8598 m_line_buffer.clear();
8599 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8601 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8607 m_line_buffer.append(5,
'\0');
8612 m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8615 std::getline(*m_stream, line);
8617 m_line_buffer += line +
"\n";
8621 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.c_str());
8622 assert(m_content !=
nullptr);
8623 m_start = m_content;
8624 m_marker = m_start + offset_marker;
8625 m_cursor = m_start + offset_cursor;
8626 m_limit = m_start + m_line_buffer.size();
8632 assert(m_start !=
nullptr);
8633 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8634 static_cast<size_t>(m_cursor - m_start));
8696 assert(m_cursor - m_start >= 2);
8699 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8702 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8758 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8759 4).c_str(),
nullptr, 16);
8762 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8765 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8767 throw std::invalid_argument(
"missing low surrogate");
8771 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8772 (i + 7), 4).c_str(),
nullptr, 16);
8773 result += to_unicode(codepoint, codepoint2);
8780 result += to_unicode(codepoint);
8792 result.append(1, static_cast<typename string_t::value_type>(*i));
8814 long double str_to_float_t(
long double* ,
char** endptr)
const 8816 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8834 double str_to_float_t(
double* ,
char** endptr)
const 8836 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8854 float str_to_float_t(
float* ,
char** endptr)
const 8856 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8882 assert(m_start !=
nullptr);
8884 const lexer::lexer_char_t* curptr = m_start;
8898 type = value_t::number_integer;
8899 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8904 type = value_t::number_unsigned;
8905 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8909 for (; curptr < m_cursor; curptr++)
8912 if (*curptr < '0' || *curptr >
'9')
8917 type = value_t::number_float;
8922 type = value_t::number_float;
8927 if (type != value_t::number_float)
8930 auto temp = value * 10 + *curptr -
'0';
8933 if (temp < value || temp > max)
8936 type = value_t::number_float;
8947 if (type == value_t::number_unsigned)
8949 result.m_value.number_unsigned = value;
8951 else if (type == value_t::number_integer)
8958 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8962 result.m_type = type;
8967 std::istream* m_stream =
nullptr;
8971 const lexer_char_t* m_content =
nullptr;
8973 const lexer_char_t* m_start =
nullptr;
8975 const lexer_char_t* m_marker =
nullptr;
8977 const lexer_char_t* m_cursor =
nullptr;
8979 const lexer_char_t* m_limit =
nullptr;
8981 token_type last_token_type = token_type::end_of_input;
8995 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
9000 : callback(cb), m_lexer(is)
9004 template<
class IteratorType,
typename std::enable_if<
9005 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9008 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
9010 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9011 static_cast<size_t>(std::distance(first, last)))
9021 result.assert_invariant();
9023 expect(lexer::token_type::end_of_input);
9034 auto result =
basic_json(value_t::discarded);
9038 case lexer::token_type::begin_object:
9040 if (keep and (not callback
9041 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9044 result.m_type = value_t::object;
9045 result.m_value = value_t::object;
9052 if (last_token == lexer::token_type::end_object)
9055 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9063 unexpect(lexer::token_type::value_separator);
9069 if (last_token == lexer::token_type::value_separator)
9075 expect(lexer::token_type::value_string);
9076 const auto key = m_lexer.get_string();
9078 bool keep_tag =
false;
9084 keep_tag = callback(depth, parse_event_t::key, k);
9094 expect(lexer::token_type::name_separator);
9098 auto value = parse_internal(keep);
9099 if (keep and keep_tag and not value.is_discarded())
9101 result[key] = std::move(value);
9104 while (last_token == lexer::token_type::value_separator);
9107 expect(lexer::token_type::end_object);
9109 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9117 case lexer::token_type::begin_array:
9119 if (keep and (not callback
9120 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9123 result.m_type = value_t::array;
9124 result.m_value = value_t::array;
9131 if (last_token == lexer::token_type::end_array)
9134 if (callback and not callback(--depth, parse_event_t::array_end, result))
9142 unexpect(lexer::token_type::value_separator);
9148 if (last_token == lexer::token_type::value_separator)
9154 auto value = parse_internal(keep);
9155 if (keep and not value.is_discarded())
9157 result.push_back(std::move(value));
9160 while (last_token == lexer::token_type::value_separator);
9163 expect(lexer::token_type::end_array);
9165 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9173 case lexer::token_type::literal_null:
9176 result.m_type = value_t::null;
9180 case lexer::token_type::value_string:
9182 const auto s = m_lexer.get_string();
9188 case lexer::token_type::literal_true:
9191 result.m_type = value_t::boolean;
9192 result.m_value =
true;
9196 case lexer::token_type::literal_false:
9199 result.m_type = value_t::boolean;
9200 result.m_value =
false;
9204 case lexer::token_type::value_number:
9206 m_lexer.get_number(result);
9214 unexpect(last_token);
9218 if (keep and callback and not callback(depth, parse_event_t::value, result))
9226 typename lexer::token_type get_token()
9228 last_token = m_lexer.scan();
9232 void expect(
typename lexer::token_type t)
const 9234 if (t != last_token)
9236 std::string error_msg =
"parse error - unexpected ";
9237 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9239 lexer::token_type_name(last_token));
9240 error_msg +=
"; expected " + lexer::token_type_name(t);
9241 throw std::invalid_argument(error_msg);
9245 void unexpect(
typename lexer::token_type t)
const 9247 if (t == last_token)
9249 std::string error_msg =
"parse error - unexpected ";
9250 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9252 lexer::token_type_name(last_token));
9253 throw std::invalid_argument(error_msg);
9263 typename lexer::token_type last_token = lexer::token_type::uninitialized;
9309 : reference_tokens(split(s))
9329 return std::accumulate(reference_tokens.begin(),
9330 reference_tokens.end(), std::string{},
9331 [](
const std::string & a,
const std::string & b)
9333 return a +
"/" + escape(b);
9338 operator std::string()
const 9345 std::string pop_back()
9349 throw std::domain_error(
"JSON pointer has no parent");
9352 auto last = reference_tokens.back();
9353 reference_tokens.pop_back();
9358 bool is_root()
const 9360 return reference_tokens.empty();
9367 throw std::domain_error(
"JSON pointer has no parent");
9371 result.reference_tokens = {reference_tokens[0]};
9386 for (
const auto& reference_token : reference_tokens)
9388 switch (result->m_type)
9392 if (reference_token ==
"0")
9395 result = &result->operator[](0);
9400 result = &result->operator[](reference_token);
9405 case value_t::object:
9408 result = &result->operator[](reference_token);
9412 case value_t::array:
9415 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9428 throw std::domain_error(
"invalid value to unflatten");
9451 for (
const auto& reference_token : reference_tokens)
9453 switch (ptr->m_type)
9455 case value_t::object:
9458 ptr = &ptr->operator[](reference_token);
9462 case value_t::array:
9465 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9467 throw std::domain_error(
"array index must not begin with '0'");
9470 if (reference_token ==
"-")
9473 ptr = &ptr->operator[](ptr->m_value.array->size());
9478 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9485 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9495 for (
const auto& reference_token : reference_tokens)
9497 switch (ptr->m_type)
9499 case value_t::object:
9502 ptr = &ptr->
at(reference_token);
9506 case value_t::array:
9508 if (reference_token ==
"-")
9511 throw std::out_of_range(
"array index '-' (" +
9512 std::to_string(ptr->m_value.array->size()) +
9513 ") is out of range");
9517 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9519 throw std::domain_error(
"array index must not begin with '0'");
9523 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9529 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9547 for (
const auto& reference_token : reference_tokens)
9549 switch (ptr->m_type)
9551 case value_t::object:
9554 ptr = &ptr->operator[](reference_token);
9558 case value_t::array:
9560 if (reference_token ==
"-")
9563 throw std::out_of_range(
"array index '-' (" +
9564 std::to_string(ptr->m_value.array->size()) +
9565 ") is out of range");
9569 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9571 throw std::domain_error(
"array index must not begin with '0'");
9575 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9581 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9591 for (
const auto& reference_token : reference_tokens)
9593 switch (ptr->m_type)
9595 case value_t::object:
9598 ptr = &ptr->
at(reference_token);
9602 case value_t::array:
9604 if (reference_token ==
"-")
9607 throw std::out_of_range(
"array index '-' (" +
9608 std::to_string(ptr->m_value.array->size()) +
9609 ") is out of range");
9613 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9615 throw std::domain_error(
"array index must not begin with '0'");
9619 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9625 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9634 static std::vector<std::string> split(
const std::string& reference_string)
9636 std::vector<std::string> result;
9639 if (reference_string.empty())
9645 if (reference_string[0] !=
'/')
9647 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9655 size_t slash = reference_string.find_first_of(
"/", 1),
9664 slash = reference_string.find_first_of(
"/", start))
9668 auto reference_token = reference_string.substr(start, slash - start);
9671 for (
size_t pos = reference_token.find_first_of(
"~");
9672 pos != std::string::npos;
9673 pos = reference_token.find_first_of(
"~", pos + 1))
9675 assert(reference_token[pos] ==
'~');
9678 if (pos == reference_token.size() - 1 or
9679 (reference_token[pos + 1] !=
'0' and
9680 reference_token[pos + 1] !=
'1'))
9682 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9687 unescape(reference_token);
9688 result.push_back(reference_token);
9709 static void replace_substring(std::string& s,
9710 const std::string& f,
9711 const std::string& t)
9713 assert(not f.empty());
9716 size_t pos = s.find(f);
9717 pos != std::string::npos;
9718 s.replace(pos, f.size(), t),
9719 pos = s.find(f, pos + t.size())
9724 static std::string escape(std::string s)
9727 replace_substring(s,
"~",
"~0");
9728 replace_substring(s,
"/",
"~1");
9733 static void unescape(std::string& s)
9736 replace_substring(s,
"~1",
"/");
9738 replace_substring(s,
"~0",
"~");
9748 static void flatten(
const std::string& reference_string,
9752 switch (value.m_type)
9754 case value_t::array:
9756 if (value.m_value.array->empty())
9759 result[reference_string] =
nullptr;
9764 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9766 flatten(reference_string +
"/" + std::to_string(i),
9767 value.m_value.array->operator[](i), result);
9773 case value_t::object:
9775 if (value.m_value.object->empty())
9778 result[reference_string] =
nullptr;
9783 for (
const auto& element : *value.m_value.object)
9785 flatten(reference_string +
"/" + escape(element.first),
9786 element.second, result);
9795 result[reference_string] = value;
9810 throw std::domain_error(
"only objects can be unflattened");
9816 for (
const auto& element : *value.m_value.object)
9818 if (not element.second.is_primitive())
9820 throw std::domain_error(
"values in object must be primitive");
9828 json_pointer(element.first).get_and_create(result) = element.second;
9836 std::vector<std::string> reference_tokens {};
9881 return ptr.get_unchecked(
this);
9908 return ptr.get_unchecked(
this);
9933 return ptr.get_checked(
this);
9958 return ptr.get_checked(
this);
9986 json_pointer::flatten(
"", *
this, result);
10019 return json_pointer::unflatten(*
this);
10073 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
10075 const auto get_op = [](
const std::string op)
10079 return patch_operations::add;
10081 if (op ==
"remove")
10083 return patch_operations::remove;
10085 if (op ==
"replace")
10087 return patch_operations::replace;
10091 return patch_operations::move;
10095 return patch_operations::copy;
10099 return patch_operations::test;
10102 return patch_operations::invalid;
10117 if (top_pointer != ptr)
10119 result.
at(top_pointer);
10123 const auto last_path = ptr.pop_back();
10126 switch (parent.m_type)
10128 case value_t::null:
10129 case value_t::object:
10132 parent[last_path] = val;
10136 case value_t::array:
10138 if (last_path ==
"-")
10145 const auto idx = std::stoi(last_path);
10146 if (static_cast<size_type>(idx) > parent.
size())
10149 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
10170 const auto operation_remove = [&result](
json_pointer & ptr)
10173 const auto last_path = ptr.pop_back();
10180 auto it = parent.
find(last_path);
10181 if (it != parent.
end())
10187 throw std::out_of_range(
"key '" + last_path +
"' not found");
10193 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
10201 throw std::invalid_argument(
"JSON patch must be an array of objects");
10205 for (
const auto& val : json_patch)
10208 const auto get_value = [&val](
const std::string & op,
10209 const std::string & member,
10213 auto it = val.m_value.object->find(member);
10216 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
10219 if (it == val.m_value.object->end())
10221 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
10225 if (string_type and not it->second.is_string())
10227 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
10235 if (not val.is_object())
10237 throw std::invalid_argument(
"JSON patch must be an array of objects");
10241 const std::string op = get_value(
"op",
"op",
true);
10242 const std::string path = get_value(op,
"path",
true);
10245 switch (get_op(op))
10247 case patch_operations::add:
10249 operation_add(ptr, get_value(
"add",
"value",
false));
10253 case patch_operations::remove:
10255 operation_remove(ptr);
10259 case patch_operations::replace:
10262 result.
at(ptr) = get_value(
"replace",
"value",
false);
10266 case patch_operations::move:
10268 const std::string from_path = get_value(
"move",
"from",
true);
10278 operation_remove(from_ptr);
10279 operation_add(ptr, v);
10283 case patch_operations::copy:
10285 const std::string from_path = get_value(
"copy",
"from",
true);;
10289 result[ptr] = result.
at(from_ptr);
10293 case patch_operations::test:
10295 bool success =
false;
10300 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
10302 catch (std::out_of_range&)
10310 throw std::domain_error(
"unsuccessful: " + val.dump());
10316 case patch_operations::invalid:
10320 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
10362 const std::string& path =
"")
10368 if (source == target)
10373 if (source.
type() != target.
type())
10385 switch (source.
type())
10387 case value_t::array:
10391 while (i < source.
size() and i < target.
size())
10394 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10395 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
10404 while (i < source.
size())
10408 result.
insert(result.
begin() + end_index, object(
10411 {
"path", path +
"/" + std::to_string(i)}
10417 while (i < target.
size())
10422 {
"path", path +
"/" + std::to_string(i)},
10423 {
"value", target[i]}
10431 case value_t::object:
10434 for (
auto it = source.
begin(); it != source.
end(); ++it)
10437 const auto key = json_pointer::escape(it.key());
10439 if (target.
find(it.key()) != target.
end())
10442 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10443 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
10451 {
"path", path +
"/" + key}
10457 for (
auto it = target.
begin(); it != target.
end(); ++it)
10459 if (source.
find(it.key()) == source.
end())
10462 const auto key = json_pointer::escape(it.key());
10466 {
"path", path +
"/" + key},
10467 {
"value", it.value()}
10527 is_nothrow_move_constructible<nlohmann::json>::value and
10528 is_nothrow_move_assignable<nlohmann::json>::value
10546 const auto& h = hash<nlohmann::json::string_t>();
10547 return h(j.
dump());
10564 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10589 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10590 #pragma GCC diagnostic pop const_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7161
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition: json.hpp:7540
iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7376
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition: json.hpp:3237
iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7406
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7510
void swap(string_t &other)
exchanges the values
Definition: json.hpp:5374
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4378
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition: json.hpp:4756
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition: json.hpp:2091
const value_type & const_reference
the type of an element const reference
Definition: json.hpp:259
bool operator<(const const_iterator &other) const
comparison: smaller
Definition: json.hpp:7101
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition: json.hpp:5181
typename basic_json::difference_type difference_type
a type to represent differences between iterators
Definition: json.hpp:6720
std::bidirectional_iterator_tag iterator_category
the category of the iterator
Definition: json.hpp:6726
constexpr bool is_structured() const noexcept
return whether type is structured
Definition: json.hpp:2296
json_reverse_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7504
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition: json.hpp:5074
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:6811
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition: json.hpp:7524
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition: json.hpp:5638
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition: json.hpp:262
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition: json.hpp:7486
iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7399
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7289
const_iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:6737
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition: json.hpp:2269
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
Definition: json.hpp:7152
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
Definition: json.hpp:5893
AllocatorType< basic_json > allocator_type
the allocator type
Definition: json.hpp:267
void push_back(const basic_json &val)
add an object to an array
Definition: json.hpp:4924
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
Definition: json.hpp:1511
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition: json.hpp:4040
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition: json.hpp:3469
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition: json.hpp:4408
ValueType get() const
get a value (explicit)
Definition: json.hpp:2897
a class to store JSON values
Definition: json.hpp:231
basic_json(const CompatibleStringType &val)
create a string (implicit)
Definition: json.hpp:1302
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition: json.hpp:10017
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition: json.hpp:1827
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition: json.hpp:2548
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
Definition: json.hpp:3005
reference value() const
return the value of an iterator
Definition: json.hpp:7307
ReferenceType get_ref() const
get a reference value (implicit)
Definition: json.hpp:3067
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition: json.hpp:5818
reference value() const
return the value of an iterator
Definition: json.hpp:7559
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition: json.hpp:2427
iterator(pointer object) noexcept
constructor for a given JSON instance
Definition: json.hpp:7342
a mutable random access iterator for the basic_json class
Definition: json.hpp:7331
constexpr bool is_object() const noexcept
return whether value is an object
Definition: json.hpp:2477
PointerType get_ptr() noexcept
get a pointer value (implicit)
Definition: json.hpp:2977
Definition: BitcoinLikeFeePolicy.hpp:29
iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7413
const_iterator & operator-=(difference_type i)
subtract from iterator
Definition: json.hpp:7192
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition: json.hpp:1087
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:9931
size_type size() const noexcept
returns the number of elements
Definition: json.hpp:4690
static allocator_type get_allocator()
returns the allocator associated with the container
Definition: json.hpp:289
constexpr bool is_array() const noexcept
return whether value is an array
Definition: json.hpp:2499
const_iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7212
basic_json(const CompatibleObjectType &val)
create an object (implicit)
Definition: json.hpp:1147
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
Definition: json.hpp:1558
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
Definition: json.hpp:5547
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:9906
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5046
iterator end() noexcept
returns an iterator to one past the last element
Definition: json.hpp:4368
const_iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7016
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
Definition: json.hpp:1385
basic_json(const CompatibleArrayType &val)
create an array (implicit)
Definition: json.hpp:1215
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:7364
reference back()
access the last element
Definition: json.hpp:3867
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition: json.hpp:4475
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition: json.hpp:7481
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
Definition: json.hpp:1756
friend class basic_json
allow basic_json to access private members
Definition: json.hpp:6714
reference operator+=(const basic_json &val)
add an object to an array
Definition: json.hpp:4948
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4570
NumberFloatType number_float_t
a type for a number (floating-point)
Definition: json.hpp:721
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5970
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
Definition: json.hpp:6722
basic_json(const value_t value_type)
create an empty value with a given type
Definition: json.hpp:1063
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
Definition: json.hpp:4257
bool operator!=(const const_iterator &other) const
comparison: not equal
Definition: json.hpp:7092
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
Definition: json.hpp:6093
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition: json.hpp:7517
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4483
bool operator>(const const_iterator &other) const
comparison: greater than
Definition: json.hpp:7143
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
Definition: json.hpp:5931
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition: json.hpp:3284
basic_json(const object_t &val)
create an object (explicit)
Definition: json.hpp:1112
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition: json.hpp:4438
basic_json(const string_t &val)
create a string (explicit)
Definition: json.hpp:1245
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7442
iterator find(typename object_t::key_type key)
find an element in a JSON object
Definition: json.hpp:4211
constexpr bool is_number() const noexcept
return whether value is a number
Definition: json.hpp:2370
void swap(object_t &other)
exchanges the values
Definition: json.hpp:5341
BooleanType boolean_t
a type for a boolean
Definition: json.hpp:510
const_reference operator[](T *key) const
read-only access specified object element
Definition: json.hpp:3631
reference operator[](T *(&key)[n])
access specified object element
Definition: json.hpp:3511
pointer operator->() const
dereference the iterator
Definition: json.hpp:7370
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
Definition: json.hpp:6769
json_reverse_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7497
namespace for Niels Lohmann
Definition: json.hpp:91
parse_event_t
JSON callback events.
Definition: json.hpp:942
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition: json.hpp:2239
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition: json.hpp:1780
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition: json.hpp:4541
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
Definition: json.hpp:3546
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
Definition: json.hpp:1012
const_iterator & operator--()
pre-decrement (–it)
Definition: json.hpp:7027
constexpr bool is_string() const noexcept
return whether value is a string
Definition: json.hpp:2521
difference_type operator-(const iterator &other) const
return difference
Definition: json.hpp:7436
basic_json value_type
the type of elements in a basic_json container
Definition: json.hpp:254
basic_json(boolean_t val) noexcept
create a boolean (explicit)
Definition: json.hpp:1322
std::string to_string() const noexcept
return a string representation of the JSON pointer
Definition: json.hpp:9327
basic_json(basic_json &&other) noexcept
move constructor
Definition: json.hpp:2054
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
Definition: json.hpp:1716
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition: json.hpp:6133
basic_json(const typename string_t::value_type *val)
create a string (explicit)
Definition: json.hpp:1271
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition: json.hpp:5454
JSON Pointer.
Definition: json.hpp:9280
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition: json.hpp:5850
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition: json.hpp:6123
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
Definition: json.hpp:3695
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition: json.hpp:5276
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7546
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4998
std::size_t size_type
a type to represent container sizes
Definition: json.hpp:264
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
Definition: json.hpp:4562
reference operator+=(basic_json &&val)
add an object to an array
Definition: json.hpp:4914
reference operator[](size_type idx)
access specified array element
Definition: json.hpp:3330
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4307
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
Definition: json.hpp:5600
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
Definition: json.hpp:6718
reference operator[](difference_type n) const
access to successor
Definition: json.hpp:7250
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4512
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition: json.hpp:2455
string_t dump(const int indent=-1) const
serialization
Definition: json.hpp:2196
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition: json.hpp:4337
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition: json.hpp:10543
array (ordered collection of values)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition: json.hpp:2399
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
Definition: json.hpp:1480
static basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition: json.hpp:10360
json_reverse_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:7491
const_reference back() const
access the last element
Definition: json.hpp:3877
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition: json.hpp:2340
void push_back(basic_json &&val)
add an object to an array
Definition: json.hpp:4888
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition: json.hpp:272
ReferenceType get_ref()
get a reference value (implicit)
Definition: json.hpp:3054
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition: json.hpp:5755
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition: json.hpp:4446
NumberIntegerType number_integer_t
a type for a number (integer)
Definition: json.hpp:582
iterator operator--(int)
post-decrement (it–)
Definition: json.hpp:7391
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition: json.hpp:10067
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
Definition: json.hpp:1449
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition: json.hpp:5100
bool empty() const noexcept
checks whether the container is empty
Definition: json.hpp:4622
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
Definition: json.hpp:1945
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
Definition: json.hpp:1354
constexpr bool is_null() const noexcept
return whether value is null
Definition: json.hpp:2318
iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7420
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
Definition: json.hpp:4227
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
Definition: json.hpp:1633
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition: json.hpp:270
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition: json.hpp:9879
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition: json.hpp:9956
const_reference front() const
access the first element
Definition: json.hpp:3832
value_t
the JSON type enumeration
Definition: json.hpp:752
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition: json.hpp:3933
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition: json.hpp:3190
iterator & operator++()
pre-increment (++it)
Definition: json.hpp:7384
json_pointer(const std::string &s="")
create JSON pointer
Definition: json.hpp:9308
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:3147
difference_type operator-(const const_iterator &other) const
return difference
Definition: json.hpp:7223
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
Definition: json.hpp:1422
object_t::key_type key() const
return the key of an object iterator
Definition: json.hpp:7552
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition: json.hpp:4974
iterator operator-(difference_type i)
subtract from iterator
Definition: json.hpp:7428
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
Definition: json.hpp:5961
object (unordered set of name/value pairs)
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3794
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:5407
const_iterator & operator++()
pre-increment (++it)
Definition: json.hpp:6984
basic_json(const array_t &val)
create an array (explicit)
Definition: json.hpp:1175
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition: json.hpp:3721
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: json.hpp:6896
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
Definition: json.hpp:3769
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
Definition: json.hpp:6724
iterator(const iterator &other) noexcept
copy constructor
Definition: json.hpp:7347
pointer operator->() const
dereference the iterator
Definition: json.hpp:6937
reference value() const
return the value of an iterator
Definition: json.hpp:7448
basic_json<> json
default JSON class
Definition: json.hpp:10508
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
Definition: json.hpp:5239
bool operator<=(const const_iterator &other) const
comparison: less than or equal
Definition: json.hpp:7134
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition: json.hpp:4128
void erase(const size_type idx)
remove element from a JSON array given an index
Definition: json.hpp:4165
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition: json.hpp:437
void clear() noexcept
clears the contents
Definition: json.hpp:4815
a const random access iterator for the basic_json class
Definition: json.hpp:6711
a template for a reverse iterator class
Definition: json.hpp:241
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition: json.hpp:653
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
Definition: json.hpp:7476
const_iterator operator++(int)
post-increment (it++)
Definition: json.hpp:6973
reference operator[](T *key)
access specified object element
Definition: json.hpp:3579
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
Definition: json.hpp:5609
typename Base::reference reference
the reference type for the pointed-to element
Definition: json.hpp:7478
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
Definition: json.hpp:7352
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition: json.hpp:5733
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition: json.hpp:5777
const_iterator operator+(difference_type i)
add to iterator
Definition: json.hpp:7201
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition: json.hpp:5577
const_reference operator[](size_type idx) const
access specified array element
Definition: json.hpp:3378
bool operator==(const const_iterator &other) const
comparison: equal
Definition: json.hpp:7059
iterator begin() noexcept
returns an iterator to the first element
Definition: json.hpp:4297
StringType string_t
a type for a string
Definition: json.hpp:484
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
Definition: json.hpp:6021
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition: json.hpp:7532
reference front()
access the first element
Definition: json.hpp:3824
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition: json.hpp:5129
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
Definition: json.hpp:5556
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
Definition: json.hpp:391
value_type & reference
the type of an element reference
Definition: json.hpp:257
basic_json(const basic_json &other)
copy constructor
Definition: json.hpp:1977
~basic_json()
destructor
Definition: json.hpp:2124
basic_json flatten() const
return flattened JSON value
Definition: json.hpp:9983
void push_back(std::initializer_list< basic_json > init)
add an object to an object
Definition: json.hpp:5029
const_iterator(const const_iterator &other) noexcept
copy constructor
Definition: json.hpp:6802
void swap(array_t &other)
exchanges the values
Definition: json.hpp:5308
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition: json.hpp:3418