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>>;
715 template<
typename T,
typename... Args>
716 static T* create(Args&& ... args)
718 AllocatorType<T> alloc;
719 auto deleter = [&](T * object)
721 alloc.deallocate(
object, 1);
723 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
724 alloc.construct(
object.
get(), std::forward<Args>(args)...);
725 return object.release();
757 json_value() =
default;
759 json_value(
boolean_t v) noexcept : boolean(v) {}
771 case value_t::object:
773 object = create<object_t>();
779 array = create<array_t>();
783 case value_t::string:
785 string = create<string_t>(
"");
789 case value_t::boolean:
795 case value_t::number_integer:
801 case value_t::number_unsigned:
807 case value_t::number_float:
823 string = create<string_t>(value);
829 object = create<object_t>(value);
833 json_value(
const array_t& value)
835 array = create<array_t>(value);
918 using parser_callback_t = std::function<bool(int depth, parse_event_t event, basic_json& parsed)>;
968 : m_type(value_type), m_value(value_type)
995 basic_json() =
default;
1043 : m_type(
value_t::object), m_value(val)
1072 template <
class CompatibleObjectType,
typename 1074 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1075 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type
1082 m_value.object = create<object_t>(begin(val), end(val));
1105 : m_type(
value_t::array), m_value(val)
1134 template <
class CompatibleArrayType,
typename 1136 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1137 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1138 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1139 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1140 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1141 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1142 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type
1149 m_value.array = create<array_t>(begin(val), end(val));
1174 : m_type(
value_t::string), m_value(val)
1224 template <
class CompatibleStringType,
typename 1226 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type
1247 : m_type(value_t::boolean), m_value(val)
1273 template<
typename T,
1274 typename std::enable_if<
1275 not (std::is_same<T, int>::value)
1276 and std::is_same<T, number_integer_t>::value
1280 : m_type(value_t::number_integer), m_value(val)
1309 : m_type(value_t::number_integer),
1310 m_value(static_cast<number_integer_t>(val))
1338 template<
typename CompatibleNumberIntegerType,
typename 1340 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1341 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1342 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1343 CompatibleNumberIntegerType>::type
1346 : m_type(value_t::number_integer),
1347 m_value(static_cast<number_integer_t>(val))
1367 template<
typename T,
1368 typename std::enable_if<
1369 not (std::is_same<T, int>::value)
1370 and std::is_same<T, number_unsigned_t>::value
1374 : m_type(value_t::number_unsigned), m_value(val)
1397 template <
typename CompatibleNumberUnsignedType,
typename 1399 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1400 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1401 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1402 CompatibleNumberUnsignedType>::type
1405 : m_type(value_t::number_unsigned),
1406 m_value(static_cast<number_unsigned_t>(val))
1434 : m_type(value_t::number_float), m_value(val)
1437 if (not std::isfinite(val))
1439 m_type = value_t::null;
1440 m_value = json_value();
1475 template<
typename CompatibleNumberFloatType,
typename =
typename 1477 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1478 std::is_floating_point<CompatibleNumberFloatType>::value>::type
1554 bool type_deduction =
true,
1555 value_t manual_type = value_t::array)
1558 bool is_an_object =
true;
1562 for (
const auto& element : init)
1564 if (not element.is_array() or element.size() != 2
1565 or not element[0].is_string())
1569 is_an_object =
false;
1575 if (not type_deduction)
1578 if (manual_type == value_t::array)
1580 is_an_object =
false;
1584 if (manual_type == value_t::object and not is_an_object)
1586 throw std::domain_error(
"cannot create object from initializer list");
1593 m_type = value_t::object;
1594 m_value = value_t::object;
1596 assert(m_value.object !=
nullptr);
1598 for (
auto& element : init)
1600 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1606 m_type = value_t::array;
1607 m_value.array = create<array_t>(init);
1645 static basic_json
array(std::initializer_list<basic_json> init =
1646 std::initializer_list<basic_json>())
1648 return basic_json(init,
false, value_t::array);
1685 static basic_json
object(std::initializer_list<basic_json> init =
1686 std::initializer_list<basic_json>())
1688 return basic_json(init,
false, value_t::object);
1712 m_value.array = create<array_t>(cnt, val);
1749 template <
class InputIT,
typename 1751 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1752 std::is_same<InputIT, typename basic_json_t::const_iterator>::value
1755 basic_json(InputIT first, InputIT last) : m_type(first.m_object->m_type)
1758 if (first.m_object != last.m_object)
1760 throw std::domain_error(
"iterators are not compatible");
1766 case value_t::boolean:
1767 case value_t::number_float:
1768 case value_t::number_integer:
1769 case value_t::number_unsigned:
1770 case value_t::string:
1772 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1774 throw std::out_of_range(
"iterators out of range");
1787 case value_t::number_integer:
1789 assert(first.m_object !=
nullptr);
1790 m_value.number_integer = first.m_object->m_value.number_integer;
1794 case value_t::number_unsigned:
1796 assert(first.m_object !=
nullptr);
1797 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1801 case value_t::number_float:
1803 assert(first.m_object !=
nullptr);
1804 m_value.number_float = first.m_object->m_value.number_float;
1808 case value_t::boolean:
1810 assert(first.m_object !=
nullptr);
1811 m_value.boolean = first.m_object->m_value.boolean;
1815 case value_t::string:
1817 assert(first.m_object !=
nullptr);
1818 m_value = *first.m_object->m_value.string;
1822 case value_t::object:
1824 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1828 case value_t::array:
1830 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1836 assert(first.m_object !=
nullptr);
1837 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1864 *
this = parser(i, cb).parse();
1894 : m_type(other.m_type)
1898 case value_t::object:
1900 assert(other.m_value.object !=
nullptr);
1901 m_value = *other.m_value.object;
1905 case value_t::array:
1907 assert(other.m_value.array !=
nullptr);
1908 m_value = *other.m_value.array;
1912 case value_t::string:
1914 assert(other.m_value.string !=
nullptr);
1915 m_value = *other.m_value.string;
1919 case value_t::boolean:
1921 m_value = other.m_value.boolean;
1925 case value_t::number_integer:
1927 m_value = other.m_value.number_integer;
1931 case value_t::number_unsigned:
1933 m_value = other.m_value.number_unsigned;
1937 case value_t::number_float:
1939 m_value = other.m_value.number_float;
1969 : m_type(
std::move(other.m_type)),
1970 m_value(
std::move(other.m_value))
1973 other.m_type = value_t::null;
2001 std::is_nothrow_move_constructible<value_t>::value and
2002 std::is_nothrow_move_assignable<value_t>::value and
2003 std::is_nothrow_move_constructible<json_value>::value and
2004 std::is_nothrow_move_assignable<json_value>::value
2008 swap(m_type, other.m_type);
2009 swap(m_value, other.m_value);
2032 case value_t::object:
2034 AllocatorType<object_t> alloc;
2035 alloc.destroy(m_value.object);
2036 alloc.deallocate(m_value.object, 1);
2040 case value_t::array:
2042 AllocatorType<array_t> alloc;
2043 alloc.destroy(m_value.array);
2044 alloc.deallocate(m_value.array, 1);
2048 case value_t::string:
2050 AllocatorType<string_t> alloc;
2051 alloc.destroy(m_value.string);
2052 alloc.deallocate(m_value.string, 1);
2099 std::stringstream ss;
2101 ss.imbue(std::locale(std::locale(),
new DecimalSeparator));
2105 dump(ss,
true, static_cast<unsigned int>(indent));
2165 return is_null() or is_string() or is_boolean() or is_number();
2192 return is_array() or is_object();
2214 return m_type == value_t::null;
2236 return m_type == value_t::boolean;
2266 return is_number_integer() or is_number_float();
2295 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2323 return m_type == value_t::number_unsigned;
2351 return m_type == value_t::number_float;
2373 return m_type == value_t::object;
2395 return m_type == value_t::array;
2417 return m_type == value_t::string;
2444 return m_type == value_t::discarded;
2478 template <
class T,
typename 2480 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2481 std::is_convertible<basic_json_t, typename T::mapped_type>::value
2483 T get_impl(T*)
const 2487 assert(m_value.object !=
nullptr);
2488 return T(m_value.object->begin(), m_value.object->end());
2492 throw std::domain_error(
"type must be object, but is " + type_name());
2501 assert(m_value.object !=
nullptr);
2502 return *(m_value.object);
2506 throw std::domain_error(
"type must be object, but is " + type_name());
2511 template <
class T,
typename 2513 std::is_convertible<basic_json_t, typename T::value_type>::value and
2514 not std::is_same<basic_json_t, typename T::value_type>::value and
2515 not std::is_arithmetic<T>::value and
2516 not std::is_convertible<std::string, T>::value and
2517 not has_mapped_type<T>::value
2519 T get_impl(T*)
const 2524 assert(m_value.array !=
nullptr);
2525 std::transform(m_value.array->begin(), m_value.array->end(),
2526 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2528 return i.
get<
typename T::value_type>();
2534 throw std::domain_error(
"type must be array, but is " + type_name());
2539 template <
class T,
typename 2541 std::is_convertible<basic_json_t, T>::value and
2542 not std::is_same<basic_json_t, T>::value
2544 std::vector<T> get_impl(std::vector<T>*)
const 2548 std::vector<T> to_vector;
2549 assert(m_value.array !=
nullptr);
2550 to_vector.reserve(m_value.array->size());
2551 std::transform(m_value.array->begin(), m_value.array->end(),
2552 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2560 throw std::domain_error(
"type must be array, but is " + type_name());
2565 template <
class T,
typename 2567 std::is_same<basic_json, typename T::value_type>::value and
2568 not has_mapped_type<T>::value
2570 T get_impl(T*)
const 2574 assert(m_value.array !=
nullptr);
2575 return T(m_value.array->begin(), m_value.array->end());
2579 throw std::domain_error(
"type must be array, but is " + type_name());
2588 assert(m_value.array !=
nullptr);
2589 return *(m_value.array);
2593 throw std::domain_error(
"type must be array, but is " + type_name());
2598 template <
typename T,
typename 2600 std::is_convertible<string_t, T>::value
2602 T get_impl(T*)
const 2606 assert(m_value.string !=
nullptr);
2607 return *m_value.string;
2611 throw std::domain_error(
"type must be string, but is " + type_name());
2616 template<
typename T,
typename 2618 std::is_arithmetic<T>::value
2620 T get_impl(T*)
const 2624 case value_t::number_integer:
2626 return static_cast<T
>(m_value.number_integer);
2629 case value_t::number_unsigned:
2631 return static_cast<T
>(m_value.number_unsigned);
2634 case value_t::number_float:
2636 return static_cast<T
>(m_value.number_float);
2641 throw std::domain_error(
"type must be number, but is " + type_name());
2651 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2657 return is_object() ? m_value.object :
nullptr;
2663 return is_object() ? m_value.object :
nullptr;
2669 return is_array() ? m_value.array :
nullptr;
2673 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2675 return is_array() ? m_value.array :
nullptr;
2681 return is_string() ? m_value.string :
nullptr;
2687 return is_string() ? m_value.string :
nullptr;
2693 return is_boolean() ? &m_value.boolean :
nullptr;
2699 return is_boolean() ? &m_value.boolean :
nullptr;
2705 return is_number_integer() ? &m_value.number_integer :
nullptr;
2711 return is_number_integer() ? &m_value.number_integer :
nullptr;
2717 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2723 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2729 return is_number_float() ? &m_value.number_float :
nullptr;
2735 return is_number_float() ? &m_value.number_float :
nullptr;
2749 template<
typename ReferenceType,
typename ThisType>
2750 static ReferenceType get_ref_impl(ThisType& obj)
2753 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2754 auto ptr = obj.template get_ptr<PointerType>();
2762 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2805 template<
typename ValueType,
typename 2807 not std::is_pointer<ValueType>::value
2809 ValueType
get()
const 2811 return get_impl(static_cast<ValueType*>(
nullptr));
2840 template<
typename PointerType,
typename 2842 std::is_pointer<PointerType>::value
2844 PointerType
get() noexcept
2847 return get_ptr<PointerType>();
2854 template<
typename PointerType,
typename 2856 std::is_pointer<PointerType>::value
2858 constexpr
const PointerType
get()
const noexcept
2861 return get_ptr<PointerType>();
2889 template<
typename PointerType,
typename 2891 std::is_pointer<PointerType>::value
2896 return get_impl_ptr(static_cast<PointerType>(
nullptr));
2903 template<
typename PointerType,
typename 2905 std::is_pointer<PointerType>::value
2906 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
2908 constexpr
const PointerType
get_ptr() const noexcept
2911 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
2940 template<
typename ReferenceType,
typename 2942 std::is_reference<ReferenceType>::value
2947 return get_ref_impl<ReferenceType>(*this);
2954 template<
typename ReferenceType,
typename 2956 std::is_reference<ReferenceType>::value
2957 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
2962 return get_ref_impl<ReferenceType>(*this);
2993 template <
typename ValueType,
typename 2995 not std::is_pointer<ValueType>::value
2996 and not std::is_same<ValueType, typename string_t::value_type>::value
2997 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 2998 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3001 operator ValueType()
const 3004 return get<ValueType>();
3046 assert(m_value.array !=
nullptr);
3047 return m_value.array->at(idx);
3049 catch (std::out_of_range&)
3052 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3057 throw std::domain_error(
"cannot use at() with " + type_name());
3090 assert(m_value.array !=
nullptr);
3091 return m_value.array->at(idx);
3093 catch (std::out_of_range&)
3096 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3101 throw std::domain_error(
"cannot use at() with " + type_name());
3138 assert(m_value.object !=
nullptr);
3139 return m_value.object->at(key);
3141 catch (std::out_of_range&)
3144 throw std::out_of_range(
"key '" + key +
"' not found");
3149 throw std::domain_error(
"cannot use at() with " + type_name());
3186 assert(m_value.object !=
nullptr);
3187 return m_value.object->at(key);
3189 catch (std::out_of_range&)
3192 throw std::out_of_range(
"key '" + key +
"' not found");
3197 throw std::domain_error(
"cannot use at() with " + type_name());
3231 m_type = value_t::array;
3232 m_value.
array = create<array_t>();
3239 assert(m_value.array !=
nullptr);
3240 for (
size_t i = m_value.array->size(); i <= idx; ++i)
3242 m_value.array->push_back(basic_json());
3245 return m_value.array->operator[](idx);
3249 throw std::domain_error(
"cannot use operator[] with " + type_name());
3277 assert(m_value.array !=
nullptr);
3278 return m_value.array->operator[](idx);
3282 throw std::domain_error(
"cannot use operator[] with " + type_name());
3318 m_type = value_t::object;
3319 m_value.
object = create<object_t>();
3325 assert(m_value.object !=
nullptr);
3326 return m_value.object->operator[](key);
3330 throw std::domain_error(
"cannot use operator[] with " + type_name());
3366 assert(m_value.object !=
nullptr);
3367 assert(m_value.object->find(key) != m_value.object->end());
3368 return m_value.object->find(key)->second;
3372 throw std::domain_error(
"cannot use operator[] with " + type_name());
3403 template<
typename T, std::
size_t n>
3406 return operator[](static_cast<const T>(key));
3438 template<
typename T, std::
size_t n>
3441 return operator[](static_cast<const T>(key));
3471 template<
typename T>
3477 m_type = value_t::object;
3478 m_value = value_t::object;
3484 assert(m_value.object !=
nullptr);
3485 return m_value.object->operator[](key);
3489 throw std::domain_error(
"cannot use operator[] with " + type_name());
3520 template<
typename T>
3526 assert(m_value.object !=
nullptr);
3527 assert(m_value.object->find(key) != m_value.object->end());
3528 return m_value.object->find(key)->second;
3532 throw std::domain_error(
"cannot use operator[] with " + type_name());
3584 template <
class ValueType,
typename 3586 std::is_convertible<basic_json_t, ValueType>::value
3588 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 3594 const auto it = find(key);
3601 return default_value;
3606 throw std::domain_error(
"cannot use value() with " + type_name());
3614 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3616 return value(key,
string_t(default_value));
3747 template <
class InteratorType,
typename 3749 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3750 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3756 if (
this != pos.m_object)
3758 throw std::domain_error(
"iterator does not fit current value");
3761 InteratorType result = end();
3765 case value_t::boolean:
3766 case value_t::number_float:
3767 case value_t::number_integer:
3768 case value_t::number_unsigned:
3769 case value_t::string:
3771 if (not pos.m_it.primitive_iterator.is_begin())
3773 throw std::out_of_range(
"iterator out of range");
3778 delete m_value.string;
3779 m_value.string =
nullptr;
3782 m_type = value_t::null;
3786 case value_t::object:
3788 assert(m_value.object !=
nullptr);
3789 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3793 case value_t::array:
3795 assert(m_value.array !=
nullptr);
3796 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3802 throw std::domain_error(
"cannot use erase() with " + type_name());
3855 template <
class InteratorType,
typename 3857 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
3858 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
3861 InteratorType
erase(InteratorType first, InteratorType last)
3864 if (
this != first.m_object or
this != last.m_object)
3866 throw std::domain_error(
"iterators do not fit current value");
3869 InteratorType result = end();
3873 case value_t::boolean:
3874 case value_t::number_float:
3875 case value_t::number_integer:
3876 case value_t::number_unsigned:
3877 case value_t::string:
3879 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
3881 throw std::out_of_range(
"iterators out of range");
3886 delete m_value.string;
3887 m_value.string =
nullptr;
3890 m_type = value_t::null;
3894 case value_t::object:
3896 assert(m_value.object !=
nullptr);
3897 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
3898 last.m_it.object_iterator);
3902 case value_t::array:
3904 assert(m_value.array !=
nullptr);
3905 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
3906 last.m_it.array_iterator);
3912 throw std::domain_error(
"cannot use erase() with " + type_name());
3953 assert(m_value.object !=
nullptr);
3954 return m_value.object->erase(key);
3958 throw std::domain_error(
"cannot use erase() with " + type_name());
3993 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3996 assert(m_value.array !=
nullptr);
3997 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4001 throw std::domain_error(
"cannot use erase() with " + type_name());
4035 auto result = end();
4039 assert(m_value.object !=
nullptr);
4040 result.m_it.object_iterator = m_value.object->find(key);
4052 auto result = cend();
4056 assert(m_value.object !=
nullptr);
4057 result.m_it.object_iterator = m_value.object->find(key);
4084 assert(not is_object() or m_value.object !=
nullptr);
4085 return is_object() ? m_value.object->count(key) : 0;
4373 template<
typename IteratorType>
class iteration_proxy;
4389 return iteration_proxy<iterator>(cont);
4397 return iteration_proxy<const_iterator>(cont);
4453 case value_t::array:
4455 assert(m_value.array !=
nullptr);
4456 return m_value.array->empty();
4459 case value_t::object:
4461 assert(m_value.object !=
nullptr);
4462 return m_value.object->empty();
4517 case value_t::array:
4519 assert(m_value.array !=
nullptr);
4520 return m_value.array->size();
4523 case value_t::object:
4525 assert(m_value.object !=
nullptr);
4526 return m_value.object->size();
4577 case value_t::array:
4579 assert(m_value.array !=
nullptr);
4580 return m_value.array->max_size();
4583 case value_t::object:
4585 assert(m_value.object !=
nullptr);
4586 return m_value.object->max_size();
4636 case value_t::number_integer:
4638 m_value.number_integer = 0;
4642 case value_t::number_unsigned:
4644 m_value.number_unsigned = 0;
4648 case value_t::number_float:
4650 m_value.number_float = 0.0;
4654 case value_t::boolean:
4656 m_value.boolean =
false;
4660 case value_t::string:
4662 assert(m_value.string !=
nullptr);
4663 m_value.string->clear();
4667 case value_t::array:
4669 assert(m_value.array !=
nullptr);
4670 m_value.array->clear();
4674 case value_t::object:
4676 assert(m_value.object !=
nullptr);
4677 m_value.object->clear();
4711 if (not(is_null() or is_array()))
4713 throw std::domain_error(
"cannot use push_back() with " + type_name());
4719 m_type = value_t::array;
4720 m_value = value_t::array;
4724 assert(m_value.array !=
nullptr);
4725 m_value.array->push_back(std::move(val));
4727 val.m_type = value_t::null;
4736 push_back(std::move(val));
4747 if (not(is_null() or is_array()))
4749 throw std::domain_error(
"cannot use push_back() with " + type_name());
4755 m_type = value_t::array;
4756 m_value = value_t::array;
4760 assert(m_value.array !=
nullptr);
4761 m_value.array->push_back(val);
4797 if (not(is_null() or is_object()))
4799 throw std::domain_error(
"cannot use push_back() with " + type_name());
4805 m_type = value_t::object;
4806 m_value = value_t::object;
4810 assert(m_value.object !=
nullptr);
4811 m_value.object->insert(val);
4851 if (is_object() and init.size() == 2 and init.begin()->is_string())
4853 const string_t key = *init.begin();
4854 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
4858 push_back(basic_json(init));
4900 if (pos.m_object !=
this)
4902 throw std::domain_error(
"iterator does not fit current value");
4907 assert(m_value.array !=
nullptr);
4908 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
4913 throw std::domain_error(
"cannot use insert() with " + type_name());
4923 return insert(pos, val);
4956 if (pos.m_object !=
this)
4958 throw std::domain_error(
"iterator does not fit current value");
4963 assert(m_value.array !=
nullptr);
4964 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
4969 throw std::domain_error(
"cannot use insert() with " + type_name());
5008 throw std::domain_error(
"cannot use insert() with " + type_name());
5012 if (pos.m_object !=
this)
5014 throw std::domain_error(
"iterator does not fit current value");
5018 if (first.m_object != last.m_object)
5020 throw std::domain_error(
"iterators do not fit");
5023 if (first.m_object ==
this or last.m_object ==
this)
5025 throw std::domain_error(
"passed iterators may not belong to container");
5030 assert(m_value.array !=
nullptr);
5031 result.m_it.array_iterator = m_value.array->insert(
5032 pos.m_it.array_iterator,
5033 first.m_it.array_iterator,
5034 last.m_it.array_iterator);
5067 throw std::domain_error(
"cannot use insert() with " + type_name());
5071 if (pos.m_object !=
this)
5073 throw std::domain_error(
"iterator does not fit current value");
5078 assert(m_value.array !=
nullptr);
5079 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5101 std::is_nothrow_move_constructible<value_t>::value and
5102 std::is_nothrow_move_assignable<value_t>::value and
5103 std::is_nothrow_move_constructible<json_value>::value and
5104 std::is_nothrow_move_assignable<json_value>::value
5107 std::swap(m_type, other.m_type);
5108 std::swap(m_value, other.m_value);
5136 assert(m_value.array !=
nullptr);
5137 std::swap(*(m_value.array), other);
5141 throw std::domain_error(
"cannot use swap() with " + type_name());
5170 assert(m_value.object !=
nullptr);
5171 std::swap(*(m_value.object), other);
5175 throw std::domain_error(
"cannot use swap() with " + type_name());
5204 assert(m_value.string !=
nullptr);
5205 std::swap(*(m_value.string), other);
5209 throw std::domain_error(
"cannot use swap() with " + type_name());
5235 static constexpr std::array<uint8_t, 8> order = {{
5248 if (lhs == value_t::discarded or rhs == value_t::discarded)
5253 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5282 const auto lhs_type = lhs.type();
5283 const auto rhs_type = rhs.type();
5285 if (lhs_type == rhs_type)
5289 case value_t::array:
5291 assert(lhs.m_value.array !=
nullptr);
5292 assert(rhs.m_value.array !=
nullptr);
5293 return *lhs.m_value.array == *rhs.m_value.array;
5295 case value_t::object:
5297 assert(lhs.m_value.object !=
nullptr);
5298 assert(rhs.m_value.object !=
nullptr);
5299 return *lhs.m_value.object == *rhs.m_value.object;
5305 case value_t::string:
5307 assert(lhs.m_value.string !=
nullptr);
5308 assert(rhs.m_value.string !=
nullptr);
5309 return *lhs.m_value.string == *rhs.m_value.string;
5311 case value_t::boolean:
5313 return lhs.m_value.boolean == rhs.m_value.boolean;
5315 case value_t::number_integer:
5317 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5319 case value_t::number_unsigned:
5321 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5323 case value_t::number_float:
5325 return lhs.m_value.number_float == rhs.m_value.number_float;
5333 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5335 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5337 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5339 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5341 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5343 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5345 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5347 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5349 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5351 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5353 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5355 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5411 return not (lhs == rhs);
5443 return not v.is_null();
5472 const auto lhs_type = lhs.type();
5473 const auto rhs_type = rhs.type();
5475 if (lhs_type == rhs_type)
5479 case value_t::array:
5481 assert(lhs.m_value.array !=
nullptr);
5482 assert(rhs.m_value.array !=
nullptr);
5483 return *lhs.m_value.array < *rhs.m_value.array;
5485 case value_t::object:
5487 assert(lhs.m_value.object !=
nullptr);
5488 assert(rhs.m_value.object !=
nullptr);
5489 return *lhs.m_value.object < *rhs.m_value.object;
5495 case value_t::string:
5497 assert(lhs.m_value.string !=
nullptr);
5498 assert(rhs.m_value.string !=
nullptr);
5499 return *lhs.m_value.string < *rhs.m_value.string;
5501 case value_t::boolean:
5503 return lhs.m_value.boolean < rhs.m_value.boolean;
5505 case value_t::number_integer:
5507 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5509 case value_t::number_unsigned:
5511 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5513 case value_t::number_float:
5515 return lhs.m_value.number_float < rhs.m_value.number_float;
5523 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5525 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5527 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5529 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
5531 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5533 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5535 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5537 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5539 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5541 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5543 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5545 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5551 return operator<(lhs_type, rhs_type);
5573 return not (rhs < lhs);
5595 return not (lhs <= rhs);
5617 return not (lhs < rhs);
5652 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5655 const bool pretty_print = (o.width() > 0);
5656 const auto indentation = (pretty_print ? o.width() : 0);
5661 auto old_locale = o.imbue(std::locale(std::locale(),
new DecimalSeparator));
5664 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
5667 o.imbue(old_locale);
5675 friend std::ostream&
operator>>(
const basic_json& j, std::ostream& o)
5716 return parser(s, cb).
parse();
5745 return parser(i, cb).
parse();
5753 return parser(i, cb).
parse();
5781 j = parser(i).
parse();
5791 j = parser(i).
parse();
5804 string_t type_name()
const noexcept
5810 case value_t::object:
5812 case value_t::array:
5814 case value_t::string:
5816 case value_t::boolean:
5818 case value_t::discarded:
5833 static std::size_t extra_space(
const string_t& s) noexcept
5835 std::size_t result = 0;
5837 for (
const auto& c : s)
5856 if (c >= 0x00 and c <= 0x1f)
5884 const auto space = extra_space(s);
5891 string_t result(s.size() + space,
'\\');
5892 std::size_t pos = 0;
5894 for (
const auto& c : s)
5901 result[pos + 1] =
'"';
5917 result[pos + 1] =
'b';
5925 result[pos + 1] =
'f';
5933 result[pos + 1] =
'n';
5941 result[pos + 1] =
'r';
5949 result[pos + 1] =
't';
5956 if (c >= 0x00 and c <= 0x1f)
5960 const auto hexify = [](
const int v) ->
char 5963 ? (
'0' +
static_cast<char>(v))
5964 : (
'a' +
static_cast<char>((v - 10) & 0x1f));
5969 {
'u',
'0',
'0', hexify(c >> 4), hexify(c & 0x0f)
6007 void dump(std::ostream& o,
6008 const bool pretty_print,
6009 const unsigned int indent_step,
6010 const unsigned int current_indent = 0)
const 6013 unsigned int new_indent = current_indent;
6017 case value_t::object:
6019 assert(m_value.object !=
nullptr);
6021 if (m_value.object->empty())
6032 new_indent += indent_step;
6036 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6038 if (i != m_value.object->cbegin())
6040 o << (pretty_print ?
",\n" :
",");
6042 o <<
string_t(new_indent,
' ') <<
"\"" 6043 << escape_string(i->first) <<
"\":" 6044 << (pretty_print ?
" " :
"");
6045 i->second.dump(o, pretty_print, indent_step, new_indent);
6051 new_indent -= indent_step;
6055 o <<
string_t(new_indent,
' ') +
"}";
6059 case value_t::array:
6061 assert(m_value.array !=
nullptr);
6063 if (m_value.array->empty())
6074 new_indent += indent_step;
6078 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6080 if (i != m_value.array->cbegin())
6082 o << (pretty_print ?
",\n" :
",");
6085 i->dump(o, pretty_print, indent_step, new_indent);
6091 new_indent -= indent_step;
6095 o <<
string_t(new_indent,
' ') <<
"]";
6099 case value_t::string:
6101 assert(m_value.string !=
nullptr);
6102 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6106 case value_t::boolean:
6108 o << (m_value.boolean ?
"true" :
"false");
6112 case value_t::number_integer:
6114 o << m_value.number_integer;
6118 case value_t::number_unsigned:
6120 o << m_value.number_unsigned;
6124 case value_t::number_float:
6126 if (m_value.number_float == 0)
6129 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6138 o << std::setprecision(std::numeric_limits<double>::digits10)
6139 << m_value.number_float;
6144 case value_t::discarded:
6164 value_t m_type = value_t::null;
6167 json_value m_value = {};
6184 class primitive_iterator_t
6188 void set_begin() noexcept
6194 void set_end() noexcept
6200 constexpr
bool is_begin()
const noexcept
6202 return (m_it == begin_value);
6206 constexpr
bool is_end()
const noexcept
6208 return (m_it == end_value);
6228 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6238 struct internal_iterator
6241 typename object_t::iterator object_iterator;
6243 typename array_t::iterator array_iterator;
6245 primitive_iterator_t primitive_iterator;
6248 internal_iterator() noexcept
6249 : object_iterator(), array_iterator(), primitive_iterator()
6254 template<
typename IteratorType>
6255 class iteration_proxy
6259 class iteration_proxy_internal
6263 IteratorType anchor;
6265 size_t array_index = 0;
6268 explicit iteration_proxy_internal(IteratorType it) noexcept
6273 iteration_proxy_internal& operator*()
6279 iteration_proxy_internal& operator++()
6288 bool operator!= (
const iteration_proxy_internal& o)
const 6290 return anchor != o.anchor;
6296 assert(anchor.m_object !=
nullptr);
6298 switch (anchor.m_object->type())
6301 case value_t::array:
6303 return std::to_string(array_index);
6307 case value_t::object:
6309 return anchor.key();
6321 typename IteratorType::reference value()
const 6323 return anchor.value();
6328 typename IteratorType::reference container;
6332 explicit iteration_proxy(
typename IteratorType::reference cont)
6337 iteration_proxy_internal begin() noexcept
6339 return iteration_proxy_internal(container.begin());
6343 iteration_proxy_internal end() noexcept
6345 return iteration_proxy_internal(container.end());
6363 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6366 friend class basic_json;
6387 assert(m_object !=
nullptr);
6389 switch (m_object->m_type)
6393 m_it.object_iterator =
typename object_t::iterator();
6399 m_it.array_iterator =
typename array_t::iterator();
6405 m_it.primitive_iterator = primitive_iterator_t();
6413 : m_object(other.m_object)
6415 assert(m_object !=
nullptr);
6417 switch (m_object->m_type)
6421 m_it.object_iterator = other.m_it.object_iterator;
6427 m_it.array_iterator = other.m_it.array_iterator;
6433 m_it.primitive_iterator = other.m_it.primitive_iterator;
6441 : m_object(other.m_object), m_it(other.m_it)
6446 std::is_nothrow_move_constructible<pointer>::value and
6447 std::is_nothrow_move_assignable<pointer>::value and
6448 std::is_nothrow_move_constructible<internal_iterator>::value and
6449 std::is_nothrow_move_assignable<internal_iterator>::value
6452 std::swap(m_object, other.m_object);
6453 std::swap(m_it, other.m_it);
6459 void set_begin() noexcept
6461 assert(m_object !=
nullptr);
6463 switch (m_object->m_type)
6467 assert(m_object->m_value.object !=
nullptr);
6468 m_it.object_iterator = m_object->m_value.object->begin();
6474 assert(m_object->m_value.array !=
nullptr);
6475 m_it.array_iterator = m_object->m_value.array->begin();
6482 m_it.primitive_iterator.set_end();
6488 m_it.primitive_iterator.set_begin();
6495 void set_end() noexcept
6497 assert(m_object !=
nullptr);
6499 switch (m_object->m_type)
6503 assert(m_object->m_value.object !=
nullptr);
6504 m_it.object_iterator = m_object->m_value.object->end();
6510 assert(m_object->m_value.array !=
nullptr);
6511 m_it.array_iterator = m_object->m_value.array->end();
6517 m_it.primitive_iterator.set_end();
6527 assert(m_object !=
nullptr);
6529 switch (m_object->m_type)
6533 assert(m_object->m_value.object);
6534 assert(m_it.object_iterator != m_object->m_value.object->end());
6535 return m_it.object_iterator->second;
6540 assert(m_object->m_value.array);
6541 assert(m_it.array_iterator != m_object->m_value.array->end());
6542 return *m_it.array_iterator;
6547 throw std::out_of_range(
"cannot get value");
6552 if (m_it.primitive_iterator.is_begin())
6558 throw std::out_of_range(
"cannot get value");
6567 assert(m_object !=
nullptr);
6569 switch (m_object->m_type)
6573 assert(m_object->m_value.object);
6574 assert(m_it.object_iterator != m_object->m_value.object->end());
6575 return &(m_it.object_iterator->second);
6580 assert(m_object->m_value.array);
6581 assert(m_it.array_iterator != m_object->m_value.array->end());
6582 return &*m_it.array_iterator;
6587 if (m_it.primitive_iterator.is_begin())
6593 throw std::out_of_range(
"cannot get value");
6602 auto result = *
this;
6610 assert(m_object !=
nullptr);
6612 switch (m_object->m_type)
6616 ++m_it.object_iterator;
6622 ++m_it.array_iterator;
6628 ++m_it.primitive_iterator;
6639 auto result = *
this;
6647 assert(m_object !=
nullptr);
6649 switch (m_object->m_type)
6653 --m_it.object_iterator;
6659 --m_it.array_iterator;
6665 --m_it.primitive_iterator;
6677 if (m_object != other.m_object)
6679 throw std::domain_error(
"cannot compare iterators of different containers");
6682 assert(m_object !=
nullptr);
6684 switch (m_object->m_type)
6688 return (m_it.object_iterator == other.m_it.object_iterator);
6693 return (m_it.array_iterator == other.m_it.array_iterator);
6698 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
6706 return not operator==(other);
6713 if (m_object != other.m_object)
6715 throw std::domain_error(
"cannot compare iterators of different containers");
6718 assert(m_object !=
nullptr);
6720 switch (m_object->m_type)
6724 throw std::domain_error(
"cannot compare order of object iterators");
6729 return (m_it.array_iterator < other.m_it.array_iterator);
6734 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6742 return not other.operator < (*this);
6748 return not operator<=(other);
6754 return not operator<(other);
6760 assert(m_object !=
nullptr);
6762 switch (m_object->m_type)
6766 throw std::domain_error(
"cannot use offsets with object iterators");
6771 m_it.array_iterator += i;
6777 m_it.primitive_iterator += i;
6788 return operator+=(-i);
6794 auto result = *
this;
6802 auto result = *
this;
6810 assert(m_object !=
nullptr);
6812 switch (m_object->m_type)
6816 throw std::domain_error(
"cannot use offsets with object iterators");
6821 return m_it.array_iterator - other.m_it.array_iterator;
6826 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6834 assert(m_object !=
nullptr);
6836 switch (m_object->m_type)
6840 throw std::domain_error(
"cannot use operator[] for object iterators");
6845 return *(m_it.array_iterator + n);
6850 throw std::out_of_range(
"cannot get value");
6855 if (m_it.primitive_iterator == -n)
6861 throw std::out_of_range(
"cannot get value");
6868 typename object_t::key_type
key()
const 6870 assert(m_object !=
nullptr);
6872 if (m_object->is_object())
6874 return m_it.object_iterator->first;
6878 throw std::domain_error(
"cannot use key() for non-object iterators");
6892 internal_iterator m_it = internal_iterator();
6929 std::is_nothrow_move_constructible<pointer>::value and
6930 std::is_nothrow_move_assignable<pointer>::value and
6931 std::is_nothrow_move_constructible<internal_iterator>::value and
6932 std::is_nothrow_move_assignable<internal_iterator>::value
6935 base_iterator::operator=(other);
6942 return const_cast<reference>(base_iterator::operator*());
6948 return const_cast<pointer>(base_iterator::operator->());
6955 base_iterator::operator++();
6962 base_iterator::operator++();
6970 base_iterator::operator--();
6977 base_iterator::operator--();
6984 base_iterator::operator+=(i);
6991 base_iterator::operator-=(i);
6998 auto result = *
this;
7006 auto result = *
this;
7014 return base_iterator::operator-(other);
7020 return const_cast<reference>(base_iterator::operator[](n));
7026 return const_cast<reference>(base_iterator::value());
7047 template<
typename Base>
7069 return base_iterator::operator++(1);
7075 base_iterator::operator++();
7082 return base_iterator::operator--(1);
7088 base_iterator::operator--();
7095 base_iterator::operator+=(i);
7102 auto result = *
this;
7110 auto result = *
this;
7118 return this->base() - other.base();
7124 return *(this->operator+(n));
7128 typename object_t::key_type
key()
const 7130 auto it = --this->base();
7137 auto it = --this->base();
7138 return it.operator * ();
7159 enum class token_type
7178 using lexer_char_t =
unsigned char;
7181 explicit lexer(
const string_t& s) noexcept
7182 : m_stream(
nullptr), m_buffer(s)
7184 m_content =
reinterpret_cast<const lexer_char_t*
>(s.c_str());
7185 assert(m_content !=
nullptr);
7186 m_start = m_cursor = m_content;
7187 m_limit = m_content + s.size();
7191 explicit lexer(std::istream* s) noexcept
7192 : m_stream(s), m_buffer()
7194 assert(m_stream !=
nullptr);
7195 getline(*m_stream, m_buffer);
7196 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7197 assert(m_content !=
nullptr);
7198 m_start = m_cursor = m_content;
7199 m_limit = m_content + m_buffer.size();
7206 lexer(
const lexer&) =
delete;
7207 lexer operator=(
const lexer&) =
delete;
7224 static string_t to_unicode(
const std::size_t codepoint1,
7225 const std::size_t codepoint2 = 0)
7228 std::size_t codepoint = codepoint1;
7231 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7234 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7248 throw std::invalid_argument(
"missing or wrong low surrogate");
7254 if (codepoint < 0x80)
7257 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7259 else if (codepoint <= 0x7ff)
7262 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7263 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7265 else if (codepoint <= 0xffff)
7268 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7269 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7270 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7272 else if (codepoint <= 0x10ffff)
7275 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7276 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7277 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7278 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7282 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7289 static std::string token_type_name(token_type t)
7293 case token_type::uninitialized:
7294 return "<uninitialized>";
7295 case token_type::literal_true:
7296 return "true literal";
7297 case token_type::literal_false:
7298 return "false literal";
7299 case token_type::literal_null:
7300 return "null literal";
7301 case token_type::value_string:
7302 return "string literal";
7303 case token_type::value_number:
7304 return "number literal";
7305 case token_type::begin_array:
7307 case token_type::begin_object:
7309 case token_type::end_array:
7311 case token_type::end_object:
7313 case token_type::name_separator:
7315 case token_type::value_separator:
7317 case token_type::parse_error:
7318 return "<parse error>";
7319 case token_type::end_of_input:
7320 return "end of input";
7324 return "unknown token";
7339 token_type scan() noexcept
7346 assert(m_start !=
nullptr);
7351 unsigned int yyaccept = 0;
7352 static const unsigned char yybm[] = {
7353 0, 0, 0, 0, 0, 0, 0, 0,
7354 0, 32, 32, 0, 0, 32, 0, 0,
7355 128, 128, 128, 128, 128, 128, 128, 128,
7356 128, 128, 128, 128, 128, 128, 128, 128,
7357 160, 128, 0, 128, 128, 128, 128, 128,
7358 128, 128, 128, 128, 128, 128, 128, 128,
7359 192, 192, 192, 192, 192, 192, 192, 192,
7360 192, 192, 128, 128, 128, 128, 128, 128,
7361 128, 128, 128, 128, 128, 128, 128, 128,
7362 128, 128, 128, 128, 128, 128, 128, 128,
7363 128, 128, 128, 128, 128, 128, 128, 128,
7364 128, 128, 128, 128, 0, 128, 128, 128,
7365 128, 128, 128, 128, 128, 128, 128, 128,
7366 128, 128, 128, 128, 128, 128, 128, 128,
7367 128, 128, 128, 128, 128, 128, 128, 128,
7368 128, 128, 128, 128, 128, 128, 128, 128,
7369 128, 128, 128, 128, 128, 128, 128, 128,
7370 128, 128, 128, 128, 128, 128, 128, 128,
7371 128, 128, 128, 128, 128, 128, 128, 128,
7372 128, 128, 128, 128, 128, 128, 128, 128,
7373 128, 128, 128, 128, 128, 128, 128, 128,
7374 128, 128, 128, 128, 128, 128, 128, 128,
7375 128, 128, 128, 128, 128, 128, 128, 128,
7376 128, 128, 128, 128, 128, 128, 128, 128,
7377 128, 128, 128, 128, 128, 128, 128, 128,
7378 128, 128, 128, 128, 128, 128, 128, 128,
7379 128, 128, 128, 128, 128, 128, 128, 128,
7380 128, 128, 128, 128, 128, 128, 128, 128,
7381 128, 128, 128, 128, 128, 128, 128, 128,
7382 128, 128, 128, 128, 128, 128, 128, 128,
7383 128, 128, 128, 128, 128, 128, 128, 128,
7384 128, 128, 128, 128, 128, 128, 128, 128,
7386 if ((m_limit - m_cursor) < 5) yyfill();
7388 if (yybm[0+yych] & 32) {
7389 goto basic_json_parser_6;
7394 if (yych <= 0x00)
goto basic_json_parser_2;
7395 if (yych <=
'!')
goto basic_json_parser_4;
7396 goto basic_json_parser_9;
7398 if (yych <=
'+')
goto basic_json_parser_4;
7399 if (yych <=
',')
goto basic_json_parser_10;
7400 goto basic_json_parser_12;
7404 if (yych <=
'/')
goto basic_json_parser_4;
7405 if (yych <=
'0')
goto basic_json_parser_13;
7406 goto basic_json_parser_15;
7408 if (yych <=
':')
goto basic_json_parser_17;
7409 if (yych ==
'[')
goto basic_json_parser_19;
7410 goto basic_json_parser_4;
7416 if (yych <=
']')
goto basic_json_parser_21;
7417 if (yych <=
'e')
goto basic_json_parser_4;
7418 goto basic_json_parser_23;
7420 if (yych ==
'n')
goto basic_json_parser_24;
7421 if (yych <=
's')
goto basic_json_parser_4;
7422 goto basic_json_parser_25;
7426 if (yych ==
'{')
goto basic_json_parser_26;
7427 goto basic_json_parser_4;
7429 if (yych <=
'}')
goto basic_json_parser_28;
7430 if (yych == 0xEF)
goto basic_json_parser_30;
7431 goto basic_json_parser_4;
7435 basic_json_parser_2:
7437 {
return token_type::end_of_input; }
7438 basic_json_parser_4:
7440 basic_json_parser_5:
7441 {
return token_type::parse_error; }
7442 basic_json_parser_6:
7444 if (m_limit <= m_cursor) yyfill();
7446 if (yybm[0+yych] & 32) {
7447 goto basic_json_parser_6;
7450 basic_json_parser_9:
7452 yych = *(m_marker = ++m_cursor);
7453 if (yych <= 0x0F)
goto basic_json_parser_5;
7454 goto basic_json_parser_32;
7455 basic_json_parser_10:
7457 {
return token_type::value_separator; }
7458 basic_json_parser_12:
7460 if (yych <=
'/')
goto basic_json_parser_5;
7461 if (yych <=
'0')
goto basic_json_parser_13;
7462 if (yych <=
'9')
goto basic_json_parser_15;
7463 goto basic_json_parser_5;
7464 basic_json_parser_13:
7466 yych = *(m_marker = ++m_cursor);
7468 if (yych ==
'.')
goto basic_json_parser_37;
7470 if (yych <=
'E')
goto basic_json_parser_38;
7471 if (yych ==
'e')
goto basic_json_parser_38;
7473 basic_json_parser_14:
7474 {
return token_type::value_number; }
7475 basic_json_parser_15:
7477 m_marker = ++m_cursor;
7478 if ((m_limit - m_cursor) < 3) yyfill();
7480 if (yybm[0+yych] & 64) {
7481 goto basic_json_parser_15;
7484 if (yych ==
'.')
goto basic_json_parser_37;
7485 goto basic_json_parser_14;
7487 if (yych <=
'E')
goto basic_json_parser_38;
7488 if (yych ==
'e')
goto basic_json_parser_38;
7489 goto basic_json_parser_14;
7491 basic_json_parser_17:
7493 {
return token_type::name_separator; }
7494 basic_json_parser_19:
7496 {
return token_type::begin_array; }
7497 basic_json_parser_21:
7499 {
return token_type::end_array; }
7500 basic_json_parser_23:
7502 yych = *(m_marker = ++m_cursor);
7503 if (yych ==
'a')
goto basic_json_parser_39;
7504 goto basic_json_parser_5;
7505 basic_json_parser_24:
7507 yych = *(m_marker = ++m_cursor);
7508 if (yych ==
'u')
goto basic_json_parser_40;
7509 goto basic_json_parser_5;
7510 basic_json_parser_25:
7512 yych = *(m_marker = ++m_cursor);
7513 if (yych ==
'r')
goto basic_json_parser_41;
7514 goto basic_json_parser_5;
7515 basic_json_parser_26:
7517 {
return token_type::begin_object; }
7518 basic_json_parser_28:
7520 {
return token_type::end_object; }
7521 basic_json_parser_30:
7523 yych = *(m_marker = ++m_cursor);
7524 if (yych == 0xBB)
goto basic_json_parser_42;
7525 goto basic_json_parser_5;
7526 basic_json_parser_31:
7528 if (m_limit <= m_cursor) yyfill();
7530 basic_json_parser_32:
7531 if (yybm[0+yych] & 128) {
7532 goto basic_json_parser_31;
7534 if (yych <= 0x0F)
goto basic_json_parser_33;
7535 if (yych <=
'"')
goto basic_json_parser_34;
7536 goto basic_json_parser_36;
7537 basic_json_parser_33:
7538 m_cursor = m_marker;
7539 if (yyaccept == 0) {
7540 goto basic_json_parser_5;
7542 goto basic_json_parser_14;
7544 basic_json_parser_34:
7546 {
return token_type::value_string; }
7547 basic_json_parser_36:
7549 if (m_limit <= m_cursor) yyfill();
7553 if (yych ==
'"')
goto basic_json_parser_31;
7554 if (yych <=
'.')
goto basic_json_parser_33;
7555 goto basic_json_parser_31;
7558 if (yych <=
'[')
goto basic_json_parser_33;
7559 goto basic_json_parser_31;
7561 if (yych ==
'b')
goto basic_json_parser_31;
7562 goto basic_json_parser_33;
7567 if (yych <=
'f')
goto basic_json_parser_31;
7568 if (yych ==
'n')
goto basic_json_parser_31;
7569 goto basic_json_parser_33;
7572 if (yych <=
'r')
goto basic_json_parser_31;
7573 goto basic_json_parser_33;
7575 if (yych <=
't')
goto basic_json_parser_31;
7576 if (yych <=
'u')
goto basic_json_parser_43;
7577 goto basic_json_parser_33;
7581 basic_json_parser_37:
7583 if (yych <=
'/')
goto basic_json_parser_33;
7584 if (yych <=
'9')
goto basic_json_parser_44;
7585 goto basic_json_parser_33;
7586 basic_json_parser_38:
7589 if (yych ==
'+')
goto basic_json_parser_46;
7590 goto basic_json_parser_33;
7592 if (yych <=
'-')
goto basic_json_parser_46;
7593 if (yych <=
'/')
goto basic_json_parser_33;
7594 if (yych <=
'9')
goto basic_json_parser_47;
7595 goto basic_json_parser_33;
7597 basic_json_parser_39:
7599 if (yych ==
'l')
goto basic_json_parser_49;
7600 goto basic_json_parser_33;
7601 basic_json_parser_40:
7603 if (yych ==
'l')
goto basic_json_parser_50;
7604 goto basic_json_parser_33;
7605 basic_json_parser_41:
7607 if (yych ==
'u')
goto basic_json_parser_51;
7608 goto basic_json_parser_33;
7609 basic_json_parser_42:
7611 if (yych == 0xBF)
goto basic_json_parser_52;
7612 goto basic_json_parser_33;
7613 basic_json_parser_43:
7615 if (m_limit <= m_cursor) yyfill();
7618 if (yych <=
'/')
goto basic_json_parser_33;
7619 if (yych <=
'9')
goto basic_json_parser_54;
7620 goto basic_json_parser_33;
7622 if (yych <=
'F')
goto basic_json_parser_54;
7623 if (yych <=
'`')
goto basic_json_parser_33;
7624 if (yych <=
'f')
goto basic_json_parser_54;
7625 goto basic_json_parser_33;
7627 basic_json_parser_44:
7629 m_marker = ++m_cursor;
7630 if ((m_limit - m_cursor) < 3) yyfill();
7633 if (yych <=
'/')
goto basic_json_parser_14;
7634 if (yych <=
'9')
goto basic_json_parser_44;
7635 goto basic_json_parser_14;
7637 if (yych <=
'E')
goto basic_json_parser_38;
7638 if (yych ==
'e')
goto basic_json_parser_38;
7639 goto basic_json_parser_14;
7641 basic_json_parser_46:
7643 if (yych <=
'/')
goto basic_json_parser_33;
7644 if (yych >=
':')
goto basic_json_parser_33;
7645 basic_json_parser_47:
7647 if (m_limit <= m_cursor) yyfill();
7649 if (yych <=
'/')
goto basic_json_parser_14;
7650 if (yych <=
'9')
goto basic_json_parser_47;
7651 goto basic_json_parser_14;
7652 basic_json_parser_49:
7654 if (yych ==
's')
goto basic_json_parser_55;
7655 goto basic_json_parser_33;
7656 basic_json_parser_50:
7658 if (yych ==
'l')
goto basic_json_parser_56;
7659 goto basic_json_parser_33;
7660 basic_json_parser_51:
7662 if (yych ==
'e')
goto basic_json_parser_58;
7663 goto basic_json_parser_33;
7664 basic_json_parser_52:
7667 basic_json_parser_54:
7669 if (m_limit <= m_cursor) yyfill();
7672 if (yych <=
'/')
goto basic_json_parser_33;
7673 if (yych <=
'9')
goto basic_json_parser_60;
7674 goto basic_json_parser_33;
7676 if (yych <=
'F')
goto basic_json_parser_60;
7677 if (yych <=
'`')
goto basic_json_parser_33;
7678 if (yych <=
'f')
goto basic_json_parser_60;
7679 goto basic_json_parser_33;
7681 basic_json_parser_55:
7683 if (yych ==
'e')
goto basic_json_parser_61;
7684 goto basic_json_parser_33;
7685 basic_json_parser_56:
7687 {
return token_type::literal_null; }
7688 basic_json_parser_58:
7690 {
return token_type::literal_true; }
7691 basic_json_parser_60:
7693 if (m_limit <= m_cursor) yyfill();
7696 if (yych <=
'/')
goto basic_json_parser_33;
7697 if (yych <=
'9')
goto basic_json_parser_63;
7698 goto basic_json_parser_33;
7700 if (yych <=
'F')
goto basic_json_parser_63;
7701 if (yych <=
'`')
goto basic_json_parser_33;
7702 if (yych <=
'f')
goto basic_json_parser_63;
7703 goto basic_json_parser_33;
7705 basic_json_parser_61:
7707 {
return token_type::literal_false; }
7708 basic_json_parser_63:
7710 if (m_limit <= m_cursor) yyfill();
7713 if (yych <=
'/')
goto basic_json_parser_33;
7714 if (yych <=
'9')
goto basic_json_parser_31;
7715 goto basic_json_parser_33;
7717 if (yych <=
'F')
goto basic_json_parser_31;
7718 if (yych <=
'`')
goto basic_json_parser_33;
7719 if (yych <=
'f')
goto basic_json_parser_31;
7720 goto basic_json_parser_33;
7727 void yyfill() noexcept
7729 if (m_stream ==
nullptr or not * m_stream)
7734 const auto offset_start = m_start - m_content;
7735 const auto offset_marker = m_marker - m_start;
7736 const auto offset_cursor = m_cursor - m_start;
7738 m_buffer.erase(0, static_cast<size_t>(offset_start));
7740 assert(m_stream !=
nullptr);
7741 std::getline(*m_stream, line);
7742 m_buffer +=
"\n" + line;
7744 m_content =
reinterpret_cast<const lexer_char_t*
>(m_buffer.c_str());
7745 assert(m_content !=
nullptr);
7746 m_start = m_content;
7747 m_marker = m_start + offset_marker;
7748 m_cursor = m_start + offset_cursor;
7749 m_limit = m_start + m_buffer.size() - 1;
7755 assert(m_start !=
nullptr);
7756 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
7757 static_cast<size_t>(m_cursor - m_start));
7785 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
7788 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
7844 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
7845 4).c_str(),
nullptr, 16);
7848 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
7851 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
7853 throw std::invalid_argument(
"missing low surrogate");
7857 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
7858 (i + 7), 4).c_str(),
nullptr, 16);
7859 result += to_unicode(codepoint, codepoint2);
7866 result += to_unicode(codepoint);
7878 result.append(1, static_cast<typename string_t::value_type>(*i));
7905 long double str_to_float_t(
long double* ,
char** endptr)
const 7907 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7925 double str_to_float_t(
double* ,
char** endptr)
const 7927 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7945 float str_to_float_t(
float* ,
char** endptr)
const 7947 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
7971 void get_number(basic_json& result)
const 7973 assert(m_start !=
nullptr);
7975 const lexer::lexer_char_t* curptr = m_start;
7989 type = value_t::number_integer;
7990 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
7995 type = value_t::number_unsigned;
7996 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8000 for (; curptr < m_cursor; curptr++)
8003 if (*curptr < '0' || *curptr >
'9')
8008 type = value_t::number_float;
8013 type = value_t::number_float;
8018 if (type != value_t::number_float)
8021 auto temp = value * 10 + *curptr - 0x30;
8024 if (temp < value || temp > max)
8027 type = value_t::number_float;
8038 if (type == value_t::number_unsigned)
8040 result.m_value.number_unsigned = value;
8042 else if (type == value_t::number_integer)
8049 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8053 result.m_type = type;
8058 std::istream* m_stream =
nullptr;
8062 const lexer_char_t* m_content =
nullptr;
8064 const lexer_char_t* m_start =
nullptr;
8066 const lexer_char_t* m_marker =
nullptr;
8068 const lexer_char_t* m_cursor =
nullptr;
8070 const lexer_char_t* m_limit =
nullptr;
8083 : callback(cb), m_lexer(s)
8091 : callback(cb), m_lexer(&_is)
8100 basic_json result = parse_internal(
true);
8102 expect(lexer::token_type::end_of_input);
8111 basic_json parse_internal(
bool keep)
8113 auto result = basic_json(value_t::discarded);
8117 case lexer::token_type::begin_object:
8119 if (keep and (not callback or (keep = callback(depth++, parse_event_t::object_start, result))))
8122 result.m_type = value_t::object;
8123 result.m_value = json_value(value_t::object);
8130 if (last_token == lexer::token_type::end_object)
8133 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8135 result = basic_json(value_t::discarded);
8141 unexpect(lexer::token_type::value_separator);
8147 if (last_token == lexer::token_type::value_separator)
8153 expect(lexer::token_type::value_string);
8154 const auto key = m_lexer.get_string();
8156 bool keep_tag =
false;
8162 keep_tag = callback(depth, parse_event_t::key, k);
8172 expect(lexer::token_type::name_separator);
8176 auto value = parse_internal(keep);
8177 if (keep and keep_tag and not value.is_discarded())
8179 result[key] = std::move(value);
8182 while (last_token == lexer::token_type::value_separator);
8185 expect(lexer::token_type::end_object);
8187 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
8189 result = basic_json(value_t::discarded);
8195 case lexer::token_type::begin_array:
8197 if (keep and (not callback or (keep = callback(depth++, parse_event_t::array_start, result))))
8200 result.m_type = value_t::array;
8201 result.m_value = json_value(value_t::array);
8208 if (last_token == lexer::token_type::end_array)
8211 if (callback and not callback(--depth, parse_event_t::array_end, result))
8213 result = basic_json(value_t::discarded);
8219 unexpect(lexer::token_type::value_separator);
8225 if (last_token == lexer::token_type::value_separator)
8231 auto value = parse_internal(keep);
8232 if (keep and not value.is_discarded())
8234 result.push_back(std::move(value));
8237 while (last_token == lexer::token_type::value_separator);
8240 expect(lexer::token_type::end_array);
8242 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
8244 result = basic_json(value_t::discarded);
8250 case lexer::token_type::literal_null:
8253 result.m_type = value_t::null;
8257 case lexer::token_type::value_string:
8259 const auto s = m_lexer.get_string();
8261 result = basic_json(s);
8265 case lexer::token_type::literal_true:
8268 result.m_type = value_t::boolean;
8269 result.m_value =
true;
8273 case lexer::token_type::literal_false:
8276 result.m_type = value_t::boolean;
8277 result.m_value =
false;
8281 case lexer::token_type::value_number:
8283 m_lexer.get_number(result);
8291 unexpect(last_token);
8295 if (keep and callback and not callback(depth, parse_event_t::value, result))
8297 result = basic_json(value_t::discarded);
8303 typename lexer::token_type get_token() noexcept
8305 last_token = m_lexer.scan();
8309 void expect(
typename lexer::token_type t)
const 8311 if (t != last_token)
8313 std::string error_msg =
"parse error - unexpected ";
8314 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8315 lexer::token_type_name(last_token));
8316 error_msg +=
"; expected " + lexer::token_type_name(t);
8317 throw std::invalid_argument(error_msg);
8321 void unexpect(
typename lexer::token_type t)
const 8323 if (t == last_token)
8325 std::string error_msg =
"parse error - unexpected ";
8326 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token() +
"'") :
8327 lexer::token_type_name(last_token));
8328 throw std::invalid_argument(error_msg);
8338 typename lexer::token_type last_token = lexer::token_type::uninitialized;
8358 friend class basic_json;
8384 : reference_tokens(split(s))
8402 std::string to_string()
const noexcept
8406 for (
const auto& reference_token : reference_tokens)
8408 result +=
"/" + escape(reference_token);
8415 operator std::string()
const 8422 std::string pop_back()
8426 throw std::domain_error(
"JSON pointer has no parent");
8429 auto last = reference_tokens.back();
8430 reference_tokens.pop_back();
8435 bool is_root()
const 8437 return reference_tokens.empty();
8444 throw std::domain_error(
"JSON pointer has no parent");
8448 result.reference_tokens = {reference_tokens[0]};
8461 for (
const auto& reference_token : reference_tokens)
8463 switch (result->m_type)
8467 if (reference_token ==
"0")
8470 result = &result->operator[](0);
8475 result = &result->operator[](reference_token);
8480 case value_t::object:
8483 result = &result->operator[](reference_token);
8487 case value_t::array:
8490 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8503 throw std::domain_error(
"invalid value to unflatten");
8526 for (
const auto& reference_token : reference_tokens)
8528 switch (ptr->m_type)
8530 case value_t::object:
8533 ptr = &ptr->operator[](reference_token);
8537 case value_t::array:
8540 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8542 throw std::domain_error(
"array index must not begin with '0'");
8545 if (reference_token ==
"-")
8548 ptr = &ptr->operator[](ptr->m_value.array->size());
8553 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8560 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8570 for (
const auto& reference_token : reference_tokens)
8572 switch (ptr->m_type)
8574 case value_t::object:
8577 ptr = &ptr->
at(reference_token);
8581 case value_t::array:
8583 if (reference_token ==
"-")
8586 throw std::out_of_range(
"array index '-' (" +
8587 std::to_string(ptr->m_value.array->size()) +
8588 ") is out of range");
8592 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8594 throw std::domain_error(
"array index must not begin with '0'");
8598 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8604 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8622 for (
const auto& reference_token : reference_tokens)
8624 switch (ptr->m_type)
8626 case value_t::object:
8629 ptr = &ptr->operator[](reference_token);
8633 case value_t::array:
8635 if (reference_token ==
"-")
8638 throw std::out_of_range(
"array index '-' (" +
8639 std::to_string(ptr->m_value.array->size()) +
8640 ") is out of range");
8644 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8646 throw std::domain_error(
"array index must not begin with '0'");
8650 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
8656 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8666 for (
const auto& reference_token : reference_tokens)
8668 switch (ptr->m_type)
8670 case value_t::object:
8673 ptr = &ptr->
at(reference_token);
8677 case value_t::array:
8679 if (reference_token ==
"-")
8682 throw std::out_of_range(
"array index '-' (" +
8683 std::to_string(ptr->m_value.array->size()) +
8684 ") is out of range");
8688 if (reference_token.size() > 1 and reference_token[0] ==
'0')
8690 throw std::domain_error(
"array index must not begin with '0'");
8694 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
8700 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
8709 static std::vector<std::string> split(std::string reference_string)
8711 std::vector<std::string> result;
8714 if (reference_string.empty())
8720 if (reference_string[0] !=
'/')
8722 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
8730 size_t slash = reference_string.find_first_of(
"/", 1),
8739 slash = reference_string.find_first_of(
"/", start))
8743 auto reference_token = reference_string.substr(start, slash - start);
8746 for (
size_t pos = reference_token.find_first_of(
"~");
8747 pos != std::string::npos;
8748 pos = reference_token.find_first_of(
"~", pos + 1))
8750 assert(reference_token[pos] ==
'~');
8753 if (pos == reference_token.size() - 1 or
8754 (reference_token[pos + 1] !=
'0' and
8755 reference_token[pos + 1] !=
'1'))
8757 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
8762 unescape(reference_token);
8763 result.push_back(reference_token);
8784 static void replace_substring(std::string& s,
8785 const std::string& f,
8786 const std::string& t)
8788 assert(not f.empty());
8791 size_t pos = s.find(f);
8792 pos != std::string::npos;
8793 s.replace(pos, f.size(), t),
8794 pos = s.find(f, pos + t.size())
8799 static std::string escape(std::string s)
8802 replace_substring(s,
"~",
"~0");
8803 replace_substring(s,
"/",
"~1");
8808 static void unescape(std::string& s)
8811 replace_substring(s,
"~1",
"/");
8813 replace_substring(s,
"~0",
"~");
8823 static void flatten(
const std::string& reference_string,
8824 const basic_json& value,
8827 switch (value.m_type)
8829 case value_t::array:
8831 if (value.m_value.array->empty())
8834 result[reference_string] =
nullptr;
8839 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
8841 flatten(reference_string +
"/" + std::to_string(i),
8842 value.m_value.array->operator[](i), result);
8848 case value_t::object:
8850 if (value.m_value.object->empty())
8853 result[reference_string] =
nullptr;
8858 for (
const auto& element : *value.m_value.object)
8860 flatten(reference_string +
"/" + escape(element.first),
8861 element.second, result);
8870 result[reference_string] = value;
8881 static basic_json unflatten(
const basic_json& value)
8885 throw std::domain_error(
"only objects can be unflattened");
8891 for (
const auto& element : *value.m_value.object)
8893 if (not element.second.is_primitive())
8895 throw std::domain_error(
"values in object must be primitive");
8903 json_pointer(element.first).get_and_create(result) = element.second;
8911 std::vector<std::string> reference_tokens {};
8956 return ptr.get_unchecked(
this);
8983 return ptr.get_unchecked(
this);
9008 return ptr.get_checked(
this);
9033 return ptr.get_checked(
this);
9058 basic_json flatten()
const 9060 basic_json result(value_t::object);
9061 json_pointer::flatten(
"", *
this, result);
9092 basic_json unflatten()
const 9094 return json_pointer::unflatten(*
this);
9142 basic_json patch(
const basic_json& json_patch)
const 9145 basic_json result = *
this;
9148 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
9150 const auto get_op = [](
const std::string op)
9154 return patch_operations::add;
9158 return patch_operations::remove;
9160 if (op ==
"replace")
9162 return patch_operations::replace;
9166 return patch_operations::move;
9170 return patch_operations::copy;
9174 return patch_operations::test;
9177 return patch_operations::invalid;
9181 const auto operation_add = [&result](
json_pointer & ptr, basic_json val)
9192 if (top_pointer != ptr)
9194 basic_json& x = result.
at(top_pointer);
9198 const auto last_path = ptr.pop_back();
9199 basic_json& parent = result[ptr];
9201 switch (parent.m_type)
9204 case value_t::object:
9207 parent[last_path] = val;
9211 case value_t::array:
9213 if (last_path ==
"-")
9220 const auto idx = std::stoi(last_path);
9221 if (static_cast<size_type>(idx) > parent.
size())
9224 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
9245 const auto operation_remove = [&result](
json_pointer & ptr)
9248 const auto last_path = ptr.pop_back();
9249 basic_json& parent = result.
at(ptr);
9255 auto it = parent.
find(last_path);
9256 if (it != parent.
end())
9262 throw std::out_of_range(
"key '" + last_path +
"' not found");
9268 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
9276 throw std::invalid_argument(
"JSON patch must be an array of objects");
9280 for (
const auto& val : json_patch)
9283 const auto get_value = [&val](
const std::string & op,
9284 const std::string & member,
9285 bool string_type) -> basic_json&
9288 auto it = val.m_value.object->find(member);
9291 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
9294 if (it == val.m_value.object->end())
9296 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
9300 if (string_type and not it->second.is_string())
9302 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
9310 if (not val.is_object())
9312 throw std::invalid_argument(
"JSON patch must be an array of objects");
9316 const std::string op = get_value(
"op",
"op",
true);
9317 const std::string path = get_value(op,
"path",
true);
9322 case patch_operations::add:
9324 operation_add(ptr, get_value(
"add",
"value",
false));
9328 case patch_operations::remove:
9330 operation_remove(ptr);
9334 case patch_operations::replace:
9337 result.
at(ptr) = get_value(
"replace",
"value",
false);
9341 case patch_operations::move:
9343 const std::string from_path = get_value(
"move",
"from",
true);
9347 basic_json v = result.
at(from_ptr);
9353 operation_remove(from_ptr);
9354 operation_add(ptr, v);
9358 case patch_operations::copy:
9360 const std::string from_path = get_value(
"copy",
"from",
true);;
9364 result[ptr] = result.
at(from_ptr);
9368 case patch_operations::test:
9370 bool success =
false;
9375 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
9377 catch (std::out_of_range&)
9385 throw std::domain_error(
"unsuccessful: " + val.dump());
9391 case patch_operations::invalid:
9395 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
9435 static basic_json diff(
const basic_json& source,
9436 const basic_json& target,
9437 std::string path =
"")
9440 basic_json result(value_t::array);
9443 if (source == target)
9448 if (source.
type() != target.
type())
9460 switch (source.
type())
9462 case value_t::array:
9466 while (i < source.
size() and i < target.
size())
9469 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
9470 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9479 while (i < source.
size())
9483 result.insert(result.begin() + end_index, object(
9486 {
"path", path +
"/" + std::to_string(i)}
9492 while (i < target.
size())
9497 {
"path", path +
"/" + std::to_string(i)},
9498 {
"value", target[i]}
9506 case value_t::object:
9509 for (
auto it = source.
begin(); it != source.
end(); ++it)
9512 const auto key = json_pointer::escape(it.key());
9514 if (target.
find(it.key()) != target.
end())
9517 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
9518 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
9523 result.push_back(
object(
9526 {
"path", path +
"/" + key}
9532 for (
auto it = target.
begin(); it != target.
end(); ++it)
9534 if (source.
find(it.key()) == source.
end())
9537 const auto key = json_pointer::escape(it.key());
9541 {
"path", path +
"/" + key},
9542 {
"value", it.value()}
9602 is_nothrow_move_constructible<nlohmann::json>::value and
9603 is_nothrow_move_assignable<nlohmann::json>::value
9621 const auto& h = hash<nlohmann::json::string_t>();
9639 inline nlohmann::json operator "" _json(
const char* s, std::size_t)
9655 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 9656 #pragma GCC diagnostic pop const_iterator(pointer object) noexcept
constructor for a given JSON instance
size_type max_size() const noexcept
returns the maximum possible number of elements
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
constexpr bool is_array() const noexcept
return whether value is an array
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_iterator end() const noexcept
returns a const iterator to one past the last element
constexpr bool is_primitive() const noexcept
return whether type is primitive
constexpr bool is_null() const noexcept
return whether value is null
const_reference operator[](size_type idx) const
access specified array element
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
constexpr bool is_structured() const noexcept
return whether type is structured
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
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
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
copy assignment
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
const_iterator operator-(difference_type i)
subtract from iterator
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value andstd::is_nothrow_move_assignable< value_t >::value andstd::is_nothrow_move_constructible< json_value >::value andstd::is_nothrow_move_assignable< json_value >::value)
exchanges the values
BooleanType boolean_t
a type for a boolean
iterator & operator=(iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
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
constexpr bool is_object() const noexcept
return whether value is an object
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
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++)
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json >>> object_t
a type for an object
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
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
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)
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference back()
access the last element
const value_type & const_reference
the type of an element const reference
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
bool empty() const noexcept
checks whether the container is empty
void push_back(std::initializer_list< basic_json > init)
add an object to an object
json_pointer(const std::string &s="")
create JSON pointer
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
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
basic_json(std::nullptr_t) noexcept
create a null object (explicitly)
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
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
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)
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
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++)
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
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
object (unordered set of name/value pairs)
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
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
size_type size() const noexcept
returns the number of elements
difference_type operator-(const iterator &other) const
return difference
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
constexpr bool is_string() const noexcept
return whether value is a string
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
pointer operator->() const
dereference the iterator
NumberFloatType number_float_t
a type for a number (floating-point)
value_t
the JSON type enumeration
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
std::ptrdiff_t difference_type
a type to represent differences between iterators
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)
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)
constexpr bool is_boolean() const noexcept
return whether value is a boolean
reference operator*() const
return a reference to the value pointed to by the iterator
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
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
const_iterator & operator++()
pre-increment (++it)
pointer operator->() const
dereference the iterator
constexpr bool is_number() const noexcept
return whether value is a number
reference value() const
return the value of an iterator
const_iterator begin() const noexcept
returns a const iterator to the first element
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
const_iterator cend() const noexcept
returns a const iterator to one past the last element
basic_json(const CompatibleObjectType &val)
create an object (implicit)
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
bool operator>=(const const_iterator &other) const
comparison: greater than or equal
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
const_iterator & operator=(const_iterator other) noexcept(std::is_nothrow_move_constructible< pointer >::value andstd::is_nothrow_move_assignable< pointer >::value andstd::is_nothrow_move_constructible< internal_iterator >::value andstd::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
reference operator[](difference_type n) const
access to successor
a const random access iterator for the basic_json class
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
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
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.