29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 42 #include <initializer_list> 54 #include <type_traits> 59 #if defined(__clang__) 60 #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 61 #if CLANG_VERSION < 30400 62 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 64 #elif defined(__GNUC__) 65 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 66 #if GCC_VERSION < 40900 67 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 73 #pragma GCC diagnostic push 74 #pragma GCC diagnostic ignored "-Wfloat-equal" 78 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 79 #define JSON_DEPRECATED __attribute__((deprecated)) 80 #elif defined(_MSC_VER) 81 #define JSON_DEPRECATED __declspec(deprecated) 83 #define JSON_DEPRECATED 112 struct has_mapped_type
115 template<
typename C>
static char test(
typename C::mapped_type*);
116 template<
typename C>
static char (&test(...))[2];
118 static constexpr
bool value =
sizeof(test<T>(0)) == 1;
133 struct DecimalSeparator : std::numpunct<char>
135 char do_decimal_point()
const 222 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
223 template<
typename U,
typename... Args>
class ArrayType = std::vector,
224 class StringType = std::string,
225 class BooleanType = bool,
226 class NumberIntegerType = std::int64_t,
227 class NumberUnsignedType = std::uint64_t,
228 class NumberFloatType = double,
229 template<
typename U>
class AllocatorType = std::allocator
235 using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
236 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
241 template<
typename Base>
class json_reverse_iterator;
254 using value_type = basic_json;
257 using reference = value_type&;
259 using const_reference =
const value_type&;
262 using difference_type = std::ptrdiff_t;
264 using size_type = std::size_t;
267 using allocator_type = AllocatorType<basic_json>;
270 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
272 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
277 class const_iterator;
279 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
281 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
289 static allocator_type get_allocator()
291 return allocator_type();
387 using object_t = ObjectType<StringType,
389 std::less<StringType>,
390 AllocatorType<std::pair<
const StringType,
437 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
484 using string_t = StringType;
510 using boolean_t = BooleanType;
582 using number_integer_t = NumberIntegerType;
653 using number_unsigned_t = NumberUnsignedType;
721 using number_float_t = NumberFloatType;
752 enum class value_t : uint8_t
769 template<
typename T,
typename... Args>
770 static T* create(Args&& ... args)
772 AllocatorType<T> alloc;
773 auto deleter = [&](T * object)
775 alloc.deallocate(
object, 1);
777 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
778 alloc.construct(
object.
get(), std::forward<Args>(args)...);
779 assert(
object.
get() !=
nullptr);
780 return object.release();
822 number_integer_t number_integer;
824 number_unsigned_t number_unsigned;
826 number_float_t number_float;
829 json_value() =
default;
831 json_value(boolean_t v) noexcept : boolean(v) {}
833 json_value(number_integer_t v) noexcept : number_integer(v) {}
835 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
837 json_value(number_float_t v) noexcept : number_float(v) {}
839 json_value(value_t t)
843 case value_t::object:
845 object = create<object_t>();
851 array = create<array_t>();
855 case value_t::string:
857 string = create<string_t>(
"");
861 case value_t::boolean:
863 boolean = boolean_t(
false);
867 case value_t::number_integer:
869 number_integer = number_integer_t(0);
873 case value_t::number_unsigned:
875 number_unsigned = number_unsigned_t(0);
879 case value_t::number_float:
881 number_float = number_float_t(0.0);
893 json_value(
const string_t& value)
895 string = create<string_t>(value);
899 json_value(
const object_t& value)
901 object = create<object_t>(value);
905 json_value(
const array_t& value)
907 array = create<array_t>(value);
920 void assert_invariant()
const 922 assert(m_type != value_t::object or m_value.object !=
nullptr);
923 assert(m_type != value_t::array or m_value.array !=
nullptr);
924 assert(m_type != value_t::string or m_value.string !=
nullptr);
942 enum class parse_event_t : uint8_t
1010 using parser_callback_t = std::function<bool(
int depth,
1011 parse_event_t event,
1012 basic_json& parsed)>;
1063 basic_json(
const value_t value_type)
1064 : m_type(value_type), m_value(value_type)
1087 basic_json(std::nullptr_t =
nullptr) noexcept
1088 : basic_json(value_t::null)
1112 basic_json(
const object_t& val)
1113 : m_type(value_t::object), m_value(val)
1144 template<
class CompatibleObjectType,
typename std::enable_if<
1145 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
1146 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value,
int>::type = 0>
1147 basic_json(
const CompatibleObjectType& val)
1148 : m_type(value_t::object)
1152 m_value.object = create<object_t>(begin(val), end(val));
1175 basic_json(
const array_t& val)
1176 : m_type(value_t::array), m_value(val)
1207 template<
class CompatibleArrayType,
typename std::enable_if<
1208 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
1209 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
1210 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
1211 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
1212 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
1213 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
1214 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value,
int>::type = 0>
1215 basic_json(
const CompatibleArrayType& val)
1216 : m_type(value_t::array)
1220 m_value.array = create<array_t>(begin(val), end(val));
1245 basic_json(
const string_t& val)
1246 : m_type(value_t::string), m_value(val)
1271 basic_json(
const typename string_t::value_type* val)
1272 : basic_json(string_t(val))
1300 template<
class CompatibleStringType,
typename std::enable_if<
1301 std::is_constructible<string_t, CompatibleStringType>::value,
int>::type = 0>
1302 basic_json(
const CompatibleStringType& val)
1303 : basic_json(string_t(val))
1322 basic_json(boolean_t val) noexcept
1323 : m_type(value_t::boolean), m_value(val)
1351 template<
typename T,
typename std::enable_if<
1352 not (std::is_same<T, int>::value) and
1353 std::is_same<T, number_integer_t>::value,
int>::type = 0>
1354 basic_json(
const number_integer_t val) noexcept
1355 : m_type(value_t::number_integer), m_value(val)
1385 basic_json(
const int val) noexcept
1386 : m_type(value_t::number_integer),
1387 m_value(static_cast<number_integer_t>(val))
1417 template<
typename CompatibleNumberIntegerType,
typename std::enable_if<
1418 std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
1419 std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
1420 std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
1421 CompatibleNumberIntegerType>::type = 0>
1422 basic_json(
const CompatibleNumberIntegerType val) noexcept
1423 : m_type(value_t::number_integer),
1424 m_value(static_cast<number_integer_t>(val))
1446 template<
typename T,
typename std::enable_if<
1447 not (std::is_same<T, int>::value) and
1448 std::is_same<T, number_unsigned_t>::value,
int>::type = 0>
1449 basic_json(
const number_unsigned_t val) noexcept
1450 : m_type(value_t::number_unsigned), m_value(val)
1475 template<
typename CompatibleNumberUnsignedType,
typename std::enable_if <
1476 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
1477 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
1478 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
1479 CompatibleNumberUnsignedType>::type = 0>
1480 basic_json(
const CompatibleNumberUnsignedType val) noexcept
1481 : m_type(value_t::number_unsigned),
1482 m_value(static_cast<number_unsigned_t>(val))
1511 basic_json(
const number_float_t val) noexcept
1512 : m_type(value_t::number_float), m_value(val)
1515 if (not std::isfinite(val))
1517 m_type = value_t::null;
1518 m_value = json_value();
1555 template<
typename CompatibleNumberFloatType,
typename =
typename std::enable_if<
1556 std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
1557 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
1558 basic_json(
const CompatibleNumberFloatType val) noexcept
1559 : basic_json(number_float_t(val))
1633 basic_json(std::initializer_list<basic_json> init,
1634 bool type_deduction =
true,
1635 value_t manual_type = value_t::array)
1639 bool is_an_object = std::all_of(init.begin(), init.end(),
1640 [](
const basic_json & element)
1642 return element.is_array() and element.size() == 2 and element[0].is_string();
1646 if (not type_deduction)
1649 if (manual_type == value_t::array)
1651 is_an_object =
false;
1655 if (manual_type == value_t::object and not is_an_object)
1657 throw std::domain_error(
"cannot create object from initializer list");
1664 m_type = value_t::object;
1665 m_value = value_t::object;
1667 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
1669 m_value.object->emplace(*(element[0].m_value.string), element[1]);
1675 m_type = value_t::array;
1676 m_value.array = create<array_t>(init);
1716 static basic_json array(std::initializer_list<basic_json> init =
1717 std::initializer_list<basic_json>())
1719 return basic_json(init,
false, value_t::array);
1756 static basic_json object(std::initializer_list<basic_json> init =
1757 std::initializer_list<basic_json>())
1759 return basic_json(init,
false, value_t::object);
1780 basic_json(size_type cnt,
const basic_json& val)
1781 : m_type(value_t::array)
1783 m_value.array = create<array_t>(cnt, val);
1824 template<
class InputIT,
typename std::enable_if<
1825 std::is_same<InputIT, typename basic_json_t::iterator>::value or
1826 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
1827 basic_json(InputIT first, InputIT last)
1829 assert(first.m_object !=
nullptr);
1830 assert(last.m_object !=
nullptr);
1833 if (first.m_object != last.m_object)
1835 throw std::domain_error(
"iterators are not compatible");
1839 m_type = first.m_object->m_type;
1844 case value_t::boolean:
1845 case value_t::number_float:
1846 case value_t::number_integer:
1847 case value_t::number_unsigned:
1848 case value_t::string:
1850 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
1852 throw std::out_of_range(
"iterators out of range");
1865 case value_t::number_integer:
1867 m_value.number_integer = first.m_object->m_value.number_integer;
1871 case value_t::number_unsigned:
1873 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1877 case value_t::number_float:
1879 m_value.number_float = first.m_object->m_value.number_float;
1883 case value_t::boolean:
1885 m_value.boolean = first.m_object->m_value.boolean;
1889 case value_t::string:
1891 m_value = *first.m_object->m_value.string;
1895 case value_t::object:
1897 m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
1901 case value_t::array:
1903 m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
1909 throw std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name());
1945 explicit basic_json(std::istream& i,
const parser_callback_t cb =
nullptr)
1947 *
this = parser(i, cb).parse();
1977 basic_json(
const basic_json& other)
1978 : m_type(other.m_type)
1981 other.assert_invariant();
1985 case value_t::object:
1987 m_value = *other.m_value.object;
1991 case value_t::array:
1993 m_value = *other.m_value.array;
1997 case value_t::string:
1999 m_value = *other.m_value.string;
2003 case value_t::boolean:
2005 m_value = other.m_value.boolean;
2009 case value_t::number_integer:
2011 m_value = other.m_value.number_integer;
2015 case value_t::number_unsigned:
2017 m_value = other.m_value.number_unsigned;
2021 case value_t::number_float:
2023 m_value = other.m_value.number_float;
2054 basic_json(basic_json&& other) noexcept
2055 : m_type(std::move(other.m_type)),
2056 m_value(std::move(other.m_value))
2059 other.assert_invariant();
2062 other.m_type = value_t::null;
2091 reference& operator=(basic_json other) noexcept (
2092 std::is_nothrow_move_constructible<value_t>::value and
2093 std::is_nothrow_move_assignable<value_t>::value and
2094 std::is_nothrow_move_constructible<json_value>::value and
2095 std::is_nothrow_move_assignable<json_value>::value
2099 other.assert_invariant();
2102 swap(m_type, other.m_type);
2103 swap(m_value, other.m_value);
2130 case value_t::object:
2132 AllocatorType<object_t> alloc;
2133 alloc.destroy(m_value.object);
2134 alloc.deallocate(m_value.object, 1);
2138 case value_t::array:
2140 AllocatorType<array_t> alloc;
2141 alloc.destroy(m_value.array);
2142 alloc.deallocate(m_value.array, 1);
2146 case value_t::string:
2148 AllocatorType<string_t> alloc;
2149 alloc.destroy(m_value.string);
2150 alloc.deallocate(m_value.string, 1);
2196 string_t dump(
const int indent = -1)
const 2198 std::stringstream ss;
2200 const static std::locale loc(std::locale(),
new DecimalSeparator);
2207 ss.precision(std::numeric_limits<double>::digits10);
2211 dump(ss,
true, static_cast<unsigned int>(indent));
2239 constexpr value_t type() const noexcept
2269 constexpr
bool is_primitive() const noexcept
2271 return is_null() or is_string() or is_boolean() or is_number();
2296 constexpr
bool is_structured() const noexcept
2298 return is_array() or is_object();
2318 constexpr
bool is_null() const noexcept
2320 return m_type == value_t::null;
2340 constexpr
bool is_boolean() const noexcept
2342 return m_type == value_t::boolean;
2370 constexpr
bool is_number() const noexcept
2372 return is_number_integer() or is_number_float();
2399 constexpr
bool is_number_integer() const noexcept
2401 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2427 constexpr
bool is_number_unsigned() const noexcept
2429 return m_type == value_t::number_unsigned;
2455 constexpr
bool is_number_float() const noexcept
2457 return m_type == value_t::number_float;
2477 constexpr
bool is_object() const noexcept
2479 return m_type == value_t::object;
2499 constexpr
bool is_array() const noexcept
2501 return m_type == value_t::array;
2521 constexpr
bool is_string() const noexcept
2523 return m_type == value_t::string;
2548 constexpr
bool is_discarded() const noexcept
2550 return m_type == value_t::discarded;
2571 constexpr
operator value_t() const noexcept
2584 template<
class T,
typename std::enable_if<
2585 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
2586 std::is_convertible<basic_json_t, typename T::mapped_type>::value,
int>::type = 0>
2587 T get_impl(T*)
const 2591 return T(m_value.object->begin(), m_value.object->end());
2595 throw std::domain_error(
"type must be object, but is " + type_name());
2600 object_t get_impl(object_t*)
const 2604 return *(m_value.object);
2608 throw std::domain_error(
"type must be object, but is " + type_name());
2613 template<
class T,
typename std::enable_if<
2614 std::is_convertible<basic_json_t, typename T::value_type>::value and
2615 not std::is_same<basic_json_t, typename T::value_type>::value and
2616 not std::is_arithmetic<T>::value and
2617 not std::is_convertible<std::string, T>::value and
2618 not has_mapped_type<T>::value,
int>::type = 0>
2619 T get_impl(T*)
const 2624 std::transform(m_value.array->begin(), m_value.array->end(),
2625 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2627 return i.get<
typename T::value_type>();
2633 throw std::domain_error(
"type must be array, but is " + type_name());
2638 template<
class T,
typename std::enable_if<
2639 std::is_convertible<basic_json_t, T>::value and
2640 not std::is_same<basic_json_t, T>::value,
int>::type = 0>
2641 std::vector<T> get_impl(std::vector<T>*)
const 2645 std::vector<T> to_vector;
2646 to_vector.reserve(m_value.array->size());
2647 std::transform(m_value.array->begin(), m_value.array->end(),
2648 std::inserter(to_vector, to_vector.end()), [](basic_json i)
2656 throw std::domain_error(
"type must be array, but is " + type_name());
2661 template<
class T,
typename std::enable_if<
2662 std::is_same<basic_json, typename T::value_type>::value and
2663 not has_mapped_type<T>::value,
int>::type = 0>
2664 T get_impl(T*)
const 2668 return T(m_value.array->begin(), m_value.array->end());
2672 throw std::domain_error(
"type must be array, but is " + type_name());
2677 array_t get_impl(array_t*)
const 2681 return *(m_value.array);
2685 throw std::domain_error(
"type must be array, but is " + type_name());
2690 template<
typename T,
typename std::enable_if<
2691 std::is_convertible<string_t, T>::value,
int>::type = 0>
2692 T get_impl(T*)
const 2696 return *m_value.string;
2700 throw std::domain_error(
"type must be string, but is " + type_name());
2705 template<
typename T,
typename std::enable_if<
2706 std::is_arithmetic<T>::value,
int>::type = 0>
2707 T get_impl(T*)
const 2711 case value_t::number_integer:
2713 return static_cast<T
>(m_value.number_integer);
2716 case value_t::number_unsigned:
2718 return static_cast<T
>(m_value.number_unsigned);
2721 case value_t::number_float:
2723 return static_cast<T
>(m_value.number_float);
2728 throw std::domain_error(
"type must be number, but is " + type_name());
2734 constexpr boolean_t get_impl(boolean_t*)
const 2738 :
throw std::domain_error(
"type must be boolean, but is " + type_name());
2742 object_t* get_impl_ptr(object_t*) noexcept
2744 return is_object() ? m_value.object :
nullptr;
2748 constexpr
const object_t* get_impl_ptr(
const object_t*)
const noexcept
2750 return is_object() ? m_value.object :
nullptr;
2754 array_t* get_impl_ptr(array_t*) noexcept
2756 return is_array() ? m_value.array :
nullptr;
2760 constexpr
const array_t* get_impl_ptr(
const array_t*)
const noexcept
2762 return is_array() ? m_value.array :
nullptr;
2766 string_t* get_impl_ptr(string_t*) noexcept
2768 return is_string() ? m_value.string :
nullptr;
2772 constexpr
const string_t* get_impl_ptr(
const string_t*)
const noexcept
2774 return is_string() ? m_value.string :
nullptr;
2778 boolean_t* get_impl_ptr(boolean_t*) noexcept
2780 return is_boolean() ? &m_value.boolean :
nullptr;
2784 constexpr
const boolean_t* get_impl_ptr(
const boolean_t*)
const noexcept
2786 return is_boolean() ? &m_value.boolean :
nullptr;
2790 number_integer_t* get_impl_ptr(number_integer_t*) noexcept
2792 return is_number_integer() ? &m_value.number_integer :
nullptr;
2796 constexpr
const number_integer_t* get_impl_ptr(
const number_integer_t*)
const noexcept
2798 return is_number_integer() ? &m_value.number_integer :
nullptr;
2802 number_unsigned_t* get_impl_ptr(number_unsigned_t*) noexcept
2804 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2808 constexpr
const number_unsigned_t* get_impl_ptr(
const number_unsigned_t*)
const noexcept
2810 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
2814 number_float_t* get_impl_ptr(number_float_t*) noexcept
2816 return is_number_float() ? &m_value.number_float :
nullptr;
2820 constexpr
const number_float_t* get_impl_ptr(
const number_float_t*)
const noexcept
2822 return is_number_float() ? &m_value.number_float :
nullptr;
2836 template<
typename ReferenceType,
typename ThisType>
2837 static ReferenceType get_ref_impl(ThisType& obj)
2840 using PointerType =
typename std::add_pointer<ReferenceType>::type;
2843 auto ptr = obj.template get_ptr<PointerType>();
2851 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
2895 template<
typename ValueType,
typename std::enable_if<
2896 not std::is_pointer<ValueType>::value,
int>::type = 0>
2897 ValueType
get()
const 2899 return get_impl(static_cast<ValueType*>(
nullptr));
2929 template<
typename PointerType,
typename std::enable_if<
2930 std::is_pointer<PointerType>::value,
int>::type = 0>
2931 PointerType
get() noexcept
2934 return get_ptr<PointerType>();
2941 template<
typename PointerType,
typename std::enable_if<
2942 std::is_pointer<PointerType>::value,
int>::type = 0>
2943 constexpr
const PointerType
get()
const noexcept
2946 return get_ptr<PointerType>();
2975 template<
typename PointerType,
typename std::enable_if<
2976 std::is_pointer<PointerType>::value,
int>::type = 0>
2977 PointerType get_ptr() noexcept
2980 using pointee_t =
typename std::remove_const<
typename 2981 std::remove_pointer<
typename 2982 std::remove_const<PointerType>::type>::type>::type;
2985 std::is_same<object_t, pointee_t>::value
2986 or std::is_same<array_t, pointee_t>::value
2987 or std::is_same<string_t, pointee_t>::value
2988 or std::is_same<boolean_t, pointee_t>::value
2989 or std::is_same<number_integer_t, pointee_t>::value
2990 or std::is_same<number_unsigned_t, pointee_t>::value
2991 or std::is_same<number_float_t, pointee_t>::value
2992 ,
"incompatible pointer type");
2995 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3002 template<
typename PointerType,
typename std::enable_if<
3003 std::is_pointer<PointerType>::value and
3004 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3005 constexpr
const PointerType get_ptr() const noexcept
3008 using pointee_t =
typename std::remove_const<
typename 3009 std::remove_pointer<
typename 3010 std::remove_const<PointerType>::type>::type>::type;
3013 std::is_same<object_t, pointee_t>::value
3014 or std::is_same<array_t, pointee_t>::value
3015 or std::is_same<string_t, pointee_t>::value
3016 or std::is_same<boolean_t, pointee_t>::value
3017 or std::is_same<number_integer_t, pointee_t>::value
3018 or std::is_same<number_unsigned_t, pointee_t>::value
3019 or std::is_same<number_float_t, pointee_t>::value
3020 ,
"incompatible pointer type");
3023 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3052 template<
typename ReferenceType,
typename std::enable_if<
3053 std::is_reference<ReferenceType>::value,
int>::type = 0>
3054 ReferenceType get_ref()
3057 return get_ref_impl<ReferenceType>(*this);
3064 template<
typename ReferenceType,
typename std::enable_if<
3065 std::is_reference<ReferenceType>::value and
3066 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3067 ReferenceType get_ref()
const 3070 return get_ref_impl<ReferenceType>(*this);
3101 template <
typename ValueType,
typename std::enable_if <
3102 not std::is_pointer<ValueType>::value and
3103 not std::is_same<ValueType, typename string_t::value_type>::value
3104 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 3105 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3108 operator ValueType()
const 3111 return get<ValueType>();
3147 reference at(size_type idx)
3154 return m_value.array->at(idx);
3156 catch (std::out_of_range&)
3159 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3164 throw std::domain_error(
"cannot use at() with " + type_name());
3190 const_reference at(size_type idx)
const 3197 return m_value.array->at(idx);
3199 catch (std::out_of_range&)
3202 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
3207 throw std::domain_error(
"cannot use at() with " + type_name());
3237 reference at(
const typename object_t::key_type& key)
3244 return m_value.object->at(key);
3246 catch (std::out_of_range&)
3249 throw std::out_of_range(
"key '" + key +
"' not found");
3254 throw std::domain_error(
"cannot use at() with " + type_name());
3284 const_reference at(
const typename object_t::key_type& key)
const 3291 return m_value.object->at(key);
3293 catch (std::out_of_range&)
3296 throw std::out_of_range(
"key '" + key +
"' not found");
3301 throw std::domain_error(
"cannot use at() with " + type_name());
3330 reference operator[](size_type idx)
3335 m_type = value_t::array;
3336 m_value.array = create<array_t>();
3344 if (idx >= m_value.array->size())
3346 m_value.array->insert(m_value.array->end(),
3347 idx - m_value.array->size() + 1,
3351 return m_value.array->operator[](idx);
3355 throw std::domain_error(
"cannot use operator[] with " + type_name());
3378 const_reference operator[](size_type idx)
const 3383 return m_value.array->operator[](idx);
3387 throw std::domain_error(
"cannot use operator[] with " + type_name());
3418 reference operator[](
const typename object_t::key_type& key)
3423 m_type = value_t::object;
3424 m_value.object = create<object_t>();
3431 return m_value.object->operator[](key);
3435 throw std::domain_error(
"cannot use operator[] with " + type_name());
3469 const_reference operator[](
const typename object_t::key_type& key)
const 3474 assert(m_value.object->find(key) != m_value.object->end());
3475 return m_value.object->find(key)->second;
3479 throw std::domain_error(
"cannot use operator[] with " + type_name());
3510 template<
typename T, std::
size_t n>
3511 reference operator[](T * (&key)[n])
3513 return operator[](static_cast<const T>(key));
3545 template<
typename T, std::
size_t n>
3546 const_reference operator[](T * (&key)[n])
const 3548 return operator[](static_cast<const T>(key));
3578 template<
typename T>
3579 reference operator[](T* key)
3584 m_type = value_t::object;
3585 m_value = value_t::object;
3592 return m_value.object->operator[](key);
3596 throw std::domain_error(
"cannot use operator[] with " + type_name());
3630 template<
typename T>
3631 const_reference operator[](T* key)
const 3636 assert(m_value.object->find(key) != m_value.object->end());
3637 return m_value.object->find(key)->second;
3641 throw std::domain_error(
"cannot use operator[] with " + type_name());
3693 template<
class ValueType,
typename std::enable_if<
3694 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3695 ValueType value(
const typename object_t::key_type& key, ValueType default_value)
const 3701 const auto it = find(key);
3708 return default_value;
3713 throw std::domain_error(
"cannot use value() with " + type_name());
3721 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 3723 return value(key, string_t(default_value));
3767 template<
class ValueType,
typename std::enable_if<
3768 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
3769 ValueType value(
const json_pointer& ptr, ValueType default_value)
const 3777 return ptr.get_checked(
this);
3779 catch (std::out_of_range&)
3781 return default_value;
3786 throw std::domain_error(
"cannot use value() with " + type_name());
3794 string_t value(
const json_pointer& ptr,
const char* default_value)
const 3796 return value(ptr, string_t(default_value));
3832 const_reference front()
const 3877 const_reference back()
const 3929 template<
class IteratorType,
typename std::enable_if<
3930 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
3931 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
3933 IteratorType erase(IteratorType pos)
3936 if (
this != pos.m_object)
3938 throw std::domain_error(
"iterator does not fit current value");
3941 IteratorType result = end();
3945 case value_t::boolean:
3946 case value_t::number_float:
3947 case value_t::number_integer:
3948 case value_t::number_unsigned:
3949 case value_t::string:
3951 if (not pos.m_it.primitive_iterator.is_begin())
3953 throw std::out_of_range(
"iterator out of range");
3958 AllocatorType<string_t> alloc;
3959 alloc.destroy(m_value.string);
3960 alloc.deallocate(m_value.string, 1);
3961 m_value.string =
nullptr;
3964 m_type = value_t::null;
3969 case value_t::object:
3971 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
3975 case value_t::array:
3977 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
3983 throw std::domain_error(
"cannot use erase() with " + type_name());
4036 template<
class IteratorType,
typename std::enable_if<
4037 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4038 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4040 IteratorType erase(IteratorType first, IteratorType last)
4043 if (
this != first.m_object or
this != last.m_object)
4045 throw std::domain_error(
"iterators do not fit current value");
4048 IteratorType result = end();
4052 case value_t::boolean:
4053 case value_t::number_float:
4054 case value_t::number_integer:
4055 case value_t::number_unsigned:
4056 case value_t::string:
4058 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4060 throw std::out_of_range(
"iterators out of range");
4065 AllocatorType<string_t> alloc;
4066 alloc.destroy(m_value.string);
4067 alloc.deallocate(m_value.string, 1);
4068 m_value.string =
nullptr;
4071 m_type = value_t::null;
4076 case value_t::object:
4078 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4079 last.m_it.object_iterator);
4083 case value_t::array:
4085 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4086 last.m_it.array_iterator);
4092 throw std::domain_error(
"cannot use erase() with " + type_name());
4128 size_type erase(
const typename object_t::key_type& key)
4133 return m_value.object->erase(key);
4137 throw std::domain_error(
"cannot use erase() with " + type_name());
4165 void erase(
const size_type idx)
4172 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
4175 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type
>(idx));
4179 throw std::domain_error(
"cannot use erase() with " + type_name());
4211 iterator find(
typename object_t::key_type key)
4213 auto result = end();
4217 result.m_it.object_iterator = m_value.object->find(key);
4227 const_iterator find(
typename object_t::key_type key)
const 4229 auto result = cend();
4233 result.m_it.object_iterator = m_value.object->find(key);
4257 size_type count(
typename object_t::key_type key)
const 4260 return is_object() ? m_value.object->count(key) : 0;
4297 iterator begin() noexcept
4299 iterator result(
this);
4307 const_iterator begin() const noexcept
4337 const_iterator cbegin() const noexcept
4339 const_iterator result(
this);
4368 iterator end() noexcept
4370 iterator result(
this);
4378 const_iterator end() const noexcept
4408 const_iterator cend() const noexcept
4410 const_iterator result(
this);
4438 reverse_iterator rbegin() noexcept
4440 return reverse_iterator(end());
4446 const_reverse_iterator rbegin() const noexcept
4475 reverse_iterator rend() noexcept
4477 return reverse_iterator(begin());
4483 const_reverse_iterator rend() const noexcept
4512 const_reverse_iterator crbegin() const noexcept
4514 return const_reverse_iterator(cend());
4541 const_reverse_iterator crend() const noexcept
4543 return const_reverse_iterator(cbegin());
4548 template<
typename IteratorType>
class iteration_proxy;
4562 static iteration_proxy<iterator> iterator_wrapper(reference cont)
4564 return iteration_proxy<iterator>(cont);
4570 static iteration_proxy<const_iterator> iterator_wrapper(const_reference cont)
4572 return iteration_proxy<const_iterator>(cont);
4622 bool empty() const noexcept
4632 case value_t::array:
4635 return m_value.array->empty();
4638 case value_t::object:
4641 return m_value.object->empty();
4690 size_type size() const noexcept
4700 case value_t::array:
4703 return m_value.array->size();
4706 case value_t::object:
4709 return m_value.object->size();
4756 size_type max_size() const noexcept
4760 case value_t::array:
4763 return m_value.array->max_size();
4766 case value_t::object:
4769 return m_value.object->max_size();
4815 void clear() noexcept
4819 case value_t::number_integer:
4821 m_value.number_integer = 0;
4825 case value_t::number_unsigned:
4827 m_value.number_unsigned = 0;
4831 case value_t::number_float:
4833 m_value.number_float = 0.0;
4837 case value_t::boolean:
4839 m_value.boolean =
false;
4843 case value_t::string:
4845 m_value.string->clear();
4849 case value_t::array:
4851 m_value.array->clear();
4855 case value_t::object:
4857 m_value.object->clear();
4888 void push_back(basic_json&& val)
4891 if (not(is_null() or is_array()))
4893 throw std::domain_error(
"cannot use push_back() with " + type_name());
4899 m_type = value_t::array;
4900 m_value = value_t::array;
4905 m_value.array->push_back(std::move(val));
4907 val.m_type = value_t::null;
4914 reference operator+=(basic_json&& val)
4916 push_back(std::move(val));
4924 void push_back(
const basic_json& val)
4927 if (not(is_null() or is_array()))
4929 throw std::domain_error(
"cannot use push_back() with " + type_name());
4935 m_type = value_t::array;
4936 m_value = value_t::array;
4941 m_value.array->push_back(val);
4948 reference operator+=(
const basic_json& val)
4974 void push_back(
const typename object_t::value_type& val)
4977 if (not(is_null() or is_object()))
4979 throw std::domain_error(
"cannot use push_back() with " + type_name());
4985 m_type = value_t::object;
4986 m_value = value_t::object;
4991 m_value.object->insert(val);
4998 reference operator+=(
const typename object_t::value_type& val)
5029 void push_back(std::initializer_list<basic_json> init)
5031 if (is_object() and init.size() == 2 and init.begin()->is_string())
5033 const string_t key = *init.begin();
5034 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5038 push_back(basic_json(init));
5046 reference operator+=(std::initializer_list<basic_json> init)
5074 iterator insert(const_iterator pos,
const basic_json& val)
5080 if (pos.m_object !=
this)
5082 throw std::domain_error(
"iterator does not fit current value");
5086 iterator result(
this);
5087 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5092 throw std::domain_error(
"cannot use insert() with " + type_name());
5100 iterator insert(const_iterator pos, basic_json&& val)
5102 return insert(pos, val);
5129 iterator insert(const_iterator pos, size_type cnt,
const basic_json& val)
5135 if (pos.m_object !=
this)
5137 throw std::domain_error(
"iterator does not fit current value");
5141 iterator result(
this);
5142 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5147 throw std::domain_error(
"cannot use insert() with " + type_name());
5181 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
5186 throw std::domain_error(
"cannot use insert() with " + type_name());
5190 if (pos.m_object !=
this)
5192 throw std::domain_error(
"iterator does not fit current value");
5196 if (first.m_object != last.m_object)
5198 throw std::domain_error(
"iterators do not fit");
5201 if (first.m_object ==
this or last.m_object ==
this)
5203 throw std::domain_error(
"passed iterators may not belong to container");
5207 iterator result(
this);
5208 result.m_it.array_iterator = m_value.array->insert(
5209 pos.m_it.array_iterator,
5210 first.m_it.array_iterator,
5211 last.m_it.array_iterator);
5239 iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
5244 throw std::domain_error(
"cannot use insert() with " + type_name());
5248 if (pos.m_object !=
this)
5250 throw std::domain_error(
"iterator does not fit current value");
5254 iterator result(
this);
5255 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5276 void swap(reference other) noexcept (
5277 std::is_nothrow_move_constructible<value_t>::value and
5278 std::is_nothrow_move_assignable<value_t>::value and
5279 std::is_nothrow_move_constructible<json_value>::value and
5280 std::is_nothrow_move_assignable<json_value>::value
5283 std::swap(m_type, other.m_type);
5284 std::swap(m_value, other.m_value);
5308 void swap(array_t& other)
5313 std::swap(*(m_value.array), other);
5317 throw std::domain_error(
"cannot use swap() with " + type_name());
5341 void swap(object_t& other)
5346 std::swap(*(m_value.object), other);
5350 throw std::domain_error(
"cannot use swap() with " + type_name());
5374 void swap(string_t& other)
5379 std::swap(*(m_value.string), other);
5383 throw std::domain_error(
"cannot use swap() with " + type_name());
5407 friend bool operator<(
const value_t lhs,
const value_t rhs) noexcept
5409 static constexpr std::array<uint8_t, 8> order = {{
5422 if (lhs == value_t::discarded or rhs == value_t::discarded)
5427 return order[
static_cast<std::size_t
>(lhs)] < order[static_cast<std::size_t>(rhs)];
5454 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
5456 const auto lhs_type = lhs.type();
5457 const auto rhs_type = rhs.type();
5459 if (lhs_type == rhs_type)
5463 case value_t::array:
5465 return *lhs.m_value.array == *rhs.m_value.array;
5467 case value_t::object:
5469 return *lhs.m_value.object == *rhs.m_value.object;
5475 case value_t::string:
5477 return *lhs.m_value.string == *rhs.m_value.string;
5479 case value_t::boolean:
5481 return lhs.m_value.boolean == rhs.m_value.boolean;
5483 case value_t::number_integer:
5485 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5487 case value_t::number_unsigned:
5489 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5491 case value_t::number_float:
5493 return lhs.m_value.number_float == rhs.m_value.number_float;
5501 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5503 return static_cast<number_float_t
>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5505 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5507 return lhs.m_value.number_float ==
static_cast<number_float_t
>(rhs.m_value.number_integer);
5509 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5511 return static_cast<number_float_t
>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5513 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5515 return lhs.m_value.number_float ==
static_cast<number_float_t
>(rhs.m_value.number_unsigned);
5517 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5519 return static_cast<number_integer_t
>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5521 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5523 return lhs.m_value.number_integer ==
static_cast<number_integer_t
>(rhs.m_value.number_unsigned);
5547 friend bool operator==(const_reference v, std::nullptr_t) noexcept
5556 friend bool operator==(std::nullptr_t, const_reference v) noexcept
5577 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
5579 return not (lhs == rhs);
5600 friend bool operator!=(const_reference v, std::nullptr_t) noexcept
5602 return not v.is_null();
5609 friend bool operator!=(std::nullptr_t, const_reference v) noexcept
5611 return not v.is_null();
5638 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
5640 const auto lhs_type = lhs.type();
5641 const auto rhs_type = rhs.type();
5643 if (lhs_type == rhs_type)
5647 case value_t::array:
5649 return *lhs.m_value.array < *rhs.m_value.array;
5651 case value_t::object:
5653 return *lhs.m_value.object < *rhs.m_value.object;
5659 case value_t::string:
5661 return *lhs.m_value.string < *rhs.m_value.string;
5663 case value_t::boolean:
5665 return lhs.m_value.boolean < rhs.m_value.boolean;
5667 case value_t::number_integer:
5669 return lhs.m_value.number_integer < rhs.m_value.number_integer;
5671 case value_t::number_unsigned:
5673 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
5675 case value_t::number_float:
5677 return lhs.m_value.number_float < rhs.m_value.number_float;
5685 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5687 return static_cast<number_float_t
>(lhs.m_value.number_integer) < rhs.m_value.number_float;
5689 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5691 return lhs.m_value.number_float <
static_cast<number_float_t
>(rhs.m_value.number_integer);
5693 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5695 return static_cast<number_float_t
>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
5697 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5699 return lhs.m_value.number_float <
static_cast<number_float_t
>(rhs.m_value.number_unsigned);
5701 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5703 return lhs.m_value.number_integer <
static_cast<number_integer_t
>(rhs.m_value.number_unsigned);
5705 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5707 return static_cast<number_integer_t
>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
5713 return operator<(lhs_type, rhs_type);
5733 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
5735 return not (rhs < lhs);
5755 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
5757 return not (lhs <= rhs);
5777 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
5779 return not (lhs < rhs);
5818 friend std::ostream&
operator<<(std::ostream& o,
const basic_json& j)
5821 const bool pretty_print = (o.width() > 0);
5822 const auto indentation = (pretty_print ? o.width() : 0);
5828 const auto old_locale = o.imbue(std::locale(std::locale(),
new DecimalSeparator));
5835 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
5838 j.dump(o, pretty_print, static_cast<unsigned int>(indentation));
5841 o.imbue(old_locale);
5842 o.precision(old_precision);
5850 friend std::ostream& operator>>(
const basic_json& j, std::ostream& o)
5892 template<
class T, std::
size_t N>
5893 static basic_json parse(T (&array)[N],
5894 const parser_callback_t cb =
nullptr)
5897 return parse(std::begin(array), std::end(array), cb);
5927 template<
typename CharPT,
typename std::enable_if<
5928 std::is_pointer<CharPT>::value and
5929 std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
5930 sizeof(
typename std::remove_pointer<CharPT>::type) == 1,
int>::type = 0>
5931 static basic_json parse(
const CharPT s,
5932 const parser_callback_t cb =
nullptr)
5934 return parser(reinterpret_cast<const char*>(s), cb).parse();
5961 static basic_json parse(std::istream& i,
5962 const parser_callback_t cb =
nullptr)
5964 return parser(i, cb).parse();
5970 static basic_json parse(std::istream&& i,
5971 const parser_callback_t cb =
nullptr)
5973 return parser(i, cb).parse();
6017 template<
class IteratorType,
typename std::enable_if<
6019 std::random_access_iterator_tag,
6020 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6021 static basic_json parse(IteratorType first, IteratorType last,
6022 const parser_callback_t cb =
nullptr)
6026 assert(std::accumulate(first, last, std::make_pair<bool, int>(
true, 0),
6027 [&first](std::pair<bool, int> res, decltype(*first) val)
6029 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6034 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6035 "each element in the iterator range must have the size of 1 byte");
6039 if (std::distance(first, last) <= 0)
6041 return parser(
"").parse();
6044 return parser(first, last, cb).parse();
6087 template<
class ContiguousContainer,
typename std::enable_if<
6088 not std::is_pointer<ContiguousContainer>::value and
6090 std::random_access_iterator_tag,
6091 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6093 static basic_json parse(
const ContiguousContainer& c,
6094 const parser_callback_t cb =
nullptr)
6097 return parse(std::begin(c), std::end(c), cb);
6123 friend std::istream&
operator<<(basic_json& j, std::istream& i)
6125 j = parser(i).parse();
6133 friend std::istream& operator>>(std::istream& i, basic_json& j)
6135 j = parser(i).parse();
6159 std::string type_name()
const 6165 case value_t::object:
6167 case value_t::array:
6169 case value_t::string:
6171 case value_t::boolean:
6173 case value_t::discarded:
6188 static std::size_t extra_space(
const string_t& s) noexcept
6190 return std::accumulate(s.begin(), s.end(),
size_t{},
6191 [](
size_t res,
typename string_t::value_type c)
6209 if (c >= 0x00 and c <= 0x1f)
6236 static string_t escape_string(
const string_t& s)
6238 const auto space = extra_space(s);
6245 string_t result(s.size() + space,
'\\');
6246 std::size_t pos = 0;
6248 for (
const auto& c : s)
6255 result[pos + 1] =
'"';
6271 result[pos + 1] =
'b';
6279 result[pos + 1] =
'f';
6287 result[pos + 1] =
'n';
6295 result[pos + 1] =
'r';
6303 result[pos + 1] =
't';
6310 if (c >= 0x00 and c <= 0x1f)
6314 static const char hexify[16] =
6316 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
6317 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 6322 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
6360 void dump(std::ostream& o,
6361 const bool pretty_print,
6362 const unsigned int indent_step,
6363 const unsigned int current_indent = 0)
const 6366 unsigned int new_indent = current_indent;
6370 case value_t::object:
6372 if (m_value.object->empty())
6383 new_indent += indent_step;
6387 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
6389 if (i != m_value.object->cbegin())
6391 o << (pretty_print ?
",\n" :
",");
6393 o << string_t(new_indent,
' ') <<
"\"" 6394 << escape_string(i->first) <<
"\":" 6395 << (pretty_print ?
" " :
"");
6396 i->second.dump(o, pretty_print, indent_step, new_indent);
6402 new_indent -= indent_step;
6406 o << string_t(new_indent,
' ') +
"}";
6410 case value_t::array:
6412 if (m_value.array->empty())
6423 new_indent += indent_step;
6427 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
6429 if (i != m_value.array->cbegin())
6431 o << (pretty_print ?
",\n" :
",");
6433 o << string_t(new_indent,
' ');
6434 i->dump(o, pretty_print, indent_step, new_indent);
6440 new_indent -= indent_step;
6444 o << string_t(new_indent,
' ') <<
"]";
6448 case value_t::string:
6450 o << string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
6454 case value_t::boolean:
6456 o << (m_value.boolean ?
"true" :
"false");
6460 case value_t::number_integer:
6462 o << m_value.number_integer;
6466 case value_t::number_unsigned:
6468 o << m_value.number_unsigned;
6472 case value_t::number_float:
6474 if (m_value.number_float == 0)
6477 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
6481 o << m_value.number_float;
6486 case value_t::discarded:
6506 value_t m_type = value_t::null;
6509 json_value m_value = {};
6526 class primitive_iterator_t
6530 void set_begin() noexcept
6536 void set_end() noexcept
6542 constexpr
bool is_begin() const noexcept
6544 return (m_it == begin_value);
6548 constexpr
bool is_end() const noexcept
6550 return (m_it == end_value);
6554 operator difference_type& () noexcept
6560 constexpr
operator difference_type () const noexcept
6566 static constexpr difference_type begin_value = 0;
6567 static constexpr difference_type end_value = begin_value + 1;
6570 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
6580 struct internal_iterator
6583 typename object_t::iterator object_iterator;
6585 typename array_t::iterator array_iterator;
6587 primitive_iterator_t primitive_iterator;
6590 internal_iterator() noexcept
6591 : object_iterator(), array_iterator(), primitive_iterator()
6596 template<
typename IteratorType>
6597 class iteration_proxy
6601 class iteration_proxy_internal
6605 IteratorType anchor;
6607 size_t array_index = 0;
6610 explicit iteration_proxy_internal(IteratorType it) noexcept
6615 iteration_proxy_internal& operator*()
6621 iteration_proxy_internal& operator++()
6630 bool operator!= (
const iteration_proxy_internal& o)
const 6632 return anchor != o.anchor;
6636 typename basic_json::string_t key()
const 6638 assert(anchor.m_object !=
nullptr);
6640 switch (anchor.m_object->type())
6643 case value_t::array:
6645 return std::to_string(array_index);
6649 case value_t::object:
6651 return anchor.key();
6663 typename IteratorType::reference value()
const 6665 return anchor.value();
6670 typename IteratorType::reference container;
6674 explicit iteration_proxy(
typename IteratorType::reference cont)
6679 iteration_proxy_internal begin() noexcept
6681 return iteration_proxy_internal(container.begin());
6685 iteration_proxy_internal end() noexcept
6687 return iteration_proxy_internal(container.end());
6711 class const_iterator :
public std::iterator<std::random_access_iterator_tag, const basic_json>
6714 friend class basic_json;
6718 using value_type =
typename basic_json::value_type;
6720 using difference_type =
typename basic_json::difference_type;
6722 using pointer =
typename basic_json::const_pointer;
6724 using reference =
typename basic_json::const_reference;
6726 using iterator_category = std::bidirectional_iterator_tag;
6729 const_iterator() =
default;
6737 explicit const_iterator(pointer
object) noexcept
6740 assert(m_object !=
nullptr);
6742 switch (m_object->m_type)
6744 case basic_json::value_t::object:
6746 m_it.object_iterator =
typename object_t::iterator();
6750 case basic_json::value_t::array:
6752 m_it.array_iterator =
typename array_t::iterator();
6758 m_it.primitive_iterator = primitive_iterator_t();
6769 explicit const_iterator(
const iterator& other) noexcept
6770 : m_object(other.m_object)
6772 if (m_object !=
nullptr)
6774 switch (m_object->m_type)
6776 case basic_json::value_t::object:
6778 m_it.object_iterator = other.m_it.object_iterator;
6782 case basic_json::value_t::array:
6784 m_it.array_iterator = other.m_it.array_iterator;
6790 m_it.primitive_iterator = other.m_it.primitive_iterator;
6802 const_iterator(
const const_iterator& other) noexcept
6803 : m_object(other.m_object), m_it(other.m_it)
6811 const_iterator& operator=(const_iterator other) noexcept(
6812 std::is_nothrow_move_constructible<pointer>::value and
6813 std::is_nothrow_move_assignable<pointer>::value and
6814 std::is_nothrow_move_constructible<internal_iterator>::value and
6815 std::is_nothrow_move_assignable<internal_iterator>::value
6818 std::swap(m_object, other.m_object);
6819 std::swap(m_it, other.m_it);
6828 void set_begin() noexcept
6830 assert(m_object !=
nullptr);
6832 switch (m_object->m_type)
6834 case basic_json::value_t::object:
6836 m_it.object_iterator = m_object->m_value.object->begin();
6840 case basic_json::value_t::array:
6842 m_it.array_iterator = m_object->m_value.array->begin();
6846 case basic_json::value_t::null:
6849 m_it.primitive_iterator.set_end();
6855 m_it.primitive_iterator.set_begin();
6865 void set_end() noexcept
6867 assert(m_object !=
nullptr);
6869 switch (m_object->m_type)
6871 case basic_json::value_t::object:
6873 m_it.object_iterator = m_object->m_value.object->end();
6877 case basic_json::value_t::array:
6879 m_it.array_iterator = m_object->m_value.array->end();
6885 m_it.primitive_iterator.set_end();
6896 reference operator*()
const 6898 assert(m_object !=
nullptr);
6900 switch (m_object->m_type)
6902 case basic_json::value_t::object:
6904 assert(m_it.object_iterator != m_object->m_value.object->end());
6905 return m_it.object_iterator->second;
6908 case basic_json::value_t::array:
6910 assert(m_it.array_iterator != m_object->m_value.array->end());
6911 return *m_it.array_iterator;
6914 case basic_json::value_t::null:
6916 throw std::out_of_range(
"cannot get value");
6921 if (m_it.primitive_iterator.is_begin())
6927 throw std::out_of_range(
"cannot get value");
6937 pointer operator->()
const 6939 assert(m_object !=
nullptr);
6941 switch (m_object->m_type)
6943 case basic_json::value_t::object:
6945 assert(m_it.object_iterator != m_object->m_value.object->end());
6946 return &(m_it.object_iterator->second);
6949 case basic_json::value_t::array:
6951 assert(m_it.array_iterator != m_object->m_value.array->end());
6952 return &*m_it.array_iterator;
6957 if (m_it.primitive_iterator.is_begin())
6963 throw std::out_of_range(
"cannot get value");
6973 const_iterator operator++(
int)
6975 auto result = *
this;
6984 const_iterator& operator++()
6986 assert(m_object !=
nullptr);
6988 switch (m_object->m_type)
6990 case basic_json::value_t::object:
6992 std::advance(m_it.object_iterator, 1);
6996 case basic_json::value_t::array:
6998 std::advance(m_it.array_iterator, 1);
7004 ++m_it.primitive_iterator;
7016 const_iterator operator--(
int)
7018 auto result = *
this;
7027 const_iterator& operator--()
7029 assert(m_object !=
nullptr);
7031 switch (m_object->m_type)
7033 case basic_json::value_t::object:
7035 std::advance(m_it.object_iterator, -1);
7039 case basic_json::value_t::array:
7041 std::advance(m_it.array_iterator, -1);
7047 --m_it.primitive_iterator;
7059 bool operator==(
const const_iterator& other)
const 7062 if (m_object != other.m_object)
7064 throw std::domain_error(
"cannot compare iterators of different containers");
7067 assert(m_object !=
nullptr);
7069 switch (m_object->m_type)
7071 case basic_json::value_t::object:
7073 return (m_it.object_iterator == other.m_it.object_iterator);
7076 case basic_json::value_t::array:
7078 return (m_it.array_iterator == other.m_it.array_iterator);
7083 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
7092 bool operator!=(
const const_iterator& other)
const 7101 bool operator<(
const const_iterator& other)
const 7104 if (m_object != other.m_object)
7106 throw std::domain_error(
"cannot compare iterators of different containers");
7109 assert(m_object !=
nullptr);
7111 switch (m_object->m_type)
7113 case basic_json::value_t::object:
7115 throw std::domain_error(
"cannot compare order of object iterators");
7118 case basic_json::value_t::array:
7120 return (m_it.array_iterator < other.m_it.array_iterator);
7125 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
7134 bool operator<=(
const const_iterator& other)
const 7136 return not other.operator < (*this);
7143 bool operator>(
const const_iterator& other)
const 7145 return not operator<=(other);
7152 bool operator>=(
const const_iterator& other)
const 7154 return not operator<(other);
7161 const_iterator& operator+=(difference_type i)
7163 assert(m_object !=
nullptr);
7165 switch (m_object->m_type)
7167 case basic_json::value_t::object:
7169 throw std::domain_error(
"cannot use offsets with object iterators");
7172 case basic_json::value_t::array:
7174 std::advance(m_it.array_iterator, i);
7180 m_it.primitive_iterator += i;
7192 const_iterator& operator-=(difference_type i)
7194 return operator+=(-i);
7201 const_iterator operator+(difference_type i)
7203 auto result = *
this;
7212 const_iterator operator-(difference_type i)
7214 auto result = *
this;
7223 difference_type operator-(
const const_iterator& other)
const 7225 assert(m_object !=
nullptr);
7227 switch (m_object->m_type)
7229 case basic_json::value_t::object:
7231 throw std::domain_error(
"cannot use offsets with object iterators");
7234 case basic_json::value_t::array:
7236 return m_it.array_iterator - other.m_it.array_iterator;
7241 return m_it.primitive_iterator - other.m_it.primitive_iterator;
7250 reference operator[](difference_type n)
const 7252 assert(m_object !=
nullptr);
7254 switch (m_object->m_type)
7256 case basic_json::value_t::object:
7258 throw std::domain_error(
"cannot use operator[] for object iterators");
7261 case basic_json::value_t::array:
7263 return *std::next(m_it.array_iterator, n);
7266 case basic_json::value_t::null:
7268 throw std::out_of_range(
"cannot get value");
7273 if (m_it.primitive_iterator == -n)
7279 throw std::out_of_range(
"cannot get value");
7289 typename object_t::key_type key()
const 7291 assert(m_object !=
nullptr);
7293 if (m_object->is_object())
7295 return m_it.object_iterator->first;
7299 throw std::domain_error(
"cannot use key() for non-object iterators");
7307 reference value()
const 7314 pointer m_object =
nullptr;
7316 internal_iterator m_it = internal_iterator();
7331 class iterator :
public const_iterator
7334 using base_iterator = const_iterator;
7335 using pointer =
typename basic_json::pointer;
7336 using reference =
typename basic_json::reference;
7339 iterator() =
default;
7342 explicit iterator(pointer
object) noexcept
7343 : base_iterator(
object)
7347 iterator(
const iterator& other) noexcept
7348 : base_iterator(other)
7352 iterator& operator=(iterator other) noexcept(
7353 std::is_nothrow_move_constructible<pointer>::value and
7354 std::is_nothrow_move_assignable<pointer>::value and
7355 std::is_nothrow_move_constructible<internal_iterator>::value and
7356 std::is_nothrow_move_assignable<internal_iterator>::value
7359 base_iterator::operator=(other);
7364 reference operator*()
const 7366 return const_cast<reference
>(base_iterator::operator*());
7370 pointer operator->()
const 7372 return const_cast<pointer
>(base_iterator::operator->());
7376 iterator operator++(
int)
7378 iterator result = *
this;
7379 base_iterator::operator++();
7384 iterator& operator++()
7386 base_iterator::operator++();
7391 iterator operator--(
int)
7393 iterator result = *
this;
7394 base_iterator::operator--();
7399 iterator& operator--()
7401 base_iterator::operator--();
7406 iterator& operator+=(difference_type i)
7408 base_iterator::operator+=(i);
7413 iterator& operator-=(difference_type i)
7415 base_iterator::operator-=(i);
7420 iterator operator+(difference_type i)
7422 auto result = *
this;
7428 iterator operator-(difference_type i)
7430 auto result = *
this;
7436 difference_type operator-(
const iterator& other)
const 7438 return base_iterator::operator-(other);
7442 reference operator[](difference_type n)
const 7444 return const_cast<reference
>(base_iterator::operator[](n));
7448 reference value()
const 7450 return const_cast<reference
>(base_iterator::value());
7471 template<
typename Base>
7472 class json_reverse_iterator :
public std::reverse_iterator<Base>
7476 using base_iterator = std::reverse_iterator<Base>;
7478 using reference =
typename Base::reference;
7481 json_reverse_iterator(
const typename base_iterator::iterator_type& it) noexcept
7486 json_reverse_iterator(
const base_iterator& it) noexcept
7491 json_reverse_iterator operator++(
int)
7493 return base_iterator::operator++(1);
7497 json_reverse_iterator& operator++()
7499 base_iterator::operator++();
7504 json_reverse_iterator operator--(
int)
7506 return base_iterator::operator--(1);
7510 json_reverse_iterator& operator--()
7512 base_iterator::operator--();
7517 json_reverse_iterator& operator+=(difference_type i)
7519 base_iterator::operator+=(i);
7524 json_reverse_iterator operator+(difference_type i)
const 7526 auto result = *
this;
7532 json_reverse_iterator operator-(difference_type i)
const 7534 auto result = *
this;
7540 difference_type operator-(
const json_reverse_iterator& other)
const 7542 return this->base() - other.base();
7546 reference operator[](difference_type n)
const 7548 return *(this->operator+(n));
7552 typename object_t::key_type key()
const 7554 auto it = --this->base();
7559 reference value()
const 7561 auto it = --this->base();
7562 return it.operator * ();
7583 enum class token_type
7602 using lexer_char_t =
unsigned char;
7605 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
7608 assert(m_content !=
nullptr);
7609 m_start = m_cursor = m_content;
7610 m_limit = m_content + len;
7614 explicit lexer(std::istream& s)
7615 : m_stream(&s), m_line_buffer()
7623 lexer(
const lexer&) =
delete;
7624 lexer operator=(
const lexer&) =
delete;
7649 static string_t to_unicode(
const std::size_t codepoint1,
7650 const std::size_t codepoint2 = 0)
7653 std::size_t codepoint = codepoint1;
7656 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
7659 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
7673 throw std::invalid_argument(
"missing or wrong low surrogate");
7679 if (codepoint < 0x80)
7682 result.append(1, static_cast<typename string_t::value_type>(codepoint));
7684 else if (codepoint <= 0x7ff)
7687 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
7688 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7690 else if (codepoint <= 0xffff)
7693 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
7694 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7695 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7697 else if (codepoint <= 0x10ffff)
7700 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
7701 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
7702 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
7703 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
7707 throw std::out_of_range(
"code points above 0x10FFFF are invalid");
7714 static std::string token_type_name(
const token_type t)
7718 case token_type::uninitialized:
7719 return "<uninitialized>";
7720 case token_type::literal_true:
7721 return "true literal";
7722 case token_type::literal_false:
7723 return "false literal";
7724 case token_type::literal_null:
7725 return "null literal";
7726 case token_type::value_string:
7727 return "string literal";
7728 case token_type::value_number:
7729 return "number literal";
7730 case token_type::begin_array:
7732 case token_type::begin_object:
7734 case token_type::end_array:
7736 case token_type::end_object:
7738 case token_type::name_separator:
7740 case token_type::value_separator:
7742 case token_type::parse_error:
7743 return "<parse error>";
7744 case token_type::end_of_input:
7745 return "end of input";
7749 return "unknown token";
7784 assert(m_start !=
nullptr);
7789 unsigned int yyaccept = 0;
7790 static const unsigned char yybm[] =
7792 0, 0, 0, 0, 0, 0, 0, 0,
7793 0, 32, 32, 0, 0, 32, 0, 0,
7794 0, 0, 0, 0, 0, 0, 0, 0,
7795 0, 0, 0, 0, 0, 0, 0, 0,
7796 160, 128, 0, 128, 128, 128, 128, 128,
7797 128, 128, 128, 128, 128, 128, 128, 128,
7798 192, 192, 192, 192, 192, 192, 192, 192,
7799 192, 192, 128, 128, 128, 128, 128, 128,
7800 128, 128, 128, 128, 128, 128, 128, 128,
7801 128, 128, 128, 128, 128, 128, 128, 128,
7802 128, 128, 128, 128, 128, 128, 128, 128,
7803 128, 128, 128, 128, 0, 128, 128, 128,
7804 128, 128, 128, 128, 128, 128, 128, 128,
7805 128, 128, 128, 128, 128, 128, 128, 128,
7806 128, 128, 128, 128, 128, 128, 128, 128,
7807 128, 128, 128, 128, 128, 128, 128, 128,
7808 128, 128, 128, 128, 128, 128, 128, 128,
7809 128, 128, 128, 128, 128, 128, 128, 128,
7810 128, 128, 128, 128, 128, 128, 128, 128,
7811 128, 128, 128, 128, 128, 128, 128, 128,
7812 128, 128, 128, 128, 128, 128, 128, 128,
7813 128, 128, 128, 128, 128, 128, 128, 128,
7814 128, 128, 128, 128, 128, 128, 128, 128,
7815 128, 128, 128, 128, 128, 128, 128, 128,
7816 128, 128, 128, 128, 128, 128, 128, 128,
7817 128, 128, 128, 128, 128, 128, 128, 128,
7818 128, 128, 128, 128, 128, 128, 128, 128,
7819 128, 128, 128, 128, 128, 128, 128, 128,
7820 128, 128, 128, 128, 128, 128, 128, 128,
7821 128, 128, 128, 128, 128, 128, 128, 128,
7822 128, 128, 128, 128, 128, 128, 128, 128,
7823 128, 128, 128, 128, 128, 128, 128, 128,
7825 if ((m_limit - m_cursor) < 5)
7830 if (yybm[0 + yych] & 32)
7832 goto basic_json_parser_6;
7842 goto basic_json_parser_2;
7846 goto basic_json_parser_4;
7848 goto basic_json_parser_9;
7854 goto basic_json_parser_4;
7858 goto basic_json_parser_10;
7860 goto basic_json_parser_12;
7869 goto basic_json_parser_4;
7873 goto basic_json_parser_13;
7875 goto basic_json_parser_15;
7881 goto basic_json_parser_17;
7885 goto basic_json_parser_19;
7887 goto basic_json_parser_4;
7899 goto basic_json_parser_21;
7903 goto basic_json_parser_4;
7905 goto basic_json_parser_23;
7911 goto basic_json_parser_24;
7915 goto basic_json_parser_4;
7917 goto basic_json_parser_25;
7926 goto basic_json_parser_26;
7928 goto basic_json_parser_4;
7934 goto basic_json_parser_28;
7938 goto basic_json_parser_30;
7940 goto basic_json_parser_4;
7944 basic_json_parser_2:
7947 last_token_type = token_type::end_of_input;
7950 basic_json_parser_4:
7952 basic_json_parser_5:
7954 last_token_type = token_type::parse_error;
7957 basic_json_parser_6:
7959 if (m_limit <= m_cursor)
7964 if (yybm[0 + yych] & 32)
7966 goto basic_json_parser_6;
7971 basic_json_parser_9:
7973 yych = *(m_marker = ++m_cursor);
7976 goto basic_json_parser_5;
7978 goto basic_json_parser_32;
7979 basic_json_parser_10:
7982 last_token_type = token_type::value_separator;
7985 basic_json_parser_12:
7989 goto basic_json_parser_5;
7993 goto basic_json_parser_13;
7997 goto basic_json_parser_15;
7999 goto basic_json_parser_5;
8000 basic_json_parser_13:
8002 yych = *(m_marker = ++m_cursor);
8007 goto basic_json_parser_37;
8014 goto basic_json_parser_38;
8018 goto basic_json_parser_38;
8021 basic_json_parser_14:
8023 last_token_type = token_type::value_number;
8026 basic_json_parser_15:
8028 m_marker = ++m_cursor;
8029 if ((m_limit - m_cursor) < 3)
8034 if (yybm[0 + yych] & 64)
8036 goto basic_json_parser_15;
8042 goto basic_json_parser_37;
8044 goto basic_json_parser_14;
8050 goto basic_json_parser_38;
8054 goto basic_json_parser_38;
8056 goto basic_json_parser_14;
8058 basic_json_parser_17:
8061 last_token_type = token_type::name_separator;
8064 basic_json_parser_19:
8067 last_token_type = token_type::begin_array;
8070 basic_json_parser_21:
8073 last_token_type = token_type::end_array;
8076 basic_json_parser_23:
8078 yych = *(m_marker = ++m_cursor);
8081 goto basic_json_parser_39;
8083 goto basic_json_parser_5;
8084 basic_json_parser_24:
8086 yych = *(m_marker = ++m_cursor);
8089 goto basic_json_parser_40;
8091 goto basic_json_parser_5;
8092 basic_json_parser_25:
8094 yych = *(m_marker = ++m_cursor);
8097 goto basic_json_parser_41;
8099 goto basic_json_parser_5;
8100 basic_json_parser_26:
8103 last_token_type = token_type::begin_object;
8106 basic_json_parser_28:
8109 last_token_type = token_type::end_object;
8112 basic_json_parser_30:
8114 yych = *(m_marker = ++m_cursor);
8117 goto basic_json_parser_42;
8119 goto basic_json_parser_5;
8120 basic_json_parser_31:
8122 if (m_limit <= m_cursor)
8127 basic_json_parser_32:
8128 if (yybm[0 + yych] & 128)
8130 goto basic_json_parser_31;
8134 goto basic_json_parser_33;
8138 goto basic_json_parser_34;
8140 goto basic_json_parser_36;
8141 basic_json_parser_33:
8142 m_cursor = m_marker;
8145 goto basic_json_parser_5;
8149 goto basic_json_parser_14;
8151 basic_json_parser_34:
8154 last_token_type = token_type::value_string;
8157 basic_json_parser_36:
8159 if (m_limit <= m_cursor)
8170 goto basic_json_parser_31;
8174 goto basic_json_parser_33;
8176 goto basic_json_parser_31;
8184 goto basic_json_parser_33;
8186 goto basic_json_parser_31;
8192 goto basic_json_parser_31;
8194 goto basic_json_parser_33;
8204 goto basic_json_parser_31;
8208 goto basic_json_parser_31;
8210 goto basic_json_parser_33;
8218 goto basic_json_parser_31;
8220 goto basic_json_parser_33;
8226 goto basic_json_parser_31;
8230 goto basic_json_parser_43;
8232 goto basic_json_parser_33;
8236 basic_json_parser_37:
8240 goto basic_json_parser_33;
8244 goto basic_json_parser_44;
8246 goto basic_json_parser_33;
8247 basic_json_parser_38:
8253 goto basic_json_parser_46;
8255 goto basic_json_parser_33;
8261 goto basic_json_parser_46;
8265 goto basic_json_parser_33;
8269 goto basic_json_parser_47;
8271 goto basic_json_parser_33;
8273 basic_json_parser_39:
8277 goto basic_json_parser_49;
8279 goto basic_json_parser_33;
8280 basic_json_parser_40:
8284 goto basic_json_parser_50;
8286 goto basic_json_parser_33;
8287 basic_json_parser_41:
8291 goto basic_json_parser_51;
8293 goto basic_json_parser_33;
8294 basic_json_parser_42:
8298 goto basic_json_parser_52;
8300 goto basic_json_parser_33;
8301 basic_json_parser_43:
8303 if (m_limit <= m_cursor)
8312 goto basic_json_parser_33;
8316 goto basic_json_parser_54;
8318 goto basic_json_parser_33;
8324 goto basic_json_parser_54;
8328 goto basic_json_parser_33;
8332 goto basic_json_parser_54;
8334 goto basic_json_parser_33;
8336 basic_json_parser_44:
8338 m_marker = ++m_cursor;
8339 if ((m_limit - m_cursor) < 3)
8348 goto basic_json_parser_14;
8352 goto basic_json_parser_44;
8354 goto basic_json_parser_14;
8360 goto basic_json_parser_38;
8364 goto basic_json_parser_38;
8366 goto basic_json_parser_14;
8368 basic_json_parser_46:
8372 goto basic_json_parser_33;
8376 goto basic_json_parser_33;
8378 basic_json_parser_47:
8380 if (m_limit <= m_cursor)
8387 goto basic_json_parser_14;
8391 goto basic_json_parser_47;
8393 goto basic_json_parser_14;
8394 basic_json_parser_49:
8398 goto basic_json_parser_55;
8400 goto basic_json_parser_33;
8401 basic_json_parser_50:
8405 goto basic_json_parser_56;
8407 goto basic_json_parser_33;
8408 basic_json_parser_51:
8412 goto basic_json_parser_58;
8414 goto basic_json_parser_33;
8415 basic_json_parser_52:
8420 basic_json_parser_54:
8422 if (m_limit <= m_cursor)
8431 goto basic_json_parser_33;
8435 goto basic_json_parser_60;
8437 goto basic_json_parser_33;
8443 goto basic_json_parser_60;
8447 goto basic_json_parser_33;
8451 goto basic_json_parser_60;
8453 goto basic_json_parser_33;
8455 basic_json_parser_55:
8459 goto basic_json_parser_61;
8461 goto basic_json_parser_33;
8462 basic_json_parser_56:
8465 last_token_type = token_type::literal_null;
8468 basic_json_parser_58:
8471 last_token_type = token_type::literal_true;
8474 basic_json_parser_60:
8476 if (m_limit <= m_cursor)
8485 goto basic_json_parser_33;
8489 goto basic_json_parser_63;
8491 goto basic_json_parser_33;
8497 goto basic_json_parser_63;
8501 goto basic_json_parser_33;
8505 goto basic_json_parser_63;
8507 goto basic_json_parser_33;
8509 basic_json_parser_61:
8512 last_token_type = token_type::literal_false;
8515 basic_json_parser_63:
8517 if (m_limit <= m_cursor)
8526 goto basic_json_parser_33;
8530 goto basic_json_parser_31;
8532 goto basic_json_parser_33;
8538 goto basic_json_parser_31;
8542 goto basic_json_parser_33;
8546 goto basic_json_parser_31;
8548 goto basic_json_parser_33;
8554 return last_token_type;
8585 void fill_line_buffer()
8588 const auto offset_start = m_start - m_content;
8590 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
8592 const auto offset_cursor = m_cursor - m_start;
8595 if (m_stream ==
nullptr or not * m_stream)
8598 m_line_buffer.clear();
8599 for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
8601 m_line_buffer.append(1, static_cast<const char>(*m_cursor));
8607 m_line_buffer.append(5,
'\0');
8612 m_line_buffer.erase(0, static_cast<size_t>(offset_start));
8615 std::getline(*m_stream, line);
8617 m_line_buffer +=
"\n" + line;
8621 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.c_str());
8622 assert(m_content !=
nullptr);
8623 m_start = m_content;
8624 m_marker = m_start + offset_marker;
8625 m_cursor = m_start + offset_cursor;
8626 m_limit = m_start + m_line_buffer.size();
8630 string_t get_token_string()
const 8632 assert(m_start !=
nullptr);
8633 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
8634 static_cast<size_t>(m_cursor - m_start));
8694 string_t get_string()
const 8696 assert(m_cursor - m_start >= 2);
8699 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
8702 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
8758 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
8759 4).c_str(),
nullptr, 16);
8762 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
8765 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
8767 throw std::invalid_argument(
"missing low surrogate");
8771 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
8772 (i + 7), 4).c_str(),
nullptr, 16);
8773 result += to_unicode(codepoint, codepoint2);
8780 result += to_unicode(codepoint);
8792 result.append(1, static_cast<typename string_t::value_type>(*i));
8814 long double str_to_float_t(
long double* ,
char** endptr)
const 8816 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8834 double str_to_float_t(
double* ,
char** endptr)
const 8836 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8854 float str_to_float_t(
float* ,
char** endptr)
const 8856 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
8880 void get_number(basic_json& result)
const 8882 assert(m_start !=
nullptr);
8884 const lexer::lexer_char_t* curptr = m_start;
8887 number_unsigned_t value = 0;
8890 number_unsigned_t max;
8898 type = value_t::number_integer;
8899 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
8904 type = value_t::number_unsigned;
8905 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
8909 for (; curptr < m_cursor; curptr++)
8912 if (*curptr < '0' || *curptr >
'9')
8917 type = value_t::number_float;
8922 type = value_t::number_float;
8927 if (type != value_t::number_float)
8930 auto temp = value * 10 + *curptr -
'0';
8933 if (temp < value || temp > max)
8936 type = value_t::number_float;
8947 if (type == value_t::number_unsigned)
8949 result.m_value.number_unsigned = value;
8951 else if (type == value_t::number_integer)
8953 result.m_value.number_integer = -
static_cast<number_integer_t
>(value);
8958 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr), NULL);
8962 result.m_type = type;
8967 std::istream* m_stream =
nullptr;
8969 string_t m_line_buffer {};
8971 const lexer_char_t* m_content =
nullptr;
8973 const lexer_char_t* m_start =
nullptr;
8975 const lexer_char_t* m_marker =
nullptr;
8977 const lexer_char_t* m_cursor =
nullptr;
8979 const lexer_char_t* m_limit =
nullptr;
8981 token_type last_token_type = token_type::end_of_input;
8993 parser(
const char* buff,
const parser_callback_t cb =
nullptr)
8995 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), strlen(buff))
8999 parser(std::istream& is,
const parser_callback_t cb =
nullptr)
9000 : callback(cb), m_lexer(is)
9004 template<
class IteratorType,
typename std::enable_if<
9005 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
9008 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
9010 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
9011 static_cast<size_t>(
std::distance(first, last)))
9020 basic_json result = parse_internal(
true);
9021 result.assert_invariant();
9023 expect(lexer::token_type::end_of_input);
9027 return result.is_discarded() ? basic_json() :
std::move(result);
9032 basic_json parse_internal(
bool keep)
9034 auto result = basic_json(value_t::discarded);
9038 case lexer::token_type::begin_object:
9040 if (keep and (not callback
9041 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
9044 result.m_type = value_t::object;
9045 result.m_value = value_t::object;
9052 if (last_token == lexer::token_type::end_object)
9055 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9057 result = basic_json(value_t::discarded);
9063 unexpect(lexer::token_type::value_separator);
9069 if (last_token == lexer::token_type::value_separator)
9075 expect(lexer::token_type::value_string);
9076 const auto key = m_lexer.get_string();
9078 bool keep_tag =
false;
9084 keep_tag = callback(depth, parse_event_t::key, k);
9094 expect(lexer::token_type::name_separator);
9098 auto value = parse_internal(keep);
9099 if (keep and keep_tag and not value.is_discarded())
9101 result[key] = std::move(value);
9104 while (last_token == lexer::token_type::value_separator);
9107 expect(lexer::token_type::end_object);
9109 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
9111 result = basic_json(value_t::discarded);
9117 case lexer::token_type::begin_array:
9119 if (keep and (not callback
9120 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
9123 result.m_type = value_t::array;
9124 result.m_value = value_t::array;
9131 if (last_token == lexer::token_type::end_array)
9134 if (callback and not callback(--depth, parse_event_t::array_end, result))
9136 result = basic_json(value_t::discarded);
9142 unexpect(lexer::token_type::value_separator);
9148 if (last_token == lexer::token_type::value_separator)
9154 auto value = parse_internal(keep);
9155 if (keep and not value.is_discarded())
9157 result.push_back(std::move(value));
9160 while (last_token == lexer::token_type::value_separator);
9163 expect(lexer::token_type::end_array);
9165 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
9167 result = basic_json(value_t::discarded);
9173 case lexer::token_type::literal_null:
9176 result.m_type = value_t::null;
9180 case lexer::token_type::value_string:
9182 const auto s = m_lexer.get_string();
9184 result = basic_json(s);
9188 case lexer::token_type::literal_true:
9191 result.m_type = value_t::boolean;
9192 result.m_value =
true;
9196 case lexer::token_type::literal_false:
9199 result.m_type = value_t::boolean;
9200 result.m_value =
false;
9204 case lexer::token_type::value_number:
9206 m_lexer.get_number(result);
9214 unexpect(last_token);
9218 if (keep and callback and not callback(depth, parse_event_t::value, result))
9220 result = basic_json(value_t::discarded);
9226 typename lexer::token_type get_token()
9228 last_token = m_lexer.scan();
9232 void expect(
typename lexer::token_type t)
const 9234 if (t != last_token)
9236 std::string error_msg =
"parse error - unexpected ";
9237 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9239 lexer::token_type_name(last_token));
9240 error_msg +=
"; expected " + lexer::token_type_name(t);
9241 throw std::invalid_argument(error_msg);
9245 void unexpect(
typename lexer::token_type t)
const 9247 if (t == last_token)
9249 std::string error_msg =
"parse error - unexpected ";
9250 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
9252 lexer::token_type_name(last_token));
9253 throw std::invalid_argument(error_msg);
9261 const parser_callback_t callback =
nullptr;
9263 typename lexer::token_type last_token = lexer::token_type::uninitialized;
9283 friend class basic_json;
9308 explicit json_pointer(
const std::string& s =
"")
9309 : reference_tokens(split(s))
9327 std::string to_string() const noexcept
9329 return std::accumulate(reference_tokens.begin(),
9330 reference_tokens.end(), std::string{},
9331 [](
const std::string & a,
const std::string & b)
9333 return a +
"/" + escape(b);
9338 operator std::string()
const 9345 std::string pop_back()
9349 throw std::domain_error(
"JSON pointer has no parent");
9352 auto last = reference_tokens.back();
9353 reference_tokens.pop_back();
9358 bool is_root()
const 9360 return reference_tokens.empty();
9363 json_pointer top()
const 9367 throw std::domain_error(
"JSON pointer has no parent");
9370 json_pointer result = *
this;
9371 result.reference_tokens = {reference_tokens[0]};
9380 reference get_and_create(reference j)
const 9382 pointer result = &j;
9386 for (
const auto& reference_token : reference_tokens)
9388 switch (result->m_type)
9392 if (reference_token ==
"0")
9395 result = &result->operator[](0);
9400 result = &result->operator[](reference_token);
9405 case value_t::object:
9408 result = &result->operator[](reference_token);
9412 case value_t::array:
9415 result = &result->operator[](
static_cast<size_type
>(std::stoi(reference_token)));
9428 throw std::domain_error(
"invalid value to unflatten");
9449 reference get_unchecked(pointer ptr)
const 9451 for (
const auto& reference_token : reference_tokens)
9453 switch (ptr->m_type)
9455 case value_t::object:
9458 ptr = &ptr->operator[](reference_token);
9462 case value_t::array:
9465 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9467 throw std::domain_error(
"array index must not begin with '0'");
9470 if (reference_token ==
"-")
9473 ptr = &ptr->operator[](ptr->m_value.array->size());
9478 ptr = &ptr->operator[](
static_cast<size_type
>(std::stoi(reference_token)));
9485 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9493 reference get_checked(pointer ptr)
const 9495 for (
const auto& reference_token : reference_tokens)
9497 switch (ptr->m_type)
9499 case value_t::object:
9502 ptr = &ptr->at(reference_token);
9506 case value_t::array:
9508 if (reference_token ==
"-")
9511 throw std::out_of_range(
"array index '-' (" +
9512 std::to_string(ptr->m_value.array->size()) +
9513 ") is out of range");
9517 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9519 throw std::domain_error(
"array index must not begin with '0'");
9523 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9529 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9545 const_reference get_unchecked(const_pointer ptr)
const 9547 for (
const auto& reference_token : reference_tokens)
9549 switch (ptr->m_type)
9551 case value_t::object:
9554 ptr = &ptr->operator[](reference_token);
9558 case value_t::array:
9560 if (reference_token ==
"-")
9563 throw std::out_of_range(
"array index '-' (" +
9564 std::to_string(ptr->m_value.array->size()) +
9565 ") is out of range");
9569 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9571 throw std::domain_error(
"array index must not begin with '0'");
9575 ptr = &ptr->operator[](
static_cast<size_type
>(std::stoi(reference_token)));
9581 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9589 const_reference get_checked(const_pointer ptr)
const 9591 for (
const auto& reference_token : reference_tokens)
9593 switch (ptr->m_type)
9595 case value_t::object:
9598 ptr = &ptr->at(reference_token);
9602 case value_t::array:
9604 if (reference_token ==
"-")
9607 throw std::out_of_range(
"array index '-' (" +
9608 std::to_string(ptr->m_value.array->size()) +
9609 ") is out of range");
9613 if (reference_token.size() > 1 and reference_token[0] ==
'0')
9615 throw std::domain_error(
"array index must not begin with '0'");
9619 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
9625 throw std::out_of_range(
"unresolved reference token '" + reference_token +
"'");
9634 static std::vector<std::string> split(
const std::string& reference_string)
9636 std::vector<std::string> result;
9639 if (reference_string.empty())
9645 if (reference_string[0] !=
'/')
9647 throw std::domain_error(
"JSON pointer must be empty or begin with '/'");
9655 size_t slash = reference_string.find_first_of(
"/", 1),
9664 slash = reference_string.find_first_of(
"/", start))
9668 auto reference_token = reference_string.substr(start, slash - start);
9671 for (
size_t pos = reference_token.find_first_of(
"~");
9672 pos != std::string::npos;
9673 pos = reference_token.find_first_of(
"~", pos + 1))
9675 assert(reference_token[pos] ==
'~');
9678 if (pos == reference_token.size() - 1 or
9679 (reference_token[pos + 1] !=
'0' and
9680 reference_token[pos + 1] !=
'1'))
9682 throw std::domain_error(
"escape error: '~' must be followed with '0' or '1'");
9687 unescape(reference_token);
9688 result.push_back(reference_token);
9709 static void replace_substring(std::string& s,
9710 const std::string& f,
9711 const std::string& t)
9713 assert(not f.empty());
9716 size_t pos = s.find(f);
9717 pos != std::string::npos;
9718 s.replace(pos, f.size(), t),
9719 pos = s.find(f, pos + t.size())
9724 static std::string escape(std::string s)
9727 replace_substring(s,
"~",
"~0");
9728 replace_substring(s,
"/",
"~1");
9733 static void unescape(std::string& s)
9736 replace_substring(s,
"~1",
"/");
9738 replace_substring(s,
"~0",
"~");
9748 static void flatten(
const std::string& reference_string,
9749 const basic_json& value,
9752 switch (value.m_type)
9754 case value_t::array:
9756 if (value.m_value.array->empty())
9759 result[reference_string] =
nullptr;
9764 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
9766 flatten(reference_string +
"/" + std::to_string(i),
9767 value.m_value.array->operator[](i), result);
9773 case value_t::object:
9775 if (value.m_value.object->empty())
9778 result[reference_string] =
nullptr;
9783 for (
const auto& element : *value.m_value.object)
9785 flatten(reference_string +
"/" + escape(element.first),
9786 element.second, result);
9795 result[reference_string] = value;
9806 static basic_json unflatten(
const basic_json& value)
9808 if (not value.is_object())
9810 throw std::domain_error(
"only objects can be unflattened");
9816 for (
const auto& element : *value.m_value.object)
9818 if (not element.second.is_primitive())
9820 throw std::domain_error(
"values in object must be primitive");
9828 json_pointer(element.first).get_and_create(result) = element.second;
9836 std::vector<std::string> reference_tokens {};
9879 reference operator[](
const json_pointer& ptr)
9881 return ptr.get_unchecked(
this);
9906 const_reference operator[](
const json_pointer& ptr)
const 9908 return ptr.get_unchecked(
this);
9931 reference at(
const json_pointer& ptr)
9933 return ptr.get_checked(
this);
9956 const_reference at(
const json_pointer& ptr)
const 9958 return ptr.get_checked(
this);
9983 basic_json flatten()
const 9985 basic_json result(value_t::object);
9986 json_pointer::flatten(
"", *
this, result);
10017 basic_json unflatten()
const 10019 return json_pointer::unflatten(*
this);
10067 basic_json patch(
const basic_json& json_patch)
const 10070 basic_json result = *
this;
10073 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
10075 const auto get_op = [](
const std::string op)
10079 return patch_operations::add;
10081 if (op ==
"remove")
10083 return patch_operations::remove;
10085 if (op ==
"replace")
10087 return patch_operations::replace;
10091 return patch_operations::move;
10095 return patch_operations::copy;
10099 return patch_operations::test;
10102 return patch_operations::invalid;
10106 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
10116 json_pointer top_pointer = ptr.top();
10117 if (top_pointer != ptr)
10119 basic_json& x = result.at(top_pointer);
10123 const auto last_path = ptr.pop_back();
10124 basic_json& parent = result[ptr];
10126 switch (parent.m_type)
10128 case value_t::null:
10129 case value_t::object:
10132 parent[last_path] = val;
10136 case value_t::array:
10138 if (last_path ==
"-")
10141 parent.push_back(val);
10145 const auto idx = std::stoi(last_path);
10146 if (static_cast<size_type>(idx) > parent.size())
10149 throw std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range");
10154 parent.insert(parent.begin() +
static_cast<difference_type
>(idx), val);
10170 const auto operation_remove = [&result](json_pointer & ptr)
10173 const auto last_path = ptr.pop_back();
10174 basic_json& parent = result.at(ptr);
10177 if (parent.is_object())
10180 auto it = parent.find(last_path);
10181 if (it != parent.end())
10187 throw std::out_of_range(
"key '" + last_path +
"' not found");
10190 else if (parent.is_array())
10193 parent.erase(static_cast<size_type>(std::stoi(last_path)));
10198 if (not json_patch.is_array())
10201 throw std::invalid_argument(
"JSON patch must be an array of objects");
10205 for (
const auto& val : json_patch)
10208 const auto get_value = [&val](
const std::string & op,
10209 const std::string & member,
10210 bool string_type) -> basic_json&
10213 auto it = val.m_value.object->find(member);
10216 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
10219 if (it == val.m_value.object->end())
10221 throw std::invalid_argument(error_msg +
" must have member '" + member +
"'");
10225 if (string_type and not it->second.is_string())
10227 throw std::invalid_argument(error_msg +
" must have string member '" + member +
"'");
10235 if (not val.is_object())
10237 throw std::invalid_argument(
"JSON patch must be an array of objects");
10241 const std::string op = get_value(
"op",
"op",
true);
10242 const std::string path = get_value(op,
"path",
true);
10243 json_pointer ptr(path);
10245 switch (get_op(op))
10247 case patch_operations::add:
10249 operation_add(ptr, get_value(
"add",
"value",
false));
10253 case patch_operations::remove:
10255 operation_remove(ptr);
10259 case patch_operations::replace:
10262 result.at(ptr) = get_value(
"replace",
"value",
false);
10266 case patch_operations::move:
10268 const std::string from_path = get_value(
"move",
"from",
true);
10269 json_pointer from_ptr(from_path);
10272 basic_json v = result.at(from_ptr);
10278 operation_remove(from_ptr);
10279 operation_add(ptr, v);
10283 case patch_operations::copy:
10285 const std::string from_path = get_value(
"copy",
"from",
true);;
10286 const json_pointer from_ptr(from_path);
10289 result[ptr] = result.at(from_ptr);
10293 case patch_operations::test:
10295 bool success =
false;
10300 success = (result.at(ptr) == get_value(
"test",
"value",
false));
10302 catch (std::out_of_range&)
10310 throw std::domain_error(
"unsuccessful: " + val.dump());
10316 case patch_operations::invalid:
10320 throw std::invalid_argument(
"operation value '" + op +
"' is invalid");
10360 static basic_json diff(
const basic_json& source,
10361 const basic_json& target,
10362 const std::string& path =
"")
10365 basic_json result(value_t::array);
10368 if (source == target)
10373 if (source.type() != target.type())
10385 switch (source.type())
10387 case value_t::array:
10391 while (i < source.size() and i < target.size())
10394 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
10395 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10403 const auto end_index =
static_cast<difference_type
>(result.size());
10404 while (i < source.size())
10408 result.insert(result.begin() + end_index, object(
10411 {
"path", path +
"/" + std::to_string(i)}
10417 while (i < target.size())
10422 {
"path", path +
"/" + std::to_string(i)},
10423 {
"value", target[i]}
10431 case value_t::object:
10434 for (
auto it = source.begin(); it != source.end(); ++it)
10437 const auto key = json_pointer::escape(it.key());
10439 if (target.find(it.key()) != target.end())
10442 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
10443 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
10448 result.push_back(
object(
10451 {
"path", path +
"/" + key}
10457 for (
auto it = target.begin(); it != target.end(); ++it)
10459 if (source.find(it.key()) == source.end())
10462 const auto key = json_pointer::escape(it.key());
10466 {
"path", path +
"/" + key},
10467 {
"value", it.value()}
10508 using json = basic_json<>;
10525 inline void swap(nlohmann::json& j1,
10526 nlohmann::json& j2) noexcept(
10527 is_nothrow_move_constructible<nlohmann::json>::value and
10528 is_nothrow_move_assignable<nlohmann::json>::value
10543 std::size_t operator()(
const nlohmann::json& j)
const 10546 const auto& h = hash<nlohmann::json::string_t>();
10547 return h(j.dump());
10564 inline nlohmann::json
operator "" _json(
const char* s, std::size_t)
10566 return nlohmann::json::parse(s);
10581 inline nlohmann::json::json_pointer
operator "" _json_pointer(
const char* s, std::size_t)
10583 return nlohmann::json::json_pointer(s);
10587 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 10588 #pragma GCC diagnostic pop
bool operator==(const FieldID &left, const FieldID &right)
Check for equality of FieldIDs.
namespace for Niels Lohmann
bool operator!=(const FieldID &left, const FieldID &right)
Check for inequality of FieldIDs.
std::ostream & operator<<(std::ostream &stream, const FieldID &f)
Convert FieldID to stream.