29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 42 #include <initializer_list> 52 #include <type_traits> 57 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 58 #pragma GCC diagnostic push 59 #pragma GCC diagnostic ignored "-Wfloat-equal" 82 struct has_mapped_type
85 template<
typename C>
static char test(
typename C::mapped_type*);
86 template<
typename C>
static char (&test(...))[2];
88 static constexpr
bool value =
sizeof(test<T>(0)) == 1;
95 class DecimalSeparator :
public std::numpunct<char>
98 char do_decimal_point()
const 178 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
179 template<
typename U,
typename... Args>
class ArrayType = std::vector,
180 class StringType = std::string,
181 class BooleanType = bool,
182 class NumberIntegerType = std::int64_t,
183 class NumberUnsignedType = std::uint64_t,
184 class NumberFloatType = double,
185 template<
typename U>
class AllocatorType = std::allocator
229 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
231 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
343 using object_t = ObjectType<StringType,
345 std::less<StringType>,
346 AllocatorType<std::pair<
const StringType,
393 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
735 uint16_t has_exp : 1;
737 uint16_t exp_plus : 1;
739 uint16_t exp_cap : 1;
741 uint16_t precision : 8;
748 return static_cast<value_t>(bits.type);
752 bool operator==(
const value_t& rhs)
const 754 return static_cast<value_t>(bits.type) == rhs;
758 type_data_t& operator=(
value_t rhs)
760 bits.type =
static_cast<uint16_t
>(rhs);
765 type_data_t(
value_t t) noexcept
767 *
reinterpret_cast<uint16_t*
>(
this) = 0;
768 bits.type =
static_cast<uint16_t
>(t);
772 type_data_t() noexcept
775 bits.type =
reinterpret_cast<uint16_t
>(value_t::null);
780 template<
typename T,
typename... Args>
781 static T* create(Args&& ... args)
783 AllocatorType<T> alloc;
784 auto deleter = [&](T * object)
786 alloc.deallocate(
object, 1);
788 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
789 alloc.construct(
object.
get(), std::forward<Args>(args)...);
790 return object.release();
822 json_value() =
default;
824 json_value(
boolean_t v) noexcept : boolean(v) {}
836 case value_t::object:
838 object = create<object_t>();
844 array = create<array_t>();
848 case value_t::string:
850 string = create<string_t>(
"");
854 case value_t::boolean:
860 case value_t::number_integer:
866 case value_t::number_unsigned:
872 case value_t::number_float:
888 string = create<string_t>(value);
894 object = create<object_t>(value);
898 json_value(
const array_t& value)
900 array = create<array_t>(value);
983 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
1033 : m_type(value_type), m_value(value_type)
1060 basic_json() =
default;
1108 : m_type(
value_t::object), m_value(val)
1137 template <
class CompatibleObjectType,
typename 1139 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1140 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1147 m_value.object = create<object_t>(begin(val), end(val));
1170 : m_type(
value_t::array), m_value(val)
1199 template <
class CompatibleArrayType,
typename 1201 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1202 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1203 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1204 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1205 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1206 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1207 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1214 m_value.array = create<array_t>(begin(val), end(val));
1239 : m_type(
value_t::string), m_value(val)
1289 template <
class CompatibleStringType,
typename 1291 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1312 : m_type(value_t::boolean), m_value(val)
1338 template<
typename T,
1339 typename std::enable_if<
1340 not (std::is_same<T, int>::value)
1341 and std::is_same<T, number_integer_t>::value
1345 : m_type(value_t::number_integer), m_value(val)
1374 : m_type(value_t::number_integer),
1375 m_value(static_cast<number_integer_t>(val))
1403 template<
typename CompatibleNumberIntegerType,
typename 1405 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1406 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1407 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1408 CompatibleNumberIntegerType>::type
1411 : m_type(value_t::number_integer),
1412 m_value(static_cast<number_integer_t>(val))
1432 template<
typename T,
1433 typename std::enable_if<
1434 not (std::is_same<T, int>::value)
1435 and std::is_same<T, number_unsigned_t>::value
1439 : m_type(value_t::number_unsigned), m_value(val)
1462 template <
typename CompatibleNumberUnsignedType,
typename 1464 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1465 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1466 !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1467 CompatibleNumberUnsignedType >::type
1470 : m_type(value_t::number_unsigned),
1471 m_value(static_cast<number_unsigned_t>(val))
1499 : m_type(value_t::number_float), m_value(val)
1502 if (not std::isfinite(val))
1504 m_type = value_t::null;
1505 m_value = json_value();
1539 template<
typename CompatibleNumberFloatType,
typename =
typename 1541 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1542 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1618 bool type_deduction =
true,
1619 value_t manual_type = value_t::array)
1622 bool is_an_object =
true;
1626 for (
const auto& element : init)
1628 if (not element.is_array() or element.size() != 2
1629 or not element[0].is_string())
1633 is_an_object =
false;
1639 if (not type_deduction)
1642 if (manual_type == value_t::array)
1644 is_an_object =
false;
1648 if (manual_type == value_t::object and not is_an_object)
1650 throw std::domain_error(
"cannot create object from initializer list");
1657 m_type = value_t::object;
1658 m_value = value_t::object;
1660 assert(m_value.object !=
nullptr);
1662 for (
auto& element : init)
1664 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1670 m_type = value_t::array;
1671 m_value.array = create<array_t>(init);
1709 static basic_json
array(std::initializer_list<basic_json> init =
1710 std::initializer_list<basic_json>())
1712 return basic_json(init,
false, value_t::array);
1749 static basic_json
object(std::initializer_list<basic_json> init =
1750 std::initializer_list<basic_json>())
1752 return basic_json(init,
false, value_t::object);
1776 m_value.array = create<array_t>(cnt, val);
1813 template <
class InputIT,
typename 1815 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1816 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1819 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1822 if (first.m_object != last.m_object)
1824 throw std::domain_error(
"iterators are not compatible");
1830 case value_t::boolean:
1831 case value_t::number_float:
1832 case value_t::number_integer:
1833 case value_t::number_unsigned:
1834 case value_t::string:
1836 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1838 throw std::out_of_range(
"iterators out of range");
1851 case value_t::number_integer:
1853 assert(first.m_object !=
nullptr);
1854 m_value.number_integer = first.m_object->m_value.number_integer;
1858 case value_t::number_unsigned:
1860 assert(first.m_object !=
nullptr);
1861 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1865 case value_t::number_float:
1867 assert(first.m_object !=
nullptr);
1868 m_value.number_float = first.m_object->m_value.number_float;
1872 case value_t::boolean:
1874 assert(first.m_object !=
nullptr);
1875 m_value.boolean = first.m_object->m_value.boolean;
1879 case value_t::string:
1881 assert(first.m_object !=
nullptr);
1882 m_value = *first.m_object->m_value.string;
1886 case value_t::object:
1888 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1892 case value_t::array:
1894 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1900 assert(first.m_object !=
nullptr);
1901 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1928 *
this = parser(i, cb).parse();
1958 : m_type(other.m_type)
1962 case value_t::object:
1964 assert(other.m_value.object !=
nullptr);
1965 m_value = *other.m_value.object;
1969 case value_t::array:
1971 assert(other.m_value.array !=
nullptr);
1972 m_value = *other.m_value.array;
1976 case value_t::string:
1978 assert(other.m_value.string !=
nullptr);
1979 m_value = *other.m_value.string;
1983 case value_t::boolean:
1985 m_value = other.m_value.boolean;
1989 case value_t::number_integer:
1991 m_value = other.m_value.number_integer;
1995 case value_t::number_unsigned:
1997 m_value = other.m_value.number_unsigned;
2001 case value_t::number_float:
2003 m_value = other.m_value.number_float;
2033 : m_type(
std::move(other.m_type)),
2034 m_value(
std::move(other.m_value))
2037 other.m_type = value_t::null;
2065 std::is_nothrow_move_constructible<value_t>::value and
2066 std::is_nothrow_move_assignable<value_t>::value and
2067 std::is_nothrow_move_constructible<json_value>::value and
2068 std::is_nothrow_move_assignable<json_value>::value
2072 swap(m_type, other.m_type);
2073 swap(m_value, other.m_value);
2096 case value_t::object:
2098 AllocatorType<object_t> alloc;
2099 alloc.destroy(m_value.object);
2100 alloc.deallocate(m_value.object, 1);
2104 case value_t::array:
2106 AllocatorType<array_t> alloc;
2107 alloc.destroy(m_value.array);
2108 alloc.deallocate(m_value.array, 1);
2112 case value_t::string:
2114 AllocatorType<string_t> alloc;
2115 alloc.destroy(m_value.string);
2116 alloc.deallocate(m_value.string, 1);
2163 std::stringstream ss;
2167 dump(ss,
true, static_cast<unsigned int>(indent));
2227 return is_null() or is_string() or is_boolean() or is_number();
2254 return is_array() or is_object();
2276 return m_type == value_t::null;
2298 return m_type == value_t::boolean;
2328 return is_number_integer() or is_number_float();
2357 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2385 return m_type == value_t::number_unsigned;
2413 return m_type == value_t::number_float;
2435 return m_type == value_t::object;
2457 return m_type == value_t::array;
2479 return m_type == value_t::string;
2506 return m_type == value_t::discarded;
2540 template <
class T,
typename 2542 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2543 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2545 T get_impl(T*)
const 2549 assert(m_value.object !=
nullptr);
2550 return T(m_value.object->begin(), m_value.object->end());
2554 throw std::domain_error(
"type must be object, but is " + type_name());
2563 assert(m_value.object !=
nullptr);
2564 return *(m_value.object);
2568 throw std::domain_error(
"type must be object, but is " + type_name());
2573 template <
class T,
typename 2575 std::is_convertible<basic_json_t, typename T::value_type>::value and
2576 not std::is_same<basic_json_t, typename T::value_type>::value and
2577 not std::is_arithmetic<T>::value and
2578 not std::is_convertible<std::string, T>::value and
2579 not has_mapped_type<T>::value
2581 T get_impl(T*)
const 2586 assert(m_value.array !=
nullptr);
2587 std::transform(m_value.array->begin(), m_value.array->end(),
2588 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2590 return i.
get<
typename T::value_type>();
2596 throw std::domain_error(
"type must be array, but is " + type_name());
2601 template <
class T,
typename 2603 std::is_convertible<basic_json_t, T>::value and
2604 not std::is_same<basic_json_t, T>::value
2606 std::vector<T> get_impl(std::vector<T>*)
const 2610 std::vector<T> to_vector;
2611 assert(m_value.array !=
nullptr);
2612 to_vector.reserve(m_value.array->size());
2613 std::transform(m_value.array->begin(), m_value.array->end(),
2614 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2622 throw std::domain_error(
"type must be array, but is " + type_name());
2627 template <
class T,
typename 2629 std::is_same<basic_json, typename T::value_type>::value and
2630 not has_mapped_type<T>::value
2632 T get_impl(T*)
const 2636 assert(m_value.array !=
nullptr);
2637 return T(m_value.array->begin(), m_value.array->end());
2641 throw std::domain_error(
"type must be array, but is " + type_name());
2650 assert(m_value.array !=
nullptr);
2651 return *(m_value.array);
2655 throw std::domain_error(
"type must be array, but is " + type_name());
2660 template <
typename T,
typename 2662 std::is_convertible<string_t, T>::value
2664 T get_impl(T*)
const 2668 assert(m_value.string !=
nullptr);
2669 return *m_value.string;
2673 throw std::domain_error(
"type must be string, but is " + type_name());
2678 template<
typename T,
typename 2680 std::is_arithmetic<T>::value
2682 T get_impl(T*)
const 2686 case value_t::number_integer:
2688 return static_cast<T
>(m_value.number_integer);
2691 case value_t::number_unsigned:
2693 return static_cast<T
>(m_value.number_unsigned);
2696 case value_t::number_float:
2698 return static_cast<T
>(m_value.number_float);
2703 throw std::domain_error(
"type must be number, but is " + type_name());
2713 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2719 return is_object() ? m_value.object :
nullptr;
2725 return is_object() ? m_value.object :
nullptr;
2731 return is_array() ? m_value.array :
nullptr;
2735 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2737 return is_array() ? m_value.array :
nullptr;
2743 return is_string() ? m_value.string :
nullptr;
2749 return is_string() ? m_value.string :
nullptr;
2755 return is_boolean() ? &m_value.boolean :
nullptr;
2761 return is_boolean() ? &m_value.boolean :
nullptr;
2767 return is_number_integer() ? &m_value.number_integer :
nullptr;
2773 return is_number_integer() ? &m_value.number_integer :
nullptr;
2779 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2785 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2791 return is_number_float() ? &m_value.number_float :
nullptr;
2797 return is_number_float() ? &m_value.number_float :
nullptr;
2811 template<
typename ReferenceType,
typename ThisType>
2812 static ReferenceType get_ref_impl(ThisType& obj)
2815 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2816 auto ptr = obj.template get_ptr<PointerType>();
2824 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2867 template<
typename ValueType,
typename 2869 not std::is_pointer<ValueType>::value
2871 ValueType
get()
const 2873 return get_impl(static_cast<ValueType*>(
nullptr));
2902 template<
typename PointerType,
typename 2904 std::is_pointer<PointerType>::value
2906 PointerType
get() noexcept
2909 return get_ptr<PointerType>();
2916 template<
typename PointerType,
typename 2918 std::is_pointer<PointerType>::value
2920 constexpr
const PointerType
get()
const noexcept
2923 return get_ptr<PointerType>();
2951 template<
typename PointerType,
typename 2953 std::is_pointer<PointerType>::value
2958 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2965 template<
typename PointerType,
typename 2967 std::is_pointer<PointerType>::value
2968 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2970 constexpr
const PointerType
get_ptr() const noexcept
2973 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3002 template<
typename ReferenceType,
typename 3004 std::is_reference<ReferenceType>::value
3009 return get_ref_impl<ReferenceType>(*this);
3016 template<
typename ReferenceType,
typename 3018 std::is_reference<ReferenceType>::value
3019 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
3024 return get_ref_impl<ReferenceType>(*this);
3055 template <
typename ValueType,
typename 3057 not std::is_pointer<ValueType>::value
3058 and not std::is_same<ValueType, typename string_t::value_type>::value
3059 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3060 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3063 operator ValueType()
const 3066 return get<ValueType>();
3108 assert(m_value.array !=
nullptr);
3109 return m_value.array->at(idx);
3111 catch (std::out_of_range&)
3114 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3119 throw std::domain_error(
"cannot use at() with " + type_name());
3152 assert(m_value.array !=
nullptr);
3153 return m_value.array->at(idx);
3155 catch (std::out_of_range&)
3158 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3163 throw std::domain_error(
"cannot use at() with " + type_name());
3200 assert(m_value.object !=
nullptr);
3201 return m_value.object->at(key);
3203 catch (std::out_of_range&)
3206 throw std::out_of_range(
"key '" + key +
"' not found");
3211 throw std::domain_error(
"cannot use at() with " + type_name());
3248 assert(m_value.object !=
nullptr);
3249 return m_value.object->at(key);
3251 catch (std::out_of_range&)
3254 throw std::out_of_range(
"key '" + key +
"' not found");
3259 throw std::domain_error(
"cannot use at() with " + type_name());
3293 m_type = value_t::array;
3294 m_value.
array = create<array_t>();
3301 assert(m_value.array !=
nullptr);
3302 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3304 m_value.array->push_back(basic_json());
3307 return m_value.array->operator[](idx);
3311 throw std::domain_error(
"cannot use operator[] with " + type_name());
3339 assert(m_value.array !=
nullptr);
3340 return m_value.array->operator[](idx);
3344 throw std::domain_error(
"cannot use operator[] with " + type_name());
3380 m_type = value_t::object;
3381 m_value.
object = create<object_t>();
3387 assert(m_value.object !=
nullptr);
3388 return m_value.object->operator[](key);
3392 throw std::domain_error(
"cannot use operator[] with " + type_name());
3428 assert(m_value.object !=
nullptr);
3429 assert(m_value.object->find(key) != m_value.object->end());
3430 return m_value.object->find(key)->second;
3434 throw std::domain_error(
"cannot use operator[] with " + type_name());
3465 template<
typename T, std::
size_t n>
3468 return operator[](static_cast<const T>(key));
3500 template<
typename T, std::
size_t n>
3503 return operator[](static_cast<const T>(key));
3533 template<
typename T>
3539 m_type = value_t::object;
3540 m_value = value_t::object;
3546 assert(m_value.object !=
nullptr);
3547 return m_value.object->operator[](key);
3551 throw std::domain_error(
"cannot use operator[] with " + type_name());
3582 template<
typename T>
3588 assert(m_value.object !=
nullptr);
3589 assert(m_value.object->find(key) != m_value.object->end());
3590 return m_value.object->find(key)->second;
3594 throw std::domain_error(
"cannot use operator[] with " + type_name());
3646 template <
class ValueType,
typename 3648 std::is_convertible<basic_json_t, ValueType>::value
3650 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3656 const auto it = find(key);
3663 return default_value;
3668 throw std::domain_error(
"cannot use value() with " + type_name());
3676 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3678 return value(key,
string_t(default_value));
3809 template <
class InteratorType,
typename 3811 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3812 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3818 if (
this != pos.m_object)
3820 throw std::domain_error(
"iterator does not fit current value");
3823 InteratorType result = end();
3827 case value_t::boolean:
3828 case value_t::number_float:
3829 case value_t::number_integer:
3830 case value_t::number_unsigned:
3831 case value_t::string:
3833 if (not pos.m_it.primitive_iterator.is_begin())
3835 throw std::out_of_range(
"iterator out of range");
3840 delete m_value.string;
3841 m_value.string =
nullptr;
3844 m_type = value_t::null;
3848 case value_t::object:
3850 assert(m_value.object !=
nullptr);
3851 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3855 case value_t::array:
3857 assert(m_value.array !=
nullptr);
3858 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3864 throw std::domain_error(
"cannot use erase() with " + type_name());
3917 template <
class InteratorType,
typename 3919 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3920 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3923 InteratorType
erase(InteratorType first, InteratorType last)
3926 if (
this != first.m_object or
this != last.m_object)
3928 throw std::domain_error(
"iterators do not fit current value");
3931 InteratorType result = end();
3935 case value_t::boolean:
3936 case value_t::number_float:
3937 case value_t::number_integer:
3938 case value_t::number_unsigned:
3939 case value_t::string:
3941 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3943 throw std::out_of_range(
"iterators out of range");
3948 delete m_value.string;
3949 m_value.string =
nullptr;
3952 m_type = value_t::null;
3956 case value_t::object:
3958 assert(m_value.object !=
nullptr);
3959 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3960 last.m_it.object_iterator);
3964 case value_t::array:
3966 assert(m_value.array !=
nullptr);
3967 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3968 last.m_it.array_iterator);
3974 throw std::domain_error(
"cannot use erase() with " + type_name());
4015 assert(m_value.object !=
nullptr);
4016 return m_value.object->erase(key);
4020 throw std::domain_error(
"cannot use erase() with " + type_name());
4055 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4058 assert(m_value.array !=
nullptr);
4059 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4063 throw std::domain_error(
"cannot use erase() with " + type_name());
4096 auto result = end();
4100 assert(m_value.object !=
nullptr);
4101 result.m_it.object_iterator = m_value.object->find(key);
4113 auto result = cend();
4117 assert(m_value.object !=
nullptr);
4118 result.m_it.object_iterator = m_value.object->find(key);
4145 assert(not is_object() or m_value.object !=
nullptr);
4146 return is_object() ? m_value.object->count(key) : 0;
4434 template<
typename IteratorType>
class iteration_proxy;
4450 return iteration_proxy<iterator>(cont);
4458 return iteration_proxy<const_iterator>(cont);
4514 case value_t::array:
4516 assert(m_value.array !=
nullptr);
4517 return m_value.array->empty();
4520 case value_t::object:
4522 assert(m_value.object !=
nullptr);
4523 return m_value.object->empty();
4577 case value_t::array:
4579 assert(m_value.array !=
nullptr);
4580 return m_value.array->size();
4583 case value_t::object:
4585 assert(m_value.object !=
nullptr);
4586 return m_value.object->size();
4637 case value_t::array:
4639 assert(m_value.array !=
nullptr);
4640 return m_value.array->max_size();
4643 case value_t::object:
4645 assert(m_value.object !=
nullptr);
4646 return m_value.object->max_size();
4696 case value_t::number_integer:
4698 m_value.number_integer = 0;
4702 case value_t::number_unsigned:
4704 m_value.number_unsigned = 0;
4708 case value_t::number_float:
4710 m_value.number_float = 0.0;
4714 case value_t::boolean:
4716 m_value.boolean =
false;
4720 case value_t::string:
4722 assert(m_value.string !=
nullptr);
4723 m_value.string->clear();
4727 case value_t::array:
4729 assert(m_value.array !=
nullptr);
4730 m_value.array->clear();
4734 case value_t::object:
4736 assert(m_value.object !=
nullptr);
4737 m_value.object->clear();
4771 if (not(is_null() or is_array()))
4773 throw std::domain_error(
"cannot use push_back() with " + type_name());
4779 m_type = value_t::array;
4780 m_value = value_t::array;
4784 assert(m_value.array !=
nullptr);
4785 m_value.array->push_back(std::move(val));
4787 val.m_type = value_t::null;
4796 push_back(std::move(val));
4807 if (not(is_null() or is_array()))
4809 throw std::domain_error(
"cannot use push_back() with " + type_name());
4815 m_type = value_t::array;
4816 m_value = value_t::array;
4820 assert(m_value.array !=
nullptr);
4821 m_value.array->push_back(val);
4857 if (not(is_null() or is_object()))
4859 throw std::domain_error(
"cannot use push_back() with " + type_name());
4865 m_type = value_t::object;
4866 m_value = value_t::object;
4870 assert(m_value.object !=
nullptr);
4871 m_value.object->insert(val);
4881 return operator[](val.first);
4912 if (pos.m_object !=
this)
4914 throw std::domain_error(
"iterator does not fit current value");
4919 assert(m_value.array !=
nullptr);
4920 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4925 throw std::domain_error(
"cannot use insert() with " + type_name());
4935 return insert(pos, val);
4968 if (pos.m_object !=
this)
4970 throw std::domain_error(
"iterator does not fit current value");
4975 assert(m_value.array !=
nullptr);
4976 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4981 throw std::domain_error(
"cannot use insert() with " + type_name());
5020 throw std::domain_error(
"cannot use insert() with " + type_name());
5024 if (pos.m_object !=
this)
5026 throw std::domain_error(
"iterator does not fit current value");
5029 if (first.m_object != last.m_object)
5031 throw std::domain_error(
"iterators do not fit");
5034 if (first.m_object ==
this or last.m_object ==
this)
5036 throw std::domain_error(
"passed iterators may not belong to container");
5041 assert(m_value.array !=
nullptr);
5042 result.m_it.array_iterator = m_value.array->insert(
5043 pos.m_it.array_iterator,
5044 first.m_it.array_iterator,
5045 last.m_it.array_iterator);
5078 throw std::domain_error(
"cannot use insert() with " + type_name());
5082 if (pos.m_object !=
this)
5084 throw std::domain_error(
"iterator does not fit current value");
5089 assert(m_value.array !=
nullptr);
5090 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5112 std::is_nothrow_move_constructible<value_t>::value and
5113 std::is_nothrow_move_assignable<value_t>::value and
5114 std::is_nothrow_move_constructible<json_value>::value and
5115 std::is_nothrow_move_assignable<json_value>::value
5118 std::swap(m_type, other.m_type);
5119 std::swap(m_value, other.m_value);
5147 assert(m_value.array !=
nullptr);
5148 std::swap(*(m_value.array), other);
5152 throw std::domain_error(
"cannot use swap() with " + type_name());
5181 assert(m_value.object !=
nullptr);
5182 std::swap(*(m_value.object), other);
5186 throw std::domain_error(
"cannot use swap() with " + type_name());
5215 assert(m_value.string !=
nullptr);
5216 std::swap(*(m_value.string), other);
5220 throw std::domain_error(
"cannot use swap() with " + type_name());
5246 static constexpr std::array<uint8_t, 8> order = {{
5259 if (lhs == value_t::discarded or rhs == value_t::discarded)
5264 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5293 const auto lhs_type = lhs.type();
5294 const auto rhs_type = rhs.type();
5296 if (lhs_type == rhs_type)
5300 case value_t::array:
5302 assert(lhs.m_value.array !=
nullptr);
5303 assert(rhs.m_value.array !=
nullptr);
5304 return *lhs.m_value.array == *rhs.m_value.array;
5306 case value_t::object:
5308 assert(lhs.m_value.object !=
nullptr);
5309 assert(rhs.m_value.object !=
nullptr);
5310 return *lhs.m_value.object == *rhs.m_value.object;
5316 case value_t::string:
5318 assert(lhs.m_value.string !=
nullptr);
5319 assert(rhs.m_value.string !=
nullptr);
5320 return *lhs.m_value.string == *rhs.m_value.string;
5322 case value_t::boolean:
5324 return lhs.m_value.boolean == rhs.m_value.boolean;
5326 case value_t::number_integer:
5328 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5330 case value_t::number_unsigned:
5332 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5334 case value_t::number_float:
5336 return lhs.m_value.number_float == rhs.m_value.number_float;
5344 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5346 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5348 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5350 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5352 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5354 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5356 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5358 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5360 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5362 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5364 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5366 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5422 return not (lhs == rhs);
5454 return not v.is_null();
5483 const auto lhs_type = lhs.type();
5484 const auto rhs_type = rhs.type();
5486 if (lhs_type == rhs_type)
5490 case value_t::array:
5492 assert(lhs.m_value.array !=
nullptr);
5493 assert(rhs.m_value.array !=
nullptr);
5494 return *lhs.m_value.array < *rhs.m_value.array;
5496 case value_t::object:
5498 assert(lhs.m_value.object !=
nullptr);
5499 assert(rhs.m_value.object !=
nullptr);
5500 return *lhs.m_value.object < *rhs.m_value.object;
5506 case value_t::string:
5508 assert(lhs.m_value.string !=
nullptr);
5509 assert(rhs.m_value.string !=
nullptr);
5510 return *lhs.m_value.string < *rhs.m_value.string;
5512 case value_t::boolean:
5514 return lhs.m_value.boolean < rhs.m_value.boolean;
5516 case value_t::number_integer:
5518 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5520 case value_t::number_unsigned:
5522 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5524 case value_t::number_float:
5526 return lhs.m_value.number_float < rhs.m_value.number_float;
5534 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5536 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5538 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5540 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5542 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5544 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5546 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5548 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5550 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5552 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5554 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5556 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5562 return operator<(lhs_type, rhs_type);
5584 return not (rhs < lhs);
5606 return not (lhs <= rhs);
5628 return not (lhs < rhs);
5663 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5666 const bool pretty_print = (o.width() > 0);
5667 const auto indentation = (pretty_print ? o.width() : 0);
5673 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5681 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5722 return parser(s, cb).
parse();
5751 return parser(i, cb).
parse();
5759 return parser(i, cb).
parse();
5787 j = parser(i).
parse();
5797 j = parser(i).
parse();
5810 string_t type_name()
const noexcept
5816 case value_t::object:
5818 case value_t::array:
5820 case value_t::string:
5822 case value_t::boolean:
5824 case value_t::discarded:
5839 static std::size_t extra_space(
const string_t& s) noexcept
5841 std::size_t result = 0;
5843 for (
const auto& c : s)
5862 if (c >= 0x00 and c <= 0x1f)
5890 const auto space = extra_space(s);
5897 string_t result(s.size() + space,
'\\');
5898 std::size_t pos = 0;
5900 for (
const auto& c : s)
5907 result[pos + 1] =
'"';
5923 result[pos + 1] =
'b';
5931 result[pos + 1] =
'f';
5939 result[pos + 1] =
'n';
5947 result[pos + 1] =
'r';
5955 result[pos + 1] =
't';
5962 if (c >= 0x00 and c <= 0x1f)
5966 auto hexify = [](
const char v) ->
char 5968 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
5973 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6011 void dump(std::ostream& o,
6012 const bool pretty_print,
6013 const unsigned int indent_step,
6014 const unsigned int current_indent = 0)
const 6017 unsigned int new_indent = current_indent;
6021 case value_t::object:
6023 assert(m_value.object !=
nullptr);
6025 if (m_value.object->empty())
6036 new_indent += indent_step;
6040 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6042 if (i != m_value.object->cbegin())
6044 o << (pretty_print ?
",\n" :
",");
6046 o <<
string_t(new_indent,
' ') <<
"\"" 6047 << escape_string(i->first) <<
"\":" 6048 << (pretty_print ?
" " :
"");
6049 i->second.dump(o, pretty_print, indent_step, new_indent);
6055 new_indent -= indent_step;
6059 o <<
string_t(new_indent,
' ') +
"}";
6063 case value_t::array:
6065 assert(m_value.array !=
nullptr);
6067 if (m_value.array->empty())
6078 new_indent += indent_step;
6082 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6084 if (i != m_value.array->cbegin())
6086 o << (pretty_print ?
",\n" :
",");
6089 i->dump(o, pretty_print, indent_step, new_indent);
6095 new_indent -= indent_step;
6099 o <<
string_t(new_indent,
' ') <<
"]";
6103 case value_t::string:
6105 assert(m_value.string !=
nullptr);
6106 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6110 case value_t::boolean:
6112 o << (m_value.boolean ?
"true" :
"false");
6116 case value_t::number_integer:
6118 o << m_value.number_integer;
6122 case value_t::number_unsigned:
6124 o << m_value.number_unsigned;
6128 case value_t::number_float:
6131 if (m_type.bits.parsed)
6134 if (m_type.bits.has_exp)
6141 if (m_type.bits.exp_cap)
6143 len = snprintf(buf,
sizeof(buf),
"%.*E",
6144 m_type.bits.precision, m_value.number_float) + 1;
6148 len = snprintf(buf,
sizeof(buf),
"%.*e",
6149 m_type.bits.precision, m_value.number_float) + 1;
6153 if (not m_type.bits.exp_plus)
6155 if (len > static_cast<int>(
sizeof(buf)))
6159 for (
int i = 0; i < len; i++)
6163 for (; i + 1 < len; i++)
6165 buf[i] = buf[i + 1];
6176 std::stringstream ss;
6177 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6178 ss << std::setprecision(m_type.bits.precision)
6179 << std::fixed << m_value.number_float;
6185 if (m_value.number_float == 0)
6188 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6197 std::stringstream ss;
6198 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6199 ss << std::setprecision(std::numeric_limits<double>::digits10)
6200 << m_value.number_float;
6207 case value_t::discarded:
6227 type_data_t m_type = value_t::null;
6230 json_value m_value = {};
6247 class primitive_iterator_t
6251 void set_begin() noexcept
6257 void set_end() noexcept
6263 constexpr
bool is_begin()
const noexcept
6265 return (m_it == begin_value);
6269 constexpr
bool is_end()
const noexcept
6271 return (m_it == end_value);
6291 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6301 struct internal_iterator
6304 typename object_t::iterator object_iterator;
6306 typename array_t::iterator array_iterator;
6308 primitive_iterator_t primitive_iterator;
6311 internal_iterator() noexcept
6312 : object_iterator(), array_iterator(), primitive_iterator()
6317 template<
typename IteratorType>
6318 class iteration_proxy
6322 class iteration_proxy_internal
6326 IteratorType anchor;
6328 size_t array_index = 0;
6331 explicit iteration_proxy_internal(IteratorType it) noexcept
6336 iteration_proxy_internal& operator*()
6342 iteration_proxy_internal& operator++()
6351 bool operator!= (
const iteration_proxy_internal& o)
const 6353 return anchor != o.anchor;
6359 assert(anchor.m_object !=
nullptr);
6361 switch (anchor.m_object->type())
6364 case value_t::array:
6366 return std::to_string(array_index);
6370 case value_t::object:
6372 return anchor.key();
6384 typename IteratorType::reference value()
const 6386 return anchor.value();
6391 typename IteratorType::reference container;
6395 explicit iteration_proxy(
typename IteratorType::reference cont)
6400 iteration_proxy_internal begin() noexcept
6402 return iteration_proxy_internal(container.begin());
6406 iteration_proxy_internal end() noexcept
6408 return iteration_proxy_internal(container.end());
6426 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6429 friend class basic_json;
6450 assert(m_object !=
nullptr);
6452 switch (m_object->m_type)
6456 m_it.object_iterator =
typename object_t::iterator();
6462 m_it.array_iterator =
typename array_t::iterator();
6468 m_it.primitive_iterator = primitive_iterator_t();
6476 : m_object(other.m_object)
6478 assert(m_object !=
nullptr);
6480 switch (m_object->m_type)
6484 m_it.object_iterator = other.m_it.object_iterator;
6490 m_it.array_iterator = other.m_it.array_iterator;
6496 m_it.primitive_iterator = other.m_it.primitive_iterator;
6504 : m_object(other.m_object), m_it(other.m_it)
6509 std::is_nothrow_move_constructible<pointer>::value and
6510 std::is_nothrow_move_assignable<pointer>::value and
6511 std::is_nothrow_move_constructible<internal_iterator>::value and
6512 std::is_nothrow_move_assignable<internal_iterator>::value
6515 std::swap(m_object, other.m_object);
6516 std::swap(m_it, other.m_it);
6522 void set_begin() noexcept
6524 assert(m_object !=
nullptr);
6526 switch (m_object->m_type)
6530 assert(m_object->m_value.object !=
nullptr);
6531 m_it.object_iterator = m_object->m_value.object->begin();
6537 assert(m_object->m_value.array !=
nullptr);
6538 m_it.array_iterator = m_object->m_value.array->begin();
6545 m_it.primitive_iterator.set_end();
6551 m_it.primitive_iterator.set_begin();
6558 void set_end() noexcept
6560 assert(m_object !=
nullptr);
6562 switch (m_object->m_type)
6566 assert(m_object->m_value.object !=
nullptr);
6567 m_it.object_iterator = m_object->m_value.object->end();
6573 assert(m_object->m_value.array !=
nullptr);
6574 m_it.array_iterator = m_object->m_value.array->end();
6580 m_it.primitive_iterator.set_end();
6590 assert(m_object !=
nullptr);
6592 switch (m_object->m_type)
6596 assert(m_object->m_value.object);
6597 assert(m_it.object_iterator != m_object->m_value.object->end());
6598 return m_it.object_iterator->second;
6603 assert(m_object->m_value.array);
6604 assert(m_it.array_iterator != m_object->m_value.array->end());
6605 return *m_it.array_iterator;
6610 throw std::out_of_range(
"cannot get value");
6615 if (m_it.primitive_iterator.is_begin())
6621 throw std::out_of_range(
"cannot get value");
6630 assert(m_object !=
nullptr);
6632 switch (m_object->m_type)
6636 assert(m_object->m_value.object);
6637 assert(m_it.object_iterator != m_object->m_value.object->end());
6638 return &(m_it.object_iterator->second);
6643 assert(m_object->m_value.array);
6644 assert(m_it.array_iterator != m_object->m_value.array->end());
6645 return &*m_it.array_iterator;
6650 if (m_it.primitive_iterator.is_begin())
6656 throw std::out_of_range(
"cannot get value");
6665 auto result = *
this;
6673 assert(m_object !=
nullptr);
6675 switch (m_object->m_type)
6679 ++m_it.object_iterator;
6685 ++m_it.array_iterator;
6691 ++m_it.primitive_iterator;
6702 auto result = *
this;
6710 assert(m_object !=
nullptr);
6712 switch (m_object->m_type)
6716 --m_it.object_iterator;
6722 --m_it.array_iterator;
6728 --m_it.primitive_iterator;
6740 if (m_object != other.m_object)
6742 throw std::domain_error(
"cannot compare iterators of different containers");
6745 assert(m_object !=
nullptr);
6747 switch (m_object->m_type)
6751 return (m_it.object_iterator == other.m_it.object_iterator);
6756 return (m_it.array_iterator == other.m_it.array_iterator);
6761 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6769 return not operator==(other);
6776 if (m_object != other.m_object)
6778 throw std::domain_error(
"cannot compare iterators of different containers");
6781 assert(m_object !=
nullptr);
6783 switch (m_object->m_type)
6787 throw std::domain_error(
"cannot compare order of object iterators");
6792 return (m_it.array_iterator < other.m_it.array_iterator);
6797 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6805 return not other.operator < (*this);
6811 return not operator<=(other);
6817 return not operator<(other);
6823 assert(m_object !=
nullptr);
6825 switch (m_object->m_type)
6829 throw std::domain_error(
"cannot use offsets with object iterators");
6834 m_it.array_iterator += i;
6840 m_it.primitive_iterator += i;
6851 return operator+=(-i);
6857 auto result = *
this;
6865 auto result = *
this;
6873 assert(m_object !=
nullptr);
6875 switch (m_object->m_type)
6879 throw std::domain_error(
"cannot use offsets with object iterators");
6884 return m_it.array_iterator - other.m_it.array_iterator;
6889 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6897 assert(m_object !=
nullptr);
6899 switch (m_object->m_type)
6903 throw std::domain_error(
"cannot use operator[] for object iterators");
6908 return *(m_it.array_iterator + n);
6913 throw std::out_of_range(
"cannot get value");
6918 if (m_it.primitive_iterator == -n)
6924 throw std::out_of_range(
"cannot get value");
6931 typename object_t::key_type
key()
const 6933 assert(m_object !=
nullptr);
6935 if (m_object->is_object())
6937 return m_it.object_iterator->first;
6941 throw std::domain_error(
"cannot use key() for non-object iterators");
6955 internal_iterator m_it = internal_iterator();
6992 std::is_nothrow_move_constructible<pointer>::value and
6993 std::is_nothrow_move_assignable<pointer>::value and
6994 std::is_nothrow_move_constructible<internal_iterator>::value and
6995 std::is_nothrow_move_assignable<internal_iterator>::value
6998 base_iterator::operator=(other);
7005 return const_cast<reference>(base_iterator::operator*());
7011 return const_cast<pointer>(base_iterator::operator->());
7018 base_iterator::operator++();
7025 base_iterator::operator++();
7033 base_iterator::operator--();
7040 base_iterator::operator--();
7047 base_iterator::operator+=(i);
7054 base_iterator::operator-=(i);
7061 auto result = *
this;
7069 auto result = *
this;
7077 return base_iterator::operator-(other);
7083 return const_cast<reference>(base_iterator::operator[](n));
7089 return const_cast<reference>(base_iterator::value());
7110 template<
typename Base>
7132 return base_iterator::operator++(1);
7138 base_iterator::operator++();
7145 return base_iterator::operator--(1);
7151 base_iterator::operator--();
7158 base_iterator::operator+=(i);
7165 auto result = *
this;
7173 auto result = *
this;
7181 return this->base() - other.base();
7187 return *(this->operator+(n));
7191 typename object_t::key_type
key()
const 7193 auto it = --this->base();
7200 auto it = --this->base();
7201 return it.operator * ();
7222 enum class token_type
7241 using lexer_char_t =
unsigned char;
7244 explicit lexer(
const string_t& s) noexcept
7245 : m_stream(
nullptr), m_buffer(s)
7247 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7248 assert(m_content !=
nullptr);
7249 m_start = m_cursor = m_content;
7250 m_limit = m_content + s.size();
7254 explicit lexer(std::istream* s) noexcept
7255 : m_stream(s), m_buffer()
7257 assert(m_stream !=
nullptr);
7258 getline(*m_stream, m_buffer);
7259 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7260 assert(m_content !=
nullptr);
7261 m_start = m_cursor = m_content;
7262 m_limit = m_content + m_buffer.size();
7269 lexer(
const lexer&) =
delete;
7270 lexer operator=(
const lexer&) =
delete;
7287 static string_t to_unicode(
const std::size_t codepoint1,
7288 const std::size_t codepoint2 = 0)
7291 std::size_t codepoint = codepoint1;
7294 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7297 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7311 throw std::invalid_argument(
"missing or wrong low surrogate");
7317 if (codepoint < 0x80)
7320 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7322 else if (codepoint <= 0x7ff)
7325 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7326 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7328 else if (codepoint <= 0xffff)
7331 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7332 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7333 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7335 else if (codepoint <= 0x10ffff)
7338 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7339 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7340 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7341 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7345 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7352 static std::string token_type_name(token_type t)
7356 case token_type::uninitialized:
7357 return "<uninitialized>";
7358 case token_type::literal_true:
7359 return "true literal";
7360 case token_type::literal_false:
7361 return "false literal";
7362 case token_type::literal_null:
7363 return "null literal";
7364 case token_type::value_string:
7365 return "string literal";
7366 case token_type::value_number:
7367 return "number literal";
7368 case token_type::begin_array:
7370 case token_type::begin_object:
7372 case token_type::end_array:
7374 case token_type::end_object:
7376 case token_type::name_separator:
7378 case token_type::value_separator:
7380 case token_type::parse_error:
7381 return "<parse error>";
7382 case token_type::end_of_input:
7383 return "end of input";
7387 return "unknown token";
7402 token_type scan() noexcept
7409 assert(m_start !=
nullptr);
7414 unsigned int yyaccept = 0;
7415 static const unsigned char yybm[] =
7417 0, 0, 0, 0, 0, 0, 0, 0,
7418 0, 32, 32, 0, 0, 32, 0, 0,
7419 128, 128, 128, 128, 128, 128, 128, 128,
7420 128, 128, 128, 128, 128, 128, 128, 128,
7421 160, 128, 0, 128, 128, 128, 128, 128,
7422 128, 128, 128, 128, 128, 128, 128, 128,
7423 192, 192, 192, 192, 192, 192, 192, 192,
7424 192, 192, 128, 128, 128, 128, 128, 128,
7425 128, 128, 128, 128, 128, 128, 128, 128,
7426 128, 128, 128, 128, 128, 128, 128, 128,
7427 128, 128, 128, 128, 128, 128, 128, 128,
7428 128, 128, 128, 128, 0, 128, 128, 128,
7429 128, 128, 128, 128, 128, 128, 128, 128,
7430 128, 128, 128, 128, 128, 128, 128, 128,
7431 128, 128, 128, 128, 128, 128, 128, 128,
7432 128, 128, 128, 128, 128, 128, 128, 128,
7433 128, 128, 128, 128, 128, 128, 128, 128,
7434 128, 128, 128, 128, 128, 128, 128, 128,
7435 128, 128, 128, 128, 128, 128, 128, 128,
7436 128, 128, 128, 128, 128, 128, 128, 128,
7437 128, 128, 128, 128, 128, 128, 128, 128,
7438 128, 128, 128, 128, 128, 128, 128, 128,
7439 128, 128, 128, 128, 128, 128, 128, 128,
7440 128, 128, 128, 128, 128, 128, 128, 128,
7441 128, 128, 128, 128, 128, 128, 128, 128,
7442 128, 128, 128, 128, 128, 128, 128, 128,
7443 128, 128, 128, 128, 128, 128, 128, 128,
7444 128, 128, 128, 128, 128, 128, 128, 128,
7445 128, 128, 128, 128, 128, 128, 128, 128,
7446 128, 128, 128, 128, 128, 128, 128, 128,
7447 128, 128, 128, 128, 128, 128, 128, 128,
7448 128, 128, 128, 128, 128, 128, 128, 128,
7450 if ((m_limit - m_cursor) < 5)
7455 if (yybm[0 + yych] & 32)
7457 goto basic_json_parser_6;
7467 goto basic_json_parser_2;
7471 goto basic_json_parser_4;
7473 goto basic_json_parser_9;
7479 goto basic_json_parser_4;
7483 goto basic_json_parser_10;
7485 goto basic_json_parser_12;
7494 goto basic_json_parser_4;
7498 goto basic_json_parser_13;
7500 goto basic_json_parser_15;
7506 goto basic_json_parser_17;
7510 goto basic_json_parser_19;
7512 goto basic_json_parser_4;
7524 goto basic_json_parser_21;
7528 goto basic_json_parser_4;
7530 goto basic_json_parser_23;
7536 goto basic_json_parser_24;
7540 goto basic_json_parser_4;
7542 goto basic_json_parser_25;
7551 goto basic_json_parser_26;
7553 goto basic_json_parser_4;
7559 goto basic_json_parser_28;
7563 goto basic_json_parser_30;
7565 goto basic_json_parser_4;
7569 basic_json_parser_2:
7572 return token_type::end_of_input;
7574 basic_json_parser_4:
7576 basic_json_parser_5:
7578 return token_type::parse_error;
7580 basic_json_parser_6:
7582 if (m_limit <= m_cursor)
7587 if (yybm[0 + yych] & 32)
7589 goto basic_json_parser_6;
7594 basic_json_parser_9:
7596 yych = *(m_marker = ++m_cursor);
7599 goto basic_json_parser_5;
7601 goto basic_json_parser_32;
7602 basic_json_parser_10:
7605 return token_type::value_separator;
7607 basic_json_parser_12:
7611 goto basic_json_parser_5;
7615 goto basic_json_parser_13;
7619 goto basic_json_parser_15;
7621 goto basic_json_parser_5;
7622 basic_json_parser_13:
7624 yych = *(m_marker = ++m_cursor);
7629 goto basic_json_parser_37;
7636 goto basic_json_parser_38;
7640 goto basic_json_parser_38;
7643 basic_json_parser_14:
7645 return token_type::value_number;
7647 basic_json_parser_15:
7649 m_marker = ++m_cursor;
7650 if ((m_limit - m_cursor) < 3)
7655 if (yybm[0 + yych] & 64)
7657 goto basic_json_parser_15;
7663 goto basic_json_parser_37;
7665 goto basic_json_parser_14;
7671 goto basic_json_parser_38;
7675 goto basic_json_parser_38;
7677 goto basic_json_parser_14;
7679 basic_json_parser_17:
7682 return token_type::name_separator;
7684 basic_json_parser_19:
7687 return token_type::begin_array;
7689 basic_json_parser_21:
7692 return token_type::end_array;
7694 basic_json_parser_23:
7696 yych = *(m_marker = ++m_cursor);
7699 goto basic_json_parser_39;
7701 goto basic_json_parser_5;
7702 basic_json_parser_24:
7704 yych = *(m_marker = ++m_cursor);
7707 goto basic_json_parser_40;
7709 goto basic_json_parser_5;
7710 basic_json_parser_25:
7712 yych = *(m_marker = ++m_cursor);
7715 goto basic_json_parser_41;
7717 goto basic_json_parser_5;
7718 basic_json_parser_26:
7721 return token_type::begin_object;
7723 basic_json_parser_28:
7726 return token_type::end_object;
7728 basic_json_parser_30:
7730 yych = *(m_marker = ++m_cursor);
7733 goto basic_json_parser_42;
7735 goto basic_json_parser_5;
7736 basic_json_parser_31:
7738 if (m_limit <= m_cursor)
7743 basic_json_parser_32:
7744 if (yybm[0 + yych] & 128)
7746 goto basic_json_parser_31;
7750 goto basic_json_parser_33;
7754 goto basic_json_parser_34;
7756 goto basic_json_parser_36;
7757 basic_json_parser_33:
7758 m_cursor = m_marker;
7761 goto basic_json_parser_5;
7765 goto basic_json_parser_14;
7767 basic_json_parser_34:
7770 return token_type::value_string;
7772 basic_json_parser_36:
7774 if (m_limit <= m_cursor)
7785 goto basic_json_parser_31;
7789 goto basic_json_parser_33;
7791 goto basic_json_parser_31;
7799 goto basic_json_parser_33;
7801 goto basic_json_parser_31;
7807 goto basic_json_parser_31;
7809 goto basic_json_parser_33;
7819 goto basic_json_parser_31;
7823 goto basic_json_parser_31;
7825 goto basic_json_parser_33;
7833 goto basic_json_parser_31;
7835 goto basic_json_parser_33;
7841 goto basic_json_parser_31;
7845 goto basic_json_parser_43;
7847 goto basic_json_parser_33;
7851 basic_json_parser_37:
7855 goto basic_json_parser_33;
7859 goto basic_json_parser_44;
7861 goto basic_json_parser_33;
7862 basic_json_parser_38:
7868 goto basic_json_parser_46;
7870 goto basic_json_parser_33;
7876 goto basic_json_parser_46;
7880 goto basic_json_parser_33;
7884 goto basic_json_parser_47;
7886 goto basic_json_parser_33;
7888 basic_json_parser_39:
7892 goto basic_json_parser_49;
7894 goto basic_json_parser_33;
7895 basic_json_parser_40:
7899 goto basic_json_parser_50;
7901 goto basic_json_parser_33;
7902 basic_json_parser_41:
7906 goto basic_json_parser_51;
7908 goto basic_json_parser_33;
7909 basic_json_parser_42:
7913 goto basic_json_parser_52;
7915 goto basic_json_parser_33;
7916 basic_json_parser_43:
7918 if (m_limit <= m_cursor)
7927 goto basic_json_parser_33;
7931 goto basic_json_parser_54;
7933 goto basic_json_parser_33;
7939 goto basic_json_parser_54;
7943 goto basic_json_parser_33;
7947 goto basic_json_parser_54;
7949 goto basic_json_parser_33;
7951 basic_json_parser_44:
7953 m_marker = ++m_cursor;
7954 if ((m_limit - m_cursor) < 3)
7963 goto basic_json_parser_14;
7967 goto basic_json_parser_44;
7969 goto basic_json_parser_14;
7975 goto basic_json_parser_38;
7979 goto basic_json_parser_38;
7981 goto basic_json_parser_14;
7983 basic_json_parser_46:
7987 goto basic_json_parser_33;
7991 goto basic_json_parser_33;
7993 basic_json_parser_47:
7995 if (m_limit <= m_cursor)
8002 goto basic_json_parser_14;
8006 goto basic_json_parser_47;
8008 goto basic_json_parser_14;
8009 basic_json_parser_49:
8013 goto basic_json_parser_55;
8015 goto basic_json_parser_33;
8016 basic_json_parser_50:
8020 goto basic_json_parser_56;
8022 goto basic_json_parser_33;
8023 basic_json_parser_51:
8027 goto basic_json_parser_58;
8029 goto basic_json_parser_33;
8030 basic_json_parser_52:
8035 basic_json_parser_54:
8037 if (m_limit <= m_cursor)
8046 goto basic_json_parser_33;
8050 goto basic_json_parser_60;
8052 goto basic_json_parser_33;
8058 goto basic_json_parser_60;
8062 goto basic_json_parser_33;
8066 goto basic_json_parser_60;
8068 goto basic_json_parser_33;
8070 basic_json_parser_55:
8074 goto basic_json_parser_61;
8076 goto basic_json_parser_33;
8077 basic_json_parser_56:
8080 return token_type::literal_null;
8082 basic_json_parser_58:
8085 return token_type::literal_true;
8087 basic_json_parser_60:
8089 if (m_limit <= m_cursor)
8098 goto basic_json_parser_33;
8102 goto basic_json_parser_63;
8104 goto basic_json_parser_33;
8110 goto basic_json_parser_63;
8114 goto basic_json_parser_33;
8118 goto basic_json_parser_63;
8120 goto basic_json_parser_33;
8122 basic_json_parser_61:
8125 return token_type::literal_false;
8127 basic_json_parser_63:
8129 if (m_limit <= m_cursor)
8138 goto basic_json_parser_33;
8142 goto basic_json_parser_31;
8144 goto basic_json_parser_33;
8150 goto basic_json_parser_31;
8154 goto basic_json_parser_33;
8158 goto basic_json_parser_31;
8160 goto basic_json_parser_33;
8167 void yyfill() noexcept
8169 if (m_stream ==
nullptr or not * m_stream)
8174 const auto offset_start = m_start - m_content;
8175 const auto offset_marker = m_marker - m_start;
8176 const auto offset_cursor = m_cursor - m_start;
8178 m_buffer.erase(0, static_cast<size_t>(offset_start));
8180 assert(m_stream !=
nullptr);
8181 std::getline(*m_stream, line);
8182 m_buffer +=
"\n" + line;
8184 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8185 assert(m_content !=
nullptr);
8186 m_start = m_content;
8187 m_marker = m_start + offset_marker;
8188 m_cursor = m_start + offset_cursor;
8189 m_limit = m_start + m_buffer.size() - 1;
8195 assert(m_start !=
nullptr);
8196 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8197 static_cast<size_t>(m_cursor - m_start));
8224 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8227 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8283 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8284 4).c_str(),
nullptr, 16);
8287 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8290 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8292 throw std::invalid_argument(
"missing low surrogate");
8296 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8297 (i + 7), 4).c_str(),
nullptr, 16);
8298 result += to_unicode(codepoint, codepoint2);
8305 result += to_unicode(codepoint);
8317 result.append(1, static_cast<typename string_t::value_type>(*i));
8344 long double str_to_float_t(
long double* ,
char** endptr)
const 8346 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8364 double str_to_float_t(
double* ,
char** endptr)
const 8366 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8384 float str_to_float_t(
float* ,
char** endptr)
const 8386 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8416 void get_number(basic_json& result)
const 8418 assert(m_start !=
nullptr);
8420 const lexer::lexer_char_t* curptr = m_start;
8423 result.m_type.bits.parsed =
true;
8428 uint8_t found_radix_point = 0;
8429 uint8_t precision = 0;
8443 type = value_t::number_integer;
8444 max =
static_cast<uint64_t
>(std::numeric_limits<number_integer_t>::max()) + 1;
8449 type = value_t::number_unsigned;
8450 max =
static_cast<uint64_t
>(std::numeric_limits<number_unsigned_t>::max());
8458 for (; curptr < m_cursor; curptr++)
8461 if (*curptr < '0' || *curptr >
'9')
8466 type = value_t::number_float;
8470 found_radix_point = 0xFF;
8475 type = value_t::number_float;
8476 result.m_type.bits.has_exp =
true;
8479 result.m_type.bits.exp_cap = (*curptr ==
'E');
8482 result.m_type.bits.exp_plus = (*(++curptr) ==
'+');
8487 if (type != value_t::number_float)
8490 auto temp = value * 10 + *curptr - 0x30;
8493 if (temp < value || temp > max)
8496 type = value_t::number_float;
8509 result.m_type.bits.precision = precision & found_radix_point;
8512 if (type == value_t::number_unsigned)
8514 result.m_value.number_unsigned = value;
8516 else if (type == value_t::number_integer)
8523 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8527 result.m_type = type;
8532 std::istream* m_stream =
nullptr;
8536 const lexer_char_t* m_content =
nullptr;
8538 const lexer_char_t* m_start =
nullptr;
8540 const lexer_char_t* m_marker =
nullptr;
8542 const lexer_char_t* m_cursor =
nullptr;
8544 const lexer_char_t* m_limit =
nullptr;
8557 : callback(cb), m_lexer(s)
8565 : callback(cb), m_lexer(&_is)
8574 basic_json result = parse_internal(
true);
8576 expect(lexer::token_type::end_of_input);
8585 basic_json parse_internal(
bool keep)
8587 auto result = basic_json(value_t::discarded);
8591 case lexer::token_type::begin_object:
8593 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8596 result.m_type = value_t::object;
8597 result.m_value = json_value(value_t::object);
8604 if (last_token == lexer::token_type::end_object)
8607 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8609 result = basic_json(value_t::discarded);
8615 unexpect(lexer::token_type::value_separator);
8621 if (last_token == lexer::token_type::value_separator)
8627 expect(lexer::token_type::value_string);
8628 const auto key = m_lexer.get_string();
8630 bool keep_tag =
false;
8636 keep_tag = callback(depth, parse_event_t::key, k);
8646 expect(lexer::token_type::name_separator);
8650 auto value = parse_internal(keep);
8651 if (keep and keep_tag and not value.is_discarded())
8653 result[key] = std::move(value);
8656 while (last_token == lexer::token_type::value_separator);
8659 expect(lexer::token_type::end_object);
8661 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8663 result = basic_json(value_t::discarded);
8669 case lexer::token_type::begin_array:
8671 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8674 result.m_type = value_t::array;
8675 result.m_value = json_value(value_t::array);
8682 if (last_token == lexer::token_type::end_array)
8685 if (callback and not callback(--depth, parse_event_t::array_end, result))
8687 result = basic_json(value_t::discarded);
8693 unexpect(lexer::token_type::value_separator);
8699 if (last_token == lexer::token_type::value_separator)
8705 auto value = parse_internal(keep);
8706 if (keep and not value.is_discarded())
8708 result.push_back(std::move(value));
8711 while (last_token == lexer::token_type::value_separator);
8714 expect(lexer::token_type::end_array);
8716 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8718 result = basic_json(value_t::discarded);
8724 case lexer::token_type::literal_null:
8727 result.m_type = value_t::null;
8731 case lexer::token_type::value_string:
8733 const auto s = m_lexer.get_string();
8735 result = basic_json(s);
8739 case lexer::token_type::literal_true:
8742 result.m_type = value_t::boolean;
8743 result.m_value =
true;
8747 case lexer::token_type::literal_false:
8750 result.m_type = value_t::boolean;
8751 result.m_value =
false;
8755 case lexer::token_type::value_number:
8757 m_lexer.get_number(result);
8765 unexpect(last_token);
8769 if (keep and callback and not callback(depth, parse_event_t::value, result))
8771 result = basic_json(value_t::discarded);
8777 typename lexer::token_type get_token() noexcept
8779 last_token = m_lexer.scan();
8783 void expect(
typename lexer::token_type t)
const 8785 if (t != last_token)
8787 std::string error_msg =
"parse error - unexpected ";
8788 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8789 lexer::token_type_name(last_token));
8790 error_msg +=
"; expected " + lexer::token_type_name(t);
8791 throw std::invalid_argument(error_msg);
8795 void unexpect(
typename lexer::token_type t)
const 8797 if (t == last_token)
8799 std::string error_msg =
"parse error - unexpected ";
8800 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8801 lexer::token_type_name(last_token));
8802 throw std::invalid_argument(error_msg);
8812 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8832 friend class basic_json;
8858 : reference_tokens(split(s))
8876 std::string to_string()
const noexcept
8880 for (
const auto& reference_token : reference_tokens)
8882 result +=
"/" + escape(reference_token);
8889 operator std::string()
const 8896 std::string pop_back()
8900 throw std::domain_error(
"JSON pointer has no parent");
8903 auto last = reference_tokens.back();
8904 reference_tokens.pop_back();
8909 bool is_root()
const 8911 return reference_tokens.empty();
8918 throw std::domain_error(
"JSON pointer has no parent");
8922 result.reference_tokens = {reference_tokens[0]};
8935 for (
const auto& reference_token : reference_tokens)
8937 switch (result->m_type)
8941 if (reference_token ==
"0")
8944 result = &result->operator[](0);
8949 result = &result->operator[](reference_token);
8954 case value_t::object:
8957 result = &result->operator[](reference_token);
8961 case value_t::array:
8964 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8977 throw std::domain_error(
"invalid value to unflatten");
9000 for (
const auto& reference_token : reference_tokens)
9002 switch (ptr->m_type)
9004 case value_t::object:
9007 ptr = &ptr->operator[](reference_token);
9011 case value_t::array:
9014 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9016 throw std::domain_error(
"array index must not begin with '0'");
9019 if (reference_token ==
"-")
9022 ptr = &ptr->operator[](ptr->m_value.array->size());
9027 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9034 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9044 for (
const auto& reference_token : reference_tokens)
9046 switch (ptr->m_type)
9048 case value_t::object:
9051 ptr = &ptr->
at(reference_token);
9055 case value_t::array:
9057 if (reference_token ==
"-")
9060 throw std::out_of_range(
"array index '-' (" +
9061 std::to_string(ptr->m_value.array->size()) +
9062 ") is out of range");
9066 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9068 throw std::domain_error(
"array index must not begin with '0'");
9072 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9078 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9096 for (
const auto& reference_token : reference_tokens)
9098 switch (ptr->m_type)
9100 case value_t::object:
9103 ptr = &ptr->operator[](reference_token);
9107 case value_t::array:
9109 if (reference_token ==
"-")
9112 throw std::out_of_range(
"array index '-' (" +
9113 std::to_string(ptr->m_value.array->size()) +
9114 ") is out of range");
9118 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9120 throw std::domain_error(
"array index must not begin with '0'");
9124 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9130 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9140 for (
const auto& reference_token : reference_tokens)
9142 switch (ptr->m_type)
9144 case value_t::object:
9147 ptr = &ptr->
at(reference_token);
9151 case value_t::array:
9153 if (reference_token ==
"-")
9156 throw std::out_of_range(
"array index '-' (" +
9157 std::to_string(ptr->m_value.array->size()) +
9158 ") is out of range");
9162 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9164 throw std::domain_error(
"array index must not begin with '0'");
9168 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9174 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9183 static std::vector<std::string> split(std::string reference_string)
9185 std::vector<std::string> result;
9188 if (reference_string.empty())
9194 if (reference_string[0] !=
'/')
9196 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9204 size_t slash = reference_string.find_first_of(
"/", 1),
9213 slash = reference_string.find_first_of(
"/", start))
9217 auto reference_token = reference_string.substr(start, slash - start);
9220 for (
size_t pos = reference_token.find_first_of(
"~");
9221 pos != std::string::npos;
9222 pos = reference_token.find_first_of(
"~", pos + 1))
9224 assert(reference_token[pos] ==
'~');
9227 if (pos == reference_token.size() - 1 or
9228 (reference_token[pos + 1] !=
'0' and
9229 reference_token[pos + 1] !=
'1'))
9231 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9236 unescape(reference_token);
9237 result.push_back(reference_token);
9258 static void replace_substring(std::string& s,
9259 const std::string& f,
9260 const std::string& t)
9262 assert(not f.empty());
9265 size_t pos = s.find(f);
9266 pos != std::string::npos;
9267 s.replace(pos, f.size(), t),
9268 pos = s.find(f, pos + t.size())
9273 static std::string escape(std::string s)
9276 replace_substring(s,
"~",
"~0");
9277 replace_substring(s,
"/",
"~1");
9282 static void unescape(std::string& s)
9285 replace_substring(s,
"~1",
"/");
9287 replace_substring(s,
"~0",
"~");
9297 static void flatten(
const std::string& reference_string,
9298 const basic_json& value,
9301 switch (value.m_type)
9303 case value_t::array:
9305 if (value.m_value.array->empty())
9308 result[reference_string] =
nullptr;
9313 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9315 flatten(reference_string +
"/" + std::to_string(i),
9316 value.m_value.array->operator[](i), result);
9322 case value_t::object:
9324 if (value.m_value.object->empty())
9327 result[reference_string] =
nullptr;
9332 for (
const auto& element : *value.m_value.object)
9334 flatten(reference_string +
"/" + escape(element.first),
9335 element.second, result);
9344 result[reference_string] = value;
9355 static basic_json unflatten(
const basic_json& value)
9359 throw std::domain_error(
"only objects can be unflattened");
9365 for (
const auto& element : *value.m_value.object)
9367 if (not element.second.is_primitive())
9369 throw std::domain_error(
"values in object must be primitive");
9377 json_pointer(element.first).get_and_create(result) = element.second;
9385 std::vector<std::string> reference_tokens {};
9430 return ptr.get_unchecked(
this);
9457 return ptr.get_unchecked(
this);
9482 return ptr.get_checked(
this);
9507 return ptr.get_checked(
this);
9532 basic_json flatten()
const 9534 basic_json result(value_t::object);
9535 json_pointer::flatten(
"", *
this, result);
9566 basic_json unflatten()
const 9568 return json_pointer::unflatten(*
this);
9616 basic_json patch(
const basic_json& patch)
const 9619 basic_json result = *
this;
9622 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9624 const auto get_op = [](
const std::string op)
9628 return patch_operations::add;
9632 return patch_operations::remove;
9634 if (op ==
"replace")
9636 return patch_operations::replace;
9640 return patch_operations::move;
9644 return patch_operations::copy;
9648 return patch_operations::test;
9651 return patch_operations::invalid;
9655 const auto operation_add = [&result](
json_pointer & ptr, basic_json val)
9666 if (top_pointer != ptr)
9668 basic_json& x = result.
at(top_pointer);
9672 const auto last_path = ptr.pop_back();
9673 basic_json& parent = result[ptr];
9675 switch (parent.m_type)
9678 case value_t::object:
9681 parent[last_path] = val;
9685 case value_t::array:
9687 if (last_path ==
"-")
9694 const auto idx = std::stoi(last_path);
9695 if (static_cast<size_type>(idx) > parent.
size())
9698 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9719 const auto operation_remove = [&result](
json_pointer & ptr)
9722 const auto last_path = ptr.pop_back();
9723 basic_json& parent = result.
at(ptr);
9729 auto it = parent.
find(last_path);
9730 if (it != parent.
end())
9736 throw std::out_of_range(
"key '" + last_path +
"' not found");
9742 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9750 throw std::invalid_argument(
"JSON patch must be an array of objects");
9754 for (
const auto& val : patch)
9757 const auto get_value = [&val](
const std::string & op,
9758 const std::string & member,
9759 bool string_type) -> basic_json&
9762 auto it = val.m_value.object->find(member);
9765 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9768 if (it == val.m_value.object->end())
9770 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9774 if (string_type and not it->second.is_string())
9776 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9784 if (not val.is_object())
9786 throw std::invalid_argument(
"JSON patch must be an array of objects");
9790 const std::string op = get_value(
"op",
"op",
true);
9791 const std::string path = get_value(op,
"path",
true);
9796 case patch_operations::add:
9798 operation_add(ptr, get_value(
"add",
"value",
false));
9802 case patch_operations::remove:
9804 operation_remove(ptr);
9808 case patch_operations::replace:
9811 result.
at(ptr) = get_value(
"replace",
"value",
false);
9815 case patch_operations::move:
9817 const std::string from_path = get_value(
"move",
"from",
true);
9821 basic_json v = result.
at(from_ptr);
9827 operation_remove(from_ptr);
9828 operation_add(ptr, v);
9832 case patch_operations::copy:
9834 const std::string from_path = get_value(
"copy",
"from",
true);;
9838 result[ptr] = result.
at(from_ptr);
9842 case patch_operations::test:
9844 bool success =
false;
9849 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9851 catch (std::out_of_range&)
9859 throw std::domain_error(
"unsuccessful: " + val.dump());
9865 case patch_operations::invalid:
9869 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9909 static basic_json diff(
const basic_json& source,
9910 const basic_json& target,
9911 std::string path =
"") noexcept
9914 basic_json result(value_t::array);
9917 if (source == target)
9922 if (source.
type() != target.
type())
9934 switch (source.
type())
9936 case value_t::array:
9940 while (i < source.
size() and i < target.
size())
9943 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
9944 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9952 while (i < source.
size())
9954 result.push_back(
object(
9957 {
"path", path +
"/" + std::to_string(i)}
9963 while (i < target.
size())
9968 {
"path", path +
"/" + std::to_string(i)},
9969 {
"value", target[i]}
9977 case value_t::object:
9980 for (
auto it = source.
begin(); it != source.
end(); ++it)
9983 const auto key = json_pointer::escape(it.key());
9985 if (target.
find(it.key()) != target.
end())
9988 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
9989 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9994 result.push_back(
object(
9997 {
"path", path +
"/" + key}
10003 for (
auto it = target.
begin(); it != target.
end(); ++it)
10005 if (source.
find(it.key()) == source.
end())
10008 const auto key = json_pointer::escape(it.key());
10012 {
"path", path +
"/" + key},
10013 {
"value", it.value()}
10073 is_nothrow_move_constructible<nlohmann::json>::value and
10074 is_nothrow_move_assignable<nlohmann::json>::value
10092 const auto& h = hash<nlohmann::json::string_t>();
10110 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10126 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10127 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
basic_json(const value_t value_type)
create an empty value with a given type
basic_json(const array_t &val)
create an array (explicit)
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
const_reference operator[](size_type idx) const
access specified array element
reference value() const
return the value of an iterator
json_reverse_iterator & operator--()
pre-decrement (–it)
void clear() noexcept
clears the contents
bool operator==(const const_iterator &other) const
comparison: equal
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
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
iterator & operator+=(difference_type i)
add to iterator
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
const_iterator operator-(difference_type i)
subtract from iterator
BooleanType boolean_t
a type for a boolean
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference operator+=(const typename object_t::value_type &val)
add an object to an object
reference operator*() const
return a reference to the value pointed to by the iterator
basic_json(const typename string_t::value_type *val)
create a string (explicit)
reference operator[](difference_type n) const
access to successor
iterator find(typename object_t::key_type key)
find an element in a JSON object
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
basic_json(const string_t &val)
create a string (explicit)
void push_back(const basic_json &val)
add an object to an array
void erase(const size_type idx)
remove element from a JSON array given an index
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
reference front()
access the first element
void swap(object_t &other)
exchanges the values
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
const_iterator & operator+=(difference_type i)
add to iterator
a class to store JSON values
basic_json(const int val) noexcept
create an integer number from an enum type (explicit)
reference value() const
return the value of an iterator
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
NumberIntegerType number_integer_t
a type for a number (integer)
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
const_iterator operator+(difference_type i)
add to iterator
constexpr bool is_object() const noexcept
return whether value is an object
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
a mutable random access iterator for the basic_json class
static basic_json parse(std::istream &&i, parser_callback_t cb=nullptr)
deserialize from stream
const_iterator operator++(int)
post-increment (it++)
const_iterator cend() const noexcept
returns a const iterator to one past the last element
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)
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
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
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
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
PointerType get_ptr() noexcept
get a pointer value (implicit)
constexpr bool is_string() const noexcept
return whether value is a string
reference back()
access the last element
const value_type & const_reference
the type of an element const reference
typename basic_json::const_pointer pointer
defines a pointer to the type iterated over (value_type)
void push_back(const typename object_t::value_type &val)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
static basic_json parse(const string_t &s, parser_callback_t cb=nullptr)
deserialize from string
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
reference operator[](difference_type n) const
access to successor
static allocator_type get_allocator()
returns the allocator associated with the container
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_reference operator[](T *key) const
read-only access specified object element
json_reverse_iterator operator+(difference_type i) const
add to iterator
bool empty() const noexcept
checks whether the container is empty
std::size_t size_type
a type to represent container sizes
object_t::key_type key() const
return the key of an object iterator
const_iterator(const iterator &other) noexcept
copy constructor given a nonconst iterator
basic_json(const CompatibleArrayType &val)
create an array (implicit)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
const_reference at(size_type idx) const
access specified array element with bounds checking
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
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
iterator insert(const_iterator pos, const basic_json &val)
inserts element
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
iterator & operator++()
pre-increment (++it)
bool operator<(const const_iterator &other) const
comparison: smaller
iterator operator++(int)
post-increment (it++)
basic_json(basic_json &&other) noexcept
move constructor
const_iterator operator--(int)
post-decrement (it–)
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
iterator & operator=(iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
object (unordered set of name/value pairs)
size_type max_size() const noexcept
returns the maximum possible number of elements
iterator operator--(int)
post-decrement (it–)
iterator operator-(difference_type i)
subtract from iterator
const_iterator & operator--()
pre-decrement (–it)
string_t dump(const int indent=-1) const
serialization
basic_json value_type
the type of elements in a basic_json container
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
AllocatorType< basic_json > allocator_type
the allocator type
StringType string_t
a type for a string
reference operator+=(const basic_json &val)
add an object to an array
difference_type operator-(const const_iterator &other) const
return difference
value_type & reference
the type of an element reference
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_iterator begin() const noexcept
returns a const iterator to the first element
difference_type operator-(const iterator &other) const
return difference
constexpr bool is_array() const noexcept
return whether value is an array
iterator(const iterator &other) noexcept
copy constructor
namespace for Niels Lohmann
typename basic_json::difference_type difference_type
a type to represent differences between iterators
void swap(string_t &other)
exchanges the values
basic_json(const CompatibleNumberIntegerType val) noexcept
create an integer number (implicit)
const_reference front() const
access the first element
bool operator>(const const_iterator &other) const
comparison: greater than
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
pointer operator->() const
dereference the iterator
NumberFloatType number_float_t
a type for a number (floating-point)
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
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
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
constexpr bool is_null() const noexcept
return whether value is null
std::ptrdiff_t difference_type
a type to represent differences between iterators
ValueType get() const
get a value (explicit)
void swap(array_t &other)
exchanges the values
InteratorType erase(InteratorType first, InteratorType last)
remove elements given an iterator range
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
typename Base::reference reference
the reference type for the pointed-to element
const_reference back() const
access the last element
void push_back(basic_json &&val)
add an object to an array
array (ordered collection of values)
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
json_reverse_iterator & operator++()
pre-increment (++it)
static basic_json parse(std::istream &i, parser_callback_t cb=nullptr)
deserialize from stream
friend bool operator==(const_reference lhs, const_reference rhs) 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*
ReferenceType get_ref() const
get a reference value (implicit)
basic_json(const CompatibleNumberUnsignedType val) noexcept
create an unsigned number (implicit)
reference operator*() const
return a reference to the value pointed to by 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
iterator operator+(difference_type i)
add to iterator
basic_json(const CompatibleNumberFloatType val) noexcept
create an floating-point number (implicit)
bool operator<=(const const_iterator &other) const
comparison: less than or equal
InteratorType erase(InteratorType pos)
remove element given an iterator
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
iterator(pointer object) noexcept
constructor for a given JSON instance
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
constexpr bool is_primitive() const noexcept
return whether type is primitive
const_iterator & operator++()
pre-increment (++it)
pointer operator->() const
dereference the iterator
reference value() const
return the value of an iterator
constexpr bool is_structured() const noexcept
return whether type is structured
std::bidirectional_iterator_tag iterator_category
the category of the iterator
basic_json(boolean_t val) noexcept
create a boolean (explicit)
iterator end() noexcept
returns an iterator to one past the last element
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
difference_type operator-(const json_reverse_iterator &other) const
return difference
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
iterator begin() noexcept
returns an iterator to the first element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
const_iterator end() const noexcept
returns a const iterator to one past the last element
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
const_iterator & operator=(const_iterator other) noexcept( std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value )
copy assignment
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
object_t::key_type key() const
return the key of an object iterator
reference operator+=(basic_json &&val)
add an object to an array
reference operator[](difference_type n) const
access to successor
a const random access iterator for the basic_json class
constexpr bool is_number() const noexcept
return whether value is a number
a template for a reverse iterator class
basic_json(std::istream &i, parser_callback_t cb=nullptr)
construct a JSON value given an input stream
typename basic_json::const_reference reference
defines a reference to the type iterated over (value_type)
json_reverse_iterator operator++(int)
post-increment (it++)
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
reference operator[](size_type idx)
access specified array element
bool operator!=(const const_iterator &other) const
comparison: not equal
json_reverse_iterator & operator+=(difference_type i)
add to iterator
reference at(size_type idx)
access specified array element with bounds checking
size_type size() const noexcept
returns the number of elements
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const object_t &val)
create an object (explicit)
basic_json(const number_unsigned_t val) noexcept
create an unsigned integer number (explicit)
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
const_iterator(const const_iterator &other) noexcept
copy constructor
iterator & operator--()
pre-decrement (–it)
iterator insert(const_iterator pos, basic_json &&val)
inserts element
ReferenceType get_ref()
get a reference value (implicit)
const_iterator & operator-=(difference_type i)
subtract from iterator
basic_json(const CompatibleStringType &val)
create a string (implicit)
basic_json(const basic_json &other)
copy constructor
reference operator[](T *key)
access specified object element
parse_event_t
JSON callback events.