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);
4911 if (is_object() and init.size() == 2 and init.begin()->is_string())
4913 const string_t key = *init.begin();
4914 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
4918 push_back(basic_json(init));
4960 if (pos.m_object !=
this)
4962 throw std::domain_error(
"iterator does not fit current value");
4967 assert(m_value.array !=
nullptr);
4968 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4973 throw std::domain_error(
"cannot use insert() with " + type_name());
4983 return insert(pos, val);
5016 if (pos.m_object !=
this)
5018 throw std::domain_error(
"iterator does not fit current value");
5023 assert(m_value.array !=
nullptr);
5024 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5029 throw std::domain_error(
"cannot use insert() with " + type_name());
5068 throw std::domain_error(
"cannot use insert() with " + type_name());
5072 if (pos.m_object !=
this)
5074 throw std::domain_error(
"iterator does not fit current value");
5077 if (first.m_object != last.m_object)
5079 throw std::domain_error(
"iterators do not fit");
5082 if (first.m_object ==
this or last.m_object ==
this)
5084 throw std::domain_error(
"passed iterators may not belong to container");
5089 assert(m_value.array !=
nullptr);
5090 result.m_it.array_iterator = m_value.array->insert(
5091 pos.m_it.array_iterator,
5092 first.m_it.array_iterator,
5093 last.m_it.array_iterator);
5126 throw std::domain_error(
"cannot use insert() with " + type_name());
5130 if (pos.m_object !=
this)
5132 throw std::domain_error(
"iterator does not fit current value");
5137 assert(m_value.array !=
nullptr);
5138 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5160 std::is_nothrow_move_constructible<value_t>::value and
5161 std::is_nothrow_move_assignable<value_t>::value and
5162 std::is_nothrow_move_constructible<json_value>::value and
5163 std::is_nothrow_move_assignable<json_value>::value
5166 std::swap(m_type, other.m_type);
5167 std::swap(m_value, other.m_value);
5195 assert(m_value.array !=
nullptr);
5196 std::swap(*(m_value.array), other);
5200 throw std::domain_error(
"cannot use swap() with " + type_name());
5229 assert(m_value.object !=
nullptr);
5230 std::swap(*(m_value.object), other);
5234 throw std::domain_error(
"cannot use swap() with " + type_name());
5263 assert(m_value.string !=
nullptr);
5264 std::swap(*(m_value.string), other);
5268 throw std::domain_error(
"cannot use swap() with " + type_name());
5294 static constexpr std::array<uint8_t, 8> order = {{
5307 if (lhs == value_t::discarded or rhs == value_t::discarded)
5312 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5341 const auto lhs_type = lhs.type();
5342 const auto rhs_type = rhs.type();
5344 if (lhs_type == rhs_type)
5348 case value_t::array:
5350 assert(lhs.m_value.array !=
nullptr);
5351 assert(rhs.m_value.array !=
nullptr);
5352 return *lhs.m_value.array == *rhs.m_value.array;
5354 case value_t::object:
5356 assert(lhs.m_value.object !=
nullptr);
5357 assert(rhs.m_value.object !=
nullptr);
5358 return *lhs.m_value.object == *rhs.m_value.object;
5364 case value_t::string:
5366 assert(lhs.m_value.string !=
nullptr);
5367 assert(rhs.m_value.string !=
nullptr);
5368 return *lhs.m_value.string == *rhs.m_value.string;
5370 case value_t::boolean:
5372 return lhs.m_value.boolean == rhs.m_value.boolean;
5374 case value_t::number_integer:
5376 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5378 case value_t::number_unsigned:
5380 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5382 case value_t::number_float:
5384 return lhs.m_value.number_float == rhs.m_value.number_float;
5392 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5394 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5396 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5398 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5400 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5402 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5404 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5406 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5408 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5410 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5412 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5414 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5470 return not (lhs == rhs);
5502 return not v.is_null();
5531 const auto lhs_type = lhs.type();
5532 const auto rhs_type = rhs.type();
5534 if (lhs_type == rhs_type)
5538 case value_t::array:
5540 assert(lhs.m_value.array !=
nullptr);
5541 assert(rhs.m_value.array !=
nullptr);
5542 return *lhs.m_value.array < *rhs.m_value.array;
5544 case value_t::object:
5546 assert(lhs.m_value.object !=
nullptr);
5547 assert(rhs.m_value.object !=
nullptr);
5548 return *lhs.m_value.object < *rhs.m_value.object;
5554 case value_t::string:
5556 assert(lhs.m_value.string !=
nullptr);
5557 assert(rhs.m_value.string !=
nullptr);
5558 return *lhs.m_value.string < *rhs.m_value.string;
5560 case value_t::boolean:
5562 return lhs.m_value.boolean < rhs.m_value.boolean;
5564 case value_t::number_integer:
5566 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5568 case value_t::number_unsigned:
5570 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5572 case value_t::number_float:
5574 return lhs.m_value.number_float < rhs.m_value.number_float;
5582 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5584 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5586 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5588 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5590 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5592 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5594 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5596 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5598 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5600 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5602 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5604 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5610 return operator<(lhs_type, rhs_type);
5632 return not (rhs < lhs);
5654 return not (lhs <= rhs);
5676 return not (lhs < rhs);
5711 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5714 const bool pretty_print = (o.width() > 0);
5715 const auto indentation = (pretty_print ? o.width() : 0);
5721 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5729 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5770 return parser(s, cb).
parse();
5799 return parser(i, cb).
parse();
5807 return parser(i, cb).
parse();
5835 j = parser(i).
parse();
5845 j = parser(i).
parse();
5858 string_t type_name()
const noexcept
5864 case value_t::object:
5866 case value_t::array:
5868 case value_t::string:
5870 case value_t::boolean:
5872 case value_t::discarded:
5887 static std::size_t extra_space(
const string_t& s) noexcept
5889 std::size_t result = 0;
5891 for (
const auto& c : s)
5910 if (c >= 0x00 and c <= 0x1f)
5938 const auto space = extra_space(s);
5945 string_t result(s.size() + space,
'\\');
5946 std::size_t pos = 0;
5948 for (
const auto& c : s)
5955 result[pos + 1] =
'"';
5971 result[pos + 1] =
'b';
5979 result[pos + 1] =
'f';
5987 result[pos + 1] =
'n';
5995 result[pos + 1] =
'r';
6003 result[pos + 1] =
't';
6010 if (c >= 0x00 and c <= 0x1f)
6014 auto hexify = [](
const char v) ->
char 6016 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
6021 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6059 void dump(std::ostream& o,
6060 const bool pretty_print,
6061 const unsigned int indent_step,
6062 const unsigned int current_indent = 0)
const 6065 unsigned int new_indent = current_indent;
6069 case value_t::object:
6071 assert(m_value.object !=
nullptr);
6073 if (m_value.object->empty())
6084 new_indent += indent_step;
6088 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6090 if (i != m_value.object->cbegin())
6092 o << (pretty_print ?
",\n" :
",");
6094 o <<
string_t(new_indent,
' ') <<
"\"" 6095 << escape_string(i->first) <<
"\":" 6096 << (pretty_print ?
" " :
"");
6097 i->second.dump(o, pretty_print, indent_step, new_indent);
6103 new_indent -= indent_step;
6107 o <<
string_t(new_indent,
' ') +
"}";
6111 case value_t::array:
6113 assert(m_value.array !=
nullptr);
6115 if (m_value.array->empty())
6126 new_indent += indent_step;
6130 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6132 if (i != m_value.array->cbegin())
6134 o << (pretty_print ?
",\n" :
",");
6137 i->dump(o, pretty_print, indent_step, new_indent);
6143 new_indent -= indent_step;
6147 o <<
string_t(new_indent,
' ') <<
"]";
6151 case value_t::string:
6153 assert(m_value.string !=
nullptr);
6154 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6158 case value_t::boolean:
6160 o << (m_value.boolean ?
"true" :
"false");
6164 case value_t::number_integer:
6166 o << m_value.number_integer;
6170 case value_t::number_unsigned:
6172 o << m_value.number_unsigned;
6176 case value_t::number_float:
6179 if (m_type.bits.parsed)
6182 if (m_type.bits.has_exp)
6189 if (m_type.bits.exp_cap)
6191 len = snprintf(buf,
sizeof(buf),
"%.*E",
6192 m_type.bits.precision, m_value.number_float) + 1;
6196 len = snprintf(buf,
sizeof(buf),
"%.*e",
6197 m_type.bits.precision, m_value.number_float) + 1;
6201 if (not m_type.bits.exp_plus)
6203 if (len > static_cast<int>(
sizeof(buf)))
6207 for (
int i = 0; i < len; i++)
6211 for (; i + 1 < len; i++)
6213 buf[i] = buf[i + 1];
6224 std::stringstream ss;
6225 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6226 ss << std::setprecision(m_type.bits.precision)
6227 << std::fixed << m_value.number_float;
6233 if (m_value.number_float == 0)
6236 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6245 std::stringstream ss;
6246 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6247 ss << std::setprecision(std::numeric_limits<double>::digits10)
6248 << m_value.number_float;
6255 case value_t::discarded:
6275 type_data_t m_type = value_t::null;
6278 json_value m_value = {};
6295 class primitive_iterator_t
6299 void set_begin() noexcept
6305 void set_end() noexcept
6311 constexpr
bool is_begin()
const noexcept
6313 return (m_it == begin_value);
6317 constexpr
bool is_end()
const noexcept
6319 return (m_it == end_value);
6339 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6349 struct internal_iterator
6352 typename object_t::iterator object_iterator;
6354 typename array_t::iterator array_iterator;
6356 primitive_iterator_t primitive_iterator;
6359 internal_iterator() noexcept
6360 : object_iterator(), array_iterator(), primitive_iterator()
6365 template<
typename IteratorType>
6366 class iteration_proxy
6370 class iteration_proxy_internal
6374 IteratorType anchor;
6376 size_t array_index = 0;
6379 explicit iteration_proxy_internal(IteratorType it) noexcept
6384 iteration_proxy_internal& operator*()
6390 iteration_proxy_internal& operator++()
6399 bool operator!= (
const iteration_proxy_internal& o)
const 6401 return anchor != o.anchor;
6407 assert(anchor.m_object !=
nullptr);
6409 switch (anchor.m_object->type())
6412 case value_t::array:
6414 return std::to_string(array_index);
6418 case value_t::object:
6420 return anchor.key();
6432 typename IteratorType::reference value()
const 6434 return anchor.value();
6439 typename IteratorType::reference container;
6443 explicit iteration_proxy(
typename IteratorType::reference cont)
6448 iteration_proxy_internal begin() noexcept
6450 return iteration_proxy_internal(container.begin());
6454 iteration_proxy_internal end() noexcept
6456 return iteration_proxy_internal(container.end());
6474 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6477 friend class basic_json;
6498 assert(m_object !=
nullptr);
6500 switch (m_object->m_type)
6504 m_it.object_iterator =
typename object_t::iterator();
6510 m_it.array_iterator =
typename array_t::iterator();
6516 m_it.primitive_iterator = primitive_iterator_t();
6524 : m_object(other.m_object)
6526 assert(m_object !=
nullptr);
6528 switch (m_object->m_type)
6532 m_it.object_iterator = other.m_it.object_iterator;
6538 m_it.array_iterator = other.m_it.array_iterator;
6544 m_it.primitive_iterator = other.m_it.primitive_iterator;
6552 : m_object(other.m_object), m_it(other.m_it)
6557 std::is_nothrow_move_constructible<pointer>::value and
6558 std::is_nothrow_move_assignable<pointer>::value and
6559 std::is_nothrow_move_constructible<internal_iterator>::value and
6560 std::is_nothrow_move_assignable<internal_iterator>::value
6563 std::swap(m_object, other.m_object);
6564 std::swap(m_it, other.m_it);
6570 void set_begin() noexcept
6572 assert(m_object !=
nullptr);
6574 switch (m_object->m_type)
6578 assert(m_object->m_value.object !=
nullptr);
6579 m_it.object_iterator = m_object->m_value.object->begin();
6585 assert(m_object->m_value.array !=
nullptr);
6586 m_it.array_iterator = m_object->m_value.array->begin();
6593 m_it.primitive_iterator.set_end();
6599 m_it.primitive_iterator.set_begin();
6606 void set_end() noexcept
6608 assert(m_object !=
nullptr);
6610 switch (m_object->m_type)
6614 assert(m_object->m_value.object !=
nullptr);
6615 m_it.object_iterator = m_object->m_value.object->end();
6621 assert(m_object->m_value.array !=
nullptr);
6622 m_it.array_iterator = m_object->m_value.array->end();
6628 m_it.primitive_iterator.set_end();
6638 assert(m_object !=
nullptr);
6640 switch (m_object->m_type)
6644 assert(m_object->m_value.object);
6645 assert(m_it.object_iterator != m_object->m_value.object->end());
6646 return m_it.object_iterator->second;
6651 assert(m_object->m_value.array);
6652 assert(m_it.array_iterator != m_object->m_value.array->end());
6653 return *m_it.array_iterator;
6658 throw std::out_of_range(
"cannot get value");
6663 if (m_it.primitive_iterator.is_begin())
6669 throw std::out_of_range(
"cannot get value");
6678 assert(m_object !=
nullptr);
6680 switch (m_object->m_type)
6684 assert(m_object->m_value.object);
6685 assert(m_it.object_iterator != m_object->m_value.object->end());
6686 return &(m_it.object_iterator->second);
6691 assert(m_object->m_value.array);
6692 assert(m_it.array_iterator != m_object->m_value.array->end());
6693 return &*m_it.array_iterator;
6698 if (m_it.primitive_iterator.is_begin())
6704 throw std::out_of_range(
"cannot get value");
6713 auto result = *
this;
6721 assert(m_object !=
nullptr);
6723 switch (m_object->m_type)
6727 ++m_it.object_iterator;
6733 ++m_it.array_iterator;
6739 ++m_it.primitive_iterator;
6750 auto result = *
this;
6758 assert(m_object !=
nullptr);
6760 switch (m_object->m_type)
6764 --m_it.object_iterator;
6770 --m_it.array_iterator;
6776 --m_it.primitive_iterator;
6788 if (m_object != other.m_object)
6790 throw std::domain_error(
"cannot compare iterators of different containers");
6793 assert(m_object !=
nullptr);
6795 switch (m_object->m_type)
6799 return (m_it.object_iterator == other.m_it.object_iterator);
6804 return (m_it.array_iterator == other.m_it.array_iterator);
6809 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6817 return not operator==(other);
6824 if (m_object != other.m_object)
6826 throw std::domain_error(
"cannot compare iterators of different containers");
6829 assert(m_object !=
nullptr);
6831 switch (m_object->m_type)
6835 throw std::domain_error(
"cannot compare order of object iterators");
6840 return (m_it.array_iterator < other.m_it.array_iterator);
6845 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6853 return not other.operator < (*this);
6859 return not operator<=(other);
6865 return not operator<(other);
6871 assert(m_object !=
nullptr);
6873 switch (m_object->m_type)
6877 throw std::domain_error(
"cannot use offsets with object iterators");
6882 m_it.array_iterator += i;
6888 m_it.primitive_iterator += i;
6899 return operator+=(-i);
6905 auto result = *
this;
6913 auto result = *
this;
6921 assert(m_object !=
nullptr);
6923 switch (m_object->m_type)
6927 throw std::domain_error(
"cannot use offsets with object iterators");
6932 return m_it.array_iterator - other.m_it.array_iterator;
6937 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6945 assert(m_object !=
nullptr);
6947 switch (m_object->m_type)
6951 throw std::domain_error(
"cannot use operator[] for object iterators");
6956 return *(m_it.array_iterator + n);
6961 throw std::out_of_range(
"cannot get value");
6966 if (m_it.primitive_iterator == -n)
6972 throw std::out_of_range(
"cannot get value");
6979 typename object_t::key_type
key()
const 6981 assert(m_object !=
nullptr);
6983 if (m_object->is_object())
6985 return m_it.object_iterator->first;
6989 throw std::domain_error(
"cannot use key() for non-object iterators");
7003 internal_iterator m_it = internal_iterator();
7040 std::is_nothrow_move_constructible<pointer>::value and
7041 std::is_nothrow_move_assignable<pointer>::value and
7042 std::is_nothrow_move_constructible<internal_iterator>::value and
7043 std::is_nothrow_move_assignable<internal_iterator>::value
7046 base_iterator::operator=(other);
7053 return const_cast<reference>(base_iterator::operator*());
7059 return const_cast<pointer>(base_iterator::operator->());
7066 base_iterator::operator++();
7073 base_iterator::operator++();
7081 base_iterator::operator--();
7088 base_iterator::operator--();
7095 base_iterator::operator+=(i);
7102 base_iterator::operator-=(i);
7109 auto result = *
this;
7117 auto result = *
this;
7125 return base_iterator::operator-(other);
7131 return const_cast<reference>(base_iterator::operator[](n));
7137 return const_cast<reference>(base_iterator::value());
7158 template<
typename Base>
7180 return base_iterator::operator++(1);
7186 base_iterator::operator++();
7193 return base_iterator::operator--(1);
7199 base_iterator::operator--();
7206 base_iterator::operator+=(i);
7213 auto result = *
this;
7221 auto result = *
this;
7229 return this->base() - other.base();
7235 return *(this->operator+(n));
7239 typename object_t::key_type
key()
const 7241 auto it = --this->base();
7248 auto it = --this->base();
7249 return it.operator * ();
7270 enum class token_type
7289 using lexer_char_t =
unsigned char;
7292 explicit lexer(
const string_t& s) noexcept
7293 : m_stream(
nullptr), m_buffer(s)
7295 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7296 assert(m_content !=
nullptr);
7297 m_start = m_cursor = m_content;
7298 m_limit = m_content + s.size();
7302 explicit lexer(std::istream* s) noexcept
7303 : m_stream(s), m_buffer()
7305 assert(m_stream !=
nullptr);
7306 getline(*m_stream, m_buffer);
7307 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7308 assert(m_content !=
nullptr);
7309 m_start = m_cursor = m_content;
7310 m_limit = m_content + m_buffer.size();
7317 lexer(
const lexer&) =
delete;
7318 lexer operator=(
const lexer&) =
delete;
7335 static string_t to_unicode(
const std::size_t codepoint1,
7336 const std::size_t codepoint2 = 0)
7339 std::size_t codepoint = codepoint1;
7342 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7345 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7359 throw std::invalid_argument(
"missing or wrong low surrogate");
7365 if (codepoint < 0x80)
7368 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7370 else if (codepoint <= 0x7ff)
7373 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7374 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7376 else if (codepoint <= 0xffff)
7379 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7380 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7381 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7383 else if (codepoint <= 0x10ffff)
7386 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7387 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7388 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7389 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7393 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7400 static std::string token_type_name(token_type t)
7404 case token_type::uninitialized:
7405 return "<uninitialized>";
7406 case token_type::literal_true:
7407 return "true literal";
7408 case token_type::literal_false:
7409 return "false literal";
7410 case token_type::literal_null:
7411 return "null literal";
7412 case token_type::value_string:
7413 return "string literal";
7414 case token_type::value_number:
7415 return "number literal";
7416 case token_type::begin_array:
7418 case token_type::begin_object:
7420 case token_type::end_array:
7422 case token_type::end_object:
7424 case token_type::name_separator:
7426 case token_type::value_separator:
7428 case token_type::parse_error:
7429 return "<parse error>";
7430 case token_type::end_of_input:
7431 return "end of input";
7435 return "unknown token";
7450 token_type scan() noexcept
7457 assert(m_start !=
nullptr);
7462 unsigned int yyaccept = 0;
7463 static const unsigned char yybm[] =
7465 0, 0, 0, 0, 0, 0, 0, 0,
7466 0, 32, 32, 0, 0, 32, 0, 0,
7467 128, 128, 128, 128, 128, 128, 128, 128,
7468 128, 128, 128, 128, 128, 128, 128, 128,
7469 160, 128, 0, 128, 128, 128, 128, 128,
7470 128, 128, 128, 128, 128, 128, 128, 128,
7471 192, 192, 192, 192, 192, 192, 192, 192,
7472 192, 192, 128, 128, 128, 128, 128, 128,
7473 128, 128, 128, 128, 128, 128, 128, 128,
7474 128, 128, 128, 128, 128, 128, 128, 128,
7475 128, 128, 128, 128, 128, 128, 128, 128,
7476 128, 128, 128, 128, 0, 128, 128, 128,
7477 128, 128, 128, 128, 128, 128, 128, 128,
7478 128, 128, 128, 128, 128, 128, 128, 128,
7479 128, 128, 128, 128, 128, 128, 128, 128,
7480 128, 128, 128, 128, 128, 128, 128, 128,
7481 128, 128, 128, 128, 128, 128, 128, 128,
7482 128, 128, 128, 128, 128, 128, 128, 128,
7483 128, 128, 128, 128, 128, 128, 128, 128,
7484 128, 128, 128, 128, 128, 128, 128, 128,
7485 128, 128, 128, 128, 128, 128, 128, 128,
7486 128, 128, 128, 128, 128, 128, 128, 128,
7487 128, 128, 128, 128, 128, 128, 128, 128,
7488 128, 128, 128, 128, 128, 128, 128, 128,
7489 128, 128, 128, 128, 128, 128, 128, 128,
7490 128, 128, 128, 128, 128, 128, 128, 128,
7491 128, 128, 128, 128, 128, 128, 128, 128,
7492 128, 128, 128, 128, 128, 128, 128, 128,
7493 128, 128, 128, 128, 128, 128, 128, 128,
7494 128, 128, 128, 128, 128, 128, 128, 128,
7495 128, 128, 128, 128, 128, 128, 128, 128,
7496 128, 128, 128, 128, 128, 128, 128, 128,
7498 if ((m_limit - m_cursor) < 5)
7503 if (yybm[0 + yych] & 32)
7505 goto basic_json_parser_6;
7515 goto basic_json_parser_2;
7519 goto basic_json_parser_4;
7521 goto basic_json_parser_9;
7527 goto basic_json_parser_4;
7531 goto basic_json_parser_10;
7533 goto basic_json_parser_12;
7542 goto basic_json_parser_4;
7546 goto basic_json_parser_13;
7548 goto basic_json_parser_15;
7554 goto basic_json_parser_17;
7558 goto basic_json_parser_19;
7560 goto basic_json_parser_4;
7572 goto basic_json_parser_21;
7576 goto basic_json_parser_4;
7578 goto basic_json_parser_23;
7584 goto basic_json_parser_24;
7588 goto basic_json_parser_4;
7590 goto basic_json_parser_25;
7599 goto basic_json_parser_26;
7601 goto basic_json_parser_4;
7607 goto basic_json_parser_28;
7611 goto basic_json_parser_30;
7613 goto basic_json_parser_4;
7617 basic_json_parser_2:
7620 return token_type::end_of_input;
7622 basic_json_parser_4:
7624 basic_json_parser_5:
7626 return token_type::parse_error;
7628 basic_json_parser_6:
7630 if (m_limit <= m_cursor)
7635 if (yybm[0 + yych] & 32)
7637 goto basic_json_parser_6;
7642 basic_json_parser_9:
7644 yych = *(m_marker = ++m_cursor);
7647 goto basic_json_parser_5;
7649 goto basic_json_parser_32;
7650 basic_json_parser_10:
7653 return token_type::value_separator;
7655 basic_json_parser_12:
7659 goto basic_json_parser_5;
7663 goto basic_json_parser_13;
7667 goto basic_json_parser_15;
7669 goto basic_json_parser_5;
7670 basic_json_parser_13:
7672 yych = *(m_marker = ++m_cursor);
7677 goto basic_json_parser_37;
7684 goto basic_json_parser_38;
7688 goto basic_json_parser_38;
7691 basic_json_parser_14:
7693 return token_type::value_number;
7695 basic_json_parser_15:
7697 m_marker = ++m_cursor;
7698 if ((m_limit - m_cursor) < 3)
7703 if (yybm[0 + yych] & 64)
7705 goto basic_json_parser_15;
7711 goto basic_json_parser_37;
7713 goto basic_json_parser_14;
7719 goto basic_json_parser_38;
7723 goto basic_json_parser_38;
7725 goto basic_json_parser_14;
7727 basic_json_parser_17:
7730 return token_type::name_separator;
7732 basic_json_parser_19:
7735 return token_type::begin_array;
7737 basic_json_parser_21:
7740 return token_type::end_array;
7742 basic_json_parser_23:
7744 yych = *(m_marker = ++m_cursor);
7747 goto basic_json_parser_39;
7749 goto basic_json_parser_5;
7750 basic_json_parser_24:
7752 yych = *(m_marker = ++m_cursor);
7755 goto basic_json_parser_40;
7757 goto basic_json_parser_5;
7758 basic_json_parser_25:
7760 yych = *(m_marker = ++m_cursor);
7763 goto basic_json_parser_41;
7765 goto basic_json_parser_5;
7766 basic_json_parser_26:
7769 return token_type::begin_object;
7771 basic_json_parser_28:
7774 return token_type::end_object;
7776 basic_json_parser_30:
7778 yych = *(m_marker = ++m_cursor);
7781 goto basic_json_parser_42;
7783 goto basic_json_parser_5;
7784 basic_json_parser_31:
7786 if (m_limit <= m_cursor)
7791 basic_json_parser_32:
7792 if (yybm[0 + yych] & 128)
7794 goto basic_json_parser_31;
7798 goto basic_json_parser_33;
7802 goto basic_json_parser_34;
7804 goto basic_json_parser_36;
7805 basic_json_parser_33:
7806 m_cursor = m_marker;
7809 goto basic_json_parser_5;
7813 goto basic_json_parser_14;
7815 basic_json_parser_34:
7818 return token_type::value_string;
7820 basic_json_parser_36:
7822 if (m_limit <= m_cursor)
7833 goto basic_json_parser_31;
7837 goto basic_json_parser_33;
7839 goto basic_json_parser_31;
7847 goto basic_json_parser_33;
7849 goto basic_json_parser_31;
7855 goto basic_json_parser_31;
7857 goto basic_json_parser_33;
7867 goto basic_json_parser_31;
7871 goto basic_json_parser_31;
7873 goto basic_json_parser_33;
7881 goto basic_json_parser_31;
7883 goto basic_json_parser_33;
7889 goto basic_json_parser_31;
7893 goto basic_json_parser_43;
7895 goto basic_json_parser_33;
7899 basic_json_parser_37:
7903 goto basic_json_parser_33;
7907 goto basic_json_parser_44;
7909 goto basic_json_parser_33;
7910 basic_json_parser_38:
7916 goto basic_json_parser_46;
7918 goto basic_json_parser_33;
7924 goto basic_json_parser_46;
7928 goto basic_json_parser_33;
7932 goto basic_json_parser_47;
7934 goto basic_json_parser_33;
7936 basic_json_parser_39:
7940 goto basic_json_parser_49;
7942 goto basic_json_parser_33;
7943 basic_json_parser_40:
7947 goto basic_json_parser_50;
7949 goto basic_json_parser_33;
7950 basic_json_parser_41:
7954 goto basic_json_parser_51;
7956 goto basic_json_parser_33;
7957 basic_json_parser_42:
7961 goto basic_json_parser_52;
7963 goto basic_json_parser_33;
7964 basic_json_parser_43:
7966 if (m_limit <= m_cursor)
7975 goto basic_json_parser_33;
7979 goto basic_json_parser_54;
7981 goto basic_json_parser_33;
7987 goto basic_json_parser_54;
7991 goto basic_json_parser_33;
7995 goto basic_json_parser_54;
7997 goto basic_json_parser_33;
7999 basic_json_parser_44:
8001 m_marker = ++m_cursor;
8002 if ((m_limit - m_cursor) < 3)
8011 goto basic_json_parser_14;
8015 goto basic_json_parser_44;
8017 goto basic_json_parser_14;
8023 goto basic_json_parser_38;
8027 goto basic_json_parser_38;
8029 goto basic_json_parser_14;
8031 basic_json_parser_46:
8035 goto basic_json_parser_33;
8039 goto basic_json_parser_33;
8041 basic_json_parser_47:
8043 if (m_limit <= m_cursor)
8050 goto basic_json_parser_14;
8054 goto basic_json_parser_47;
8056 goto basic_json_parser_14;
8057 basic_json_parser_49:
8061 goto basic_json_parser_55;
8063 goto basic_json_parser_33;
8064 basic_json_parser_50:
8068 goto basic_json_parser_56;
8070 goto basic_json_parser_33;
8071 basic_json_parser_51:
8075 goto basic_json_parser_58;
8077 goto basic_json_parser_33;
8078 basic_json_parser_52:
8083 basic_json_parser_54:
8085 if (m_limit <= m_cursor)
8094 goto basic_json_parser_33;
8098 goto basic_json_parser_60;
8100 goto basic_json_parser_33;
8106 goto basic_json_parser_60;
8110 goto basic_json_parser_33;
8114 goto basic_json_parser_60;
8116 goto basic_json_parser_33;
8118 basic_json_parser_55:
8122 goto basic_json_parser_61;
8124 goto basic_json_parser_33;
8125 basic_json_parser_56:
8128 return token_type::literal_null;
8130 basic_json_parser_58:
8133 return token_type::literal_true;
8135 basic_json_parser_60:
8137 if (m_limit <= m_cursor)
8146 goto basic_json_parser_33;
8150 goto basic_json_parser_63;
8152 goto basic_json_parser_33;
8158 goto basic_json_parser_63;
8162 goto basic_json_parser_33;
8166 goto basic_json_parser_63;
8168 goto basic_json_parser_33;
8170 basic_json_parser_61:
8173 return token_type::literal_false;
8175 basic_json_parser_63:
8177 if (m_limit <= m_cursor)
8186 goto basic_json_parser_33;
8190 goto basic_json_parser_31;
8192 goto basic_json_parser_33;
8198 goto basic_json_parser_31;
8202 goto basic_json_parser_33;
8206 goto basic_json_parser_31;
8208 goto basic_json_parser_33;
8215 void yyfill() noexcept
8217 if (m_stream ==
nullptr or not * m_stream)
8222 const auto offset_start = m_start - m_content;
8223 const auto offset_marker = m_marker - m_start;
8224 const auto offset_cursor = m_cursor - m_start;
8226 m_buffer.erase(0, static_cast<size_t>(offset_start));
8228 assert(m_stream !=
nullptr);
8229 std::getline(*m_stream, line);
8230 m_buffer +=
"\n" + line;
8232 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8233 assert(m_content !=
nullptr);
8234 m_start = m_content;
8235 m_marker = m_start + offset_marker;
8236 m_cursor = m_start + offset_cursor;
8237 m_limit = m_start + m_buffer.size() - 1;
8243 assert(m_start !=
nullptr);
8244 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8245 static_cast<size_t>(m_cursor - m_start));
8272 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8275 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8331 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8332 4).c_str(),
nullptr, 16);
8335 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8338 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8340 throw std::invalid_argument(
"missing low surrogate");
8344 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8345 (i + 7), 4).c_str(),
nullptr, 16);
8346 result += to_unicode(codepoint, codepoint2);
8353 result += to_unicode(codepoint);
8365 result.append(1, static_cast<typename string_t::value_type>(*i));
8392 long double str_to_float_t(
long double* ,
char** endptr)
const 8394 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8412 double str_to_float_t(
double* ,
char** endptr)
const 8414 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8432 float str_to_float_t(
float* ,
char** endptr)
const 8434 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8464 void get_number(basic_json& result)
const 8466 assert(m_start !=
nullptr);
8468 const lexer::lexer_char_t* curptr = m_start;
8471 result.m_type.bits.parsed =
true;
8476 uint8_t found_radix_point = 0;
8477 uint8_t precision = 0;
8491 type = value_t::number_integer;
8492 max =
static_cast<uint64_t
>(std::numeric_limits<number_integer_t>::max()) + 1;
8497 type = value_t::number_unsigned;
8498 max =
static_cast<uint64_t
>(std::numeric_limits<number_unsigned_t>::max());
8502 for (; curptr < m_cursor; curptr++)
8505 if (*curptr < '0' || *curptr >
'9')
8510 type = value_t::number_float;
8514 found_radix_point = 0xFF;
8519 type = value_t::number_float;
8520 result.m_type.bits.has_exp =
true;
8523 result.m_type.bits.exp_cap = (*curptr ==
'E');
8526 result.m_type.bits.exp_plus = (*(++curptr) ==
'+');
8531 if (type != value_t::number_float)
8534 auto temp = value * 10 + *curptr - 0x30;
8537 if (temp < value || temp > max)
8540 type = value_t::number_float;
8553 result.m_type.bits.precision = precision & found_radix_point;
8556 if (type == value_t::number_unsigned)
8558 result.m_value.number_unsigned = value;
8560 else if (type == value_t::number_integer)
8567 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8571 result.m_type = type;
8576 std::istream* m_stream =
nullptr;
8580 const lexer_char_t* m_content =
nullptr;
8582 const lexer_char_t* m_start =
nullptr;
8584 const lexer_char_t* m_marker =
nullptr;
8586 const lexer_char_t* m_cursor =
nullptr;
8588 const lexer_char_t* m_limit =
nullptr;
8601 : callback(cb), m_lexer(s)
8609 : callback(cb), m_lexer(&_is)
8618 basic_json result = parse_internal(
true);
8620 expect(lexer::token_type::end_of_input);
8629 basic_json parse_internal(
bool keep)
8631 auto result = basic_json(value_t::discarded);
8635 case lexer::token_type::begin_object:
8637 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8640 result.m_type = value_t::object;
8641 result.m_value = json_value(value_t::object);
8648 if (last_token == lexer::token_type::end_object)
8651 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8653 result = basic_json(value_t::discarded);
8659 unexpect(lexer::token_type::value_separator);
8665 if (last_token == lexer::token_type::value_separator)
8671 expect(lexer::token_type::value_string);
8672 const auto key = m_lexer.get_string();
8674 bool keep_tag =
false;
8680 keep_tag = callback(depth, parse_event_t::key, k);
8690 expect(lexer::token_type::name_separator);
8694 auto value = parse_internal(keep);
8695 if (keep and keep_tag and not value.is_discarded())
8697 result[key] = std::move(value);
8700 while (last_token == lexer::token_type::value_separator);
8703 expect(lexer::token_type::end_object);
8705 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8707 result = basic_json(value_t::discarded);
8713 case lexer::token_type::begin_array:
8715 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8718 result.m_type = value_t::array;
8719 result.m_value = json_value(value_t::array);
8726 if (last_token == lexer::token_type::end_array)
8729 if (callback and not callback(--depth, parse_event_t::array_end, result))
8731 result = basic_json(value_t::discarded);
8737 unexpect(lexer::token_type::value_separator);
8743 if (last_token == lexer::token_type::value_separator)
8749 auto value = parse_internal(keep);
8750 if (keep and not value.is_discarded())
8752 result.push_back(std::move(value));
8755 while (last_token == lexer::token_type::value_separator);
8758 expect(lexer::token_type::end_array);
8760 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8762 result = basic_json(value_t::discarded);
8768 case lexer::token_type::literal_null:
8771 result.m_type = value_t::null;
8775 case lexer::token_type::value_string:
8777 const auto s = m_lexer.get_string();
8779 result = basic_json(s);
8783 case lexer::token_type::literal_true:
8786 result.m_type = value_t::boolean;
8787 result.m_value =
true;
8791 case lexer::token_type::literal_false:
8794 result.m_type = value_t::boolean;
8795 result.m_value =
false;
8799 case lexer::token_type::value_number:
8801 m_lexer.get_number(result);
8809 unexpect(last_token);
8813 if (keep and callback and not callback(depth, parse_event_t::value, result))
8815 result = basic_json(value_t::discarded);
8821 typename lexer::token_type get_token() noexcept
8823 last_token = m_lexer.scan();
8827 void expect(
typename lexer::token_type t)
const 8829 if (t != last_token)
8831 std::string error_msg =
"parse error - unexpected ";
8832 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8833 lexer::token_type_name(last_token));
8834 error_msg +=
"; expected " + lexer::token_type_name(t);
8835 throw std::invalid_argument(error_msg);
8839 void unexpect(
typename lexer::token_type t)
const 8841 if (t == last_token)
8843 std::string error_msg =
"parse error - unexpected ";
8844 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8845 lexer::token_type_name(last_token));
8846 throw std::invalid_argument(error_msg);
8856 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8876 friend class basic_json;
8902 : reference_tokens(split(s))
8920 std::string to_string()
const noexcept
8924 for (
const auto& reference_token : reference_tokens)
8926 result +=
"/" + escape(reference_token);
8933 operator std::string()
const 8940 std::string pop_back()
8944 throw std::domain_error(
"JSON pointer has no parent");
8947 auto last = reference_tokens.back();
8948 reference_tokens.pop_back();
8953 bool is_root()
const 8955 return reference_tokens.empty();
8962 throw std::domain_error(
"JSON pointer has no parent");
8966 result.reference_tokens = {reference_tokens[0]};
8979 for (
const auto& reference_token : reference_tokens)
8981 switch (result->m_type)
8985 if (reference_token ==
"0")
8988 result = &result->operator[](0);
8993 result = &result->operator[](reference_token);
8998 case value_t::object:
9001 result = &result->operator[](reference_token);
9005 case value_t::array:
9008 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9021 throw std::domain_error(
"invalid value to unflatten");
9044 for (
const auto& reference_token : reference_tokens)
9046 switch (ptr->m_type)
9048 case value_t::object:
9051 ptr = &ptr->operator[](reference_token);
9055 case value_t::array:
9058 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9060 throw std::domain_error(
"array index must not begin with '0'");
9063 if (reference_token ==
"-")
9066 ptr = &ptr->operator[](ptr->m_value.array->size());
9071 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9078 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9088 for (
const auto& reference_token : reference_tokens)
9090 switch (ptr->m_type)
9092 case value_t::object:
9095 ptr = &ptr->
at(reference_token);
9099 case value_t::array:
9101 if (reference_token ==
"-")
9104 throw std::out_of_range(
"array index '-' (" +
9105 std::to_string(ptr->m_value.array->size()) +
9106 ") is out of range");
9110 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9112 throw std::domain_error(
"array index must not begin with '0'");
9116 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9122 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->operator[](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->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9174 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9184 for (
const auto& reference_token : reference_tokens)
9186 switch (ptr->m_type)
9188 case value_t::object:
9191 ptr = &ptr->
at(reference_token);
9195 case value_t::array:
9197 if (reference_token ==
"-")
9200 throw std::out_of_range(
"array index '-' (" +
9201 std::to_string(ptr->m_value.array->size()) +
9202 ") is out of range");
9206 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9208 throw std::domain_error(
"array index must not begin with '0'");
9212 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9218 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9227 static std::vector<std::string> split(std::string reference_string)
9229 std::vector<std::string> result;
9232 if (reference_string.empty())
9238 if (reference_string[0] !=
'/')
9240 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9248 size_t slash = reference_string.find_first_of(
"/", 1),
9257 slash = reference_string.find_first_of(
"/", start))
9261 auto reference_token = reference_string.substr(start, slash - start);
9264 for (
size_t pos = reference_token.find_first_of(
"~");
9265 pos != std::string::npos;
9266 pos = reference_token.find_first_of(
"~", pos + 1))
9268 assert(reference_token[pos] ==
'~');
9271 if (pos == reference_token.size() - 1 or
9272 (reference_token[pos + 1] !=
'0' and
9273 reference_token[pos + 1] !=
'1'))
9275 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9280 unescape(reference_token);
9281 result.push_back(reference_token);
9302 static void replace_substring(std::string& s,
9303 const std::string& f,
9304 const std::string& t)
9306 assert(not f.empty());
9309 size_t pos = s.find(f);
9310 pos != std::string::npos;
9311 s.replace(pos, f.size(), t),
9312 pos = s.find(f, pos + t.size())
9317 static std::string escape(std::string s)
9320 replace_substring(s,
"~",
"~0");
9321 replace_substring(s,
"/",
"~1");
9326 static void unescape(std::string& s)
9329 replace_substring(s,
"~1",
"/");
9331 replace_substring(s,
"~0",
"~");
9341 static void flatten(
const std::string& reference_string,
9342 const basic_json& value,
9345 switch (value.m_type)
9347 case value_t::array:
9349 if (value.m_value.array->empty())
9352 result[reference_string] =
nullptr;
9357 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9359 flatten(reference_string +
"/" + std::to_string(i),
9360 value.m_value.array->operator[](i), result);
9366 case value_t::object:
9368 if (value.m_value.object->empty())
9371 result[reference_string] =
nullptr;
9376 for (
const auto& element : *value.m_value.object)
9378 flatten(reference_string +
"/" + escape(element.first),
9379 element.second, result);
9388 result[reference_string] = value;
9399 static basic_json unflatten(
const basic_json& value)
9403 throw std::domain_error(
"only objects can be unflattened");
9409 for (
const auto& element : *value.m_value.object)
9411 if (not element.second.is_primitive())
9413 throw std::domain_error(
"values in object must be primitive");
9421 json_pointer(element.first).get_and_create(result) = element.second;
9429 std::vector<std::string> reference_tokens {};
9474 return ptr.get_unchecked(
this);
9501 return ptr.get_unchecked(
this);
9526 return ptr.get_checked(
this);
9551 return ptr.get_checked(
this);
9576 basic_json flatten()
const 9578 basic_json result(value_t::object);
9579 json_pointer::flatten(
"", *
this, result);
9610 basic_json unflatten()
const 9612 return json_pointer::unflatten(*
this);
9660 basic_json patch(
const basic_json& patch)
const 9663 basic_json result = *
this;
9666 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9668 const auto get_op = [](
const std::string op)
9672 return patch_operations::add;
9676 return patch_operations::remove;
9678 if (op ==
"replace")
9680 return patch_operations::replace;
9684 return patch_operations::move;
9688 return patch_operations::copy;
9692 return patch_operations::test;
9695 return patch_operations::invalid;
9699 const auto operation_add = [&result](
json_pointer & ptr, basic_json val)
9710 if (top_pointer != ptr)
9712 basic_json& x = result.
at(top_pointer);
9716 const auto last_path = ptr.pop_back();
9717 basic_json& parent = result[ptr];
9719 switch (parent.m_type)
9722 case value_t::object:
9725 parent[last_path] = val;
9729 case value_t::array:
9731 if (last_path ==
"-")
9738 const auto idx = std::stoi(last_path);
9739 if (static_cast<size_type>(idx) > parent.
size())
9742 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9763 const auto operation_remove = [&result](
json_pointer & ptr)
9766 const auto last_path = ptr.pop_back();
9767 basic_json& parent = result.
at(ptr);
9773 auto it = parent.
find(last_path);
9774 if (it != parent.
end())
9780 throw std::out_of_range(
"key '" + last_path +
"' not found");
9786 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9794 throw std::invalid_argument(
"JSON patch must be an array of objects");
9798 for (
const auto& val : patch)
9801 const auto get_value = [&val](
const std::string & op,
9802 const std::string & member,
9803 bool string_type) -> basic_json&
9806 auto it = val.m_value.object->find(member);
9809 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9812 if (it == val.m_value.object->end())
9814 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9818 if (string_type and not it->second.is_string())
9820 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9828 if (not val.is_object())
9830 throw std::invalid_argument(
"JSON patch must be an array of objects");
9834 const std::string op = get_value(
"op",
"op",
true);
9835 const std::string path = get_value(op,
"path",
true);
9840 case patch_operations::add:
9842 operation_add(ptr, get_value(
"add",
"value",
false));
9846 case patch_operations::remove:
9848 operation_remove(ptr);
9852 case patch_operations::replace:
9855 result.
at(ptr) = get_value(
"replace",
"value",
false);
9859 case patch_operations::move:
9861 const std::string from_path = get_value(
"move",
"from",
true);
9865 basic_json v = result.
at(from_ptr);
9871 operation_remove(from_ptr);
9872 operation_add(ptr, v);
9876 case patch_operations::copy:
9878 const std::string from_path = get_value(
"copy",
"from",
true);;
9882 result[ptr] = result.
at(from_ptr);
9886 case patch_operations::test:
9888 bool success =
false;
9893 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9895 catch (std::out_of_range&)
9903 throw std::domain_error(
"unsuccessful: " + val.dump());
9909 case patch_operations::invalid:
9913 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9953 static basic_json diff(
const basic_json& source,
9954 const basic_json& target,
9955 std::string path =
"") noexcept
9958 basic_json result(value_t::array);
9961 if (source == target)
9966 if (source.
type() != target.
type())
9978 switch (source.
type())
9980 case value_t::array:
9984 while (i < source.
size() and i < target.
size())
9987 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
9988 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9996 while (i < source.
size())
9998 result.push_back(
object(
10001 {
"path", path +
"/" + std::to_string(i)}
10007 while (i < target.
size())
10012 {
"path", path +
"/" + std::to_string(i)},
10013 {
"value", target[i]}
10021 case value_t::object:
10024 for (
auto it = source.
begin(); it != source.
end(); ++it)
10027 const auto key = json_pointer::escape(it.key());
10029 if (target.
find(it.key()) != target.
end())
10032 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10033 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10038 result.push_back(
object(
10041 {
"path", path +
"/" + key}
10047 for (
auto it = target.
begin(); it != target.
end(); ++it)
10049 if (source.
find(it.key()) == source.
end())
10052 const auto key = json_pointer::escape(it.key());
10056 {
"path", path +
"/" + key},
10057 {
"value", it.value()}
10117 is_nothrow_move_constructible<nlohmann::json>::value and
10118 is_nothrow_move_assignable<nlohmann::json>::value
10136 const auto& h = hash<nlohmann::json::string_t>();
10154 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10170 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10171 #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
void push_back(std::initializer_list< basic_json > init)
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
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
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.