29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 43 #include <initializer_list> 55 #include <type_traits> 60 #if defined(__clang__) 61 #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 62 #if CLANG_VERSION < 30400 63 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 65 #elif defined(__GNUC__) 66 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 67 #if GCC_VERSION < 40900 68 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 73 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 74 #pragma GCC diagnostic push 75 #pragma GCC diagnostic ignored "-Wfloat-equal" 79 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 80 #define JSON_DEPRECATED __attribute__((deprecated)) 81 #elif defined(_MSC_VER) 82 #define JSON_DEPRECATED __declspec(deprecated) 84 #define JSON_DEPRECATED 113 struct has_mapped_type
116 template <
typename U,
typename =
typename U::mapped_type>
117 static int detect(U&&);
119 static void detect(...);
121 static constexpr
bool value =
122 std::is_integral<decltype(detect(std::declval<T>()))>::value;
137 struct DecimalSeparator : std::numpunct<char>
139 char do_decimal_point()
const 226 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
227 template<
typename U,
typename... Args>
class ArrayType = std::vector,
228 class StringType = std::string,
229 class BooleanType = bool,
230 class NumberIntegerType = std::int64_t,
231 class NumberUnsignedType = std::uint64_t,
232 class NumberFloatType = double,
233 template<
typename U>
class AllocatorType = std::allocator
240 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
274 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
276 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
391 using object_t = ObjectType<StringType,
393 std::less<StringType>,
394 AllocatorType<std::pair<
const StringType,
441 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
773 template<
typename T,
typename... Args>
774 static T* create(Args&& ... args)
776 AllocatorType<T> alloc;
777 auto deleter = [&](T * object)
779 alloc.deallocate(
object, 1);
781 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
782 alloc.construct(
object.
get(), std::forward<Args>(args)...);
783 assert(
object.
get() !=
nullptr);
784 return object.release();
833 json_value() =
default;
835 json_value(
boolean_t v) noexcept : boolean(v) {}
847 case value_t::object:
849 object = create<object_t>();
855 array = create<array_t>();
859 case value_t::string:
861 string = create<string_t>(
"");
865 case value_t::boolean:
871 case value_t::number_integer:
877 case value_t::number_unsigned:
883 case value_t::number_float:
899 string = create<string_t>(value);
905 object = create<object_t>(value);
909 json_value(
const array_t& value)
911 array = create<array_t>(value);
924 void assert_invariant()
const 926 assert(m_type != value_t::object or m_value.object !=
nullptr);
927 assert(m_type != value_t::array or m_value.array !=
nullptr);
928 assert(m_type != value_t::string or m_value.string !=
nullptr);
1016 basic_json& parsed)>;
1068 : m_type(value_type), m_value(value_type)
1117 : m_type(
value_t::object), m_value(val)
1148 template<
class CompatibleObjectType,
typename std::enable_if<
1149 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1150 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1156 m_value.object = create<object_t>(begin(val), end(val));
1180 : m_type(
value_t::array), m_value(val)
1211 template<
class CompatibleArrayType,
typename std::enable_if<
1212 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1213 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1214 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1215 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1216 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1217 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1218 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1224 m_value.array = create<array_t>(begin(val), end(val));
1250 : m_type(
value_t::string), m_value(val)
1304 template<
class CompatibleStringType,
typename std::enable_if<
1305 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1327 : m_type(value_t::boolean), m_value(val)
1355 template<
typename T,
typename std::enable_if<
1356 not (std::is_same<T, int>::value) and
1357 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1359 : m_type(value_t::number_integer), m_value(val)
1390 : m_type(value_t::number_integer),
1391 m_value(static_cast<number_integer_t>(val))
1421 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1422 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1423 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1424 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1425 CompatibleNumberIntegerType>::type = 0>
1427 : m_type(value_t::number_integer),
1428 m_value(static_cast<number_integer_t>(val))
1450 template<
typename T,
typename std::enable_if<
1451 not (std::is_same<T, int>::value) and
1452 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1454 : m_type(value_t::number_unsigned), m_value(val)
1479 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1480 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1481 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1482 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1483 CompatibleNumberUnsignedType>::type = 0>
1485 : m_type(value_t::number_unsigned),
1486 m_value(static_cast<number_unsigned_t>(val))
1516 : m_type(value_t::number_float), m_value(val)
1519 if (not std::isfinite(val))
1521 m_type = value_t::null;
1522 m_value = json_value();
1559 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1560 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1561 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1638 bool type_deduction =
true,
1639 value_t manual_type = value_t::array)
1643 bool is_an_object = std::all_of(init.begin(), init.end(),
1646 return element.is_array() and element.size() == 2 and element[0].is_string();
1650 if (not type_deduction)
1653 if (manual_type == value_t::array)
1655 is_an_object =
false;
1659 if (manual_type == value_t::object and not is_an_object)
1661 throw std::domain_error(
"cannot create object from initializer list");
1668 m_type = value_t::object;
1669 m_value = value_t::object;
1671 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1673 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1679 m_type = value_t::array;
1680 m_value.array = create<array_t>(init);
1721 std::initializer_list<basic_json>())
1723 return basic_json(init,
false, value_t::array);
1761 std::initializer_list<basic_json>())
1763 return basic_json(init,
false, value_t::object);
1787 m_value.array = create<array_t>(cnt, val);
1828 template<
class InputIT,
typename std::enable_if<
1829 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1830 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1833 assert(first.m_object !=
nullptr);
1834 assert(last.m_object !=
nullptr);
1837 if (first.m_object != last.m_object)
1839 throw std::domain_error(
"iterators are not compatible");
1843 m_type = first.m_object->m_type;
1848 case value_t::boolean:
1849 case value_t::number_float:
1850 case value_t::number_integer:
1851 case value_t::number_unsigned:
1852 case value_t::string:
1854 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1856 throw std::out_of_range(
"iterators out of range");
1869 case value_t::number_integer:
1871 m_value.number_integer = first.m_object->m_value.number_integer;
1875 case value_t::number_unsigned:
1877 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1881 case value_t::number_float:
1883 m_value.number_float = first.m_object->m_value.number_float;
1887 case value_t::boolean:
1889 m_value.boolean = first.m_object->m_value.boolean;
1893 case value_t::string:
1895 m_value = *first.m_object->m_value.string;
1899 case value_t::object:
1901 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1905 case value_t::array:
1907 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1913 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1951 *
this = parser(i, cb).parse();
1982 : m_type(other.m_type)
1985 other.assert_invariant();
1989 case value_t::object:
1991 m_value = *other.m_value.object;
1995 case value_t::array:
1997 m_value = *other.m_value.array;
2001 case value_t::string:
2003 m_value = *other.m_value.string;
2007 case value_t::boolean:
2009 m_value = other.m_value.boolean;
2013 case value_t::number_integer:
2015 m_value = other.m_value.number_integer;
2019 case value_t::number_unsigned:
2021 m_value = other.m_value.number_unsigned;
2025 case value_t::number_float:
2027 m_value = other.m_value.number_float;
2059 : m_type(
std::move(other.m_type)),
2060 m_value(
std::move(other.m_value))
2063 other.assert_invariant();
2066 other.m_type = value_t::null;
2096 std::is_nothrow_move_constructible<value_t>::value and
2097 std::is_nothrow_move_assignable<value_t>::value and
2098 std::is_nothrow_move_constructible<json_value>::value and
2099 std::is_nothrow_move_assignable<json_value>::value
2103 other.assert_invariant();
2106 swap(m_type, other.m_type);
2107 swap(m_value, other.m_value);
2134 case value_t::object:
2136 AllocatorType<object_t> alloc;
2137 alloc.destroy(m_value.object);
2138 alloc.deallocate(m_value.object, 1);
2142 case value_t::array:
2144 AllocatorType<array_t> alloc;
2145 alloc.destroy(m_value.array);
2146 alloc.deallocate(m_value.array, 1);
2150 case value_t::string:
2152 AllocatorType<string_t> alloc;
2153 alloc.destroy(m_value.string);
2154 alloc.deallocate(m_value.string, 1);
2202 std::stringstream ss;
2204 const static std::locale loc(std::locale(),
new DecimalSeparator);
2211 ss.precision(std::numeric_limits<double>::digits10);
2215 dump(ss,
true, static_cast<unsigned int>(indent));
2275 return is_null() or is_string() or is_boolean() or is_number();
2302 return is_array() or is_object();
2324 return m_type == value_t::null;
2346 return m_type == value_t::boolean;
2376 return is_number_integer() or is_number_float();
2405 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2433 return m_type == value_t::number_unsigned;
2461 return m_type == value_t::number_float;
2483 return m_type == value_t::object;
2505 return m_type == value_t::array;
2527 return m_type == value_t::string;
2554 return m_type == value_t::discarded;
2588 template<
class T,
typename std::enable_if<
2589 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2590 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2591 T get_impl(T*)
const 2595 return T(m_value.object->begin(), m_value.object->end());
2599 throw std::domain_error(
"type must be object, but is " + type_name());
2608 return *(m_value.object);
2612 throw std::domain_error(
"type must be object, but is " + type_name());
2617 template<
class T,
typename std::enable_if<
2618 std::is_convertible<basic_json_t, typename T::value_type>::value and
2619 not std::is_same<basic_json_t, typename T::value_type>::value and
2620 not std::is_arithmetic<T>::value and
2621 not std::is_convertible<std::string, T>::value and
2622 not has_mapped_type<T>::value,
int>::type = 0>
2623 T get_impl(T*)
const 2628 std::transform(m_value.array->begin(), m_value.array->end(),
2629 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2631 return i.
get<
typename T::value_type>();
2637 throw std::domain_error(
"type must be array, but is " + type_name());
2642 template<
class T,
typename std::enable_if<
2643 std::is_convertible<basic_json_t, T>::value and
2644 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2645 std::vector<T> get_impl(std::vector<T>*)
const 2649 std::vector<T> to_vector;
2650 to_vector.reserve(m_value.array->size());
2651 std::transform(m_value.array->begin(), m_value.array->end(),
2652 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2660 throw std::domain_error(
"type must be array, but is " + type_name());
2665 template<
class T,
typename std::enable_if<
2666 std::is_same<basic_json, typename T::value_type>::value and
2667 not has_mapped_type<T>::value,
int>::type = 0>
2668 T get_impl(T*)
const 2672 return T(m_value.array->begin(), m_value.array->end());
2676 throw std::domain_error(
"type must be array, but is " + type_name());
2685 return *(m_value.array);
2689 throw std::domain_error(
"type must be array, but is " + type_name());
2694 template<
typename T,
typename std::enable_if<
2695 std::is_convertible<string_t, T>::value,
int>::type = 0>
2696 T get_impl(T*)
const 2700 return *m_value.string;
2704 throw std::domain_error(
"type must be string, but is " + type_name());
2709 template<
typename T,
typename std::enable_if<
2710 std::is_arithmetic<T>::value,
int>::type = 0>
2711 T get_impl(T*)
const 2715 case value_t::number_integer:
2717 return static_cast<T
>(m_value.number_integer);
2720 case value_t::number_unsigned:
2722 return static_cast<T
>(m_value.number_unsigned);
2725 case value_t::number_float:
2727 return static_cast<T
>(m_value.number_float);
2732 throw std::domain_error(
"type must be number, but is " + type_name());
2742 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2748 return is_object() ? m_value.object :
nullptr;
2754 return is_object() ? m_value.object :
nullptr;
2760 return is_array() ? m_value.array :
nullptr;
2764 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2766 return is_array() ? m_value.array :
nullptr;
2772 return is_string() ? m_value.string :
nullptr;
2778 return is_string() ? m_value.string :
nullptr;
2784 return is_boolean() ? &m_value.boolean :
nullptr;
2790 return is_boolean() ? &m_value.boolean :
nullptr;
2796 return is_number_integer() ? &m_value.number_integer :
nullptr;
2802 return is_number_integer() ? &m_value.number_integer :
nullptr;
2808 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2814 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2820 return is_number_float() ? &m_value.number_float :
nullptr;
2826 return is_number_float() ? &m_value.number_float :
nullptr;
2840 template<
typename ReferenceType,
typename ThisType>
2841 static ReferenceType get_ref_impl(ThisType& obj)
2844 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2847 auto ptr = obj.template get_ptr<PointerType>();
2855 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2899 template<
typename ValueType,
typename std::enable_if<
2900 not std::is_pointer<ValueType>::value,
int>::type = 0>
2901 ValueType
get()
const 2903 return get_impl(static_cast<ValueType*>(
nullptr));
2933 template<
typename PointerType,
typename std::enable_if<
2934 std::is_pointer<PointerType>::value,
int>::type = 0>
2935 PointerType
get() noexcept
2938 return get_ptr<PointerType>();
2945 template<
typename PointerType,
typename std::enable_if<
2946 std::is_pointer<PointerType>::value,
int>::type = 0>
2947 constexpr
const PointerType
get()
const noexcept
2950 return get_ptr<PointerType>();
2979 template<
typename PointerType,
typename std::enable_if<
2980 std::is_pointer<PointerType>::value,
int>::type = 0>
2984 using pointee_t =
typename std::remove_const<
typename 2985 std::remove_pointer<
typename 2986 std::remove_const<PointerType>::type>::type>::type;
2989 std::is_same<object_t, pointee_t>::value
2990 or std::is_same<array_t, pointee_t>::value
2991 or std::is_same<string_t, pointee_t>::value
2992 or std::is_same<boolean_t, pointee_t>::value
2993 or std::is_same<number_integer_t, pointee_t>::value
2994 or std::is_same<number_unsigned_t, pointee_t>::value
2995 or std::is_same<number_float_t, pointee_t>::value
2996 ,
"incompatible pointer type");
2999 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3006 template<
typename PointerType,
typename std::enable_if<
3007 std::is_pointer<PointerType>::value and
3008 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3009 constexpr
const PointerType
get_ptr() const noexcept
3012 using pointee_t =
typename std::remove_const<
typename 3013 std::remove_pointer<
typename 3014 std::remove_const<PointerType>::type>::type>::type;
3017 std::is_same<object_t, pointee_t>::value
3018 or std::is_same<array_t, pointee_t>::value
3019 or std::is_same<string_t, pointee_t>::value
3020 or std::is_same<boolean_t, pointee_t>::value
3021 or std::is_same<number_integer_t, pointee_t>::value
3022 or std::is_same<number_unsigned_t, pointee_t>::value
3023 or std::is_same<number_float_t, pointee_t>::value
3024 ,
"incompatible pointer type");
3027 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3056 template<
typename ReferenceType,
typename std::enable_if<
3057 std::is_reference<ReferenceType>::value,
int>::type = 0>
3061 return get_ref_impl<ReferenceType>(*this);
3068 template<
typename ReferenceType,
typename std::enable_if<
3069 std::is_reference<ReferenceType>::value and
3070 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3074 return get_ref_impl<ReferenceType>(*this);
3105 template <
typename ValueType,
typename std::enable_if <
3106 not std::is_pointer<ValueType>::value and
3107 not std::is_same<ValueType, typename string_t::value_type>::value
3108 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3109 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3112 operator ValueType()
const 3115 return get<ValueType>();
3158 return m_value.
array->
at(idx);
3160 catch (std::out_of_range&)
3163 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3168 throw std::domain_error(
"cannot use at() with " + type_name());
3201 return m_value.
array->
at(idx);
3203 catch (std::out_of_range&)
3206 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3211 throw std::domain_error(
"cannot use at() with " + type_name());
3250 catch (std::out_of_range&)
3253 throw std::out_of_range(
"key '" + key +
"' not found");
3258 throw std::domain_error(
"cannot use at() with " + type_name());
3297 catch (std::out_of_range&)
3300 throw std::out_of_range(
"key '" + key +
"' not found");
3305 throw std::domain_error(
"cannot use at() with " + type_name());
3339 m_type = value_t::array;
3340 m_value.
array = create<array_t>();
3348 if (idx >= m_value.array->size())
3350 m_value.array->insert(m_value.array->end(),
3351 idx - m_value.array->size() + 1,
3355 return m_value.array->operator[](idx);
3359 throw std::domain_error(
"cannot use operator[] with " + type_name());
3387 return m_value.
array->operator[](idx);
3391 throw std::domain_error(
"cannot use operator[] with " + type_name());
3427 m_type = value_t::object;
3428 m_value.
object = create<object_t>();
3435 return m_value.object->operator[](key);
3439 throw std::domain_error(
"cannot use operator[] with " + type_name());
3478 assert(m_value.object->find(key) != m_value.object->end());
3483 throw std::domain_error(
"cannot use operator[] with " + type_name());
3514 template<
typename T, std::
size_t n>
3517 return operator[](static_cast<const T>(key));
3549 template<
typename T, std::
size_t n>
3552 return operator[](static_cast<const T>(key));
3582 template<
typename T>
3588 m_type = value_t::object;
3589 m_value = value_t::object;
3596 return m_value.object->operator[](key);
3600 throw std::domain_error(
"cannot use operator[] with " + type_name());
3634 template<
typename T>
3640 assert(m_value.object->find(key) != m_value.object->end());
3645 throw std::domain_error(
"cannot use operator[] with " + type_name());
3697 template<
class ValueType,
typename std::enable_if<
3698 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3699 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3705 const auto it = find(key);
3712 return default_value;
3717 throw std::domain_error(
"cannot use value() with " + type_name());
3725 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3727 return value(key,
string_t(default_value));
3771 template<
class ValueType,
typename std::enable_if<
3772 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3781 return ptr.get_checked(
this);
3783 catch (std::out_of_range&)
3785 return default_value;
3790 throw std::domain_error(
"cannot use value() with " + type_name());
3800 return value(ptr,
string_t(default_value));
3933 template<
class IteratorType,
typename std::enable_if<
3934 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3935 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3940 if (
this != pos.m_object)
3942 throw std::domain_error(
"iterator does not fit current value");
3945 IteratorType result = end();
3949 case value_t::boolean:
3950 case value_t::number_float:
3951 case value_t::number_integer:
3952 case value_t::number_unsigned:
3953 case value_t::string:
3955 if (not pos.m_it.primitive_iterator.is_begin())
3957 throw std::out_of_range(
"iterator out of range");
3962 AllocatorType<string_t> alloc;
3963 alloc.destroy(m_value.string);
3964 alloc.deallocate(m_value.string, 1);
3965 m_value.string =
nullptr;
3968 m_type = value_t::null;
3973 case value_t::object:
3975 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3979 case value_t::array:
3981 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3987 throw std::domain_error(
"cannot use erase() with " + type_name());
4040 template<
class IteratorType,
typename std::enable_if<
4041 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4042 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4044 IteratorType
erase(IteratorType first, IteratorType last)
4047 if (
this != first.m_object or
this != last.m_object)
4049 throw std::domain_error(
"iterators do not fit current value");
4052 IteratorType result = end();
4056 case value_t::boolean:
4057 case value_t::number_float:
4058 case value_t::number_integer:
4059 case value_t::number_unsigned:
4060 case value_t::string:
4062 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4064 throw std::out_of_range(
"iterators out of range");
4069 AllocatorType<string_t> alloc;
4070 alloc.destroy(m_value.string);
4071 alloc.deallocate(m_value.string, 1);
4072 m_value.string =
nullptr;
4075 m_type = value_t::null;
4080 case value_t::object:
4082 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4083 last.m_it.object_iterator);
4087 case value_t::array:
4089 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4090 last.m_it.array_iterator);
4096 throw std::domain_error(
"cannot use erase() with " + type_name());
4137 return m_value.object->erase(key);
4141 throw std::domain_error(
"cannot use erase() with " + type_name());
4176 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4179 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4183 throw std::domain_error(
"cannot use erase() with " + type_name());
4217 auto result = end();
4221 result.m_it.object_iterator = m_value.object->find(key);
4233 auto result = cend();
4237 result.m_it.object_iterator = m_value.object->find(key);
4264 return is_object() ? m_value.object->count(key) : 0;
4552 template<
typename IteratorType>
class iteration_proxy;
4568 return iteration_proxy<iterator>(cont);
4576 return iteration_proxy<const_iterator>(cont);
4636 case value_t::array:
4639 return m_value.array->empty();
4642 case value_t::object:
4645 return m_value.object->empty();
4704 case value_t::array:
4707 return m_value.array->size();
4710 case value_t::object:
4713 return m_value.object->size();
4764 case value_t::array:
4767 return m_value.array->max_size();
4770 case value_t::object:
4773 return m_value.object->max_size();
4823 case value_t::number_integer:
4825 m_value.number_integer = 0;
4829 case value_t::number_unsigned:
4831 m_value.number_unsigned = 0;
4835 case value_t::number_float:
4837 m_value.number_float = 0.0;
4841 case value_t::boolean:
4843 m_value.boolean =
false;
4847 case value_t::string:
4849 m_value.string->clear();
4853 case value_t::array:
4855 m_value.array->clear();
4859 case value_t::object:
4861 m_value.object->clear();
4895 if (not(is_null() or is_array()))
4897 throw std::domain_error(
"cannot use push_back() with " + type_name());
4903 m_type = value_t::array;
4904 m_value = value_t::array;
4909 m_value.array->push_back(std::move(val));
4911 val.m_type = value_t::null;
4920 push_back(std::move(val));
4931 if (not(is_null() or is_array()))
4933 throw std::domain_error(
"cannot use push_back() with " + type_name());
4939 m_type = value_t::array;
4940 m_value = value_t::array;
4945 m_value.array->push_back(val);
4981 if (not(is_null() or is_object()))
4983 throw std::domain_error(
"cannot use push_back() with " + type_name());
4989 m_type = value_t::object;
4990 m_value = value_t::object;
4995 m_value.object->insert(val);
5035 if (is_object() and init.size() == 2 and init.begin()->is_string())
5037 const string_t key = *init.begin();
5038 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5084 if (pos.m_object !=
this)
5086 throw std::domain_error(
"iterator does not fit current value");
5091 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5096 throw std::domain_error(
"cannot use insert() with " + type_name());
5106 return insert(pos, val);
5139 if (pos.m_object !=
this)
5141 throw std::domain_error(
"iterator does not fit current value");
5146 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5151 throw std::domain_error(
"cannot use insert() with " + type_name());
5190 throw std::domain_error(
"cannot use insert() with " + type_name());
5194 if (pos.m_object !=
this)
5196 throw std::domain_error(
"iterator does not fit current value");
5200 if (first.m_object != last.m_object)
5202 throw std::domain_error(
"iterators do not fit");
5205 if (first.m_object ==
this or last.m_object ==
this)
5207 throw std::domain_error(
"passed iterators may not belong to container");
5212 result.m_it.array_iterator = m_value.array->insert(
5213 pos.m_it.array_iterator,
5214 first.m_it.array_iterator,
5215 last.m_it.array_iterator);
5248 throw std::domain_error(
"cannot use insert() with " + type_name());
5252 if (pos.m_object !=
this)
5254 throw std::domain_error(
"iterator does not fit current value");
5259 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5281 std::is_nothrow_move_constructible<value_t>::value and
5282 std::is_nothrow_move_assignable<value_t>::value and
5283 std::is_nothrow_move_constructible<json_value>::value and
5284 std::is_nothrow_move_assignable<json_value>::value
5287 std::swap(m_type, other.m_type);
5288 std::swap(m_value, other.m_value);
5317 std::swap(*(m_value.array), other);
5321 throw std::domain_error(
"cannot use swap() with " + type_name());
5350 std::swap(*(m_value.object), other);
5354 throw std::domain_error(
"cannot use swap() with " + type_name());
5383 std::swap(*(m_value.string), other);
5387 throw std::domain_error(
"cannot use swap() with " + type_name());
5413 static constexpr std::array<uint8_t, 8> order = {{
5426 if (lhs == value_t::discarded or rhs == value_t::discarded)
5431 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5460 const auto lhs_type = lhs.type();
5461 const auto rhs_type = rhs.type();
5463 if (lhs_type == rhs_type)
5467 case value_t::array:
5469 return *lhs.m_value.array == *rhs.m_value.array;
5471 case value_t::object:
5473 return *lhs.m_value.object == *rhs.m_value.object;
5479 case value_t::string:
5481 return *lhs.m_value.string == *rhs.m_value.string;
5483 case value_t::boolean:
5485 return lhs.m_value.boolean == rhs.m_value.boolean;
5487 case value_t::number_integer:
5489 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5491 case value_t::number_unsigned:
5493 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5495 case value_t::number_float:
5497 return lhs.m_value.number_float == rhs.m_value.number_float;
5505 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5507 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5509 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5511 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5513 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5515 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5517 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5519 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5521 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5523 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5525 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5527 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5583 return not (lhs == rhs);
5615 return not v.is_null();
5644 const auto lhs_type = lhs.type();
5645 const auto rhs_type = rhs.type();
5647 if (lhs_type == rhs_type)
5651 case value_t::array:
5653 return *lhs.m_value.array < *rhs.m_value.array;
5655 case value_t::object:
5657 return *lhs.m_value.object < *rhs.m_value.object;
5663 case value_t::string:
5665 return *lhs.m_value.string < *rhs.m_value.string;
5667 case value_t::boolean:
5669 return lhs.m_value.boolean < rhs.m_value.boolean;
5671 case value_t::number_integer:
5673 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5675 case value_t::number_unsigned:
5677 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5679 case value_t::number_float:
5681 return lhs.m_value.number_float < rhs.m_value.number_float;
5689 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5691 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5693 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5695 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5697 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5699 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5701 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5703 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5705 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5707 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5709 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5711 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5717 return operator<(lhs_type, rhs_type);
5739 return not (rhs < lhs);
5761 return not (lhs <= rhs);
5783 return not (lhs < rhs);
5825 const bool pretty_print = (o.width() > 0);
5826 const auto indentation = (pretty_print ? o.width() : 0);
5832 const auto old_locale = o.imbue(std::locale(std::locale(),
new DecimalSeparator));
5839 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5842 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5845 o.imbue(old_locale);
5846 o.precision(old_precision);
5896 template<
class T, std::
size_t N>
5901 return parse(std::begin(array), std::end(array), cb);
5931 template<
typename CharPT,
typename std::enable_if<
5932 std::is_pointer<CharPT>::value and
5933 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5934 sizeof(
typename std::remove_pointer<CharPT>::type) == 1,
int>::type = 0>
5938 return parser(reinterpret_cast<const char*>(s), cb).
parse();
5968 return parser(i, cb).
parse();
5977 return parser(i, cb).
parse();
6021 template<
class IteratorType,
typename std::enable_if<
6023 std::random_access_iterator_tag,
6024 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6030 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6031 [&first](std::pair<bool, int> res, decltype(*first) val)
6033 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6038 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6039 "each element in the iterator range must have the size of 1 byte");
6043 if (std::distance(first, last) <= 0)
6045 return parser(
"").parse();
6048 return parser(first, last, cb).parse();
6091 template<
class ContiguousContainer,
typename std::enable_if<
6092 not std::is_pointer<ContiguousContainer>::value and
6094 std::random_access_iterator_tag,
6095 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6101 return parse(std::begin(c), std::end(c), cb);
6129 j = parser(i).
parse();
6139 j = parser(i).
parse();
6163 std::string type_name()
const 6169 case value_t::object:
6171 case value_t::array:
6173 case value_t::string:
6175 case value_t::boolean:
6177 case value_t::discarded:
6192 static std::size_t extra_space(
const string_t& s) noexcept
6194 return std::accumulate(s.begin(), s.end(),
size_t{},
6195 [](
size_t res,
typename string_t::value_type c)
6213 if (c >= 0x00 and c <= 0x1f)
6242 const auto space = extra_space(s);
6249 string_t result(s.size() + space,
'\\');
6250 std::size_t pos = 0;
6252 for (
const auto& c : s)
6259 result[pos + 1] =
'"';
6275 result[pos + 1] =
'b';
6283 result[pos + 1] =
'f';
6291 result[pos + 1] =
'n';
6299 result[pos + 1] =
'r';
6307 result[pos + 1] =
't';
6314 if (c >= 0x00 and c <= 0x1f)
6318 static const char hexify[16] =
6320 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
6321 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 6326 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
6364 void dump(std::ostream& o,
6365 const bool pretty_print,
6366 const unsigned int indent_step,
6367 const unsigned int current_indent = 0)
const 6370 unsigned int new_indent = current_indent;
6374 case value_t::object:
6376 if (m_value.object->empty())
6387 new_indent += indent_step;
6391 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6393 if (i != m_value.object->cbegin())
6395 o << (pretty_print ?
",\n" :
",");
6397 o <<
string_t(new_indent,
' ') <<
"\"" 6398 << escape_string(i->first) <<
"\":" 6399 << (pretty_print ?
" " :
"");
6400 i->second.dump(o, pretty_print, indent_step, new_indent);
6406 new_indent -= indent_step;
6410 o <<
string_t(new_indent,
' ') +
"}";
6414 case value_t::array:
6416 if (m_value.array->empty())
6427 new_indent += indent_step;
6431 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6433 if (i != m_value.array->cbegin())
6435 o << (pretty_print ?
",\n" :
",");
6438 i->dump(o, pretty_print, indent_step, new_indent);
6444 new_indent -= indent_step;
6448 o <<
string_t(new_indent,
' ') <<
"]";
6452 case value_t::string:
6454 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6458 case value_t::boolean:
6460 o << (m_value.boolean ?
"true" :
"false");
6464 case value_t::number_integer:
6466 o << m_value.number_integer;
6470 case value_t::number_unsigned:
6472 o << m_value.number_unsigned;
6476 case value_t::number_float:
6478 if (m_value.number_float == 0)
6481 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6485 o << m_value.number_float;
6490 case value_t::discarded:
6510 value_t m_type = value_t::null;
6513 json_value m_value = {};
6530 class primitive_iterator_t
6534 void set_begin() noexcept
6540 void set_end() noexcept
6546 constexpr
bool is_begin()
const noexcept
6548 return (m_it == begin_value);
6552 constexpr
bool is_end()
const noexcept
6554 return (m_it == end_value);
6574 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6584 struct internal_iterator
6587 typename object_t::iterator object_iterator;
6589 typename array_t::iterator array_iterator;
6591 primitive_iterator_t primitive_iterator;
6594 internal_iterator() noexcept
6595 : object_iterator(), array_iterator(), primitive_iterator()
6600 template<
typename IteratorType>
6601 class iteration_proxy
6605 class iteration_proxy_internal
6609 IteratorType anchor;
6611 size_t array_index = 0;
6614 explicit iteration_proxy_internal(IteratorType it) noexcept
6619 iteration_proxy_internal& operator*()
6625 iteration_proxy_internal& operator++()
6634 bool operator!= (
const iteration_proxy_internal& o)
const 6636 return anchor != o.anchor;
6642 assert(anchor.m_object !=
nullptr);
6644 switch (anchor.m_object->type())
6647 case value_t::array:
6649 return std::to_string(array_index);
6653 case value_t::object:
6655 return anchor.key();
6667 typename IteratorType::reference value()
const 6669 return anchor.value();
6674 typename IteratorType::reference container;
6678 explicit iteration_proxy(
typename IteratorType::reference cont)
6683 iteration_proxy_internal begin() noexcept
6685 return iteration_proxy_internal(container.begin());
6689 iteration_proxy_internal end() noexcept
6691 return iteration_proxy_internal(container.end());
6715 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6744 assert(m_object !=
nullptr);
6746 switch (m_object->m_type)
6750 m_it.object_iterator =
typename object_t::iterator();
6756 m_it.array_iterator =
typename array_t::iterator();
6762 m_it.primitive_iterator = primitive_iterator_t();
6774 : m_object(other.m_object)
6776 if (m_object !=
nullptr)
6778 switch (m_object->m_type)
6782 m_it.object_iterator = other.m_it.object_iterator;
6788 m_it.array_iterator = other.m_it.array_iterator;
6794 m_it.primitive_iterator = other.m_it.primitive_iterator;
6807 : m_object(other.m_object), m_it(other.m_it)
6816 std::is_nothrow_move_constructible<pointer>::value and
6817 std::is_nothrow_move_assignable<pointer>::value and
6818 std::is_nothrow_move_constructible<internal_iterator>::value and
6819 std::is_nothrow_move_assignable<internal_iterator>::value
6822 std::swap(m_object, other.m_object);
6823 std::swap(m_it, other.m_it);
6832 void set_begin() noexcept
6834 assert(m_object !=
nullptr);
6836 switch (m_object->m_type)
6840 m_it.object_iterator = m_object->m_value.object->begin();
6846 m_it.array_iterator = m_object->m_value.array->begin();
6853 m_it.primitive_iterator.set_end();
6859 m_it.primitive_iterator.set_begin();
6869 void set_end() noexcept
6871 assert(m_object !=
nullptr);
6873 switch (m_object->m_type)
6877 m_it.object_iterator = m_object->m_value.object->end();
6883 m_it.array_iterator = m_object->m_value.array->end();
6889 m_it.primitive_iterator.set_end();
6902 assert(m_object !=
nullptr);
6904 switch (m_object->m_type)
6908 assert(m_it.object_iterator != m_object->m_value.object->end());
6909 return m_it.object_iterator->second;
6914 assert(m_it.array_iterator != m_object->m_value.array->end());
6915 return *m_it.array_iterator;
6920 throw std::out_of_range(
"cannot get value");
6925 if (m_it.primitive_iterator.is_begin())
6931 throw std::out_of_range(
"cannot get value");
6943 assert(m_object !=
nullptr);
6945 switch (m_object->m_type)
6949 assert(m_it.object_iterator != m_object->m_value.object->end());
6950 return &(m_it.object_iterator->second);
6955 assert(m_it.array_iterator != m_object->m_value.array->end());
6956 return &*m_it.array_iterator;
6961 if (m_it.primitive_iterator.is_begin())
6967 throw std::out_of_range(
"cannot get value");
6979 auto result = *
this;
6990 assert(m_object !=
nullptr);
6992 switch (m_object->m_type)
6996 std::advance(m_it.object_iterator, 1);
7002 std::advance(m_it.array_iterator, 1);
7008 ++m_it.primitive_iterator;
7022 auto result = *
this;
7033 assert(m_object !=
nullptr);
7035 switch (m_object->m_type)
7039 std::advance(m_it.object_iterator, -1);
7045 std::advance(m_it.array_iterator, -1);
7051 --m_it.primitive_iterator;
7066 if (m_object != other.m_object)
7068 throw std::domain_error(
"cannot compare iterators of different containers");
7071 assert(m_object !=
nullptr);
7073 switch (m_object->m_type)
7077 return (m_it.object_iterator == other.m_it.object_iterator);
7082 return (m_it.array_iterator == other.m_it.array_iterator);
7087 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7098 return not operator==(other);
7108 if (m_object != other.m_object)
7110 throw std::domain_error(
"cannot compare iterators of different containers");
7113 assert(m_object !=
nullptr);
7115 switch (m_object->m_type)
7119 throw std::domain_error(
"cannot compare order of object iterators");
7124 return (m_it.array_iterator < other.m_it.array_iterator);
7129 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7140 return not other.operator < (*this);
7149 return not operator<=(other);
7158 return not operator<(other);
7167 assert(m_object !=
nullptr);
7169 switch (m_object->m_type)
7173 throw std::domain_error(
"cannot use offsets with object iterators");
7178 std::advance(m_it.array_iterator, i);
7184 m_it.primitive_iterator += i;
7198 return operator+=(-i);
7207 auto result = *
this;
7218 auto result = *
this;
7229 assert(m_object !=
nullptr);
7231 switch (m_object->m_type)
7235 throw std::domain_error(
"cannot use offsets with object iterators");
7240 return m_it.array_iterator - other.m_it.array_iterator;
7245 return m_it.primitive_iterator - other.m_it.primitive_iterator;
7256 assert(m_object !=
nullptr);
7258 switch (m_object->m_type)
7262 throw std::domain_error(
"cannot use operator[] for object iterators");
7267 return *std::next(m_it.array_iterator, n);
7272 throw std::out_of_range(
"cannot get value");
7277 if (m_it.primitive_iterator == -n)
7283 throw std::out_of_range(
"cannot get value");
7293 typename object_t::key_type
key()
const 7295 assert(m_object !=
nullptr);
7297 if (m_object->is_object())
7299 return m_it.object_iterator->first;
7303 throw std::domain_error(
"cannot use key() for non-object iterators");
7320 internal_iterator m_it = internal_iterator();
7357 std::is_nothrow_move_constructible<pointer>::value and
7358 std::is_nothrow_move_assignable<pointer>::value and
7359 std::is_nothrow_move_constructible<internal_iterator>::value and
7360 std::is_nothrow_move_assignable<internal_iterator>::value
7363 base_iterator::operator=(other);
7370 return const_cast<reference>(base_iterator::operator*());
7376 return const_cast<pointer>(base_iterator::operator->());
7383 base_iterator::operator++();
7390 base_iterator::operator++();
7398 base_iterator::operator--();
7405 base_iterator::operator--();
7412 base_iterator::operator+=(i);
7419 base_iterator::operator-=(i);
7426 auto result = *
this;
7434 auto result = *
this;
7442 return base_iterator::operator-(other);
7448 return const_cast<reference>(base_iterator::operator[](n));
7454 return const_cast<reference>(base_iterator::value());
7475 template<
typename Base>
7497 return base_iterator::operator++(1);
7503 base_iterator::operator++();
7510 return base_iterator::operator--(1);
7516 base_iterator::operator--();
7523 base_iterator::operator+=(i);
7530 auto result = *
this;
7538 auto result = *
this;
7546 return this->base() - other.base();
7552 return *(this->operator+(n));
7556 typename object_t::key_type
key()
const 7558 auto it = --this->base();
7565 auto it = --this->base();
7566 return it.operator * ();
7587 enum class token_type
7606 using lexer_char_t =
unsigned char;
7609 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
7612 assert(m_content !=
nullptr);
7613 m_start = m_cursor = m_content;
7614 m_limit = m_content + len;
7618 explicit lexer(std::istream& s)
7619 : m_stream(&s), m_line_buffer()
7627 lexer(
const lexer&) =
delete;
7628 lexer operator=(
const lexer&) =
delete;
7653 static string_t to_unicode(
const std::size_t codepoint1,
7654 const std::size_t codepoint2 = 0)
7657 std::size_t codepoint = codepoint1;
7660 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7663 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7677 throw std::invalid_argument(
"missing or wrong low surrogate");
7683 if (codepoint < 0x80)
7686 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7688 else if (codepoint <= 0x7ff)
7691 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7692 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7694 else if (codepoint <= 0xffff)
7697 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7698 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7699 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7701 else if (codepoint <= 0x10ffff)
7704 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7705 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7706 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7707 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7711 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7718 static std::string token_type_name(
const token_type t)
7722 case token_type::uninitialized:
7723 return "<uninitialized>";
7724 case token_type::literal_true:
7725 return "true literal";
7726 case token_type::literal_false:
7727 return "false literal";
7728 case token_type::literal_null:
7729 return "null literal";
7730 case token_type::value_string:
7731 return "string literal";
7732 case token_type::value_number:
7733 return "number literal";
7734 case token_type::begin_array:
7736 case token_type::begin_object:
7738 case token_type::end_array:
7740 case token_type::end_object:
7742 case token_type::name_separator:
7744 case token_type::value_separator:
7746 case token_type::parse_error:
7747 return "<parse error>";
7748 case token_type::end_of_input:
7749 return "end of input";
7753 return "unknown token";
7788 assert(m_start !=
nullptr);
7793 unsigned int yyaccept = 0;
7794 static const unsigned char yybm[] =
7796 0, 0, 0, 0, 0, 0, 0, 0,
7797 0, 32, 32, 0, 0, 32, 0, 0,
7798 0, 0, 0, 0, 0, 0, 0, 0,
7799 0, 0, 0, 0, 0, 0, 0, 0,
7800 160, 128, 0, 128, 128, 128, 128, 128,
7801 128, 128, 128, 128, 128, 128, 128, 128,
7802 192, 192, 192, 192, 192, 192, 192, 192,
7803 192, 192, 128, 128, 128, 128, 128, 128,
7804 128, 128, 128, 128, 128, 128, 128, 128,
7805 128, 128, 128, 128, 128, 128, 128, 128,
7806 128, 128, 128, 128, 128, 128, 128, 128,
7807 128, 128, 128, 128, 0, 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,
7824 128, 128, 128, 128, 128, 128, 128, 128,
7825 128, 128, 128, 128, 128, 128, 128, 128,
7826 128, 128, 128, 128, 128, 128, 128, 128,
7827 128, 128, 128, 128, 128, 128, 128, 128,
7829 if ((m_limit - m_cursor) < 5)
7834 if (yybm[0 + yych] & 32)
7836 goto basic_json_parser_6;
7846 goto basic_json_parser_2;
7850 goto basic_json_parser_4;
7852 goto basic_json_parser_9;
7858 goto basic_json_parser_4;
7862 goto basic_json_parser_10;
7864 goto basic_json_parser_12;
7873 goto basic_json_parser_4;
7877 goto basic_json_parser_13;
7879 goto basic_json_parser_15;
7885 goto basic_json_parser_17;
7889 goto basic_json_parser_19;
7891 goto basic_json_parser_4;
7903 goto basic_json_parser_21;
7907 goto basic_json_parser_4;
7909 goto basic_json_parser_23;
7915 goto basic_json_parser_24;
7919 goto basic_json_parser_4;
7921 goto basic_json_parser_25;
7930 goto basic_json_parser_26;
7932 goto basic_json_parser_4;
7938 goto basic_json_parser_28;
7942 goto basic_json_parser_30;
7944 goto basic_json_parser_4;
7948 basic_json_parser_2:
7951 last_token_type = token_type::end_of_input;
7954 basic_json_parser_4:
7956 basic_json_parser_5:
7958 last_token_type = token_type::parse_error;
7961 basic_json_parser_6:
7963 if (m_limit <= m_cursor)
7968 if (yybm[0 + yych] & 32)
7970 goto basic_json_parser_6;
7975 basic_json_parser_9:
7977 yych = *(m_marker = ++m_cursor);
7980 goto basic_json_parser_5;
7982 goto basic_json_parser_32;
7983 basic_json_parser_10:
7986 last_token_type = token_type::value_separator;
7989 basic_json_parser_12:
7993 goto basic_json_parser_5;
7997 goto basic_json_parser_13;
8001 goto basic_json_parser_15;
8003 goto basic_json_parser_5;
8004 basic_json_parser_13:
8006 yych = *(m_marker = ++m_cursor);
8011 goto basic_json_parser_37;
8018 goto basic_json_parser_38;
8022 goto basic_json_parser_38;
8025 basic_json_parser_14:
8027 last_token_type = token_type::value_number;
8030 basic_json_parser_15:
8032 m_marker = ++m_cursor;
8033 if ((m_limit - m_cursor) < 3)
8038 if (yybm[0 + yych] & 64)
8040 goto basic_json_parser_15;
8046 goto basic_json_parser_37;
8048 goto basic_json_parser_14;
8054 goto basic_json_parser_38;
8058 goto basic_json_parser_38;
8060 goto basic_json_parser_14;
8062 basic_json_parser_17:
8065 last_token_type = token_type::name_separator;
8068 basic_json_parser_19:
8071 last_token_type = token_type::begin_array;
8074 basic_json_parser_21:
8077 last_token_type = token_type::end_array;
8080 basic_json_parser_23:
8082 yych = *(m_marker = ++m_cursor);
8085 goto basic_json_parser_39;
8087 goto basic_json_parser_5;
8088 basic_json_parser_24:
8090 yych = *(m_marker = ++m_cursor);
8093 goto basic_json_parser_40;
8095 goto basic_json_parser_5;
8096 basic_json_parser_25:
8098 yych = *(m_marker = ++m_cursor);
8101 goto basic_json_parser_41;
8103 goto basic_json_parser_5;
8104 basic_json_parser_26:
8107 last_token_type = token_type::begin_object;
8110 basic_json_parser_28:
8113 last_token_type = token_type::end_object;
8116 basic_json_parser_30:
8118 yych = *(m_marker = ++m_cursor);
8121 goto basic_json_parser_42;
8123 goto basic_json_parser_5;
8124 basic_json_parser_31:
8126 if (m_limit <= m_cursor)
8131 basic_json_parser_32:
8132 if (yybm[0 + yych] & 128)
8134 goto basic_json_parser_31;
8138 goto basic_json_parser_33;
8142 goto basic_json_parser_34;
8144 goto basic_json_parser_36;
8145 basic_json_parser_33:
8146 m_cursor = m_marker;
8149 goto basic_json_parser_5;
8153 goto basic_json_parser_14;
8155 basic_json_parser_34:
8158 last_token_type = token_type::value_string;
8161 basic_json_parser_36:
8163 if (m_limit <= m_cursor)
8174 goto basic_json_parser_31;
8178 goto basic_json_parser_33;
8180 goto basic_json_parser_31;
8188 goto basic_json_parser_33;
8190 goto basic_json_parser_31;
8196 goto basic_json_parser_31;
8198 goto basic_json_parser_33;
8208 goto basic_json_parser_31;
8212 goto basic_json_parser_31;
8214 goto basic_json_parser_33;
8222 goto basic_json_parser_31;
8224 goto basic_json_parser_33;
8230 goto basic_json_parser_31;
8234 goto basic_json_parser_43;
8236 goto basic_json_parser_33;
8240 basic_json_parser_37:
8244 goto basic_json_parser_33;
8248 goto basic_json_parser_44;
8250 goto basic_json_parser_33;
8251 basic_json_parser_38:
8257 goto basic_json_parser_46;
8259 goto basic_json_parser_33;
8265 goto basic_json_parser_46;
8269 goto basic_json_parser_33;
8273 goto basic_json_parser_47;
8275 goto basic_json_parser_33;
8277 basic_json_parser_39:
8281 goto basic_json_parser_49;
8283 goto basic_json_parser_33;
8284 basic_json_parser_40:
8288 goto basic_json_parser_50;
8290 goto basic_json_parser_33;
8291 basic_json_parser_41:
8295 goto basic_json_parser_51;
8297 goto basic_json_parser_33;
8298 basic_json_parser_42:
8302 goto basic_json_parser_52;
8304 goto basic_json_parser_33;
8305 basic_json_parser_43:
8307 if (m_limit <= m_cursor)
8316 goto basic_json_parser_33;
8320 goto basic_json_parser_54;
8322 goto basic_json_parser_33;
8328 goto basic_json_parser_54;
8332 goto basic_json_parser_33;
8336 goto basic_json_parser_54;
8338 goto basic_json_parser_33;
8340 basic_json_parser_44:
8342 m_marker = ++m_cursor;
8343 if ((m_limit - m_cursor) < 3)
8352 goto basic_json_parser_14;
8356 goto basic_json_parser_44;
8358 goto basic_json_parser_14;
8364 goto basic_json_parser_38;
8368 goto basic_json_parser_38;
8370 goto basic_json_parser_14;
8372 basic_json_parser_46:
8376 goto basic_json_parser_33;
8380 goto basic_json_parser_33;
8382 basic_json_parser_47:
8384 if (m_limit <= m_cursor)
8391 goto basic_json_parser_14;
8395 goto basic_json_parser_47;
8397 goto basic_json_parser_14;
8398 basic_json_parser_49:
8402 goto basic_json_parser_55;
8404 goto basic_json_parser_33;
8405 basic_json_parser_50:
8409 goto basic_json_parser_56;
8411 goto basic_json_parser_33;
8412 basic_json_parser_51:
8416 goto basic_json_parser_58;
8418 goto basic_json_parser_33;
8419 basic_json_parser_52:
8424 basic_json_parser_54:
8426 if (m_limit <= m_cursor)
8435 goto basic_json_parser_33;
8439 goto basic_json_parser_60;
8441 goto basic_json_parser_33;
8447 goto basic_json_parser_60;
8451 goto basic_json_parser_33;
8455 goto basic_json_parser_60;
8457 goto basic_json_parser_33;
8459 basic_json_parser_55:
8463 goto basic_json_parser_61;
8465 goto basic_json_parser_33;
8466 basic_json_parser_56:
8469 last_token_type = token_type::literal_null;
8472 basic_json_parser_58:
8475 last_token_type = token_type::literal_true;
8478 basic_json_parser_60:
8480 if (m_limit <= m_cursor)
8489 goto basic_json_parser_33;
8493 goto basic_json_parser_63;
8495 goto basic_json_parser_33;
8501 goto basic_json_parser_63;
8505 goto basic_json_parser_33;
8509 goto basic_json_parser_63;
8511 goto basic_json_parser_33;
8513 basic_json_parser_61:
8516 last_token_type = token_type::literal_false;
8519 basic_json_parser_63:
8521 if (m_limit <= m_cursor)
8530 goto basic_json_parser_33;
8534 goto basic_json_parser_31;
8536 goto basic_json_parser_33;
8542 goto basic_json_parser_31;
8546 goto basic_json_parser_33;
8550 goto basic_json_parser_31;
8552 goto basic_json_parser_33;
8558 return last_token_type;
8589 void fill_line_buffer()
8592 const auto offset_start = m_start - m_content;
8594 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8596 const auto offset_cursor = m_cursor - m_start;
8599 if (m_stream ==
nullptr or m_stream->eof())
8602 m_line_buffer.clear();
8603 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8605 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8611 m_line_buffer.append(5,
'\0');
8616 m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8619 std::getline(*m_stream, line);
8621 m_line_buffer += line +
"\n";
8625 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.c_str());
8626 assert(m_content !=
nullptr);
8627 m_start = m_content;
8628 m_marker = m_start + offset_marker;
8629 m_cursor = m_start + offset_cursor;
8630 m_limit = m_start + m_line_buffer.size();
8636 assert(m_start !=
nullptr);
8637 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8638 static_cast<size_t>(m_cursor - m_start));
8700 assert(m_cursor - m_start >= 2);
8703 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8706 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8762 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8763 4).c_str(),
nullptr, 16);
8766 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8769 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8771 throw std::invalid_argument(
"missing low surrogate");
8775 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8776 (i + 7), 4).c_str(),
nullptr, 16);
8777 result += to_unicode(codepoint, codepoint2);
8784 result += to_unicode(codepoint);
8796 result.append(1, static_cast<typename string_t::value_type>(*i));
8818 long double str_to_float_t(
long double* ,
char** endptr)
const 8820 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8838 double str_to_float_t(
double* ,
char** endptr)
const 8840 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8858 float str_to_float_t(
float* ,
char** endptr)
const 8860 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8886 assert(m_start !=
nullptr);
8888 const lexer::lexer_char_t* curptr = m_start;
8902 type = value_t::number_integer;
8903 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8908 type = value_t::number_unsigned;
8909 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8913 for (; curptr < m_cursor; curptr++)
8916 if (*curptr < '0' || *curptr >
'9')
8921 type = value_t::number_float;
8926 type = value_t::number_float;
8931 if (type != value_t::number_float)
8934 auto temp = value * 10 + *curptr -
'0';
8937 if (temp < value || temp > max)
8940 type = value_t::number_float;
8951 if (type == value_t::number_unsigned)
8953 result.m_value.number_unsigned = value;
8955 else if (type == value_t::number_integer)
8962 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8966 result.m_type = type;
8971 std::istream* m_stream =
nullptr;
8975 const lexer_char_t* m_content =
nullptr;
8977 const lexer_char_t* m_start =
nullptr;
8979 const lexer_char_t* m_marker =
nullptr;
8981 const lexer_char_t* m_cursor =
nullptr;
8983 const lexer_char_t* m_limit =
nullptr;
8985 token_type last_token_type = token_type::end_of_input;
8999 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
9004 : callback(cb), m_lexer(is)
9008 template<
class IteratorType,
typename std::enable_if<
9009 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9012 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
9014 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9015 static_cast<size_t>(std::distance(first, last)))
9025 result.assert_invariant();
9027 expect(lexer::token_type::end_of_input);
9038 auto result =
basic_json(value_t::discarded);
9042 case lexer::token_type::begin_object:
9044 if (keep and (not callback
9045 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9048 result.m_type = value_t::object;
9049 result.m_value = value_t::object;
9056 if (last_token == lexer::token_type::end_object)
9059 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9067 unexpect(lexer::token_type::value_separator);
9073 if (last_token == lexer::token_type::value_separator)
9079 expect(lexer::token_type::value_string);
9080 const auto key = m_lexer.get_string();
9082 bool keep_tag =
false;
9088 keep_tag = callback(depth, parse_event_t::key, k);
9098 expect(lexer::token_type::name_separator);
9102 auto value = parse_internal(keep);
9103 if (keep and keep_tag and not value.is_discarded())
9105 result[key] = std::move(value);
9108 while (last_token == lexer::token_type::value_separator);
9111 expect(lexer::token_type::end_object);
9113 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9121 case lexer::token_type::begin_array:
9123 if (keep and (not callback
9124 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9127 result.m_type = value_t::array;
9128 result.m_value = value_t::array;
9135 if (last_token == lexer::token_type::end_array)
9138 if (callback and not callback(--depth, parse_event_t::array_end, result))
9146 unexpect(lexer::token_type::value_separator);
9152 if (last_token == lexer::token_type::value_separator)
9158 auto value = parse_internal(keep);
9159 if (keep and not value.is_discarded())
9161 result.push_back(std::move(value));
9164 while (last_token == lexer::token_type::value_separator);
9167 expect(lexer::token_type::end_array);
9169 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9177 case lexer::token_type::literal_null:
9180 result.m_type = value_t::null;
9184 case lexer::token_type::value_string:
9186 const auto s = m_lexer.get_string();
9192 case lexer::token_type::literal_true:
9195 result.m_type = value_t::boolean;
9196 result.m_value =
true;
9200 case lexer::token_type::literal_false:
9203 result.m_type = value_t::boolean;
9204 result.m_value =
false;
9208 case lexer::token_type::value_number:
9210 m_lexer.get_number(result);
9218 unexpect(last_token);
9222 if (keep and callback and not callback(depth, parse_event_t::value, result))
9230 typename lexer::token_type get_token()
9232 last_token = m_lexer.scan();
9236 void expect(
typename lexer::token_type t)
const 9238 if (t != last_token)
9240 std::string error_msg =
"parse error - unexpected ";
9241 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9243 lexer::token_type_name(last_token));
9244 error_msg +=
"; expected " + lexer::token_type_name(t);
9245 throw std::invalid_argument(error_msg);
9249 void unexpect(
typename lexer::token_type t)
const 9251 if (t == last_token)
9253 std::string error_msg =
"parse error - unexpected ";
9254 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9256 lexer::token_type_name(last_token));
9257 throw std::invalid_argument(error_msg);
9267 typename lexer::token_type last_token = lexer::token_type::uninitialized;
9313 : reference_tokens(split(s))
9331 std::string to_string()
const noexcept
9333 return std::accumulate(reference_tokens.begin(),
9334 reference_tokens.end(), std::string{},
9335 [](
const std::string & a,
const std::string & b)
9337 return a +
"/" + escape(b);
9342 operator std::string()
const 9349 std::string pop_back()
9353 throw std::domain_error(
"JSON pointer has no parent");
9356 auto last = reference_tokens.back();
9357 reference_tokens.pop_back();
9362 bool is_root()
const 9364 return reference_tokens.empty();
9371 throw std::domain_error(
"JSON pointer has no parent");
9375 result.reference_tokens = {reference_tokens[0]};
9390 for (
const auto& reference_token : reference_tokens)
9392 switch (result->m_type)
9396 if (reference_token ==
"0")
9399 result = &result->operator[](0);
9404 result = &result->operator[](reference_token);
9409 case value_t::object:
9412 result = &result->operator[](reference_token);
9416 case value_t::array:
9419 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9432 throw std::domain_error(
"invalid value to unflatten");
9461 for (
const auto& reference_token : reference_tokens)
9464 if (ptr->m_type == value_t::null)
9467 const bool nums = std::all_of(reference_token.begin(),
9468 reference_token.end(),
9471 return std::isdigit(x);
9476 if (nums or reference_token ==
"-")
9478 *ptr = value_t::array;
9482 *ptr = value_t::object;
9486 switch (ptr->m_type)
9488 case value_t::object:
9491 ptr = &ptr->operator[](reference_token);
9495 case value_t::array:
9498 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9500 throw std::domain_error(
"array index must not begin with '0'");
9503 if (reference_token ==
"-")
9506 ptr = &ptr->operator[](ptr->m_value.array->size());
9511 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9518 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9528 for (
const auto& reference_token : reference_tokens)
9530 switch (ptr->m_type)
9532 case value_t::object:
9535 ptr = &ptr->
at(reference_token);
9539 case value_t::array:
9541 if (reference_token ==
"-")
9544 throw std::out_of_range(
"array index '-' (" +
9545 std::to_string(ptr->m_value.array->size()) +
9546 ") is out of range");
9550 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9552 throw std::domain_error(
"array index must not begin with '0'");
9556 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9562 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9580 for (
const auto& reference_token : reference_tokens)
9582 switch (ptr->m_type)
9584 case value_t::object:
9587 ptr = &ptr->operator[](reference_token);
9591 case value_t::array:
9593 if (reference_token ==
"-")
9596 throw std::out_of_range(
"array index '-' (" +
9597 std::to_string(ptr->m_value.array->size()) +
9598 ") is out of range");
9602 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9604 throw std::domain_error(
"array index must not begin with '0'");
9608 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9614 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9624 for (
const auto& reference_token : reference_tokens)
9626 switch (ptr->m_type)
9628 case value_t::object:
9631 ptr = &ptr->
at(reference_token);
9635 case value_t::array:
9637 if (reference_token ==
"-")
9640 throw std::out_of_range(
"array index '-' (" +
9641 std::to_string(ptr->m_value.array->size()) +
9642 ") is out of range");
9646 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9648 throw std::domain_error(
"array index must not begin with '0'");
9652 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9658 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9667 static std::vector<std::string> split(
const std::string& reference_string)
9669 std::vector<std::string> result;
9672 if (reference_string.empty())
9678 if (reference_string[0] !=
'/')
9680 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9688 size_t slash = reference_string.find_first_of(
"/", 1),
9697 slash = reference_string.find_first_of(
"/", start))
9701 auto reference_token = reference_string.substr(start, slash - start);
9704 for (
size_t pos = reference_token.find_first_of(
"~");
9705 pos != std::string::npos;
9706 pos = reference_token.find_first_of(
"~", pos + 1))
9708 assert(reference_token[pos] ==
'~');
9711 if (pos == reference_token.size() - 1 or
9712 (reference_token[pos + 1] !=
'0' and
9713 reference_token[pos + 1] !=
'1'))
9715 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9720 unescape(reference_token);
9721 result.push_back(reference_token);
9742 static void replace_substring(std::string& s,
9743 const std::string& f,
9744 const std::string& t)
9746 assert(not f.empty());
9749 size_t pos = s.find(f);
9750 pos != std::string::npos;
9751 s.replace(pos, f.size(), t),
9752 pos = s.find(f, pos + t.size())
9757 static std::string escape(std::string s)
9760 replace_substring(s,
"~",
"~0");
9761 replace_substring(s,
"/",
"~1");
9766 static void unescape(std::string& s)
9769 replace_substring(s,
"~1",
"/");
9771 replace_substring(s,
"~0",
"~");
9781 static void flatten(
const std::string& reference_string,
9785 switch (value.m_type)
9787 case value_t::array:
9789 if (value.m_value.array->empty())
9792 result[reference_string] =
nullptr;
9797 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9799 flatten(reference_string +
"/" + std::to_string(i),
9800 value.m_value.array->operator[](i), result);
9806 case value_t::object:
9808 if (value.m_value.object->empty())
9811 result[reference_string] =
nullptr;
9816 for (
const auto& element : *value.m_value.object)
9818 flatten(reference_string +
"/" + escape(element.first),
9819 element.second, result);
9828 result[reference_string] = value;
9843 throw std::domain_error(
"only objects can be unflattened");
9849 for (
const auto& element : *value.m_value.object)
9851 if (not element.second.is_primitive())
9853 throw std::domain_error(
"values in object must be primitive");
9861 json_pointer(element.first).get_and_create(result) = element.second;
9869 std::vector<std::string> reference_tokens {};
9914 return ptr.get_unchecked(
this);
9941 return ptr.get_unchecked(
this);
9966 return ptr.get_checked(
this);
9991 return ptr.get_checked(
this);
10019 json_pointer::flatten(
"", *
this, result);
10052 return json_pointer::unflatten(*
this);
10106 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
10108 const auto get_op = [](
const std::string op)
10112 return patch_operations::add;
10114 if (op ==
"remove")
10116 return patch_operations::remove;
10118 if (op ==
"replace")
10120 return patch_operations::replace;
10124 return patch_operations::move;
10128 return patch_operations::copy;
10132 return patch_operations::test;
10135 return patch_operations::invalid;
10150 if (top_pointer != ptr)
10152 result.
at(top_pointer);
10156 const auto last_path = ptr.pop_back();
10159 switch (parent.m_type)
10161 case value_t::null:
10162 case value_t::object:
10165 parent[last_path] = val;
10169 case value_t::array:
10171 if (last_path ==
"-")
10178 const auto idx = std::stoi(last_path);
10179 if (static_cast<size_type>(idx) > parent.
size())
10182 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
10203 const auto operation_remove = [&result](
json_pointer & ptr)
10206 const auto last_path = ptr.pop_back();
10213 auto it = parent.
find(last_path);
10214 if (it != parent.
end())
10220 throw std::out_of_range(
"key '" + last_path +
"' not found");
10226 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
10234 throw std::invalid_argument(
"JSON patch must be an array of objects");
10238 for (
const auto& val : json_patch)
10241 const auto get_value = [&val](
const std::string & op,
10242 const std::string & member,
10246 auto it = val.m_value.object->find(member);
10249 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
10252 if (it == val.m_value.object->end())
10254 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
10258 if (string_type and not it->second.is_string())
10260 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
10268 if (not val.is_object())
10270 throw std::invalid_argument(
"JSON patch must be an array of objects");
10274 const std::string op = get_value(
"op",
"op",
true);
10275 const std::string path = get_value(op,
"path",
true);
10278 switch (get_op(op))
10280 case patch_operations::add:
10282 operation_add(ptr, get_value(
"add",
"value",
false));
10286 case patch_operations::remove:
10288 operation_remove(ptr);
10292 case patch_operations::replace:
10295 result.
at(ptr) = get_value(
"replace",
"value",
false);
10299 case patch_operations::move:
10301 const std::string from_path = get_value(
"move",
"from",
true);
10311 operation_remove(from_ptr);
10312 operation_add(ptr, v);
10316 case patch_operations::copy:
10318 const std::string from_path = get_value(
"copy",
"from",
true);;
10322 result[ptr] = result.
at(from_ptr);
10326 case patch_operations::test:
10328 bool success =
false;
10333 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
10335 catch (std::out_of_range&)
10343 throw std::domain_error(
"unsuccessful: " + val.dump());
10349 case patch_operations::invalid:
10353 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
10395 const std::string& path =
"")
10401 if (source == target)
10406 if (source.
type() != target.
type())
10418 switch (source.
type())
10420 case value_t::array:
10424 while (i < source.
size() and i < target.
size())
10427 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10428 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10437 while (i < source.
size())
10441 result.insert(result.begin() + end_index, object(
10444 {
"path", path +
"/" + std::to_string(i)}
10450 while (i < target.
size())
10455 {
"path", path +
"/" + std::to_string(i)},
10456 {
"value", target[i]}
10464 case value_t::object:
10467 for (
auto it = source.
begin(); it != source.
end(); ++it)
10470 const auto key = json_pointer::escape(it.key());
10472 if (target.
find(it.key()) != target.
end())
10475 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10476 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10481 result.push_back(
object(
10484 {
"path", path +
"/" + key}
10490 for (
auto it = target.
begin(); it != target.
end(); ++it)
10492 if (source.
find(it.key()) == source.
end())
10495 const auto key = json_pointer::escape(it.key());
10499 {
"path", path +
"/" + key},
10500 {
"value", it.value()}
10560 is_nothrow_move_constructible<nlohmann::json>::value and
10561 is_nothrow_move_assignable<nlohmann::json>::value
10579 const auto& h = hash<nlohmann::json::string_t>();
10597 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10620 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10621 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
size_type max_size() const noexcept
returns the maximum possible number of elements
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
constexpr bool is_array() const noexcept
return whether value is an array
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
basic_json(const value_t value_type)
create an empty value with a given type
basic_json(const array_t &val)
create an array (explicit)
reference value() const
return the value of an iterator
const_iterator end() const noexcept
returns a const iterator to one past the last element
constexpr bool is_primitive() const noexcept
return whether type is primitive
constexpr bool is_null() const noexcept
return whether value is null
ValueType get() const
get a value (explicit)
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
constexpr bool is_structured() const noexcept
return whether type is structured
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
const_reference operator[](size_type idx) const
access specified array element
static basic_json parse(const CharPT s, const parser_callback_t cb=nullptr)
deserialize from string literal
json_reverse_iterator operator--(int)
post-decrement (it–)
reference operator[](T *(&key)[n])
access specified object element
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
iterator & operator+=(difference_type i)
add to iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
const_iterator operator-(difference_type i)
subtract from iterator
BooleanType boolean_t
a type for a boolean
reference operator+=(const typename object_t::value_type &val)
add an object to an object
basic_json(const typename string_t::value_type *val)
create a string (explicit)
object_t::key_type key() const
return the key of an object iterator
iterator find(typename object_t::key_type key)
find an element in a JSON object
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
basic_json(const string_t &val)
create a string (explicit)
reference operator*() const
return a reference to the value pointed to by the iterator
void push_back(const basic_json &val)
add an object to an array
void erase(const size_type idx)
remove element from a JSON array given an index
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
reference front()
access the first element
void swap(object_t &other)
exchanges the values
const_iterator & operator+=(difference_type i)
add to iterator
a class to store JSON values
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
constexpr bool is_object() const noexcept
return whether value is an object
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
NumberIntegerType number_integer_t
a type for a number (integer)
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
const_iterator operator+(difference_type i)
add to iterator
a mutable random access iterator for the basic_json class
const_iterator operator++(int)
post-increment (it++)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
pointer operator->() const
dereference the iterator
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
basic_json(const number_integer_t val) noexcept
create an integer number (explicit)
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
const_reference front() const
access the first element
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
PointerType get_ptr() noexcept
get a pointer value (implicit)
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference back()
access the last element
const value_type & const_reference
the type of an element const reference
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
void push_back(const typename object_t::value_type &val)
add an object to an object
bool empty() const noexcept
checks whether the container is empty
void push_back(std::initializer_list< basic_json > init)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
IteratorType erase(IteratorType pos)
remove element given an iterator
static allocator_type get_allocator()
returns the allocator associated with the container
json_reverse_iterator operator+(difference_type i) const
add to iterator
string_t dump(const int indent=-1) const
serialization
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
std::size_t size_type
a type to represent container sizes
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
const_iterator(const iterator &other) noexcept
copy constructor given a non-const iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
object_t::key_type key() const
return the key of an object iterator
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
iterator & operator++()
pre-increment (++it)
iterator operator++(int)
post-increment (it++)
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
basic_json(basic_json &&other) noexcept
move constructor
const_iterator operator--(int)
post-decrement (it–)
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
object (unordered set of name/value pairs)
iterator operator--(int)
post-decrement (it–)
iterator operator-(difference_type i)
subtract from iterator
const_iterator & operator--()
pre-decrement (–it)
basic_json value_type
the type of elements in a basic_json container
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
AllocatorType< basic_json > allocator_type
the allocator type
StringType string_t
a type for a string
reference operator+=(const basic_json &val)
add an object to an array
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
value_type & reference
the type of an element reference
pointer operator->() const
dereference the iterator
ReferenceType get_ref() const
get a reference value (implicit)
reference value() const
return the value of an iterator
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
size_type size() const noexcept
returns the number of elements
iterator(const iterator &other) noexcept
copy constructor
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
constexpr bool is_string() const noexcept
return whether value is a string
void swap(string_t &other)
exchanges the values
reference operator[](difference_type n) const
access to successor
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference at(size_type idx) const
access specified array element with bounds checking
reference value() const
return the value of an iterator
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
const_reference operator[](T *key) const
read-only access specified object element
NumberFloatType number_float_t
a type for a number (floating-point)
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
std::ptrdiff_t difference_type
a type to represent differences between iterators
difference_type operator-(const const_iterator &other) const
return difference
void swap(array_t &other)
exchanges the values
reference operator[](difference_type n) const
access to successor
typename Base::reference reference
the reference type for the pointed-to element
void push_back(basic_json &&val)
add an object to an array
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
difference_type operator-(const iterator &other) const
return difference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
bool operator!=(const const_iterator &other) const
comparison: not equal
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
bool operator==(const const_iterator &other) const
comparison: equal
bool operator<=(const const_iterator &other) const
comparison: less than or equal
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
friend class basic_json
allow basic_json to access private members
reference operator[](difference_type n) const
access to successor
friend bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
basic_json(const number_float_t val) noexcept
create a floating-point number (explicit)
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
iterator operator+(difference_type i)
add to iterator
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_reference back() const
access the last element
const_iterator & operator++()
pre-increment (++it)
constexpr bool is_number() const noexcept
return whether value is a number
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
const_iterator begin() const noexcept
returns a const iterator to the first element
bool operator>(const const_iterator &other) const
comparison: greater than
std::bidirectional_iterator_tag iterator_category
the category of the iterator
basic_json(boolean_t val) noexcept
create a boolean (explicit)
iterator end() noexcept
returns an iterator to one past the last element
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
iterator begin() noexcept
returns an iterator to the first element
const_iterator cend() const noexcept
returns a const iterator to one past the last element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
reference operator[](const typename object_t::key_type &key)
access specified object element
reference operator+=(basic_json &&val)
add an object to an array
a const random access iterator for the basic_json class
a template for a reverse iterator class
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
json_reverse_iterator operator++(int)
post-increment (it++)
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](size_type idx)
access specified array element
json_reverse_iterator & operator+=(difference_type i)
add to iterator
reference at(size_type idx)
access specified array element with bounds checking
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const object_t &val)
create an object (explicit)
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
const_iterator(const const_iterator &other) noexcept
copy constructor
iterator & operator--()
pre-decrement (–it)
reference operator*() const
return a reference to the value pointed to by the iterator
iterator insert(const_iterator pos, basic_json &&val)
inserts element
ReferenceType get_ref()
get a reference value (implicit)
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const CompatibleStringType &val)
create a string (implicit)
basic_json(const basic_json &other)
copy constructor
bool operator<(const const_iterator &other) const
comparison: smaller
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.