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__) 80 #pragma GCC diagnostic push 81 #pragma GCC diagnostic ignored "-Wdocumentation" 85 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 86 #define JSON_DEPRECATED __attribute__((deprecated)) 87 #elif defined(_MSC_VER) 88 #define JSON_DEPRECATED __declspec(deprecated) 90 #define JSON_DEPRECATED 119 struct has_mapped_type
122 template <
typename U,
typename =
typename U::mapped_type>
123 static int detect(U&&);
125 static void detect(...);
127 static constexpr
bool value =
128 std::is_integral<decltype(detect(std::declval<T>()))>::value;
212 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
213 template<
typename U,
typename... Args>
class ArrayType = std::vector,
214 class StringType = std::string,
215 class BooleanType = bool,
216 class NumberIntegerType = std::int64_t,
217 class NumberUnsignedType = std::uint64_t,
218 class NumberFloatType = double,
219 template<
typename U>
class AllocatorType = std::allocator
226 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
261 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
263 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
378 using object_t = ObjectType<StringType,
380 std::less<StringType>,
381 AllocatorType<std::pair<
const StringType,
428 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
760 template<
typename T,
typename... Args>
761 static T* create(Args&& ... args)
763 AllocatorType<T> alloc;
764 auto deleter = [&](T * object)
766 alloc.deallocate(
object, 1);
768 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
769 alloc.construct(
object.
get(), std::forward<Args>(args)...);
770 assert(
object.
get() !=
nullptr);
771 return object.release();
820 json_value() =
default;
822 json_value(
boolean_t v) noexcept : boolean(v) {}
834 case value_t::object:
836 object = create<object_t>();
842 array = create<array_t>();
846 case value_t::string:
848 string = create<string_t>(
"");
852 case value_t::boolean:
858 case value_t::number_integer:
864 case value_t::number_unsigned:
870 case value_t::number_float:
886 string = create<string_t>(value);
892 object = create<object_t>(value);
896 json_value(
const array_t& value)
898 array = create<array_t>(value);
911 void assert_invariant()
const 913 assert(m_type != value_t::object or m_value.object !=
nullptr);
914 assert(m_type != value_t::array or m_value.array !=
nullptr);
915 assert(m_type != value_t::string or m_value.string !=
nullptr);
1003 basic_json& parsed)>;
1055 : m_type(value_type), m_value(value_type)
1104 : m_type(
value_t::object), m_value(val)
1135 template<
class CompatibleObjectType,
typename std::enable_if<
1136 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1137 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1143 m_value.object = create<object_t>(begin(val), end(val));
1167 : m_type(
value_t::array), m_value(val)
1198 template<
class CompatibleArrayType,
typename std::enable_if<
1199 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1200 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1201 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1202 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1203 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1204 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1205 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1211 m_value.array = create<array_t>(begin(val), end(val));
1237 : m_type(
value_t::string), m_value(val)
1291 template<
class CompatibleStringType,
typename std::enable_if<
1292 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1314 : m_type(value_t::boolean), m_value(val)
1342 template<
typename T,
typename std::enable_if<
1343 not (std::is_same<T, int>::value) and
1344 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1346 : m_type(value_t::number_integer), m_value(val)
1377 : m_type(value_t::number_integer),
1378 m_value(static_cast<number_integer_t>(val))
1408 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1409 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1410 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1411 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1412 CompatibleNumberIntegerType>::type = 0>
1414 : m_type(value_t::number_integer),
1415 m_value(static_cast<number_integer_t>(val))
1437 template<
typename T,
typename std::enable_if<
1438 not (std::is_same<T, int>::value) and
1439 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1441 : m_type(value_t::number_unsigned), m_value(val)
1466 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1467 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1468 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1469 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1470 CompatibleNumberUnsignedType>::type = 0>
1472 : m_type(value_t::number_unsigned),
1473 m_value(static_cast<number_unsigned_t>(val))
1503 : m_type(value_t::number_float), m_value(val)
1506 if (not std::isfinite(val))
1508 m_type = value_t::null;
1509 m_value = json_value();
1546 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1547 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1548 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1625 bool type_deduction =
true,
1626 value_t manual_type = value_t::array)
1630 bool is_an_object = std::all_of(init.begin(), init.end(),
1633 return element.is_array() and element.size() == 2 and element[0].is_string();
1637 if (not type_deduction)
1640 if (manual_type == value_t::array)
1642 is_an_object =
false;
1646 if (manual_type == value_t::object and not is_an_object)
1648 throw std::domain_error(
"cannot create object from initializer list");
1655 m_type = value_t::object;
1656 m_value = value_t::object;
1658 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1660 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1666 m_type = value_t::array;
1667 m_value.array = create<array_t>(init);
1708 std::initializer_list<basic_json>())
1710 return basic_json(init,
false, value_t::array);
1748 std::initializer_list<basic_json>())
1750 return basic_json(init,
false, value_t::object);
1774 m_value.array = create<array_t>(cnt, val);
1815 template<
class InputIT,
typename std::enable_if<
1816 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1817 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1820 assert(first.m_object !=
nullptr);
1821 assert(last.m_object !=
nullptr);
1824 if (first.m_object != last.m_object)
1826 throw std::domain_error(
"iterators are not compatible");
1830 m_type = first.m_object->m_type;
1835 case value_t::boolean:
1836 case value_t::number_float:
1837 case value_t::number_integer:
1838 case value_t::number_unsigned:
1839 case value_t::string:
1841 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1843 throw std::out_of_range(
"iterators out of range");
1856 case value_t::number_integer:
1858 m_value.number_integer = first.m_object->m_value.number_integer;
1862 case value_t::number_unsigned:
1864 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1868 case value_t::number_float:
1870 m_value.number_float = first.m_object->m_value.number_float;
1874 case value_t::boolean:
1876 m_value.boolean = first.m_object->m_value.boolean;
1880 case value_t::string:
1882 m_value = *first.m_object->m_value.string;
1886 case value_t::object:
1888 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1892 case value_t::array:
1894 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1900 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1938 *
this = parser(i, cb).parse();
1969 : m_type(other.m_type)
1972 other.assert_invariant();
1976 case value_t::object:
1978 m_value = *other.m_value.object;
1982 case value_t::array:
1984 m_value = *other.m_value.array;
1988 case value_t::string:
1990 m_value = *other.m_value.string;
1994 case value_t::boolean:
1996 m_value = other.m_value.boolean;
2000 case value_t::number_integer:
2002 m_value = other.m_value.number_integer;
2006 case value_t::number_unsigned:
2008 m_value = other.m_value.number_unsigned;
2012 case value_t::number_float:
2014 m_value = other.m_value.number_float;
2046 : m_type(
std::move(other.m_type)),
2047 m_value(
std::move(other.m_value))
2050 other.assert_invariant();
2053 other.m_type = value_t::null;
2083 std::is_nothrow_move_constructible<value_t>::value and
2084 std::is_nothrow_move_assignable<value_t>::value and
2085 std::is_nothrow_move_constructible<json_value>::value and
2086 std::is_nothrow_move_assignable<json_value>::value
2090 other.assert_invariant();
2093 swap(m_type, other.m_type);
2094 swap(m_value, other.m_value);
2121 case value_t::object:
2123 AllocatorType<object_t> alloc;
2124 alloc.destroy(m_value.object);
2125 alloc.deallocate(m_value.object, 1);
2129 case value_t::array:
2131 AllocatorType<array_t> alloc;
2132 alloc.destroy(m_value.array);
2133 alloc.deallocate(m_value.array, 1);
2137 case value_t::string:
2139 AllocatorType<string_t> alloc;
2140 alloc.destroy(m_value.string);
2141 alloc.deallocate(m_value.string, 1);
2189 std::stringstream ss;
2191 ss.imbue(std::locale::classic());
2197 ss.precision(std::numeric_limits<double>::digits10);
2201 dump(ss,
true, static_cast<unsigned int>(indent));
2261 return is_null() or is_string() or is_boolean() or is_number();
2288 return is_array() or is_object();
2310 return m_type == value_t::null;
2332 return m_type == value_t::boolean;
2362 return is_number_integer() or is_number_float();
2391 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2419 return m_type == value_t::number_unsigned;
2447 return m_type == value_t::number_float;
2469 return m_type == value_t::object;
2491 return m_type == value_t::array;
2513 return m_type == value_t::string;
2540 return m_type == value_t::discarded;
2574 template<
class T,
typename std::enable_if<
2575 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2576 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2577 T get_impl(T*)
const 2581 return T(m_value.object->begin(), m_value.object->end());
2585 throw std::domain_error(
"type must be object, but is " + type_name());
2594 return *(m_value.object);
2598 throw std::domain_error(
"type must be object, but is " + type_name());
2603 template<
class T,
typename std::enable_if<
2604 std::is_convertible<basic_json_t, typename T::value_type>::value and
2605 not std::is_same<basic_json_t, typename T::value_type>::value and
2606 not std::is_arithmetic<T>::value and
2607 not std::is_convertible<std::string, T>::value and
2608 not has_mapped_type<T>::value,
int>::type = 0>
2609 T get_impl(T*)
const 2614 std::transform(m_value.array->begin(), m_value.array->end(),
2615 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2617 return i.
get<
typename T::value_type>();
2623 throw std::domain_error(
"type must be array, but is " + type_name());
2628 template<
class T,
typename std::enable_if<
2629 std::is_convertible<basic_json_t, T>::value and
2630 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2631 std::vector<T> get_impl(std::vector<T>*)
const 2635 std::vector<T> to_vector;
2636 to_vector.reserve(m_value.array->size());
2637 std::transform(m_value.array->begin(), m_value.array->end(),
2638 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2646 throw std::domain_error(
"type must be array, but is " + type_name());
2651 template<
class T,
typename std::enable_if<
2652 std::is_same<basic_json, typename T::value_type>::value and
2653 not has_mapped_type<T>::value,
int>::type = 0>
2654 T get_impl(T*)
const 2658 return T(m_value.array->begin(), m_value.array->end());
2662 throw std::domain_error(
"type must be array, but is " + type_name());
2671 return *(m_value.array);
2675 throw std::domain_error(
"type must be array, but is " + type_name());
2680 template<
typename T,
typename std::enable_if<
2681 std::is_convertible<string_t, T>::value,
int>::type = 0>
2682 T get_impl(T*)
const 2686 return *m_value.string;
2690 throw std::domain_error(
"type must be string, but is " + type_name());
2695 template<
typename T,
typename std::enable_if<
2696 std::is_arithmetic<T>::value,
int>::type = 0>
2697 T get_impl(T*)
const 2701 case value_t::number_integer:
2703 return static_cast<T
>(m_value.number_integer);
2706 case value_t::number_unsigned:
2708 return static_cast<T
>(m_value.number_unsigned);
2711 case value_t::number_float:
2713 return static_cast<T
>(m_value.number_float);
2718 throw std::domain_error(
"type must be number, but is " + type_name());
2728 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2734 return is_object() ? m_value.object :
nullptr;
2740 return is_object() ? m_value.object :
nullptr;
2746 return is_array() ? m_value.array :
nullptr;
2750 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2752 return is_array() ? m_value.array :
nullptr;
2758 return is_string() ? m_value.string :
nullptr;
2764 return is_string() ? m_value.string :
nullptr;
2770 return is_boolean() ? &m_value.boolean :
nullptr;
2776 return is_boolean() ? &m_value.boolean :
nullptr;
2782 return is_number_integer() ? &m_value.number_integer :
nullptr;
2788 return is_number_integer() ? &m_value.number_integer :
nullptr;
2794 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2800 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2806 return is_number_float() ? &m_value.number_float :
nullptr;
2812 return is_number_float() ? &m_value.number_float :
nullptr;
2826 template<
typename ReferenceType,
typename ThisType>
2827 static ReferenceType get_ref_impl(ThisType& obj)
2830 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2833 auto ptr = obj.template get_ptr<PointerType>();
2841 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2885 template<
typename ValueType,
typename std::enable_if<
2886 not std::is_pointer<ValueType>::value,
int>::type = 0>
2887 ValueType
get()
const 2889 return get_impl(static_cast<ValueType*>(
nullptr));
2919 template<
typename PointerType,
typename std::enable_if<
2920 std::is_pointer<PointerType>::value,
int>::type = 0>
2921 PointerType
get() noexcept
2924 return get_ptr<PointerType>();
2931 template<
typename PointerType,
typename std::enable_if<
2932 std::is_pointer<PointerType>::value,
int>::type = 0>
2933 constexpr
const PointerType
get()
const noexcept
2936 return get_ptr<PointerType>();
2965 template<
typename PointerType,
typename std::enable_if<
2966 std::is_pointer<PointerType>::value,
int>::type = 0>
2970 using pointee_t =
typename std::remove_const<
typename 2971 std::remove_pointer<
typename 2972 std::remove_const<PointerType>::type>::type>::type;
2975 std::is_same<object_t, pointee_t>::value
2976 or std::is_same<array_t, pointee_t>::value
2977 or std::is_same<string_t, pointee_t>::value
2978 or std::is_same<boolean_t, pointee_t>::value
2979 or std::is_same<number_integer_t, pointee_t>::value
2980 or std::is_same<number_unsigned_t, pointee_t>::value
2981 or std::is_same<number_float_t, pointee_t>::value
2982 ,
"incompatible pointer type");
2985 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2992 template<
typename PointerType,
typename std::enable_if<
2993 std::is_pointer<PointerType>::value and
2994 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
2995 constexpr
const PointerType
get_ptr() const noexcept
2998 using pointee_t =
typename std::remove_const<
typename 2999 std::remove_pointer<
typename 3000 std::remove_const<PointerType>::type>::type>::type;
3003 std::is_same<object_t, pointee_t>::value
3004 or std::is_same<array_t, pointee_t>::value
3005 or std::is_same<string_t, pointee_t>::value
3006 or std::is_same<boolean_t, pointee_t>::value
3007 or std::is_same<number_integer_t, pointee_t>::value
3008 or std::is_same<number_unsigned_t, pointee_t>::value
3009 or std::is_same<number_float_t, pointee_t>::value
3010 ,
"incompatible pointer type");
3013 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3042 template<
typename ReferenceType,
typename std::enable_if<
3043 std::is_reference<ReferenceType>::value,
int>::type = 0>
3047 return get_ref_impl<ReferenceType>(*this);
3054 template<
typename ReferenceType,
typename std::enable_if<
3055 std::is_reference<ReferenceType>::value and
3056 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3060 return get_ref_impl<ReferenceType>(*this);
3091 template <
typename ValueType,
typename std::enable_if <
3092 not std::is_pointer<ValueType>::value and
3093 not std::is_same<ValueType, typename string_t::value_type>::value
3094 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3095 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3098 operator ValueType()
const 3101 return get<ValueType>();
3144 return m_value.
array->
at(idx);
3146 catch (std::out_of_range&)
3149 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3154 throw std::domain_error(
"cannot use at() with " + type_name());
3187 return m_value.
array->
at(idx);
3189 catch (std::out_of_range&)
3192 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3197 throw std::domain_error(
"cannot use at() with " + type_name());
3236 catch (std::out_of_range&)
3239 throw std::out_of_range(
"key '" + key +
"' not found");
3244 throw std::domain_error(
"cannot use at() with " + type_name());
3283 catch (std::out_of_range&)
3286 throw std::out_of_range(
"key '" + key +
"' not found");
3291 throw std::domain_error(
"cannot use at() with " + type_name());
3325 m_type = value_t::array;
3326 m_value.
array = create<array_t>();
3334 if (idx >= m_value.array->size())
3336 m_value.array->insert(m_value.array->end(),
3337 idx - m_value.array->size() + 1,
3341 return m_value.array->operator[](idx);
3345 throw std::domain_error(
"cannot use operator[] with " + type_name());
3373 return m_value.
array->operator[](idx);
3377 throw std::domain_error(
"cannot use operator[] with " + type_name());
3413 m_type = value_t::object;
3414 m_value.
object = create<object_t>();
3421 return m_value.object->operator[](key);
3425 throw std::domain_error(
"cannot use operator[] with " + type_name());
3464 assert(m_value.object->find(key) != m_value.object->end());
3469 throw std::domain_error(
"cannot use operator[] with " + type_name());
3500 template<
typename T, std::
size_t n>
3503 return operator[](static_cast<const T>(key));
3535 template<
typename T, std::
size_t n>
3538 return operator[](static_cast<const T>(key));
3568 template<
typename T>
3574 m_type = value_t::object;
3575 m_value = value_t::object;
3582 return m_value.object->operator[](key);
3586 throw std::domain_error(
"cannot use operator[] with " + type_name());
3620 template<
typename T>
3626 assert(m_value.object->find(key) != m_value.object->end());
3631 throw std::domain_error(
"cannot use operator[] with " + type_name());
3683 template<
class ValueType,
typename std::enable_if<
3684 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3685 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3691 const auto it = find(key);
3698 return default_value;
3703 throw std::domain_error(
"cannot use value() with " + type_name());
3711 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3713 return value(key,
string_t(default_value));
3757 template<
class ValueType,
typename std::enable_if<
3758 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3767 return ptr.get_checked(
this);
3769 catch (std::out_of_range&)
3771 return default_value;
3776 throw std::domain_error(
"cannot use value() with " + type_name());
3786 return value(ptr,
string_t(default_value));
3919 template<
class IteratorType,
typename std::enable_if<
3920 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3921 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3926 if (
this != pos.m_object)
3928 throw std::domain_error(
"iterator does not fit current value");
3931 IteratorType result = end();
3935 case value_t::boolean:
3936 case value_t::number_float:
3937 case value_t::number_integer:
3938 case value_t::number_unsigned:
3939 case value_t::string:
3941 if (not pos.m_it.primitive_iterator.is_begin())
3943 throw std::out_of_range(
"iterator out of range");
3948 AllocatorType<string_t> alloc;
3949 alloc.destroy(m_value.string);
3950 alloc.deallocate(m_value.string, 1);
3951 m_value.string =
nullptr;
3954 m_type = value_t::null;
3959 case value_t::object:
3961 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3965 case value_t::array:
3967 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3973 throw std::domain_error(
"cannot use erase() with " + type_name());
4026 template<
class IteratorType,
typename std::enable_if<
4027 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4028 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4030 IteratorType
erase(IteratorType first, IteratorType last)
4033 if (
this != first.m_object or
this != last.m_object)
4035 throw std::domain_error(
"iterators do not fit current value");
4038 IteratorType result = end();
4042 case value_t::boolean:
4043 case value_t::number_float:
4044 case value_t::number_integer:
4045 case value_t::number_unsigned:
4046 case value_t::string:
4048 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4050 throw std::out_of_range(
"iterators out of range");
4055 AllocatorType<string_t> alloc;
4056 alloc.destroy(m_value.string);
4057 alloc.deallocate(m_value.string, 1);
4058 m_value.string =
nullptr;
4061 m_type = value_t::null;
4066 case value_t::object:
4068 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4069 last.m_it.object_iterator);
4073 case value_t::array:
4075 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4076 last.m_it.array_iterator);
4082 throw std::domain_error(
"cannot use erase() with " + type_name());
4123 return m_value.object->erase(key);
4127 throw std::domain_error(
"cannot use erase() with " + type_name());
4162 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4165 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4169 throw std::domain_error(
"cannot use erase() with " + type_name());
4203 auto result = end();
4207 result.m_it.object_iterator = m_value.object->find(key);
4219 auto result = cend();
4223 result.m_it.object_iterator = m_value.object->find(key);
4250 return is_object() ? m_value.object->count(key) : 0;
4538 template<
typename IteratorType>
class iteration_proxy;
4554 return iteration_proxy<iterator>(cont);
4562 return iteration_proxy<const_iterator>(cont);
4622 case value_t::array:
4625 return m_value.array->empty();
4628 case value_t::object:
4631 return m_value.object->empty();
4690 case value_t::array:
4693 return m_value.array->size();
4696 case value_t::object:
4699 return m_value.object->size();
4750 case value_t::array:
4753 return m_value.array->max_size();
4756 case value_t::object:
4759 return m_value.object->max_size();
4809 case value_t::number_integer:
4811 m_value.number_integer = 0;
4815 case value_t::number_unsigned:
4817 m_value.number_unsigned = 0;
4821 case value_t::number_float:
4823 m_value.number_float = 0.0;
4827 case value_t::boolean:
4829 m_value.boolean =
false;
4833 case value_t::string:
4835 m_value.string->clear();
4839 case value_t::array:
4841 m_value.array->clear();
4845 case value_t::object:
4847 m_value.object->clear();
4881 if (not(is_null() or is_array()))
4883 throw std::domain_error(
"cannot use push_back() with " + type_name());
4889 m_type = value_t::array;
4890 m_value = value_t::array;
4895 m_value.array->push_back(std::move(val));
4897 val.m_type = value_t::null;
4906 push_back(std::move(val));
4917 if (not(is_null() or is_array()))
4919 throw std::domain_error(
"cannot use push_back() with " + type_name());
4925 m_type = value_t::array;
4926 m_value = value_t::array;
4931 m_value.array->push_back(val);
4967 if (not(is_null() or is_object()))
4969 throw std::domain_error(
"cannot use push_back() with " + type_name());
4975 m_type = value_t::object;
4976 m_value = value_t::object;
4981 m_value.object->insert(val);
5021 if (is_object() and init.size() == 2 and init.begin()->is_string())
5023 const string_t key = *init.begin();
5024 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5063 template<
class... Args>
5067 if (not(is_null() or is_array()))
5069 throw std::domain_error(
"cannot use emplace_back() with " + type_name());
5075 m_type = value_t::array;
5076 m_value = value_t::array;
5081 m_value.array->emplace_back(std::forward<Args>(args)...);
5111 template<
class... Args>
5112 std::pair<iterator, bool>
emplace(Args&& ... args)
5115 if (not(is_null() or is_object()))
5117 throw std::domain_error(
"cannot use emplace() with " + type_name());
5123 m_type = value_t::object;
5124 m_value = value_t::object;
5129 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5132 it.m_it.object_iterator = res.first;
5135 return {it, res.second};
5166 if (pos.m_object !=
this)
5168 throw std::domain_error(
"iterator does not fit current value");
5173 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5178 throw std::domain_error(
"cannot use insert() with " + type_name());
5188 return insert(pos, val);
5221 if (pos.m_object !=
this)
5223 throw std::domain_error(
"iterator does not fit current value");
5228 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5233 throw std::domain_error(
"cannot use insert() with " + type_name());
5272 throw std::domain_error(
"cannot use insert() with " + type_name());
5276 if (pos.m_object !=
this)
5278 throw std::domain_error(
"iterator does not fit current value");
5282 if (first.m_object != last.m_object)
5284 throw std::domain_error(
"iterators do not fit");
5287 if (first.m_object ==
this or last.m_object ==
this)
5289 throw std::domain_error(
"passed iterators may not belong to container");
5294 result.m_it.array_iterator = m_value.array->insert(
5295 pos.m_it.array_iterator,
5296 first.m_it.array_iterator,
5297 last.m_it.array_iterator);
5330 throw std::domain_error(
"cannot use insert() with " + type_name());
5334 if (pos.m_object !=
this)
5336 throw std::domain_error(
"iterator does not fit current value");
5341 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5363 std::is_nothrow_move_constructible<value_t>::value and
5364 std::is_nothrow_move_assignable<value_t>::value and
5365 std::is_nothrow_move_constructible<json_value>::value and
5366 std::is_nothrow_move_assignable<json_value>::value
5369 std::swap(m_type, other.m_type);
5370 std::swap(m_value, other.m_value);
5399 std::swap(*(m_value.array), other);
5403 throw std::domain_error(
"cannot use swap() with " + type_name());
5432 std::swap(*(m_value.object), other);
5436 throw std::domain_error(
"cannot use swap() with " + type_name());
5465 std::swap(*(m_value.string), other);
5469 throw std::domain_error(
"cannot use swap() with " + type_name());
5495 static constexpr std::array<uint8_t, 8> order = {{
5508 if (lhs == value_t::discarded or rhs == value_t::discarded)
5513 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5542 const auto lhs_type = lhs.type();
5543 const auto rhs_type = rhs.type();
5545 if (lhs_type == rhs_type)
5549 case value_t::array:
5551 return *lhs.m_value.array == *rhs.m_value.array;
5553 case value_t::object:
5555 return *lhs.m_value.object == *rhs.m_value.object;
5561 case value_t::string:
5563 return *lhs.m_value.string == *rhs.m_value.string;
5565 case value_t::boolean:
5567 return lhs.m_value.boolean == rhs.m_value.boolean;
5569 case value_t::number_integer:
5571 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5573 case value_t::number_unsigned:
5575 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5577 case value_t::number_float:
5579 return lhs.m_value.number_float == rhs.m_value.number_float;
5587 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5589 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5591 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5593 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5595 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5597 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5599 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5601 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5603 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5605 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5607 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5609 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5665 return not (lhs == rhs);
5697 return not v.is_null();
5726 const auto lhs_type = lhs.type();
5727 const auto rhs_type = rhs.type();
5729 if (lhs_type == rhs_type)
5733 case value_t::array:
5735 return *lhs.m_value.array < *rhs.m_value.array;
5737 case value_t::object:
5739 return *lhs.m_value.object < *rhs.m_value.object;
5745 case value_t::string:
5747 return *lhs.m_value.string < *rhs.m_value.string;
5749 case value_t::boolean:
5751 return lhs.m_value.boolean < rhs.m_value.boolean;
5753 case value_t::number_integer:
5755 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5757 case value_t::number_unsigned:
5759 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5761 case value_t::number_float:
5763 return lhs.m_value.number_float < rhs.m_value.number_float;
5771 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5773 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5775 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5777 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5779 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5781 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5783 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5785 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5787 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5789 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5791 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5793 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5799 return operator<(lhs_type, rhs_type);
5821 return not (rhs < lhs);
5843 return not (lhs <= rhs);
5865 return not (lhs < rhs);
5907 const bool pretty_print = (o.width() > 0);
5908 const auto indentation = (pretty_print ? o.width() : 0);
5914 const auto old_locale = o.imbue(std::locale::classic());
5921 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5924 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5927 o.imbue(old_locale);
5928 o.precision(old_precision);
5978 template<
class T, std::
size_t N>
5983 return parse(std::begin(array), std::end(array), cb);
6013 template<
typename CharT,
typename std::enable_if<
6014 std::is_pointer<CharT>::value and
6015 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6016 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
6020 return parser(reinterpret_cast<const char*>(s), cb).
parse();
6050 return parser(i, cb).
parse();
6059 return parser(i, cb).
parse();
6103 template<
class IteratorType,
typename std::enable_if<
6105 std::random_access_iterator_tag,
6106 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6112 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6113 [&first](std::pair<bool, int> res, decltype(*first) val)
6115 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6120 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6121 "each element in the iterator range must have the size of 1 byte");
6125 if (std::distance(first, last) <= 0)
6127 return parser(
"").parse();
6130 return parser(first, last, cb).parse();
6173 template<
class ContiguousContainer,
typename std::enable_if<
6174 not std::is_pointer<ContiguousContainer>::value and
6176 std::random_access_iterator_tag,
6177 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6183 return parse(std::begin(c), std::end(c), cb);
6211 j = parser(i).
parse();
6221 j = parser(i).
parse();
6235 template<
typename T>
6236 static void add_to_vector(std::vector<uint8_t>& vec,
size_t bytes,
const T number)
6238 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6244 vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6245 vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6246 vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6247 vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6253 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6254 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6260 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6266 vec.push_back(static_cast<uint8_t>(number & 0xff));
6308 template<
typename T>
6309 static T get_from_vector(
const std::vector<uint8_t>& vec,
const size_t current_index)
6311 if (current_index +
sizeof(T) + 1 > vec.size())
6313 throw std::out_of_range(
"cannot read " + std::to_string(
sizeof(T)) +
" bytes from vector");
6317 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(&result);
6318 for (
size_t i = 0; i <
sizeof(T); ++i)
6320 *ptr++ = vec[current_index +
sizeof(T) - i];
6335 static void to_msgpack_internal(
const basic_json& j, std::vector<uint8_t>& v)
6346 case value_t::boolean:
6349 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6353 case value_t::number_integer:
6355 if (j.m_value.number_integer >= 0)
6360 if (j.m_value.number_unsigned < 128)
6363 add_to_vector(v, 1, j.m_value.number_unsigned);
6365 else if (j.m_value.number_unsigned <= UINT8_MAX)
6369 add_to_vector(v, 1, j.m_value.number_unsigned);
6371 else if (j.m_value.number_unsigned <= UINT16_MAX)
6375 add_to_vector(v, 2, j.m_value.number_unsigned);
6377 else if (j.m_value.number_unsigned <= UINT32_MAX)
6381 add_to_vector(v, 4, j.m_value.number_unsigned);
6383 else if (j.m_value.number_unsigned <= UINT64_MAX)
6387 add_to_vector(v, 8, j.m_value.number_unsigned);
6392 if (j.m_value.number_integer >= -32)
6395 add_to_vector(v, 1, j.m_value.number_integer);
6397 else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6401 add_to_vector(v, 1, j.m_value.number_integer);
6403 else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6407 add_to_vector(v, 2, j.m_value.number_integer);
6409 else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6413 add_to_vector(v, 4, j.m_value.number_integer);
6415 else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6419 add_to_vector(v, 8, j.m_value.number_integer);
6425 case value_t::number_unsigned:
6427 if (j.m_value.number_unsigned < 128)
6430 add_to_vector(v, 1, j.m_value.number_unsigned);
6432 else if (j.m_value.number_unsigned <= UINT8_MAX)
6436 add_to_vector(v, 1, j.m_value.number_unsigned);
6438 else if (j.m_value.number_unsigned <= UINT16_MAX)
6442 add_to_vector(v, 2, j.m_value.number_unsigned);
6444 else if (j.m_value.number_unsigned <= UINT32_MAX)
6448 add_to_vector(v, 4, j.m_value.number_unsigned);
6450 else if (j.m_value.number_unsigned <= UINT64_MAX)
6454 add_to_vector(v, 8, j.m_value.number_unsigned);
6459 case value_t::number_float:
6463 const uint8_t* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6464 for (
size_t i = 0; i < 8; ++i)
6466 v.push_back(helper[7 - i]);
6471 case value_t::string:
6473 const auto N = j.m_value.string->size();
6477 v.push_back(static_cast<uint8_t>(0xa0 | N));
6483 add_to_vector(v, 1, N);
6485 else if (N <= 65535)
6489 add_to_vector(v, 2, N);
6491 else if (N <= 4294967295)
6495 add_to_vector(v, 4, N);
6499 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6500 std::back_inserter(v));
6504 case value_t::array:
6506 const auto N = j.m_value.array->size();
6510 v.push_back(static_cast<uint8_t>(0x90 | N));
6512 else if (N <= 0xffff)
6516 add_to_vector(v, 2, N);
6518 else if (N <= 0xffffffff)
6522 add_to_vector(v, 4, N);
6526 for (
const auto& el : *j.m_value.array)
6528 to_msgpack_internal(el, v);
6533 case value_t::object:
6535 const auto N = j.m_value.object->size();
6539 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6541 else if (N <= 65535)
6545 add_to_vector(v, 2, N);
6547 else if (N <= 4294967295)
6551 add_to_vector(v, 4, N);
6555 for (
const auto& el : *j.m_value.object)
6557 to_msgpack_internal(el.first, v);
6558 to_msgpack_internal(el.second, v);
6580 static void to_cbor_internal(
const basic_json& j, std::vector<uint8_t>& v)
6590 case value_t::boolean:
6592 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6596 case value_t::number_integer:
6598 if (j.m_value.number_integer >= 0)
6603 if (j.m_value.number_integer <= 0x17)
6605 add_to_vector(v, 1, j.m_value.number_integer);
6607 else if (j.m_value.number_integer <= UINT8_MAX)
6611 add_to_vector(v, 1, j.m_value.number_integer);
6613 else if (j.m_value.number_integer <= UINT16_MAX)
6617 add_to_vector(v, 2, j.m_value.number_integer);
6619 else if (j.m_value.number_integer <= UINT32_MAX)
6623 add_to_vector(v, 4, j.m_value.number_integer);
6629 add_to_vector(v, 8, j.m_value.number_integer);
6636 const auto positive_number = -1 - j.m_value.number_integer;
6637 if (j.m_value.number_integer >= -24)
6639 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6641 else if (positive_number <= UINT8_MAX)
6645 add_to_vector(v, 1, positive_number);
6647 else if (positive_number <= UINT16_MAX)
6651 add_to_vector(v, 2, positive_number);
6653 else if (positive_number <= UINT32_MAX)
6657 add_to_vector(v, 4, positive_number);
6663 add_to_vector(v, 8, positive_number);
6669 case value_t::number_unsigned:
6671 if (j.m_value.number_unsigned <= 0x17)
6673 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6675 else if (j.m_value.number_unsigned <= 0xff)
6679 add_to_vector(v, 1, j.m_value.number_unsigned);
6681 else if (j.m_value.number_unsigned <= 0xffff)
6685 add_to_vector(v, 2, j.m_value.number_unsigned);
6687 else if (j.m_value.number_unsigned <= 0xffffffff)
6691 add_to_vector(v, 4, j.m_value.number_unsigned);
6693 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6697 add_to_vector(v, 8, j.m_value.number_unsigned);
6702 case value_t::number_float:
6706 const uint8_t* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6707 for (
size_t i = 0; i < 8; ++i)
6709 v.push_back(helper[7 - i]);
6714 case value_t::string:
6716 const auto N = j.m_value.string->size();
6719 v.push_back(0x60 + N);
6724 add_to_vector(v, 1, N);
6726 else if (N <= 0xffff)
6729 add_to_vector(v, 2, N);
6731 else if (N <= 0xffffffff)
6734 add_to_vector(v, 4, N);
6737 else if (N <= 0xffffffffffffffff)
6740 add_to_vector(v, 8, N);
6745 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6746 std::back_inserter(v));
6750 case value_t::array:
6752 const auto N = j.m_value.array->size();
6755 v.push_back(0x80 + N);
6760 add_to_vector(v, 1, N);
6762 else if (N <= 0xffff)
6765 add_to_vector(v, 2, N);
6767 else if (N <= 0xffffffff)
6770 add_to_vector(v, 4, N);
6773 else if (N <= 0xffffffffffffffff)
6776 add_to_vector(v, 8, N);
6781 for (
const auto& el : *j.m_value.array)
6783 to_cbor_internal(el, v);
6788 case value_t::object:
6790 const auto N = j.m_value.object->size();
6793 v.push_back(0xa0 + N);
6798 add_to_vector(v, 1, N);
6800 else if (N <= 0xffff)
6803 add_to_vector(v, 2, N);
6805 else if (N <= 0xffffffff)
6808 add_to_vector(v, 4, N);
6811 else if (N <= 0xffffffffffffffff)
6814 add_to_vector(v, 8, N);
6819 for (
const auto& el : *j.m_value.object)
6821 to_cbor_internal(el.first, v);
6822 to_cbor_internal(el.second, v);
6848 static basic_json from_msgpack_internal(
const std::vector<uint8_t>& v,
size_t& idx)
6851 const size_t current_idx = idx++;
6853 if (v[current_idx] <= 0xbf)
6855 if (v[current_idx] <= 0x7f)
6857 return v[current_idx];
6859 else if (v[current_idx] <= 0x8f)
6862 const size_t len = v[current_idx] & 0x0f;
6863 for (
size_t i = 0; i < len; ++i)
6865 std::string key = from_msgpack_internal(v, idx);
6866 result[key] = from_msgpack_internal(v, idx);
6870 else if (v[current_idx] <= 0x9f)
6873 const size_t len = v[current_idx] & 0x0f;
6874 for (
size_t i = 0; i < len; ++i)
6876 result.
push_back(from_msgpack_internal(v, idx));
6882 const size_t len = v[current_idx] & 0x1f;
6883 const size_t offset = current_idx + 1;
6885 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6888 else if (v[current_idx] >= 0xe0)
6890 return static_cast<int8_t
>(v[current_idx]);
6894 switch (v[current_idx])
6898 return value_t::null;
6915 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
6917 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v[current_idx + 1 + byte];
6919 idx +=
sizeof(float);
6927 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
6929 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v[current_idx + 1 + byte];
6931 idx +=
sizeof(double);
6938 return get_from_vector<uint8_t>(v, current_idx);
6944 return get_from_vector<uint16_t>(v, current_idx);
6950 return get_from_vector<uint32_t>(v, current_idx);
6956 return get_from_vector<uint64_t>(v, current_idx);
6962 return get_from_vector<int8_t>(v, current_idx);
6968 return get_from_vector<int16_t>(v, current_idx);
6974 return get_from_vector<int32_t>(v, current_idx);
6980 return get_from_vector<int64_t>(v, current_idx);
6985 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
6986 const size_t offset = current_idx + 2;
6988 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6993 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
6994 const size_t offset = current_idx + 3;
6996 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7001 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7002 const size_t offset = current_idx + 5;
7004 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7010 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7012 for (
size_t i = 0; i < len; ++i)
7014 result.
push_back(from_msgpack_internal(v, idx));
7022 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7024 for (
size_t i = 0; i < len; ++i)
7026 result.
push_back(from_msgpack_internal(v, idx));
7034 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7036 for (
size_t i = 0; i < len; ++i)
7038 std::string key = from_msgpack_internal(v, idx);
7039 result[key] = from_msgpack_internal(v, idx);
7047 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7049 for (
size_t i = 0; i < len; ++i)
7051 std::string key = from_msgpack_internal(v, idx);
7052 result[key] = from_msgpack_internal(v, idx);
7059 throw std::invalid_argument(
"error parsing a msgpack @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx])));
7079 static basic_json from_cbor_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7082 const size_t current_idx = idx++;
7084 switch (v[current_idx])
7112 return v[current_idx];
7118 return get_from_vector<uint8_t>(v, current_idx);
7124 return get_from_vector<uint16_t>(v, current_idx);
7130 return get_from_vector<uint32_t>(v, current_idx);
7136 return get_from_vector<uint64_t>(v, current_idx);
7165 return static_cast<int8_t
>(0x20 - 1 - v[current_idx]);
7172 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7178 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7184 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7190 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7219 const auto len =
static_cast<size_t>(v[current_idx] - 0x60);
7220 const size_t offset = current_idx + 1;
7222 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7227 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7228 const size_t offset = current_idx + 2;
7230 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7235 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7236 const size_t offset = current_idx + 3;
7238 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7243 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7244 const size_t offset = current_idx + 5;
7246 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7251 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7252 const size_t offset = current_idx + 9;
7254 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7260 while (v[idx] != 0xff)
7262 string_t s = from_cbor_internal(v, idx);
7297 const auto len =
static_cast<size_t>(v[current_idx] - 0x80);
7298 for (
size_t i = 0; i < len; ++i)
7300 result.
push_back(from_cbor_internal(v, idx));
7308 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7310 for (
size_t i = 0; i < len; ++i)
7312 result.
push_back(from_cbor_internal(v, idx));
7320 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7322 for (
size_t i = 0; i < len; ++i)
7324 result.
push_back(from_cbor_internal(v, idx));
7332 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7334 for (
size_t i = 0; i < len; ++i)
7336 result.
push_back(from_cbor_internal(v, idx));
7344 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7346 for (
size_t i = 0; i < len; ++i)
7348 result.
push_back(from_cbor_internal(v, idx));
7356 while (v[idx] != 0xff)
7358 result.
push_back(from_cbor_internal(v, idx));
7392 const auto len =
static_cast<size_t>(v[current_idx] - 0xa0);
7393 for (
size_t i = 0; i < len; ++i)
7395 std::string key = from_cbor_internal(v, idx);
7396 result[key] = from_cbor_internal(v, idx);
7404 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7406 for (
size_t i = 0; i < len; ++i)
7408 std::string key = from_cbor_internal(v, idx);
7409 result[key] = from_cbor_internal(v, idx);
7417 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7419 for (
size_t i = 0; i < len; ++i)
7421 std::string key = from_cbor_internal(v, idx);
7422 result[key] = from_cbor_internal(v, idx);
7430 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7432 for (
size_t i = 0; i < len; ++i)
7434 std::string key = from_cbor_internal(v, idx);
7435 result[key] = from_cbor_internal(v, idx);
7443 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7445 for (
size_t i = 0; i < len; ++i)
7447 std::string key = from_cbor_internal(v, idx);
7448 result[key] = from_cbor_internal(v, idx);
7456 while (v[idx] != 0xff)
7458 std::string key = from_cbor_internal(v, idx);
7459 result[key] = from_cbor_internal(v, idx);
7478 return value_t::null;
7492 const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
7493 const int exp = (half >> 10) & 0x1f;
7494 const int mant = half & 0x3ff;
7498 val = std::ldexp(mant, -24);
7502 val = std::ldexp(mant + 1024, exp - 25);
7506 val = mant == 0 ? INFINITY : NAN;
7508 return half & 0x8000 ? -val : val;
7515 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7517 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v[current_idx + 1 + byte];
7519 idx +=
sizeof(float);
7527 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7529 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v[current_idx + 1 + byte];
7531 idx +=
sizeof(double);
7537 throw std::invalid_argument(
"error parsing a CBOR @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx])));
7565 std::vector<uint8_t> result;
7566 to_msgpack_internal(j, result);
7595 return from_msgpack_internal(v, i);
7621 std::vector<uint8_t> result;
7622 to_cbor_internal(j, result);
7652 return from_cbor_internal(v, i);
7674 std::string type_name()
const 7680 case value_t::object:
7682 case value_t::array:
7684 case value_t::string:
7686 case value_t::boolean:
7688 case value_t::discarded:
7703 static std::size_t extra_space(
const string_t& s) noexcept
7705 return std::accumulate(s.begin(), s.end(),
size_t{},
7706 [](
size_t res,
typename string_t::value_type c)
7724 if (c >= 0x00 and c <= 0x1f)
7753 const auto space = extra_space(s);
7760 string_t result(s.size() + space,
'\\');
7761 std::size_t pos = 0;
7763 for (
const auto& c : s)
7770 result[pos + 1] =
'"';
7786 result[pos + 1] =
'b';
7794 result[pos + 1] =
'f';
7802 result[pos + 1] =
'n';
7810 result[pos + 1] =
'r';
7818 result[pos + 1] =
't';
7825 if (c >= 0x00 and c <= 0x1f)
7829 static const char hexify[16] =
7831 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
7832 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 7837 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
7875 void dump(std::ostream& o,
7876 const bool pretty_print,
7877 const unsigned int indent_step,
7878 const unsigned int current_indent = 0)
const 7881 unsigned int new_indent = current_indent;
7885 case value_t::object:
7887 if (m_value.object->empty())
7898 new_indent += indent_step;
7902 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
7904 if (i != m_value.object->cbegin())
7906 o << (pretty_print ?
",\n" :
",");
7908 o <<
string_t(new_indent,
' ') <<
"\"" 7909 << escape_string(i->first) <<
"\":" 7910 << (pretty_print ?
" " :
"");
7911 i->second.dump(o, pretty_print, indent_step, new_indent);
7917 new_indent -= indent_step;
7921 o <<
string_t(new_indent,
' ') +
"}";
7925 case value_t::array:
7927 if (m_value.array->empty())
7938 new_indent += indent_step;
7942 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
7944 if (i != m_value.array->cbegin())
7946 o << (pretty_print ?
",\n" :
",");
7949 i->dump(o, pretty_print, indent_step, new_indent);
7955 new_indent -= indent_step;
7959 o <<
string_t(new_indent,
' ') <<
"]";
7963 case value_t::string:
7965 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
7969 case value_t::boolean:
7971 o << (m_value.boolean ?
"true" :
"false");
7975 case value_t::number_integer:
7977 o << m_value.number_integer;
7981 case value_t::number_unsigned:
7983 o << m_value.number_unsigned;
7987 case value_t::number_float:
7989 if (m_value.number_float == 0)
7992 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
7996 o << m_value.number_float;
8001 case value_t::discarded:
8021 value_t m_type = value_t::null;
8024 json_value m_value = {};
8041 class primitive_iterator_t
8045 void set_begin() noexcept
8051 void set_end() noexcept
8057 constexpr
bool is_begin()
const noexcept
8059 return (m_it == begin_value);
8063 constexpr
bool is_end()
const noexcept
8065 return (m_it == end_value);
8085 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8095 struct internal_iterator
8098 typename object_t::iterator object_iterator;
8100 typename array_t::iterator array_iterator;
8102 primitive_iterator_t primitive_iterator;
8105 internal_iterator() noexcept
8106 : object_iterator(), array_iterator(), primitive_iterator()
8111 template<
typename IteratorType>
8112 class iteration_proxy
8116 class iteration_proxy_internal
8120 IteratorType anchor;
8122 size_t array_index = 0;
8125 explicit iteration_proxy_internal(IteratorType it) noexcept
8130 iteration_proxy_internal& operator*()
8136 iteration_proxy_internal& operator++()
8145 bool operator!= (
const iteration_proxy_internal& o)
const 8147 return anchor != o.anchor;
8153 assert(anchor.m_object !=
nullptr);
8155 switch (anchor.m_object->type())
8158 case value_t::array:
8160 return std::to_string(array_index);
8164 case value_t::object:
8166 return anchor.key();
8178 typename IteratorType::reference value()
const 8180 return anchor.value();
8185 typename IteratorType::reference container;
8189 explicit iteration_proxy(
typename IteratorType::reference cont)
8194 iteration_proxy_internal begin() noexcept
8196 return iteration_proxy_internal(container.begin());
8200 iteration_proxy_internal end() noexcept
8202 return iteration_proxy_internal(container.end());
8226 template<
typename U>
8227 class iter_impl :
public std::iterator<std::random_access_iterator_tag, U>
8233 static_assert(std::is_same<U, basic_json>::value
8234 or std::is_same<U, const basic_json>::value,
8235 "iter_impl only accepts (const) basic_json");
8243 using pointer =
typename std::conditional<std::is_const<U>::value,
8247 using reference =
typename std::conditional<std::is_const<U>::value,
8265 assert(m_object !=
nullptr);
8267 switch (m_object->m_type)
8271 m_it.object_iterator =
typename object_t::iterator();
8277 m_it.array_iterator =
typename array_t::iterator();
8283 m_it.primitive_iterator = primitive_iterator_t();
8303 ret.m_object = m_object;
8316 : m_object(other.m_object), m_it(other.m_it)
8325 std::is_nothrow_move_constructible<pointer>::value and
8326 std::is_nothrow_move_assignable<pointer>::value and
8327 std::is_nothrow_move_constructible<internal_iterator>::value and
8328 std::is_nothrow_move_assignable<internal_iterator>::value
8331 std::swap(m_object, other.m_object);
8332 std::swap(m_it, other.m_it);
8341 void set_begin() noexcept
8343 assert(m_object !=
nullptr);
8345 switch (m_object->m_type)
8349 m_it.object_iterator = m_object->m_value.object->begin();
8355 m_it.array_iterator = m_object->m_value.array->begin();
8362 m_it.primitive_iterator.set_end();
8368 m_it.primitive_iterator.set_begin();
8378 void set_end() noexcept
8380 assert(m_object !=
nullptr);
8382 switch (m_object->m_type)
8386 m_it.object_iterator = m_object->m_value.object->end();
8392 m_it.array_iterator = m_object->m_value.array->end();
8398 m_it.primitive_iterator.set_end();
8411 assert(m_object !=
nullptr);
8413 switch (m_object->m_type)
8417 assert(m_it.object_iterator != m_object->m_value.object->end());
8418 return m_it.object_iterator->second;
8423 assert(m_it.array_iterator != m_object->m_value.array->end());
8424 return *m_it.array_iterator;
8429 throw std::out_of_range(
"cannot get value");
8434 if (m_it.primitive_iterator.is_begin())
8440 throw std::out_of_range(
"cannot get value");
8452 assert(m_object !=
nullptr);
8454 switch (m_object->m_type)
8458 assert(m_it.object_iterator != m_object->m_value.object->end());
8459 return &(m_it.object_iterator->second);
8464 assert(m_it.array_iterator != m_object->m_value.array->end());
8465 return &*m_it.array_iterator;
8470 if (m_it.primitive_iterator.is_begin())
8476 throw std::out_of_range(
"cannot get value");
8488 auto result = *
this;
8499 assert(m_object !=
nullptr);
8501 switch (m_object->m_type)
8505 std::advance(m_it.object_iterator, 1);
8511 std::advance(m_it.array_iterator, 1);
8517 ++m_it.primitive_iterator;
8531 auto result = *
this;
8542 assert(m_object !=
nullptr);
8544 switch (m_object->m_type)
8548 std::advance(m_it.object_iterator, -1);
8554 std::advance(m_it.array_iterator, -1);
8560 --m_it.primitive_iterator;
8575 if (m_object != other.m_object)
8577 throw std::domain_error(
"cannot compare iterators of different containers");
8580 assert(m_object !=
nullptr);
8582 switch (m_object->m_type)
8586 return (m_it.object_iterator == other.m_it.object_iterator);
8591 return (m_it.array_iterator == other.m_it.array_iterator);
8596 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
8607 return not operator==(other);
8617 if (m_object != other.m_object)
8619 throw std::domain_error(
"cannot compare iterators of different containers");
8622 assert(m_object !=
nullptr);
8624 switch (m_object->m_type)
8628 throw std::domain_error(
"cannot compare order of object iterators");
8633 return (m_it.array_iterator < other.m_it.array_iterator);
8638 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
8649 return not other.operator < (*this);
8658 return not operator<=(other);
8667 return not operator<(other);
8676 assert(m_object !=
nullptr);
8678 switch (m_object->m_type)
8682 throw std::domain_error(
"cannot use offsets with object iterators");
8687 std::advance(m_it.array_iterator, i);
8693 m_it.primitive_iterator += i;
8707 return operator+=(-i);
8716 auto result = *
this;
8727 auto result = *
this;
8738 assert(m_object !=
nullptr);
8740 switch (m_object->m_type)
8744 throw std::domain_error(
"cannot use offsets with object iterators");
8749 return m_it.array_iterator - other.m_it.array_iterator;
8754 return m_it.primitive_iterator - other.m_it.primitive_iterator;
8765 assert(m_object !=
nullptr);
8767 switch (m_object->m_type)
8771 throw std::domain_error(
"cannot use operator[] for object iterators");
8776 return *std::next(m_it.array_iterator, n);
8781 throw std::out_of_range(
"cannot get value");
8786 if (m_it.primitive_iterator == -n)
8792 throw std::out_of_range(
"cannot get value");
8802 typename object_t::key_type
key()
const 8804 assert(m_object !=
nullptr);
8806 if (m_object->is_object())
8808 return m_it.object_iterator->first;
8812 throw std::domain_error(
"cannot use key() for non-object iterators");
8829 internal_iterator m_it = internal_iterator();
8849 template<
typename Base>
8871 return base_iterator::operator++(1);
8877 base_iterator::operator++();
8884 return base_iterator::operator--(1);
8890 base_iterator::operator--();
8897 base_iterator::operator+=(i);
8904 auto result = *
this;
8912 auto result = *
this;
8920 return this->base() - other.base();
8926 return *(this->operator+(n));
8930 typename object_t::key_type
key()
const 8932 auto it = --this->base();
8939 auto it = --this->base();
8940 return it.operator * ();
8961 enum class token_type
8980 using lexer_char_t =
unsigned char;
8983 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
8986 assert(m_content !=
nullptr);
8987 m_start = m_cursor = m_content;
8988 m_limit = m_content + len;
8992 explicit lexer(std::istream& s)
8993 : m_stream(&s), m_line_buffer()
8998 throw std::invalid_argument(
"stream error: " + std::string(strerror(errno)));
9005 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
9007 m_line_buffer[0] =
' ';
9008 m_line_buffer[1] =
' ';
9009 m_line_buffer[2] =
' ';
9015 lexer(
const lexer&) =
delete;
9016 lexer operator=(
const lexer&) =
delete;
9041 static string_t to_unicode(
const std::size_t codepoint1,
9042 const std::size_t codepoint2 = 0)
9045 std::size_t codepoint = codepoint1;
9048 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9051 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9065 throw std::invalid_argument(
"missing or wrong low surrogate");
9071 if (codepoint < 0x80)
9074 result.append(1, static_cast<typename string_t::value_type>(codepoint));
9076 else if (codepoint <= 0x7ff)
9079 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9080 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9082 else if (codepoint <= 0xffff)
9085 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9086 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9087 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9089 else if (codepoint <= 0x10ffff)
9092 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9093 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9094 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9095 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9099 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
9106 static std::string token_type_name(
const token_type t)
9110 case token_type::uninitialized:
9111 return "<uninitialized>";
9112 case token_type::literal_true:
9113 return "true literal";
9114 case token_type::literal_false:
9115 return "false literal";
9116 case token_type::literal_null:
9117 return "null literal";
9118 case token_type::value_string:
9119 return "string literal";
9120 case token_type::value_number:
9121 return "number literal";
9122 case token_type::begin_array:
9124 case token_type::begin_object:
9126 case token_type::end_array:
9128 case token_type::end_object:
9130 case token_type::name_separator:
9132 case token_type::value_separator:
9134 case token_type::parse_error:
9135 return "<parse error>";
9136 case token_type::end_of_input:
9137 return "end of input";
9141 return "unknown token";
9176 assert(m_start !=
nullptr);
9181 unsigned int yyaccept = 0;
9182 static const unsigned char yybm[] =
9184 0, 0, 0, 0, 0, 0, 0, 0,
9185 0, 32, 32, 0, 0, 32, 0, 0,
9186 0, 0, 0, 0, 0, 0, 0, 0,
9187 0, 0, 0, 0, 0, 0, 0, 0,
9188 160, 128, 0, 128, 128, 128, 128, 128,
9189 128, 128, 128, 128, 128, 128, 128, 128,
9190 192, 192, 192, 192, 192, 192, 192, 192,
9191 192, 192, 128, 128, 128, 128, 128, 128,
9192 128, 128, 128, 128, 128, 128, 128, 128,
9193 128, 128, 128, 128, 128, 128, 128, 128,
9194 128, 128, 128, 128, 128, 128, 128, 128,
9195 128, 128, 128, 128, 0, 128, 128, 128,
9196 128, 128, 128, 128, 128, 128, 128, 128,
9197 128, 128, 128, 128, 128, 128, 128, 128,
9198 128, 128, 128, 128, 128, 128, 128, 128,
9199 128, 128, 128, 128, 128, 128, 128, 128,
9200 0, 0, 0, 0, 0, 0, 0, 0,
9201 0, 0, 0, 0, 0, 0, 0, 0,
9202 0, 0, 0, 0, 0, 0, 0, 0,
9203 0, 0, 0, 0, 0, 0, 0, 0,
9204 0, 0, 0, 0, 0, 0, 0, 0,
9205 0, 0, 0, 0, 0, 0, 0, 0,
9206 0, 0, 0, 0, 0, 0, 0, 0,
9207 0, 0, 0, 0, 0, 0, 0, 0,
9208 0, 0, 0, 0, 0, 0, 0, 0,
9209 0, 0, 0, 0, 0, 0, 0, 0,
9210 0, 0, 0, 0, 0, 0, 0, 0,
9211 0, 0, 0, 0, 0, 0, 0, 0,
9212 0, 0, 0, 0, 0, 0, 0, 0,
9213 0, 0, 0, 0, 0, 0, 0, 0,
9214 0, 0, 0, 0, 0, 0, 0, 0,
9215 0, 0, 0, 0, 0, 0, 0, 0,
9217 if ((m_limit - m_cursor) < 5)
9219 fill_line_buffer(5);
9222 if (yybm[0 + yych] & 32)
9224 goto basic_json_parser_6;
9234 goto basic_json_parser_2;
9238 goto basic_json_parser_4;
9240 goto basic_json_parser_9;
9246 goto basic_json_parser_4;
9250 goto basic_json_parser_10;
9252 goto basic_json_parser_12;
9261 goto basic_json_parser_4;
9265 goto basic_json_parser_13;
9267 goto basic_json_parser_15;
9273 goto basic_json_parser_17;
9277 goto basic_json_parser_4;
9279 goto basic_json_parser_19;
9291 goto basic_json_parser_21;
9293 goto basic_json_parser_4;
9299 goto basic_json_parser_23;
9303 goto basic_json_parser_4;
9305 goto basic_json_parser_24;
9314 goto basic_json_parser_25;
9316 goto basic_json_parser_4;
9322 goto basic_json_parser_26;
9326 goto basic_json_parser_28;
9328 goto basic_json_parser_4;
9332 basic_json_parser_2:
9335 last_token_type = token_type::end_of_input;
9338 basic_json_parser_4:
9340 basic_json_parser_5:
9342 last_token_type = token_type::parse_error;
9345 basic_json_parser_6:
9347 if (m_limit <= m_cursor)
9349 fill_line_buffer(1);
9352 if (yybm[0 + yych] & 32)
9354 goto basic_json_parser_6;
9359 basic_json_parser_9:
9361 yych = *(m_marker = ++m_cursor);
9364 goto basic_json_parser_5;
9368 goto basic_json_parser_31;
9372 goto basic_json_parser_5;
9376 goto basic_json_parser_31;
9378 goto basic_json_parser_5;
9379 basic_json_parser_10:
9382 last_token_type = token_type::value_separator;
9385 basic_json_parser_12:
9389 goto basic_json_parser_5;
9393 goto basic_json_parser_13;
9397 goto basic_json_parser_15;
9399 goto basic_json_parser_5;
9400 basic_json_parser_13:
9402 yych = *(m_marker = ++m_cursor);
9407 goto basic_json_parser_43;
9414 goto basic_json_parser_44;
9418 goto basic_json_parser_44;
9421 basic_json_parser_14:
9423 last_token_type = token_type::value_number;
9426 basic_json_parser_15:
9428 m_marker = ++m_cursor;
9429 if ((m_limit - m_cursor) < 3)
9431 fill_line_buffer(3);
9434 if (yybm[0 + yych] & 64)
9436 goto basic_json_parser_15;
9442 goto basic_json_parser_43;
9444 goto basic_json_parser_14;
9450 goto basic_json_parser_44;
9454 goto basic_json_parser_44;
9456 goto basic_json_parser_14;
9458 basic_json_parser_17:
9461 last_token_type = token_type::name_separator;
9464 basic_json_parser_19:
9467 last_token_type = token_type::begin_array;
9470 basic_json_parser_21:
9473 last_token_type = token_type::end_array;
9476 basic_json_parser_23:
9478 yych = *(m_marker = ++m_cursor);
9481 goto basic_json_parser_45;
9483 goto basic_json_parser_5;
9484 basic_json_parser_24:
9486 yych = *(m_marker = ++m_cursor);
9489 goto basic_json_parser_46;
9491 goto basic_json_parser_5;
9492 basic_json_parser_25:
9494 yych = *(m_marker = ++m_cursor);
9497 goto basic_json_parser_47;
9499 goto basic_json_parser_5;
9500 basic_json_parser_26:
9503 last_token_type = token_type::begin_object;
9506 basic_json_parser_28:
9509 last_token_type = token_type::end_object;
9512 basic_json_parser_30:
9514 if (m_limit <= m_cursor)
9516 fill_line_buffer(1);
9519 basic_json_parser_31:
9520 if (yybm[0 + yych] & 128)
9522 goto basic_json_parser_30;
9530 goto basic_json_parser_32;
9534 goto basic_json_parser_33;
9536 goto basic_json_parser_35;
9542 goto basic_json_parser_32;
9546 goto basic_json_parser_36;
9548 goto basic_json_parser_37;
9557 goto basic_json_parser_39;
9559 goto basic_json_parser_38;
9565 goto basic_json_parser_40;
9569 goto basic_json_parser_41;
9573 goto basic_json_parser_42;
9577 basic_json_parser_32:
9578 m_cursor = m_marker;
9581 goto basic_json_parser_5;
9585 goto basic_json_parser_14;
9587 basic_json_parser_33:
9590 last_token_type = token_type::value_string;
9593 basic_json_parser_35:
9595 if (m_limit <= m_cursor)
9597 fill_line_buffer(1);
9606 goto basic_json_parser_30;
9610 goto basic_json_parser_32;
9612 goto basic_json_parser_30;
9620 goto basic_json_parser_32;
9622 goto basic_json_parser_30;
9628 goto basic_json_parser_30;
9630 goto basic_json_parser_32;
9640 goto basic_json_parser_30;
9644 goto basic_json_parser_30;
9646 goto basic_json_parser_32;
9654 goto basic_json_parser_30;
9656 goto basic_json_parser_32;
9662 goto basic_json_parser_30;
9666 goto basic_json_parser_48;
9668 goto basic_json_parser_32;
9672 basic_json_parser_36:
9674 if (m_limit <= m_cursor)
9676 fill_line_buffer(1);
9681 goto basic_json_parser_32;
9685 goto basic_json_parser_30;
9687 goto basic_json_parser_32;
9688 basic_json_parser_37:
9690 if (m_limit <= m_cursor)
9692 fill_line_buffer(1);
9697 goto basic_json_parser_32;
9701 goto basic_json_parser_36;
9703 goto basic_json_parser_32;
9704 basic_json_parser_38:
9706 if (m_limit <= m_cursor)
9708 fill_line_buffer(1);
9713 goto basic_json_parser_32;
9717 goto basic_json_parser_36;
9719 goto basic_json_parser_32;
9720 basic_json_parser_39:
9722 if (m_limit <= m_cursor)
9724 fill_line_buffer(1);
9729 goto basic_json_parser_32;
9733 goto basic_json_parser_36;
9735 goto basic_json_parser_32;
9736 basic_json_parser_40:
9738 if (m_limit <= m_cursor)
9740 fill_line_buffer(1);
9745 goto basic_json_parser_32;
9749 goto basic_json_parser_38;
9751 goto basic_json_parser_32;
9752 basic_json_parser_41:
9754 if (m_limit <= m_cursor)
9756 fill_line_buffer(1);
9761 goto basic_json_parser_32;
9765 goto basic_json_parser_38;
9767 goto basic_json_parser_32;
9768 basic_json_parser_42:
9770 if (m_limit <= m_cursor)
9772 fill_line_buffer(1);
9777 goto basic_json_parser_32;
9781 goto basic_json_parser_38;
9783 goto basic_json_parser_32;
9784 basic_json_parser_43:
9788 goto basic_json_parser_32;
9792 goto basic_json_parser_49;
9794 goto basic_json_parser_32;
9795 basic_json_parser_44:
9801 goto basic_json_parser_51;
9803 goto basic_json_parser_32;
9809 goto basic_json_parser_51;
9813 goto basic_json_parser_32;
9817 goto basic_json_parser_52;
9819 goto basic_json_parser_32;
9821 basic_json_parser_45:
9825 goto basic_json_parser_54;
9827 goto basic_json_parser_32;
9828 basic_json_parser_46:
9832 goto basic_json_parser_55;
9834 goto basic_json_parser_32;
9835 basic_json_parser_47:
9839 goto basic_json_parser_56;
9841 goto basic_json_parser_32;
9842 basic_json_parser_48:
9844 if (m_limit <= m_cursor)
9846 fill_line_buffer(1);
9853 goto basic_json_parser_32;
9857 goto basic_json_parser_57;
9859 goto basic_json_parser_32;
9865 goto basic_json_parser_57;
9869 goto basic_json_parser_32;
9873 goto basic_json_parser_57;
9875 goto basic_json_parser_32;
9877 basic_json_parser_49:
9879 m_marker = ++m_cursor;
9880 if ((m_limit - m_cursor) < 3)
9882 fill_line_buffer(3);
9889 goto basic_json_parser_14;
9893 goto basic_json_parser_49;
9895 goto basic_json_parser_14;
9901 goto basic_json_parser_44;
9905 goto basic_json_parser_44;
9907 goto basic_json_parser_14;
9909 basic_json_parser_51:
9913 goto basic_json_parser_32;
9917 goto basic_json_parser_32;
9919 basic_json_parser_52:
9921 if (m_limit <= m_cursor)
9923 fill_line_buffer(1);
9928 goto basic_json_parser_14;
9932 goto basic_json_parser_52;
9934 goto basic_json_parser_14;
9935 basic_json_parser_54:
9939 goto basic_json_parser_58;
9941 goto basic_json_parser_32;
9942 basic_json_parser_55:
9946 goto basic_json_parser_59;
9948 goto basic_json_parser_32;
9949 basic_json_parser_56:
9953 goto basic_json_parser_61;
9955 goto basic_json_parser_32;
9956 basic_json_parser_57:
9958 if (m_limit <= m_cursor)
9960 fill_line_buffer(1);
9967 goto basic_json_parser_32;
9971 goto basic_json_parser_63;
9973 goto basic_json_parser_32;
9979 goto basic_json_parser_63;
9983 goto basic_json_parser_32;
9987 goto basic_json_parser_63;
9989 goto basic_json_parser_32;
9991 basic_json_parser_58:
9995 goto basic_json_parser_64;
9997 goto basic_json_parser_32;
9998 basic_json_parser_59:
10001 last_token_type = token_type::literal_null;
10004 basic_json_parser_61:
10007 last_token_type = token_type::literal_true;
10010 basic_json_parser_63:
10012 if (m_limit <= m_cursor)
10014 fill_line_buffer(1);
10021 goto basic_json_parser_32;
10025 goto basic_json_parser_66;
10027 goto basic_json_parser_32;
10033 goto basic_json_parser_66;
10037 goto basic_json_parser_32;
10041 goto basic_json_parser_66;
10043 goto basic_json_parser_32;
10045 basic_json_parser_64:
10048 last_token_type = token_type::literal_false;
10051 basic_json_parser_66:
10053 if (m_limit <= m_cursor)
10055 fill_line_buffer(1);
10062 goto basic_json_parser_32;
10066 goto basic_json_parser_30;
10068 goto basic_json_parser_32;
10074 goto basic_json_parser_30;
10078 goto basic_json_parser_32;
10082 goto basic_json_parser_30;
10084 goto basic_json_parser_32;
10090 return last_token_type;
10121 void fill_line_buffer(
size_t n = 0)
10124 assert(m_line_buffer.empty()
10125 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
10128 assert(m_line_buffer.empty()
10129 or m_limit == m_content + m_line_buffer.size());
10132 assert(m_content <= m_start);
10133 assert(m_start <= m_cursor);
10134 assert(m_cursor <= m_limit);
10135 assert(m_marker ==
nullptr or m_marker <= m_limit);
10138 const size_t num_processed_chars =
static_cast<size_t>(m_start - m_content);
10140 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
10142 const auto offset_cursor = m_cursor - m_start;
10145 if (m_stream ==
nullptr or m_stream->eof())
10150 m_line_buffer.assign(m_start, m_limit);
10154 m_line_buffer.append(1,
'\x00');
10157 m_line_buffer.append(n - 1,
'\x01');
10163 m_line_buffer.erase(0, num_processed_chars);
10165 m_line_buffer_tmp.clear();
10166 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
10169 m_line_buffer += m_line_buffer_tmp;
10170 m_line_buffer.push_back(
'\n');
10174 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
10175 assert(m_content !=
nullptr);
10176 m_start = m_content;
10177 m_marker = m_start + offset_marker;
10178 m_cursor = m_start + offset_cursor;
10179 m_limit = m_start + m_line_buffer.size();
10185 assert(m_start !=
nullptr);
10186 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10187 static_cast<size_t>(m_cursor - m_start));
10249 assert(m_cursor - m_start >= 2);
10252 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10255 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10258 auto e = std::find(i, m_cursor - 1,
'\\');
10262 for (
auto k = i; k < e; k++)
10264 result.push_back(static_cast<typename string_t::value_type>(*k));
10322 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10323 4).c_str(),
nullptr, 16);
10326 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10329 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
10331 throw std::invalid_argument(
"missing low surrogate");
10335 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10336 (i + 7), 4).c_str(),
nullptr, 16);
10337 result += to_unicode(codepoint, codepoint2);
10341 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10344 throw std::invalid_argument(
"missing high surrogate");
10349 result += to_unicode(codepoint);
10375 long double str_to_float_t(
long double* ,
char** endptr)
const 10377 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10393 double str_to_float_t(
double* ,
char** endptr)
const 10395 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10411 float str_to_float_t(
float* ,
char** endptr)
const 10413 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10439 assert(m_start !=
nullptr);
10441 const lexer::lexer_char_t* curptr = m_start;
10453 if (*curptr ==
'-')
10455 type = value_t::number_integer;
10456 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
10461 type = value_t::number_unsigned;
10462 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
10466 for (; curptr < m_cursor; curptr++)
10469 if (*curptr < '0' || *curptr >
'9')
10471 if (*curptr ==
'.')
10474 type = value_t::number_float;
10479 type = value_t::number_float;
10484 if (type != value_t::number_float)
10490 if (value > (max - digit) / 10)
10493 type = value_t::number_float;
10498 value = value * 10 + digit;
10504 if (type == value_t::number_unsigned)
10506 result.m_value.number_unsigned = value;
10508 else if (type == value_t::number_integer)
10512 assert(value >= 0);
10513 assert(value <= max);
10530 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
10533 if (not std::isfinite(result.m_value.number_float))
10535 type = value_t::null;
10536 result.m_value = basic_json::json_value();
10541 result.m_type = type;
10546 std::istream* m_stream =
nullptr;
10552 const lexer_char_t* m_content =
nullptr;
10554 const lexer_char_t* m_start =
nullptr;
10556 const lexer_char_t* m_marker =
nullptr;
10558 const lexer_char_t* m_cursor =
nullptr;
10560 const lexer_char_t* m_limit =
nullptr;
10562 token_type last_token_type = token_type::end_of_input;
10576 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10581 : callback(cb), m_lexer(is)
10585 template<
class IteratorType,
typename std::enable_if<
10586 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10589 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
10591 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10592 static_cast<size_t>(std::distance(first, last)))
10602 result.assert_invariant();
10604 expect(lexer::token_type::end_of_input);
10615 auto result =
basic_json(value_t::discarded);
10617 switch (last_token)
10619 case lexer::token_type::begin_object:
10621 if (keep and (not callback
10622 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10625 result.m_type = value_t::object;
10626 result.m_value = value_t::object;
10633 if (last_token == lexer::token_type::end_object)
10636 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10644 unexpect(lexer::token_type::value_separator);
10650 if (last_token == lexer::token_type::value_separator)
10656 expect(lexer::token_type::value_string);
10657 const auto key = m_lexer.get_string();
10659 bool keep_tag =
false;
10665 keep_tag = callback(depth, parse_event_t::key, k);
10675 expect(lexer::token_type::name_separator);
10679 auto value = parse_internal(keep);
10680 if (keep and keep_tag and not value.is_discarded())
10682 result[key] = std::move(value);
10685 while (last_token == lexer::token_type::value_separator);
10688 expect(lexer::token_type::end_object);
10690 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10698 case lexer::token_type::begin_array:
10700 if (keep and (not callback
10701 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10704 result.m_type = value_t::array;
10705 result.m_value = value_t::array;
10712 if (last_token == lexer::token_type::end_array)
10715 if (callback and not callback(--depth, parse_event_t::array_end, result))
10723 unexpect(lexer::token_type::value_separator);
10729 if (last_token == lexer::token_type::value_separator)
10735 auto value = parse_internal(keep);
10736 if (keep and not value.is_discarded())
10738 result.push_back(std::move(value));
10741 while (last_token == lexer::token_type::value_separator);
10744 expect(lexer::token_type::end_array);
10746 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10754 case lexer::token_type::literal_null:
10757 result.m_type = value_t::null;
10761 case lexer::token_type::value_string:
10763 const auto s = m_lexer.get_string();
10769 case lexer::token_type::literal_true:
10772 result.m_type = value_t::boolean;
10773 result.m_value =
true;
10777 case lexer::token_type::literal_false:
10780 result.m_type = value_t::boolean;
10781 result.m_value =
false;
10785 case lexer::token_type::value_number:
10787 m_lexer.get_number(result);
10795 unexpect(last_token);
10799 if (keep and callback and not callback(depth, parse_event_t::value, result))
10807 typename lexer::token_type get_token()
10809 last_token = m_lexer.scan();
10813 void expect(
typename lexer::token_type t)
const 10815 if (t != last_token)
10817 std::string error_msg =
"parse error - unexpected ";
10818 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
10820 lexer::token_type_name(last_token));
10821 error_msg +=
"; expected " + lexer::token_type_name(t);
10822 throw std::invalid_argument(error_msg);
10826 void unexpect(
typename lexer::token_type t)
const 10828 if (t == last_token)
10830 std::string error_msg =
"parse error - unexpected ";
10831 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
10833 lexer::token_type_name(last_token));
10834 throw std::invalid_argument(error_msg);
10844 typename lexer::token_type last_token = lexer::token_type::uninitialized;
10890 : reference_tokens(split(s))
10908 std::string to_string()
const noexcept
10910 return std::accumulate(reference_tokens.begin(),
10911 reference_tokens.end(), std::string{},
10912 [](
const std::string & a,
const std::string & b)
10914 return a +
"/" + escape(b);
10919 operator std::string()
const 10921 return to_string();
10926 std::string pop_back()
10930 throw std::domain_error(
"JSON pointer has no parent");
10933 auto last = reference_tokens.back();
10934 reference_tokens.pop_back();
10939 bool is_root()
const 10941 return reference_tokens.empty();
10948 throw std::domain_error(
"JSON pointer has no parent");
10952 result.reference_tokens = {reference_tokens[0]};
10967 for (
const auto& reference_token : reference_tokens)
10969 switch (result->m_type)
10971 case value_t::null:
10973 if (reference_token ==
"0")
10976 result = &result->operator[](0);
10981 result = &result->operator[](reference_token);
10986 case value_t::object:
10989 result = &result->operator[](reference_token);
10993 case value_t::array:
10996 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11009 throw std::domain_error(
"invalid value to unflatten");
11038 for (
const auto& reference_token : reference_tokens)
11041 if (ptr->m_type == value_t::null)
11044 const bool nums = std::all_of(reference_token.begin(),
11045 reference_token.end(),
11048 return std::isdigit(x);
11053 if (nums or reference_token ==
"-")
11055 *ptr = value_t::array;
11059 *ptr = value_t::object;
11063 switch (ptr->m_type)
11065 case value_t::object:
11068 ptr = &ptr->operator[](reference_token);
11072 case value_t::array:
11075 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11077 throw std::domain_error(
"array index must not begin with '0'");
11080 if (reference_token ==
"-")
11083 ptr = &ptr->operator[](ptr->m_value.array->size());
11088 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11095 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11105 for (
const auto& reference_token : reference_tokens)
11107 switch (ptr->m_type)
11109 case value_t::object:
11112 ptr = &ptr->
at(reference_token);
11116 case value_t::array:
11118 if (reference_token ==
"-")
11121 throw std::out_of_range(
"array index '-' (" +
11122 std::to_string(ptr->m_value.array->size()) +
11123 ") is out of range");
11127 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11129 throw std::domain_error(
"array index must not begin with '0'");
11133 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11139 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11157 for (
const auto& reference_token : reference_tokens)
11159 switch (ptr->m_type)
11161 case value_t::object:
11164 ptr = &ptr->operator[](reference_token);
11168 case value_t::array:
11170 if (reference_token ==
"-")
11173 throw std::out_of_range(
"array index '-' (" +
11174 std::to_string(ptr->m_value.array->size()) +
11175 ") is out of range");
11179 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11181 throw std::domain_error(
"array index must not begin with '0'");
11185 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11191 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11201 for (
const auto& reference_token : reference_tokens)
11203 switch (ptr->m_type)
11205 case value_t::object:
11208 ptr = &ptr->
at(reference_token);
11212 case value_t::array:
11214 if (reference_token ==
"-")
11217 throw std::out_of_range(
"array index '-' (" +
11218 std::to_string(ptr->m_value.array->size()) +
11219 ") is out of range");
11223 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11225 throw std::domain_error(
"array index must not begin with '0'");
11229 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11235 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11244 static std::vector<std::string> split(
const std::string& reference_string)
11246 std::vector<std::string> result;
11249 if (reference_string.empty())
11255 if (reference_string[0] !=
'/')
11257 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
11265 size_t slash = reference_string.find_first_of(
"/", 1),
11274 slash = reference_string.find_first_of(
"/", start))
11278 auto reference_token = reference_string.substr(start, slash - start);
11281 for (
size_t pos = reference_token.find_first_of(
"~");
11282 pos != std::string::npos;
11283 pos = reference_token.find_first_of(
"~", pos + 1))
11285 assert(reference_token[pos] ==
'~');
11288 if (pos == reference_token.size() - 1 or
11289 (reference_token[pos + 1] !=
'0' and
11290 reference_token[pos + 1] !=
'1'))
11292 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
11297 unescape(reference_token);
11298 result.push_back(reference_token);
11317 static void replace_substring(std::string& s,
11318 const std::string& f,
11319 const std::string& t)
11321 assert(not f.empty());
11324 size_t pos = s.find(f);
11325 pos != std::string::npos;
11326 s.replace(pos, f.size(), t),
11327 pos = s.find(f, pos + t.size())
11332 static std::string escape(std::string s)
11335 replace_substring(s,
"~",
"~0");
11336 replace_substring(s,
"/",
"~1");
11341 static void unescape(std::string& s)
11344 replace_substring(s,
"~1",
"/");
11346 replace_substring(s,
"~0",
"~");
11356 static void flatten(
const std::string& reference_string,
11360 switch (value.m_type)
11362 case value_t::array:
11364 if (value.m_value.array->empty())
11367 result[reference_string] =
nullptr;
11372 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
11374 flatten(reference_string +
"/" + std::to_string(i),
11375 value.m_value.array->operator[](i), result);
11381 case value_t::object:
11383 if (value.m_value.object->empty())
11386 result[reference_string] =
nullptr;
11391 for (
const auto& element : *value.m_value.object)
11393 flatten(reference_string +
"/" + escape(element.first),
11394 element.second, result);
11403 result[reference_string] = value;
11418 throw std::domain_error(
"only objects can be unflattened");
11424 for (
const auto& element : *value.m_value.object)
11426 if (not element.second.is_primitive())
11428 throw std::domain_error(
"values in object must be primitive");
11436 json_pointer(element.first).get_and_create(result) = element.second;
11444 std::vector<std::string> reference_tokens {};
11489 return ptr.get_unchecked(
this);
11516 return ptr.get_unchecked(
this);
11541 return ptr.get_checked(
this);
11566 return ptr.get_checked(
this);
11594 json_pointer::flatten(
"", *
this, result);
11627 return json_pointer::unflatten(*
this);
11681 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
11683 const auto get_op = [](
const std::string op)
11687 return patch_operations::add;
11689 if (op ==
"remove")
11691 return patch_operations::remove;
11693 if (op ==
"replace")
11695 return patch_operations::replace;
11699 return patch_operations::move;
11703 return patch_operations::copy;
11707 return patch_operations::test;
11710 return patch_operations::invalid;
11725 if (top_pointer != ptr)
11727 result.
at(top_pointer);
11731 const auto last_path = ptr.pop_back();
11734 switch (parent.m_type)
11736 case value_t::null:
11737 case value_t::object:
11740 parent[last_path] = val;
11744 case value_t::array:
11746 if (last_path ==
"-")
11753 const auto idx = std::stoi(last_path);
11754 if (static_cast<size_type>(idx) > parent.
size())
11757 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
11778 const auto operation_remove = [&result](
json_pointer & ptr)
11781 const auto last_path = ptr.pop_back();
11788 auto it = parent.
find(last_path);
11789 if (it != parent.
end())
11795 throw std::out_of_range(
"key '" + last_path +
"' not found");
11801 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
11809 throw std::invalid_argument(
"JSON patch must be an array of objects");
11813 for (
const auto& val : json_patch)
11816 const auto get_value = [&val](
const std::string & op,
11817 const std::string & member,
11821 auto it = val.m_value.object->find(member);
11824 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
11827 if (it == val.m_value.object->end())
11829 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
11833 if (string_type and not it->second.is_string())
11835 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
11843 if (not val.is_object())
11845 throw std::invalid_argument(
"JSON patch must be an array of objects");
11849 const std::string op = get_value(
"op",
"op",
true);
11850 const std::string path = get_value(op,
"path",
true);
11853 switch (get_op(op))
11855 case patch_operations::add:
11857 operation_add(ptr, get_value(
"add",
"value",
false));
11861 case patch_operations::remove:
11863 operation_remove(ptr);
11867 case patch_operations::replace:
11870 result.
at(ptr) = get_value(
"replace",
"value",
false);
11874 case patch_operations::move:
11876 const std::string from_path = get_value(
"move",
"from",
true);
11886 operation_remove(from_ptr);
11887 operation_add(ptr, v);
11891 case patch_operations::copy:
11893 const std::string from_path = get_value(
"copy",
"from",
true);;
11897 result[ptr] = result.
at(from_ptr);
11901 case patch_operations::test:
11903 bool success =
false;
11908 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
11910 catch (std::out_of_range&)
11918 throw std::domain_error(
"unsuccessful: " + val.dump());
11924 case patch_operations::invalid:
11928 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
11970 const std::string& path =
"")
11976 if (source == target)
11981 if (source.
type() != target.
type())
11993 switch (source.
type())
11995 case value_t::array:
11999 while (i < source.
size() and i < target.
size())
12002 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
12003 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12012 while (i < source.
size())
12016 result.insert(result.begin() + end_index, object(
12019 {
"path", path +
"/" + std::to_string(i)}
12025 while (i < target.
size())
12030 {
"path", path +
"/" + std::to_string(i)},
12031 {
"value", target[i]}
12039 case value_t::object:
12042 for (
auto it = source.
begin(); it != source.
end(); ++it)
12045 const auto key = json_pointer::escape(it.key());
12047 if (target.
find(it.key()) != target.
end())
12050 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
12051 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12056 result.push_back(
object(
12059 {
"path", path +
"/" + key}
12065 for (
auto it = target.
begin(); it != target.
end(); ++it)
12067 if (source.
find(it.key()) == source.
end())
12070 const auto key = json_pointer::escape(it.key());
12074 {
"path", path +
"/" + key},
12075 {
"value", it.value()}
12135 is_nothrow_move_constructible<nlohmann::json>::value and
12136 is_nothrow_move_assignable<nlohmann::json>::value
12154 const auto& h = hash<nlohmann::json::string_t>();
12173 inline nlohmann::json operator "" _json(
const char* s, std::size_t n)
12197 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 12198 #pragma GCC diagnostic pop 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
bool operator>(const iter_impl &other) const
comparison: greater than
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
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
bool operator!=(const iter_impl &other) const
comparison: not equal
iter_impl operator++(int)
post-increment (it++)
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
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)
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
bool operator<=(const iter_impl &other) const
comparison: less than or equal
basic_json(const string_t &val)
create a string (explicit)
void push_back(const basic_json &val)
add an object to an array
void erase(const size_type idx)
remove element from a JSON array given an index
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
bool operator==(const iter_impl &other) const
comparison: equal
reference front()
access the first element
void swap(object_t &other)
exchanges the values
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
static basic_json from_cbor(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in CBOR format
iter_impl(pointer object) noexcept
constructor for a given JSON instance
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
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
iter_impl(const iter_impl &other) noexcept
copy constructor
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
reference operator[](difference_type n) const
access to successor
void emplace_back(Args &&... args)
add an object to an array
friend class basic_json
allow basic_json to access private members
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
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
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
iter_impl operator-(difference_type i)
subtract from 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
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
basic_json(basic_json &&other) noexcept
move constructor
iter_impl & operator-=(difference_type i)
subtract from iterator
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
object (unordered set of name/value pairs)
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
iter_impl & operator=(iter_impl 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
typename basic_json::difference_type difference_type
a type to represent differences between iterators
reference operator+=(const basic_json &val)
add an object to an array
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
ReferenceType get_ref() const
get a reference value (implicit)
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
size_type size() const noexcept
returns the number of elements
namespace for Niels Lohmann
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
iter_impl & operator++()
pre-increment (++it)
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)
difference_type operator-(const iter_impl &other) const
return difference
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
void swap(array_t &other)
exchanges the values
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
iter_impl & operator--()
pre-decrement (–it)
typename Base::reference reference
the reference type for the pointed-to element
void push_back(basic_json &&val)
add an object to an array
static basic_json from_msgpack(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in MessagePack format
array (ordered collection of values)
json_reverse_iterator & operator++()
pre-increment (++it)
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
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
reference value() const
return the value of an iterator
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
bool operator<(const iter_impl &other) const
comparison: smaller
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
pointer operator->() const
dereference the iterator
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
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
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
iter_impl operator--(int)
post-decrement (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
typename std::conditional< std::is_const< U >::value, typename basic_json::const_pointer, typename basic_json::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
const_iterator begin() const noexcept
returns a const iterator to the first element
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
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
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
typename std::conditional< std::is_const< U >::value, typename basic_json::const_reference, typename basic_json::reference >::type reference
defines a reference to the type iterated over (value_type)
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
a template for a reverse iterator class
object_t::key_type key() const
return the key of an object iterator
json_reverse_iterator operator++(int)
post-increment (it++)
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
iter_impl operator+(difference_type i)
add to iterator
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
reference operator*() const
return a reference to the value pointed to by the iterator
iter_impl & operator+=(difference_type i)
add to iterator
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
std::bidirectional_iterator_tag iterator_category
the category of the 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
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
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
a template for a random access iterator for the basic_json class
iterator insert(const_iterator pos, basic_json &&val)
inserts element
ReferenceType get_ref()
get a reference value (implicit)
basic_json(const CompatibleStringType &val)
create a string (implicit)
basic_json(const basic_json &other)
copy constructor
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.