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;
344 using object_t = ObjectType<StringType,
346 std::less<StringType>,
347 AllocatorType<std::pair<
const StringType,
394 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
737 uint16_t has_exp : 1;
739 uint16_t exp_plus : 1;
741 uint16_t exp_cap : 1;
743 uint16_t precision : 8;
750 return static_cast<value_t>(bits.type);
754 bool operator==(
const value_t& rhs)
const 756 return static_cast<value_t>(bits.type) == rhs;
760 type_data_t& operator=(
value_t rhs)
762 bits.type =
static_cast<uint16_t
>(rhs) & 15;
767 type_data_t(
value_t t) noexcept
769 *
reinterpret_cast<uint16_t*
>(
this) = 0;
770 bits.type =
static_cast<uint16_t
>(t) & 15;
774 type_data_t() noexcept
777 bits.type =
reinterpret_cast<uint16_t
>(value_t::null);
782 template<
typename T,
typename... Args>
783 static T* create(Args&& ... args)
785 AllocatorType<T> alloc;
786 auto deleter = [&](T * object)
788 alloc.deallocate(
object, 1);
790 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
791 alloc.construct(
object.
get(), std::forward<Args>(args)...);
792 return object.release();
824 json_value() =
default;
826 json_value(
boolean_t v) noexcept : boolean(v) {}
838 case value_t::object:
840 object = create<object_t>();
846 array = create<array_t>();
850 case value_t::string:
852 string = create<string_t>(
"");
856 case value_t::boolean:
862 case value_t::number_integer:
868 case value_t::number_unsigned:
874 case value_t::number_float:
890 string = create<string_t>(value);
896 object = create<object_t>(value);
900 json_value(
const array_t& value)
902 array = create<array_t>(value);
985 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
1035 : m_type(value_type), m_value(value_type)
1062 basic_json() =
default;
1110 : m_type(
value_t::object), m_value(val)
1139 template <
class CompatibleObjectType,
typename 1141 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1142 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1149 m_value.object = create<object_t>(begin(val), end(val));
1172 : m_type(
value_t::array), m_value(val)
1201 template <
class CompatibleArrayType,
typename 1203 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1204 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1205 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1206 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1207 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1208 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1209 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1216 m_value.array = create<array_t>(begin(val), end(val));
1241 : m_type(
value_t::string), m_value(val)
1291 template <
class CompatibleStringType,
typename 1293 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1314 : m_type(value_t::boolean), m_value(val)
1340 template<
typename T,
1341 typename std::enable_if<
1342 not (std::is_same<T, int>::value)
1343 and std::is_same<T, number_integer_t>::value
1347 : m_type(value_t::number_integer), m_value(val)
1376 : m_type(value_t::number_integer),
1377 m_value(static_cast<number_integer_t>(val))
1405 template<
typename CompatibleNumberIntegerType,
typename 1407 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1408 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1409 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1410 CompatibleNumberIntegerType>::type
1413 : m_type(value_t::number_integer),
1414 m_value(static_cast<number_integer_t>(val))
1434 template<
typename T,
1435 typename std::enable_if<
1436 not (std::is_same<T, int>::value)
1437 and std::is_same<T, number_unsigned_t>::value
1441 : m_type(value_t::number_unsigned), m_value(val)
1464 template <
typename CompatibleNumberUnsignedType,
typename 1466 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1467 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1468 !std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1469 CompatibleNumberUnsignedType >::type
1472 : m_type(value_t::number_unsigned),
1473 m_value(static_cast<number_unsigned_t>(val))
1501 : m_type(value_t::number_float), m_value(val)
1504 if (not std::isfinite(val))
1506 m_type = value_t::null;
1507 m_value = json_value();
1542 template<
typename CompatibleNumberFloatType,
typename =
typename 1544 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1545 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1621 bool type_deduction =
true,
1622 value_t manual_type = value_t::array)
1625 bool is_an_object =
true;
1629 for (
const auto& element : init)
1631 if (not element.is_array() or element.size() != 2
1632 or not element[0].is_string())
1636 is_an_object =
false;
1642 if (not type_deduction)
1645 if (manual_type == value_t::array)
1647 is_an_object =
false;
1651 if (manual_type == value_t::object and not is_an_object)
1653 throw std::domain_error(
"cannot create object from initializer list");
1660 m_type = value_t::object;
1661 m_value = value_t::object;
1663 assert(m_value.object !=
nullptr);
1665 for (
auto& element : init)
1667 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1673 m_type = value_t::array;
1674 m_value.array = create<array_t>(init);
1712 static basic_json
array(std::initializer_list<basic_json> init =
1713 std::initializer_list<basic_json>())
1715 return basic_json(init,
false, value_t::array);
1752 static basic_json
object(std::initializer_list<basic_json> init =
1753 std::initializer_list<basic_json>())
1755 return basic_json(init,
false, value_t::object);
1779 m_value.array = create<array_t>(cnt, val);
1816 template <
class InputIT,
typename 1818 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1819 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1822 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1825 if (first.m_object != last.m_object)
1827 throw std::domain_error(
"iterators are not compatible");
1833 case value_t::boolean:
1834 case value_t::number_float:
1835 case value_t::number_integer:
1836 case value_t::number_unsigned:
1837 case value_t::string:
1839 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1841 throw std::out_of_range(
"iterators out of range");
1854 case value_t::number_integer:
1856 assert(first.m_object !=
nullptr);
1857 m_value.number_integer = first.m_object->m_value.number_integer;
1861 case value_t::number_unsigned:
1863 assert(first.m_object !=
nullptr);
1864 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1868 case value_t::number_float:
1870 assert(first.m_object !=
nullptr);
1871 m_value.number_float = first.m_object->m_value.number_float;
1875 case value_t::boolean:
1877 assert(first.m_object !=
nullptr);
1878 m_value.boolean = first.m_object->m_value.boolean;
1882 case value_t::string:
1884 assert(first.m_object !=
nullptr);
1885 m_value = *first.m_object->m_value.string;
1889 case value_t::object:
1891 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1895 case value_t::array:
1897 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1903 assert(first.m_object !=
nullptr);
1904 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1931 *
this = parser(i, cb).parse();
1961 : m_type(other.m_type)
1965 case value_t::object:
1967 assert(other.m_value.object !=
nullptr);
1968 m_value = *other.m_value.object;
1972 case value_t::array:
1974 assert(other.m_value.array !=
nullptr);
1975 m_value = *other.m_value.array;
1979 case value_t::string:
1981 assert(other.m_value.string !=
nullptr);
1982 m_value = *other.m_value.string;
1986 case value_t::boolean:
1988 m_value = other.m_value.boolean;
1992 case value_t::number_integer:
1994 m_value = other.m_value.number_integer;
1998 case value_t::number_unsigned:
2000 m_value = other.m_value.number_unsigned;
2004 case value_t::number_float:
2006 m_value = other.m_value.number_float;
2036 : m_type(
std::move(other.m_type)),
2037 m_value(
std::move(other.m_value))
2040 other.m_type = value_t::null;
2068 std::is_nothrow_move_constructible<value_t>::value and
2069 std::is_nothrow_move_assignable<value_t>::value and
2070 std::is_nothrow_move_constructible<json_value>::value and
2071 std::is_nothrow_move_assignable<json_value>::value
2075 swap(m_type, other.m_type);
2076 swap(m_value, other.m_value);
2099 case value_t::object:
2101 AllocatorType<object_t> alloc;
2102 alloc.destroy(m_value.object);
2103 alloc.deallocate(m_value.object, 1);
2107 case value_t::array:
2109 AllocatorType<array_t> alloc;
2110 alloc.destroy(m_value.array);
2111 alloc.deallocate(m_value.array, 1);
2115 case value_t::string:
2117 AllocatorType<string_t> alloc;
2118 alloc.destroy(m_value.string);
2119 alloc.deallocate(m_value.string, 1);
2166 std::stringstream ss;
2170 dump(ss,
true, static_cast<unsigned int>(indent));
2230 return is_null() or is_string() or is_boolean() or is_number();
2257 return is_array() or is_object();
2279 return m_type == value_t::null;
2301 return m_type == value_t::boolean;
2331 return is_number_integer() or is_number_float();
2360 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2388 return m_type == value_t::number_unsigned;
2416 return m_type == value_t::number_float;
2438 return m_type == value_t::object;
2460 return m_type == value_t::array;
2482 return m_type == value_t::string;
2509 return m_type == value_t::discarded;
2543 template <
class T,
typename 2545 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2546 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2548 T get_impl(T*)
const 2552 assert(m_value.object !=
nullptr);
2553 return T(m_value.object->begin(), m_value.object->end());
2557 throw std::domain_error(
"type must be object, but is " + type_name());
2566 assert(m_value.object !=
nullptr);
2567 return *(m_value.object);
2571 throw std::domain_error(
"type must be object, but is " + type_name());
2576 template <
class T,
typename 2578 std::is_convertible<basic_json_t, typename T::value_type>::value and
2579 not std::is_same<basic_json_t, typename T::value_type>::value and
2580 not std::is_arithmetic<T>::value and
2581 not std::is_convertible<std::string, T>::value and
2582 not has_mapped_type<T>::value
2584 T get_impl(T*)
const 2589 assert(m_value.array !=
nullptr);
2590 std::transform(m_value.array->begin(), m_value.array->end(),
2591 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2593 return i.
get<
typename T::value_type>();
2599 throw std::domain_error(
"type must be array, but is " + type_name());
2604 template <
class T,
typename 2606 std::is_convertible<basic_json_t, T>::value and
2607 not std::is_same<basic_json_t, T>::value
2609 std::vector<T> get_impl(std::vector<T>*)
const 2613 std::vector<T> to_vector;
2614 assert(m_value.array !=
nullptr);
2615 to_vector.reserve(m_value.array->size());
2616 std::transform(m_value.array->begin(), m_value.array->end(),
2617 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2625 throw std::domain_error(
"type must be array, but is " + type_name());
2630 template <
class T,
typename 2632 std::is_same<basic_json, typename T::value_type>::value and
2633 not has_mapped_type<T>::value
2635 T get_impl(T*)
const 2639 assert(m_value.array !=
nullptr);
2640 return T(m_value.array->begin(), m_value.array->end());
2644 throw std::domain_error(
"type must be array, but is " + type_name());
2653 assert(m_value.array !=
nullptr);
2654 return *(m_value.array);
2658 throw std::domain_error(
"type must be array, but is " + type_name());
2663 template <
typename T,
typename 2665 std::is_convertible<string_t, T>::value
2667 T get_impl(T*)
const 2671 assert(m_value.string !=
nullptr);
2672 return *m_value.string;
2676 throw std::domain_error(
"type must be string, but is " + type_name());
2681 template<
typename T,
typename 2683 std::is_arithmetic<T>::value
2685 T get_impl(T*)
const 2689 case value_t::number_integer:
2691 return static_cast<T
>(m_value.number_integer);
2694 case value_t::number_unsigned:
2696 return static_cast<T
>(m_value.number_unsigned);
2699 case value_t::number_float:
2701 return static_cast<T
>(m_value.number_float);
2706 throw std::domain_error(
"type must be number, but is " + type_name());
2716 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2722 return is_object() ? m_value.object :
nullptr;
2728 return is_object() ? m_value.object :
nullptr;
2734 return is_array() ? m_value.array :
nullptr;
2738 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2740 return is_array() ? m_value.array :
nullptr;
2746 return is_string() ? m_value.string :
nullptr;
2752 return is_string() ? m_value.string :
nullptr;
2758 return is_boolean() ? &m_value.boolean :
nullptr;
2764 return is_boolean() ? &m_value.boolean :
nullptr;
2770 return is_number_integer() ? &m_value.number_integer :
nullptr;
2776 return is_number_integer() ? &m_value.number_integer :
nullptr;
2782 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2788 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2794 return is_number_float() ? &m_value.number_float :
nullptr;
2800 return is_number_float() ? &m_value.number_float :
nullptr;
2814 template<
typename ReferenceType,
typename ThisType>
2815 static ReferenceType get_ref_impl(ThisType& obj)
2818 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2819 auto ptr = obj.template get_ptr<PointerType>();
2827 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2870 template<
typename ValueType,
typename 2872 not std::is_pointer<ValueType>::value
2874 ValueType
get()
const 2876 return get_impl(static_cast<ValueType*>(
nullptr));
2905 template<
typename PointerType,
typename 2907 std::is_pointer<PointerType>::value
2909 PointerType
get() noexcept
2912 return get_ptr<PointerType>();
2919 template<
typename PointerType,
typename 2921 std::is_pointer<PointerType>::value
2923 constexpr
const PointerType
get()
const noexcept
2926 return get_ptr<PointerType>();
2954 template<
typename PointerType,
typename 2956 std::is_pointer<PointerType>::value
2961 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2968 template<
typename PointerType,
typename 2970 std::is_pointer<PointerType>::value
2971 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2973 constexpr
const PointerType
get_ptr() const noexcept
2976 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3005 template<
typename ReferenceType,
typename 3007 std::is_reference<ReferenceType>::value
3012 return get_ref_impl<ReferenceType>(*this);
3019 template<
typename ReferenceType,
typename 3021 std::is_reference<ReferenceType>::value
3022 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
3027 return get_ref_impl<ReferenceType>(*this);
3058 template <
typename ValueType,
typename 3060 not std::is_pointer<ValueType>::value
3061 and not std::is_same<ValueType, typename string_t::value_type>::value
3062 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3063 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3066 operator ValueType()
const 3069 return get<ValueType>();
3111 assert(m_value.array !=
nullptr);
3112 return m_value.array->at(idx);
3114 catch (std::out_of_range&)
3117 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3122 throw std::domain_error(
"cannot use at() with " + type_name());
3155 assert(m_value.array !=
nullptr);
3156 return m_value.array->at(idx);
3158 catch (std::out_of_range&)
3161 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3166 throw std::domain_error(
"cannot use at() with " + type_name());
3203 assert(m_value.object !=
nullptr);
3204 return m_value.object->at(key);
3206 catch (std::out_of_range&)
3209 throw std::out_of_range(
"key '" + key +
"' not found");
3214 throw std::domain_error(
"cannot use at() with " + type_name());
3251 assert(m_value.object !=
nullptr);
3252 return m_value.object->at(key);
3254 catch (std::out_of_range&)
3257 throw std::out_of_range(
"key '" + key +
"' not found");
3262 throw std::domain_error(
"cannot use at() with " + type_name());
3296 m_type = value_t::array;
3297 m_value.
array = create<array_t>();
3304 assert(m_value.array !=
nullptr);
3305 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3307 m_value.array->push_back(basic_json());
3310 return m_value.array->operator[](idx);
3314 throw std::domain_error(
"cannot use operator[] with " + type_name());
3342 assert(m_value.array !=
nullptr);
3343 return m_value.array->operator[](idx);
3347 throw std::domain_error(
"cannot use operator[] with " + type_name());
3383 m_type = value_t::object;
3384 m_value.
object = create<object_t>();
3390 assert(m_value.object !=
nullptr);
3391 return m_value.object->operator[](key);
3395 throw std::domain_error(
"cannot use operator[] with " + type_name());
3431 assert(m_value.object !=
nullptr);
3432 assert(m_value.object->find(key) != m_value.object->end());
3433 return m_value.object->find(key)->second;
3437 throw std::domain_error(
"cannot use operator[] with " + type_name());
3468 template<
typename T, std::
size_t n>
3471 return operator[](static_cast<const T>(key));
3503 template<
typename T, std::
size_t n>
3506 return operator[](static_cast<const T>(key));
3536 template<
typename T>
3542 m_type = value_t::object;
3543 m_value = value_t::object;
3549 assert(m_value.object !=
nullptr);
3550 return m_value.object->operator[](key);
3554 throw std::domain_error(
"cannot use operator[] with " + type_name());
3585 template<
typename T>
3591 assert(m_value.object !=
nullptr);
3592 assert(m_value.object->find(key) != m_value.object->end());
3593 return m_value.object->find(key)->second;
3597 throw std::domain_error(
"cannot use operator[] with " + type_name());
3649 template <
class ValueType,
typename 3651 std::is_convertible<basic_json_t, ValueType>::value
3653 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3659 const auto it = find(key);
3666 return default_value;
3671 throw std::domain_error(
"cannot use value() with " + type_name());
3679 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3681 return value(key,
string_t(default_value));
3812 template <
class InteratorType,
typename 3814 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3815 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3821 if (
this != pos.m_object)
3823 throw std::domain_error(
"iterator does not fit current value");
3826 InteratorType result = end();
3830 case value_t::boolean:
3831 case value_t::number_float:
3832 case value_t::number_integer:
3833 case value_t::number_unsigned:
3834 case value_t::string:
3836 if (not pos.m_it.primitive_iterator.is_begin())
3838 throw std::out_of_range(
"iterator out of range");
3843 delete m_value.string;
3844 m_value.string =
nullptr;
3847 m_type = value_t::null;
3851 case value_t::object:
3853 assert(m_value.object !=
nullptr);
3854 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3858 case value_t::array:
3860 assert(m_value.array !=
nullptr);
3861 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3867 throw std::domain_error(
"cannot use erase() with " + type_name());
3920 template <
class InteratorType,
typename 3922 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3923 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3926 InteratorType
erase(InteratorType first, InteratorType last)
3929 if (
this != first.m_object or
this != last.m_object)
3931 throw std::domain_error(
"iterators do not fit current value");
3934 InteratorType result = end();
3938 case value_t::boolean:
3939 case value_t::number_float:
3940 case value_t::number_integer:
3941 case value_t::number_unsigned:
3942 case value_t::string:
3944 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3946 throw std::out_of_range(
"iterators out of range");
3951 delete m_value.string;
3952 m_value.string =
nullptr;
3955 m_type = value_t::null;
3959 case value_t::object:
3961 assert(m_value.object !=
nullptr);
3962 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3963 last.m_it.object_iterator);
3967 case value_t::array:
3969 assert(m_value.array !=
nullptr);
3970 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3971 last.m_it.array_iterator);
3977 throw std::domain_error(
"cannot use erase() with " + type_name());
4018 assert(m_value.object !=
nullptr);
4019 return m_value.object->erase(key);
4023 throw std::domain_error(
"cannot use erase() with " + type_name());
4058 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4061 assert(m_value.array !=
nullptr);
4062 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4066 throw std::domain_error(
"cannot use erase() with " + type_name());
4100 auto result = end();
4104 assert(m_value.object !=
nullptr);
4105 result.m_it.object_iterator = m_value.object->find(key);
4117 auto result = cend();
4121 assert(m_value.object !=
nullptr);
4122 result.m_it.object_iterator = m_value.object->find(key);
4149 assert(not is_object() or m_value.object !=
nullptr);
4150 return is_object() ? m_value.object->count(key) : 0;
4438 template<
typename IteratorType>
class iteration_proxy;
4454 return iteration_proxy<iterator>(cont);
4462 return iteration_proxy<const_iterator>(cont);
4518 case value_t::array:
4520 assert(m_value.array !=
nullptr);
4521 return m_value.array->empty();
4524 case value_t::object:
4526 assert(m_value.object !=
nullptr);
4527 return m_value.object->empty();
4582 case value_t::array:
4584 assert(m_value.array !=
nullptr);
4585 return m_value.array->size();
4588 case value_t::object:
4590 assert(m_value.object !=
nullptr);
4591 return m_value.object->size();
4642 case value_t::array:
4644 assert(m_value.array !=
nullptr);
4645 return m_value.array->max_size();
4648 case value_t::object:
4650 assert(m_value.object !=
nullptr);
4651 return m_value.object->max_size();
4701 case value_t::number_integer:
4703 m_value.number_integer = 0;
4707 case value_t::number_unsigned:
4709 m_value.number_unsigned = 0;
4713 case value_t::number_float:
4715 m_value.number_float = 0.0;
4719 case value_t::boolean:
4721 m_value.boolean =
false;
4725 case value_t::string:
4727 assert(m_value.string !=
nullptr);
4728 m_value.string->clear();
4732 case value_t::array:
4734 assert(m_value.array !=
nullptr);
4735 m_value.array->clear();
4739 case value_t::object:
4741 assert(m_value.object !=
nullptr);
4742 m_value.object->clear();
4776 if (not(is_null() or is_array()))
4778 throw std::domain_error(
"cannot use push_back() with " + type_name());
4784 m_type = value_t::array;
4785 m_value = value_t::array;
4789 assert(m_value.array !=
nullptr);
4790 m_value.array->push_back(std::move(val));
4792 val.m_type = value_t::null;
4801 push_back(std::move(val));
4812 if (not(is_null() or is_array()))
4814 throw std::domain_error(
"cannot use push_back() with " + type_name());
4820 m_type = value_t::array;
4821 m_value = value_t::array;
4825 assert(m_value.array !=
nullptr);
4826 m_value.array->push_back(val);
4862 if (not(is_null() or is_object()))
4864 throw std::domain_error(
"cannot use push_back() with " + type_name());
4870 m_type = value_t::object;
4871 m_value = value_t::object;
4875 assert(m_value.object !=
nullptr);
4876 m_value.object->insert(val);
4916 if (is_object() and init.size() == 2 and init.begin()->is_string())
4918 const string_t key = *init.begin();
4919 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
4923 push_back(basic_json(init));
4965 if (pos.m_object !=
this)
4967 throw std::domain_error(
"iterator does not fit current value");
4972 assert(m_value.array !=
nullptr);
4973 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4978 throw std::domain_error(
"cannot use insert() with " + type_name());
4988 return insert(pos, val);
5021 if (pos.m_object !=
this)
5023 throw std::domain_error(
"iterator does not fit current value");
5028 assert(m_value.array !=
nullptr);
5029 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5034 throw std::domain_error(
"cannot use insert() with " + type_name());
5073 throw std::domain_error(
"cannot use insert() with " + type_name());
5077 if (pos.m_object !=
this)
5079 throw std::domain_error(
"iterator does not fit current value");
5082 if (first.m_object != last.m_object)
5084 throw std::domain_error(
"iterators do not fit");
5087 if (first.m_object ==
this or last.m_object ==
this)
5089 throw std::domain_error(
"passed iterators may not belong to container");
5094 assert(m_value.array !=
nullptr);
5095 result.m_it.array_iterator = m_value.array->insert(
5096 pos.m_it.array_iterator,
5097 first.m_it.array_iterator,
5098 last.m_it.array_iterator);
5131 throw std::domain_error(
"cannot use insert() with " + type_name());
5135 if (pos.m_object !=
this)
5137 throw std::domain_error(
"iterator does not fit current value");
5142 assert(m_value.array !=
nullptr);
5143 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5165 std::is_nothrow_move_constructible<value_t>::value and
5166 std::is_nothrow_move_assignable<value_t>::value and
5167 std::is_nothrow_move_constructible<json_value>::value and
5168 std::is_nothrow_move_assignable<json_value>::value
5171 std::swap(m_type, other.m_type);
5172 std::swap(m_value, other.m_value);
5200 assert(m_value.array !=
nullptr);
5201 std::swap(*(m_value.array), other);
5205 throw std::domain_error(
"cannot use swap() with " + type_name());
5234 assert(m_value.object !=
nullptr);
5235 std::swap(*(m_value.object), other);
5239 throw std::domain_error(
"cannot use swap() with " + type_name());
5268 assert(m_value.string !=
nullptr);
5269 std::swap(*(m_value.string), other);
5273 throw std::domain_error(
"cannot use swap() with " + type_name());
5299 static constexpr std::array<uint8_t, 8> order = {{
5312 if (lhs == value_t::discarded or rhs == value_t::discarded)
5317 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5346 const auto lhs_type = lhs.type();
5347 const auto rhs_type = rhs.type();
5349 if (lhs_type == rhs_type)
5353 case value_t::array:
5355 assert(lhs.m_value.array !=
nullptr);
5356 assert(rhs.m_value.array !=
nullptr);
5357 return *lhs.m_value.array == *rhs.m_value.array;
5359 case value_t::object:
5361 assert(lhs.m_value.object !=
nullptr);
5362 assert(rhs.m_value.object !=
nullptr);
5363 return *lhs.m_value.object == *rhs.m_value.object;
5369 case value_t::string:
5371 assert(lhs.m_value.string !=
nullptr);
5372 assert(rhs.m_value.string !=
nullptr);
5373 return *lhs.m_value.string == *rhs.m_value.string;
5375 case value_t::boolean:
5377 return lhs.m_value.boolean == rhs.m_value.boolean;
5379 case value_t::number_integer:
5381 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5383 case value_t::number_unsigned:
5385 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5387 case value_t::number_float:
5389 return lhs.m_value.number_float == rhs.m_value.number_float;
5397 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5399 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5401 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5403 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5405 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5407 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5409 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5411 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5413 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5415 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5417 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5419 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5475 return not (lhs == rhs);
5507 return not v.is_null();
5536 const auto lhs_type = lhs.type();
5537 const auto rhs_type = rhs.type();
5539 if (lhs_type == rhs_type)
5543 case value_t::array:
5545 assert(lhs.m_value.array !=
nullptr);
5546 assert(rhs.m_value.array !=
nullptr);
5547 return *lhs.m_value.array < *rhs.m_value.array;
5549 case value_t::object:
5551 assert(lhs.m_value.object !=
nullptr);
5552 assert(rhs.m_value.object !=
nullptr);
5553 return *lhs.m_value.object < *rhs.m_value.object;
5559 case value_t::string:
5561 assert(lhs.m_value.string !=
nullptr);
5562 assert(rhs.m_value.string !=
nullptr);
5563 return *lhs.m_value.string < *rhs.m_value.string;
5565 case value_t::boolean:
5567 return lhs.m_value.boolean < rhs.m_value.boolean;
5569 case value_t::number_integer:
5571 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5573 case value_t::number_unsigned:
5575 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5577 case value_t::number_float:
5579 return lhs.m_value.number_float < rhs.m_value.number_float;
5587 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5589 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5591 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5593 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5595 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5597 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5599 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5601 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5603 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5605 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5607 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5609 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5615 return operator<(lhs_type, rhs_type);
5637 return not (rhs < lhs);
5659 return not (lhs <= rhs);
5681 return not (lhs < rhs);
5716 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5719 const bool pretty_print = (o.width() > 0);
5720 const auto indentation = (pretty_print ? o.width() : 0);
5726 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5734 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5775 return parser(s, cb).
parse();
5804 return parser(i, cb).
parse();
5812 return parser(i, cb).
parse();
5840 j = parser(i).
parse();
5850 j = parser(i).
parse();
5863 string_t type_name()
const noexcept
5869 case value_t::object:
5871 case value_t::array:
5873 case value_t::string:
5875 case value_t::boolean:
5877 case value_t::discarded:
5892 static std::size_t extra_space(
const string_t& s) noexcept
5894 std::size_t result = 0;
5896 for (
const auto& c : s)
5915 if (c >= 0x00 and c <= 0x1f)
5943 const auto space = extra_space(s);
5950 string_t result(s.size() + space,
'\\');
5951 std::size_t pos = 0;
5953 for (
const auto& c : s)
5960 result[pos + 1] =
'"';
5976 result[pos + 1] =
'b';
5984 result[pos + 1] =
'f';
5992 result[pos + 1] =
'n';
6000 result[pos + 1] =
'r';
6008 result[pos + 1] =
't';
6015 if (c >= 0x00 and c <= 0x1f)
6019 const auto hexify = [](
const int v) ->
char 6022 ? (
'0' +
static_cast<char>(v))
6023 : (
'a' +
static_cast<char>((v - 10) & 0x1f));
6028 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6066 void dump(std::ostream& o,
6067 const bool pretty_print,
6068 const unsigned int indent_step,
6069 const unsigned int current_indent = 0)
const 6072 unsigned int new_indent = current_indent;
6076 case value_t::object:
6078 assert(m_value.object !=
nullptr);
6080 if (m_value.object->empty())
6091 new_indent += indent_step;
6095 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6097 if (i != m_value.object->cbegin())
6099 o << (pretty_print ?
",\n" :
",");
6101 o <<
string_t(new_indent,
' ') <<
"\"" 6102 << escape_string(i->first) <<
"\":" 6103 << (pretty_print ?
" " :
"");
6104 i->second.dump(o, pretty_print, indent_step, new_indent);
6110 new_indent -= indent_step;
6114 o <<
string_t(new_indent,
' ') +
"}";
6118 case value_t::array:
6120 assert(m_value.array !=
nullptr);
6122 if (m_value.array->empty())
6133 new_indent += indent_step;
6137 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6139 if (i != m_value.array->cbegin())
6141 o << (pretty_print ?
",\n" :
",");
6144 i->dump(o, pretty_print, indent_step, new_indent);
6150 new_indent -= indent_step;
6154 o <<
string_t(new_indent,
' ') <<
"]";
6158 case value_t::string:
6160 assert(m_value.string !=
nullptr);
6161 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6165 case value_t::boolean:
6167 o << (m_value.boolean ?
"true" :
"false");
6171 case value_t::number_integer:
6173 o << m_value.number_integer;
6177 case value_t::number_unsigned:
6179 o << m_value.number_unsigned;
6183 case value_t::number_float:
6186 if (m_type.bits.parsed)
6189 if (m_type.bits.has_exp)
6196 if (m_type.bits.exp_cap)
6198 len = snprintf(buf,
sizeof(buf),
"%.*E",
6199 m_type.bits.precision, m_value.number_float) + 1;
6203 len = snprintf(buf,
sizeof(buf),
"%.*e",
6204 m_type.bits.precision, m_value.number_float) + 1;
6208 if (not m_type.bits.exp_plus)
6210 if (len > static_cast<int>(
sizeof(buf)))
6214 for (
int i = 0; i < len; i++)
6218 for (; i + 1 < len; i++)
6220 buf[i] = buf[i + 1];
6231 std::stringstream ss;
6232 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6233 ss << std::setprecision(m_type.bits.precision)
6234 << std::fixed << m_value.number_float;
6240 if (m_value.number_float == 0)
6243 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6252 std::stringstream ss;
6253 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
6254 ss << std::setprecision(std::numeric_limits<double>::digits10)
6255 << m_value.number_float;
6262 case value_t::discarded:
6282 type_data_t m_type = value_t::null;
6285 json_value m_value = {};
6302 class primitive_iterator_t
6306 void set_begin() noexcept
6312 void set_end() noexcept
6318 constexpr
bool is_begin()
const noexcept
6320 return (m_it == begin_value);
6324 constexpr
bool is_end()
const noexcept
6326 return (m_it == end_value);
6346 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6356 struct internal_iterator
6359 typename object_t::iterator object_iterator;
6361 typename array_t::iterator array_iterator;
6363 primitive_iterator_t primitive_iterator;
6366 internal_iterator() noexcept
6367 : object_iterator(), array_iterator(), primitive_iterator()
6372 template<
typename IteratorType>
6373 class iteration_proxy
6377 class iteration_proxy_internal
6381 IteratorType anchor;
6383 size_t array_index = 0;
6386 explicit iteration_proxy_internal(IteratorType it) noexcept
6391 iteration_proxy_internal& operator*()
6397 iteration_proxy_internal& operator++()
6406 bool operator!= (
const iteration_proxy_internal& o)
const 6408 return anchor != o.anchor;
6414 assert(anchor.m_object !=
nullptr);
6416 switch (anchor.m_object->type())
6419 case value_t::array:
6421 return std::to_string(array_index);
6425 case value_t::object:
6427 return anchor.key();
6439 typename IteratorType::reference value()
const 6441 return anchor.value();
6446 typename IteratorType::reference container;
6450 explicit iteration_proxy(
typename IteratorType::reference cont)
6455 iteration_proxy_internal begin() noexcept
6457 return iteration_proxy_internal(container.begin());
6461 iteration_proxy_internal end() noexcept
6463 return iteration_proxy_internal(container.end());
6481 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6484 friend class basic_json;
6505 assert(m_object !=
nullptr);
6507 switch (m_object->m_type)
6511 m_it.object_iterator =
typename object_t::iterator();
6517 m_it.array_iterator =
typename array_t::iterator();
6523 m_it.primitive_iterator = primitive_iterator_t();
6531 : m_object(other.m_object)
6533 assert(m_object !=
nullptr);
6535 switch (m_object->m_type)
6539 m_it.object_iterator = other.m_it.object_iterator;
6545 m_it.array_iterator = other.m_it.array_iterator;
6551 m_it.primitive_iterator = other.m_it.primitive_iterator;
6559 : m_object(other.m_object), m_it(other.m_it)
6564 std::is_nothrow_move_constructible<pointer>::value and
6565 std::is_nothrow_move_assignable<pointer>::value and
6566 std::is_nothrow_move_constructible<internal_iterator>::value and
6567 std::is_nothrow_move_assignable<internal_iterator>::value
6570 std::swap(m_object, other.m_object);
6571 std::swap(m_it, other.m_it);
6577 void set_begin() noexcept
6579 assert(m_object !=
nullptr);
6581 switch (m_object->m_type)
6585 assert(m_object->m_value.object !=
nullptr);
6586 m_it.object_iterator = m_object->m_value.object->begin();
6592 assert(m_object->m_value.array !=
nullptr);
6593 m_it.array_iterator = m_object->m_value.array->begin();
6600 m_it.primitive_iterator.set_end();
6606 m_it.primitive_iterator.set_begin();
6613 void set_end() noexcept
6615 assert(m_object !=
nullptr);
6617 switch (m_object->m_type)
6621 assert(m_object->m_value.object !=
nullptr);
6622 m_it.object_iterator = m_object->m_value.object->end();
6628 assert(m_object->m_value.array !=
nullptr);
6629 m_it.array_iterator = m_object->m_value.array->end();
6635 m_it.primitive_iterator.set_end();
6645 assert(m_object !=
nullptr);
6647 switch (m_object->m_type)
6651 assert(m_object->m_value.object);
6652 assert(m_it.object_iterator != m_object->m_value.object->end());
6653 return m_it.object_iterator->second;
6658 assert(m_object->m_value.array);
6659 assert(m_it.array_iterator != m_object->m_value.array->end());
6660 return *m_it.array_iterator;
6665 throw std::out_of_range(
"cannot get value");
6670 if (m_it.primitive_iterator.is_begin())
6676 throw std::out_of_range(
"cannot get value");
6685 assert(m_object !=
nullptr);
6687 switch (m_object->m_type)
6691 assert(m_object->m_value.object);
6692 assert(m_it.object_iterator != m_object->m_value.object->end());
6693 return &(m_it.object_iterator->second);
6698 assert(m_object->m_value.array);
6699 assert(m_it.array_iterator != m_object->m_value.array->end());
6700 return &*m_it.array_iterator;
6705 if (m_it.primitive_iterator.is_begin())
6711 throw std::out_of_range(
"cannot get value");
6720 auto result = *
this;
6728 assert(m_object !=
nullptr);
6730 switch (m_object->m_type)
6734 ++m_it.object_iterator;
6740 ++m_it.array_iterator;
6746 ++m_it.primitive_iterator;
6757 auto result = *
this;
6765 assert(m_object !=
nullptr);
6767 switch (m_object->m_type)
6771 --m_it.object_iterator;
6777 --m_it.array_iterator;
6783 --m_it.primitive_iterator;
6795 if (m_object != other.m_object)
6797 throw std::domain_error(
"cannot compare iterators of different containers");
6800 assert(m_object !=
nullptr);
6802 switch (m_object->m_type)
6806 return (m_it.object_iterator == other.m_it.object_iterator);
6811 return (m_it.array_iterator == other.m_it.array_iterator);
6816 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6824 return not operator==(other);
6831 if (m_object != other.m_object)
6833 throw std::domain_error(
"cannot compare iterators of different containers");
6836 assert(m_object !=
nullptr);
6838 switch (m_object->m_type)
6842 throw std::domain_error(
"cannot compare order of object iterators");
6847 return (m_it.array_iterator < other.m_it.array_iterator);
6852 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6860 return not other.operator < (*this);
6866 return not operator<=(other);
6872 return not operator<(other);
6878 assert(m_object !=
nullptr);
6880 switch (m_object->m_type)
6884 throw std::domain_error(
"cannot use offsets with object iterators");
6889 m_it.array_iterator += i;
6895 m_it.primitive_iterator += i;
6906 return operator+=(-i);
6912 auto result = *
this;
6920 auto result = *
this;
6928 assert(m_object !=
nullptr);
6930 switch (m_object->m_type)
6934 throw std::domain_error(
"cannot use offsets with object iterators");
6939 return m_it.array_iterator - other.m_it.array_iterator;
6944 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6952 assert(m_object !=
nullptr);
6954 switch (m_object->m_type)
6958 throw std::domain_error(
"cannot use operator[] for object iterators");
6963 return *(m_it.array_iterator + n);
6968 throw std::out_of_range(
"cannot get value");
6973 if (m_it.primitive_iterator == -n)
6979 throw std::out_of_range(
"cannot get value");
6986 typename object_t::key_type
key()
const 6988 assert(m_object !=
nullptr);
6990 if (m_object->is_object())
6992 return m_it.object_iterator->first;
6996 throw std::domain_error(
"cannot use key() for non-object iterators");
7010 internal_iterator m_it = internal_iterator();
7047 std::is_nothrow_move_constructible<pointer>::value and
7048 std::is_nothrow_move_assignable<pointer>::value and
7049 std::is_nothrow_move_constructible<internal_iterator>::value and
7050 std::is_nothrow_move_assignable<internal_iterator>::value
7053 base_iterator::operator=(other);
7060 return const_cast<reference>(base_iterator::operator*());
7066 return const_cast<pointer>(base_iterator::operator->());
7073 base_iterator::operator++();
7080 base_iterator::operator++();
7088 base_iterator::operator--();
7095 base_iterator::operator--();
7102 base_iterator::operator+=(i);
7109 base_iterator::operator-=(i);
7116 auto result = *
this;
7124 auto result = *
this;
7132 return base_iterator::operator-(other);
7138 return const_cast<reference>(base_iterator::operator[](n));
7144 return const_cast<reference>(base_iterator::value());
7165 template<
typename Base>
7187 return base_iterator::operator++(1);
7193 base_iterator::operator++();
7200 return base_iterator::operator--(1);
7206 base_iterator::operator--();
7213 base_iterator::operator+=(i);
7220 auto result = *
this;
7228 auto result = *
this;
7236 return this->base() - other.base();
7242 return *(this->operator+(n));
7246 typename object_t::key_type
key()
const 7248 auto it = --this->base();
7255 auto it = --this->base();
7256 return it.operator * ();
7277 enum class token_type
7296 using lexer_char_t =
unsigned char;
7299 explicit lexer(
const string_t& s) noexcept
7300 : m_stream(
nullptr), m_buffer(s)
7302 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7303 assert(m_content !=
nullptr);
7304 m_start = m_cursor = m_content;
7305 m_limit = m_content + s.size();
7309 explicit lexer(std::istream* s) noexcept
7310 : m_stream(s), m_buffer()
7312 assert(m_stream !=
nullptr);
7313 getline(*m_stream, m_buffer);
7314 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7315 assert(m_content !=
nullptr);
7316 m_start = m_cursor = m_content;
7317 m_limit = m_content + m_buffer.size();
7324 lexer(
const lexer&) =
delete;
7325 lexer operator=(
const lexer&) =
delete;
7342 static string_t to_unicode(
const std::size_t codepoint1,
7343 const std::size_t codepoint2 = 0)
7346 std::size_t codepoint = codepoint1;
7349 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7352 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7366 throw std::invalid_argument(
"missing or wrong low surrogate");
7372 if (codepoint < 0x80)
7375 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7377 else if (codepoint <= 0x7ff)
7380 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7381 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7383 else if (codepoint <= 0xffff)
7386 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7387 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7388 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7390 else if (codepoint <= 0x10ffff)
7393 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7394 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7395 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7396 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7400 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7407 static std::string token_type_name(token_type t)
7411 case token_type::uninitialized:
7412 return "<uninitialized>";
7413 case token_type::literal_true:
7414 return "true literal";
7415 case token_type::literal_false:
7416 return "false literal";
7417 case token_type::literal_null:
7418 return "null literal";
7419 case token_type::value_string:
7420 return "string literal";
7421 case token_type::value_number:
7422 return "number literal";
7423 case token_type::begin_array:
7425 case token_type::begin_object:
7427 case token_type::end_array:
7429 case token_type::end_object:
7431 case token_type::name_separator:
7433 case token_type::value_separator:
7435 case token_type::parse_error:
7436 return "<parse error>";
7437 case token_type::end_of_input:
7438 return "end of input";
7442 return "unknown token";
7457 token_type scan() noexcept
7464 assert(m_start !=
nullptr);
7469 unsigned int yyaccept = 0;
7470 static const unsigned char yybm[] =
7472 0, 0, 0, 0, 0, 0, 0, 0,
7473 0, 32, 32, 0, 0, 32, 0, 0,
7474 128, 128, 128, 128, 128, 128, 128, 128,
7475 128, 128, 128, 128, 128, 128, 128, 128,
7476 160, 128, 0, 128, 128, 128, 128, 128,
7477 128, 128, 128, 128, 128, 128, 128, 128,
7478 192, 192, 192, 192, 192, 192, 192, 192,
7479 192, 192, 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, 0, 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,
7497 128, 128, 128, 128, 128, 128, 128, 128,
7498 128, 128, 128, 128, 128, 128, 128, 128,
7499 128, 128, 128, 128, 128, 128, 128, 128,
7500 128, 128, 128, 128, 128, 128, 128, 128,
7501 128, 128, 128, 128, 128, 128, 128, 128,
7502 128, 128, 128, 128, 128, 128, 128, 128,
7503 128, 128, 128, 128, 128, 128, 128, 128,
7505 if ((m_limit - m_cursor) < 5)
7510 if (yybm[0 + yych] & 32)
7512 goto basic_json_parser_6;
7522 goto basic_json_parser_2;
7526 goto basic_json_parser_4;
7528 goto basic_json_parser_9;
7534 goto basic_json_parser_4;
7538 goto basic_json_parser_10;
7540 goto basic_json_parser_12;
7549 goto basic_json_parser_4;
7553 goto basic_json_parser_13;
7555 goto basic_json_parser_15;
7561 goto basic_json_parser_17;
7565 goto basic_json_parser_19;
7567 goto basic_json_parser_4;
7579 goto basic_json_parser_21;
7583 goto basic_json_parser_4;
7585 goto basic_json_parser_23;
7591 goto basic_json_parser_24;
7595 goto basic_json_parser_4;
7597 goto basic_json_parser_25;
7606 goto basic_json_parser_26;
7608 goto basic_json_parser_4;
7614 goto basic_json_parser_28;
7618 goto basic_json_parser_30;
7620 goto basic_json_parser_4;
7624 basic_json_parser_2:
7627 return token_type::end_of_input;
7629 basic_json_parser_4:
7631 basic_json_parser_5:
7633 return token_type::parse_error;
7635 basic_json_parser_6:
7637 if (m_limit <= m_cursor)
7642 if (yybm[0 + yych] & 32)
7644 goto basic_json_parser_6;
7649 basic_json_parser_9:
7651 yych = *(m_marker = ++m_cursor);
7654 goto basic_json_parser_5;
7656 goto basic_json_parser_32;
7657 basic_json_parser_10:
7660 return token_type::value_separator;
7662 basic_json_parser_12:
7666 goto basic_json_parser_5;
7670 goto basic_json_parser_13;
7674 goto basic_json_parser_15;
7676 goto basic_json_parser_5;
7677 basic_json_parser_13:
7679 yych = *(m_marker = ++m_cursor);
7684 goto basic_json_parser_37;
7691 goto basic_json_parser_38;
7695 goto basic_json_parser_38;
7698 basic_json_parser_14:
7700 return token_type::value_number;
7702 basic_json_parser_15:
7704 m_marker = ++m_cursor;
7705 if ((m_limit - m_cursor) < 3)
7710 if (yybm[0 + yych] & 64)
7712 goto basic_json_parser_15;
7718 goto basic_json_parser_37;
7720 goto basic_json_parser_14;
7726 goto basic_json_parser_38;
7730 goto basic_json_parser_38;
7732 goto basic_json_parser_14;
7734 basic_json_parser_17:
7737 return token_type::name_separator;
7739 basic_json_parser_19:
7742 return token_type::begin_array;
7744 basic_json_parser_21:
7747 return token_type::end_array;
7749 basic_json_parser_23:
7751 yych = *(m_marker = ++m_cursor);
7754 goto basic_json_parser_39;
7756 goto basic_json_parser_5;
7757 basic_json_parser_24:
7759 yych = *(m_marker = ++m_cursor);
7762 goto basic_json_parser_40;
7764 goto basic_json_parser_5;
7765 basic_json_parser_25:
7767 yych = *(m_marker = ++m_cursor);
7770 goto basic_json_parser_41;
7772 goto basic_json_parser_5;
7773 basic_json_parser_26:
7776 return token_type::begin_object;
7778 basic_json_parser_28:
7781 return token_type::end_object;
7783 basic_json_parser_30:
7785 yych = *(m_marker = ++m_cursor);
7788 goto basic_json_parser_42;
7790 goto basic_json_parser_5;
7791 basic_json_parser_31:
7793 if (m_limit <= m_cursor)
7798 basic_json_parser_32:
7799 if (yybm[0 + yych] & 128)
7801 goto basic_json_parser_31;
7805 goto basic_json_parser_33;
7809 goto basic_json_parser_34;
7811 goto basic_json_parser_36;
7812 basic_json_parser_33:
7813 m_cursor = m_marker;
7816 goto basic_json_parser_5;
7820 goto basic_json_parser_14;
7822 basic_json_parser_34:
7825 return token_type::value_string;
7827 basic_json_parser_36:
7829 if (m_limit <= m_cursor)
7840 goto basic_json_parser_31;
7844 goto basic_json_parser_33;
7846 goto basic_json_parser_31;
7854 goto basic_json_parser_33;
7856 goto basic_json_parser_31;
7862 goto basic_json_parser_31;
7864 goto basic_json_parser_33;
7874 goto basic_json_parser_31;
7878 goto basic_json_parser_31;
7880 goto basic_json_parser_33;
7888 goto basic_json_parser_31;
7890 goto basic_json_parser_33;
7896 goto basic_json_parser_31;
7900 goto basic_json_parser_43;
7902 goto basic_json_parser_33;
7906 basic_json_parser_37:
7910 goto basic_json_parser_33;
7914 goto basic_json_parser_44;
7916 goto basic_json_parser_33;
7917 basic_json_parser_38:
7923 goto basic_json_parser_46;
7925 goto basic_json_parser_33;
7931 goto basic_json_parser_46;
7935 goto basic_json_parser_33;
7939 goto basic_json_parser_47;
7941 goto basic_json_parser_33;
7943 basic_json_parser_39:
7947 goto basic_json_parser_49;
7949 goto basic_json_parser_33;
7950 basic_json_parser_40:
7954 goto basic_json_parser_50;
7956 goto basic_json_parser_33;
7957 basic_json_parser_41:
7961 goto basic_json_parser_51;
7963 goto basic_json_parser_33;
7964 basic_json_parser_42:
7968 goto basic_json_parser_52;
7970 goto basic_json_parser_33;
7971 basic_json_parser_43:
7973 if (m_limit <= m_cursor)
7982 goto basic_json_parser_33;
7986 goto basic_json_parser_54;
7988 goto basic_json_parser_33;
7994 goto basic_json_parser_54;
7998 goto basic_json_parser_33;
8002 goto basic_json_parser_54;
8004 goto basic_json_parser_33;
8006 basic_json_parser_44:
8008 m_marker = ++m_cursor;
8009 if ((m_limit - m_cursor) < 3)
8018 goto basic_json_parser_14;
8022 goto basic_json_parser_44;
8024 goto basic_json_parser_14;
8030 goto basic_json_parser_38;
8034 goto basic_json_parser_38;
8036 goto basic_json_parser_14;
8038 basic_json_parser_46:
8042 goto basic_json_parser_33;
8046 goto basic_json_parser_33;
8048 basic_json_parser_47:
8050 if (m_limit <= m_cursor)
8057 goto basic_json_parser_14;
8061 goto basic_json_parser_47;
8063 goto basic_json_parser_14;
8064 basic_json_parser_49:
8068 goto basic_json_parser_55;
8070 goto basic_json_parser_33;
8071 basic_json_parser_50:
8075 goto basic_json_parser_56;
8077 goto basic_json_parser_33;
8078 basic_json_parser_51:
8082 goto basic_json_parser_58;
8084 goto basic_json_parser_33;
8085 basic_json_parser_52:
8090 basic_json_parser_54:
8092 if (m_limit <= m_cursor)
8101 goto basic_json_parser_33;
8105 goto basic_json_parser_60;
8107 goto basic_json_parser_33;
8113 goto basic_json_parser_60;
8117 goto basic_json_parser_33;
8121 goto basic_json_parser_60;
8123 goto basic_json_parser_33;
8125 basic_json_parser_55:
8129 goto basic_json_parser_61;
8131 goto basic_json_parser_33;
8132 basic_json_parser_56:
8135 return token_type::literal_null;
8137 basic_json_parser_58:
8140 return token_type::literal_true;
8142 basic_json_parser_60:
8144 if (m_limit <= m_cursor)
8153 goto basic_json_parser_33;
8157 goto basic_json_parser_63;
8159 goto basic_json_parser_33;
8165 goto basic_json_parser_63;
8169 goto basic_json_parser_33;
8173 goto basic_json_parser_63;
8175 goto basic_json_parser_33;
8177 basic_json_parser_61:
8180 return token_type::literal_false;
8182 basic_json_parser_63:
8184 if (m_limit <= m_cursor)
8193 goto basic_json_parser_33;
8197 goto basic_json_parser_31;
8199 goto basic_json_parser_33;
8205 goto basic_json_parser_31;
8209 goto basic_json_parser_33;
8213 goto basic_json_parser_31;
8215 goto basic_json_parser_33;
8222 void yyfill() noexcept
8224 if (m_stream ==
nullptr or not * m_stream)
8229 const auto offset_start = m_start - m_content;
8230 const auto offset_marker = m_marker - m_start;
8231 const auto offset_cursor = m_cursor - m_start;
8233 m_buffer.erase(0, static_cast<size_t>(offset_start));
8235 assert(m_stream !=
nullptr);
8236 std::getline(*m_stream, line);
8237 m_buffer +=
"\n" + line;
8239 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
8240 assert(m_content !=
nullptr);
8241 m_start = m_content;
8242 m_marker = m_start + offset_marker;
8243 m_cursor = m_start + offset_cursor;
8244 m_limit = m_start + m_buffer.size() - 1;
8250 assert(m_start !=
nullptr);
8251 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8252 static_cast<size_t>(m_cursor - m_start));
8280 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8283 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8339 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8340 4).c_str(),
nullptr, 16);
8343 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8346 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8348 throw std::invalid_argument(
"missing low surrogate");
8352 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8353 (i + 7), 4).c_str(),
nullptr, 16);
8354 result += to_unicode(codepoint, codepoint2);
8361 result += to_unicode(codepoint);
8373 result.append(1, static_cast<typename string_t::value_type>(*i));
8400 long double str_to_float_t(
long double* ,
char** endptr)
const 8402 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8420 double str_to_float_t(
double* ,
char** endptr)
const 8422 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8440 float str_to_float_t(
float* ,
char** endptr)
const 8442 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8472 void get_number(basic_json& result)
const 8474 assert(m_start !=
nullptr);
8476 const lexer::lexer_char_t* curptr = m_start;
8479 result.m_type.bits.parsed =
true;
8484 uint8_t found_radix_point = 0;
8485 uint8_t precision = 0;
8499 type = value_t::number_integer;
8500 max =
static_cast<uint64_t
>(std::numeric_limits<number_integer_t>::max()) + 1;
8505 type = value_t::number_unsigned;
8506 max =
static_cast<uint64_t
>(std::numeric_limits<number_unsigned_t>::max());
8510 for (; curptr < m_cursor; curptr++)
8513 if (*curptr < '0' || *curptr >
'9')
8518 type = value_t::number_float;
8522 found_radix_point = 0xFF;
8527 type = value_t::number_float;
8528 result.m_type.bits.has_exp =
true;
8531 result.m_type.bits.exp_cap = (*curptr ==
'E');
8534 result.m_type.bits.exp_plus = (*(++curptr) ==
'+');
8539 if (type != value_t::number_float)
8542 auto temp = value * 10 + *curptr - 0x30;
8545 if (temp < value || temp > max)
8548 type = value_t::number_float;
8561 result.m_type.bits.precision = precision & found_radix_point;
8564 if (type == value_t::number_unsigned)
8566 result.m_value.number_unsigned = value;
8568 else if (type == value_t::number_integer)
8575 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8579 result.m_type = type;
8584 std::istream* m_stream =
nullptr;
8588 const lexer_char_t* m_content =
nullptr;
8590 const lexer_char_t* m_start =
nullptr;
8592 const lexer_char_t* m_marker =
nullptr;
8594 const lexer_char_t* m_cursor =
nullptr;
8596 const lexer_char_t* m_limit =
nullptr;
8609 : callback(cb), m_lexer(s)
8617 : callback(cb), m_lexer(&_is)
8626 basic_json result = parse_internal(
true);
8628 expect(lexer::token_type::end_of_input);
8637 basic_json parse_internal(
bool keep)
8639 auto result = basic_json(value_t::discarded);
8643 case lexer::token_type::begin_object:
8645 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8648 result.m_type = value_t::object;
8649 result.m_value = json_value(value_t::object);
8656 if (last_token == lexer::token_type::end_object)
8659 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8661 result = basic_json(value_t::discarded);
8667 unexpect(lexer::token_type::value_separator);
8673 if (last_token == lexer::token_type::value_separator)
8679 expect(lexer::token_type::value_string);
8680 const auto key = m_lexer.get_string();
8682 bool keep_tag =
false;
8688 keep_tag = callback(depth, parse_event_t::key, k);
8698 expect(lexer::token_type::name_separator);
8702 auto value = parse_internal(keep);
8703 if (keep and keep_tag and not value.is_discarded())
8705 result[key] = std::move(value);
8708 while (last_token == lexer::token_type::value_separator);
8711 expect(lexer::token_type::end_object);
8713 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8715 result = basic_json(value_t::discarded);
8721 case lexer::token_type::begin_array:
8723 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8726 result.m_type = value_t::array;
8727 result.m_value = json_value(value_t::array);
8734 if (last_token == lexer::token_type::end_array)
8737 if (callback and not callback(--depth, parse_event_t::array_end, result))
8739 result = basic_json(value_t::discarded);
8745 unexpect(lexer::token_type::value_separator);
8751 if (last_token == lexer::token_type::value_separator)
8757 auto value = parse_internal(keep);
8758 if (keep and not value.is_discarded())
8760 result.push_back(std::move(value));
8763 while (last_token == lexer::token_type::value_separator);
8766 expect(lexer::token_type::end_array);
8768 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8770 result = basic_json(value_t::discarded);
8776 case lexer::token_type::literal_null:
8779 result.m_type = value_t::null;
8783 case lexer::token_type::value_string:
8785 const auto s = m_lexer.get_string();
8787 result = basic_json(s);
8791 case lexer::token_type::literal_true:
8794 result.m_type = value_t::boolean;
8795 result.m_value =
true;
8799 case lexer::token_type::literal_false:
8802 result.m_type = value_t::boolean;
8803 result.m_value =
false;
8807 case lexer::token_type::value_number:
8809 m_lexer.get_number(result);
8817 unexpect(last_token);
8821 if (keep and callback and not callback(depth, parse_event_t::value, result))
8823 result = basic_json(value_t::discarded);
8829 typename lexer::token_type get_token() noexcept
8831 last_token = m_lexer.scan();
8835 void expect(
typename lexer::token_type t)
const 8837 if (t != last_token)
8839 std::string error_msg =
"parse error - unexpected ";
8840 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8841 lexer::token_type_name(last_token));
8842 error_msg +=
"; expected " + lexer::token_type_name(t);
8843 throw std::invalid_argument(error_msg);
8847 void unexpect(
typename lexer::token_type t)
const 8849 if (t == last_token)
8851 std::string error_msg =
"parse error - unexpected ";
8852 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8853 lexer::token_type_name(last_token));
8854 throw std::invalid_argument(error_msg);
8864 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8884 friend class basic_json;
8910 : reference_tokens(split(s))
8928 std::string to_string()
const noexcept
8932 for (
const auto& reference_token : reference_tokens)
8934 result +=
"/" + escape(reference_token);
8941 operator std::string()
const 8948 std::string pop_back()
8952 throw std::domain_error(
"JSON pointer has no parent");
8955 auto last = reference_tokens.back();
8956 reference_tokens.pop_back();
8961 bool is_root()
const 8963 return reference_tokens.empty();
8970 throw std::domain_error(
"JSON pointer has no parent");
8974 result.reference_tokens = {reference_tokens[0]};
8987 for (
const auto& reference_token : reference_tokens)
8989 switch (result->m_type)
8993 if (reference_token ==
"0")
8996 result = &result->operator[](0);
9001 result = &result->operator[](reference_token);
9006 case value_t::object:
9009 result = &result->operator[](reference_token);
9013 case value_t::array:
9016 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9029 throw std::domain_error(
"invalid value to unflatten");
9052 for (
const auto& reference_token : reference_tokens)
9054 switch (ptr->m_type)
9056 case value_t::object:
9059 ptr = &ptr->operator[](reference_token);
9063 case value_t::array:
9066 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9068 throw std::domain_error(
"array index must not begin with '0'");
9071 if (reference_token ==
"-")
9074 ptr = &ptr->operator[](ptr->m_value.array->size());
9079 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9086 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9096 for (
const auto& reference_token : reference_tokens)
9098 switch (ptr->m_type)
9100 case value_t::object:
9103 ptr = &ptr->
at(reference_token);
9107 case value_t::array:
9109 if (reference_token ==
"-")
9112 throw std::out_of_range(
"array index '-' (" +
9113 std::to_string(ptr->m_value.array->size()) +
9114 ") is out of range");
9118 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9120 throw std::domain_error(
"array index must not begin with '0'");
9124 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9130 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9148 for (
const auto& reference_token : reference_tokens)
9150 switch (ptr->m_type)
9152 case value_t::object:
9155 ptr = &ptr->operator[](reference_token);
9159 case value_t::array:
9161 if (reference_token ==
"-")
9164 throw std::out_of_range(
"array index '-' (" +
9165 std::to_string(ptr->m_value.array->size()) +
9166 ") is out of range");
9170 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9172 throw std::domain_error(
"array index must not begin with '0'");
9176 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
9182 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9192 for (
const auto& reference_token : reference_tokens)
9194 switch (ptr->m_type)
9196 case value_t::object:
9199 ptr = &ptr->
at(reference_token);
9203 case value_t::array:
9205 if (reference_token ==
"-")
9208 throw std::out_of_range(
"array index '-' (" +
9209 std::to_string(ptr->m_value.array->size()) +
9210 ") is out of range");
9214 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9216 throw std::domain_error(
"array index must not begin with '0'");
9220 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9226 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9235 static std::vector<std::string> split(std::string reference_string)
9237 std::vector<std::string> result;
9240 if (reference_string.empty())
9246 if (reference_string[0] !=
'/')
9248 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9256 size_t slash = reference_string.find_first_of(
"/", 1),
9265 slash = reference_string.find_first_of(
"/", start))
9269 auto reference_token = reference_string.substr(start, slash - start);
9272 for (
size_t pos = reference_token.find_first_of(
"~");
9273 pos != std::string::npos;
9274 pos = reference_token.find_first_of(
"~", pos + 1))
9276 assert(reference_token[pos] ==
'~');
9279 if (pos == reference_token.size() - 1 or
9280 (reference_token[pos + 1] !=
'0' and
9281 reference_token[pos + 1] !=
'1'))
9283 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9288 unescape(reference_token);
9289 result.push_back(reference_token);
9310 static void replace_substring(std::string& s,
9311 const std::string& f,
9312 const std::string& t)
9314 assert(not f.empty());
9317 size_t pos = s.find(f);
9318 pos != std::string::npos;
9319 s.replace(pos, f.size(), t),
9320 pos = s.find(f, pos + t.size())
9325 static std::string escape(std::string s)
9328 replace_substring(s,
"~",
"~0");
9329 replace_substring(s,
"/",
"~1");
9334 static void unescape(std::string& s)
9337 replace_substring(s,
"~1",
"/");
9339 replace_substring(s,
"~0",
"~");
9349 static void flatten(
const std::string& reference_string,
9350 const basic_json& value,
9353 switch (value.m_type)
9355 case value_t::array:
9357 if (value.m_value.array->empty())
9360 result[reference_string] =
nullptr;
9365 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9367 flatten(reference_string +
"/" + std::to_string(i),
9368 value.m_value.array->operator[](i), result);
9374 case value_t::object:
9376 if (value.m_value.object->empty())
9379 result[reference_string] =
nullptr;
9384 for (
const auto& element : *value.m_value.object)
9386 flatten(reference_string +
"/" + escape(element.first),
9387 element.second, result);
9396 result[reference_string] = value;
9407 static basic_json unflatten(
const basic_json& value)
9411 throw std::domain_error(
"only objects can be unflattened");
9417 for (
const auto& element : *value.m_value.object)
9419 if (not element.second.is_primitive())
9421 throw std::domain_error(
"values in object must be primitive");
9429 json_pointer(element.first).get_and_create(result) = element.second;
9437 std::vector<std::string> reference_tokens {};
9482 return ptr.get_unchecked(
this);
9509 return ptr.get_unchecked(
this);
9534 return ptr.get_checked(
this);
9559 return ptr.get_checked(
this);
9584 basic_json flatten()
const 9586 basic_json result(value_t::object);
9587 json_pointer::flatten(
"", *
this, result);
9618 basic_json unflatten()
const 9620 return json_pointer::unflatten(*
this);
9668 basic_json patch(
const basic_json& json_patch)
const 9671 basic_json result = *
this;
9674 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9676 const auto get_op = [](
const std::string op)
9680 return patch_operations::add;
9684 return patch_operations::remove;
9686 if (op ==
"replace")
9688 return patch_operations::replace;
9692 return patch_operations::move;
9696 return patch_operations::copy;
9700 return patch_operations::test;
9703 return patch_operations::invalid;
9707 const auto operation_add = [&result](
json_pointer & ptr, basic_json val)
9718 if (top_pointer != ptr)
9720 basic_json& x = result.
at(top_pointer);
9724 const auto last_path = ptr.pop_back();
9725 basic_json& parent = result[ptr];
9727 switch (parent.m_type)
9730 case value_t::object:
9733 parent[last_path] = val;
9737 case value_t::array:
9739 if (last_path ==
"-")
9746 const auto idx = std::stoi(last_path);
9747 if (static_cast<size_type>(idx) > parent.
size())
9750 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9771 const auto operation_remove = [&result](
json_pointer & ptr)
9774 const auto last_path = ptr.pop_back();
9775 basic_json& parent = result.
at(ptr);
9781 auto it = parent.
find(last_path);
9782 if (it != parent.
end())
9788 throw std::out_of_range(
"key '" + last_path +
"' not found");
9794 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9802 throw std::invalid_argument(
"JSON patch must be an array of objects");
9806 for (
const auto& val : json_patch)
9809 const auto get_value = [&val](
const std::string & op,
9810 const std::string & member,
9811 bool string_type) -> basic_json&
9814 auto it = val.m_value.object->find(member);
9817 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9820 if (it == val.m_value.object->end())
9822 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9826 if (string_type and not it->second.is_string())
9828 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9836 if (not val.is_object())
9838 throw std::invalid_argument(
"JSON patch must be an array of objects");
9842 const std::string op = get_value(
"op",
"op",
true);
9843 const std::string path = get_value(op,
"path",
true);
9848 case patch_operations::add:
9850 operation_add(ptr, get_value(
"add",
"value",
false));
9854 case patch_operations::remove:
9856 operation_remove(ptr);
9860 case patch_operations::replace:
9863 result.
at(ptr) = get_value(
"replace",
"value",
false);
9867 case patch_operations::move:
9869 const std::string from_path = get_value(
"move",
"from",
true);
9873 basic_json v = result.
at(from_ptr);
9879 operation_remove(from_ptr);
9880 operation_add(ptr, v);
9884 case patch_operations::copy:
9886 const std::string from_path = get_value(
"copy",
"from",
true);;
9890 result[ptr] = result.
at(from_ptr);
9894 case patch_operations::test:
9896 bool success =
false;
9901 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9903 catch (std::out_of_range&)
9911 throw std::domain_error(
"unsuccessful: " + val.dump());
9917 case patch_operations::invalid:
9921 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9961 static basic_json diff(
const basic_json& source,
9962 const basic_json& target,
9963 std::string path =
"")
9966 basic_json result(value_t::array);
9969 if (source == target)
9974 if (source.
type() != target.
type())
9986 switch (source.
type())
9988 case value_t::array:
9992 while (i < source.
size() and i < target.
size())
9995 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
9996 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10004 while (i < source.
size())
10006 result.push_back(
object(
10009 {
"path", path +
"/" + std::to_string(i)}
10015 while (i < target.
size())
10020 {
"path", path +
"/" + std::to_string(i)},
10021 {
"value", target[i]}
10029 case value_t::object:
10032 for (
auto it = source.
begin(); it != source.
end(); ++it)
10035 const auto key = json_pointer::escape(it.key());
10037 if (target.
find(it.key()) != target.
end())
10040 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10041 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10046 result.push_back(
object(
10049 {
"path", path +
"/" + key}
10055 for (
auto it = target.
begin(); it != target.
end(); ++it)
10057 if (source.
find(it.key()) == source.
end())
10060 const auto key = json_pointer::escape(it.key());
10064 {
"path", path +
"/" + key},
10065 {
"value", it.value()}
10125 is_nothrow_move_constructible<nlohmann::json>::value and
10126 is_nothrow_move_assignable<nlohmann::json>::value
10144 const auto& h = hash<nlohmann::json::string_t>();
10162 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
10178 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10179 #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.