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());
3633 return ptr.get_unchecked(
this);
3660 return ptr.get_unchecked(
this);
3685 return ptr.get_checked(
this);
3710 return ptr.get_checked(
this);
3761 template <
class ValueType,
typename 3763 std::is_convertible<basic_json_t, ValueType>::value
3765 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3771 const auto it = find(key);
3778 return default_value;
3783 throw std::domain_error(
"cannot use value() with " + type_name());
3791 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3793 return value(key,
string_t(default_value));
3924 template <
class InteratorType,
typename 3926 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3927 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3933 if (
this != pos.m_object)
3935 throw std::domain_error(
"iterator does not fit current value");
3938 InteratorType result = end();
3942 case value_t::boolean:
3943 case value_t::number_float:
3944 case value_t::number_integer:
3945 case value_t::number_unsigned:
3946 case value_t::string:
3948 if (not pos.m_it.primitive_iterator.is_begin())
3950 throw std::out_of_range(
"iterator out of range");
3955 delete m_value.string;
3956 m_value.string =
nullptr;
3959 m_type = value_t::null;
3963 case value_t::object:
3965 assert(m_value.object !=
nullptr);
3966 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3970 case value_t::array:
3972 assert(m_value.array !=
nullptr);
3973 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3979 throw std::domain_error(
"cannot use erase() with " + type_name());
4032 template <
class InteratorType,
typename 4034 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
4035 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
4038 InteratorType
erase(InteratorType first, InteratorType last)
4041 if (
this != first.m_object or
this != last.m_object)
4043 throw std::domain_error(
"iterators do not fit current value");
4046 InteratorType result = end();
4050 case value_t::boolean:
4051 case value_t::number_float:
4052 case value_t::number_integer:
4053 case value_t::number_unsigned:
4054 case value_t::string:
4056 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4058 throw std::out_of_range(
"iterators out of range");
4063 delete m_value.string;
4064 m_value.string =
nullptr;
4067 m_type = value_t::null;
4071 case value_t::object:
4073 assert(m_value.object !=
nullptr);
4074 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4075 last.m_it.object_iterator);
4079 case value_t::array:
4081 assert(m_value.array !=
nullptr);
4082 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4083 last.m_it.array_iterator);
4089 throw std::domain_error(
"cannot use erase() with " + type_name());
4130 assert(m_value.object !=
nullptr);
4131 return m_value.object->erase(key);
4135 throw std::domain_error(
"cannot use erase() with " + type_name());
4170 throw std::out_of_range(
"index out of range");
4173 assert(m_value.array !=
nullptr);
4174 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4178 throw std::domain_error(
"cannot use erase() with " + type_name());
4211 auto result = end();
4215 assert(m_value.object !=
nullptr);
4216 result.m_it.object_iterator = m_value.object->find(key);
4228 auto result = cend();
4232 assert(m_value.object !=
nullptr);
4233 result.m_it.object_iterator = m_value.object->find(key);
4260 assert(not is_object() or m_value.object !=
nullptr);
4261 return is_object() ? m_value.object->count(key) : 0;
4549 template<
typename IteratorType>
class iteration_proxy;
4565 return iteration_proxy<iterator>(cont);
4573 return iteration_proxy<const_iterator>(cont);
4629 case value_t::array:
4631 assert(m_value.array !=
nullptr);
4632 return m_value.array->empty();
4635 case value_t::object:
4637 assert(m_value.object !=
nullptr);
4638 return m_value.object->empty();
4692 case value_t::array:
4694 assert(m_value.array !=
nullptr);
4695 return m_value.array->size();
4698 case value_t::object:
4700 assert(m_value.object !=
nullptr);
4701 return m_value.object->size();
4752 case value_t::array:
4754 assert(m_value.array !=
nullptr);
4755 return m_value.array->max_size();
4758 case value_t::object:
4760 assert(m_value.object !=
nullptr);
4761 return m_value.object->max_size();
4811 case value_t::number_integer:
4813 m_value.number_integer = 0;
4817 case value_t::number_unsigned:
4819 m_value.number_unsigned = 0;
4823 case value_t::number_float:
4825 m_value.number_float = 0.0;
4829 case value_t::boolean:
4831 m_value.boolean =
false;
4835 case value_t::string:
4837 assert(m_value.string !=
nullptr);
4838 m_value.string->clear();
4842 case value_t::array:
4844 assert(m_value.array !=
nullptr);
4845 m_value.array->clear();
4849 case value_t::object:
4851 assert(m_value.object !=
nullptr);
4852 m_value.object->clear();
4886 if (not(is_null() or is_array()))
4888 throw std::domain_error(
"cannot use push_back() with " + type_name());
4894 m_type = value_t::array;
4895 m_value = value_t::array;
4899 assert(m_value.array !=
nullptr);
4900 m_value.array->push_back(std::move(val));
4902 val.m_type = value_t::null;
4911 push_back(std::move(val));
4922 if (not(is_null() or is_array()))
4924 throw std::domain_error(
"cannot use push_back() with " + type_name());
4930 m_type = value_t::array;
4931 m_value = value_t::array;
4935 assert(m_value.array !=
nullptr);
4936 m_value.array->push_back(val);
4972 if (not(is_null() or is_object()))
4974 throw std::domain_error(
"cannot use push_back() with " + type_name());
4980 m_type = value_t::object;
4981 m_value = value_t::object;
4985 assert(m_value.object !=
nullptr);
4986 m_value.object->insert(val);
4996 return operator[](val.first);
5027 if (pos.m_object !=
this)
5029 throw std::domain_error(
"iterator does not fit current value");
5034 assert(m_value.array !=
nullptr);
5035 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5040 throw std::domain_error(
"cannot use insert() with " + type_name());
5050 return insert(pos, val);
5083 if (pos.m_object !=
this)
5085 throw std::domain_error(
"iterator does not fit current value");
5090 assert(m_value.array !=
nullptr);
5091 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5096 throw std::domain_error(
"cannot use insert() with " + type_name());
5135 throw std::domain_error(
"cannot use insert() with " + type_name());
5139 if (pos.m_object !=
this)
5141 throw std::domain_error(
"iterator does not fit current value");
5144 if (first.m_object != last.m_object)
5146 throw std::domain_error(
"iterators do not fit");
5149 if (first.m_object ==
this or last.m_object ==
this)
5151 throw std::domain_error(
"passed iterators may not belong to container");
5156 assert(m_value.array !=
nullptr);
5157 result.m_it.array_iterator = m_value.array->insert(
5158 pos.m_it.array_iterator,
5159 first.m_it.array_iterator,
5160 last.m_it.array_iterator);
5193 throw std::domain_error(
"cannot use insert() with " + type_name());
5197 if (pos.m_object !=
this)
5199 throw std::domain_error(
"iterator does not fit current value");
5204 assert(m_value.array !=
nullptr);
5205 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5227 std::is_nothrow_move_constructible<value_t>::value and
5228 std::is_nothrow_move_assignable<value_t>::value and
5229 std::is_nothrow_move_constructible<json_value>::value and
5230 std::is_nothrow_move_assignable<json_value>::value
5233 std::swap(m_type, other.m_type);
5234 std::swap(m_value, other.m_value);
5262 assert(m_value.array !=
nullptr);
5263 std::swap(*(m_value.array), other);
5267 throw std::domain_error(
"cannot use swap() with " + type_name());
5296 assert(m_value.object !=
nullptr);
5297 std::swap(*(m_value.object), other);
5301 throw std::domain_error(
"cannot use swap() with " + type_name());
5330 assert(m_value.string !=
nullptr);
5331 std::swap(*(m_value.string), other);
5335 throw std::domain_error(
"cannot use swap() with " + type_name());
5361 static constexpr std::array<uint8_t, 8> order = {{
5374 if (lhs == value_t::discarded or rhs == value_t::discarded)
5379 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5408 const auto lhs_type = lhs.type();
5409 const auto rhs_type = rhs.type();
5411 if (lhs_type == rhs_type)
5415 case value_t::array:
5417 assert(lhs.m_value.array !=
nullptr);
5418 assert(rhs.m_value.array !=
nullptr);
5419 return *lhs.m_value.array == *rhs.m_value.array;
5421 case value_t::object:
5423 assert(lhs.m_value.object !=
nullptr);
5424 assert(rhs.m_value.object !=
nullptr);
5425 return *lhs.m_value.object == *rhs.m_value.object;
5431 case value_t::string:
5433 assert(lhs.m_value.string !=
nullptr);
5434 assert(rhs.m_value.string !=
nullptr);
5435 return *lhs.m_value.string == *rhs.m_value.string;
5437 case value_t::boolean:
5439 return lhs.m_value.boolean == rhs.m_value.boolean;
5441 case value_t::number_integer:
5443 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5445 case value_t::number_unsigned:
5447 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5449 case value_t::number_float:
5451 return lhs.m_value.number_float == rhs.m_value.number_float;
5459 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5461 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5463 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5465 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5467 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5469 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5471 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5473 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5475 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5477 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5479 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5481 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5537 return not (lhs == rhs);
5569 return not v.is_null();
5598 const auto lhs_type = lhs.type();
5599 const auto rhs_type = rhs.type();
5601 if (lhs_type == rhs_type)
5605 case value_t::array:
5607 assert(lhs.m_value.array !=
nullptr);
5608 assert(rhs.m_value.array !=
nullptr);
5609 return *lhs.m_value.array < *rhs.m_value.array;
5611 case value_t::object:
5613 assert(lhs.m_value.object !=
nullptr);
5614 assert(rhs.m_value.object !=
nullptr);
5615 return *lhs.m_value.object < *rhs.m_value.object;
5621 case value_t::string:
5623 assert(lhs.m_value.string !=
nullptr);
5624 assert(rhs.m_value.string !=
nullptr);
5625 return *lhs.m_value.string < *rhs.m_value.string;
5627 case value_t::boolean:
5629 return lhs.m_value.boolean < rhs.m_value.boolean;
5631 case value_t::number_integer:
5633 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5635 case value_t::number_unsigned:
5637 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5639 case value_t::number_float:
5641 return lhs.m_value.number_float < rhs.m_value.number_float;
5649 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5651 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5653 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5655 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5657 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5659 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5661 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5663 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5665 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5667 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5669 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5671 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5677 return operator<(lhs_type, rhs_type);
5699 return not (rhs < lhs);
5721 return not (lhs <= rhs);
5743 return not (lhs < rhs);
5778 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5781 const bool pretty_print = (o.width() > 0);
5782 const auto indentation = (pretty_print ? o.width() : 0);
5788 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5796 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5837 return parser(s, cb).
parse();
5866 return parser(i, cb).
parse();
5874 return parser(i, cb).
parse();
5902 j = parser(i).
parse();
5912 j = parser(i).
parse();
5925 string_t type_name()
const noexcept
5931 case value_t::object:
5933 case value_t::array:
5935 case value_t::string:
5937 case value_t::boolean:
5939 case value_t::discarded:
5954 static std::size_t extra_space(
const string_t& s) noexcept
5956 std::size_t result = 0;
5958 for (
const auto& c : s)
5977 if (c >= 0x00 and c <= 0x1f)
6005 const auto space = extra_space(s);
6012 string_t result(s.size() + space,
'\\');
6013 std::size_t pos = 0;
6015 for (
const auto& c : s)
6022 result[pos + 1] =
'"';
6038 result[pos + 1] =
'b';
6046 result[pos + 1] =
'f';
6054 result[pos + 1] =
'n';
6062 result[pos + 1] =
'r';
6070 result[pos + 1] =
't';
6077 if (c >= 0x00 and c <= 0x1f)
6081 auto hexify = [](
const char v) ->
char 6083 return (v < 10) ? (
'0' + v) : (
'a' + v - 10);
6088 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6126 void dump(std::ostream& o,
6127 const bool pretty_print,
6128 const unsigned int indent_step,
6129 const unsigned int current_indent = 0)
const 6132 unsigned int new_indent = current_indent;
6136 case value_t::object:
6138 assert(m_value.object !=
nullptr);
6140 if (m_value.object->empty())
6151 new_indent += indent_step;
6155 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6157 if (i != m_value.object->cbegin())
6159 o << (pretty_print ?
",\n" :
",");
6161 o <<
string_t(new_indent,
' ') <<
"\"" 6162 << escape_string(i->first) <<
"\":" 6163 << (pretty_print ?
" " :
"");
6164 i->second.dump(o, pretty_print, indent_step, new_indent);
6170 new_indent -= indent_step;
6174 o <<
string_t(new_indent,
' ') +
"}";
6178 case value_t::array:
6180 assert(m_value.array !=
nullptr);
6182 if (m_value.array->empty())
6193 new_indent += indent_step;
6197 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6199 if (i != m_value.array->cbegin())
6201 o << (pretty_print ?
",\n" :
",");
6204 i->dump(o, pretty_print, indent_step, new_indent);
6210 new_indent -= indent_step;
6214 o <<
string_t(new_indent,
' ') <<
"]";
6218 case value_t::string:
6220 assert(m_value.string !=
nullptr);
6221 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6225 case value_t::boolean:
6227 o << (m_value.boolean ?
"true" :
"false");
6231 case value_t::number_integer:
6233 o << m_value.number_integer;
6237 case value_t::number_unsigned:
6239 o << m_value.number_unsigned;
6243 case value_t::number_float:
6246 if (m_type.bits.parsed)
6249 if (m_type.bits.has_exp)
6256 if (m_type.bits.exp_cap)
6258 len = snprintf(buf,
sizeof(buf),
"%.*E",
6259 m_type.bits.precision, m_value.number_float) + 1;
6263 len = snprintf(buf,
sizeof(buf),
"%.*e",
6264 m_type.bits.precision, m_value.number_float) + 1;
6268 if (not m_type.bits.exp_plus)
6270 if (len > static_cast<int>(
sizeof(buf)))
6274 for (
int i = 0; i < len; i++)
6278 for (; i + 1 < len; i++)
6280 buf[i] = buf[i + 1];
6291 std::stringstream ss;
6292 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6293 ss << std::setprecision(m_type.bits.precision)
6294 << std::fixed << m_value.number_float;
6300 if (m_value.number_float == 0)
6303 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6312 std::stringstream ss;
6313 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6314 ss << std::setprecision(std::numeric_limits<double>::digits10)
6315 << m_value.number_float;
6322 case value_t::discarded:
6342 type_data_t m_type = value_t::null;
6345 json_value m_value = {};
6362 class primitive_iterator_t
6366 void set_begin() noexcept
6372 void set_end() noexcept
6378 constexpr
bool is_begin()
const noexcept
6380 return (m_it == begin_value);
6384 constexpr
bool is_end()
const noexcept
6386 return (m_it == end_value);
6406 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6416 struct internal_iterator
6419 typename object_t::iterator object_iterator;
6421 typename array_t::iterator array_iterator;
6423 primitive_iterator_t primitive_iterator;
6426 internal_iterator() noexcept
6427 : object_iterator(), array_iterator(), primitive_iterator()
6432 template<
typename IteratorType>
6433 class iteration_proxy
6437 class iteration_proxy_internal
6441 IteratorType anchor;
6443 size_t array_index = 0;
6446 explicit iteration_proxy_internal(IteratorType it) noexcept
6451 iteration_proxy_internal& operator*()
6457 iteration_proxy_internal& operator++()
6466 bool operator!= (
const iteration_proxy_internal& o)
const 6468 return anchor != o.anchor;
6474 assert(anchor.m_object !=
nullptr);
6476 switch (anchor.m_object->type())
6479 case value_t::array:
6481 return std::to_string(array_index);
6485 case value_t::object:
6487 return anchor.key();
6499 typename IteratorType::reference value()
const 6501 return anchor.value();
6506 typename IteratorType::reference container;
6510 explicit iteration_proxy(
typename IteratorType::reference cont)
6515 iteration_proxy_internal begin() noexcept
6517 return iteration_proxy_internal(container.begin());
6521 iteration_proxy_internal end() noexcept
6523 return iteration_proxy_internal(container.end());
6541 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6544 friend class basic_json;
6565 assert(m_object !=
nullptr);
6567 switch (m_object->m_type)
6571 m_it.object_iterator =
typename object_t::iterator();
6577 m_it.array_iterator =
typename array_t::iterator();
6583 m_it.primitive_iterator = primitive_iterator_t();
6591 : m_object(other.m_object)
6593 assert(m_object !=
nullptr);
6595 switch (m_object->m_type)
6599 m_it.object_iterator = other.m_it.object_iterator;
6605 m_it.array_iterator = other.m_it.array_iterator;
6611 m_it.primitive_iterator = other.m_it.primitive_iterator;
6619 : m_object(other.m_object), m_it(other.m_it)
6624 std::is_nothrow_move_constructible<pointer>::value and
6625 std::is_nothrow_move_assignable<pointer>::value and
6626 std::is_nothrow_move_constructible<internal_iterator>::value and
6627 std::is_nothrow_move_assignable<internal_iterator>::value
6630 std::swap(m_object, other.m_object);
6631 std::swap(m_it, other.m_it);
6637 void set_begin() noexcept
6639 assert(m_object !=
nullptr);
6641 switch (m_object->m_type)
6645 assert(m_object->m_value.object !=
nullptr);
6646 m_it.object_iterator = m_object->m_value.object->begin();
6652 assert(m_object->m_value.array !=
nullptr);
6653 m_it.array_iterator = m_object->m_value.array->begin();
6660 m_it.primitive_iterator.set_end();
6666 m_it.primitive_iterator.set_begin();
6673 void set_end() noexcept
6675 assert(m_object !=
nullptr);
6677 switch (m_object->m_type)
6681 assert(m_object->m_value.object !=
nullptr);
6682 m_it.object_iterator = m_object->m_value.object->end();
6688 assert(m_object->m_value.array !=
nullptr);
6689 m_it.array_iterator = m_object->m_value.array->end();
6695 m_it.primitive_iterator.set_end();
6705 assert(m_object !=
nullptr);
6707 switch (m_object->m_type)
6711 assert(m_object->m_value.object);
6712 assert(m_it.object_iterator != m_object->m_value.object->end());
6713 return m_it.object_iterator->second;
6718 assert(m_object->m_value.array);
6719 assert(m_it.array_iterator != m_object->m_value.array->end());
6720 return *m_it.array_iterator;
6725 throw std::out_of_range(
"cannot get value");
6730 if (m_it.primitive_iterator.is_begin())
6736 throw std::out_of_range(
"cannot get value");
6745 assert(m_object !=
nullptr);
6747 switch (m_object->m_type)
6751 assert(m_object->m_value.object);
6752 assert(m_it.object_iterator != m_object->m_value.object->end());
6753 return &(m_it.object_iterator->second);
6758 assert(m_object->m_value.array);
6759 assert(m_it.array_iterator != m_object->m_value.array->end());
6760 return &*m_it.array_iterator;
6765 if (m_it.primitive_iterator.is_begin())
6771 throw std::out_of_range(
"cannot get value");
6780 auto result = *
this;
6788 assert(m_object !=
nullptr);
6790 switch (m_object->m_type)
6794 ++m_it.object_iterator;
6800 ++m_it.array_iterator;
6806 ++m_it.primitive_iterator;
6817 auto result = *
this;
6825 assert(m_object !=
nullptr);
6827 switch (m_object->m_type)
6831 --m_it.object_iterator;
6837 --m_it.array_iterator;
6843 --m_it.primitive_iterator;
6855 if (m_object != other.m_object)
6857 throw std::domain_error(
"cannot compare iterators of different containers");
6860 assert(m_object !=
nullptr);
6862 switch (m_object->m_type)
6866 return (m_it.object_iterator == other.m_it.object_iterator);
6871 return (m_it.array_iterator == other.m_it.array_iterator);
6876 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6884 return not operator==(other);
6891 if (m_object != other.m_object)
6893 throw std::domain_error(
"cannot compare iterators of different containers");
6896 assert(m_object !=
nullptr);
6898 switch (m_object->m_type)
6902 throw std::domain_error(
"cannot compare order of object iterators");
6907 return (m_it.array_iterator < other.m_it.array_iterator);
6912 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6920 return not other.operator < (*this);
6926 return not operator<=(other);
6932 return not operator<(other);
6938 assert(m_object !=
nullptr);
6940 switch (m_object->m_type)
6944 throw std::domain_error(
"cannot use offsets with object iterators");
6949 m_it.array_iterator += i;
6955 m_it.primitive_iterator += i;
6966 return operator+=(-i);
6972 auto result = *
this;
6980 auto result = *
this;
6988 assert(m_object !=
nullptr);
6990 switch (m_object->m_type)
6994 throw std::domain_error(
"cannot use offsets with object iterators");
6999 return m_it.array_iterator - other.m_it.array_iterator;
7004 return m_it.primitive_iterator - other.m_it.primitive_iterator;
7012 assert(m_object !=
nullptr);
7014 switch (m_object->m_type)
7018 throw std::domain_error(
"cannot use operator[] for object iterators");
7023 return *(m_it.array_iterator + n);
7028 throw std::out_of_range(
"cannot get value");
7033 if (m_it.primitive_iterator == -n)
7039 throw std::out_of_range(
"cannot get value");
7046 typename object_t::key_type
key()
const 7048 assert(m_object !=
nullptr);
7050 if (m_object->is_object())
7052 return m_it.object_iterator->first;
7056 throw std::domain_error(
"cannot use key() for non-object iterators");
7070 internal_iterator m_it = internal_iterator();
7107 std::is_nothrow_move_constructible<pointer>::value and
7108 std::is_nothrow_move_assignable<pointer>::value and
7109 std::is_nothrow_move_constructible<internal_iterator>::value and
7110 std::is_nothrow_move_assignable<internal_iterator>::value
7113 base_iterator::operator=(other);
7120 return const_cast<reference>(base_iterator::operator*());
7126 return const_cast<pointer>(base_iterator::operator->());
7133 base_iterator::operator++();
7140 base_iterator::operator++();
7148 base_iterator::operator--();
7155 base_iterator::operator--();
7162 base_iterator::operator+=(i);
7169 base_iterator::operator-=(i);
7176 auto result = *
this;
7184 auto result = *
this;
7192 return base_iterator::operator-(other);
7198 return const_cast<reference>(base_iterator::operator[](n));
7204 return const_cast<reference>(base_iterator::value());
7225 template<
typename Base>
7247 return base_iterator::operator++(1);
7253 base_iterator::operator++();
7260 return base_iterator::operator--(1);
7266 base_iterator::operator--();
7273 base_iterator::operator+=(i);
7280 auto result = *
this;
7288 auto result = *
this;
7296 return this->base() - other.base();
7302 return *(this->operator+(n));
7306 typename object_t::key_type
key()
const 7308 auto it = --this->base();
7315 auto it = --this->base();
7316 return it.operator * ();
7337 enum class token_type
7356 using lexer_char_t =
unsigned char;
7359 explicit lexer(
const string_t& s) noexcept
7360 : m_stream(
nullptr), m_buffer(s)
7362 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7363 assert(m_content !=
nullptr);
7364 m_start = m_cursor = m_content;
7365 m_limit = m_content + s.size();
7369 explicit lexer(std::istream* s) noexcept
7370 : m_stream(s), m_buffer()
7372 assert(m_stream !=
nullptr);
7373 getline(*m_stream, m_buffer);
7374 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7375 assert(m_content !=
nullptr);
7376 m_start = m_cursor = m_content;
7377 m_limit = m_content + m_buffer.size();
7384 lexer(
const lexer&) =
delete;
7385 lexer operator=(
const lexer&) =
delete;
7402 static string_t to_unicode(
const std::size_t codepoint1,
7403 const std::size_t codepoint2 = 0)
7406 std::size_t codepoint = codepoint1;
7409 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7412 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7426 throw std::invalid_argument(
"missing or wrong low surrogate");
7432 if (codepoint < 0x80)
7435 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7437 else if (codepoint <= 0x7ff)
7440 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7441 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7443 else if (codepoint <= 0xffff)
7446 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7447 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7448 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7450 else if (codepoint <= 0x10ffff)
7453 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7454 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7455 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7456 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7460 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7467 static std::string token_type_name(token_type t)
7471 case token_type::uninitialized:
7472 return "<uninitialized>";
7473 case token_type::literal_true:
7474 return "true literal";
7475 case token_type::literal_false:
7476 return "false literal";
7477 case token_type::literal_null:
7478 return "null literal";
7479 case token_type::value_string:
7480 return "string literal";
7481 case token_type::value_number:
7482 return "number literal";
7483 case token_type::begin_array:
7485 case token_type::begin_object:
7487 case token_type::end_array:
7489 case token_type::end_object:
7491 case token_type::name_separator:
7493 case token_type::value_separator:
7495 case token_type::parse_error:
7496 return "<parse error>";
7497 case token_type::end_of_input:
7498 return "end of input";
7502 return "unknown token";
7517 token_type scan() noexcept
7524 assert(m_start !=
nullptr);
7529 unsigned int yyaccept = 0;
7530 static const unsigned char yybm[] =
7532 0, 0, 0, 0, 0, 0, 0, 0,
7533 0, 32, 32, 0, 0, 32, 0, 0,
7534 128, 128, 128, 128, 128, 128, 128, 128,
7535 128, 128, 128, 128, 128, 128, 128, 128,
7536 160, 128, 0, 128, 128, 128, 128, 128,
7537 128, 128, 128, 128, 128, 128, 128, 128,
7538 192, 192, 192, 192, 192, 192, 192, 192,
7539 192, 192, 128, 128, 128, 128, 128, 128,
7540 128, 128, 128, 128, 128, 128, 128, 128,
7541 128, 128, 128, 128, 128, 128, 128, 128,
7542 128, 128, 128, 128, 128, 128, 128, 128,
7543 128, 128, 128, 128, 0, 128, 128, 128,
7544 128, 128, 128, 128, 128, 128, 128, 128,
7545 128, 128, 128, 128, 128, 128, 128, 128,
7546 128, 128, 128, 128, 128, 128, 128, 128,
7547 128, 128, 128, 128, 128, 128, 128, 128,
7548 128, 128, 128, 128, 128, 128, 128, 128,
7549 128, 128, 128, 128, 128, 128, 128, 128,
7550 128, 128, 128, 128, 128, 128, 128, 128,
7551 128, 128, 128, 128, 128, 128, 128, 128,
7552 128, 128, 128, 128, 128, 128, 128, 128,
7553 128, 128, 128, 128, 128, 128, 128, 128,
7554 128, 128, 128, 128, 128, 128, 128, 128,
7555 128, 128, 128, 128, 128, 128, 128, 128,
7556 128, 128, 128, 128, 128, 128, 128, 128,
7557 128, 128, 128, 128, 128, 128, 128, 128,
7558 128, 128, 128, 128, 128, 128, 128, 128,
7559 128, 128, 128, 128, 128, 128, 128, 128,
7560 128, 128, 128, 128, 128, 128, 128, 128,
7561 128, 128, 128, 128, 128, 128, 128, 128,
7562 128, 128, 128, 128, 128, 128, 128, 128,
7563 128, 128, 128, 128, 128, 128, 128, 128,
7565 if ((m_limit - m_cursor) < 5)
7570 if (yybm[0 + yych] & 32)
7572 goto basic_json_parser_6;
7582 goto basic_json_parser_2;
7586 goto basic_json_parser_4;
7588 goto basic_json_parser_9;
7594 goto basic_json_parser_4;
7598 goto basic_json_parser_10;
7600 goto basic_json_parser_12;
7609 goto basic_json_parser_4;
7613 goto basic_json_parser_13;
7615 goto basic_json_parser_15;
7621 goto basic_json_parser_17;
7625 goto basic_json_parser_19;
7627 goto basic_json_parser_4;
7639 goto basic_json_parser_21;
7643 goto basic_json_parser_4;
7645 goto basic_json_parser_23;
7651 goto basic_json_parser_24;
7655 goto basic_json_parser_4;
7657 goto basic_json_parser_25;
7666 goto basic_json_parser_26;
7668 goto basic_json_parser_4;
7674 goto basic_json_parser_28;
7678 goto basic_json_parser_30;
7680 goto basic_json_parser_4;
7684 basic_json_parser_2:
7687 return token_type::end_of_input;
7689 basic_json_parser_4:
7691 basic_json_parser_5:
7693 return token_type::parse_error;
7695 basic_json_parser_6:
7697 if (m_limit <= m_cursor)
7702 if (yybm[0 + yych] & 32)
7704 goto basic_json_parser_6;
7709 basic_json_parser_9:
7711 yych = *(m_marker = ++m_cursor);
7714 goto basic_json_parser_5;
7716 goto basic_json_parser_32;
7717 basic_json_parser_10:
7720 return token_type::value_separator;
7722 basic_json_parser_12:
7726 goto basic_json_parser_5;
7730 goto basic_json_parser_13;
7734 goto basic_json_parser_15;
7736 goto basic_json_parser_5;
7737 basic_json_parser_13:
7739 yych = *(m_marker = ++m_cursor);
7744 goto basic_json_parser_37;
7751 goto basic_json_parser_38;
7755 goto basic_json_parser_38;
7758 basic_json_parser_14:
7760 return token_type::value_number;
7762 basic_json_parser_15:
7764 m_marker = ++m_cursor;
7765 if ((m_limit - m_cursor) < 3)
7770 if (yybm[0 + yych] & 64)
7772 goto basic_json_parser_15;
7778 goto basic_json_parser_37;
7780 goto basic_json_parser_14;
7786 goto basic_json_parser_38;
7790 goto basic_json_parser_38;
7792 goto basic_json_parser_14;
7794 basic_json_parser_17:
7797 return token_type::name_separator;
7799 basic_json_parser_19:
7802 return token_type::begin_array;
7804 basic_json_parser_21:
7807 return token_type::end_array;
7809 basic_json_parser_23:
7811 yych = *(m_marker = ++m_cursor);
7814 goto basic_json_parser_39;
7816 goto basic_json_parser_5;
7817 basic_json_parser_24:
7819 yych = *(m_marker = ++m_cursor);
7822 goto basic_json_parser_40;
7824 goto basic_json_parser_5;
7825 basic_json_parser_25:
7827 yych = *(m_marker = ++m_cursor);
7830 goto basic_json_parser_41;
7832 goto basic_json_parser_5;
7833 basic_json_parser_26:
7836 return token_type::begin_object;
7838 basic_json_parser_28:
7841 return token_type::end_object;
7843 basic_json_parser_30:
7845 yych = *(m_marker = ++m_cursor);
7848 goto basic_json_parser_42;
7850 goto basic_json_parser_5;
7851 basic_json_parser_31:
7853 if (m_limit <= m_cursor)
7858 basic_json_parser_32:
7859 if (yybm[0 + yych] & 128)
7861 goto basic_json_parser_31;
7865 goto basic_json_parser_33;
7869 goto basic_json_parser_34;
7871 goto basic_json_parser_36;
7872 basic_json_parser_33:
7873 m_cursor = m_marker;
7876 goto basic_json_parser_5;
7880 goto basic_json_parser_14;
7882 basic_json_parser_34:
7885 return token_type::value_string;
7887 basic_json_parser_36:
7889 if (m_limit <= m_cursor)
7900 goto basic_json_parser_31;
7904 goto basic_json_parser_33;
7906 goto basic_json_parser_31;
7914 goto basic_json_parser_33;
7916 goto basic_json_parser_31;
7922 goto basic_json_parser_31;
7924 goto basic_json_parser_33;
7934 goto basic_json_parser_31;
7938 goto basic_json_parser_31;
7940 goto basic_json_parser_33;
7948 goto basic_json_parser_31;
7950 goto basic_json_parser_33;
7956 goto basic_json_parser_31;
7960 goto basic_json_parser_43;
7962 goto basic_json_parser_33;
7966 basic_json_parser_37:
7970 goto basic_json_parser_33;
7974 goto basic_json_parser_44;
7976 goto basic_json_parser_33;
7977 basic_json_parser_38:
7983 goto basic_json_parser_46;
7985 goto basic_json_parser_33;
7991 goto basic_json_parser_46;
7995 goto basic_json_parser_33;
7999 goto basic_json_parser_47;
8001 goto basic_json_parser_33;
8003 basic_json_parser_39:
8007 goto basic_json_parser_49;
8009 goto basic_json_parser_33;
8010 basic_json_parser_40:
8014 goto basic_json_parser_50;
8016 goto basic_json_parser_33;
8017 basic_json_parser_41:
8021 goto basic_json_parser_51;
8023 goto basic_json_parser_33;
8024 basic_json_parser_42:
8028 goto basic_json_parser_52;
8030 goto basic_json_parser_33;
8031 basic_json_parser_43:
8033 if (m_limit <= m_cursor)
8042 goto basic_json_parser_33;
8046 goto basic_json_parser_54;
8048 goto basic_json_parser_33;
8054 goto basic_json_parser_54;
8058 goto basic_json_parser_33;
8062 goto basic_json_parser_54;
8064 goto basic_json_parser_33;
8066 basic_json_parser_44:
8068 m_marker = ++m_cursor;
8069 if ((m_limit - m_cursor) < 3)
8078 goto basic_json_parser_14;
8082 goto basic_json_parser_44;
8084 goto basic_json_parser_14;
8090 goto basic_json_parser_38;
8094 goto basic_json_parser_38;
8096 goto basic_json_parser_14;
8098 basic_json_parser_46:
8102 goto basic_json_parser_33;
8106 goto basic_json_parser_33;
8108 basic_json_parser_47:
8110 if (m_limit <= m_cursor)
8117 goto basic_json_parser_14;
8121 goto basic_json_parser_47;
8123 goto basic_json_parser_14;
8124 basic_json_parser_49:
8128 goto basic_json_parser_55;
8130 goto basic_json_parser_33;
8131 basic_json_parser_50:
8135 goto basic_json_parser_56;
8137 goto basic_json_parser_33;
8138 basic_json_parser_51:
8142 goto basic_json_parser_58;
8144 goto basic_json_parser_33;
8145 basic_json_parser_52:
8150 basic_json_parser_54:
8152 if (m_limit <= m_cursor)
8161 goto basic_json_parser_33;
8165 goto basic_json_parser_60;
8167 goto basic_json_parser_33;
8173 goto basic_json_parser_60;
8177 goto basic_json_parser_33;
8181 goto basic_json_parser_60;
8183 goto basic_json_parser_33;
8185 basic_json_parser_55:
8189 goto basic_json_parser_61;
8191 goto basic_json_parser_33;
8192 basic_json_parser_56:
8195 return token_type::literal_null;
8197 basic_json_parser_58:
8200 return token_type::literal_true;
8202 basic_json_parser_60:
8204 if (m_limit <= m_cursor)
8213 goto basic_json_parser_33;
8217 goto basic_json_parser_63;
8219 goto basic_json_parser_33;
8225 goto basic_json_parser_63;
8229 goto basic_json_parser_33;
8233 goto basic_json_parser_63;
8235 goto basic_json_parser_33;
8237 basic_json_parser_61:
8240 return token_type::literal_false;
8242 basic_json_parser_63:
8244 if (m_limit <= m_cursor)
8253 goto basic_json_parser_33;
8257 goto basic_json_parser_31;
8259 goto basic_json_parser_33;
8265 goto basic_json_parser_31;
8269 goto basic_json_parser_33;
8273 goto basic_json_parser_31;
8275 goto basic_json_parser_33;
8282 void yyfill() noexcept
8284 if (m_stream ==
nullptr or not * m_stream)
8289 const auto offset_start = m_start - m_content;
8290 const auto offset_marker = m_marker - m_start;
8291 const auto offset_cursor = m_cursor - m_start;
8293 m_buffer.erase(0, static_cast<size_t>(offset_start));
8295 assert(m_stream !=
nullptr);
8296 std::getline(*m_stream, line);
8297 m_buffer +=
"\n" + line;
8299 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8300 assert(m_content !=
nullptr);
8301 m_start = m_content;
8302 m_marker = m_start + offset_marker;
8303 m_cursor = m_start + offset_cursor;
8304 m_limit = m_start + m_buffer.size() - 1;
8310 assert(m_start !=
nullptr);
8311 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8312 static_cast<size_t>(m_cursor - m_start));
8339 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8342 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8398 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8399 4).c_str(),
nullptr, 16);
8402 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8405 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8407 throw std::invalid_argument(
"missing low surrogate");
8411 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8412 (i + 7), 4).c_str(),
nullptr, 16);
8413 result += to_unicode(codepoint, codepoint2);
8420 result += to_unicode(codepoint);
8432 result.append(1, static_cast<typename string_t::value_type>(*i));
8459 long double str_to_float_t(
long double* ,
char** endptr)
const 8461 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8479 double str_to_float_t(
double* ,
char** endptr)
const 8481 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8499 float str_to_float_t(
float* ,
char** endptr)
const 8501 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8531 void get_number(basic_json& result)
const 8533 assert(m_start !=
nullptr);
8535 const lexer::lexer_char_t* curptr = m_start;
8538 result.m_type.bits.parsed =
true;
8543 uint8_t found_radix_point = 0;
8544 uint8_t precision = 0;
8558 type = value_t::number_integer;
8559 max =
static_cast<uint64_t
>(std::numeric_limits<number_integer_t>::max()) + 1;
8564 type = value_t::number_unsigned;
8565 max =
static_cast<uint64_t
>(std::numeric_limits<number_unsigned_t>::max());
8573 for (; curptr < m_cursor; curptr++)
8576 if (*curptr < '0' || *curptr >
'9')
8581 type = value_t::number_float;
8585 found_radix_point = 0xFF;
8590 type = value_t::number_float;
8591 result.m_type.bits.has_exp =
true;
8594 result.m_type.bits.exp_cap = (*curptr ==
'E');
8597 result.m_type.bits.exp_plus = (*(++curptr) ==
'+');
8602 if (type != value_t::number_float)
8605 auto temp = value * 10 + *curptr - 0x30;
8608 if (temp < value || temp > max)
8611 type = value_t::number_float;
8624 result.m_type.bits.precision = precision & found_radix_point;
8627 if (type == value_t::number_unsigned)
8629 result.m_value.number_unsigned = value;
8631 else if (type == value_t::number_integer)
8638 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8642 result.m_type = type;
8647 std::istream* m_stream =
nullptr;
8651 const lexer_char_t* m_content =
nullptr;
8653 const lexer_char_t* m_start =
nullptr;
8655 const lexer_char_t* m_marker =
nullptr;
8657 const lexer_char_t* m_cursor =
nullptr;
8659 const lexer_char_t* m_limit =
nullptr;
8672 : callback(cb), m_lexer(s)
8680 : callback(cb), m_lexer(&_is)
8689 basic_json result = parse_internal(
true);
8691 expect(lexer::token_type::end_of_input);
8700 basic_json parse_internal(
bool keep)
8702 auto result = basic_json(value_t::discarded);
8706 case lexer::token_type::begin_object:
8708 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8711 result.m_type = value_t::object;
8712 result.m_value = json_value(value_t::object);
8719 if (last_token == lexer::token_type::end_object)
8722 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8724 result = basic_json(value_t::discarded);
8730 unexpect(lexer::token_type::value_separator);
8736 if (last_token == lexer::token_type::value_separator)
8742 expect(lexer::token_type::value_string);
8743 const auto key = m_lexer.get_string();
8745 bool keep_tag =
false;
8751 keep_tag = callback(depth, parse_event_t::key, k);
8761 expect(lexer::token_type::name_separator);
8765 auto value = parse_internal(keep);
8766 if (keep and keep_tag and not value.is_discarded())
8768 result[key] = std::move(value);
8771 while (last_token == lexer::token_type::value_separator);
8774 expect(lexer::token_type::end_object);
8776 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8778 result = basic_json(value_t::discarded);
8784 case lexer::token_type::begin_array:
8786 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8789 result.m_type = value_t::array;
8790 result.m_value = json_value(value_t::array);
8797 if (last_token == lexer::token_type::end_array)
8800 if (callback and not callback(--depth, parse_event_t::array_end, result))
8802 result = basic_json(value_t::discarded);
8808 unexpect(lexer::token_type::value_separator);
8814 if (last_token == lexer::token_type::value_separator)
8820 auto value = parse_internal(keep);
8821 if (keep and not value.is_discarded())
8823 result.push_back(std::move(value));
8826 while (last_token == lexer::token_type::value_separator);
8829 expect(lexer::token_type::end_array);
8831 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8833 result = basic_json(value_t::discarded);
8839 case lexer::token_type::literal_null:
8842 result.m_type = value_t::null;
8846 case lexer::token_type::value_string:
8848 const auto s = m_lexer.get_string();
8850 result = basic_json(s);
8854 case lexer::token_type::literal_true:
8857 result.m_type = value_t::boolean;
8858 result.m_value =
true;
8862 case lexer::token_type::literal_false:
8865 result.m_type = value_t::boolean;
8866 result.m_value =
false;
8870 case lexer::token_type::value_number:
8872 m_lexer.get_number(result);
8880 unexpect(last_token);
8884 if (keep and callback and not callback(depth, parse_event_t::value, result))
8886 result = basic_json(value_t::discarded);
8892 typename lexer::token_type get_token() noexcept
8894 last_token = m_lexer.scan();
8898 void expect(
typename lexer::token_type t)
const 8900 if (t != last_token)
8902 std::string error_msg =
"parse error - unexpected ";
8903 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8904 lexer::token_type_name(last_token));
8905 error_msg +=
"; expected " + lexer::token_type_name(t);
8906 throw std::invalid_argument(error_msg);
8910 void unexpect(
typename lexer::token_type t)
const 8912 if (t == last_token)
8914 std::string error_msg =
"parse error - unexpected ";
8915 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8916 lexer::token_type_name(last_token));
8917 throw std::invalid_argument(error_msg);
8927 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8943 friend class basic_json;
8969 : reference_tokens(split(s))
8982 for (
const auto& reference_token : reference_tokens)
8984 switch (result->m_type)
8988 if (reference_token ==
"0")
8991 result = &result->operator[](0);
8996 result = &result->operator[](reference_token);
9001 case value_t::object:
9004 result = &result->operator[](reference_token);
9008 case value_t::array:
9011 result = &result->operator[](
static_cast<size_t>(std::stoi(reference_token)));
9024 throw std::domain_error(
"invalid value to unflatten");
9047 for (
const auto& reference_token : reference_tokens)
9049 switch (ptr->m_type)
9051 case value_t::object:
9054 ptr = &ptr->operator[](reference_token);
9058 case value_t::array:
9061 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9063 throw std::domain_error(
"array index must not begin with '0'");
9066 if (reference_token ==
"-")
9069 ptr = &ptr->operator[](ptr->m_value.array->size());
9074 ptr = &ptr->operator[](
static_cast<size_t>(std::stoi(reference_token)));
9081 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9091 for (
const auto& reference_token : reference_tokens)
9093 switch (ptr->m_type)
9095 case value_t::object:
9098 ptr = &ptr->
at(reference_token);
9102 case value_t::array:
9104 if (reference_token ==
"-")
9107 throw std::out_of_range(
"array index '-' (" +
9108 std::to_string(ptr->m_value.array->size()) +
9109 ") is out of range");
9113 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9115 throw std::domain_error(
"array index must not begin with '0'");
9119 ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
9125 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9143 for (
const auto& reference_token : reference_tokens)
9145 switch (ptr->m_type)
9147 case value_t::object:
9150 ptr = &ptr->operator[](reference_token);
9154 case value_t::array:
9156 if (reference_token ==
"-")
9159 throw std::out_of_range(
"array index '-' (" +
9160 std::to_string(ptr->m_value.array->size()) +
9161 ") is out of range");
9165 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9167 throw std::domain_error(
"array index must not begin with '0'");
9171 ptr = &ptr->operator[](
static_cast<size_t>(std::stoi(reference_token)));
9177 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9187 for (
const auto& reference_token : reference_tokens)
9189 switch (ptr->m_type)
9191 case value_t::object:
9194 ptr = &ptr->
at(reference_token);
9198 case value_t::array:
9200 if (reference_token ==
"-")
9203 throw std::out_of_range(
"array index '-' (" +
9204 std::to_string(ptr->m_value.array->size()) +
9205 ") is out of range");
9209 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9211 throw std::domain_error(
"array index must not begin with '0'");
9215 ptr = &ptr->at(static_cast<size_t>(std::stoi(reference_token)));
9221 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9230 std::vector<std::string> split(std::string reference_string)
9232 std::vector<std::string> result;
9235 if (reference_string.empty())
9241 if (reference_string[0] !=
'/')
9243 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9251 size_t slash = reference_string.find_first_of(
"/", 1),
9260 slash = reference_string.find_first_of(
"/", start))
9264 auto reference_token = reference_string.substr(start, slash - start);
9267 for (
size_t pos = reference_token.find_first_of(
"~");
9268 pos != std::string::npos;
9269 pos = reference_token.find_first_of(
"~", pos + 1))
9271 assert(reference_token[pos] ==
'~');
9274 if (pos == reference_token.size() - 1 or
9275 (reference_token[pos + 1] !=
'0' and
9276 reference_token[pos + 1] !=
'1'))
9278 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9283 replace_substring(reference_token,
"~1",
"/");
9285 replace_substring(reference_token,
"~0",
"~");
9288 result.push_back(reference_token);
9309 static void replace_substring(std::string& s,
9310 const std::string& f,
9311 const std::string& t)
9313 assert(not f.empty());
9316 size_t pos = s.find(f);
9317 pos != std::string::npos;
9318 s.replace(pos, f.size(), t),
9319 pos = s.find(f, pos + t.size())
9330 static void flatten(
const std::string reference_string,
9331 const basic_json& value,
9334 switch (value.m_type)
9336 case value_t::array:
9338 if (value.m_value.array->empty())
9341 result[reference_string] =
nullptr;
9346 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9348 flatten(reference_string +
"/" + std::to_string(i),
9349 value.m_value.array->operator[](i), result);
9355 case value_t::object:
9357 if (value.m_value.object->empty())
9360 result[reference_string] =
nullptr;
9365 for (
const auto& element : *value.m_value.object)
9368 std::string key(element.first);
9369 replace_substring(key,
"~",
"~0");
9370 replace_substring(key,
"/",
"~1");
9372 flatten(reference_string +
"/" + key,
9373 element.second, result);
9382 result[reference_string] = value;
9393 static basic_json unflatten(
const basic_json& value)
9397 throw std::domain_error(
"only objects can be unflattened");
9403 for (
const auto& element : *value.m_value.object)
9405 if (not element.second.is_primitive())
9407 throw std::domain_error(
"values in object must be primitive");
9415 json_pointer(element.first).get_and_create(result) = element.second;
9423 const std::vector<std::string> reference_tokens {};
9457 basic_json result(value_t::object);
9458 json_pointer::flatten(
"", *
this, result);
9491 return json_pointer::unflatten(*
this);
9529 is_nothrow_move_constructible<nlohmann::json>::value and
9530 is_nothrow_move_assignable<nlohmann::json>::value
9548 const auto& h = hash<nlohmann::json::string_t>();
9566 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
9582 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 9583 #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
basic_json<> json
default JSON class
ArrayType< basic_json, AllocatorType< basic_json >> array_t
a type for an array
reference front()
access the first element
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
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++)
basic_json flatten() const
return flattened JSON value
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
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
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)
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
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 unflatten() const
unflatten a previously flattened JSON value
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
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
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.