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:
883 if (t == value_t::null)
885 throw std::domain_error(
"961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10");
895 string = create<string_t>(value);
901 object = create<object_t>(value);
905 json_value(
const array_t& value)
907 array = create<array_t>(value);
920 void assert_invariant()
const 922 assert(m_type != value_t::object or m_value.object !=
nullptr);
923 assert(m_type != value_t::array or m_value.array !=
nullptr);
924 assert(m_type != value_t::string or m_value.string !=
nullptr);
1012 basic_json& parsed)>;
1064 : m_type(value_type), m_value(value_type)
1113 : m_type(
value_t::object), m_value(val)
1144 template<
class CompatibleObjectType,
typename std::enable_if<
1145 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1146 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1152 m_value.object = create<object_t>(begin(val), end(val));
1176 : m_type(
value_t::array), m_value(val)
1207 template<
class CompatibleArrayType,
typename std::enable_if<
1208 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1209 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1210 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1211 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1212 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1213 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1214 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1220 m_value.array = create<array_t>(begin(val), end(val));
1246 : m_type(
value_t::string), m_value(val)
1300 template<
class CompatibleStringType,
typename std::enable_if<
1301 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1323 : m_type(value_t::boolean), m_value(val)
1351 template<
typename T,
typename std::enable_if<
1352 not (std::is_same<T, int>::value) and
1353 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1355 : m_type(value_t::number_integer), m_value(val)
1386 : m_type(value_t::number_integer),
1387 m_value(static_cast<number_integer_t>(val))
1417 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1418 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1419 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1420 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1421 CompatibleNumberIntegerType>::type = 0>
1423 : m_type(value_t::number_integer),
1424 m_value(static_cast<number_integer_t>(val))
1446 template<
typename T,
typename std::enable_if<
1447 not (std::is_same<T, int>::value) and
1448 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1450 : m_type(value_t::number_unsigned), m_value(val)
1475 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1476 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1477 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1478 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1479 CompatibleNumberUnsignedType>::type = 0>
1481 : m_type(value_t::number_unsigned),
1482 m_value(static_cast<number_unsigned_t>(val))
1512 : m_type(value_t::number_float), m_value(val)
1515 if (not std::isfinite(val))
1517 m_type = value_t::null;
1518 m_value = json_value();
1555 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1556 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1557 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1634 bool type_deduction =
true,
1635 value_t manual_type = value_t::array)
1639 bool is_an_object = std::all_of(init.begin(), init.end(),
1642 return element.is_array() and element.size() == 2 and element[0].is_string();
1646 if (not type_deduction)
1649 if (manual_type == value_t::array)
1651 is_an_object =
false;
1655 if (manual_type == value_t::object and not is_an_object)
1657 throw std::domain_error(
"cannot create object from initializer list");
1664 m_type = value_t::object;
1665 m_value = value_t::object;
1667 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1669 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1675 m_type = value_t::array;
1676 m_value.array = create<array_t>(init);
1717 std::initializer_list<basic_json>())
1719 return basic_json(init,
false, value_t::array);
1757 std::initializer_list<basic_json>())
1759 return basic_json(init,
false, value_t::object);
1783 m_value.array = create<array_t>(cnt, val);
1824 template<
class InputIT,
typename std::enable_if<
1825 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1826 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1829 assert(first.m_object !=
nullptr);
1830 assert(last.m_object !=
nullptr);
1833 if (first.m_object != last.m_object)
1835 throw std::domain_error(
"iterators are not compatible");
1839 m_type = first.m_object->m_type;
1844 case value_t::boolean:
1845 case value_t::number_float:
1846 case value_t::number_integer:
1847 case value_t::number_unsigned:
1848 case value_t::string:
1850 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1852 throw std::out_of_range(
"iterators out of range");
1865 case value_t::number_integer:
1867 m_value.number_integer = first.m_object->m_value.number_integer;
1871 case value_t::number_unsigned:
1873 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1877 case value_t::number_float:
1879 m_value.number_float = first.m_object->m_value.number_float;
1883 case value_t::boolean:
1885 m_value.boolean = first.m_object->m_value.boolean;
1889 case value_t::string:
1891 m_value = *first.m_object->m_value.string;
1895 case value_t::object:
1897 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1901 case value_t::array:
1903 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1909 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1947 *
this = parser(i, cb).parse();
1978 : m_type(other.m_type)
1981 other.assert_invariant();
1985 case value_t::object:
1987 m_value = *other.m_value.object;
1991 case value_t::array:
1993 m_value = *other.m_value.array;
1997 case value_t::string:
1999 m_value = *other.m_value.string;
2003 case value_t::boolean:
2005 m_value = other.m_value.boolean;
2009 case value_t::number_integer:
2011 m_value = other.m_value.number_integer;
2015 case value_t::number_unsigned:
2017 m_value = other.m_value.number_unsigned;
2021 case value_t::number_float:
2023 m_value = other.m_value.number_float;
2055 : m_type(
std::move(other.m_type)),
2056 m_value(
std::move(other.m_value))
2059 other.assert_invariant();
2062 other.m_type = value_t::null;
2092 std::is_nothrow_move_constructible<value_t>::value and
2093 std::is_nothrow_move_assignable<value_t>::value and
2094 std::is_nothrow_move_constructible<json_value>::value and
2095 std::is_nothrow_move_assignable<json_value>::value
2099 other.assert_invariant();
2102 swap(m_type, other.m_type);
2103 swap(m_value, other.m_value);
2130 case value_t::object:
2132 AllocatorType<object_t> alloc;
2133 alloc.destroy(m_value.object);
2134 alloc.deallocate(m_value.object, 1);
2138 case value_t::array:
2140 AllocatorType<array_t> alloc;
2141 alloc.destroy(m_value.array);
2142 alloc.deallocate(m_value.array, 1);
2146 case value_t::string:
2148 AllocatorType<string_t> alloc;
2149 alloc.destroy(m_value.string);
2150 alloc.deallocate(m_value.string, 1);
2198 std::stringstream ss;
2200 ss.imbue(std::locale::classic());
2206 ss.precision(std::numeric_limits<double>::digits10);
2210 dump(ss,
true, static_cast<unsigned int>(indent));
2270 return is_null() or is_string() or is_boolean() or is_number();
2297 return is_array() or is_object();
2319 return m_type == value_t::null;
2341 return m_type == value_t::boolean;
2371 return is_number_integer() or is_number_float();
2400 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2428 return m_type == value_t::number_unsigned;
2456 return m_type == value_t::number_float;
2478 return m_type == value_t::object;
2500 return m_type == value_t::array;
2522 return m_type == value_t::string;
2549 return m_type == value_t::discarded;
2583 template<
class T,
typename std::enable_if<
2584 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2585 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2586 T get_impl(T*)
const 2590 return T(m_value.object->begin(), m_value.object->end());
2594 throw std::domain_error(
"type must be object, but is " + type_name());
2603 return *(m_value.object);
2607 throw std::domain_error(
"type must be object, but is " + type_name());
2612 template<
class T,
typename std::enable_if<
2613 std::is_convertible<basic_json_t, typename T::value_type>::value and
2614 not std::is_same<basic_json_t, typename T::value_type>::value and
2615 not std::is_arithmetic<T>::value and
2616 not std::is_convertible<std::string, T>::value and
2617 not has_mapped_type<T>::value,
int>::type = 0>
2618 T get_impl(T*)
const 2623 std::transform(m_value.array->begin(), m_value.array->end(),
2624 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2626 return i.
get<
typename T::value_type>();
2632 throw std::domain_error(
"type must be array, but is " + type_name());
2637 template<
class T,
typename std::enable_if<
2638 std::is_convertible<basic_json_t, T>::value and
2639 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2640 std::vector<T> get_impl(std::vector<T>*)
const 2644 std::vector<T> to_vector;
2645 to_vector.reserve(m_value.array->size());
2646 std::transform(m_value.array->begin(), m_value.array->end(),
2647 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2655 throw std::domain_error(
"type must be array, but is " + type_name());
2660 template<
class T,
typename std::enable_if<
2661 std::is_same<basic_json, typename T::value_type>::value and
2662 not has_mapped_type<T>::value,
int>::type = 0>
2663 T get_impl(T*)
const 2667 return T(m_value.array->begin(), m_value.array->end());
2671 throw std::domain_error(
"type must be array, but is " + type_name());
2680 return *(m_value.array);
2684 throw std::domain_error(
"type must be array, but is " + type_name());
2689 template<
typename T,
typename std::enable_if<
2690 std::is_convertible<string_t, T>::value,
int>::type = 0>
2691 T get_impl(T*)
const 2695 return *m_value.string;
2699 throw std::domain_error(
"type must be string, but is " + type_name());
2704 template<
typename T,
typename std::enable_if<
2705 std::is_arithmetic<T>::value,
int>::type = 0>
2706 T get_impl(T*)
const 2710 case value_t::number_integer:
2712 return static_cast<T
>(m_value.number_integer);
2715 case value_t::number_unsigned:
2717 return static_cast<T
>(m_value.number_unsigned);
2720 case value_t::number_float:
2722 return static_cast<T
>(m_value.number_float);
2727 throw std::domain_error(
"type must be number, but is " + type_name());
2737 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2743 return is_object() ? m_value.object :
nullptr;
2749 return is_object() ? m_value.object :
nullptr;
2755 return is_array() ? m_value.array :
nullptr;
2759 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2761 return is_array() ? m_value.array :
nullptr;
2767 return is_string() ? m_value.string :
nullptr;
2773 return is_string() ? m_value.string :
nullptr;
2779 return is_boolean() ? &m_value.boolean :
nullptr;
2785 return is_boolean() ? &m_value.boolean :
nullptr;
2791 return is_number_integer() ? &m_value.number_integer :
nullptr;
2797 return is_number_integer() ? &m_value.number_integer :
nullptr;
2803 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2809 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2815 return is_number_float() ? &m_value.number_float :
nullptr;
2821 return is_number_float() ? &m_value.number_float :
nullptr;
2835 template<
typename ReferenceType,
typename ThisType>
2836 static ReferenceType get_ref_impl(ThisType& obj)
2839 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2842 auto ptr = obj.template get_ptr<PointerType>();
2850 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2894 template<
typename ValueType,
typename std::enable_if<
2895 not std::is_pointer<ValueType>::value,
int>::type = 0>
2896 ValueType
get()
const 2898 return get_impl(static_cast<ValueType*>(
nullptr));
2928 template<
typename PointerType,
typename std::enable_if<
2929 std::is_pointer<PointerType>::value,
int>::type = 0>
2930 PointerType
get() noexcept
2933 return get_ptr<PointerType>();
2940 template<
typename PointerType,
typename std::enable_if<
2941 std::is_pointer<PointerType>::value,
int>::type = 0>
2942 constexpr
const PointerType
get()
const noexcept
2945 return get_ptr<PointerType>();
2974 template<
typename PointerType,
typename std::enable_if<
2975 std::is_pointer<PointerType>::value,
int>::type = 0>
2979 using pointee_t =
typename std::remove_const<
typename 2980 std::remove_pointer<
typename 2981 std::remove_const<PointerType>::type>::type>::type;
2984 std::is_same<object_t, pointee_t>::value
2985 or std::is_same<array_t, pointee_t>::value
2986 or std::is_same<string_t, pointee_t>::value
2987 or std::is_same<boolean_t, pointee_t>::value
2988 or std::is_same<number_integer_t, pointee_t>::value
2989 or std::is_same<number_unsigned_t, pointee_t>::value
2990 or std::is_same<number_float_t, pointee_t>::value
2991 ,
"incompatible pointer type");
2994 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3001 template<
typename PointerType,
typename std::enable_if<
3002 std::is_pointer<PointerType>::value and
3003 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3004 constexpr
const PointerType
get_ptr() const noexcept
3007 using pointee_t =
typename std::remove_const<
typename 3008 std::remove_pointer<
typename 3009 std::remove_const<PointerType>::type>::type>::type;
3012 std::is_same<object_t, pointee_t>::value
3013 or std::is_same<array_t, pointee_t>::value
3014 or std::is_same<string_t, pointee_t>::value
3015 or std::is_same<boolean_t, pointee_t>::value
3016 or std::is_same<number_integer_t, pointee_t>::value
3017 or std::is_same<number_unsigned_t, pointee_t>::value
3018 or std::is_same<number_float_t, pointee_t>::value
3019 ,
"incompatible pointer type");
3022 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3051 template<
typename ReferenceType,
typename std::enable_if<
3052 std::is_reference<ReferenceType>::value,
int>::type = 0>
3056 return get_ref_impl<ReferenceType>(*this);
3063 template<
typename ReferenceType,
typename std::enable_if<
3064 std::is_reference<ReferenceType>::value and
3065 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3069 return get_ref_impl<ReferenceType>(*this);
3100 template <
typename ValueType,
typename std::enable_if <
3101 not std::is_pointer<ValueType>::value and
3102 not std::is_same<ValueType, typename string_t::value_type>::value
3103 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3104 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3107 operator ValueType()
const 3110 return get<ValueType>();
3153 return m_value.
array->
at(idx);
3155 catch (std::out_of_range&)
3158 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3163 throw std::domain_error(
"cannot use at() with " + type_name());
3196 return m_value.
array->
at(idx);
3198 catch (std::out_of_range&)
3201 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3206 throw std::domain_error(
"cannot use at() with " + type_name());
3245 catch (std::out_of_range&)
3248 throw std::out_of_range(
"key '" + key +
"' not found");
3253 throw std::domain_error(
"cannot use at() with " + type_name());
3292 catch (std::out_of_range&)
3295 throw std::out_of_range(
"key '" + key +
"' not found");
3300 throw std::domain_error(
"cannot use at() with " + type_name());
3334 m_type = value_t::array;
3335 m_value.
array = create<array_t>();
3343 if (idx >= m_value.array->size())
3345 m_value.array->insert(m_value.array->end(),
3346 idx - m_value.array->size() + 1,
3350 return m_value.array->operator[](idx);
3354 throw std::domain_error(
"cannot use operator[] with " + type_name());
3382 return m_value.
array->operator[](idx);
3386 throw std::domain_error(
"cannot use operator[] with " + type_name());
3422 m_type = value_t::object;
3423 m_value.
object = create<object_t>();
3430 return m_value.object->operator[](key);
3434 throw std::domain_error(
"cannot use operator[] with " + type_name());
3473 assert(m_value.object->find(key) != m_value.object->end());
3478 throw std::domain_error(
"cannot use operator[] with " + type_name());
3509 template<
typename T, std::
size_t n>
3512 return operator[](static_cast<const T>(key));
3544 template<
typename T, std::
size_t n>
3547 return operator[](static_cast<const T>(key));
3577 template<
typename T>
3583 m_type = value_t::object;
3584 m_value = value_t::object;
3591 return m_value.object->operator[](key);
3595 throw std::domain_error(
"cannot use operator[] with " + type_name());
3629 template<
typename T>
3635 assert(m_value.object->find(key) != m_value.object->end());
3640 throw std::domain_error(
"cannot use operator[] with " + type_name());
3692 template<
class ValueType,
typename std::enable_if<
3693 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3694 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3700 const auto it = find(key);
3707 return default_value;
3712 throw std::domain_error(
"cannot use value() with " + type_name());
3720 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3722 return value(key,
string_t(default_value));
3766 template<
class ValueType,
typename std::enable_if<
3767 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3776 return ptr.get_checked(
this);
3778 catch (std::out_of_range&)
3780 return default_value;
3785 throw std::domain_error(
"cannot use value() with " + type_name());
3795 return value(ptr,
string_t(default_value));
3928 template<
class IteratorType,
typename std::enable_if<
3929 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3930 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3935 if (
this != pos.m_object)
3937 throw std::domain_error(
"iterator does not fit current value");
3940 IteratorType result = end();
3944 case value_t::boolean:
3945 case value_t::number_float:
3946 case value_t::number_integer:
3947 case value_t::number_unsigned:
3948 case value_t::string:
3950 if (not pos.m_it.primitive_iterator.is_begin())
3952 throw std::out_of_range(
"iterator out of range");
3957 AllocatorType<string_t> alloc;
3958 alloc.destroy(m_value.string);
3959 alloc.deallocate(m_value.string, 1);
3960 m_value.string =
nullptr;
3963 m_type = value_t::null;
3968 case value_t::object:
3970 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3974 case value_t::array:
3976 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3982 throw std::domain_error(
"cannot use erase() with " + type_name());
4035 template<
class IteratorType,
typename std::enable_if<
4036 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4037 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4039 IteratorType
erase(IteratorType first, IteratorType last)
4042 if (
this != first.m_object or
this != last.m_object)
4044 throw std::domain_error(
"iterators do not fit current value");
4047 IteratorType result = end();
4051 case value_t::boolean:
4052 case value_t::number_float:
4053 case value_t::number_integer:
4054 case value_t::number_unsigned:
4055 case value_t::string:
4057 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4059 throw std::out_of_range(
"iterators out of range");
4064 AllocatorType<string_t> alloc;
4065 alloc.destroy(m_value.string);
4066 alloc.deallocate(m_value.string, 1);
4067 m_value.string =
nullptr;
4070 m_type = value_t::null;
4075 case value_t::object:
4077 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4078 last.m_it.object_iterator);
4082 case value_t::array:
4084 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4085 last.m_it.array_iterator);
4091 throw std::domain_error(
"cannot use erase() with " + type_name());
4132 return m_value.object->erase(key);
4136 throw std::domain_error(
"cannot use erase() with " + type_name());
4171 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4174 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4178 throw std::domain_error(
"cannot use erase() with " + type_name());
4216 auto result = end();
4220 result.m_it.object_iterator = m_value.object->find(key);
4232 auto result = cend();
4236 result.m_it.object_iterator = m_value.object->find(key);
4266 return is_object() ? m_value.object->count(key) : 0;
4554 template<
typename IteratorType>
class iteration_proxy;
4570 return iteration_proxy<iterator>(cont);
4578 return iteration_proxy<const_iterator>(cont);
4638 case value_t::array:
4641 return m_value.array->empty();
4644 case value_t::object:
4647 return m_value.object->empty();
4706 case value_t::array:
4709 return m_value.array->size();
4712 case value_t::object:
4715 return m_value.object->size();
4766 case value_t::array:
4769 return m_value.array->max_size();
4772 case value_t::object:
4775 return m_value.object->max_size();
4822 case value_t::number_integer:
4824 m_value.number_integer = 0;
4828 case value_t::number_unsigned:
4830 m_value.number_unsigned = 0;
4834 case value_t::number_float:
4836 m_value.number_float = 0.0;
4840 case value_t::boolean:
4842 m_value.boolean =
false;
4846 case value_t::string:
4848 m_value.string->clear();
4852 case value_t::array:
4854 m_value.array->clear();
4858 case value_t::object:
4860 m_value.object->clear();
4894 if (not(is_null() or is_array()))
4896 throw std::domain_error(
"cannot use push_back() with " + type_name());
4902 m_type = value_t::array;
4903 m_value = value_t::array;
4908 m_value.array->push_back(std::move(val));
4910 val.m_type = value_t::null;
4919 push_back(std::move(val));
4930 if (not(is_null() or is_array()))
4932 throw std::domain_error(
"cannot use push_back() with " + type_name());
4938 m_type = value_t::array;
4939 m_value = value_t::array;
4944 m_value.array->push_back(val);
4980 if (not(is_null() or is_object()))
4982 throw std::domain_error(
"cannot use push_back() with " + type_name());
4988 m_type = value_t::object;
4989 m_value = value_t::object;
4994 m_value.object->insert(val);
5034 if (is_object() and init.size() == 2 and init.begin()->is_string())
5036 const string_t key = *init.begin();
5037 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5076 template<
class... Args>
5080 if (not(is_null() or is_array()))
5082 throw std::domain_error(
"cannot use emplace_back() with " + type_name());
5088 m_type = value_t::array;
5089 m_value = value_t::array;
5094 m_value.array->emplace_back(std::forward<Args>(args)...);
5124 template<
class... Args>
5125 std::pair<iterator, bool>
emplace(Args&& ... args)
5128 if (not(is_null() or is_object()))
5130 throw std::domain_error(
"cannot use emplace() with " + type_name());
5136 m_type = value_t::object;
5137 m_value = value_t::object;
5142 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5145 it.m_it.object_iterator = res.first;
5148 return {it, res.second};
5179 if (pos.m_object !=
this)
5181 throw std::domain_error(
"iterator does not fit current value");
5186 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5191 throw std::domain_error(
"cannot use insert() with " + type_name());
5201 return insert(pos, val);
5234 if (pos.m_object !=
this)
5236 throw std::domain_error(
"iterator does not fit current value");
5241 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5246 throw std::domain_error(
"cannot use insert() with " + type_name());
5285 throw std::domain_error(
"cannot use insert() with " + type_name());
5289 if (pos.m_object !=
this)
5291 throw std::domain_error(
"iterator does not fit current value");
5295 if (first.m_object != last.m_object)
5297 throw std::domain_error(
"iterators do not fit");
5300 if (first.m_object ==
this or last.m_object ==
this)
5302 throw std::domain_error(
"passed iterators may not belong to container");
5307 result.m_it.array_iterator = m_value.array->insert(
5308 pos.m_it.array_iterator,
5309 first.m_it.array_iterator,
5310 last.m_it.array_iterator);
5343 throw std::domain_error(
"cannot use insert() with " + type_name());
5347 if (pos.m_object !=
this)
5349 throw std::domain_error(
"iterator does not fit current value");
5354 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5376 std::is_nothrow_move_constructible<value_t>::value and
5377 std::is_nothrow_move_assignable<value_t>::value and
5378 std::is_nothrow_move_constructible<json_value>::value and
5379 std::is_nothrow_move_assignable<json_value>::value
5382 std::swap(m_type, other.m_type);
5383 std::swap(m_value, other.m_value);
5412 std::swap(*(m_value.array), other);
5416 throw std::domain_error(
"cannot use swap() with " + type_name());
5445 std::swap(*(m_value.object), other);
5449 throw std::domain_error(
"cannot use swap() with " + type_name());
5478 std::swap(*(m_value.string), other);
5482 throw std::domain_error(
"cannot use swap() with " + type_name());
5508 static constexpr std::array<uint8_t, 8> order = {{
5521 if (lhs == value_t::discarded or rhs == value_t::discarded)
5526 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5555 const auto lhs_type = lhs.type();
5556 const auto rhs_type = rhs.type();
5558 if (lhs_type == rhs_type)
5562 case value_t::array:
5564 return *lhs.m_value.array == *rhs.m_value.array;
5566 case value_t::object:
5568 return *lhs.m_value.object == *rhs.m_value.object;
5574 case value_t::string:
5576 return *lhs.m_value.string == *rhs.m_value.string;
5578 case value_t::boolean:
5580 return lhs.m_value.boolean == rhs.m_value.boolean;
5582 case value_t::number_integer:
5584 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5586 case value_t::number_unsigned:
5588 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5590 case value_t::number_float:
5592 return lhs.m_value.number_float == rhs.m_value.number_float;
5600 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5602 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5604 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5606 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5608 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5610 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5612 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5614 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5616 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5618 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5620 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5622 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5678 return not (lhs == rhs);
5710 return not v.is_null();
5739 const auto lhs_type = lhs.type();
5740 const auto rhs_type = rhs.type();
5742 if (lhs_type == rhs_type)
5746 case value_t::array:
5748 return *lhs.m_value.array < *rhs.m_value.array;
5750 case value_t::object:
5752 return *lhs.m_value.object < *rhs.m_value.object;
5758 case value_t::string:
5760 return *lhs.m_value.string < *rhs.m_value.string;
5762 case value_t::boolean:
5764 return lhs.m_value.boolean < rhs.m_value.boolean;
5766 case value_t::number_integer:
5768 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5770 case value_t::number_unsigned:
5772 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5774 case value_t::number_float:
5776 return lhs.m_value.number_float < rhs.m_value.number_float;
5784 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5786 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5788 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5790 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5792 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5794 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5796 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5798 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5800 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5802 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5804 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5806 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5812 return operator<(lhs_type, rhs_type);
5834 return not (rhs < lhs);
5856 return not (lhs <= rhs);
5878 return not (lhs < rhs);
5920 const bool pretty_print = (o.width() > 0);
5921 const auto indentation = (pretty_print ? o.width() : 0);
5927 const auto old_locale = o.imbue(std::locale::classic());
5934 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5937 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5940 o.imbue(old_locale);
5941 o.precision(old_precision);
5991 template<
class T, std::
size_t N>
5996 return parse(std::begin(array), std::end(array), cb);
6026 template<
typename CharT,
typename std::enable_if<
6027 std::is_pointer<CharT>::value and
6028 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6029 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
6033 return parser(reinterpret_cast<const char*>(s), cb).
parse();
6063 return parser(i, cb).
parse();
6072 return parser(i, cb).
parse();
6116 template<
class IteratorType,
typename std::enable_if<
6118 std::random_access_iterator_tag,
6119 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6125 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6126 [&first](std::pair<bool, int> res, decltype(*first) val)
6128 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6133 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6134 "each element in the iterator range must have the size of 1 byte");
6138 if (std::distance(first, last) <= 0)
6140 return parser(
"").parse();
6143 return parser(first, last, cb).parse();
6186 template<
class ContiguousContainer,
typename std::enable_if<
6187 not std::is_pointer<ContiguousContainer>::value and
6189 std::random_access_iterator_tag,
6190 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6196 return parse(std::begin(c), std::end(c), cb);
6224 j = parser(i).
parse();
6234 j = parser(i).
parse();
6248 template<
typename T>
6249 static void add_to_vector(std::vector<uint8_t>& vec,
size_t bytes,
const T number)
6251 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6257 vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6258 vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6259 vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6260 vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6266 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6267 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6273 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6279 vec.push_back(static_cast<uint8_t>(number & 0xff));
6321 template<
typename T>
6322 static T get_from_vector(
const std::vector<uint8_t>& vec,
const size_t current_index)
6324 if (current_index +
sizeof(T) + 1 > vec.size())
6326 throw std::out_of_range(
"cannot read " + std::to_string(
sizeof(T)) +
" bytes from vector");
6330 uint8_t* ptr =
reinterpret_cast<uint8_t*
>(&result);
6331 for (
size_t i = 0; i <
sizeof(T); ++i)
6333 *ptr++ = vec[current_index +
sizeof(T) - i];
6348 static void to_msgpack_internal(
const basic_json& j, std::vector<uint8_t>& v)
6359 case value_t::boolean:
6362 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6366 case value_t::number_integer:
6368 if (j.m_value.number_integer >= 0)
6373 if (j.m_value.number_unsigned < 128)
6376 add_to_vector(v, 1, j.m_value.number_unsigned);
6378 else if (j.m_value.number_unsigned <= UINT8_MAX)
6382 add_to_vector(v, 1, j.m_value.number_unsigned);
6384 else if (j.m_value.number_unsigned <= UINT16_MAX)
6388 add_to_vector(v, 2, j.m_value.number_unsigned);
6390 else if (j.m_value.number_unsigned <= UINT32_MAX)
6394 add_to_vector(v, 4, j.m_value.number_unsigned);
6396 else if (j.m_value.number_unsigned <= UINT64_MAX)
6400 add_to_vector(v, 8, j.m_value.number_unsigned);
6405 if (j.m_value.number_integer >= -32)
6408 add_to_vector(v, 1, j.m_value.number_integer);
6410 else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6414 add_to_vector(v, 1, j.m_value.number_integer);
6416 else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6420 add_to_vector(v, 2, j.m_value.number_integer);
6422 else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6426 add_to_vector(v, 4, j.m_value.number_integer);
6428 else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6432 add_to_vector(v, 8, j.m_value.number_integer);
6438 case value_t::number_unsigned:
6440 if (j.m_value.number_unsigned < 128)
6443 add_to_vector(v, 1, j.m_value.number_unsigned);
6445 else if (j.m_value.number_unsigned <= UINT8_MAX)
6449 add_to_vector(v, 1, j.m_value.number_unsigned);
6451 else if (j.m_value.number_unsigned <= UINT16_MAX)
6455 add_to_vector(v, 2, j.m_value.number_unsigned);
6457 else if (j.m_value.number_unsigned <= UINT32_MAX)
6461 add_to_vector(v, 4, j.m_value.number_unsigned);
6463 else if (j.m_value.number_unsigned <= UINT64_MAX)
6467 add_to_vector(v, 8, j.m_value.number_unsigned);
6472 case value_t::number_float:
6476 const uint8_t* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6477 for (
size_t i = 0; i < 8; ++i)
6479 v.push_back(helper[7 - i]);
6484 case value_t::string:
6486 const auto N = j.m_value.string->size();
6490 v.push_back(static_cast<uint8_t>(0xa0 | N));
6496 add_to_vector(v, 1, N);
6498 else if (N <= 65535)
6502 add_to_vector(v, 2, N);
6504 else if (N <= 4294967295)
6508 add_to_vector(v, 4, N);
6512 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6513 std::back_inserter(v));
6517 case value_t::array:
6519 const auto N = j.m_value.array->size();
6523 v.push_back(static_cast<uint8_t>(0x90 | N));
6525 else if (N <= 0xffff)
6529 add_to_vector(v, 2, N);
6531 else if (N <= 0xffffffff)
6535 add_to_vector(v, 4, N);
6539 for (
const auto& el : *j.m_value.array)
6541 to_msgpack_internal(el, v);
6546 case value_t::object:
6548 const auto N = j.m_value.object->size();
6552 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6554 else if (N <= 65535)
6558 add_to_vector(v, 2, N);
6560 else if (N <= 4294967295)
6564 add_to_vector(v, 4, N);
6568 for (
const auto& el : *j.m_value.object)
6570 to_msgpack_internal(el.first, v);
6571 to_msgpack_internal(el.second, v);
6593 static void to_cbor_internal(
const basic_json& j, std::vector<uint8_t>& v)
6603 case value_t::boolean:
6605 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6609 case value_t::number_integer:
6611 if (j.m_value.number_integer >= 0)
6616 if (j.m_value.number_integer <= 0x17)
6618 add_to_vector(v, 1, j.m_value.number_integer);
6620 else if (j.m_value.number_integer <= UINT8_MAX)
6624 add_to_vector(v, 1, j.m_value.number_integer);
6626 else if (j.m_value.number_integer <= UINT16_MAX)
6630 add_to_vector(v, 2, j.m_value.number_integer);
6632 else if (j.m_value.number_integer <= UINT32_MAX)
6636 add_to_vector(v, 4, j.m_value.number_integer);
6642 add_to_vector(v, 8, j.m_value.number_integer);
6649 const auto positive_number = -1 - j.m_value.number_integer;
6650 if (j.m_value.number_integer >= -24)
6652 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6654 else if (positive_number <= UINT8_MAX)
6658 add_to_vector(v, 1, positive_number);
6660 else if (positive_number <= UINT16_MAX)
6664 add_to_vector(v, 2, positive_number);
6666 else if (positive_number <= UINT32_MAX)
6670 add_to_vector(v, 4, positive_number);
6676 add_to_vector(v, 8, positive_number);
6682 case value_t::number_unsigned:
6684 if (j.m_value.number_unsigned <= 0x17)
6686 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6688 else if (j.m_value.number_unsigned <= 0xff)
6692 add_to_vector(v, 1, j.m_value.number_unsigned);
6694 else if (j.m_value.number_unsigned <= 0xffff)
6698 add_to_vector(v, 2, j.m_value.number_unsigned);
6700 else if (j.m_value.number_unsigned <= 0xffffffff)
6704 add_to_vector(v, 4, j.m_value.number_unsigned);
6706 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6710 add_to_vector(v, 8, j.m_value.number_unsigned);
6715 case value_t::number_float:
6719 const uint8_t* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6720 for (
size_t i = 0; i < 8; ++i)
6722 v.push_back(helper[7 - i]);
6727 case value_t::string:
6729 const auto N = j.m_value.string->size();
6732 v.push_back(0x60 + N);
6737 add_to_vector(v, 1, N);
6739 else if (N <= 0xffff)
6742 add_to_vector(v, 2, N);
6744 else if (N <= 0xffffffff)
6747 add_to_vector(v, 4, N);
6750 else if (N <= 0xffffffffffffffff)
6753 add_to_vector(v, 8, N);
6758 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6759 std::back_inserter(v));
6763 case value_t::array:
6765 const auto N = j.m_value.array->size();
6768 v.push_back(0x80 + N);
6773 add_to_vector(v, 1, N);
6775 else if (N <= 0xffff)
6778 add_to_vector(v, 2, N);
6780 else if (N <= 0xffffffff)
6783 add_to_vector(v, 4, N);
6786 else if (N <= 0xffffffffffffffff)
6789 add_to_vector(v, 8, N);
6794 for (
const auto& el : *j.m_value.array)
6796 to_cbor_internal(el, v);
6801 case value_t::object:
6803 const auto N = j.m_value.object->size();
6806 v.push_back(0xa0 + N);
6811 add_to_vector(v, 1, N);
6813 else if (N <= 0xffff)
6816 add_to_vector(v, 2, N);
6818 else if (N <= 0xffffffff)
6821 add_to_vector(v, 4, N);
6824 else if (N <= 0xffffffffffffffff)
6827 add_to_vector(v, 8, N);
6832 for (
const auto& el : *j.m_value.object)
6834 to_cbor_internal(el.first, v);
6835 to_cbor_internal(el.second, v);
6870 static void check_length(
const size_t size,
const size_t len,
const size_t offset)
6873 if (len > size or offset > size)
6875 throw std::out_of_range(
"len out of range");
6879 if ((size > (std::numeric_limits<size_t>::max() - offset)))
6881 throw std::out_of_range(
"len+offset out of range");
6885 if (len + offset > size)
6887 throw std::out_of_range(
"len+offset out of range");
6905 static basic_json from_msgpack_internal(
const std::vector<uint8_t>& v,
size_t& idx)
6908 check_length(v.size(), 1, idx);
6911 const size_t current_idx = idx++;
6913 if (v[current_idx] <= 0xbf)
6915 if (v[current_idx] <= 0x7f)
6917 return v[current_idx];
6919 else if (v[current_idx] <= 0x8f)
6922 const size_t len = v[current_idx] & 0x0f;
6923 for (
size_t i = 0; i < len; ++i)
6925 std::string key = from_msgpack_internal(v, idx);
6926 result[key] = from_msgpack_internal(v, idx);
6930 else if (v[current_idx] <= 0x9f)
6933 const size_t len = v[current_idx] & 0x0f;
6934 for (
size_t i = 0; i < len; ++i)
6936 result.
push_back(from_msgpack_internal(v, idx));
6942 const size_t len = v[current_idx] & 0x1f;
6943 const size_t offset = current_idx + 1;
6945 check_length(v.size(), len, offset);
6946 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6949 else if (v[current_idx] >= 0xe0)
6951 return static_cast<int8_t
>(v[current_idx]);
6955 switch (v[current_idx])
6959 return value_t::null;
6975 check_length(v.size(),
sizeof(float), 1);
6977 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
6979 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v[current_idx + 1 + byte];
6981 idx +=
sizeof(float);
6988 check_length(v.size(),
sizeof(double), 1);
6990 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
6992 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v[current_idx + 1 + byte];
6994 idx +=
sizeof(double);
7001 return get_from_vector<uint8_t>(v, current_idx);
7007 return get_from_vector<uint16_t>(v, current_idx);
7013 return get_from_vector<uint32_t>(v, current_idx);
7019 return get_from_vector<uint64_t>(v, current_idx);
7025 return get_from_vector<int8_t>(v, current_idx);
7031 return get_from_vector<int16_t>(v, current_idx);
7037 return get_from_vector<int32_t>(v, current_idx);
7043 return get_from_vector<int64_t>(v, current_idx);
7048 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7049 const size_t offset = current_idx + 2;
7051 check_length(v.size(), len, offset);
7052 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7057 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7058 const size_t offset = current_idx + 3;
7060 check_length(v.size(), len, offset);
7061 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7066 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7067 const size_t offset = current_idx + 5;
7069 check_length(v.size(), len, offset);
7070 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7076 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7078 for (
size_t i = 0; i < len; ++i)
7080 result.
push_back(from_msgpack_internal(v, idx));
7088 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7090 for (
size_t i = 0; i < len; ++i)
7092 result.
push_back(from_msgpack_internal(v, idx));
7100 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7102 for (
size_t i = 0; i < len; ++i)
7104 std::string key = from_msgpack_internal(v, idx);
7105 result[key] = from_msgpack_internal(v, idx);
7113 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7115 for (
size_t i = 0; i < len; ++i)
7117 std::string key = from_msgpack_internal(v, idx);
7118 result[key] = from_msgpack_internal(v, idx);
7125 throw std::invalid_argument(
"error parsing a msgpack @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx])));
7145 static basic_json from_cbor_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7148 const size_t current_idx = idx++;
7150 switch (v.at(current_idx))
7178 return v[current_idx];
7184 return get_from_vector<uint8_t>(v, current_idx);
7190 return get_from_vector<uint16_t>(v, current_idx);
7196 return get_from_vector<uint32_t>(v, current_idx);
7202 return get_from_vector<uint64_t>(v, current_idx);
7231 return static_cast<int8_t
>(0x20 - 1 - v[current_idx]);
7238 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7244 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7250 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7256 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7285 const auto len =
static_cast<size_t>(v[current_idx] - 0x60);
7286 const size_t offset = current_idx + 1;
7288 check_length(v.size(), len, offset);
7289 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7294 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7295 const size_t offset = current_idx + 2;
7297 check_length(v.size(), len, offset);
7298 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7303 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7304 const size_t offset = current_idx + 3;
7306 check_length(v.size(), len, offset);
7307 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7312 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7313 const size_t offset = current_idx + 5;
7315 check_length(v.size(), len, offset);
7316 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7321 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7322 const size_t offset = current_idx + 9;
7324 check_length(v.size(), len, offset);
7325 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7331 while (v.at(idx) != 0xff)
7333 string_t s = from_cbor_internal(v, idx);
7368 const auto len =
static_cast<size_t>(v[current_idx] - 0x80);
7369 for (
size_t i = 0; i < len; ++i)
7371 result.
push_back(from_cbor_internal(v, idx));
7379 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7381 for (
size_t i = 0; i < len; ++i)
7383 result.
push_back(from_cbor_internal(v, idx));
7391 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7393 for (
size_t i = 0; i < len; ++i)
7395 result.
push_back(from_cbor_internal(v, idx));
7403 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7405 for (
size_t i = 0; i < len; ++i)
7407 result.
push_back(from_cbor_internal(v, idx));
7415 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7417 for (
size_t i = 0; i < len; ++i)
7419 result.
push_back(from_cbor_internal(v, idx));
7427 while (v.at(idx) != 0xff)
7429 result.
push_back(from_cbor_internal(v, idx));
7463 const auto len =
static_cast<size_t>(v[current_idx] - 0xa0);
7464 for (
size_t i = 0; i < len; ++i)
7466 std::string key = from_cbor_internal(v, idx);
7467 result[key] = from_cbor_internal(v, idx);
7475 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7477 for (
size_t i = 0; i < len; ++i)
7479 std::string key = from_cbor_internal(v, idx);
7480 result[key] = from_cbor_internal(v, idx);
7488 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7490 for (
size_t i = 0; i < len; ++i)
7492 std::string key = from_cbor_internal(v, idx);
7493 result[key] = from_cbor_internal(v, idx);
7501 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7503 for (
size_t i = 0; i < len; ++i)
7505 std::string key = from_cbor_internal(v, idx);
7506 result[key] = from_cbor_internal(v, idx);
7514 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7516 for (
size_t i = 0; i < len; ++i)
7518 std::string key = from_cbor_internal(v, idx);
7519 result[key] = from_cbor_internal(v, idx);
7527 while (v.at(idx) != 0xff)
7529 std::string key = from_cbor_internal(v, idx);
7530 result[key] = from_cbor_internal(v, idx);
7549 return value_t::null;
7554 check_length(v.size(), 2, 1);
7564 const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
7565 const int exp = (half >> 10) & 0x1f;
7566 const int mant = half & 0x3ff;
7570 val = std::ldexp(mant, -24);
7574 val = std::ldexp(mant + 1024, exp - 25);
7578 val = mant == 0 ? INFINITY : NAN;
7580 return half & 0x8000 ? -val : val;
7586 check_length(v.size(),
sizeof(float), 1);
7588 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7590 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v[current_idx + 1 + byte];
7592 idx +=
sizeof(float);
7598 check_length(v.size(),
sizeof(double), 1);
7601 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7603 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v[current_idx + 1 + byte];
7605 idx +=
sizeof(double);
7611 throw std::invalid_argument(
"error parsing a CBOR @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx])));
7639 std::vector<uint8_t> result;
7640 to_msgpack_internal(j, result);
7669 return from_msgpack_internal(v, i);
7695 std::vector<uint8_t> result;
7696 to_cbor_internal(j, result);
7726 return from_cbor_internal(v, i);
7748 std::string type_name()
const 7754 case value_t::object:
7756 case value_t::array:
7758 case value_t::string:
7760 case value_t::boolean:
7762 case value_t::discarded:
7777 static std::size_t extra_space(
const string_t& s) noexcept
7779 return std::accumulate(s.begin(), s.end(),
size_t{},
7780 [](
size_t res,
typename string_t::value_type c)
7798 if (c >= 0x00 and c <= 0x1f)
7827 const auto space = extra_space(s);
7834 string_t result(s.size() + space,
'\\');
7835 std::size_t pos = 0;
7837 for (
const auto& c : s)
7844 result[pos + 1] =
'"';
7860 result[pos + 1] =
'b';
7868 result[pos + 1] =
'f';
7876 result[pos + 1] =
'n';
7884 result[pos + 1] =
'r';
7892 result[pos + 1] =
't';
7899 if (c >= 0x00 and c <= 0x1f)
7903 static const char hexify[16] =
7905 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
7906 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 7911 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
7949 void dump(std::ostream& o,
7950 const bool pretty_print,
7951 const unsigned int indent_step,
7952 const unsigned int current_indent = 0)
const 7955 unsigned int new_indent = current_indent;
7959 case value_t::object:
7961 if (m_value.object->empty())
7972 new_indent += indent_step;
7976 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
7978 if (i != m_value.object->cbegin())
7980 o << (pretty_print ?
",\n" :
",");
7982 o <<
string_t(new_indent,
' ') <<
"\"" 7983 << escape_string(i->first) <<
"\":" 7984 << (pretty_print ?
" " :
"");
7985 i->second.dump(o, pretty_print, indent_step, new_indent);
7991 new_indent -= indent_step;
7995 o <<
string_t(new_indent,
' ') +
"}";
7999 case value_t::array:
8001 if (m_value.array->empty())
8012 new_indent += indent_step;
8016 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8018 if (i != m_value.array->cbegin())
8020 o << (pretty_print ?
",\n" :
",");
8023 i->dump(o, pretty_print, indent_step, new_indent);
8029 new_indent -= indent_step;
8033 o <<
string_t(new_indent,
' ') <<
"]";
8037 case value_t::string:
8039 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
8043 case value_t::boolean:
8045 o << (m_value.boolean ?
"true" :
"false");
8049 case value_t::number_integer:
8051 o << m_value.number_integer;
8055 case value_t::number_unsigned:
8057 o << m_value.number_unsigned;
8061 case value_t::number_float:
8063 if (m_value.number_float == 0)
8066 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
8070 o << m_value.number_float;
8075 case value_t::discarded:
8095 value_t m_type = value_t::null;
8098 json_value m_value = {};
8115 class primitive_iterator_t
8119 void set_begin() noexcept
8125 void set_end() noexcept
8131 constexpr
bool is_begin()
const noexcept
8133 return (m_it == begin_value);
8137 constexpr
bool is_end()
const noexcept
8139 return (m_it == end_value);
8159 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8169 struct internal_iterator
8172 typename object_t::iterator object_iterator;
8174 typename array_t::iterator array_iterator;
8176 primitive_iterator_t primitive_iterator;
8179 internal_iterator() noexcept
8180 : object_iterator(), array_iterator(), primitive_iterator()
8185 template<
typename IteratorType>
8186 class iteration_proxy
8190 class iteration_proxy_internal
8194 IteratorType anchor;
8196 size_t array_index = 0;
8199 explicit iteration_proxy_internal(IteratorType it) noexcept
8204 iteration_proxy_internal& operator*()
8210 iteration_proxy_internal& operator++()
8219 bool operator!= (
const iteration_proxy_internal& o)
const 8221 return anchor != o.anchor;
8227 assert(anchor.m_object !=
nullptr);
8229 switch (anchor.m_object->type())
8232 case value_t::array:
8234 return std::to_string(array_index);
8238 case value_t::object:
8240 return anchor.key();
8252 typename IteratorType::reference value()
const 8254 return anchor.value();
8259 typename IteratorType::reference container;
8263 explicit iteration_proxy(
typename IteratorType::reference cont)
8268 iteration_proxy_internal begin() noexcept
8270 return iteration_proxy_internal(container.begin());
8274 iteration_proxy_internal end() noexcept
8276 return iteration_proxy_internal(container.end());
8300 template<
typename U>
8301 class iter_impl :
public std::iterator<std::random_access_iterator_tag, U>
8307 static_assert(std::is_same<U, basic_json>::value
8308 or std::is_same<U, const basic_json>::value,
8309 "iter_impl only accepts (const) basic_json");
8317 using pointer =
typename std::conditional<std::is_const<U>::value,
8321 using reference =
typename std::conditional<std::is_const<U>::value,
8339 assert(m_object !=
nullptr);
8341 switch (m_object->m_type)
8345 m_it.object_iterator =
typename object_t::iterator();
8351 m_it.array_iterator =
typename array_t::iterator();
8357 m_it.primitive_iterator = primitive_iterator_t();
8377 ret.m_object = m_object;
8390 : m_object(other.m_object), m_it(other.m_it)
8399 std::is_nothrow_move_constructible<pointer>::value and
8400 std::is_nothrow_move_assignable<pointer>::value and
8401 std::is_nothrow_move_constructible<internal_iterator>::value and
8402 std::is_nothrow_move_assignable<internal_iterator>::value
8405 std::swap(m_object, other.m_object);
8406 std::swap(m_it, other.m_it);
8415 void set_begin() noexcept
8417 assert(m_object !=
nullptr);
8419 switch (m_object->m_type)
8423 m_it.object_iterator = m_object->m_value.object->begin();
8429 m_it.array_iterator = m_object->m_value.array->begin();
8436 m_it.primitive_iterator.set_end();
8442 m_it.primitive_iterator.set_begin();
8452 void set_end() noexcept
8454 assert(m_object !=
nullptr);
8456 switch (m_object->m_type)
8460 m_it.object_iterator = m_object->m_value.object->end();
8466 m_it.array_iterator = m_object->m_value.array->end();
8472 m_it.primitive_iterator.set_end();
8485 assert(m_object !=
nullptr);
8487 switch (m_object->m_type)
8491 assert(m_it.object_iterator != m_object->m_value.object->end());
8492 return m_it.object_iterator->second;
8497 assert(m_it.array_iterator != m_object->m_value.array->end());
8498 return *m_it.array_iterator;
8503 throw std::out_of_range(
"cannot get value");
8508 if (m_it.primitive_iterator.is_begin())
8514 throw std::out_of_range(
"cannot get value");
8526 assert(m_object !=
nullptr);
8528 switch (m_object->m_type)
8532 assert(m_it.object_iterator != m_object->m_value.object->end());
8533 return &(m_it.object_iterator->second);
8538 assert(m_it.array_iterator != m_object->m_value.array->end());
8539 return &*m_it.array_iterator;
8544 if (m_it.primitive_iterator.is_begin())
8550 throw std::out_of_range(
"cannot get value");
8562 auto result = *
this;
8573 assert(m_object !=
nullptr);
8575 switch (m_object->m_type)
8579 std::advance(m_it.object_iterator, 1);
8585 std::advance(m_it.array_iterator, 1);
8591 ++m_it.primitive_iterator;
8605 auto result = *
this;
8616 assert(m_object !=
nullptr);
8618 switch (m_object->m_type)
8622 std::advance(m_it.object_iterator, -1);
8628 std::advance(m_it.array_iterator, -1);
8634 --m_it.primitive_iterator;
8649 if (m_object != other.m_object)
8651 throw std::domain_error(
"cannot compare iterators of different containers");
8654 assert(m_object !=
nullptr);
8656 switch (m_object->m_type)
8660 return (m_it.object_iterator == other.m_it.object_iterator);
8665 return (m_it.array_iterator == other.m_it.array_iterator);
8670 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
8681 return not operator==(other);
8691 if (m_object != other.m_object)
8693 throw std::domain_error(
"cannot compare iterators of different containers");
8696 assert(m_object !=
nullptr);
8698 switch (m_object->m_type)
8702 throw std::domain_error(
"cannot compare order of object iterators");
8707 return (m_it.array_iterator < other.m_it.array_iterator);
8712 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
8723 return not other.operator < (*this);
8732 return not operator<=(other);
8741 return not operator<(other);
8750 assert(m_object !=
nullptr);
8752 switch (m_object->m_type)
8756 throw std::domain_error(
"cannot use offsets with object iterators");
8761 std::advance(m_it.array_iterator, i);
8767 m_it.primitive_iterator += i;
8781 return operator+=(-i);
8790 auto result = *
this;
8801 auto result = *
this;
8812 assert(m_object !=
nullptr);
8814 switch (m_object->m_type)
8818 throw std::domain_error(
"cannot use offsets with object iterators");
8823 return m_it.array_iterator - other.m_it.array_iterator;
8828 return m_it.primitive_iterator - other.m_it.primitive_iterator;
8839 assert(m_object !=
nullptr);
8841 switch (m_object->m_type)
8845 throw std::domain_error(
"cannot use operator[] for object iterators");
8850 return *std::next(m_it.array_iterator, n);
8855 throw std::out_of_range(
"cannot get value");
8860 if (m_it.primitive_iterator == -n)
8866 throw std::out_of_range(
"cannot get value");
8876 typename object_t::key_type
key()
const 8878 assert(m_object !=
nullptr);
8880 if (m_object->is_object())
8882 return m_it.object_iterator->first;
8886 throw std::domain_error(
"cannot use key() for non-object iterators");
8903 internal_iterator m_it = internal_iterator();
8923 template<
typename Base>
8945 return base_iterator::operator++(1);
8951 base_iterator::operator++();
8958 return base_iterator::operator--(1);
8964 base_iterator::operator--();
8971 base_iterator::operator+=(i);
8978 auto result = *
this;
8986 auto result = *
this;
8994 return this->base() - other.base();
9000 return *(this->operator+(n));
9004 typename object_t::key_type
key()
const 9006 auto it = --this->base();
9013 auto it = --this->base();
9014 return it.operator * ();
9035 enum class token_type
9054 using lexer_char_t =
unsigned char;
9057 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
9060 assert(m_content !=
nullptr);
9061 m_start = m_cursor = m_content;
9062 m_limit = m_content + len;
9066 explicit lexer(std::istream& s)
9067 : m_stream(&s), m_line_buffer()
9072 throw std::invalid_argument(
"stream error");
9079 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
9081 m_line_buffer[0] =
' ';
9082 m_line_buffer[1] =
' ';
9083 m_line_buffer[2] =
' ';
9089 lexer(
const lexer&) =
delete;
9090 lexer operator=(
const lexer&) =
delete;
9115 static string_t to_unicode(
const std::size_t codepoint1,
9116 const std::size_t codepoint2 = 0)
9119 std::size_t codepoint = codepoint1;
9122 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9125 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9139 throw std::invalid_argument(
"missing or wrong low surrogate");
9145 if (codepoint < 0x80)
9148 result.append(1, static_cast<typename string_t::value_type>(codepoint));
9150 else if (codepoint <= 0x7ff)
9153 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9154 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9156 else if (codepoint <= 0xffff)
9159 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9160 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9161 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9163 else if (codepoint <= 0x10ffff)
9166 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9167 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9168 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9169 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9173 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
9180 static std::string token_type_name(
const token_type t)
9184 case token_type::uninitialized:
9185 return "<uninitialized>";
9186 case token_type::literal_true:
9187 return "true literal";
9188 case token_type::literal_false:
9189 return "false literal";
9190 case token_type::literal_null:
9191 return "null literal";
9192 case token_type::value_string:
9193 return "string literal";
9194 case token_type::value_number:
9195 return "number literal";
9196 case token_type::begin_array:
9198 case token_type::begin_object:
9200 case token_type::end_array:
9202 case token_type::end_object:
9204 case token_type::name_separator:
9206 case token_type::value_separator:
9208 case token_type::parse_error:
9209 return "<parse error>";
9210 case token_type::end_of_input:
9211 return "end of input";
9215 return "unknown token";
9250 assert(m_start !=
nullptr);
9255 unsigned int yyaccept = 0;
9256 static const unsigned char yybm[] =
9258 0, 0, 0, 0, 0, 0, 0, 0,
9259 0, 32, 32, 0, 0, 32, 0, 0,
9260 0, 0, 0, 0, 0, 0, 0, 0,
9261 0, 0, 0, 0, 0, 0, 0, 0,
9262 160, 128, 0, 128, 128, 128, 128, 128,
9263 128, 128, 128, 128, 128, 128, 128, 128,
9264 192, 192, 192, 192, 192, 192, 192, 192,
9265 192, 192, 128, 128, 128, 128, 128, 128,
9266 128, 128, 128, 128, 128, 128, 128, 128,
9267 128, 128, 128, 128, 128, 128, 128, 128,
9268 128, 128, 128, 128, 128, 128, 128, 128,
9269 128, 128, 128, 128, 0, 128, 128, 128,
9270 128, 128, 128, 128, 128, 128, 128, 128,
9271 128, 128, 128, 128, 128, 128, 128, 128,
9272 128, 128, 128, 128, 128, 128, 128, 128,
9273 128, 128, 128, 128, 128, 128, 128, 128,
9274 0, 0, 0, 0, 0, 0, 0, 0,
9275 0, 0, 0, 0, 0, 0, 0, 0,
9276 0, 0, 0, 0, 0, 0, 0, 0,
9277 0, 0, 0, 0, 0, 0, 0, 0,
9278 0, 0, 0, 0, 0, 0, 0, 0,
9279 0, 0, 0, 0, 0, 0, 0, 0,
9280 0, 0, 0, 0, 0, 0, 0, 0,
9281 0, 0, 0, 0, 0, 0, 0, 0,
9282 0, 0, 0, 0, 0, 0, 0, 0,
9283 0, 0, 0, 0, 0, 0, 0, 0,
9284 0, 0, 0, 0, 0, 0, 0, 0,
9285 0, 0, 0, 0, 0, 0, 0, 0,
9286 0, 0, 0, 0, 0, 0, 0, 0,
9287 0, 0, 0, 0, 0, 0, 0, 0,
9288 0, 0, 0, 0, 0, 0, 0, 0,
9289 0, 0, 0, 0, 0, 0, 0, 0,
9291 if ((m_limit - m_cursor) < 5)
9293 fill_line_buffer(5);
9296 if (yybm[0 + yych] & 32)
9298 goto basic_json_parser_6;
9308 goto basic_json_parser_2;
9312 goto basic_json_parser_4;
9314 goto basic_json_parser_9;
9320 goto basic_json_parser_4;
9324 goto basic_json_parser_10;
9326 goto basic_json_parser_12;
9335 goto basic_json_parser_4;
9339 goto basic_json_parser_13;
9341 goto basic_json_parser_15;
9347 goto basic_json_parser_17;
9351 goto basic_json_parser_4;
9353 goto basic_json_parser_19;
9365 goto basic_json_parser_21;
9367 goto basic_json_parser_4;
9373 goto basic_json_parser_23;
9377 goto basic_json_parser_4;
9379 goto basic_json_parser_24;
9388 goto basic_json_parser_25;
9390 goto basic_json_parser_4;
9396 goto basic_json_parser_26;
9400 goto basic_json_parser_28;
9402 goto basic_json_parser_4;
9406 basic_json_parser_2:
9409 last_token_type = token_type::end_of_input;
9412 basic_json_parser_4:
9414 basic_json_parser_5:
9416 last_token_type = token_type::parse_error;
9419 basic_json_parser_6:
9421 if (m_limit <= m_cursor)
9423 fill_line_buffer(1);
9426 if (yybm[0 + yych] & 32)
9428 goto basic_json_parser_6;
9433 basic_json_parser_9:
9435 yych = *(m_marker = ++m_cursor);
9438 goto basic_json_parser_5;
9442 goto basic_json_parser_31;
9446 goto basic_json_parser_5;
9450 goto basic_json_parser_31;
9452 goto basic_json_parser_5;
9453 basic_json_parser_10:
9456 last_token_type = token_type::value_separator;
9459 basic_json_parser_12:
9463 goto basic_json_parser_5;
9467 goto basic_json_parser_13;
9471 goto basic_json_parser_15;
9473 goto basic_json_parser_5;
9474 basic_json_parser_13:
9476 yych = *(m_marker = ++m_cursor);
9481 goto basic_json_parser_43;
9488 goto basic_json_parser_44;
9492 goto basic_json_parser_44;
9495 basic_json_parser_14:
9497 last_token_type = token_type::value_number;
9500 basic_json_parser_15:
9502 m_marker = ++m_cursor;
9503 if ((m_limit - m_cursor) < 3)
9505 fill_line_buffer(3);
9508 if (yybm[0 + yych] & 64)
9510 goto basic_json_parser_15;
9516 goto basic_json_parser_43;
9518 goto basic_json_parser_14;
9524 goto basic_json_parser_44;
9528 goto basic_json_parser_44;
9530 goto basic_json_parser_14;
9532 basic_json_parser_17:
9535 last_token_type = token_type::name_separator;
9538 basic_json_parser_19:
9541 last_token_type = token_type::begin_array;
9544 basic_json_parser_21:
9547 last_token_type = token_type::end_array;
9550 basic_json_parser_23:
9552 yych = *(m_marker = ++m_cursor);
9555 goto basic_json_parser_45;
9557 goto basic_json_parser_5;
9558 basic_json_parser_24:
9560 yych = *(m_marker = ++m_cursor);
9563 goto basic_json_parser_46;
9565 goto basic_json_parser_5;
9566 basic_json_parser_25:
9568 yych = *(m_marker = ++m_cursor);
9571 goto basic_json_parser_47;
9573 goto basic_json_parser_5;
9574 basic_json_parser_26:
9577 last_token_type = token_type::begin_object;
9580 basic_json_parser_28:
9583 last_token_type = token_type::end_object;
9586 basic_json_parser_30:
9588 if (m_limit <= m_cursor)
9590 fill_line_buffer(1);
9593 basic_json_parser_31:
9594 if (yybm[0 + yych] & 128)
9596 goto basic_json_parser_30;
9604 goto basic_json_parser_32;
9608 goto basic_json_parser_33;
9610 goto basic_json_parser_35;
9616 goto basic_json_parser_32;
9620 goto basic_json_parser_36;
9622 goto basic_json_parser_37;
9631 goto basic_json_parser_39;
9633 goto basic_json_parser_38;
9639 goto basic_json_parser_40;
9643 goto basic_json_parser_41;
9647 goto basic_json_parser_42;
9651 basic_json_parser_32:
9652 m_cursor = m_marker;
9655 goto basic_json_parser_5;
9659 goto basic_json_parser_14;
9661 basic_json_parser_33:
9664 last_token_type = token_type::value_string;
9667 basic_json_parser_35:
9669 if (m_limit <= m_cursor)
9671 fill_line_buffer(1);
9680 goto basic_json_parser_30;
9684 goto basic_json_parser_32;
9686 goto basic_json_parser_30;
9694 goto basic_json_parser_32;
9696 goto basic_json_parser_30;
9702 goto basic_json_parser_30;
9704 goto basic_json_parser_32;
9714 goto basic_json_parser_30;
9718 goto basic_json_parser_30;
9720 goto basic_json_parser_32;
9728 goto basic_json_parser_30;
9730 goto basic_json_parser_32;
9736 goto basic_json_parser_30;
9740 goto basic_json_parser_48;
9742 goto basic_json_parser_32;
9746 basic_json_parser_36:
9748 if (m_limit <= m_cursor)
9750 fill_line_buffer(1);
9755 goto basic_json_parser_32;
9759 goto basic_json_parser_30;
9761 goto basic_json_parser_32;
9762 basic_json_parser_37:
9764 if (m_limit <= m_cursor)
9766 fill_line_buffer(1);
9771 goto basic_json_parser_32;
9775 goto basic_json_parser_36;
9777 goto basic_json_parser_32;
9778 basic_json_parser_38:
9780 if (m_limit <= m_cursor)
9782 fill_line_buffer(1);
9787 goto basic_json_parser_32;
9791 goto basic_json_parser_36;
9793 goto basic_json_parser_32;
9794 basic_json_parser_39:
9796 if (m_limit <= m_cursor)
9798 fill_line_buffer(1);
9803 goto basic_json_parser_32;
9807 goto basic_json_parser_36;
9809 goto basic_json_parser_32;
9810 basic_json_parser_40:
9812 if (m_limit <= m_cursor)
9814 fill_line_buffer(1);
9819 goto basic_json_parser_32;
9823 goto basic_json_parser_38;
9825 goto basic_json_parser_32;
9826 basic_json_parser_41:
9828 if (m_limit <= m_cursor)
9830 fill_line_buffer(1);
9835 goto basic_json_parser_32;
9839 goto basic_json_parser_38;
9841 goto basic_json_parser_32;
9842 basic_json_parser_42:
9844 if (m_limit <= m_cursor)
9846 fill_line_buffer(1);
9851 goto basic_json_parser_32;
9855 goto basic_json_parser_38;
9857 goto basic_json_parser_32;
9858 basic_json_parser_43:
9862 goto basic_json_parser_32;
9866 goto basic_json_parser_49;
9868 goto basic_json_parser_32;
9869 basic_json_parser_44:
9875 goto basic_json_parser_51;
9877 goto basic_json_parser_32;
9883 goto basic_json_parser_51;
9887 goto basic_json_parser_32;
9891 goto basic_json_parser_52;
9893 goto basic_json_parser_32;
9895 basic_json_parser_45:
9899 goto basic_json_parser_54;
9901 goto basic_json_parser_32;
9902 basic_json_parser_46:
9906 goto basic_json_parser_55;
9908 goto basic_json_parser_32;
9909 basic_json_parser_47:
9913 goto basic_json_parser_56;
9915 goto basic_json_parser_32;
9916 basic_json_parser_48:
9918 if (m_limit <= m_cursor)
9920 fill_line_buffer(1);
9927 goto basic_json_parser_32;
9931 goto basic_json_parser_57;
9933 goto basic_json_parser_32;
9939 goto basic_json_parser_57;
9943 goto basic_json_parser_32;
9947 goto basic_json_parser_57;
9949 goto basic_json_parser_32;
9951 basic_json_parser_49:
9953 m_marker = ++m_cursor;
9954 if ((m_limit - m_cursor) < 3)
9956 fill_line_buffer(3);
9963 goto basic_json_parser_14;
9967 goto basic_json_parser_49;
9969 goto basic_json_parser_14;
9975 goto basic_json_parser_44;
9979 goto basic_json_parser_44;
9981 goto basic_json_parser_14;
9983 basic_json_parser_51:
9987 goto basic_json_parser_32;
9991 goto basic_json_parser_32;
9993 basic_json_parser_52:
9995 if (m_limit <= m_cursor)
9997 fill_line_buffer(1);
10002 goto basic_json_parser_14;
10006 goto basic_json_parser_52;
10008 goto basic_json_parser_14;
10009 basic_json_parser_54:
10010 yych = *++m_cursor;
10013 goto basic_json_parser_58;
10015 goto basic_json_parser_32;
10016 basic_json_parser_55:
10017 yych = *++m_cursor;
10020 goto basic_json_parser_59;
10022 goto basic_json_parser_32;
10023 basic_json_parser_56:
10024 yych = *++m_cursor;
10027 goto basic_json_parser_61;
10029 goto basic_json_parser_32;
10030 basic_json_parser_57:
10032 if (m_limit <= m_cursor)
10034 fill_line_buffer(1);
10041 goto basic_json_parser_32;
10045 goto basic_json_parser_63;
10047 goto basic_json_parser_32;
10053 goto basic_json_parser_63;
10057 goto basic_json_parser_32;
10061 goto basic_json_parser_63;
10063 goto basic_json_parser_32;
10065 basic_json_parser_58:
10066 yych = *++m_cursor;
10069 goto basic_json_parser_64;
10071 goto basic_json_parser_32;
10072 basic_json_parser_59:
10075 last_token_type = token_type::literal_null;
10078 basic_json_parser_61:
10081 last_token_type = token_type::literal_true;
10084 basic_json_parser_63:
10086 if (m_limit <= m_cursor)
10088 fill_line_buffer(1);
10095 goto basic_json_parser_32;
10099 goto basic_json_parser_66;
10101 goto basic_json_parser_32;
10107 goto basic_json_parser_66;
10111 goto basic_json_parser_32;
10115 goto basic_json_parser_66;
10117 goto basic_json_parser_32;
10119 basic_json_parser_64:
10122 last_token_type = token_type::literal_false;
10125 basic_json_parser_66:
10127 if (m_limit <= m_cursor)
10129 fill_line_buffer(1);
10136 goto basic_json_parser_32;
10140 goto basic_json_parser_30;
10142 goto basic_json_parser_32;
10148 goto basic_json_parser_30;
10152 goto basic_json_parser_32;
10156 goto basic_json_parser_30;
10158 goto basic_json_parser_32;
10164 return last_token_type;
10195 void fill_line_buffer(
size_t n = 0)
10198 assert(m_line_buffer.empty()
10199 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
10202 assert(m_line_buffer.empty()
10203 or m_limit == m_content + m_line_buffer.size());
10206 assert(m_content <= m_start);
10207 assert(m_start <= m_cursor);
10208 assert(m_cursor <= m_limit);
10209 assert(m_marker ==
nullptr or m_marker <= m_limit);
10212 const size_t num_processed_chars =
static_cast<size_t>(m_start - m_content);
10214 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
10216 const auto offset_cursor = m_cursor - m_start;
10219 if (m_stream ==
nullptr or m_stream->eof())
10224 m_line_buffer.assign(m_start, m_limit);
10228 m_line_buffer.append(1,
'\x00');
10231 m_line_buffer.append(n - 1,
'\x01');
10237 m_line_buffer.erase(0, num_processed_chars);
10239 m_line_buffer_tmp.clear();
10240 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
10243 m_line_buffer += m_line_buffer_tmp;
10244 m_line_buffer.push_back(
'\n');
10248 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
10249 assert(m_content !=
nullptr);
10250 m_start = m_content;
10251 m_marker = m_start + offset_marker;
10252 m_cursor = m_start + offset_cursor;
10253 m_limit = m_start + m_line_buffer.size();
10259 assert(m_start !=
nullptr);
10260 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10261 static_cast<size_t>(m_cursor - m_start));
10323 assert(m_cursor - m_start >= 2);
10326 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10329 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10332 auto e = std::find(i, m_cursor - 1,
'\\');
10336 for (
auto k = i; k < e; k++)
10338 result.push_back(static_cast<typename string_t::value_type>(*k));
10396 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10397 4).c_str(),
nullptr, 16);
10400 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10403 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
10405 throw std::invalid_argument(
"missing low surrogate");
10409 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10410 (i + 7), 4).c_str(),
nullptr, 16);
10411 result += to_unicode(codepoint, codepoint2);
10415 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10418 throw std::invalid_argument(
"missing high surrogate");
10423 result += to_unicode(codepoint);
10449 long double str_to_float_t(
long double* ,
char** endptr)
const 10451 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10467 double str_to_float_t(
double* ,
char** endptr)
const 10469 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10485 float str_to_float_t(
float* ,
char** endptr)
const 10487 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10513 assert(m_start !=
nullptr);
10515 const lexer::lexer_char_t* curptr = m_start;
10527 if (*curptr ==
'-')
10529 type = value_t::number_integer;
10530 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
10535 type = value_t::number_unsigned;
10536 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
10540 for (; curptr < m_cursor; curptr++)
10543 if (*curptr < '0' || *curptr >
'9')
10545 if (*curptr ==
'.')
10548 type = value_t::number_float;
10553 type = value_t::number_float;
10558 if (type != value_t::number_float)
10564 if (value > (max - digit) / 10)
10567 type = value_t::number_float;
10572 value = value * 10 + digit;
10578 if (type == value_t::number_unsigned)
10580 result.m_value.number_unsigned = value;
10582 else if (type == value_t::number_integer)
10586 assert(value >= 0);
10587 assert(value <= max);
10604 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
10607 if (not std::isfinite(result.m_value.number_float))
10609 type = value_t::null;
10610 result.m_value = basic_json::json_value();
10615 result.m_type = type;
10620 std::istream* m_stream =
nullptr;
10626 const lexer_char_t* m_content =
nullptr;
10628 const lexer_char_t* m_start =
nullptr;
10630 const lexer_char_t* m_marker =
nullptr;
10632 const lexer_char_t* m_cursor =
nullptr;
10634 const lexer_char_t* m_limit =
nullptr;
10636 token_type last_token_type = token_type::end_of_input;
10650 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10655 : callback(cb), m_lexer(is)
10659 template<
class IteratorType,
typename std::enable_if<
10660 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10663 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
10665 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10666 static_cast<size_t>(std::distance(first, last)))
10676 result.assert_invariant();
10678 expect(lexer::token_type::end_of_input);
10689 auto result =
basic_json(value_t::discarded);
10691 switch (last_token)
10693 case lexer::token_type::begin_object:
10695 if (keep and (not callback
10696 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10699 result.m_type = value_t::object;
10700 result.m_value = value_t::object;
10707 if (last_token == lexer::token_type::end_object)
10710 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10718 unexpect(lexer::token_type::value_separator);
10724 if (last_token == lexer::token_type::value_separator)
10730 expect(lexer::token_type::value_string);
10731 const auto key = m_lexer.get_string();
10733 bool keep_tag =
false;
10739 keep_tag = callback(depth, parse_event_t::key, k);
10749 expect(lexer::token_type::name_separator);
10753 auto value = parse_internal(keep);
10754 if (keep and keep_tag and not value.is_discarded())
10756 result[key] = std::move(value);
10759 while (last_token == lexer::token_type::value_separator);
10762 expect(lexer::token_type::end_object);
10764 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10772 case lexer::token_type::begin_array:
10774 if (keep and (not callback
10775 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10778 result.m_type = value_t::array;
10779 result.m_value = value_t::array;
10786 if (last_token == lexer::token_type::end_array)
10789 if (callback and not callback(--depth, parse_event_t::array_end, result))
10797 unexpect(lexer::token_type::value_separator);
10803 if (last_token == lexer::token_type::value_separator)
10809 auto value = parse_internal(keep);
10810 if (keep and not value.is_discarded())
10812 result.push_back(std::move(value));
10815 while (last_token == lexer::token_type::value_separator);
10818 expect(lexer::token_type::end_array);
10820 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10828 case lexer::token_type::literal_null:
10831 result.m_type = value_t::null;
10835 case lexer::token_type::value_string:
10837 const auto s = m_lexer.get_string();
10843 case lexer::token_type::literal_true:
10846 result.m_type = value_t::boolean;
10847 result.m_value =
true;
10851 case lexer::token_type::literal_false:
10854 result.m_type = value_t::boolean;
10855 result.m_value =
false;
10859 case lexer::token_type::value_number:
10861 m_lexer.get_number(result);
10869 unexpect(last_token);
10873 if (keep and callback and not callback(depth, parse_event_t::value, result))
10881 typename lexer::token_type get_token()
10883 last_token = m_lexer.scan();
10887 void expect(
typename lexer::token_type t)
const 10889 if (t != last_token)
10891 std::string error_msg =
"parse error - unexpected ";
10892 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
10894 lexer::token_type_name(last_token));
10895 error_msg +=
"; expected " + lexer::token_type_name(t);
10896 throw std::invalid_argument(error_msg);
10900 void unexpect(
typename lexer::token_type t)
const 10902 if (t == last_token)
10904 std::string error_msg =
"parse error - unexpected ";
10905 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
10907 lexer::token_type_name(last_token));
10908 throw std::invalid_argument(error_msg);
10918 typename lexer::token_type last_token = lexer::token_type::uninitialized;
10964 : reference_tokens(split(s))
10982 std::string to_string()
const noexcept
10984 return std::accumulate(reference_tokens.begin(),
10985 reference_tokens.end(), std::string{},
10986 [](
const std::string & a,
const std::string & b)
10988 return a +
"/" + escape(b);
10993 operator std::string()
const 10995 return to_string();
11000 std::string pop_back()
11004 throw std::domain_error(
"JSON pointer has no parent");
11007 auto last = reference_tokens.back();
11008 reference_tokens.pop_back();
11013 bool is_root()
const 11015 return reference_tokens.empty();
11022 throw std::domain_error(
"JSON pointer has no parent");
11026 result.reference_tokens = {reference_tokens[0]};
11041 for (
const auto& reference_token : reference_tokens)
11043 switch (result->m_type)
11045 case value_t::null:
11047 if (reference_token ==
"0")
11050 result = &result->operator[](0);
11055 result = &result->operator[](reference_token);
11060 case value_t::object:
11063 result = &result->operator[](reference_token);
11067 case value_t::array:
11070 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11083 throw std::domain_error(
"invalid value to unflatten");
11112 for (
const auto& reference_token : reference_tokens)
11115 if (ptr->m_type == value_t::null)
11118 const bool nums = std::all_of(reference_token.begin(),
11119 reference_token.end(),
11122 return std::isdigit(x);
11127 if (nums or reference_token ==
"-")
11129 *ptr = value_t::array;
11133 *ptr = value_t::object;
11137 switch (ptr->m_type)
11139 case value_t::object:
11142 ptr = &ptr->operator[](reference_token);
11146 case value_t::array:
11149 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11151 throw std::domain_error(
"array index must not begin with '0'");
11154 if (reference_token ==
"-")
11157 ptr = &ptr->operator[](ptr->m_value.array->size());
11162 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11169 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11179 for (
const auto& reference_token : reference_tokens)
11181 switch (ptr->m_type)
11183 case value_t::object:
11186 ptr = &ptr->
at(reference_token);
11190 case value_t::array:
11192 if (reference_token ==
"-")
11195 throw std::out_of_range(
"array index '-' (" +
11196 std::to_string(ptr->m_value.array->size()) +
11197 ") is out of range");
11201 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11203 throw std::domain_error(
"array index must not begin with '0'");
11207 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11213 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11231 for (
const auto& reference_token : reference_tokens)
11233 switch (ptr->m_type)
11235 case value_t::object:
11238 ptr = &ptr->operator[](reference_token);
11242 case value_t::array:
11244 if (reference_token ==
"-")
11247 throw std::out_of_range(
"array index '-' (" +
11248 std::to_string(ptr->m_value.array->size()) +
11249 ") is out of range");
11253 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11255 throw std::domain_error(
"array index must not begin with '0'");
11259 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11265 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11275 for (
const auto& reference_token : reference_tokens)
11277 switch (ptr->m_type)
11279 case value_t::object:
11282 ptr = &ptr->
at(reference_token);
11286 case value_t::array:
11288 if (reference_token ==
"-")
11291 throw std::out_of_range(
"array index '-' (" +
11292 std::to_string(ptr->m_value.array->size()) +
11293 ") is out of range");
11297 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11299 throw std::domain_error(
"array index must not begin with '0'");
11303 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11309 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11318 static std::vector<std::string> split(
const std::string& reference_string)
11320 std::vector<std::string> result;
11323 if (reference_string.empty())
11329 if (reference_string[0] !=
'/')
11331 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
11339 size_t slash = reference_string.find_first_of(
"/", 1),
11348 slash = reference_string.find_first_of(
"/", start))
11352 auto reference_token = reference_string.substr(start, slash - start);
11355 for (
size_t pos = reference_token.find_first_of(
"~");
11356 pos != std::string::npos;
11357 pos = reference_token.find_first_of(
"~", pos + 1))
11359 assert(reference_token[pos] ==
'~');
11362 if (pos == reference_token.size() - 1 or
11363 (reference_token[pos + 1] !=
'0' and
11364 reference_token[pos + 1] !=
'1'))
11366 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
11371 unescape(reference_token);
11372 result.push_back(reference_token);
11391 static void replace_substring(std::string& s,
11392 const std::string& f,
11393 const std::string& t)
11395 assert(not f.empty());
11398 size_t pos = s.find(f);
11399 pos != std::string::npos;
11400 s.replace(pos, f.size(), t),
11401 pos = s.find(f, pos + t.size())
11406 static std::string escape(std::string s)
11409 replace_substring(s,
"~",
"~0");
11410 replace_substring(s,
"/",
"~1");
11415 static void unescape(std::string& s)
11418 replace_substring(s,
"~1",
"/");
11420 replace_substring(s,
"~0",
"~");
11430 static void flatten(
const std::string& reference_string,
11434 switch (value.m_type)
11436 case value_t::array:
11438 if (value.m_value.array->empty())
11441 result[reference_string] =
nullptr;
11446 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
11448 flatten(reference_string +
"/" + std::to_string(i),
11449 value.m_value.array->operator[](i), result);
11455 case value_t::object:
11457 if (value.m_value.object->empty())
11460 result[reference_string] =
nullptr;
11465 for (
const auto& element : *value.m_value.object)
11467 flatten(reference_string +
"/" + escape(element.first),
11468 element.second, result);
11477 result[reference_string] = value;
11492 throw std::domain_error(
"only objects can be unflattened");
11498 for (
const auto& element : *value.m_value.object)
11500 if (not element.second.is_primitive())
11502 throw std::domain_error(
"values in object must be primitive");
11510 json_pointer(element.first).get_and_create(result) = element.second;
11518 std::vector<std::string> reference_tokens {};
11563 return ptr.get_unchecked(
this);
11590 return ptr.get_unchecked(
this);
11615 return ptr.get_checked(
this);
11640 return ptr.get_checked(
this);
11668 json_pointer::flatten(
"", *
this, result);
11701 return json_pointer::unflatten(*
this);
11755 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
11757 const auto get_op = [](
const std::string op)
11761 return patch_operations::add;
11763 if (op ==
"remove")
11765 return patch_operations::remove;
11767 if (op ==
"replace")
11769 return patch_operations::replace;
11773 return patch_operations::move;
11777 return patch_operations::copy;
11781 return patch_operations::test;
11784 return patch_operations::invalid;
11799 if (top_pointer != ptr)
11801 result.
at(top_pointer);
11805 const auto last_path = ptr.pop_back();
11808 switch (parent.m_type)
11810 case value_t::null:
11811 case value_t::object:
11814 parent[last_path] = val;
11818 case value_t::array:
11820 if (last_path ==
"-")
11827 const auto idx = std::stoi(last_path);
11828 if (static_cast<size_type>(idx) > parent.
size())
11831 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
11852 const auto operation_remove = [&result](
json_pointer & ptr)
11855 const auto last_path = ptr.pop_back();
11862 auto it = parent.
find(last_path);
11863 if (it != parent.
end())
11869 throw std::out_of_range(
"key '" + last_path +
"' not found");
11875 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
11883 throw std::invalid_argument(
"JSON patch must be an array of objects");
11887 for (
const auto& val : json_patch)
11890 const auto get_value = [&val](
const std::string & op,
11891 const std::string & member,
11895 auto it = val.m_value.object->find(member);
11898 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
11901 if (it == val.m_value.object->end())
11903 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
11907 if (string_type and not it->second.is_string())
11909 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
11917 if (not val.is_object())
11919 throw std::invalid_argument(
"JSON patch must be an array of objects");
11923 const std::string op = get_value(
"op",
"op",
true);
11924 const std::string path = get_value(op,
"path",
true);
11927 switch (get_op(op))
11929 case patch_operations::add:
11931 operation_add(ptr, get_value(
"add",
"value",
false));
11935 case patch_operations::remove:
11937 operation_remove(ptr);
11941 case patch_operations::replace:
11944 result.
at(ptr) = get_value(
"replace",
"value",
false);
11948 case patch_operations::move:
11950 const std::string from_path = get_value(
"move",
"from",
true);
11960 operation_remove(from_ptr);
11961 operation_add(ptr, v);
11965 case patch_operations::copy:
11967 const std::string from_path = get_value(
"copy",
"from",
true);;
11971 result[ptr] = result.
at(from_ptr);
11975 case patch_operations::test:
11977 bool success =
false;
11982 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
11984 catch (std::out_of_range&)
11992 throw std::domain_error(
"unsuccessful: " + val.dump());
11998 case patch_operations::invalid:
12002 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
12044 const std::string& path =
"")
12050 if (source == target)
12055 if (source.
type() != target.
type())
12067 switch (source.
type())
12069 case value_t::array:
12073 while (i < source.
size() and i < target.
size())
12076 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
12077 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12086 while (i < source.
size())
12090 result.insert(result.begin() + end_index, object(
12093 {
"path", path +
"/" + std::to_string(i)}
12099 while (i < target.
size())
12104 {
"path", path +
"/" + std::to_string(i)},
12105 {
"value", target[i]}
12113 case value_t::object:
12116 for (
auto it = source.
begin(); it != source.
end(); ++it)
12119 const auto key = json_pointer::escape(it.key());
12121 if (target.
find(it.key()) != target.
end())
12124 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
12125 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12130 result.push_back(
object(
12133 {
"path", path +
"/" + key}
12139 for (
auto it = target.
begin(); it != target.
end(); ++it)
12141 if (source.
find(it.key()) == source.
end())
12144 const auto key = json_pointer::escape(it.key());
12148 {
"path", path +
"/" + key},
12149 {
"value", it.value()}
12209 is_nothrow_move_constructible<nlohmann::json>::value and
12210 is_nothrow_move_assignable<nlohmann::json>::value
12228 const auto& h = hash<nlohmann::json::string_t>();
12247 inline nlohmann::json operator "" _json(
const char* s, std::size_t n)
12271 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 12272 #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.