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;
213 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
214 template<
typename U,
typename... Args>
class ArrayType = std::vector,
215 class StringType = std::string,
216 class BooleanType = bool,
217 class NumberIntegerType = std::int64_t,
218 class NumberUnsignedType = std::uint64_t,
219 class NumberFloatType = double,
220 template<
typename U>
class AllocatorType = std::allocator
227 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
262 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
264 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
379 using object_t = ObjectType<StringType,
381 std::less<StringType>,
382 AllocatorType<std::pair<
const StringType,
429 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
767 template<
typename T,
typename... Args>
768 static T* create(Args&& ... args)
770 AllocatorType<T> alloc;
771 auto deleter = [&](T * object)
773 alloc.deallocate(
object, 1);
775 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
776 alloc.construct(
object.
get(), std::forward<Args>(args)...);
777 assert(
object !=
nullptr);
778 return object.release();
827 json_value() =
default;
829 json_value(
boolean_t v) noexcept : boolean(v) {}
841 case value_t::object:
843 object = create<object_t>();
849 array = create<array_t>();
853 case value_t::string:
855 string = create<string_t>(
"");
859 case value_t::boolean:
865 case value_t::number_integer:
871 case value_t::number_unsigned:
877 case value_t::number_float:
890 if (t == value_t::null)
892 throw std::domain_error(
"961c151d2e87f2686a955a9be24d316f1362bf21 2.0.10");
902 string = create<string_t>(value);
908 object = create<object_t>(value);
912 json_value(
const array_t& value)
914 array = create<array_t>(value);
927 void assert_invariant()
const 929 assert(m_type != value_t::object or m_value.object !=
nullptr);
930 assert(m_type != value_t::array or m_value.array !=
nullptr);
931 assert(m_type != value_t::string or m_value.string !=
nullptr);
1019 basic_json& parsed)>;
1071 : m_type(value_type), m_value(value_type)
1120 : m_type(
value_t::object), m_value(val)
1151 template<
class CompatibleObjectType,
typename std::enable_if<
1152 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1153 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1159 m_value.object = create<object_t>(begin(val), end(val));
1183 : m_type(
value_t::array), m_value(val)
1214 template<
class CompatibleArrayType,
typename std::enable_if<
1215 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1216 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1217 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1218 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1219 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1220 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1221 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1227 m_value.array = create<array_t>(begin(val), end(val));
1253 : m_type(
value_t::string), m_value(val)
1307 template<
class CompatibleStringType,
typename std::enable_if<
1308 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1330 : m_type(value_t::boolean), m_value(val)
1358 template<
typename T,
typename std::enable_if<
1359 not (std::is_same<T, int>::value) and
1360 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1362 : m_type(value_t::number_integer), m_value(val)
1393 : m_type(value_t::number_integer),
1394 m_value(static_cast<number_integer_t>(val))
1424 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1425 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1426 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1427 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1428 CompatibleNumberIntegerType>::type = 0>
1430 : m_type(value_t::number_integer),
1431 m_value(static_cast<number_integer_t>(val))
1453 template<
typename T,
typename std::enable_if<
1454 not (std::is_same<T, int>::value) and
1455 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1457 : m_type(value_t::number_unsigned), m_value(val)
1482 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1483 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1484 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1485 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1486 CompatibleNumberUnsignedType>::type = 0>
1488 : m_type(value_t::number_unsigned),
1489 m_value(static_cast<number_unsigned_t>(val))
1519 : m_type(value_t::number_float), m_value(val)
1522 if (not std::isfinite(val))
1524 m_type = value_t::null;
1525 m_value = json_value();
1562 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1563 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1564 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1641 bool type_deduction =
true,
1642 value_t manual_type = value_t::array)
1646 bool is_an_object = std::all_of(init.begin(), init.end(),
1649 return element.is_array() and element.size() == 2 and element[0].is_string();
1653 if (not type_deduction)
1656 if (manual_type == value_t::array)
1658 is_an_object =
false;
1662 if (manual_type == value_t::object and not is_an_object)
1664 throw std::domain_error(
"cannot create object from initializer list");
1671 m_type = value_t::object;
1672 m_value = value_t::object;
1674 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1676 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1682 m_type = value_t::array;
1683 m_value.array = create<array_t>(init);
1724 std::initializer_list<basic_json>())
1726 return basic_json(init,
false, value_t::array);
1764 std::initializer_list<basic_json>())
1766 return basic_json(init,
false, value_t::object);
1790 m_value.array = create<array_t>(cnt, val);
1831 template<
class InputIT,
typename std::enable_if<
1832 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1833 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1836 assert(first.m_object !=
nullptr);
1837 assert(last.m_object !=
nullptr);
1840 if (first.m_object != last.m_object)
1842 throw std::domain_error(
"iterators are not compatible");
1846 m_type = first.m_object->m_type;
1851 case value_t::boolean:
1852 case value_t::number_float:
1853 case value_t::number_integer:
1854 case value_t::number_unsigned:
1855 case value_t::string:
1857 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1859 throw std::out_of_range(
"iterators out of range");
1872 case value_t::number_integer:
1874 m_value.number_integer = first.m_object->m_value.number_integer;
1878 case value_t::number_unsigned:
1880 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1884 case value_t::number_float:
1886 m_value.number_float = first.m_object->m_value.number_float;
1890 case value_t::boolean:
1892 m_value.boolean = first.m_object->m_value.boolean;
1896 case value_t::string:
1898 m_value = *first.m_object->m_value.string;
1902 case value_t::object:
1904 m_value.object = create<object_t>(first.m_it.object_iterator,
1905 last.m_it.object_iterator);
1909 case value_t::array:
1911 m_value.array = create<array_t>(first.m_it.array_iterator,
1912 last.m_it.array_iterator);
1918 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1956 *
this = parser(i, cb).parse();
1987 : m_type(other.m_type)
1990 other.assert_invariant();
1994 case value_t::object:
1996 m_value = *other.m_value.object;
2000 case value_t::array:
2002 m_value = *other.m_value.array;
2006 case value_t::string:
2008 m_value = *other.m_value.string;
2012 case value_t::boolean:
2014 m_value = other.m_value.boolean;
2018 case value_t::number_integer:
2020 m_value = other.m_value.number_integer;
2024 case value_t::number_unsigned:
2026 m_value = other.m_value.number_unsigned;
2030 case value_t::number_float:
2032 m_value = other.m_value.number_float;
2064 : m_type(
std::move(other.m_type)),
2065 m_value(
std::move(other.m_value))
2068 other.assert_invariant();
2071 other.m_type = value_t::null;
2101 std::is_nothrow_move_constructible<value_t>::value and
2102 std::is_nothrow_move_assignable<value_t>::value and
2103 std::is_nothrow_move_constructible<json_value>::value and
2104 std::is_nothrow_move_assignable<json_value>::value
2108 other.assert_invariant();
2111 swap(m_type, other.m_type);
2112 swap(m_value, other.m_value);
2139 case value_t::object:
2141 AllocatorType<object_t> alloc;
2142 alloc.destroy(m_value.object);
2143 alloc.deallocate(m_value.object, 1);
2147 case value_t::array:
2149 AllocatorType<array_t> alloc;
2150 alloc.destroy(m_value.array);
2151 alloc.deallocate(m_value.array, 1);
2155 case value_t::string:
2157 AllocatorType<string_t> alloc;
2158 alloc.destroy(m_value.string);
2159 alloc.deallocate(m_value.string, 1);
2207 std::stringstream ss;
2209 ss.imbue(std::locale::classic());
2215 ss.precision(std::numeric_limits<double>::digits10);
2219 dump(ss,
true, static_cast<unsigned int>(indent));
2279 return is_null() or is_string() or is_boolean() or is_number();
2306 return is_array() or is_object();
2328 return m_type == value_t::null;
2350 return m_type == value_t::boolean;
2380 return is_number_integer() or is_number_float();
2409 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2437 return m_type == value_t::number_unsigned;
2465 return m_type == value_t::number_float;
2487 return m_type == value_t::object;
2509 return m_type == value_t::array;
2531 return m_type == value_t::string;
2558 return m_type == value_t::discarded;
2592 template<
class T,
typename std::enable_if<
2593 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2594 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2595 T get_impl(T* )
const 2599 return T(m_value.object->begin(), m_value.object->end());
2602 throw std::domain_error(
"type must be object, but is " + type_name());
2610 return *(m_value.object);
2613 throw std::domain_error(
"type must be object, but is " + type_name());
2617 template<
class T,
typename std::enable_if<
2618 std::is_convertible<basic_json_t, typename T::value_type>::value and
2619 not std::is_same<basic_json_t, typename T::value_type>::value and
2620 not std::is_arithmetic<T>::value and
2621 not std::is_convertible<std::string, T>::value and
2622 not has_mapped_type<T>::value,
int>::type = 0>
2623 T get_impl(T* )
const 2628 std::transform(m_value.array->begin(), m_value.array->end(),
2629 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2631 return i.
get<
typename T::value_type>();
2636 throw std::domain_error(
"type must be array, but is " + type_name());
2640 template<
class T,
typename std::enable_if<
2641 std::is_convertible<basic_json_t, T>::value and
2642 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2643 std::vector<T> get_impl(std::vector<T>* )
const 2647 std::vector<T> to_vector;
2648 to_vector.reserve(m_value.array->size());
2649 std::transform(m_value.array->begin(), m_value.array->end(),
2650 std::inserter(to_vector, to_vector.end()), [](
basic_json i)
2657 throw std::domain_error(
"type must be array, but is " + type_name());
2661 template<
class T,
typename std::enable_if<
2662 std::is_same<basic_json, typename T::value_type>::value and
2663 not has_mapped_type<T>::value,
int>::type = 0>
2664 T get_impl(T* )
const 2668 return T(m_value.array->begin(), m_value.array->end());
2671 throw std::domain_error(
"type must be array, but is " + type_name());
2679 return *(m_value.array);
2682 throw std::domain_error(
"type must be array, but is " + type_name());
2686 template<
typename T,
typename std::enable_if<
2687 std::is_convertible<string_t, T>::value,
int>::type = 0>
2688 T get_impl(T* )
const 2692 return *m_value.string;
2695 throw std::domain_error(
"type must be string, but is " + type_name());
2699 template<
typename T,
typename std::enable_if<
2700 std::is_arithmetic<T>::value,
int>::type = 0>
2701 T get_impl(T* )
const 2705 case value_t::number_integer:
2707 return static_cast<T
>(m_value.number_integer);
2710 case value_t::number_unsigned:
2712 return static_cast<T
>(m_value.number_unsigned);
2715 case value_t::number_float:
2717 return static_cast<T
>(m_value.number_float);
2722 throw std::domain_error(
"type must be number, but is " + type_name());
2732 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2738 return is_object() ? m_value.object :
nullptr;
2744 return is_object() ? m_value.object :
nullptr;
2750 return is_array() ? m_value.array :
nullptr;
2754 constexpr
const array_t* get_impl_ptr(
const array_t* )
const noexcept
2756 return is_array() ? m_value.array :
nullptr;
2762 return is_string() ? m_value.string :
nullptr;
2768 return is_string() ? m_value.string :
nullptr;
2774 return is_boolean() ? &m_value.boolean :
nullptr;
2780 return is_boolean() ? &m_value.boolean :
nullptr;
2786 return is_number_integer() ? &m_value.number_integer :
nullptr;
2792 return is_number_integer() ? &m_value.number_integer :
nullptr;
2798 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2804 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2810 return is_number_float() ? &m_value.number_float :
nullptr;
2816 return is_number_float() ? &m_value.number_float :
nullptr;
2830 template<
typename ReferenceType,
typename ThisType>
2831 static ReferenceType get_ref_impl(ThisType& obj)
2834 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2837 auto ptr = obj.template get_ptr<PointerType>();
2844 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2887 template<
typename ValueType,
typename std::enable_if<
2888 not std::is_pointer<ValueType>::value,
int>::type = 0>
2889 ValueType
get()
const 2891 return get_impl(static_cast<ValueType*>(
nullptr));
2921 template<
typename PointerType,
typename std::enable_if<
2922 std::is_pointer<PointerType>::value,
int>::type = 0>
2923 PointerType
get() noexcept
2926 return get_ptr<PointerType>();
2933 template<
typename PointerType,
typename std::enable_if<
2934 std::is_pointer<PointerType>::value,
int>::type = 0>
2935 constexpr
const PointerType
get()
const noexcept
2938 return get_ptr<PointerType>();
2967 template<
typename PointerType,
typename std::enable_if<
2968 std::is_pointer<PointerType>::value,
int>::type = 0>
2972 using pointee_t =
typename std::remove_const<
typename 2973 std::remove_pointer<
typename 2974 std::remove_const<PointerType>::type>::type>::type;
2977 std::is_same<object_t, pointee_t>::value
2978 or std::is_same<array_t, pointee_t>::value
2979 or std::is_same<string_t, pointee_t>::value
2980 or std::is_same<boolean_t, pointee_t>::value
2981 or std::is_same<number_integer_t, pointee_t>::value
2982 or std::is_same<number_unsigned_t, pointee_t>::value
2983 or std::is_same<number_float_t, pointee_t>::value
2984 ,
"incompatible pointer type");
2987 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2994 template<
typename PointerType,
typename std::enable_if<
2995 std::is_pointer<PointerType>::value and
2996 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
2997 constexpr
const PointerType
get_ptr() const noexcept
3000 using pointee_t =
typename std::remove_const<
typename 3001 std::remove_pointer<
typename 3002 std::remove_const<PointerType>::type>::type>::type;
3005 std::is_same<object_t, pointee_t>::value
3006 or std::is_same<array_t, pointee_t>::value
3007 or std::is_same<string_t, pointee_t>::value
3008 or std::is_same<boolean_t, pointee_t>::value
3009 or std::is_same<number_integer_t, pointee_t>::value
3010 or std::is_same<number_unsigned_t, pointee_t>::value
3011 or std::is_same<number_float_t, pointee_t>::value
3012 ,
"incompatible pointer type");
3015 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3044 template<
typename ReferenceType,
typename std::enable_if<
3045 std::is_reference<ReferenceType>::value,
int>::type = 0>
3049 return get_ref_impl<ReferenceType>(*this);
3056 template<
typename ReferenceType,
typename std::enable_if<
3057 std::is_reference<ReferenceType>::value and
3058 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3062 return get_ref_impl<ReferenceType>(*this);
3093 template <
typename ValueType,
typename std::enable_if <
3094 not std::is_pointer<ValueType>::value and
3095 not std::is_same<ValueType, typename string_t::value_type>::value
3096 #ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015 3097 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3100 operator ValueType()
const 3103 return get<ValueType>();
3146 return m_value.
array->
at(idx);
3148 catch (std::out_of_range&)
3151 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3156 throw std::domain_error(
"cannot use at() with " + type_name());
3189 return m_value.
array->
at(idx);
3191 catch (std::out_of_range&)
3194 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3199 throw std::domain_error(
"cannot use at() with " + type_name());
3238 catch (std::out_of_range&)
3241 throw std::out_of_range(
"key '" + key +
"' not found");
3246 throw std::domain_error(
"cannot use at() with " + type_name());
3285 catch (std::out_of_range&)
3288 throw std::out_of_range(
"key '" + key +
"' not found");
3293 throw std::domain_error(
"cannot use at() with " + type_name());
3327 m_type = value_t::array;
3328 m_value.
array = create<array_t>();
3336 if (idx >= m_value.array->size())
3338 m_value.array->insert(m_value.array->end(),
3339 idx - m_value.array->size() + 1,
3343 return m_value.array->operator[](idx);
3346 throw std::domain_error(
"cannot use operator[] with " + type_name());
3373 return m_value.
array->operator[](idx);
3376 throw std::domain_error(
"cannot use operator[] with " + type_name());
3411 m_type = value_t::object;
3412 m_value.
object = create<object_t>();
3419 return m_value.object->operator[](key);
3422 throw std::domain_error(
"cannot use operator[] with " + type_name());
3460 assert(m_value.object->find(key) != m_value.object->end());
3464 throw std::domain_error(
"cannot use operator[] with " + type_name());
3494 template<
typename T, std::
size_t n>
3497 return operator[](static_cast<const T>(key));
3529 template<
typename T, std::
size_t n>
3532 return operator[](static_cast<const T>(key));
3562 template<
typename T>
3568 m_type = value_t::object;
3569 m_value = value_t::object;
3576 return m_value.object->operator[](key);
3579 throw std::domain_error(
"cannot use operator[] with " + type_name());
3612 template<
typename T>
3618 assert(m_value.object->find(key) != m_value.object->end());
3622 throw std::domain_error(
"cannot use operator[] with " + type_name());
3673 template<
class ValueType,
typename std::enable_if<
3674 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3675 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3681 const auto it = find(key);
3687 return default_value;
3691 throw std::domain_error(
"cannot use value() with " + type_name());
3699 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3701 return value(key,
string_t(default_value));
3745 template<
class ValueType,
typename std::enable_if<
3746 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3755 return ptr.get_checked(
this);
3757 catch (std::out_of_range&)
3759 return default_value;
3763 throw std::domain_error(
"cannot use value() with " + type_name());
3772 return value(ptr,
string_t(default_value));
3905 template<
class IteratorType,
typename std::enable_if<
3906 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3907 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3912 if (
this != pos.m_object)
3914 throw std::domain_error(
"iterator does not fit current value");
3917 IteratorType result = end();
3921 case value_t::boolean:
3922 case value_t::number_float:
3923 case value_t::number_integer:
3924 case value_t::number_unsigned:
3925 case value_t::string:
3927 if (not pos.m_it.primitive_iterator.is_begin())
3929 throw std::out_of_range(
"iterator out of range");
3934 AllocatorType<string_t> alloc;
3935 alloc.destroy(m_value.string);
3936 alloc.deallocate(m_value.string, 1);
3937 m_value.string =
nullptr;
3940 m_type = value_t::null;
3945 case value_t::object:
3947 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3951 case value_t::array:
3953 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3959 throw std::domain_error(
"cannot use erase() with " + type_name());
4012 template<
class IteratorType,
typename std::enable_if<
4013 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4014 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4016 IteratorType
erase(IteratorType first, IteratorType last)
4019 if (
this != first.m_object or
this != last.m_object)
4021 throw std::domain_error(
"iterators do not fit current value");
4024 IteratorType result = end();
4028 case value_t::boolean:
4029 case value_t::number_float:
4030 case value_t::number_integer:
4031 case value_t::number_unsigned:
4032 case value_t::string:
4034 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4036 throw std::out_of_range(
"iterators out of range");
4041 AllocatorType<string_t> alloc;
4042 alloc.destroy(m_value.string);
4043 alloc.deallocate(m_value.string, 1);
4044 m_value.string =
nullptr;
4047 m_type = value_t::null;
4052 case value_t::object:
4054 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4055 last.m_it.object_iterator);
4059 case value_t::array:
4061 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4062 last.m_it.array_iterator);
4068 throw std::domain_error(
"cannot use erase() with " + type_name());
4109 return m_value.object->erase(key);
4112 throw std::domain_error(
"cannot use erase() with " + type_name());
4146 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4149 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4153 throw std::domain_error(
"cannot use erase() with " + type_name());
4191 auto result = end();
4195 result.m_it.object_iterator = m_value.object->find(key);
4207 auto result = cend();
4211 result.m_it.object_iterator = m_value.object->find(key);
4241 return is_object() ? m_value.object->count(key) : 0;
4529 template<
typename IteratorType>
class iteration_proxy;
4545 return iteration_proxy<iterator>(cont);
4553 return iteration_proxy<const_iterator>(cont);
4613 case value_t::array:
4616 return m_value.array->empty();
4619 case value_t::object:
4622 return m_value.object->empty();
4681 case value_t::array:
4684 return m_value.array->size();
4687 case value_t::object:
4690 return m_value.object->size();
4741 case value_t::array:
4744 return m_value.array->max_size();
4747 case value_t::object:
4750 return m_value.object->max_size();
4797 case value_t::number_integer:
4799 m_value.number_integer = 0;
4803 case value_t::number_unsigned:
4805 m_value.number_unsigned = 0;
4809 case value_t::number_float:
4811 m_value.number_float = 0.0;
4815 case value_t::boolean:
4817 m_value.boolean =
false;
4821 case value_t::string:
4823 m_value.string->clear();
4827 case value_t::array:
4829 m_value.array->clear();
4833 case value_t::object:
4835 m_value.object->clear();
4869 if (not(is_null() or is_array()))
4871 throw std::domain_error(
"cannot use push_back() with " + type_name());
4877 m_type = value_t::array;
4878 m_value = value_t::array;
4883 m_value.array->push_back(std::move(val));
4885 val.m_type = value_t::null;
4894 push_back(std::move(val));
4905 if (not(is_null() or is_array()))
4907 throw std::domain_error(
"cannot use push_back() with " + type_name());
4913 m_type = value_t::array;
4914 m_value = value_t::array;
4919 m_value.array->push_back(val);
4955 if (not(is_null() or is_object()))
4957 throw std::domain_error(
"cannot use push_back() with " + type_name());
4963 m_type = value_t::object;
4964 m_value = value_t::object;
4969 m_value.object->insert(val);
5009 if (is_object() and init.size() == 2 and init.begin()->is_string())
5011 const string_t key = *init.begin();
5012 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5051 template<
class... Args>
5055 if (not(is_null() or is_array()))
5057 throw std::domain_error(
"cannot use emplace_back() with " + type_name());
5063 m_type = value_t::array;
5064 m_value = value_t::array;
5069 m_value.array->emplace_back(std::forward<Args>(args)...);
5099 template<
class... Args>
5100 std::pair<iterator, bool>
emplace(Args&& ... args)
5103 if (not(is_null() or is_object()))
5105 throw std::domain_error(
"cannot use emplace() with " + type_name());
5111 m_type = value_t::object;
5112 m_value = value_t::object;
5117 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5120 it.m_it.object_iterator = res.first;
5123 return {it, res.second};
5154 if (pos.m_object !=
this)
5156 throw std::domain_error(
"iterator does not fit current value");
5161 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5165 throw std::domain_error(
"cannot use insert() with " + type_name());
5174 return insert(pos, val);
5207 if (pos.m_object !=
this)
5209 throw std::domain_error(
"iterator does not fit current value");
5214 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5218 throw std::domain_error(
"cannot use insert() with " + type_name());
5256 throw std::domain_error(
"cannot use insert() with " + type_name());
5260 if (pos.m_object !=
this)
5262 throw std::domain_error(
"iterator does not fit current value");
5266 if (first.m_object != last.m_object)
5268 throw std::domain_error(
"iterators do not fit");
5271 if (first.m_object ==
this or last.m_object ==
this)
5273 throw std::domain_error(
"passed iterators may not belong to container");
5278 result.m_it.array_iterator = m_value.array->insert(
5279 pos.m_it.array_iterator,
5280 first.m_it.array_iterator,
5281 last.m_it.array_iterator);
5314 throw std::domain_error(
"cannot use insert() with " + type_name());
5318 if (pos.m_object !=
this)
5320 throw std::domain_error(
"iterator does not fit current value");
5325 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5347 std::is_nothrow_move_constructible<value_t>::value and
5348 std::is_nothrow_move_assignable<value_t>::value and
5349 std::is_nothrow_move_constructible<json_value>::value and
5350 std::is_nothrow_move_assignable<json_value>::value
5353 std::swap(m_type, other.m_type);
5354 std::swap(m_value, other.m_value);
5383 std::swap(*(m_value.array), other);
5387 throw std::domain_error(
"cannot use swap() with " + type_name());
5416 std::swap(*(m_value.object), other);
5420 throw std::domain_error(
"cannot use swap() with " + type_name());
5449 std::swap(*(m_value.string), other);
5453 throw std::domain_error(
"cannot use swap() with " + type_name());
5479 static constexpr std::array<uint8_t, 8> order = {{
5492 if (lhs == value_t::discarded or rhs == value_t::discarded)
5497 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5526 const auto lhs_type = lhs.type();
5527 const auto rhs_type = rhs.type();
5529 if (lhs_type == rhs_type)
5533 case value_t::array:
5535 return *lhs.m_value.array == *rhs.m_value.array;
5537 case value_t::object:
5539 return *lhs.m_value.object == *rhs.m_value.object;
5545 case value_t::string:
5547 return *lhs.m_value.string == *rhs.m_value.string;
5549 case value_t::boolean:
5551 return lhs.m_value.boolean == rhs.m_value.boolean;
5553 case value_t::number_integer:
5555 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5557 case value_t::number_unsigned:
5559 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5561 case value_t::number_float:
5563 return lhs.m_value.number_float == rhs.m_value.number_float;
5571 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5573 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5575 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5577 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5579 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5581 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5583 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5585 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5587 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5589 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5591 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5593 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5649 return not (lhs == rhs);
5681 return not v.is_null();
5710 const auto lhs_type = lhs.type();
5711 const auto rhs_type = rhs.type();
5713 if (lhs_type == rhs_type)
5717 case value_t::array:
5719 return *lhs.m_value.array < *rhs.m_value.array;
5721 case value_t::object:
5723 return *lhs.m_value.object < *rhs.m_value.object;
5729 case value_t::string:
5731 return *lhs.m_value.string < *rhs.m_value.string;
5733 case value_t::boolean:
5735 return lhs.m_value.boolean < rhs.m_value.boolean;
5737 case value_t::number_integer:
5739 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5741 case value_t::number_unsigned:
5743 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5745 case value_t::number_float:
5747 return lhs.m_value.number_float < rhs.m_value.number_float;
5755 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5757 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5759 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5761 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5763 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5765 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5767 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5769 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5771 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5773 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5775 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5777 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5783 return operator<(lhs_type, rhs_type);
5805 return not (rhs < lhs);
5827 return not (lhs <= rhs);
5849 return not (lhs < rhs);
5891 const bool pretty_print = (o.width() > 0);
5892 const auto indentation = (pretty_print ? o.width() : 0);
5898 const auto old_locale = o.imbue(std::locale::classic());
5905 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5908 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5911 o.imbue(old_locale);
5912 o.precision(old_precision);
5962 template<
class T, std::
size_t N>
5967 return parse(std::begin(array), std::end(array), cb);
5997 template<
typename CharT,
typename std::enable_if<
5998 std::is_pointer<CharT>::value and
5999 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6000 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
6004 return parser(reinterpret_cast<const char*>(s), cb).
parse();
6034 return parser(i, cb).
parse();
6043 return parser(i, cb).
parse();
6087 template<
class IteratorType,
typename std::enable_if<
6089 std::random_access_iterator_tag,
6090 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6096 assert(std::accumulate(first, last, std::pair<bool, int>(
true, 0),
6097 [&first](std::pair<bool, int> res, decltype(*first) val)
6099 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6104 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6105 "each element in the iterator range must have the size of 1 byte");
6109 if (std::distance(first, last) <= 0)
6111 return parser(
"").parse();
6114 return parser(first, last, cb).parse();
6157 template<
class ContiguousContainer,
typename std::enable_if<
6158 not std::is_pointer<ContiguousContainer>::value and
6160 std::random_access_iterator_tag,
6161 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6167 return parse(std::begin(c), std::end(c), cb);
6195 j = parser(i).
parse();
6205 j = parser(i).
parse();
6219 template<
typename T>
6220 static void add_to_vector(std::vector<uint8_t>& vec,
size_t bytes,
const T number)
6222 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6228 vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6229 vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6230 vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6231 vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6237 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6238 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6244 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6250 vec.push_back(static_cast<uint8_t>(number & 0xff));
6292 template<
typename T>
6293 static T get_from_vector(
const std::vector<uint8_t>& vec,
const size_t current_index)
6295 if (current_index +
sizeof(T) + 1 > vec.size())
6297 throw std::out_of_range(
"cannot read " + std::to_string(
sizeof(T)) +
" bytes from vector");
6301 auto* ptr =
reinterpret_cast<uint8_t*
>(&result);
6302 for (
size_t i = 0; i <
sizeof(T); ++i)
6304 *ptr++ = vec[current_index +
sizeof(T) - i];
6319 static void to_msgpack_internal(
const basic_json& j, std::vector<uint8_t>& v)
6330 case value_t::boolean:
6333 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6337 case value_t::number_integer:
6339 if (j.m_value.number_integer >= 0)
6345 if (j.m_value.number_unsigned < 128)
6348 add_to_vector(v, 1, j.m_value.number_unsigned);
6350 else if (j.m_value.number_unsigned <= UINT8_MAX)
6354 add_to_vector(v, 1, j.m_value.number_unsigned);
6356 else if (j.m_value.number_unsigned <= UINT16_MAX)
6360 add_to_vector(v, 2, j.m_value.number_unsigned);
6362 else if (j.m_value.number_unsigned <= UINT32_MAX)
6366 add_to_vector(v, 4, j.m_value.number_unsigned);
6368 else if (j.m_value.number_unsigned <= UINT64_MAX)
6372 add_to_vector(v, 8, j.m_value.number_unsigned);
6377 if (j.m_value.number_integer >= -32)
6380 add_to_vector(v, 1, j.m_value.number_integer);
6382 else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6386 add_to_vector(v, 1, j.m_value.number_integer);
6388 else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6392 add_to_vector(v, 2, j.m_value.number_integer);
6394 else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6398 add_to_vector(v, 4, j.m_value.number_integer);
6400 else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6404 add_to_vector(v, 8, j.m_value.number_integer);
6410 case value_t::number_unsigned:
6412 if (j.m_value.number_unsigned < 128)
6415 add_to_vector(v, 1, j.m_value.number_unsigned);
6417 else if (j.m_value.number_unsigned <= UINT8_MAX)
6421 add_to_vector(v, 1, j.m_value.number_unsigned);
6423 else if (j.m_value.number_unsigned <= UINT16_MAX)
6427 add_to_vector(v, 2, j.m_value.number_unsigned);
6429 else if (j.m_value.number_unsigned <= UINT32_MAX)
6433 add_to_vector(v, 4, j.m_value.number_unsigned);
6435 else if (j.m_value.number_unsigned <= UINT64_MAX)
6439 add_to_vector(v, 8, j.m_value.number_unsigned);
6444 case value_t::number_float:
6448 const auto* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6449 for (
size_t i = 0; i < 8; ++i)
6451 v.push_back(helper[7 - i]);
6456 case value_t::string:
6458 const auto N = j.m_value.string->size();
6462 v.push_back(static_cast<uint8_t>(0xa0 | N));
6468 add_to_vector(v, 1, N);
6470 else if (N <= 65535)
6474 add_to_vector(v, 2, N);
6476 else if (N <= 4294967295)
6480 add_to_vector(v, 4, N);
6484 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6485 std::back_inserter(v));
6489 case value_t::array:
6491 const auto N = j.m_value.array->size();
6495 v.push_back(static_cast<uint8_t>(0x90 | N));
6497 else if (N <= 0xffff)
6501 add_to_vector(v, 2, N);
6503 else if (N <= 0xffffffff)
6507 add_to_vector(v, 4, N);
6511 for (
const auto& el : *j.m_value.array)
6513 to_msgpack_internal(el, v);
6518 case value_t::object:
6520 const auto N = j.m_value.object->size();
6524 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6526 else if (N <= 65535)
6530 add_to_vector(v, 2, N);
6532 else if (N <= 4294967295)
6536 add_to_vector(v, 4, N);
6540 for (
const auto& el : *j.m_value.object)
6542 to_msgpack_internal(el.first, v);
6543 to_msgpack_internal(el.second, v);
6565 static void to_cbor_internal(
const basic_json& j, std::vector<uint8_t>& v)
6575 case value_t::boolean:
6577 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6581 case value_t::number_integer:
6583 if (j.m_value.number_integer >= 0)
6588 if (j.m_value.number_integer <= 0x17)
6590 add_to_vector(v, 1, j.m_value.number_integer);
6592 else if (j.m_value.number_integer <= UINT8_MAX)
6596 add_to_vector(v, 1, j.m_value.number_integer);
6598 else if (j.m_value.number_integer <= UINT16_MAX)
6602 add_to_vector(v, 2, j.m_value.number_integer);
6604 else if (j.m_value.number_integer <= UINT32_MAX)
6608 add_to_vector(v, 4, j.m_value.number_integer);
6614 add_to_vector(v, 8, j.m_value.number_integer);
6621 const auto positive_number = -1 - j.m_value.number_integer;
6622 if (j.m_value.number_integer >= -24)
6624 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6626 else if (positive_number <= UINT8_MAX)
6630 add_to_vector(v, 1, positive_number);
6632 else if (positive_number <= UINT16_MAX)
6636 add_to_vector(v, 2, positive_number);
6638 else if (positive_number <= UINT32_MAX)
6642 add_to_vector(v, 4, positive_number);
6648 add_to_vector(v, 8, positive_number);
6654 case value_t::number_unsigned:
6656 if (j.m_value.number_unsigned <= 0x17)
6658 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6660 else if (j.m_value.number_unsigned <= 0xff)
6664 add_to_vector(v, 1, j.m_value.number_unsigned);
6666 else if (j.m_value.number_unsigned <= 0xffff)
6670 add_to_vector(v, 2, j.m_value.number_unsigned);
6672 else if (j.m_value.number_unsigned <= 0xffffffff)
6676 add_to_vector(v, 4, j.m_value.number_unsigned);
6678 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6682 add_to_vector(v, 8, j.m_value.number_unsigned);
6687 case value_t::number_float:
6691 const auto* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6692 for (
size_t i = 0; i < 8; ++i)
6694 v.push_back(helper[7 - i]);
6699 case value_t::string:
6701 const auto N = j.m_value.string->size();
6704 v.push_back(0x60 + N);
6709 add_to_vector(v, 1, N);
6711 else if (N <= 0xffff)
6714 add_to_vector(v, 2, N);
6716 else if (N <= 0xffffffff)
6719 add_to_vector(v, 4, N);
6722 else if (N <= 0xffffffffffffffff)
6725 add_to_vector(v, 8, N);
6730 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6731 std::back_inserter(v));
6735 case value_t::array:
6737 const auto N = j.m_value.array->size();
6740 v.push_back(0x80 + N);
6745 add_to_vector(v, 1, N);
6747 else if (N <= 0xffff)
6750 add_to_vector(v, 2, N);
6752 else if (N <= 0xffffffff)
6755 add_to_vector(v, 4, N);
6758 else if (N <= 0xffffffffffffffff)
6761 add_to_vector(v, 8, N);
6766 for (
const auto& el : *j.m_value.array)
6768 to_cbor_internal(el, v);
6773 case value_t::object:
6775 const auto N = j.m_value.object->size();
6778 v.push_back(0xa0 + N);
6783 add_to_vector(v, 1, N);
6785 else if (N <= 0xffff)
6788 add_to_vector(v, 2, N);
6790 else if (N <= 0xffffffff)
6793 add_to_vector(v, 4, N);
6796 else if (N <= 0xffffffffffffffff)
6799 add_to_vector(v, 8, N);
6804 for (
const auto& el : *j.m_value.object)
6806 to_cbor_internal(el.first, v);
6807 to_cbor_internal(el.second, v);
6842 static void check_length(
const size_t size,
const size_t len,
const size_t offset)
6845 if (len > size or offset > size)
6847 throw std::out_of_range(
"len out of range");
6851 if ((size > (std::numeric_limits<size_t>::max() - offset)))
6853 throw std::out_of_range(
"len+offset out of range");
6857 if (len + offset > size)
6859 throw std::out_of_range(
"len+offset out of range");
6877 static basic_json from_msgpack_internal(
const std::vector<uint8_t>& v,
size_t& idx)
6880 check_length(v.size(), 1, idx);
6883 const size_t current_idx = idx++;
6885 if (v[current_idx] <= 0xbf)
6887 if (v[current_idx] <= 0x7f)
6889 return v[current_idx];
6891 if (v[current_idx] <= 0x8f)
6894 const size_t len = v[current_idx] & 0x0f;
6895 for (
size_t i = 0; i < len; ++i)
6897 std::string key = from_msgpack_internal(v, idx);
6898 result[key] = from_msgpack_internal(v, idx);
6902 else if (v[current_idx] <= 0x9f)
6905 const size_t len = v[current_idx] & 0x0f;
6906 for (
size_t i = 0; i < len; ++i)
6908 result.
push_back(from_msgpack_internal(v, idx));
6914 const size_t len = v[current_idx] & 0x1f;
6915 const size_t offset = current_idx + 1;
6917 check_length(v.size(), len, offset);
6918 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
6921 else if (v[current_idx] >= 0xe0)
6923 return static_cast<int8_t
>(v[current_idx]);
6927 switch (v[current_idx])
6931 return value_t::null;
6948 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
6950 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v.at(current_idx + 1 + byte);
6952 idx +=
sizeof(float);
6960 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
6962 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v.at(current_idx + 1 + byte);
6964 idx +=
sizeof(double);
6971 return get_from_vector<uint8_t>(v, current_idx);
6977 return get_from_vector<uint16_t>(v, current_idx);
6983 return get_from_vector<uint32_t>(v, current_idx);
6989 return get_from_vector<uint64_t>(v, current_idx);
6995 return get_from_vector<int8_t>(v, current_idx);
7001 return get_from_vector<int16_t>(v, current_idx);
7007 return get_from_vector<int32_t>(v, current_idx);
7013 return get_from_vector<int64_t>(v, current_idx);
7018 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7019 const size_t offset = current_idx + 2;
7021 check_length(v.size(), len, offset);
7022 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7027 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7028 const size_t offset = current_idx + 3;
7030 check_length(v.size(), len, offset);
7031 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7036 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7037 const size_t offset = current_idx + 5;
7039 check_length(v.size(), len, offset);
7040 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7046 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7048 for (
size_t i = 0; i < len; ++i)
7050 result.
push_back(from_msgpack_internal(v, idx));
7058 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7060 for (
size_t i = 0; i < len; ++i)
7062 result.
push_back(from_msgpack_internal(v, idx));
7070 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7072 for (
size_t i = 0; i < len; ++i)
7074 std::string key = from_msgpack_internal(v, idx);
7075 result[key] = from_msgpack_internal(v, idx);
7083 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7085 for (
size_t i = 0; i < len; ++i)
7087 std::string key = from_msgpack_internal(v, idx);
7088 result[key] = from_msgpack_internal(v, idx);
7095 throw std::invalid_argument(
"error parsing a msgpack @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx])));
7115 static basic_json from_cbor_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7118 const size_t current_idx = idx++;
7120 switch (v.at(current_idx))
7148 return v[current_idx];
7154 return get_from_vector<uint8_t>(v, current_idx);
7160 return get_from_vector<uint16_t>(v, current_idx);
7166 return get_from_vector<uint32_t>(v, current_idx);
7172 return get_from_vector<uint64_t>(v, current_idx);
7201 return static_cast<int8_t
>(0x20 - 1 - v[current_idx]);
7208 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7214 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7220 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7226 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7255 const auto len =
static_cast<size_t>(v[current_idx] - 0x60);
7256 const size_t offset = current_idx + 1;
7258 check_length(v.size(), len, offset);
7259 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7264 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7265 const size_t offset = current_idx + 2;
7267 check_length(v.size(), len, offset);
7268 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7273 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7274 const size_t offset = current_idx + 3;
7276 check_length(v.size(), len, offset);
7277 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7282 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7283 const size_t offset = current_idx + 5;
7285 check_length(v.size(), len, offset);
7286 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7291 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7292 const size_t offset = current_idx + 9;
7294 check_length(v.size(), len, offset);
7295 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7301 while (v.at(idx) != 0xff)
7303 string_t s = from_cbor_internal(v, idx);
7338 const auto len =
static_cast<size_t>(v[current_idx] - 0x80);
7339 for (
size_t i = 0; i < len; ++i)
7341 result.
push_back(from_cbor_internal(v, idx));
7349 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7351 for (
size_t i = 0; i < len; ++i)
7353 result.
push_back(from_cbor_internal(v, idx));
7361 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7363 for (
size_t i = 0; i < len; ++i)
7365 result.
push_back(from_cbor_internal(v, idx));
7373 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7375 for (
size_t i = 0; i < len; ++i)
7377 result.
push_back(from_cbor_internal(v, idx));
7385 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7387 for (
size_t i = 0; i < len; ++i)
7389 result.
push_back(from_cbor_internal(v, idx));
7397 while (v.at(idx) != 0xff)
7399 result.
push_back(from_cbor_internal(v, idx));
7433 const auto len =
static_cast<size_t>(v[current_idx] - 0xa0);
7434 for (
size_t i = 0; i < len; ++i)
7436 std::string key = from_cbor_internal(v, idx);
7437 result[key] = from_cbor_internal(v, idx);
7445 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7447 for (
size_t i = 0; i < len; ++i)
7449 std::string key = from_cbor_internal(v, idx);
7450 result[key] = from_cbor_internal(v, idx);
7458 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7460 for (
size_t i = 0; i < len; ++i)
7462 std::string key = from_cbor_internal(v, idx);
7463 result[key] = from_cbor_internal(v, idx);
7471 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7473 for (
size_t i = 0; i < len; ++i)
7475 std::string key = from_cbor_internal(v, idx);
7476 result[key] = from_cbor_internal(v, idx);
7484 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7486 for (
size_t i = 0; i < len; ++i)
7488 std::string key = from_cbor_internal(v, idx);
7489 result[key] = from_cbor_internal(v, idx);
7497 while (v.at(idx) != 0xff)
7499 std::string key = from_cbor_internal(v, idx);
7500 result[key] = from_cbor_internal(v, idx);
7519 return value_t::null;
7533 const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7534 const int exp = (half >> 10) & 0x1f;
7535 const int mant = half & 0x3ff;
7539 val = std::ldexp(mant, -24);
7543 val = std::ldexp(mant + 1024, exp - 25);
7547 val = mant == 0 ? INFINITY : NAN;
7549 return (half & 0x8000) != 0 ? -val : val;
7556 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7558 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v.at(current_idx + 1 + byte);
7560 idx +=
sizeof(float);
7568 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7570 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v.at(current_idx + 1 + byte);
7572 idx +=
sizeof(double);
7578 throw std::invalid_argument(
"error parsing a CBOR @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx])));
7606 std::vector<uint8_t> result;
7607 to_msgpack_internal(j, result);
7636 return from_msgpack_internal(v, i);
7662 std::vector<uint8_t> result;
7663 to_cbor_internal(j, result);
7693 return from_cbor_internal(v, i);
7715 std::string type_name()
const 7721 case value_t::object:
7723 case value_t::array:
7725 case value_t::string:
7727 case value_t::boolean:
7729 case value_t::discarded:
7744 static std::size_t extra_space(
const string_t& s) noexcept
7746 return std::accumulate(s.begin(), s.end(),
size_t{},
7747 [](
size_t res,
typename string_t::value_type c)
7765 if (c >= 0x00 and c <= 0x1f)
7792 const auto space = extra_space(s);
7799 string_t result(s.size() + space,
'\\');
7800 std::size_t pos = 0;
7802 for (
const auto& c : s)
7809 result[pos + 1] =
'"';
7825 result[pos + 1] =
'b';
7833 result[pos + 1] =
'f';
7841 result[pos + 1] =
'n';
7849 result[pos + 1] =
'r';
7857 result[pos + 1] =
't';
7864 if (c >= 0x00 and c <= 0x1f)
7868 static const char hexify[16] =
7870 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
7871 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 7876 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
7914 void dump(std::ostream& o,
7915 const bool pretty_print,
7916 const unsigned int indent_step,
7917 const unsigned int current_indent = 0)
const 7920 unsigned int new_indent = current_indent;
7924 case value_t::object:
7926 if (m_value.object->empty())
7937 new_indent += indent_step;
7941 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
7943 if (i != m_value.object->cbegin())
7945 o << (pretty_print ?
",\n" :
",");
7947 o <<
string_t(new_indent,
' ') <<
"\"" 7948 << escape_string(i->first) <<
"\":" 7949 << (pretty_print ?
" " :
"");
7950 i->second.dump(o, pretty_print, indent_step, new_indent);
7956 new_indent -= indent_step;
7960 o <<
string_t(new_indent,
' ') +
"}";
7964 case value_t::array:
7966 if (m_value.array->empty())
7977 new_indent += indent_step;
7981 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
7983 if (i != m_value.array->cbegin())
7985 o << (pretty_print ?
",\n" :
",");
7988 i->dump(o, pretty_print, indent_step, new_indent);
7994 new_indent -= indent_step;
7998 o <<
string_t(new_indent,
' ') <<
"]";
8002 case value_t::string:
8004 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
8008 case value_t::boolean:
8010 o << (m_value.boolean ?
"true" :
"false");
8014 case value_t::number_integer:
8016 o << m_value.number_integer;
8020 case value_t::number_unsigned:
8022 o << m_value.number_unsigned;
8026 case value_t::number_float:
8028 if (m_value.number_float == 0)
8031 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
8035 o << m_value.number_float;
8040 case value_t::discarded:
8060 value_t m_type = value_t::null;
8063 json_value m_value = {};
8080 class primitive_iterator_t
8084 void set_begin() noexcept
8090 void set_end() noexcept
8096 constexpr
bool is_begin()
const noexcept
8098 return (m_it == begin_value);
8102 constexpr
bool is_end()
const noexcept
8104 return (m_it == end_value);
8124 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8134 struct internal_iterator
8137 typename object_t::iterator object_iterator;
8139 typename array_t::iterator array_iterator;
8141 primitive_iterator_t primitive_iterator;
8144 internal_iterator() noexcept
8145 : object_iterator(), array_iterator(), primitive_iterator()
8150 template<
typename IteratorType>
8151 class iteration_proxy
8155 class iteration_proxy_internal
8159 IteratorType anchor;
8161 size_t array_index = 0;
8164 explicit iteration_proxy_internal(IteratorType it) noexcept
8169 iteration_proxy_internal& operator*()
8175 iteration_proxy_internal& operator++()
8184 bool operator!= (
const iteration_proxy_internal& o)
const 8186 return anchor != o.anchor;
8192 assert(anchor.m_object !=
nullptr);
8194 switch (anchor.m_object->type())
8197 case value_t::array:
8199 return std::to_string(array_index);
8203 case value_t::object:
8205 return anchor.key();
8217 typename IteratorType::reference value()
const 8219 return anchor.value();
8224 typename IteratorType::reference container;
8228 explicit iteration_proxy(
typename IteratorType::reference cont)
8233 iteration_proxy_internal begin() noexcept
8235 return iteration_proxy_internal(container.begin());
8239 iteration_proxy_internal end() noexcept
8241 return iteration_proxy_internal(container.end());
8265 template<
typename U>
8266 class iter_impl :
public std::iterator<std::random_access_iterator_tag, U>
8272 static_assert(std::is_same<U, basic_json>::value
8273 or std::is_same<U, const basic_json>::value,
8274 "iter_impl only accepts (const) basic_json");
8282 using pointer =
typename std::conditional<std::is_const<U>::value,
8286 using reference =
typename std::conditional<std::is_const<U>::value,
8304 assert(m_object !=
nullptr);
8306 switch (m_object->m_type)
8310 m_it.object_iterator =
typename object_t::iterator();
8316 m_it.array_iterator =
typename array_t::iterator();
8322 m_it.primitive_iterator = primitive_iterator_t();
8342 ret.m_object = m_object;
8355 : m_object(other.m_object), m_it(other.m_it)
8364 std::is_nothrow_move_constructible<pointer>::value and
8365 std::is_nothrow_move_assignable<pointer>::value and
8366 std::is_nothrow_move_constructible<internal_iterator>::value and
8367 std::is_nothrow_move_assignable<internal_iterator>::value
8370 std::swap(m_object, other.m_object);
8371 std::swap(m_it, other.m_it);
8380 void set_begin() noexcept
8382 assert(m_object !=
nullptr);
8384 switch (m_object->m_type)
8388 m_it.object_iterator = m_object->m_value.object->begin();
8394 m_it.array_iterator = m_object->m_value.array->begin();
8401 m_it.primitive_iterator.set_end();
8407 m_it.primitive_iterator.set_begin();
8417 void set_end() noexcept
8419 assert(m_object !=
nullptr);
8421 switch (m_object->m_type)
8425 m_it.object_iterator = m_object->m_value.object->end();
8431 m_it.array_iterator = m_object->m_value.array->end();
8437 m_it.primitive_iterator.set_end();
8450 assert(m_object !=
nullptr);
8452 switch (m_object->m_type)
8456 assert(m_it.object_iterator != m_object->m_value.object->end());
8457 return m_it.object_iterator->second;
8462 assert(m_it.array_iterator != m_object->m_value.array->end());
8463 return *m_it.array_iterator;
8468 throw std::out_of_range(
"cannot get value");
8473 if (m_it.primitive_iterator.is_begin())
8478 throw std::out_of_range(
"cannot get value");
8489 assert(m_object !=
nullptr);
8491 switch (m_object->m_type)
8495 assert(m_it.object_iterator != m_object->m_value.object->end());
8496 return &(m_it.object_iterator->second);
8501 assert(m_it.array_iterator != m_object->m_value.array->end());
8502 return &*m_it.array_iterator;
8507 if (m_it.primitive_iterator.is_begin())
8512 throw std::out_of_range(
"cannot get value");
8523 auto result = *
this;
8534 assert(m_object !=
nullptr);
8536 switch (m_object->m_type)
8540 std::advance(m_it.object_iterator, 1);
8546 std::advance(m_it.array_iterator, 1);
8552 ++m_it.primitive_iterator;
8566 auto result = *
this;
8577 assert(m_object !=
nullptr);
8579 switch (m_object->m_type)
8583 std::advance(m_it.object_iterator, -1);
8589 std::advance(m_it.array_iterator, -1);
8595 --m_it.primitive_iterator;
8610 if (m_object != other.m_object)
8612 throw std::domain_error(
"cannot compare iterators of different containers");
8615 assert(m_object !=
nullptr);
8617 switch (m_object->m_type)
8621 return (m_it.object_iterator == other.m_it.object_iterator);
8626 return (m_it.array_iterator == other.m_it.array_iterator);
8631 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
8642 return not operator==(other);
8652 if (m_object != other.m_object)
8654 throw std::domain_error(
"cannot compare iterators of different containers");
8657 assert(m_object !=
nullptr);
8659 switch (m_object->m_type)
8663 throw std::domain_error(
"cannot compare order of object iterators");
8668 return (m_it.array_iterator < other.m_it.array_iterator);
8673 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
8684 return not other.operator < (*this);
8693 return not operator<=(other);
8702 return not operator<(other);
8711 assert(m_object !=
nullptr);
8713 switch (m_object->m_type)
8717 throw std::domain_error(
"cannot use offsets with object iterators");
8722 std::advance(m_it.array_iterator, i);
8728 m_it.primitive_iterator += i;
8742 return operator+=(-i);
8751 auto result = *
this;
8762 auto result = *
this;
8773 assert(m_object !=
nullptr);
8775 switch (m_object->m_type)
8779 throw std::domain_error(
"cannot use offsets with object iterators");
8784 return m_it.array_iterator - other.m_it.array_iterator;
8789 return m_it.primitive_iterator - other.m_it.primitive_iterator;
8800 assert(m_object !=
nullptr);
8802 switch (m_object->m_type)
8806 throw std::domain_error(
"cannot use operator[] for object iterators");
8811 return *std::next(m_it.array_iterator, n);
8816 throw std::out_of_range(
"cannot get value");
8821 if (m_it.primitive_iterator == -n)
8826 throw std::out_of_range(
"cannot get value");
8835 typename object_t::key_type
key()
const 8837 assert(m_object !=
nullptr);
8839 if (m_object->is_object())
8841 return m_it.object_iterator->first;
8844 throw std::domain_error(
"cannot use key() for non-object iterators");
8860 internal_iterator m_it = internal_iterator();
8880 template<
typename Base>
8902 return base_iterator::operator++(1);
8908 base_iterator::operator++();
8915 return base_iterator::operator--(1);
8921 base_iterator::operator--();
8928 base_iterator::operator+=(i);
8935 auto result = *
this;
8943 auto result = *
this;
8951 return this->base() - other.base();
8957 return *(this->operator+(n));
8961 typename object_t::key_type
key()
const 8963 auto it = --this->base();
8970 auto it = --this->base();
8971 return it.operator * ();
8992 enum class token_type
9011 using lexer_char_t =
unsigned char;
9014 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
9017 assert(m_content !=
nullptr);
9018 m_start = m_cursor = m_content;
9019 m_limit = m_content + len;
9023 explicit lexer(std::istream& s)
9024 : m_stream(&s), m_line_buffer()
9029 throw std::invalid_argument(
"stream error");
9036 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
9038 m_line_buffer[0] =
' ';
9039 m_line_buffer[1] =
' ';
9040 m_line_buffer[2] =
' ';
9046 lexer(
const lexer&) =
delete;
9047 lexer operator=(
const lexer&) =
delete;
9072 static string_t to_unicode(
const std::size_t codepoint1,
9073 const std::size_t codepoint2 = 0)
9076 std::size_t codepoint = codepoint1;
9079 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9082 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9096 throw std::invalid_argument(
"missing or wrong low surrogate");
9102 if (codepoint < 0x80)
9105 result.append(1, static_cast<typename string_t::value_type>(codepoint));
9107 else if (codepoint <= 0x7ff)
9110 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9111 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9113 else if (codepoint <= 0xffff)
9116 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9117 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9118 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9120 else if (codepoint <= 0x10ffff)
9123 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9124 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9125 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9126 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9130 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
9137 static std::string token_type_name(
const token_type t)
9141 case token_type::uninitialized:
9142 return "<uninitialized>";
9143 case token_type::literal_true:
9144 return "true literal";
9145 case token_type::literal_false:
9146 return "false literal";
9147 case token_type::literal_null:
9148 return "null literal";
9149 case token_type::value_string:
9150 return "string literal";
9151 case token_type::value_number:
9152 return "number literal";
9153 case token_type::begin_array:
9155 case token_type::begin_object:
9157 case token_type::end_array:
9159 case token_type::end_object:
9161 case token_type::name_separator:
9163 case token_type::value_separator:
9165 case token_type::parse_error:
9166 return "<parse error>";
9167 case token_type::end_of_input:
9168 return "end of input";
9172 return "unknown token";
9207 assert(m_start !=
nullptr);
9212 unsigned int yyaccept = 0;
9213 static const unsigned char yybm[] =
9215 0, 0, 0, 0, 0, 0, 0, 0,
9216 0, 32, 32, 0, 0, 32, 0, 0,
9217 0, 0, 0, 0, 0, 0, 0, 0,
9218 0, 0, 0, 0, 0, 0, 0, 0,
9219 160, 128, 0, 128, 128, 128, 128, 128,
9220 128, 128, 128, 128, 128, 128, 128, 128,
9221 192, 192, 192, 192, 192, 192, 192, 192,
9222 192, 192, 128, 128, 128, 128, 128, 128,
9223 128, 128, 128, 128, 128, 128, 128, 128,
9224 128, 128, 128, 128, 128, 128, 128, 128,
9225 128, 128, 128, 128, 128, 128, 128, 128,
9226 128, 128, 128, 128, 0, 128, 128, 128,
9227 128, 128, 128, 128, 128, 128, 128, 128,
9228 128, 128, 128, 128, 128, 128, 128, 128,
9229 128, 128, 128, 128, 128, 128, 128, 128,
9230 128, 128, 128, 128, 128, 128, 128, 128,
9231 0, 0, 0, 0, 0, 0, 0, 0,
9232 0, 0, 0, 0, 0, 0, 0, 0,
9233 0, 0, 0, 0, 0, 0, 0, 0,
9234 0, 0, 0, 0, 0, 0, 0, 0,
9235 0, 0, 0, 0, 0, 0, 0, 0,
9236 0, 0, 0, 0, 0, 0, 0, 0,
9237 0, 0, 0, 0, 0, 0, 0, 0,
9238 0, 0, 0, 0, 0, 0, 0, 0,
9239 0, 0, 0, 0, 0, 0, 0, 0,
9240 0, 0, 0, 0, 0, 0, 0, 0,
9241 0, 0, 0, 0, 0, 0, 0, 0,
9242 0, 0, 0, 0, 0, 0, 0, 0,
9243 0, 0, 0, 0, 0, 0, 0, 0,
9244 0, 0, 0, 0, 0, 0, 0, 0,
9245 0, 0, 0, 0, 0, 0, 0, 0,
9246 0, 0, 0, 0, 0, 0, 0, 0,
9248 if ((m_limit - m_cursor) < 5)
9250 fill_line_buffer(5);
9253 if (yybm[0 + yych] & 32)
9255 goto basic_json_parser_6;
9265 goto basic_json_parser_2;
9269 goto basic_json_parser_4;
9271 goto basic_json_parser_9;
9277 goto basic_json_parser_4;
9281 goto basic_json_parser_10;
9283 goto basic_json_parser_12;
9292 goto basic_json_parser_4;
9296 goto basic_json_parser_13;
9298 goto basic_json_parser_15;
9304 goto basic_json_parser_17;
9308 goto basic_json_parser_4;
9310 goto basic_json_parser_19;
9322 goto basic_json_parser_21;
9324 goto basic_json_parser_4;
9330 goto basic_json_parser_23;
9334 goto basic_json_parser_4;
9336 goto basic_json_parser_24;
9345 goto basic_json_parser_25;
9347 goto basic_json_parser_4;
9353 goto basic_json_parser_26;
9357 goto basic_json_parser_28;
9359 goto basic_json_parser_4;
9363 basic_json_parser_2:
9366 last_token_type = token_type::end_of_input;
9369 basic_json_parser_4:
9371 basic_json_parser_5:
9373 last_token_type = token_type::parse_error;
9376 basic_json_parser_6:
9378 if (m_limit <= m_cursor)
9380 fill_line_buffer(1);
9383 if (yybm[0 + yych] & 32)
9385 goto basic_json_parser_6;
9390 basic_json_parser_9:
9392 yych = *(m_marker = ++m_cursor);
9395 goto basic_json_parser_5;
9399 goto basic_json_parser_31;
9403 goto basic_json_parser_5;
9407 goto basic_json_parser_31;
9409 goto basic_json_parser_5;
9410 basic_json_parser_10:
9413 last_token_type = token_type::value_separator;
9416 basic_json_parser_12:
9420 goto basic_json_parser_5;
9424 goto basic_json_parser_13;
9428 goto basic_json_parser_15;
9430 goto basic_json_parser_5;
9431 basic_json_parser_13:
9433 yych = *(m_marker = ++m_cursor);
9438 goto basic_json_parser_43;
9445 goto basic_json_parser_44;
9449 goto basic_json_parser_44;
9452 basic_json_parser_14:
9454 last_token_type = token_type::value_number;
9457 basic_json_parser_15:
9459 m_marker = ++m_cursor;
9460 if ((m_limit - m_cursor) < 3)
9462 fill_line_buffer(3);
9465 if (yybm[0 + yych] & 64)
9467 goto basic_json_parser_15;
9473 goto basic_json_parser_43;
9475 goto basic_json_parser_14;
9481 goto basic_json_parser_44;
9485 goto basic_json_parser_44;
9487 goto basic_json_parser_14;
9489 basic_json_parser_17:
9492 last_token_type = token_type::name_separator;
9495 basic_json_parser_19:
9498 last_token_type = token_type::begin_array;
9501 basic_json_parser_21:
9504 last_token_type = token_type::end_array;
9507 basic_json_parser_23:
9509 yych = *(m_marker = ++m_cursor);
9512 goto basic_json_parser_45;
9514 goto basic_json_parser_5;
9515 basic_json_parser_24:
9517 yych = *(m_marker = ++m_cursor);
9520 goto basic_json_parser_46;
9522 goto basic_json_parser_5;
9523 basic_json_parser_25:
9525 yych = *(m_marker = ++m_cursor);
9528 goto basic_json_parser_47;
9530 goto basic_json_parser_5;
9531 basic_json_parser_26:
9534 last_token_type = token_type::begin_object;
9537 basic_json_parser_28:
9540 last_token_type = token_type::end_object;
9543 basic_json_parser_30:
9545 if (m_limit <= m_cursor)
9547 fill_line_buffer(1);
9550 basic_json_parser_31:
9551 if (yybm[0 + yych] & 128)
9553 goto basic_json_parser_30;
9561 goto basic_json_parser_32;
9565 goto basic_json_parser_33;
9567 goto basic_json_parser_35;
9573 goto basic_json_parser_32;
9577 goto basic_json_parser_36;
9579 goto basic_json_parser_37;
9588 goto basic_json_parser_39;
9590 goto basic_json_parser_38;
9596 goto basic_json_parser_40;
9600 goto basic_json_parser_41;
9604 goto basic_json_parser_42;
9608 basic_json_parser_32:
9609 m_cursor = m_marker;
9612 goto basic_json_parser_5;
9616 goto basic_json_parser_14;
9618 basic_json_parser_33:
9621 last_token_type = token_type::value_string;
9624 basic_json_parser_35:
9626 if (m_limit <= m_cursor)
9628 fill_line_buffer(1);
9637 goto basic_json_parser_30;
9641 goto basic_json_parser_32;
9643 goto basic_json_parser_30;
9651 goto basic_json_parser_32;
9653 goto basic_json_parser_30;
9659 goto basic_json_parser_30;
9661 goto basic_json_parser_32;
9671 goto basic_json_parser_30;
9675 goto basic_json_parser_30;
9677 goto basic_json_parser_32;
9685 goto basic_json_parser_30;
9687 goto basic_json_parser_32;
9693 goto basic_json_parser_30;
9697 goto basic_json_parser_48;
9699 goto basic_json_parser_32;
9703 basic_json_parser_36:
9705 if (m_limit <= m_cursor)
9707 fill_line_buffer(1);
9712 goto basic_json_parser_32;
9716 goto basic_json_parser_30;
9718 goto basic_json_parser_32;
9719 basic_json_parser_37:
9721 if (m_limit <= m_cursor)
9723 fill_line_buffer(1);
9728 goto basic_json_parser_32;
9732 goto basic_json_parser_36;
9734 goto basic_json_parser_32;
9735 basic_json_parser_38:
9737 if (m_limit <= m_cursor)
9739 fill_line_buffer(1);
9744 goto basic_json_parser_32;
9748 goto basic_json_parser_36;
9750 goto basic_json_parser_32;
9751 basic_json_parser_39:
9753 if (m_limit <= m_cursor)
9755 fill_line_buffer(1);
9760 goto basic_json_parser_32;
9764 goto basic_json_parser_36;
9766 goto basic_json_parser_32;
9767 basic_json_parser_40:
9769 if (m_limit <= m_cursor)
9771 fill_line_buffer(1);
9776 goto basic_json_parser_32;
9780 goto basic_json_parser_38;
9782 goto basic_json_parser_32;
9783 basic_json_parser_41:
9785 if (m_limit <= m_cursor)
9787 fill_line_buffer(1);
9792 goto basic_json_parser_32;
9796 goto basic_json_parser_38;
9798 goto basic_json_parser_32;
9799 basic_json_parser_42:
9801 if (m_limit <= m_cursor)
9803 fill_line_buffer(1);
9808 goto basic_json_parser_32;
9812 goto basic_json_parser_38;
9814 goto basic_json_parser_32;
9815 basic_json_parser_43:
9819 goto basic_json_parser_32;
9823 goto basic_json_parser_49;
9825 goto basic_json_parser_32;
9826 basic_json_parser_44:
9832 goto basic_json_parser_51;
9834 goto basic_json_parser_32;
9840 goto basic_json_parser_51;
9844 goto basic_json_parser_32;
9848 goto basic_json_parser_52;
9850 goto basic_json_parser_32;
9852 basic_json_parser_45:
9856 goto basic_json_parser_54;
9858 goto basic_json_parser_32;
9859 basic_json_parser_46:
9863 goto basic_json_parser_55;
9865 goto basic_json_parser_32;
9866 basic_json_parser_47:
9870 goto basic_json_parser_56;
9872 goto basic_json_parser_32;
9873 basic_json_parser_48:
9875 if (m_limit <= m_cursor)
9877 fill_line_buffer(1);
9884 goto basic_json_parser_32;
9888 goto basic_json_parser_57;
9890 goto basic_json_parser_32;
9896 goto basic_json_parser_57;
9900 goto basic_json_parser_32;
9904 goto basic_json_parser_57;
9906 goto basic_json_parser_32;
9908 basic_json_parser_49:
9910 m_marker = ++m_cursor;
9911 if ((m_limit - m_cursor) < 3)
9913 fill_line_buffer(3);
9920 goto basic_json_parser_14;
9924 goto basic_json_parser_49;
9926 goto basic_json_parser_14;
9932 goto basic_json_parser_44;
9936 goto basic_json_parser_44;
9938 goto basic_json_parser_14;
9940 basic_json_parser_51:
9944 goto basic_json_parser_32;
9948 goto basic_json_parser_32;
9950 basic_json_parser_52:
9952 if (m_limit <= m_cursor)
9954 fill_line_buffer(1);
9959 goto basic_json_parser_14;
9963 goto basic_json_parser_52;
9965 goto basic_json_parser_14;
9966 basic_json_parser_54:
9970 goto basic_json_parser_58;
9972 goto basic_json_parser_32;
9973 basic_json_parser_55:
9977 goto basic_json_parser_59;
9979 goto basic_json_parser_32;
9980 basic_json_parser_56:
9984 goto basic_json_parser_61;
9986 goto basic_json_parser_32;
9987 basic_json_parser_57:
9989 if (m_limit <= m_cursor)
9991 fill_line_buffer(1);
9998 goto basic_json_parser_32;
10002 goto basic_json_parser_63;
10004 goto basic_json_parser_32;
10010 goto basic_json_parser_63;
10014 goto basic_json_parser_32;
10018 goto basic_json_parser_63;
10020 goto basic_json_parser_32;
10022 basic_json_parser_58:
10023 yych = *++m_cursor;
10026 goto basic_json_parser_64;
10028 goto basic_json_parser_32;
10029 basic_json_parser_59:
10032 last_token_type = token_type::literal_null;
10035 basic_json_parser_61:
10038 last_token_type = token_type::literal_true;
10041 basic_json_parser_63:
10043 if (m_limit <= m_cursor)
10045 fill_line_buffer(1);
10052 goto basic_json_parser_32;
10056 goto basic_json_parser_66;
10058 goto basic_json_parser_32;
10064 goto basic_json_parser_66;
10068 goto basic_json_parser_32;
10072 goto basic_json_parser_66;
10074 goto basic_json_parser_32;
10076 basic_json_parser_64:
10079 last_token_type = token_type::literal_false;
10082 basic_json_parser_66:
10084 if (m_limit <= m_cursor)
10086 fill_line_buffer(1);
10093 goto basic_json_parser_32;
10097 goto basic_json_parser_30;
10099 goto basic_json_parser_32;
10105 goto basic_json_parser_30;
10109 goto basic_json_parser_32;
10113 goto basic_json_parser_30;
10115 goto basic_json_parser_32;
10121 return last_token_type;
10152 void fill_line_buffer(
size_t n = 0)
10155 assert(m_line_buffer.empty()
10156 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
10159 assert(m_line_buffer.empty()
10160 or m_limit == m_content + m_line_buffer.size());
10163 assert(m_content <= m_start);
10164 assert(m_start <= m_cursor);
10165 assert(m_cursor <= m_limit);
10166 assert(m_marker ==
nullptr or m_marker <= m_limit);
10169 const auto num_processed_chars =
static_cast<size_t>(m_start - m_content);
10171 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
10173 const auto offset_cursor = m_cursor - m_start;
10176 if (m_stream ==
nullptr or m_stream->eof())
10181 m_line_buffer.assign(m_start, m_limit);
10185 m_line_buffer.append(1,
'\x00');
10188 m_line_buffer.append(n - 1,
'\x01');
10194 m_line_buffer.erase(0, num_processed_chars);
10196 m_line_buffer_tmp.clear();
10197 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
10200 m_line_buffer += m_line_buffer_tmp;
10201 m_line_buffer.push_back(
'\n');
10205 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
10206 assert(m_content !=
nullptr);
10207 m_start = m_content;
10208 m_marker = m_start + offset_marker;
10209 m_cursor = m_start + offset_cursor;
10210 m_limit = m_start + m_line_buffer.size();
10216 assert(m_start !=
nullptr);
10217 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10218 static_cast<size_t>(m_cursor - m_start));
10280 assert(m_cursor - m_start >= 2);
10283 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10286 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10289 auto e = std::find(i, m_cursor - 1,
'\\');
10293 for (
auto k = i; k < e; k++)
10295 result.push_back(static_cast<typename string_t::value_type>(*k));
10353 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10354 4).c_str(),
nullptr, 16);
10357 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10360 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
10362 throw std::invalid_argument(
"missing low surrogate");
10366 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10367 (i + 7), 4).c_str(),
nullptr, 16);
10368 result += to_unicode(codepoint, codepoint2);
10372 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10375 throw std::invalid_argument(
"missing high surrogate");
10380 result += to_unicode(codepoint);
10406 long double str_to_float_t(
long double* ,
char** endptr)
const 10408 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10424 double str_to_float_t(
double* ,
char** endptr)
const 10426 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10442 float str_to_float_t(
float* ,
char** endptr)
const 10444 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10470 assert(m_start !=
nullptr);
10472 const lexer::lexer_char_t* curptr = m_start;
10484 if (*curptr ==
'-')
10486 type = value_t::number_integer;
10487 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
10492 type = value_t::number_unsigned;
10493 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
10497 for (; curptr < m_cursor; curptr++)
10500 if (*curptr < '0' || *curptr >
'9')
10502 if (*curptr ==
'.')
10505 type = value_t::number_float;
10510 type = value_t::number_float;
10515 if (type != value_t::number_float)
10521 if (value > (max - digit) / 10)
10524 type = value_t::number_float;
10529 value = value * 10 + digit;
10535 if (type == value_t::number_unsigned)
10537 result.m_value.number_unsigned = value;
10539 else if (type == value_t::number_integer)
10543 assert(value >= 0);
10544 assert(value <= max);
10561 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr),
nullptr);
10564 if (not std::isfinite(result.m_value.number_float))
10566 type = value_t::null;
10567 result.m_value = basic_json::json_value();
10572 result.m_type = type;
10577 std::istream* m_stream =
nullptr;
10583 const lexer_char_t* m_content =
nullptr;
10585 const lexer_char_t* m_start =
nullptr;
10587 const lexer_char_t* m_marker =
nullptr;
10589 const lexer_char_t* m_cursor =
nullptr;
10591 const lexer_char_t* m_limit =
nullptr;
10593 token_type last_token_type = token_type::end_of_input;
10607 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
10612 : callback(cb), m_lexer(is)
10616 template<
class IteratorType,
typename std::enable_if<
10617 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10620 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
10622 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10623 static_cast<size_t>(std::distance(first, last)))
10633 result.assert_invariant();
10635 expect(lexer::token_type::end_of_input);
10646 auto result =
basic_json(value_t::discarded);
10648 switch (last_token)
10650 case lexer::token_type::begin_object:
10652 if (keep and (not callback
10653 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10656 result.m_type = value_t::object;
10657 result.m_value = value_t::object;
10664 if (last_token == lexer::token_type::end_object)
10667 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10675 unexpect(lexer::token_type::value_separator);
10681 if (last_token == lexer::token_type::value_separator)
10687 expect(lexer::token_type::value_string);
10688 const auto key = m_lexer.get_string();
10690 bool keep_tag =
false;
10696 keep_tag = callback(depth, parse_event_t::key, k);
10706 expect(lexer::token_type::name_separator);
10710 auto value = parse_internal(keep);
10711 if (keep and keep_tag and not value.is_discarded())
10713 result[key] = std::move(value);
10716 while (last_token == lexer::token_type::value_separator);
10719 expect(lexer::token_type::end_object);
10721 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10729 case lexer::token_type::begin_array:
10731 if (keep and (not callback
10732 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10735 result.m_type = value_t::array;
10736 result.m_value = value_t::array;
10743 if (last_token == lexer::token_type::end_array)
10746 if (callback and not callback(--depth, parse_event_t::array_end, result))
10754 unexpect(lexer::token_type::value_separator);
10760 if (last_token == lexer::token_type::value_separator)
10766 auto value = parse_internal(keep);
10767 if (keep and not value.is_discarded())
10769 result.push_back(std::move(value));
10772 while (last_token == lexer::token_type::value_separator);
10775 expect(lexer::token_type::end_array);
10777 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10785 case lexer::token_type::literal_null:
10788 result.m_type = value_t::null;
10792 case lexer::token_type::value_string:
10794 const auto s = m_lexer.get_string();
10800 case lexer::token_type::literal_true:
10803 result.m_type = value_t::boolean;
10804 result.m_value =
true;
10808 case lexer::token_type::literal_false:
10811 result.m_type = value_t::boolean;
10812 result.m_value =
false;
10816 case lexer::token_type::value_number:
10818 m_lexer.get_number(result);
10826 unexpect(last_token);
10830 if (keep and callback and not callback(depth, parse_event_t::value, result))
10838 typename lexer::token_type get_token()
10840 last_token = m_lexer.scan();
10844 void expect(
typename lexer::token_type t)
const 10846 if (t != last_token)
10848 std::string error_msg =
"parse error - unexpected ";
10849 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
10851 lexer::token_type_name(last_token));
10852 error_msg +=
"; expected " + lexer::token_type_name(t);
10853 throw std::invalid_argument(error_msg);
10857 void unexpect(
typename lexer::token_type t)
const 10859 if (t == last_token)
10861 std::string error_msg =
"parse error - unexpected ";
10862 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
10864 lexer::token_type_name(last_token));
10865 throw std::invalid_argument(error_msg);
10875 typename lexer::token_type last_token = lexer::token_type::uninitialized;
10921 : reference_tokens(split(s))
10939 std::string to_string()
const noexcept
10941 return std::accumulate(reference_tokens.begin(),
10942 reference_tokens.end(), std::string{},
10943 [](
const std::string & a,
const std::string & b)
10945 return a +
"/" + escape(b);
10950 operator std::string()
const 10952 return to_string();
10957 std::string pop_back()
10961 throw std::domain_error(
"JSON pointer has no parent");
10964 auto last = reference_tokens.back();
10965 reference_tokens.pop_back();
10970 bool is_root()
const 10972 return reference_tokens.empty();
10979 throw std::domain_error(
"JSON pointer has no parent");
10983 result.reference_tokens = {reference_tokens[0]};
10998 for (
const auto& reference_token : reference_tokens)
11000 switch (result->m_type)
11002 case value_t::null:
11004 if (reference_token ==
"0")
11007 result = &result->operator[](0);
11012 result = &result->operator[](reference_token);
11017 case value_t::object:
11020 result = &result->operator[](reference_token);
11024 case value_t::array:
11027 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11040 throw std::domain_error(
"invalid value to unflatten");
11069 for (
const auto& reference_token : reference_tokens)
11072 if (ptr->m_type == value_t::null)
11075 const bool nums = std::all_of(reference_token.begin(),
11076 reference_token.end(),
11079 return std::isdigit(x);
11084 if (nums or reference_token ==
"-")
11086 *ptr = value_t::array;
11090 *ptr = value_t::object;
11094 switch (ptr->m_type)
11096 case value_t::object:
11099 ptr = &ptr->operator[](reference_token);
11103 case value_t::array:
11106 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11108 throw std::domain_error(
"array index must not begin with '0'");
11111 if (reference_token ==
"-")
11114 ptr = &ptr->operator[](ptr->m_value.array->size());
11119 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11126 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11136 for (
const auto& reference_token : reference_tokens)
11138 switch (ptr->m_type)
11140 case value_t::object:
11143 ptr = &ptr->
at(reference_token);
11147 case value_t::array:
11149 if (reference_token ==
"-")
11152 throw std::out_of_range(
"array index '-' (" +
11153 std::to_string(ptr->m_value.array->size()) +
11154 ") is out of range");
11158 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11160 throw std::domain_error(
"array index must not begin with '0'");
11164 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11170 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11188 for (
const auto& reference_token : reference_tokens)
11190 switch (ptr->m_type)
11192 case value_t::object:
11195 ptr = &ptr->operator[](reference_token);
11199 case value_t::array:
11201 if (reference_token ==
"-")
11204 throw std::out_of_range(
"array index '-' (" +
11205 std::to_string(ptr->m_value.array->size()) +
11206 ") is out of range");
11210 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11212 throw std::domain_error(
"array index must not begin with '0'");
11216 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11222 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11232 for (
const auto& reference_token : reference_tokens)
11234 switch (ptr->m_type)
11236 case value_t::object:
11239 ptr = &ptr->
at(reference_token);
11243 case value_t::array:
11245 if (reference_token ==
"-")
11248 throw std::out_of_range(
"array index '-' (" +
11249 std::to_string(ptr->m_value.array->size()) +
11250 ") is out of range");
11254 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11256 throw std::domain_error(
"array index must not begin with '0'");
11260 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11266 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
11275 static std::vector<std::string> split(
const std::string& reference_string)
11277 std::vector<std::string> result;
11280 if (reference_string.empty())
11286 if (reference_string[0] !=
'/')
11288 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
11296 size_t slash = reference_string.find_first_of(
'/', 1),
11305 slash = reference_string.find_first_of(
'/', start))
11309 auto reference_token = reference_string.substr(start, slash - start);
11312 for (
size_t pos = reference_token.find_first_of(
'~');
11313 pos != std::string::npos;
11314 pos = reference_token.find_first_of(
'~', pos + 1))
11316 assert(reference_token[pos] ==
'~');
11319 if (pos == reference_token.size() - 1 or
11320 (reference_token[pos + 1] !=
'0' and
11321 reference_token[pos + 1] !=
'1'))
11323 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
11328 unescape(reference_token);
11329 result.push_back(reference_token);
11348 static void replace_substring(std::string& s,
11349 const std::string& f,
11350 const std::string& t)
11352 assert(not f.empty());
11355 size_t pos = s.find(f);
11356 pos != std::string::npos;
11357 s.replace(pos, f.size(), t),
11358 pos = s.find(f, pos + t.size())
11363 static std::string escape(std::string s)
11366 replace_substring(s,
"~",
"~0");
11367 replace_substring(s,
"/",
"~1");
11372 static void unescape(std::string& s)
11375 replace_substring(s,
"~1",
"/");
11377 replace_substring(s,
"~0",
"~");
11387 static void flatten(
const std::string& reference_string,
11391 switch (value.m_type)
11393 case value_t::array:
11395 if (value.m_value.array->empty())
11398 result[reference_string] =
nullptr;
11403 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
11405 flatten(reference_string +
"/" + std::to_string(i),
11406 value.m_value.array->operator[](i), result);
11412 case value_t::object:
11414 if (value.m_value.object->empty())
11417 result[reference_string] =
nullptr;
11422 for (
const auto& element : *value.m_value.object)
11424 flatten(reference_string +
"/" + escape(element.first),
11425 element.second, result);
11434 result[reference_string] = value;
11449 throw std::domain_error(
"only objects can be unflattened");
11455 for (
const auto& element : *value.m_value.object)
11457 if (not element.second.is_primitive())
11459 throw std::domain_error(
"values in object must be primitive");
11467 json_pointer(element.first).get_and_create(result) = element.second;
11475 std::vector<std::string> reference_tokens {};
11520 return ptr.get_unchecked(
this);
11547 return ptr.get_unchecked(
this);
11572 return ptr.get_checked(
this);
11597 return ptr.get_checked(
this);
11625 json_pointer::flatten(
"", *
this, result);
11658 return json_pointer::unflatten(*
this);
11712 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
11714 const auto get_op = [](
const std::string op)
11718 return patch_operations::add;
11720 if (op ==
"remove")
11722 return patch_operations::remove;
11724 if (op ==
"replace")
11726 return patch_operations::replace;
11730 return patch_operations::move;
11734 return patch_operations::copy;
11738 return patch_operations::test;
11741 return patch_operations::invalid;
11756 if (top_pointer != ptr)
11758 result.
at(top_pointer);
11762 const auto last_path = ptr.pop_back();
11765 switch (parent.m_type)
11767 case value_t::null:
11768 case value_t::object:
11771 parent[last_path] = val;
11775 case value_t::array:
11777 if (last_path ==
"-")
11784 const auto idx = std::stoi(last_path);
11785 if (static_cast<size_type>(idx) > parent.
size())
11788 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
11809 const auto operation_remove = [&result](
json_pointer & ptr)
11812 const auto last_path = ptr.pop_back();
11819 auto it = parent.
find(last_path);
11820 if (it != parent.
end())
11826 throw std::out_of_range(
"key '" + last_path +
"' not found");
11832 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
11840 throw std::invalid_argument(
"JSON patch must be an array of objects");
11844 for (
const auto& val : json_patch)
11847 const auto get_value = [&val](
const std::string & op,
11848 const std::string & member,
11852 auto it = val.m_value.object->find(member);
11855 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
11858 if (it == val.m_value.object->end())
11860 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
11864 if (string_type and not it->second.is_string())
11866 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
11874 if (not val.is_object())
11876 throw std::invalid_argument(
"JSON patch must be an array of objects");
11880 const std::string op = get_value(
"op",
"op",
true);
11881 const std::string path = get_value(op,
"path",
true);
11884 switch (get_op(op))
11886 case patch_operations::add:
11888 operation_add(ptr, get_value(
"add",
"value",
false));
11892 case patch_operations::remove:
11894 operation_remove(ptr);
11898 case patch_operations::replace:
11901 result.
at(ptr) = get_value(
"replace",
"value",
false);
11905 case patch_operations::move:
11907 const std::string from_path = get_value(
"move",
"from",
true);
11917 operation_remove(from_ptr);
11918 operation_add(ptr, v);
11922 case patch_operations::copy:
11924 const std::string from_path = get_value(
"copy",
"from",
true);;
11928 result[ptr] = result.
at(from_ptr);
11932 case patch_operations::test:
11934 bool success =
false;
11939 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
11941 catch (std::out_of_range&)
11949 throw std::domain_error(
"unsuccessful: " + val.dump());
11955 case patch_operations::invalid:
11959 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
12001 const std::string& path =
"")
12007 if (source == target)
12012 if (source.
type() != target.
type())
12024 switch (source.
type())
12026 case value_t::array:
12030 while (i < source.
size() and i < target.
size())
12033 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
12034 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12043 while (i < source.
size())
12047 result.insert(result.begin() + end_index, object(
12050 {
"path", path +
"/" + std::to_string(i)}
12056 while (i < target.
size())
12061 {
"path", path +
"/" + std::to_string(i)},
12062 {
"value", target[i]}
12070 case value_t::object:
12073 for (
auto it = source.
begin(); it != source.
end(); ++it)
12076 const auto key = json_pointer::escape(it.key());
12078 if (target.
find(it.key()) != target.
end())
12081 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
12082 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12087 result.push_back(
object(
12090 {
"path", path +
"/" + key}
12096 for (
auto it = target.
begin(); it != target.
end(); ++it)
12098 if (source.
find(it.key()) == source.
end())
12101 const auto key = json_pointer::escape(it.key());
12105 {
"path", path +
"/" + key},
12106 {
"value", it.value()}
12166 is_nothrow_move_constructible<nlohmann::json>::value and
12167 is_nothrow_move_assignable<nlohmann::json>::value
12185 const auto& h = hash<nlohmann::json::string_t>();
12204 inline nlohmann::json operator "" _json(
const char* s, std::size_t n)
12228 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 12229 #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.