29 #ifndef NLOHMANN_JSON_HPP 30 #define NLOHMANN_JSON_HPP 42 #include <forward_list> 44 #include <initializer_list> 56 #include <type_traits> 61 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 62 #define JSON_DEPRECATED __attribute__((deprecated)) 63 #elif defined(_MSC_VER) 64 #define JSON_DEPRECATED __declspec(deprecated) 66 #define JSON_DEPRECATED 70 #if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS) 71 #define JSON_THROW(exception) throw exception 73 #define JSON_CATCH(exception) catch(exception) 75 #define JSON_THROW(exception) std::abort() 76 #define JSON_TRY if(true) 77 #define JSON_CATCH(exception) if(false) 150 static constexpr std::array<uint8_t, 8> order = {{
168 return order[
static_cast<std::size_t
>(lhs)] <
169 order[static_cast<std::size_t>(rhs)];
178 template<
bool B,
typename T =
void>
182 using uncvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
187 std::integral_constant<bool, std::is_convertible<T, int>::value and
188 std::is_enum<T>::value>;
205 template<
class B1,
class... Bn>
206 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
208 template<
class B>
struct negation : std::integral_constant < bool, !B::value > {};
224 template<
typename BasicJsonType>
225 static void construct(BasicJsonType& j,
typename BasicJsonType::boolean_t b) noexcept
229 j.assert_invariant();
236 template<
typename BasicJsonType>
237 static void construct(BasicJsonType& j,
const typename BasicJsonType::string_t& s)
241 j.assert_invariant();
248 template<
typename BasicJsonType>
249 static void construct(BasicJsonType& j,
typename BasicJsonType::number_float_t val) noexcept
252 if (not std::isfinite(val))
261 j.assert_invariant();
268 template<
typename BasicJsonType>
269 static void construct(BasicJsonType& j,
typename BasicJsonType::number_unsigned_t val) noexcept
273 j.assert_invariant();
280 template<
typename BasicJsonType>
281 static void construct(BasicJsonType& j,
typename BasicJsonType::number_integer_t val) noexcept
285 j.assert_invariant();
292 template<
typename BasicJsonType>
293 static void construct(BasicJsonType& j,
const typename BasicJsonType::array_t& arr)
297 j.assert_invariant();
300 template<
typename BasicJsonType,
typename CompatibleArrayType,
302 typename BasicJsonType::array_t>::value,
304 static void construct(BasicJsonType& j,
const CompatibleArrayType& arr)
309 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
310 j.assert_invariant();
317 template<
typename BasicJsonType>
318 static void construct(BasicJsonType& j,
const typename BasicJsonType::object_t& obj)
322 j.assert_invariant();
325 template<
typename BasicJsonType,
typename CompatibleObjectType,
327 typename BasicJsonType::object_t>::value,
329 static void construct(BasicJsonType& j,
const CompatibleObjectType& obj)
335 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
336 j.assert_invariant();
355 #define NLOHMANN_JSON_HAS_HELPER(type) \ 356 template<typename T> struct has_##type { \ 358 template<typename U, typename = typename U::type> \ 359 static int detect(U &&); \ 360 static void detect(...); \ 362 static constexpr bool value = \ 363 std::is_integral<decltype(detect(std::declval<T>()))>::value; \ 371 #undef NLOHMANN_JSON_HAS_HELPER 374 template<
bool B,
class RealType,
class CompatibleObjectType>
377 template<
class RealType,
class CompatibleObjectType>
380 static constexpr
auto value =
381 std::is_constructible<
typename RealType::key_type,
382 typename CompatibleObjectType::key_type>::value and
383 std::is_constructible<
typename RealType::mapped_type,
384 typename CompatibleObjectType::mapped_type>::value;
387 template<
class BasicJsonType,
class CompatibleObjectType>
392 has_mapped_type<CompatibleObjectType>,
393 has_key_type<CompatibleObjectType>>::value,
394 typename BasicJsonType::object_t, CompatibleObjectType >::value;
397 template<
typename BasicJsonType,
typename T>
400 static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
401 std::is_same<T, typename BasicJsonType::const_iterator>::value or
402 std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
403 std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value or
404 std::is_same<T, typename BasicJsonType::json_pointer>::value;
407 template<
class BasicJsonType,
class CompatibleArrayType>
410 static auto constexpr value =
413 BasicJsonType, CompatibleArrayType>>,
414 negation<std::is_constructible<
typename BasicJsonType::string_t,
415 CompatibleArrayType>>,
417 has_value_type<CompatibleArrayType>,
418 has_iterator<CompatibleArrayType>>::value;
421 template<
bool,
typename,
typename>
424 template<
typename RealIntegerType,
typename CompatibleNumberIntegerType>
431 static constexpr
auto value =
432 std::is_constructible<RealIntegerType,
433 CompatibleNumberIntegerType>::value and
434 CompatibleLimits::is_integer and
435 RealLimits::is_signed == CompatibleLimits::is_signed;
438 template<
typename RealIntegerType,
typename CompatibleNumberIntegerType>
441 static constexpr
auto value =
443 std::is_integral<CompatibleNumberIntegerType>::value and
444 not std::is_same<bool, CompatibleNumberIntegerType>::value,
445 RealIntegerType, CompatibleNumberIntegerType > ::value;
450 template<
typename BasicJsonType,
typename T>
456 std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
457 static int detect(U&&);
458 static void detect(...);
461 static constexpr
bool value = std::is_integral<decltype(
462 detect(std::declval<
typename BasicJsonType::template json_serializer<T, void > >()))>::value;
467 template<
typename BasicJsonType,
typename T>
475 static int detect(U&&);
476 static void detect(...);
479 static constexpr
bool value = std::is_integral<decltype(detect(
480 std::declval<
typename BasicJsonType::template json_serializer<T, void> >()))>::value;
484 template<
typename BasicJsonType,
typename T>
489 std::declval<BasicJsonType&>(), std::declval<T>()))>
490 static int detect(U&&);
491 static void detect(...);
494 static constexpr
bool value = std::is_integral<decltype(detect(
495 std::declval<
typename BasicJsonType::template json_serializer<T, void> >()))>::value;
503 template<
typename BasicJsonType,
typename T,
enable_if_t<
504 std::is_same<T, typename BasicJsonType::boolean_t>::value,
int> = 0>
510 template<
typename BasicJsonType,
typename CompatibleString,
511 enable_if_t<std::is_constructible<
typename BasicJsonType::string_t,
512 CompatibleString>::value,
int> = 0>
513 void to_json(BasicJsonType& j,
const CompatibleString& s)
518 template<
typename BasicJsonType,
typename FloatType,
520 void to_json(BasicJsonType& j, FloatType val) noexcept
526 typename BasicJsonType,
typename CompatibleNumberUnsignedType,
528 CompatibleNumberUnsignedType>::value,
int> = 0 >
529 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
535 typename BasicJsonType,
typename CompatibleNumberIntegerType,
537 CompatibleNumberIntegerType>::value,
int> = 0 >
538 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
543 template<
typename BasicJsonType,
typename UnscopedEnumType,
545 void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
551 typename BasicJsonType,
typename CompatibleArrayType,
554 std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
556 void to_json(BasicJsonType& j,
const CompatibleArrayType& arr)
562 typename BasicJsonType,
typename CompatibleObjectType,
565 void to_json(BasicJsonType& j,
const CompatibleObjectType& arr)
576 template<
typename BasicJsonType,
typename ArithmeticType,
578 not std::is_same<ArithmeticType,
579 typename BasicJsonType::boolean_t>::value,
583 switch (static_cast<value_t>(j))
587 val =
static_cast<ArithmeticType
>(
588 *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
593 val =
static_cast<ArithmeticType
>(
594 *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
599 val =
static_cast<ArithmeticType
>(
600 *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
606 std::domain_error(
"type must be number, but is " + j.type_name()));
611 template<
typename BasicJsonType>
612 void from_json(
const BasicJsonType& j,
typename BasicJsonType::boolean_t& b)
614 if (not j.is_boolean())
616 JSON_THROW(std::domain_error(
"type must be boolean, but is " + j.type_name()));
618 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
621 template<
typename BasicJsonType>
622 void from_json(
const BasicJsonType& j,
typename BasicJsonType::string_t& s)
624 if (not j.is_string())
626 JSON_THROW(std::domain_error(
"type must be string, but is " + j.type_name()));
628 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
631 template<
typename BasicJsonType>
632 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_float_t& val)
637 template<
typename BasicJsonType>
638 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_unsigned_t& val)
643 template<
typename BasicJsonType>
644 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_integer_t& val)
649 template<
typename BasicJsonType,
typename UnscopedEnumType,
650 enable_if_t<is_unscoped_enum<UnscopedEnumType>::value,
int> = 0>
651 void from_json(
const BasicJsonType& j, UnscopedEnumType& e)
653 typename std::underlying_type<UnscopedEnumType>::type val;
655 e =
static_cast<UnscopedEnumType
>(val);
658 template<
typename BasicJsonType>
659 void from_json(
const BasicJsonType& j,
typename BasicJsonType::array_t& arr)
661 if (not j.is_array())
663 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
665 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
669 template<
typename BasicJsonType,
typename T,
typename Allocator>
670 void from_json(
const BasicJsonType& j, std::forward_list<T, Allocator>& l)
676 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
678 if (not std::is_same<T, BasicJsonType>::value)
680 if (not j.is_array())
682 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
685 for (
auto it = j.rbegin(), end = j.rend(); it != end; ++it)
687 l.push_front(it->template get<T>());
691 template<
typename BasicJsonType,
typename CompatibleArrayType>
697 std::transform(j.begin(), j.end(),
698 std::inserter(arr, end(arr)), [](
const BasicJsonType & i)
702 return i.template get<typename CompatibleArrayType::value_type>();
706 template<
typename BasicJsonType,
typename CompatibleArrayType>
709 arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
715 arr.reserve(j.size());
717 j.begin(), j.end(), std::inserter(arr, end(arr)), [](
const BasicJsonType & i)
721 return i.template get<typename CompatibleArrayType::value_type>();
725 template<
typename BasicJsonType,
typename CompatibleArrayType,
727 not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
int> = 0>
728 void from_json(
const BasicJsonType& j, CompatibleArrayType& arr)
732 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
736 if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
738 if (not j.is_array())
740 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
746 template<
typename BasicJsonType,
typename CompatibleObjectType,
747 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
int> = 0>
748 void from_json(
const BasicJsonType& j, CompatibleObjectType& obj)
750 if (not j.is_object())
752 JSON_THROW(std::domain_error(
"type must be object, but is " + j.type_name()));
755 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
761 obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));
768 template<
typename BasicJsonType,
typename ArithmeticType,
770 std::is_arithmetic<ArithmeticType>::value and
771 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
772 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
773 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
774 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
776 void from_json(
const BasicJsonType& j, ArithmeticType& val)
778 switch (static_cast<value_t>(j))
782 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
787 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
792 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
797 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
802 JSON_THROW(std::domain_error(
"type must be number, but is " + j.type_name()));
810 template<
typename BasicJsonType,
typename T>
811 auto call(BasicJsonType& j, T&& val,
priority_tag<1>)
const noexcept(noexcept(
to_json(j, std::forward<T>(val))))
812 -> decltype(
to_json(j, std::forward<T>(val)),
void())
814 return to_json(j, std::forward<T>(val));
817 template<
typename BasicJsonType,
typename T>
820 static_assert(
sizeof(BasicJsonType) == 0,
821 "could not find to_json() method in T's namespace");
825 template<
typename BasicJsonType,
typename T>
827 noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val),
priority_tag<1> {})))
836 template<
typename BasicJsonType,
typename T>
844 template<
typename BasicJsonType,
typename T>
847 static_assert(
sizeof(BasicJsonType) == 0,
848 "could not find from_json() method in T's namespace");
852 template<
typename BasicJsonType,
typename T>
854 noexcept(noexcept(std::declval<from_json_fn>().call(j, val,
priority_tag<1> {})))
864 static constexpr T value{};
887 template<
typename =
void,
typename =
void>
899 template<
typename BasicJsonType,
typename ValueType>
900 static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
915 template<
typename BasicJsonType,
typename ValueType>
916 static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
1006 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
1007 template<
typename U,
typename... Args>
class ArrayType = std::vector,
1009 class BooleanType = bool,
1010 class NumberIntegerType = std::int64_t,
1011 class NumberUnsignedType = std::uint64_t,
1012 class NumberFloatType = double,
1013 template<
typename U>
class AllocatorType = std::allocator,
1014 template<
typename T,
typename SFINAE =
void>
class JSONSerializer =
adl_serializer 1022 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
1023 AllocatorType, JSONSerializer>;
1031 template<
typename T,
typename SFINAE>
1060 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
1062 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
1111 result[
"copyright"] =
"(C) 2013-2017 Niels Lohmann";
1112 result[
"name"] =
"JSON for Modern C++";
1113 result[
"url"] =
"https://github.com/nlohmann/json";
1116 {
"string",
"2.1.1"},
1123 result[
"platform"] =
"win32";
1124 #elif defined __linux__ 1125 result[
"platform"] =
"linux";
1126 #elif defined __APPLE__ 1127 result[
"platform"] =
"apple";
1128 #elif defined __unix__ 1129 result[
"platform"] =
"unix";
1131 result[
"platform"] =
"unknown";
1134 #if defined(__clang__) 1135 result[
"compiler"] = {{
"family",
"clang"}, {
"version", __clang_version__}};
1136 #elif defined(__ICC) || defined(__INTEL_COMPILER) 1137 result[
"compiler"] = {{
"family",
"icc"}, {
"version", __INTEL_COMPILER}};
1138 #elif defined(__GNUC__) || defined(__GNUG__) 1139 result[
"compiler"] = {{
"family",
"gcc"}, {
"version", std::to_string(__GNUC__) +
"." + std::to_string(__GNUC_MINOR__) +
"." + std::to_string(__GNUC_PATCHLEVEL__)}};
1140 #elif defined(__HP_cc) || defined(__HP_aCC) 1141 result[
"compiler"] =
"hp" 1142 #elif defined(__IBMCPP__) 1143 result[
"compiler"] = {{
"family",
"ilecpp"}, {
"version", __IBMCPP__}};
1144 #elif defined(_MSC_VER) 1145 result[
"compiler"] = {{
"family",
"msvc"}, {
"version", _MSC_VER}};
1146 #elif defined(__PGI) 1147 result[
"compiler"] = {{
"family",
"pgcpp"}, {
"version", __PGI}};
1148 #elif defined(__SUNPRO_CC) 1149 result[
"compiler"] = {{
"family",
"sunpro"}, {
"version", __SUNPRO_CC}};
1151 result[
"compiler"] = {{
"family",
"unknown"}, {
"version",
"unknown"}};
1155 result[
"compiler"][
"c++"] = std::to_string(__cplusplus);
1157 result[
"compiler"][
"c++"] =
"unknown";
1255 using object_t = ObjectType<StringType,
1257 std::less<StringType>,
1258 AllocatorType<std::pair<
const StringType,
1305 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
1602 template<
typename T,
typename... Args>
1603 static T* create(Args&& ... args)
1605 AllocatorType<T> alloc;
1606 auto deleter = [&](T *
object)
1608 alloc.deallocate(
object, 1);
1610 std::unique_ptr<T, decltype(deleter)>
object(alloc.allocate(1), deleter);
1611 alloc.construct(
object.
get(), std::forward<Args>(args)...);
1612 assert(
object !=
nullptr);
1613 return object.release();
1662 json_value() =
default;
1678 object = create<object_t>();
1684 array = create<array_t>();
1690 string = create<string_t>(
"");
1727 JSON_THROW(std::domain_error(
"961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1"));
1737 string = create<string_t>(value);
1743 object = create<object_t>(value);
1747 json_value(
const array_t& value)
1749 array = create<array_t>(value);
1762 void assert_invariant()
const 1854 basic_json& parsed)>;
1894 : m_type(value_type), m_value(value_type)
1976 template<
typename CompatibleType,
typename U = detail::uncvref_t<CompatibleType>,
1977 detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
1978 not std::is_same<U, basic_json_t>::value and
1979 not detail::is_basic_json_nested_type<
1980 basic_json_t, U>::value and
1981 detail::has_to_json<basic_json, U>::value,
1984 std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
2060 bool type_deduction =
true,
2065 bool is_an_object = std::all_of(init.begin(), init.end(),
2068 return element.is_array() and element.size() == 2 and element[0].is_string();
2072 if (not type_deduction)
2077 is_an_object =
false;
2083 JSON_THROW(std::domain_error(
"cannot create object from initializer list"));
2093 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
2095 m_value.object->emplace(*(element[0].m_value.string), element[1]);
2102 m_value.array = create<array_t>(init);
2143 std::initializer_list<basic_json>())
2183 std::initializer_list<basic_json>())
2209 m_value.array = create<array_t>(cnt, val);
2250 template<
class InputIT,
typename std::enable_if<
2251 std::is_same<InputIT, typename basic_json_t::iterator>::value or
2252 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
2255 assert(first.m_object !=
nullptr);
2256 assert(last.m_object !=
nullptr);
2259 if (first.m_object != last.m_object)
2261 JSON_THROW(std::domain_error(
"iterators are not compatible"));
2265 m_type = first.m_object->m_type;
2276 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
2278 JSON_THROW(std::out_of_range(
"iterators out of range"));
2293 m_value.number_integer = first.m_object->m_value.number_integer;
2299 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2305 m_value.number_float = first.m_object->m_value.number_float;
2311 m_value.boolean = first.m_object->m_value.boolean;
2317 m_value = *first.m_object->m_value.string;
2323 m_value.object = create<object_t>(first.m_it.object_iterator,
2324 last.m_it.object_iterator);
2330 m_value.array = create<array_t>(first.m_it.array_iterator,
2331 last.m_it.array_iterator);
2337 JSON_THROW(std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name()));
2375 *
this = parser(i, cb).parse();
2406 : m_type(other.m_type)
2409 other.assert_invariant();
2415 m_value = *other.m_value.object;
2421 m_value = *other.m_value.array;
2427 m_value = *other.m_value.string;
2433 m_value = other.m_value.boolean;
2439 m_value = other.m_value.number_integer;
2445 m_value = other.m_value.number_unsigned;
2451 m_value = other.m_value.number_float;
2483 : m_type(std::move(other.m_type)),
2484 m_value(std::move(other.m_value))
2487 other.assert_invariant();
2520 std::is_nothrow_move_constructible<value_t>::value and
2521 std::is_nothrow_move_assignable<value_t>::value and
2522 std::is_nothrow_move_constructible<json_value>::value and
2523 std::is_nothrow_move_assignable<json_value>::value
2527 other.assert_invariant();
2530 swap(m_type, other.m_type);
2531 swap(m_value, other.m_value);
2560 AllocatorType<object_t> alloc;
2561 alloc.destroy(m_value.object);
2562 alloc.deallocate(m_value.object, 1);
2568 AllocatorType<array_t> alloc;
2569 alloc.destroy(m_value.array);
2570 alloc.deallocate(m_value.array, 1);
2576 AllocatorType<string_t> alloc;
2577 alloc.destroy(m_value.string);
2578 alloc.deallocate(m_value.string, 1);
2626 std::stringstream ss;
2630 dump(ss,
true, static_cast<unsigned int>(indent));
2690 return is_null() or is_string() or is_boolean() or is_number();
2717 return is_array() or is_object();
2791 return is_number_integer() or is_number_float();
3007 return m_value.boolean;
3010 JSON_THROW(std::domain_error(
"type must be boolean, but is " + type_name()));
3016 return is_object() ? m_value.object :
nullptr;
3022 return is_object() ? m_value.object :
nullptr;
3028 return is_array() ? m_value.array :
nullptr;
3032 constexpr
const array_t* get_impl_ptr(
const array_t* )
const noexcept
3034 return is_array() ? m_value.array :
nullptr;
3040 return is_string() ? m_value.string :
nullptr;
3046 return is_string() ? m_value.string :
nullptr;
3052 return is_boolean() ? &m_value.boolean :
nullptr;
3058 return is_boolean() ? &m_value.boolean :
nullptr;
3064 return is_number_integer() ? &m_value.number_integer :
nullptr;
3070 return is_number_integer() ? &m_value.number_integer :
nullptr;
3076 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
3082 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
3088 return is_number_float() ? &m_value.number_float :
nullptr;
3094 return is_number_float() ? &m_value.number_float :
nullptr;
3108 template<
typename ReferenceType,
typename ThisType>
3109 static ReferenceType get_ref_impl(ThisType& obj)
3112 using PointerType =
typename std::add_pointer<ReferenceType>::type;
3115 auto ptr = obj.template get_ptr<PointerType>();
3122 JSON_THROW(std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
3146 typename BasicJsonType,
3195 typename ValueTypeCV,
3198 not std::is_same<basic_json_t, ValueType>::value and
3202 ValueType
get()
const noexcept(noexcept(
3208 static_assert(not std::is_reference<ValueTypeCV>::value,
3209 "get() cannot be used with reference types, you might want to use get_ref()");
3210 static_assert(std::is_default_constructible<ValueType>::value,
3211 "types must be DefaultConstructible when used with get()");
3250 typename ValueTypeCV,
3254 ValueType>::value,
int> = 0 >
3255 ValueType
get()
const noexcept(noexcept(
3258 static_assert(not std::is_reference<ValueTypeCV>::value,
3259 "get() cannot be used with reference types, you might want to use get_ref()");
3290 template<
typename PointerType,
typename std::enable_if<
3291 std::is_pointer<PointerType>::value,
int>::type = 0>
3292 PointerType
get() noexcept
3295 return get_ptr<PointerType>();
3302 template<
typename PointerType,
typename std::enable_if<
3303 std::is_pointer<PointerType>::value,
int>::type = 0>
3304 constexpr
const PointerType
get()
const noexcept
3307 return get_ptr<PointerType>();
3336 template<
typename PointerType,
typename std::enable_if<
3337 std::is_pointer<PointerType>::value,
int>::type = 0>
3341 using pointee_t =
typename std::remove_const<
typename 3342 std::remove_pointer<
typename 3343 std::remove_const<PointerType>::type>::type>::type;
3346 std::is_same<object_t, pointee_t>::value
3347 or std::is_same<array_t, pointee_t>::value
3348 or std::is_same<string_t, pointee_t>::value
3349 or std::is_same<boolean_t, pointee_t>::value
3350 or std::is_same<number_integer_t, pointee_t>::value
3351 or std::is_same<number_unsigned_t, pointee_t>::value
3352 or std::is_same<number_float_t, pointee_t>::value
3353 ,
"incompatible pointer type");
3356 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3363 template<
typename PointerType,
typename std::enable_if<
3364 std::is_pointer<PointerType>::value and
3365 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3366 constexpr
const PointerType
get_ptr() const noexcept
3369 using pointee_t =
typename std::remove_const<
typename 3370 std::remove_pointer<
typename 3371 std::remove_const<PointerType>::type>::type>::type;
3374 std::is_same<object_t, pointee_t>::value
3375 or std::is_same<array_t, pointee_t>::value
3376 or std::is_same<string_t, pointee_t>::value
3377 or std::is_same<boolean_t, pointee_t>::value
3378 or std::is_same<number_integer_t, pointee_t>::value
3379 or std::is_same<number_unsigned_t, pointee_t>::value
3380 or std::is_same<number_float_t, pointee_t>::value
3381 ,
"incompatible pointer type");
3384 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3413 template<
typename ReferenceType,
typename std::enable_if<
3414 std::is_reference<ReferenceType>::value,
int>::type = 0>
3418 return get_ref_impl<ReferenceType>(*this);
3425 template<
typename ReferenceType,
typename std::enable_if<
3426 std::is_reference<ReferenceType>::value and
3427 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3431 return get_ref_impl<ReferenceType>(*this);
3462 template <
typename ValueType,
typename std::enable_if <
3463 not std::is_pointer<ValueType>::value and
3464 not std::is_same<ValueType, typename string_t::value_type>::value
3465 #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 3466 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3469 operator ValueType()
const 3472 return get<ValueType>();
3515 return m_value.array->at(idx);
3520 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
3525 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3558 return m_value.array->at(idx);
3563 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
3568 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3605 return m_value.object->at(key);
3610 JSON_THROW(std::out_of_range(
"key '" + key +
"' not found"));
3615 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3652 return m_value.object->at(key);
3657 JSON_THROW(std::out_of_range(
"key '" + key +
"' not found"));
3662 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3697 m_value.array = create<array_t>();
3705 if (idx >= m_value.array->size())
3707 m_value.array->insert(m_value.array->end(),
3708 idx - m_value.array->size() + 1,
3712 return m_value.array->operator[](idx);
3715 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3742 return m_value.
array->operator[](idx);
3745 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3781 m_value.object = create<object_t>();
3788 return m_value.object->operator[](key);
3791 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3829 assert(m_value.object->find(key) != m_value.object->end());
3833 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3863 template<
typename T, std::
size_t n>
3866 return operator[](static_cast<const T>(key));
3898 template<
typename T, std::
size_t n>
3901 return operator[](static_cast<const T>(key));
3931 template<
typename T>
3945 return m_value.object->operator[](key);
3948 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3981 template<
typename T>
3987 assert(m_value.object->find(key) != m_value.object->end());
3991 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
4042 template<
class ValueType,
typename std::enable_if<
4043 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
4044 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 4050 const auto it = find(key);
4056 return default_value;
4060 JSON_THROW(std::domain_error(
"cannot use value() with " + type_name()));
4068 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 4070 return value(key,
string_t(default_value));
4114 template<
class ValueType,
typename std::enable_if<
4115 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
4124 return ptr.get_checked(
this);
4128 return default_value;
4132 JSON_THROW(std::domain_error(
"cannot use value() with " + type_name()));
4141 return value(ptr,
string_t(default_value));
4274 template<
class IteratorType,
typename std::enable_if<
4275 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4276 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4281 if (
this != pos.m_object)
4283 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
4286 IteratorType result = end();
4296 if (not pos.m_it.primitive_iterator.is_begin())
4298 JSON_THROW(std::out_of_range(
"iterator out of range"));
4303 AllocatorType<string_t> alloc;
4304 alloc.destroy(m_value.string);
4305 alloc.deallocate(m_value.string, 1);
4306 m_value.string =
nullptr;
4316 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4322 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4328 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4381 template<
class IteratorType,
typename std::enable_if<
4382 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4383 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4385 IteratorType
erase(IteratorType first, IteratorType last)
4388 if (
this != first.m_object or
this != last.m_object)
4390 JSON_THROW(std::domain_error(
"iterators do not fit current value"));
4393 IteratorType result = end();
4403 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4405 JSON_THROW(std::out_of_range(
"iterators out of range"));
4410 AllocatorType<string_t> alloc;
4411 alloc.destroy(m_value.string);
4412 alloc.deallocate(m_value.string, 1);
4413 m_value.string =
nullptr;
4423 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4424 last.m_it.object_iterator);
4430 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4431 last.m_it.array_iterator);
4437 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4478 return m_value.object->erase(key);
4481 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4515 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
4518 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4522 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4560 auto result = end();
4564 result.m_it.object_iterator = m_value.object->find(key);
4576 auto result = cend();
4580 result.m_it.object_iterator = m_value.object->find(key);
4610 return is_object() ? m_value.object->count(key) : 0;
4898 template<
typename IteratorType>
class iteration_proxy;
4914 return iteration_proxy<iterator>(cont);
4922 return iteration_proxy<const_iterator>(cont);
4985 return m_value.array->empty();
4991 return m_value.object->empty();
5053 return m_value.array->size();
5059 return m_value.object->size();
5113 return m_value.array->max_size();
5119 return m_value.object->max_size();
5168 m_value.number_integer = 0;
5174 m_value.number_unsigned = 0;
5180 m_value.number_float = 0.0;
5186 m_value.boolean =
false;
5192 m_value.string->clear();
5198 m_value.array->clear();
5204 m_value.object->clear();
5238 if (not(is_null() or is_array()))
5240 JSON_THROW(std::domain_error(
"cannot use push_back() with " + type_name()));
5252 m_value.array->push_back(std::move(val));
5263 push_back(std::move(val));
5274 if (not(is_null() or is_array()))
5276 JSON_THROW(std::domain_error(
"cannot use push_back() with " + type_name()));
5288 m_value.array->push_back(val);
5324 if (not(is_null() or is_object()))
5326 JSON_THROW(std::domain_error(
"cannot use push_back() with " + type_name()));
5338 m_value.object->insert(val);
5378 if (is_object() and init.size() == 2 and init.begin()->is_string())
5380 const string_t key = *init.begin();
5381 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5420 template<
class... Args>
5424 if (not(is_null() or is_array()))
5426 JSON_THROW(std::domain_error(
"cannot use emplace_back() with " + type_name()));
5438 m_value.array->emplace_back(std::forward<Args>(args)...);
5468 template<
class... Args>
5469 std::pair<iterator, bool>
emplace(Args&& ... args)
5472 if (not(is_null() or is_object()))
5474 JSON_THROW(std::domain_error(
"cannot use emplace() with " + type_name()));
5486 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5489 it.m_it.object_iterator =
res.first;
5492 return {it,
res.second};
5523 if (pos.m_object !=
this)
5525 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5530 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5534 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5543 return insert(pos, val);
5576 if (pos.m_object !=
this)
5578 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5583 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5587 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5625 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5629 if (pos.m_object !=
this)
5631 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5635 if (first.m_object != last.m_object)
5637 JSON_THROW(std::domain_error(
"iterators do not fit"));
5640 if (first.m_object ==
this or last.m_object ==
this)
5642 JSON_THROW(std::domain_error(
"passed iterators may not belong to container"));
5647 result.m_it.array_iterator = m_value.array->insert(
5648 pos.m_it.array_iterator,
5649 first.m_it.array_iterator,
5650 last.m_it.array_iterator);
5683 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5687 if (pos.m_object !=
this)
5689 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5694 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5716 std::is_nothrow_move_constructible<value_t>::value and
5717 std::is_nothrow_move_assignable<value_t>::value and
5718 std::is_nothrow_move_constructible<json_value>::value and
5719 std::is_nothrow_move_assignable<json_value>::value
5756 JSON_THROW(std::domain_error(
"cannot use swap() with " + type_name()));
5789 JSON_THROW(std::domain_error(
"cannot use swap() with " + type_name()));
5822 JSON_THROW(std::domain_error(
"cannot use swap() with " + type_name()));
5861 const auto lhs_type = lhs.type();
5862 const auto rhs_type = rhs.type();
5864 if (lhs_type == rhs_type)
5870 return *lhs.m_value.array == *rhs.m_value.array;
5874 return *lhs.m_value.object == *rhs.m_value.object;
5882 return *lhs.m_value.string == *rhs.m_value.string;
5886 return lhs.m_value.boolean == rhs.m_value.boolean;
5890 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5894 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5898 return lhs.m_value.number_float == rhs.m_value.number_float;
5908 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5912 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5916 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5920 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5924 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5928 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
5938 template<
typename ScalarType,
typename std::enable_if<
5939 std::is_scalar<ScalarType>::value,
int>::type = 0>
5949 template<
typename ScalarType,
typename std::enable_if<
5950 std::is_scalar<ScalarType>::value,
int>::type = 0>
5974 return not (lhs == rhs);
5981 template<
typename ScalarType,
typename std::enable_if<
5982 std::is_scalar<ScalarType>::value,
int>::type = 0>
5992 template<
typename ScalarType,
typename std::enable_if<
5993 std::is_scalar<ScalarType>::value,
int>::type = 0>
6025 const auto lhs_type = lhs.type();
6026 const auto rhs_type = rhs.type();
6028 if (lhs_type == rhs_type)
6034 return *lhs.m_value.array < *rhs.m_value.array;
6038 return *lhs.m_value.object < *rhs.m_value.object;
6046 return *lhs.m_value.string < *rhs.m_value.string;
6050 return lhs.m_value.boolean < rhs.m_value.boolean;
6054 return lhs.m_value.number_integer < rhs.m_value.number_integer;
6058 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
6062 return lhs.m_value.number_float < rhs.m_value.number_float;
6072 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6076 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
6080 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6084 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
6088 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6092 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6120 return not (rhs < lhs);
6142 return not (lhs <= rhs);
6164 return not (lhs < rhs);
6202 const bool pretty_print = (o.width() > 0);
6203 const auto indentation = (pretty_print ? o.width() : 0);
6209 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
6260 template<
class T, std::
size_t N>
6265 return parse(std::begin(
array), std::end(
array), cb);
6295 template<
typename CharT,
typename std::enable_if<
6296 std::is_pointer<CharT>::value and
6297 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6298 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
6302 return parser(reinterpret_cast<const char*>(s), cb).
parse();
6332 return parser(i, cb).
parse();
6341 return parser(i, cb).
parse();
6385 template<
class IteratorType,
typename std::enable_if<
6387 std::random_access_iterator_tag,
6388 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6394 assert(std::accumulate(first, last, std::pair<bool, int>(
true, 0),
6395 [&first](std::pair<bool, int>
res, decltype(*first) val)
6397 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6402 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6403 "each element in the iterator range must have the size of 1 byte");
6407 if (std::distance(first, last) <= 0)
6409 return parser(
"").parse();
6412 return parser(first, last, cb).parse();
6455 template<
class ContiguousContainer,
typename std::enable_if<
6456 not std::is_pointer<ContiguousContainer>::value and
6458 std::random_access_iterator_tag,
6459 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6465 return parse(std::begin(c), std::end(c), cb);
6493 j = parser(i).
parse();
6503 j = parser(i).
parse();
6522 template<
typename T>
6523 static void add_to_vector(std::vector<uint8_t>& vec,
size_t bytes,
const T number)
6525 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6531 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 070) & 0xff));
6532 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 060) & 0xff));
6533 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 050) & 0xff));
6534 vec.push_back(static_cast<uint8_t>((static_cast<uint64_t>(number) >> 040) & 0xff));
6535 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6536 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6537 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6538 vec.push_back(static_cast<uint8_t>(number & 0xff));
6544 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6545 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6546 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6547 vec.push_back(static_cast<uint8_t>(number & 0xff));
6553 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6554 vec.push_back(static_cast<uint8_t>(number & 0xff));
6560 vec.push_back(static_cast<uint8_t>(number & 0xff));
6602 template<
typename T>
6603 static T get_from_vector(
const std::vector<uint8_t>& vec,
const size_t current_index)
6605 if (current_index +
sizeof(T) + 1 > vec.size())
6607 JSON_THROW(std::out_of_range(
"cannot read " + std::to_string(
sizeof(T)) +
" bytes from vector"));
6611 auto* ptr =
reinterpret_cast<uint8_t*
>(&result);
6612 for (
size_t i = 0; i <
sizeof(T); ++i)
6614 *ptr++ = vec[current_index +
sizeof(T) - i];
6629 static void to_msgpack_internal(
const basic_json& j, std::vector<uint8_t>& v)
6643 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6649 if (j.m_value.number_integer >= 0)
6655 if (j.m_value.number_unsigned < 128)
6658 add_to_vector(v, 1, j.m_value.number_unsigned);
6660 else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6664 add_to_vector(v, 1, j.m_value.number_unsigned);
6666 else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6670 add_to_vector(v, 2, j.m_value.number_unsigned);
6672 else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6676 add_to_vector(v, 4, j.m_value.number_unsigned);
6678 else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6682 add_to_vector(v, 8, j.m_value.number_unsigned);
6687 if (j.m_value.number_integer >= -32)
6690 add_to_vector(v, 1, j.m_value.number_integer);
6692 else if (j.m_value.number_integer >= std::numeric_limits<int8_t>::min() and j.m_value.number_integer <= std::numeric_limits<int8_t>::max())
6696 add_to_vector(v, 1, j.m_value.number_integer);
6698 else if (j.m_value.number_integer >= std::numeric_limits<int16_t>::min() and j.m_value.number_integer <= std::numeric_limits<int16_t>::max())
6702 add_to_vector(v, 2, j.m_value.number_integer);
6704 else if (j.m_value.number_integer >= std::numeric_limits<int32_t>::min() and j.m_value.number_integer <= std::numeric_limits<int32_t>::max())
6708 add_to_vector(v, 4, j.m_value.number_integer);
6710 else if (j.m_value.number_integer >= std::numeric_limits<int64_t>::min() and j.m_value.number_integer <= std::numeric_limits<int64_t>::max())
6714 add_to_vector(v, 8, j.m_value.number_integer);
6722 if (j.m_value.number_unsigned < 128)
6725 add_to_vector(v, 1, j.m_value.number_unsigned);
6727 else if (j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6731 add_to_vector(v, 1, j.m_value.number_unsigned);
6733 else if (j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6737 add_to_vector(v, 2, j.m_value.number_unsigned);
6739 else if (j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6743 add_to_vector(v, 4, j.m_value.number_unsigned);
6745 else if (j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6749 add_to_vector(v, 8, j.m_value.number_unsigned);
6758 const auto* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6759 for (
size_t i = 0; i < 8; ++i)
6761 v.push_back(helper[7 - i]);
6768 const auto N = j.m_value.string->size();
6772 v.push_back(static_cast<uint8_t>(0xa0 | N));
6778 add_to_vector(v, 1, N);
6780 else if (N <= 65535)
6784 add_to_vector(v, 2, N);
6786 else if (N <= 4294967295)
6790 add_to_vector(v, 4, N);
6794 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6795 std::back_inserter(v));
6801 const auto N = j.m_value.array->size();
6805 v.push_back(static_cast<uint8_t>(0x90 | N));
6807 else if (N <= 0xffff)
6811 add_to_vector(v, 2, N);
6813 else if (N <= 0xffffffff)
6817 add_to_vector(v, 4, N);
6821 for (
const auto& el : *j.m_value.array)
6823 to_msgpack_internal(el, v);
6830 const auto N = j.m_value.object->size();
6834 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6836 else if (N <= 65535)
6840 add_to_vector(v, 2, N);
6842 else if (N <= 4294967295)
6846 add_to_vector(v, 4, N);
6850 for (
const auto& el : *j.m_value.object)
6852 to_msgpack_internal(el.first, v);
6853 to_msgpack_internal(el.second, v);
6875 static void to_cbor_internal(
const basic_json& j, std::vector<uint8_t>& v)
6887 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6893 if (j.m_value.number_integer >= 0)
6898 if (j.m_value.number_integer <= 0x17)
6900 add_to_vector(v, 1, j.m_value.number_integer);
6902 else if (j.m_value.number_integer <= std::numeric_limits<uint8_t>::max())
6906 add_to_vector(v, 1, j.m_value.number_integer);
6908 else if (j.m_value.number_integer <= std::numeric_limits<uint16_t>::max())
6912 add_to_vector(v, 2, j.m_value.number_integer);
6914 else if (j.m_value.number_integer <= std::numeric_limits<uint32_t>::max())
6918 add_to_vector(v, 4, j.m_value.number_integer);
6924 add_to_vector(v, 8, j.m_value.number_integer);
6931 const auto positive_number = -1 - j.m_value.number_integer;
6932 if (j.m_value.number_integer >= -24)
6934 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6936 else if (positive_number <= std::numeric_limits<uint8_t>::max())
6940 add_to_vector(v, 1, positive_number);
6942 else if (positive_number <= std::numeric_limits<uint16_t>::max())
6946 add_to_vector(v, 2, positive_number);
6948 else if (positive_number <= std::numeric_limits<uint32_t>::max())
6952 add_to_vector(v, 4, positive_number);
6958 add_to_vector(v, 8, positive_number);
6966 if (j.m_value.number_unsigned <= 0x17)
6968 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
6970 else if (j.m_value.number_unsigned <= 0xff)
6974 add_to_vector(v, 1, j.m_value.number_unsigned);
6976 else if (j.m_value.number_unsigned <= 0xffff)
6980 add_to_vector(v, 2, j.m_value.number_unsigned);
6982 else if (j.m_value.number_unsigned <= 0xffffffff)
6986 add_to_vector(v, 4, j.m_value.number_unsigned);
6988 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
6992 add_to_vector(v, 8, j.m_value.number_unsigned);
7001 const auto* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
7002 for (
size_t i = 0; i < 8; ++i)
7004 v.push_back(helper[7 - i]);
7011 const auto N = j.m_value.string->size();
7014 v.push_back(0x60 + static_cast<uint8_t>(N));
7019 add_to_vector(v, 1, N);
7021 else if (N <= 0xffff)
7024 add_to_vector(v, 2, N);
7026 else if (N <= 0xffffffff)
7029 add_to_vector(v, 4, N);
7032 else if (N <= 0xffffffffffffffff)
7035 add_to_vector(v, 8, N);
7040 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
7041 std::back_inserter(v));
7047 const auto N = j.m_value.array->size();
7050 v.push_back(0x80 + static_cast<uint8_t>(N));
7055 add_to_vector(v, 1, N);
7057 else if (N <= 0xffff)
7060 add_to_vector(v, 2, N);
7062 else if (N <= 0xffffffff)
7065 add_to_vector(v, 4, N);
7068 else if (N <= 0xffffffffffffffff)
7071 add_to_vector(v, 8, N);
7076 for (
const auto& el : *j.m_value.array)
7078 to_cbor_internal(el, v);
7085 const auto N = j.m_value.object->size();
7088 v.push_back(0xa0 + static_cast<uint8_t>(N));
7093 add_to_vector(v, 1, N);
7095 else if (N <= 0xffff)
7098 add_to_vector(v, 2, N);
7100 else if (N <= 0xffffffff)
7103 add_to_vector(v, 4, N);
7106 else if (N <= 0xffffffffffffffff)
7109 add_to_vector(v, 8, N);
7114 for (
const auto& el : *j.m_value.object)
7116 to_cbor_internal(el.first, v);
7117 to_cbor_internal(el.second, v);
7152 static void check_length(
const size_t size,
const size_t len,
const size_t offset)
7155 if (len > size or offset > size)
7157 JSON_THROW(std::out_of_range(
"len out of range"));
7161 if ((size > (std::numeric_limits<size_t>::max() - offset)))
7163 JSON_THROW(std::out_of_range(
"len+offset out of range"));
7167 if (len + offset > size)
7169 JSON_THROW(std::out_of_range(
"len+offset out of range"));
7187 static basic_json from_msgpack_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7190 check_length(v.size(), 1, idx);
7193 const size_t current_idx = idx++;
7195 if (v[current_idx] <= 0xbf)
7197 if (v[current_idx] <= 0x7f)
7199 return v[current_idx];
7201 if (v[current_idx] <= 0x8f)
7204 const size_t len = v[current_idx] & 0x0f;
7205 for (
size_t i = 0; i < len; ++i)
7208 result[key] = from_msgpack_internal(v, idx);
7212 else if (v[current_idx] <= 0x9f)
7215 const size_t len = v[current_idx] & 0x0f;
7216 for (
size_t i = 0; i < len; ++i)
7218 result.
push_back(from_msgpack_internal(v, idx));
7224 const size_t len = v[current_idx] & 0x1f;
7225 const size_t offset = current_idx + 1;
7227 check_length(v.size(), len, offset);
7228 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7231 else if (v[current_idx] >= 0xe0)
7233 return static_cast<int8_t
>(v[current_idx]);
7237 switch (v[current_idx])
7258 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7260 reinterpret_cast<uint8_t*
>(&
res)[
sizeof(
float) - byte - 1] = v.at(current_idx + 1 + byte);
7262 idx +=
sizeof(float);
7270 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7272 reinterpret_cast<uint8_t*
>(&
res)[
sizeof(
double) - byte - 1] = v.at(current_idx + 1 + byte);
7274 idx +=
sizeof(double);
7281 return get_from_vector<uint8_t>(v, current_idx);
7287 return get_from_vector<uint16_t>(v, current_idx);
7293 return get_from_vector<uint32_t>(v, current_idx);
7299 return get_from_vector<uint64_t>(v, current_idx);
7305 return get_from_vector<int8_t>(v, current_idx);
7311 return get_from_vector<int16_t>(v, current_idx);
7317 return get_from_vector<int32_t>(v, current_idx);
7323 return get_from_vector<int64_t>(v, current_idx);
7328 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7329 const size_t offset = current_idx + 2;
7331 check_length(v.size(), len, offset);
7332 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7337 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7338 const size_t offset = current_idx + 3;
7340 check_length(v.size(), len, offset);
7341 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7346 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7347 const size_t offset = current_idx + 5;
7349 check_length(v.size(), len, offset);
7350 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7356 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7358 for (
size_t i = 0; i < len; ++i)
7360 result.
push_back(from_msgpack_internal(v, idx));
7368 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7370 for (
size_t i = 0; i < len; ++i)
7372 result.
push_back(from_msgpack_internal(v, idx));
7380 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7382 for (
size_t i = 0; i < len; ++i)
7385 result[key] = from_msgpack_internal(v, idx);
7393 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7395 for (
size_t i = 0; i < len; ++i)
7398 result[key] = from_msgpack_internal(v, idx);
7405 JSON_THROW(std::invalid_argument(
"error parsing a msgpack @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx]))));
7425 static basic_json from_cbor_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7428 const size_t current_idx = idx++;
7430 switch (v.at(current_idx))
7458 return v[current_idx];
7464 return get_from_vector<uint8_t>(v, current_idx);
7470 return get_from_vector<uint16_t>(v, current_idx);
7476 return get_from_vector<uint32_t>(v, current_idx);
7482 return get_from_vector<uint64_t>(v, current_idx);
7511 return static_cast<int8_t
>(0x20 - 1 - v[current_idx]);
7518 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7524 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7530 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7536 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7565 const auto len =
static_cast<size_t>(v[current_idx] - 0x60);
7566 const size_t offset = current_idx + 1;
7568 check_length(v.size(), len, offset);
7569 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7574 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7575 const size_t offset = current_idx + 2;
7577 check_length(v.size(), len, offset);
7578 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7583 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7584 const size_t offset = current_idx + 3;
7586 check_length(v.size(), len, offset);
7587 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7592 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7593 const size_t offset = current_idx + 5;
7595 check_length(v.size(), len, offset);
7596 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7601 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7602 const size_t offset = current_idx + 9;
7604 check_length(v.size(), len, offset);
7605 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7611 while (v.at(idx) != 0xff)
7613 string_t s = from_cbor_internal(v, idx);
7648 const auto len =
static_cast<size_t>(v[current_idx] - 0x80);
7649 for (
size_t i = 0; i < len; ++i)
7651 result.
push_back(from_cbor_internal(v, idx));
7659 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7661 for (
size_t i = 0; i < len; ++i)
7663 result.
push_back(from_cbor_internal(v, idx));
7671 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7673 for (
size_t i = 0; i < len; ++i)
7675 result.
push_back(from_cbor_internal(v, idx));
7683 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7685 for (
size_t i = 0; i < len; ++i)
7687 result.
push_back(from_cbor_internal(v, idx));
7695 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7697 for (
size_t i = 0; i < len; ++i)
7699 result.
push_back(from_cbor_internal(v, idx));
7707 while (v.at(idx) != 0xff)
7709 result.
push_back(from_cbor_internal(v, idx));
7743 const auto len =
static_cast<size_t>(v[current_idx] - 0xa0);
7744 for (
size_t i = 0; i < len; ++i)
7747 result[key] = from_cbor_internal(v, idx);
7755 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7757 for (
size_t i = 0; i < len; ++i)
7760 result[key] = from_cbor_internal(v, idx);
7768 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7770 for (
size_t i = 0; i < len; ++i)
7773 result[key] = from_cbor_internal(v, idx);
7781 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7783 for (
size_t i = 0; i < len; ++i)
7786 result[key] = from_cbor_internal(v, idx);
7794 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7796 for (
size_t i = 0; i < len; ++i)
7799 result[key] = from_cbor_internal(v, idx);
7807 while (v.at(idx) != 0xff)
7810 result[key] = from_cbor_internal(v, idx);
7843 const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7844 const int exp = (half >> 10) & 0x1f;
7845 const int mant = half & 0x3ff;
7849 val = std::ldexp(mant, -24);
7853 val = std::ldexp(mant + 1024, exp - 25);
7858 ? std::numeric_limits<double>::infinity()
7859 : std::numeric_limits<double>::quiet_NaN();
7861 return (half & 0x8000) != 0 ? -val : val;
7868 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7870 reinterpret_cast<uint8_t*
>(&
res)[
sizeof(
float) - byte - 1] = v.at(current_idx + 1 + byte);
7872 idx +=
sizeof(float);
7880 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7882 reinterpret_cast<uint8_t*
>(&
res)[
sizeof(
double) - byte - 1] = v.at(current_idx + 1 + byte);
7884 idx +=
sizeof(double);
7890 JSON_THROW(std::invalid_argument(
"error parsing a CBOR @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx]))));
7920 std::vector<uint8_t> result;
7921 to_msgpack_internal(j, result);
7952 const size_t start_index = 0)
7954 size_t i = start_index;
7955 return from_msgpack_internal(v, i);
7983 std::vector<uint8_t> result;
7984 to_cbor_internal(j, result);
8015 const size_t start_index = 0)
8017 size_t i = start_index;
8018 return from_cbor_internal(v, i);
8074 static std::size_t extra_space(
const string_t& s) noexcept
8076 return std::accumulate(s.begin(), s.end(),
size_t{},
8077 [](
size_t res,
typename string_t::value_type c)
8095 if (c >= 0x00 and c <= 0x1f)
8122 const auto space = extra_space(s);
8129 string_t result(s.size() + space,
'\\');
8130 std::size_t pos = 0;
8132 for (
const auto& c : s)
8139 result[pos + 1] =
'"';
8155 result[pos + 1] =
'b';
8163 result[pos + 1] =
'f';
8171 result[pos + 1] =
'n';
8179 result[pos + 1] =
'r';
8187 result[pos + 1] =
't';
8194 if (c >= 0x00 and c <= 0x1f)
8198 static const char hexify[16] =
8200 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
8201 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 8206 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
8234 template<
typename NumberType>
8235 numtostr(NumberType value)
8237 x_write(value, std::is_integral<NumberType>());
8240 const char* c_str()
const 8242 return m_buf.data();
8247 std::array < char, 64 > m_buf{{}};
8249 template<
typename NumberType>
8250 void x_write(NumberType x, std::true_type)
8259 const bool is_negative = x < 0;
8263 while (x != 0 and i < m_buf.size() - 1)
8265 const auto digit = std::labs(static_cast<long>(x % 10));
8266 m_buf[i++] =
static_cast<char>(
'0' + digit);
8276 assert(i < m_buf.size() - 2);
8280 std::reverse(m_buf.begin(), m_buf.begin() + i);
8283 template<
typename NumberType>
8284 void x_write(NumberType x, std::false_type)
8290 if (std::signbit(x))
8301 static constexpr
auto d = std::numeric_limits<NumberType>::digits10;
8304 const auto written_bytes = snprintf(m_buf.data(), m_buf.size(),
"%.*g", d, (double)x);
8307 assert(written_bytes > 0);
8309 assert(static_cast<size_t>(written_bytes) < m_buf.size());
8312 const auto loc = localeconv();
8313 assert(loc !=
nullptr);
8314 const char thousands_sep = !loc->thousands_sep ?
'\0' 8315 : loc->thousands_sep[0];
8317 const char decimal_point = !loc->decimal_point ?
'\0' 8318 : loc->decimal_point[0];
8321 if (thousands_sep !=
'\0')
8323 const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);
8324 std::fill(end, m_buf.end(),
'\0');
8328 if (decimal_point !=
'\0' and decimal_point !=
'.')
8330 for (
auto& c : m_buf)
8332 if (c == decimal_point)
8342 bool value_is_int_like =
true;
8343 for (i = 0; i < m_buf.size(); ++i)
8346 if (m_buf[i] ==
'\0')
8352 value_is_int_like = value_is_int_like and m_buf[i] !=
'.' and
8353 m_buf[i] !=
'e' and m_buf[i] !=
'E';
8356 if (value_is_int_like)
8359 assert((i + 2) < m_buf.size());
8361 assert(m_buf[i] ==
'\0');
8362 assert(m_buf[i - 1] !=
'\0');
8369 assert(m_buf[i + 2] ==
'\0');
8392 void dump(std::ostream& o,
8393 const bool pretty_print,
8394 const unsigned int indent_step,
8395 const unsigned int current_indent = 0)
const 8398 unsigned int new_indent = current_indent;
8404 if (m_value.object->empty())
8415 new_indent += indent_step;
8419 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
8421 if (i != m_value.object->cbegin())
8423 o << (pretty_print ?
",\n" :
",");
8425 o <<
string_t(new_indent,
' ') <<
"\"" 8426 << escape_string(i->first) <<
"\":" 8427 << (pretty_print ?
" " :
"");
8428 i->second.dump(o, pretty_print, indent_step, new_indent);
8434 new_indent -= indent_step;
8438 o <<
string_t(new_indent,
' ') +
"}";
8444 if (m_value.array->empty())
8455 new_indent += indent_step;
8459 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8461 if (i != m_value.array->cbegin())
8463 o << (pretty_print ?
",\n" :
",");
8466 i->dump(o, pretty_print, indent_step, new_indent);
8472 new_indent -= indent_step;
8476 o <<
string_t(new_indent,
' ') <<
"]";
8482 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
8488 o << (m_value.boolean ?
"true" :
"false");
8494 o << numtostr(m_value.number_integer).c_str();
8500 o << numtostr(m_value.number_unsigned).c_str();
8506 o << numtostr(m_value.number_float).c_str();
8533 json_value m_value = {};
8550 class primitive_iterator_t
8559 void set_begin() noexcept
8565 void set_end() noexcept
8571 constexpr
bool is_begin()
const noexcept
8573 return (m_it == begin_value);
8577 constexpr
bool is_end()
const noexcept
8579 return (m_it == end_value);
8582 friend constexpr
bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8584 return lhs.m_it == rhs.m_it;
8587 friend constexpr
bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8589 return !(lhs == rhs);
8592 friend constexpr
bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8594 return lhs.m_it < rhs.m_it;
8597 friend constexpr
bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8599 return lhs.m_it <= rhs.m_it;
8602 friend constexpr
bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8604 return lhs.m_it > rhs.m_it;
8607 friend constexpr
bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8609 return lhs.m_it >= rhs.m_it;
8614 auto result = *
this;
8619 friend constexpr
difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8621 return lhs.m_it - rhs.m_it;
8624 friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
8626 return os << it.m_it;
8629 primitive_iterator_t& operator++()
8635 primitive_iterator_t operator++(
int)
8637 auto result = *
this;
8642 primitive_iterator_t& operator--()
8648 primitive_iterator_t operator--(
int)
8650 auto result = *
this;
8672 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8682 struct internal_iterator
8685 typename object_t::iterator object_iterator;
8687 typename array_t::iterator array_iterator;
8689 primitive_iterator_t primitive_iterator;
8692 internal_iterator() noexcept
8693 : object_iterator(), array_iterator(), primitive_iterator()
8698 template<
typename IteratorType>
8699 class iteration_proxy
8703 class iteration_proxy_internal
8707 IteratorType anchor;
8709 size_t array_index = 0;
8712 explicit iteration_proxy_internal(IteratorType it) noexcept
8717 iteration_proxy_internal& operator*()
8723 iteration_proxy_internal& operator++()
8732 bool operator!= (
const iteration_proxy_internal& o)
const 8734 return anchor != o.anchor;
8740 assert(anchor.m_object !=
nullptr);
8742 switch (anchor.m_object->type())
8747 return std::to_string(array_index);
8753 return anchor.key();
8765 typename IteratorType::reference value()
const 8767 return anchor.value();
8772 typename IteratorType::reference container;
8776 explicit iteration_proxy(
typename IteratorType::reference cont)
8781 iteration_proxy_internal begin() noexcept
8783 return iteration_proxy_internal(container.begin());
8787 iteration_proxy_internal end() noexcept
8789 return iteration_proxy_internal(container.end());
8813 template<
typename U>
8814 class iter_impl :
public std::iterator<std::random_access_iterator_tag, U>
8820 static_assert(std::is_same<U, basic_json>::value
8821 or std::is_same<U, const basic_json>::value,
8822 "iter_impl only accepts (const) basic_json");
8830 using pointer =
typename std::conditional<std::is_const<U>::value,
8834 using reference =
typename std::conditional<std::is_const<U>::value,
8852 assert(m_object !=
nullptr);
8854 switch (m_object->m_type)
8858 m_it.object_iterator =
typename object_t::iterator();
8864 m_it.array_iterator =
typename array_t::iterator();
8870 m_it.primitive_iterator = primitive_iterator_t();
8890 ret.m_object = m_object;
8903 : m_object(other.m_object), m_it(other.m_it)
8912 std::is_nothrow_move_constructible<pointer>::value and
8913 std::is_nothrow_move_assignable<pointer>::value and
8914 std::is_nothrow_move_constructible<internal_iterator>::value and
8915 std::is_nothrow_move_assignable<internal_iterator>::value
8928 void set_begin() noexcept
8930 assert(m_object !=
nullptr);
8932 switch (m_object->m_type)
8936 m_it.object_iterator = m_object->m_value.object->begin();
8942 m_it.array_iterator = m_object->m_value.array->begin();
8946 case basic_json::value_t::null:
8949 m_it.primitive_iterator.set_end();
8955 m_it.primitive_iterator.set_begin();
8965 void set_end() noexcept
8967 assert(m_object !=
nullptr);
8969 switch (m_object->m_type)
8973 m_it.object_iterator = m_object->m_value.object->end();
8979 m_it.array_iterator = m_object->m_value.array->end();
8985 m_it.primitive_iterator.set_end();
8998 assert(m_object !=
nullptr);
9000 switch (m_object->m_type)
9004 assert(m_it.object_iterator != m_object->m_value.object->end());
9005 return m_it.object_iterator->second;
9010 assert(m_it.array_iterator != m_object->m_value.array->end());
9011 return *m_it.array_iterator;
9014 case basic_json::value_t::null:
9016 JSON_THROW(std::out_of_range(
"cannot get value"));
9021 if (m_it.primitive_iterator.is_begin())
9026 JSON_THROW(std::out_of_range(
"cannot get value"));
9037 assert(m_object !=
nullptr);
9039 switch (m_object->m_type)
9043 assert(m_it.object_iterator != m_object->m_value.object->end());
9044 return &(m_it.object_iterator->second);
9049 assert(m_it.array_iterator != m_object->m_value.array->end());
9050 return &*m_it.array_iterator;
9055 if (m_it.primitive_iterator.is_begin())
9060 JSON_THROW(std::out_of_range(
"cannot get value"));
9071 auto result = *
this;
9082 assert(m_object !=
nullptr);
9084 switch (m_object->m_type)
9088 std::advance(m_it.object_iterator, 1);
9094 std::advance(m_it.array_iterator, 1);
9100 ++m_it.primitive_iterator;
9114 auto result = *
this;
9125 assert(m_object !=
nullptr);
9127 switch (m_object->m_type)
9131 std::advance(m_it.object_iterator, -1);
9137 std::advance(m_it.array_iterator, -1);
9143 --m_it.primitive_iterator;
9158 if (m_object != other.m_object)
9160 JSON_THROW(std::domain_error(
"cannot compare iterators of different containers"));
9163 assert(m_object !=
nullptr);
9165 switch (m_object->m_type)
9169 return (m_it.object_iterator == other.m_it.object_iterator);
9174 return (m_it.array_iterator == other.m_it.array_iterator);
9179 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9190 return not operator==(other);
9200 if (m_object != other.m_object)
9202 JSON_THROW(std::domain_error(
"cannot compare iterators of different containers"));
9205 assert(m_object !=
nullptr);
9207 switch (m_object->m_type)
9211 JSON_THROW(std::domain_error(
"cannot compare order of object iterators"));
9216 return (m_it.array_iterator < other.m_it.array_iterator);
9221 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9232 return not other.operator < (*this);
9241 return not operator<=(other);
9259 assert(m_object !=
nullptr);
9261 switch (m_object->m_type)
9265 JSON_THROW(std::domain_error(
"cannot use offsets with object iterators"));
9270 std::advance(m_it.array_iterator, i);
9276 m_it.primitive_iterator += i;
9290 return operator+=(-i);
9299 auto result = *
this;
9310 auto result = *
this;
9321 assert(m_object !=
nullptr);
9323 switch (m_object->m_type)
9327 JSON_THROW(std::domain_error(
"cannot use offsets with object iterators"));
9332 return m_it.array_iterator - other.m_it.array_iterator;
9337 return m_it.primitive_iterator - other.m_it.primitive_iterator;
9348 assert(m_object !=
nullptr);
9350 switch (m_object->m_type)
9354 JSON_THROW(std::domain_error(
"cannot use operator[] for object iterators"));
9359 return *std::next(m_it.array_iterator, n);
9362 case basic_json::value_t::null:
9364 JSON_THROW(std::out_of_range(
"cannot get value"));
9369 if (m_it.primitive_iterator.get_value() == -n)
9374 JSON_THROW(std::out_of_range(
"cannot get value"));
9383 typename object_t::key_type
key()
const 9385 assert(m_object !=
nullptr);
9387 if (m_object->is_object())
9389 return m_it.object_iterator->first;
9392 JSON_THROW(std::domain_error(
"cannot use key() for non-object iterators"));
9408 internal_iterator m_it = internal_iterator();
9428 template<
typename Base>
9450 return base_iterator::operator++(1);
9456 base_iterator::operator++();
9463 return base_iterator::operator--(1);
9469 base_iterator::operator--();
9476 base_iterator::operator+=(i);
9483 auto result = *
this;
9491 auto result = *
this;
9499 return this->base() - other.base();
9505 return *(this->operator+(n));
9509 typename object_t::key_type
key()
const 9511 auto it = --this->base();
9518 auto it = --this->base();
9519 return it.operator * ();
9540 enum class token_type
9561 using lexer_char_t =
unsigned char;
9564 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
9567 assert(m_content !=
nullptr);
9568 m_start = m_cursor = m_content;
9569 m_limit = m_content + len;
9573 explicit lexer(std::istream& s)
9574 : m_stream(&s), m_line_buffer()
9579 JSON_THROW(std::invalid_argument(
"stream error"));
9586 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
9588 m_line_buffer[0] =
' ';
9589 m_line_buffer[1] =
' ';
9590 m_line_buffer[2] =
' ';
9596 lexer(
const lexer&) =
delete;
9597 lexer operator=(
const lexer&) =
delete;
9622 static string_t to_unicode(
const std::size_t codepoint1,
9623 const std::size_t codepoint2 = 0)
9626 std::size_t codepoint = codepoint1;
9629 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9632 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9646 JSON_THROW(std::invalid_argument(
"missing or wrong low surrogate"));
9652 if (codepoint < 0x80)
9655 result.append(1, static_cast<typename string_t::value_type>(codepoint));
9657 else if (codepoint <= 0x7ff)
9660 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9661 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9663 else if (codepoint <= 0xffff)
9666 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9667 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9668 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9670 else if (codepoint <= 0x10ffff)
9673 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9674 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9675 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9676 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9680 JSON_THROW(std::out_of_range(
"code points above 0x10FFFF are invalid"));
9687 static std::string token_type_name(
const token_type t)
9691 case token_type::uninitialized:
9692 return "<uninitialized>";
9693 case token_type::literal_true:
9694 return "true literal";
9695 case token_type::literal_false:
9696 return "false literal";
9697 case token_type::literal_null:
9698 return "null literal";
9699 case token_type::value_string:
9700 return "string literal";
9701 case lexer::token_type::value_unsigned:
9702 case lexer::token_type::value_integer:
9703 case lexer::token_type::value_float:
9704 return "number literal";
9705 case token_type::begin_array:
9707 case token_type::begin_object:
9709 case token_type::end_array:
9711 case token_type::end_object:
9713 case token_type::name_separator:
9715 case token_type::value_separator:
9717 case token_type::parse_error:
9718 return "<parse error>";
9719 case token_type::end_of_input:
9720 return "end of input";
9724 return "unknown token";
9759 assert(m_start !=
nullptr);
9764 unsigned int yyaccept = 0;
9765 static const unsigned char yybm[] =
9767 0, 0, 0, 0, 0, 0, 0, 0,
9768 0, 32, 32, 0, 0, 32, 0, 0,
9769 0, 0, 0, 0, 0, 0, 0, 0,
9770 0, 0, 0, 0, 0, 0, 0, 0,
9771 160, 128, 0, 128, 128, 128, 128, 128,
9772 128, 128, 128, 128, 128, 128, 128, 128,
9773 192, 192, 192, 192, 192, 192, 192, 192,
9774 192, 192, 128, 128, 128, 128, 128, 128,
9775 128, 128, 128, 128, 128, 128, 128, 128,
9776 128, 128, 128, 128, 128, 128, 128, 128,
9777 128, 128, 128, 128, 128, 128, 128, 128,
9778 128, 128, 128, 128, 0, 128, 128, 128,
9779 128, 128, 128, 128, 128, 128, 128, 128,
9780 128, 128, 128, 128, 128, 128, 128, 128,
9781 128, 128, 128, 128, 128, 128, 128, 128,
9782 128, 128, 128, 128, 128, 128, 128, 128,
9783 0, 0, 0, 0, 0, 0, 0, 0,
9784 0, 0, 0, 0, 0, 0, 0, 0,
9785 0, 0, 0, 0, 0, 0, 0, 0,
9786 0, 0, 0, 0, 0, 0, 0, 0,
9787 0, 0, 0, 0, 0, 0, 0, 0,
9788 0, 0, 0, 0, 0, 0, 0, 0,
9789 0, 0, 0, 0, 0, 0, 0, 0,
9790 0, 0, 0, 0, 0, 0, 0, 0,
9791 0, 0, 0, 0, 0, 0, 0, 0,
9792 0, 0, 0, 0, 0, 0, 0, 0,
9793 0, 0, 0, 0, 0, 0, 0, 0,
9794 0, 0, 0, 0, 0, 0, 0, 0,
9795 0, 0, 0, 0, 0, 0, 0, 0,
9796 0, 0, 0, 0, 0, 0, 0, 0,
9797 0, 0, 0, 0, 0, 0, 0, 0,
9798 0, 0, 0, 0, 0, 0, 0, 0,
9800 if ((m_limit - m_cursor) < 5)
9802 fill_line_buffer(5);
9805 if (yybm[0 + yych] & 32)
9807 goto basic_json_parser_6;
9817 goto basic_json_parser_2;
9821 goto basic_json_parser_4;
9823 goto basic_json_parser_9;
9829 goto basic_json_parser_4;
9833 goto basic_json_parser_10;
9835 goto basic_json_parser_12;
9844 goto basic_json_parser_4;
9848 goto basic_json_parser_13;
9850 goto basic_json_parser_15;
9856 goto basic_json_parser_17;
9860 goto basic_json_parser_4;
9862 goto basic_json_parser_19;
9874 goto basic_json_parser_21;
9876 goto basic_json_parser_4;
9882 goto basic_json_parser_23;
9886 goto basic_json_parser_4;
9888 goto basic_json_parser_24;
9897 goto basic_json_parser_25;
9899 goto basic_json_parser_4;
9905 goto basic_json_parser_26;
9909 goto basic_json_parser_28;
9911 goto basic_json_parser_4;
9915 basic_json_parser_2:
9918 last_token_type = token_type::end_of_input;
9921 basic_json_parser_4:
9923 basic_json_parser_5:
9925 last_token_type = token_type::parse_error;
9928 basic_json_parser_6:
9930 if (m_limit <= m_cursor)
9932 fill_line_buffer(1);
9935 if (yybm[0 + yych] & 32)
9937 goto basic_json_parser_6;
9942 basic_json_parser_9:
9944 yych = *(m_marker = ++m_cursor);
9947 goto basic_json_parser_5;
9951 goto basic_json_parser_31;
9955 goto basic_json_parser_5;
9959 goto basic_json_parser_31;
9961 goto basic_json_parser_5;
9962 basic_json_parser_10:
9965 last_token_type = token_type::value_separator;
9968 basic_json_parser_12:
9972 goto basic_json_parser_5;
9976 goto basic_json_parser_43;
9980 goto basic_json_parser_45;
9982 goto basic_json_parser_5;
9983 basic_json_parser_13:
9985 yych = *(m_marker = ++m_cursor);
9990 goto basic_json_parser_47;
9994 goto basic_json_parser_48;
10003 goto basic_json_parser_51;
10010 goto basic_json_parser_51;
10014 basic_json_parser_14:
10016 last_token_type = token_type::value_unsigned;
10019 basic_json_parser_15:
10021 m_marker = ++m_cursor;
10022 if ((m_limit - m_cursor) < 3)
10024 fill_line_buffer(3);
10027 if (yybm[0 + yych] & 64)
10029 goto basic_json_parser_15;
10035 goto basic_json_parser_47;
10037 goto basic_json_parser_14;
10043 goto basic_json_parser_51;
10047 goto basic_json_parser_51;
10049 goto basic_json_parser_14;
10051 basic_json_parser_17:
10054 last_token_type = token_type::name_separator;
10057 basic_json_parser_19:
10060 last_token_type = token_type::begin_array;
10063 basic_json_parser_21:
10066 last_token_type = token_type::end_array;
10069 basic_json_parser_23:
10071 yych = *(m_marker = ++m_cursor);
10074 goto basic_json_parser_52;
10076 goto basic_json_parser_5;
10077 basic_json_parser_24:
10079 yych = *(m_marker = ++m_cursor);
10082 goto basic_json_parser_53;
10084 goto basic_json_parser_5;
10085 basic_json_parser_25:
10087 yych = *(m_marker = ++m_cursor);
10090 goto basic_json_parser_54;
10092 goto basic_json_parser_5;
10093 basic_json_parser_26:
10096 last_token_type = token_type::begin_object;
10099 basic_json_parser_28:
10102 last_token_type = token_type::end_object;
10105 basic_json_parser_30:
10107 if (m_limit <= m_cursor)
10109 fill_line_buffer(1);
10112 basic_json_parser_31:
10113 if (yybm[0 + yych] & 128)
10115 goto basic_json_parser_30;
10123 goto basic_json_parser_32;
10127 goto basic_json_parser_33;
10129 goto basic_json_parser_35;
10135 goto basic_json_parser_32;
10139 goto basic_json_parser_36;
10141 goto basic_json_parser_37;
10150 goto basic_json_parser_39;
10152 goto basic_json_parser_38;
10158 goto basic_json_parser_40;
10162 goto basic_json_parser_41;
10166 goto basic_json_parser_42;
10170 basic_json_parser_32:
10171 m_cursor = m_marker;
10176 goto basic_json_parser_5;
10180 goto basic_json_parser_14;
10187 goto basic_json_parser_44;
10191 goto basic_json_parser_58;
10194 basic_json_parser_33:
10197 last_token_type = token_type::value_string;
10200 basic_json_parser_35:
10202 if (m_limit <= m_cursor)
10204 fill_line_buffer(1);
10213 goto basic_json_parser_30;
10217 goto basic_json_parser_32;
10219 goto basic_json_parser_30;
10227 goto basic_json_parser_32;
10229 goto basic_json_parser_30;
10235 goto basic_json_parser_30;
10237 goto basic_json_parser_32;
10247 goto basic_json_parser_30;
10251 goto basic_json_parser_30;
10253 goto basic_json_parser_32;
10261 goto basic_json_parser_30;
10263 goto basic_json_parser_32;
10269 goto basic_json_parser_30;
10273 goto basic_json_parser_55;
10275 goto basic_json_parser_32;
10279 basic_json_parser_36:
10281 if (m_limit <= m_cursor)
10283 fill_line_buffer(1);
10288 goto basic_json_parser_32;
10292 goto basic_json_parser_30;
10294 goto basic_json_parser_32;
10295 basic_json_parser_37:
10297 if (m_limit <= m_cursor)
10299 fill_line_buffer(1);
10304 goto basic_json_parser_32;
10308 goto basic_json_parser_36;
10310 goto basic_json_parser_32;
10311 basic_json_parser_38:
10313 if (m_limit <= m_cursor)
10315 fill_line_buffer(1);
10320 goto basic_json_parser_32;
10324 goto basic_json_parser_36;
10326 goto basic_json_parser_32;
10327 basic_json_parser_39:
10329 if (m_limit <= m_cursor)
10331 fill_line_buffer(1);
10336 goto basic_json_parser_32;
10340 goto basic_json_parser_36;
10342 goto basic_json_parser_32;
10343 basic_json_parser_40:
10345 if (m_limit <= m_cursor)
10347 fill_line_buffer(1);
10352 goto basic_json_parser_32;
10356 goto basic_json_parser_38;
10358 goto basic_json_parser_32;
10359 basic_json_parser_41:
10361 if (m_limit <= m_cursor)
10363 fill_line_buffer(1);
10368 goto basic_json_parser_32;
10372 goto basic_json_parser_38;
10374 goto basic_json_parser_32;
10375 basic_json_parser_42:
10377 if (m_limit <= m_cursor)
10379 fill_line_buffer(1);
10384 goto basic_json_parser_32;
10388 goto basic_json_parser_38;
10390 goto basic_json_parser_32;
10391 basic_json_parser_43:
10393 yych = *(m_marker = ++m_cursor);
10398 goto basic_json_parser_47;
10402 goto basic_json_parser_48;
10411 goto basic_json_parser_51;
10418 goto basic_json_parser_51;
10422 basic_json_parser_44:
10424 last_token_type = token_type::value_integer;
10427 basic_json_parser_45:
10429 m_marker = ++m_cursor;
10430 if ((m_limit - m_cursor) < 3)
10432 fill_line_buffer(3);
10439 goto basic_json_parser_47;
10443 goto basic_json_parser_44;
10445 goto basic_json_parser_45;
10453 goto basic_json_parser_44;
10455 goto basic_json_parser_51;
10461 goto basic_json_parser_51;
10463 goto basic_json_parser_44;
10466 basic_json_parser_47:
10467 yych = *++m_cursor;
10470 goto basic_json_parser_32;
10474 goto basic_json_parser_56;
10476 goto basic_json_parser_32;
10477 basic_json_parser_48:
10479 if (m_limit <= m_cursor)
10481 fill_line_buffer(1);
10486 goto basic_json_parser_50;
10490 goto basic_json_parser_48;
10492 basic_json_parser_50:
10494 last_token_type = token_type::parse_error;
10497 basic_json_parser_51:
10498 yych = *++m_cursor;
10503 goto basic_json_parser_59;
10505 goto basic_json_parser_32;
10511 goto basic_json_parser_59;
10515 goto basic_json_parser_32;
10519 goto basic_json_parser_60;
10521 goto basic_json_parser_32;
10523 basic_json_parser_52:
10524 yych = *++m_cursor;
10527 goto basic_json_parser_62;
10529 goto basic_json_parser_32;
10530 basic_json_parser_53:
10531 yych = *++m_cursor;
10534 goto basic_json_parser_63;
10536 goto basic_json_parser_32;
10537 basic_json_parser_54:
10538 yych = *++m_cursor;
10541 goto basic_json_parser_64;
10543 goto basic_json_parser_32;
10544 basic_json_parser_55:
10546 if (m_limit <= m_cursor)
10548 fill_line_buffer(1);
10555 goto basic_json_parser_32;
10559 goto basic_json_parser_65;
10561 goto basic_json_parser_32;
10567 goto basic_json_parser_65;
10571 goto basic_json_parser_32;
10575 goto basic_json_parser_65;
10577 goto basic_json_parser_32;
10579 basic_json_parser_56:
10581 m_marker = ++m_cursor;
10582 if ((m_limit - m_cursor) < 3)
10584 fill_line_buffer(3);
10591 goto basic_json_parser_58;
10595 goto basic_json_parser_56;
10602 goto basic_json_parser_51;
10606 goto basic_json_parser_51;
10609 basic_json_parser_58:
10611 last_token_type = token_type::value_float;
10614 basic_json_parser_59:
10615 yych = *++m_cursor;
10618 goto basic_json_parser_32;
10622 goto basic_json_parser_32;
10624 basic_json_parser_60:
10626 if (m_limit <= m_cursor)
10628 fill_line_buffer(1);
10633 goto basic_json_parser_58;
10637 goto basic_json_parser_60;
10639 goto basic_json_parser_58;
10640 basic_json_parser_62:
10641 yych = *++m_cursor;
10644 goto basic_json_parser_66;
10646 goto basic_json_parser_32;
10647 basic_json_parser_63:
10648 yych = *++m_cursor;
10651 goto basic_json_parser_67;
10653 goto basic_json_parser_32;
10654 basic_json_parser_64:
10655 yych = *++m_cursor;
10658 goto basic_json_parser_69;
10660 goto basic_json_parser_32;
10661 basic_json_parser_65:
10663 if (m_limit <= m_cursor)
10665 fill_line_buffer(1);
10672 goto basic_json_parser_32;
10676 goto basic_json_parser_71;
10678 goto basic_json_parser_32;
10684 goto basic_json_parser_71;
10688 goto basic_json_parser_32;
10692 goto basic_json_parser_71;
10694 goto basic_json_parser_32;
10696 basic_json_parser_66:
10697 yych = *++m_cursor;
10700 goto basic_json_parser_72;
10702 goto basic_json_parser_32;
10703 basic_json_parser_67:
10706 last_token_type = token_type::literal_null;
10709 basic_json_parser_69:
10712 last_token_type = token_type::literal_true;
10715 basic_json_parser_71:
10717 if (m_limit <= m_cursor)
10719 fill_line_buffer(1);
10726 goto basic_json_parser_32;
10730 goto basic_json_parser_74;
10732 goto basic_json_parser_32;
10738 goto basic_json_parser_74;
10742 goto basic_json_parser_32;
10746 goto basic_json_parser_74;
10748 goto basic_json_parser_32;
10750 basic_json_parser_72:
10753 last_token_type = token_type::literal_false;
10756 basic_json_parser_74:
10758 if (m_limit <= m_cursor)
10760 fill_line_buffer(1);
10767 goto basic_json_parser_32;
10771 goto basic_json_parser_30;
10773 goto basic_json_parser_32;
10779 goto basic_json_parser_30;
10783 goto basic_json_parser_32;
10787 goto basic_json_parser_30;
10789 goto basic_json_parser_32;
10795 return last_token_type;
10826 void fill_line_buffer(
size_t n = 0)
10829 assert(m_line_buffer.empty()
10830 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
10833 assert(m_line_buffer.empty()
10834 or m_limit == m_content + m_line_buffer.size());
10837 assert(m_content <= m_start);
10838 assert(m_start <= m_cursor);
10839 assert(m_cursor <= m_limit);
10840 assert(m_marker ==
nullptr or m_marker <= m_limit);
10843 const auto num_processed_chars =
static_cast<size_t>(m_start - m_content);
10845 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
10847 const auto offset_cursor = m_cursor - m_start;
10850 if (m_stream ==
nullptr or m_stream->eof())
10855 m_line_buffer.assign(m_start, m_limit);
10859 m_line_buffer.append(1,
'\x00');
10862 m_line_buffer.append(n - 1,
'\x01');
10868 m_line_buffer.erase(0, num_processed_chars);
10870 m_line_buffer_tmp.clear();
10871 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
10874 m_line_buffer += m_line_buffer_tmp;
10875 m_line_buffer.push_back(
'\n');
10879 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
10880 assert(m_content !=
nullptr);
10881 m_start = m_content;
10882 m_marker = m_start + offset_marker;
10883 m_cursor = m_start + offset_cursor;
10884 m_limit = m_start + m_line_buffer.size();
10890 assert(m_start !=
nullptr);
10891 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10892 static_cast<size_t>(m_cursor - m_start));
10954 assert(m_cursor - m_start >= 2);
10957 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10960 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10963 auto e = std::find(i, m_cursor - 1,
'\\');
10967 for (
auto k = i; k < e; k++)
10969 result.push_back(static_cast<typename string_t::value_type>(*k));
11027 auto codepoint = std::strtoul(
std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
11028 4).c_str(),
nullptr, 16);
11031 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
11034 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
11036 JSON_THROW(std::invalid_argument(
"missing low surrogate"));
11040 auto codepoint2 = std::strtoul(
std::string(reinterpret_cast<typename string_t::const_pointer>
11041 (i + 7), 4).c_str(),
nullptr, 16);
11042 result += to_unicode(codepoint, codepoint2);
11046 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
11049 JSON_THROW(std::invalid_argument(
"missing high surrogate"));
11054 result += to_unicode(codepoint);
11081 : m_start(start), m_end(end)
11090 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
11093 return parse(val, std::is_integral<T>());
11097 const char*
const m_start =
nullptr;
11098 const char*
const m_end =
nullptr;
11104 static void strtof(
float& f,
const char* str,
char** endptr)
11106 f = std::strtof(str, endptr);
11109 static void strtof(
double& f,
const char* str,
char** endptr)
11111 f = std::strtod(str, endptr);
11114 static void strtof(
long double& f,
const char* str,
char** endptr)
11116 f = std::strtold(str, endptr);
11119 template<
typename T>
11120 bool parse(T& value, std::false_type)
const 11126 std::array<char, 64>
buf;
11127 const size_t len =
static_cast<size_t>(m_end - m_start);
11135 const auto loc = localeconv();
11136 assert(loc !=
nullptr);
11137 const char decimal_point_char = (loc->decimal_point ==
nullptr) ?
'.' : loc->decimal_point[0];
11139 const char* data = m_start;
11141 if (decimal_point_char !=
'.')
11143 const size_t ds_pos =
static_cast<size_t>(std::find(m_start, m_end,
'.') - m_start);
11150 if ((len + 1) < buf.size())
11152 std::copy(m_start, m_end, buf.begin());
11154 buf[ds_pos] = decimal_point_char;
11159 tempstr.assign(m_start, m_end);
11160 tempstr[ds_pos] = decimal_point_char;
11161 data = tempstr.c_str();
11166 char* endptr =
nullptr;
11169 strtof(value, data, &endptr);
11173 const bool ok = (endptr == (data + len));
11175 if (ok and (value == static_cast<T>(0.0)) and (*data ==
'-'))
11186 signed long long parse_integral(
char** endptr, std::true_type)
const 11188 return std::strtoll(m_start, endptr, 10);
11191 unsigned long long parse_integral(
char** endptr, std::false_type)
const 11193 return std::strtoull(m_start, endptr, 10);
11196 template<
typename T>
11197 bool parse(T& value, std::true_type)
const 11199 char* endptr =
nullptr;
11201 const auto x = parse_integral(&endptr, std::is_signed<T>());
11204 static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(),
"");
11206 value =
static_cast<T
>(x);
11208 return (x ==
static_cast<decltype(x)
>(value))
11209 and (x < 0) == (value < 0)
11212 and (m_start < m_end)
11213 and (endptr == m_end);
11236 bool get_number(
basic_json& result,
const token_type token)
const 11238 assert(m_start !=
nullptr);
11239 assert(m_start < m_cursor);
11240 assert((token == token_type::value_unsigned) or
11241 (token == token_type::value_integer) or
11242 (token == token_type::value_float));
11244 strtonum num_converter(reinterpret_cast<const char*>(m_start),
11245 reinterpret_cast<const char*>(m_cursor));
11249 case lexer::token_type::value_unsigned:
11252 if (num_converter.
to(val))
11256 result.m_value = val;
11262 case lexer::token_type::value_integer:
11265 if (num_converter.
to(val))
11269 result.m_value = val;
11284 if (num_converter.
to(val))
11288 result.m_value = val;
11291 if (not std::isfinite(result.m_value.number_float))
11294 result.m_value = basic_json::json_value();
11306 std::istream* m_stream =
nullptr;
11312 const lexer_char_t* m_content =
nullptr;
11314 const lexer_char_t* m_start =
nullptr;
11316 const lexer_char_t* m_marker =
nullptr;
11318 const lexer_char_t* m_cursor =
nullptr;
11320 const lexer_char_t* m_limit =
nullptr;
11322 token_type last_token_type = token_type::end_of_input;
11336 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
11341 : callback(cb), m_lexer(is)
11345 template<
class IteratorType,
typename std::enable_if<
11346 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
11349 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
11351 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
11352 static_cast<size_t>(std::distance(first, last)))
11362 result.assert_invariant();
11364 expect(lexer::token_type::end_of_input);
11377 switch (last_token)
11379 case lexer::token_type::begin_object:
11381 if (keep and (not callback
11382 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
11393 if (last_token == lexer::token_type::end_object)
11396 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
11404 unexpect(lexer::token_type::value_separator);
11410 if (last_token == lexer::token_type::value_separator)
11416 expect(lexer::token_type::value_string);
11417 const auto key = m_lexer.get_string();
11419 bool keep_tag =
false;
11425 keep_tag = callback(depth, parse_event_t::key, k);
11435 expect(lexer::token_type::name_separator);
11439 auto value = parse_internal(keep);
11440 if (keep and keep_tag and not value.is_discarded())
11442 result[key] = std::move(value);
11445 while (last_token == lexer::token_type::value_separator);
11448 expect(lexer::token_type::end_object);
11450 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
11458 case lexer::token_type::begin_array:
11460 if (keep and (not callback
11461 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
11472 if (last_token == lexer::token_type::end_array)
11475 if (callback and not callback(--depth, parse_event_t::array_end, result))
11483 unexpect(lexer::token_type::value_separator);
11489 if (last_token == lexer::token_type::value_separator)
11495 auto value = parse_internal(keep);
11496 if (keep and not value.is_discarded())
11498 result.push_back(std::move(value));
11501 while (last_token == lexer::token_type::value_separator);
11504 expect(lexer::token_type::end_array);
11506 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
11514 case lexer::token_type::literal_null:
11521 case lexer::token_type::value_string:
11523 const auto s = m_lexer.get_string();
11529 case lexer::token_type::literal_true:
11533 result.m_value =
true;
11537 case lexer::token_type::literal_false:
11541 result.m_value =
false;
11545 case lexer::token_type::value_unsigned:
11546 case lexer::token_type::value_integer:
11547 case lexer::token_type::value_float:
11549 m_lexer.get_number(result, last_token);
11557 unexpect(last_token);
11561 if (keep and callback and not callback(depth, parse_event_t::value, result))
11569 typename lexer::token_type get_token()
11571 last_token = m_lexer.scan();
11575 void expect(
typename lexer::token_type t)
const 11577 if (t != last_token)
11579 std::string error_msg =
"parse error - unexpected ";
11580 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
11582 lexer::token_type_name(last_token));
11583 error_msg +=
"; expected " + lexer::token_type_name(t);
11584 JSON_THROW(std::invalid_argument(error_msg));
11588 void unexpect(
typename lexer::token_type t)
const 11590 if (t == last_token)
11592 std::string error_msg =
"parse error - unexpected ";
11593 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
11595 lexer::token_type_name(last_token));
11596 JSON_THROW(std::invalid_argument(error_msg));
11606 typename lexer::token_type last_token = lexer::token_type::uninitialized;
11652 : reference_tokens(split(s))
11672 return std::accumulate(reference_tokens.begin(),
11676 return a +
"/" + escape(b);
11683 return to_string();
11692 JSON_THROW(std::domain_error(
"JSON pointer has no parent"));
11695 auto last = reference_tokens.back();
11696 reference_tokens.pop_back();
11701 bool is_root()
const 11703 return reference_tokens.empty();
11710 JSON_THROW(std::domain_error(
"JSON pointer has no parent"));
11714 result.reference_tokens = {reference_tokens[0]};
11729 for (
const auto& reference_token : reference_tokens)
11731 switch (result->m_type)
11735 if (reference_token ==
"0")
11738 result = &result->operator[](0);
11743 result = &result->operator[](reference_token);
11751 result = &result->operator[](reference_token);
11758 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11771 JSON_THROW(std::domain_error(
"invalid value to unflatten"));
11800 for (
const auto& reference_token : reference_tokens)
11806 const bool nums = std::all_of(reference_token.begin(),
11807 reference_token.end(),
11810 return std::isdigit(x);
11815 if (nums or reference_token ==
"-")
11825 switch (ptr->m_type)
11830 ptr = &ptr->operator[](reference_token);
11837 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11839 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11842 if (reference_token ==
"-")
11845 ptr = &ptr->operator[](ptr->m_value.array->size());
11850 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11857 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11867 for (
const auto& reference_token : reference_tokens)
11869 switch (ptr->m_type)
11874 ptr = &ptr->at(reference_token);
11880 if (reference_token ==
"-")
11883 JSON_THROW(std::out_of_range(
"array index '-' (" +
11884 std::to_string(ptr->m_value.array->size()) +
11885 ") is out of range"));
11889 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11891 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11895 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11901 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11919 for (
const auto& reference_token : reference_tokens)
11921 switch (ptr->m_type)
11926 ptr = &ptr->operator[](reference_token);
11932 if (reference_token ==
"-")
11935 JSON_THROW(std::out_of_range(
"array index '-' (" +
11936 std::to_string(ptr->m_value.array->size()) +
11937 ") is out of range"));
11941 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11943 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11947 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11953 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11963 for (
const auto& reference_token : reference_tokens)
11965 switch (ptr->m_type)
11970 ptr = &ptr->at(reference_token);
11976 if (reference_token ==
"-")
11979 JSON_THROW(std::out_of_range(
"array index '-' (" +
11980 std::to_string(ptr->m_value.array->size()) +
11981 ") is out of range"));
11985 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11987 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11991 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11997 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
12006 static std::vector<std::string> split(
const std::string& reference_string)
12008 std::vector<std::string> result;
12011 if (reference_string.empty())
12017 if (reference_string[0] !=
'/')
12019 JSON_THROW(std::domain_error(
"JSON pointer must be empty or begin with '/'"));
12027 size_t slash = reference_string.find_first_of(
'/', 1),
12036 slash = reference_string.find_first_of(
'/', start))
12040 auto reference_token = reference_string.substr(start, slash - start);
12043 for (
size_t pos = reference_token.find_first_of(
'~');
12044 pos != std::string::npos;
12045 pos = reference_token.find_first_of(
'~', pos + 1))
12047 assert(reference_token[pos] ==
'~');
12050 if (pos == reference_token.size() - 1 or
12051 (reference_token[pos + 1] !=
'0' and
12052 reference_token[pos + 1] !=
'1'))
12054 JSON_THROW(std::domain_error(
"escape error: '~' must be followed with '0' or '1'"));
12059 unescape(reference_token);
12060 result.push_back(reference_token);
12083 assert(not f.empty());
12086 size_t pos = s.find(f);
12087 pos != std::string::npos;
12088 s.replace(pos, f.size(), t),
12089 pos = s.find(f, pos + t.size())
12097 replace_substring(s,
"~",
"~0");
12098 replace_substring(s,
"/",
"~1");
12106 replace_substring(s,
"~1",
"/");
12108 replace_substring(s,
"~0",
"~");
12118 static void flatten(
const std::string& reference_string,
12122 switch (value.m_type)
12126 if (value.m_value.array->empty())
12129 result[reference_string] =
nullptr;
12134 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
12136 flatten(reference_string +
"/" + std::to_string(i),
12137 value.m_value.array->operator[](i), result);
12145 if (value.m_value.object->empty())
12148 result[reference_string] =
nullptr;
12153 for (
const auto& element : *value.m_value.object)
12155 flatten(reference_string +
"/" + escape(element.first),
12156 element.second, result);
12165 result[reference_string] = value;
12180 JSON_THROW(std::domain_error(
"only objects can be unflattened"));
12186 for (
const auto& element : *value.m_value.object)
12188 if (not element.second.is_primitive())
12190 JSON_THROW(std::domain_error(
"values in object must be primitive"));
12198 json_pointer(element.first).get_and_create(result) = element.second;
12208 return lhs.reference_tokens == rhs.reference_tokens;
12214 return !(lhs == rhs);
12218 std::vector<std::string> reference_tokens {};
12263 return ptr.get_unchecked(
this);
12290 return ptr.get_unchecked(
this);
12315 return ptr.get_checked(
this);
12340 return ptr.get_checked(
this);
12368 json_pointer::flatten(
"", *
this, result);
12401 return json_pointer::unflatten(*
this);
12455 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
12461 return patch_operations::add;
12463 if (op ==
"remove")
12465 return patch_operations::remove;
12467 if (op ==
"replace")
12469 return patch_operations::replace;
12473 return patch_operations::move;
12477 return patch_operations::copy;
12481 return patch_operations::test;
12484 return patch_operations::invalid;
12499 if (top_pointer != ptr)
12501 result.
at(top_pointer);
12505 const auto last_path = ptr.pop_back();
12508 switch (parent.m_type)
12514 parent[last_path] = val;
12520 if (last_path ==
"-")
12527 const auto idx = std::stoi(last_path);
12528 if (static_cast<size_type>(idx) > parent.
size())
12531 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
12552 const auto operation_remove = [&result](
json_pointer & ptr)
12555 const auto last_path = ptr.pop_back();
12562 auto it = parent.
find(last_path);
12563 if (it != parent.
end())
12569 JSON_THROW(std::out_of_range(
"key '" + last_path +
"' not found"));
12575 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
12583 JSON_THROW(std::invalid_argument(
"JSON patch must be an array of objects"));
12587 for (
const auto& val : json_patch)
12590 const auto get_value = [&val](
const std::string & op,
12595 auto it = val.m_value.object->find(member);
12598 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
12601 if (it == val.m_value.object->end())
12603 JSON_THROW(std::invalid_argument(error_msg +
" must have member '" + member +
"'"));
12607 if (string_type and not it->second.is_string())
12609 JSON_THROW(std::invalid_argument(error_msg +
" must have string member '" + member +
"'"));
12617 if (not val.is_object())
12619 JSON_THROW(std::invalid_argument(
"JSON patch must be an array of objects"));
12623 const std::string op = get_value(
"op",
"op",
true);
12624 const std::string path = get_value(op,
"path",
true);
12627 switch (get_op(op))
12629 case patch_operations::add:
12631 operation_add(ptr, get_value(
"add",
"value",
false));
12635 case patch_operations::remove:
12637 operation_remove(ptr);
12641 case patch_operations::replace:
12644 result.
at(ptr) = get_value(
"replace",
"value",
false);
12648 case patch_operations::move:
12650 const std::string from_path = get_value(
"move",
"from",
true);
12660 operation_remove(from_ptr);
12661 operation_add(ptr, v);
12665 case patch_operations::copy:
12667 const std::string from_path = get_value(
"copy",
"from",
true);;
12671 result[ptr] = result.
at(from_ptr);
12675 case patch_operations::test:
12677 bool success =
false;
12682 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
12692 JSON_THROW(std::domain_error(
"unsuccessful: " + val.dump()));
12698 case patch_operations::invalid:
12702 JSON_THROW(std::invalid_argument(
"operation value '" + op +
"' is invalid"));
12750 if (source == target)
12755 if (source.
type() != target.
type())
12767 switch (source.
type())
12773 while (i < source.
size() and i < target.
size())
12776 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
12777 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
12786 while (i < source.
size())
12793 {
"path", path +
"/" + std::to_string(i)}
12799 while (i < target.
size())
12804 {
"path", path +
"/" + std::to_string(i)},
12805 {
"value", target[i]}
12816 for (
auto it = source.
begin(); it != source.
end(); ++it)
12819 const auto key = json_pointer::escape(it.key());
12821 if (target.
find(it.key()) != target.
end())
12824 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
12825 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
12833 {
"path", path +
"/" + key}
12839 for (
auto it = target.
begin(); it != target.
end(); ++it)
12841 if (source.
find(it.key()) == source.
end())
12844 const auto key = json_pointer::escape(it.key());
12848 {
"path", path +
"/" + key},
12849 {
"value", it.value()}
12908 is_nothrow_move_constructible<nlohmann::json>::value and
12909 is_nothrow_move_assignable<nlohmann::json>::value
12927 const auto& h = hash<nlohmann::json::string_t>();
12928 return h(j.
dump());
12971 #undef JSON_DEPRECATED reference operator+=(basic_json &&val)
add an object to an array
reference operator[](T *key)
access specified object element
ReferenceType get_ref()
get a reference value (implicit)
object_t::key_type key() const
return the key of an object iterator
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
json_reverse_iterator operator--(int)
post-decrement (it–)
iter_impl(pointer object) noexcept
constructor for a given JSON instance
basic_json flatten() const
return flattened JSON value
void swap(object_t &other)
exchanges the values
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
typename std::conditional< std::is_const< U >::value, typename basic_json::const_reference, typename basic_json::reference >::type reference
defines a reference to the type iterated over (value_type)
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
std::integral_constant< bool, std::is_convertible< T, int >::value and std::is_enum< T >::value > is_unscoped_enum
basic_json value_type
the type of elements in a basic_json container
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
difference_type operator-(const iter_impl &other) const
return difference
reference operator[](const typename object_t::key_type &key)
access specified object element
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
const_reference operator[](size_type idx) const
access specified array element
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
string_t dump(const int indent=-1) const
serialization
#define JSON_CATCH(exception)
iter_impl & operator++()
pre-increment (++it)
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
reference operator[](difference_type n) const
access to successor
friend bool operator==(json_pointer const &lhs, json_pointer const &rhs) noexcept
const_reference at(size_type idx) const
access specified array element with bounds checking
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
constexpr bool is_primitive() const noexcept
return whether type is primitive
iter_impl(const iter_impl &other) noexcept
copy constructor
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
bool operator<=(const iter_impl &other) const
comparison: less than or equal
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
friend bool operator!=(json_pointer const &lhs, json_pointer const &rhs) noexcept
bool empty() const noexcept
checks whether the container is empty
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
iter_impl operator++(int)
post-increment (it++)
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
size_type size() const noexcept
returns the number of elements
iter_impl & operator+=(difference_type i)
add to iterator
void erase(const size_type idx)
remove element from a JSON array given an index
json_reverse_iterator operator+(difference_type i) const
add to iterator
a class to store JSON values
iterator begin() noexcept
returns an iterator to the first element
void from_json_array_impl(const BasicJsonType &j, CompatibleArrayType &arr, priority_tag< 0 >)
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
default JSONSerializer template argument
constexpr bool is_null() const noexcept
return whether value is null
iter_impl & operator=(iter_impl other) noexcept(std::is_nothrow_move_constructible< pointer >::value and std::is_nothrow_move_assignable< pointer >::value and std::is_nothrow_move_constructible< internal_iterator >::value and std::is_nothrow_move_assignable< internal_iterator >::value)
copy assignment
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
PointerType get_ptr() noexcept
get a pointer value (implicit)
const_reference back() const
access the last element
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value and is_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
reference front()
access the first element
const_iterator cend() const noexcept
returns a const iterator to one past the last element
AllocatorType< basic_json > allocator_type
the allocator type
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
JSONSerializer< T, SFINAE > json_serializer
reference value() const
return the value of an iterator
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
IteratorType erase(IteratorType pos)
remove element given an iterator
object_t::key_type key() const
return the key of an object iterator
bool operator<(const iter_impl &other) const
comparison: smaller
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
iterator find(typename object_t::key_type key)
find an element in a JSON object
basic_json unflatten() const
unflatten a previously flattened JSON value
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
typename std::enable_if< B, T >::type enable_if_t
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
discarded by the the parser callback function
void swap(string_t &other)
exchanges the values
std::numeric_limits< RealIntegerType > RealLimits
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
iter_impl operator-(difference_type i)
subtract from iterator
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
void to_json(BasicJsonType &j, T b) noexcept
std::string type_name() const
return the type as string
void emplace_back(Args &&... args)
add an object to an array
iter_impl & operator-=(difference_type i)
subtract from iterator
constexpr bool is_structured() const noexcept
return whether type is structured
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
iter_impl operator--(int)
post-decrement (it–)
NLOHMANN_JSON_HAS_HELPER(mapped_type)
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
const_reference front() const
access the first element
void push_back(basic_json &&val)
add an object to an array
json_reverse_iterator & operator+=(difference_type i)
add to iterator
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
number value (signed integer)
iterator insert(const_iterator pos, const basic_json &val)
inserts element
reference operator*() const
return a reference to the value pointed to by the iterator
static void to_json(BasicJsonType &j, ValueType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< ValueType >(val))))
convert any value type to a JSON value
friend class basic_json
allow basic_json to access private members
#define JSON_THROW(exception)
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
parse string into a built-in arithmetic type as if the current locale is POSIX.
json_reverse_iterator operator++(int)
post-increment (it++)
json_pointer(const std::string &s="")
create JSON pointer
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
constexpr bool is_object() const noexcept
return whether value is an object
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
json_reverse_iterator & operator--()
pre-decrement (–it)
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
namespace for Niels Lohmann
static basic_json from_msgpack(const std::vector< uint8_t > &v, const size_t start_index=0)
create a JSON value from a byte vector in MessagePack format
void push_back(const typename object_t::value_type &val)
add an object to an object
constexpr bool is_string() const noexcept
return whether value is a string
iter_impl & operator--()
pre-decrement (–it)
reference at(size_type idx)
access specified array element with bounds checking
const_iterator end() const noexcept
returns a const iterator to one past the last element
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
static basic_json meta()
returns version information on the library
basic_json(const basic_json &other)
copy constructor
size_type max_size() const noexcept
returns the maximum possible number of elements
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
number value (unsigned integer)
const value_type & const_reference
the type of an element const reference
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
static void from_json(BasicJsonType &&j, ValueType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val)))
convert a JSON value to any value type
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
constexpr bool is_discarded() const noexcept
return whether value is discarded
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
basic_json(basic_json &&other) noexcept
move constructor
void push_back(const basic_json &val)
add an object to an array
typename Base::reference reference
the reference type for the pointed-to element
basic_json(const value_t value_type)
create an empty value with a given type
ReferenceType get_ref() const
get a reference value (implicit)
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
pointer operator->() const
dereference the iterator
StringType string_t
a type for a string
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
reference operator[](T *(&key)[n])
access specified object element
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
void from_json(const BasicJsonType &j, ArithmeticType &val)
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
const_reference operator[](T *key) const
read-only access specified object element
std::numeric_limits< CompatibleNumberIntegerType > CompatibleLimits
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
NumberIntegerType number_integer_t
a type for a number (integer)
int16_t half
half is a 16-bit IEEE floating-point standard number format.
void push_back(std::initializer_list< basic_json > init)
add an object to an object
basic_json(CompatibleType &&val) noexcept(noexcept(JSONSerializer< U >::to_json(std::declval< basic_json_t &>(), std::forward< CompatibleType >(val))))
create a JSON value
reference & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
static basic_json from_cbor(const std::vector< uint8_t > &v, const size_t start_index=0)
create a JSON value from a byte vector in CBOR format
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
json_reverse_iterator & operator++()
pre-increment (++it)
strtonum(const char *start, const char *end)
std::size_t size_type
a type to represent container sizes
object (unordered set of name/value pairs)
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
parse_event_t
JSON callback events.
iter_impl operator+(difference_type i)
add to iterator
constexpr bool is_boolean() const noexcept
return whether value is a boolean
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
static basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
reference operator[](difference_type n) const
access to successor
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
iterator insert(const_iterator pos, basic_json &&val)
inserts element
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
reference operator+=(const typename object_t::value_type &val)
add an object to an object
reference operator[](size_type idx)
access specified array element
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
bool operator==(const iter_impl &other) const
comparison: equal
const_iterator begin() const noexcept
returns a const iterator to the first element
std::ptrdiff_t difference_type
a type to represent differences between iterators
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference operator+=(const basic_json &val)
add an object to an array
reference back()
access the last element
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
iterator end() noexcept
returns an iterator to one past the last element
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
difference_type operator-(const json_reverse_iterator &other) const
return difference
bool operator>(const iter_impl &other) const
comparison: greater than
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
a template for a reverse iterator class
constexpr bool is_array() const noexcept
return whether value is an array
typename basic_json::difference_type difference_type
a type to represent differences between iterators
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
number value (floating-point)
static allocator_type get_allocator()
returns the allocator associated with the container
void from_json(const BasicJsonType &j, typename BasicJsonType::boolean_t &b)
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
constexpr bool is_number() const noexcept
return whether value is a number
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
BooleanType boolean_t
a type for a boolean
bool operator!=(const iter_impl &other) const
comparison: not equal
std::string to_string() const noexcept
return a string representation of the JSON pointer
void operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(std::declval< to_json_fn >().call(j, std::forward< T >(val), priority_tag< 1 > {})))
void swap(array_t &other)
exchanges the values
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
basic_json(std::initializer_list< basic_json > init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
NumberFloatType number_float_t
a type for a number (floating-point)
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
std::bidirectional_iterator_tag iterator_category
the category of the iterator
array (ordered collection of values)
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
void to_json(BasicJsonType &j, const CompatibleObjectType &arr)
reference value() const
return the value of an iterator
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
a template for a random access iterator for the basic_json class
value_t
the JSON type enumeration
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
void clear() noexcept
clears the contents
void operator()(const BasicJsonType &j, T &val) const noexcept(noexcept(std::declval< from_json_fn >().call(j, val, priority_tag< 1 > {})))
typename std::conditional< std::is_const< U >::value, typename basic_json::const_pointer, typename basic_json::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for