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__) 62 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 63 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 65 #elif defined(__GNUC__) 66 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 67 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 72 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 73 #pragma GCC diagnostic push 74 #pragma GCC diagnostic ignored "-Wfloat-equal" 78 #if defined(__clang__) 79 #pragma GCC diagnostic push 80 #pragma GCC diagnostic ignored "-Wdocumentation" 84 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 85 #define JSON_DEPRECATED __attribute__((deprecated)) 86 #elif defined(_MSC_VER) 87 #define JSON_DEPRECATED __declspec(deprecated) 89 #define JSON_DEPRECATED 93 #if not defined(JSON_NOEXCEPTION) || defined(__EXCEPTIONS) 94 #define JSON_THROW(exception) throw exception 96 #define JSON_CATCH(exception) catch(exception) 98 #define JSON_THROW(exception) std::abort() 99 #define JSON_TRY if(true) 100 #define JSON_CATCH(exception) if(false) 149 enum class value_t : uint8_t
171 inline bool operator<(
const value_t lhs,
const value_t rhs) noexcept
173 static constexpr std::array<uint8_t, 8> order = {{
186 if (lhs == value_t::discarded or rhs == value_t::discarded)
191 return order[
static_cast<std::size_t
>(lhs)] <
192 order[static_cast<std::size_t>(rhs)];
201 template<
bool B,
typename T =
void>
202 using enable_if_t =
typename std::enable_if<B, T>::type;
205 using uncvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
209 using is_unscoped_enum =
210 std::integral_constant<bool, std::is_convertible<T, int>::value and
211 std::is_enum<T>::value>;
226 template<
class...>
struct conjunction : std::true_type {};
227 template<
class B1>
struct conjunction<B1> : B1 {};
228 template<
class B1,
class... Bn>
229 struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
231 template<
class B>
struct negation : std::integral_constant < bool, !B::value > {};
234 template<
unsigned N>
struct priority_tag : priority_tag < N - 1 > {};
235 template<>
struct priority_tag<0> {};
242 template<value_t>
struct external_constructor;
245 struct external_constructor<value_t::boolean>
247 template<
typename BasicJsonType>
248 static void construct(BasicJsonType& j,
typename BasicJsonType::boolean_t b) noexcept
250 j.m_type = value_t::boolean;
252 j.assert_invariant();
257 struct external_constructor<value_t::string>
259 template<
typename BasicJsonType>
260 static void construct(BasicJsonType& j,
const typename BasicJsonType::string_t& s)
262 j.m_type = value_t::string;
264 j.assert_invariant();
269 struct external_constructor<value_t::number_float>
271 template<
typename BasicJsonType>
272 static void construct(BasicJsonType& j,
typename BasicJsonType::number_float_t val) noexcept
275 if (not std::isfinite(val))
281 j.m_type = value_t::number_float;
284 j.assert_invariant();
289 struct external_constructor<value_t::number_unsigned>
291 template<
typename BasicJsonType>
292 static void construct(BasicJsonType& j,
typename BasicJsonType::number_unsigned_t val) noexcept
294 j.m_type = value_t::number_unsigned;
296 j.assert_invariant();
301 struct external_constructor<value_t::number_integer>
303 template<
typename BasicJsonType>
304 static void construct(BasicJsonType& j,
typename BasicJsonType::number_integer_t val) noexcept
306 j.m_type = value_t::number_integer;
308 j.assert_invariant();
313 struct external_constructor<value_t::array>
315 template<
typename BasicJsonType>
316 static void construct(BasicJsonType& j,
const typename BasicJsonType::array_t& arr)
318 j.m_type = value_t::array;
320 j.assert_invariant();
323 template<
typename BasicJsonType,
typename CompatibleArrayType,
324 enable_if_t<not std::is_same<CompatibleArrayType,
325 typename BasicJsonType::array_t>::value,
327 static void construct(BasicJsonType& j,
const CompatibleArrayType& arr)
331 j.m_type = value_t::array;
332 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
333 j.assert_invariant();
338 struct external_constructor<value_t::object>
340 template<
typename BasicJsonType>
341 static void construct(BasicJsonType& j,
const typename BasicJsonType::object_t& obj)
343 j.m_type = value_t::object;
345 j.assert_invariant();
348 template<
typename BasicJsonType,
typename CompatibleObjectType,
349 enable_if_t<not std::is_same<CompatibleObjectType,
350 typename BasicJsonType::object_t>::value,
352 static void construct(BasicJsonType& j,
const CompatibleObjectType& obj)
357 j.m_type = value_t::object;
358 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
359 j.assert_invariant();
378 #define NLOHMANN_JSON_HAS_HELPER(type) \ 379 template<typename T> struct has_##type { \ 381 template<typename U, typename = typename U::type> \ 382 static int detect(U &&); \ 383 static void detect(...); \ 385 static constexpr bool value = \ 386 std::is_integral<decltype(detect(std::declval<T>()))>::value; \ 389 NLOHMANN_JSON_HAS_HELPER(mapped_type);
390 NLOHMANN_JSON_HAS_HELPER(key_type);
391 NLOHMANN_JSON_HAS_HELPER(value_type);
392 NLOHMANN_JSON_HAS_HELPER(iterator);
394 #undef NLOHMANN_JSON_HAS_HELPER 397 template<
bool B,
class RealType,
class CompatibleObjectType>
398 struct is_compatible_object_type_impl : std::false_type {};
400 template<
class RealType,
class CompatibleObjectType>
401 struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
403 static constexpr
auto value =
404 std::is_constructible<
typename RealType::key_type,
405 typename CompatibleObjectType::key_type>::value and
406 std::is_constructible<
typename RealType::mapped_type,
407 typename CompatibleObjectType::mapped_type>::value;
410 template<
class BasicJsonType,
class CompatibleObjectType>
411 struct is_compatible_object_type
413 static auto constexpr value = is_compatible_object_type_impl <
414 conjunction<negation<std::is_same<void, CompatibleObjectType>>,
415 has_mapped_type<CompatibleObjectType>,
416 has_key_type<CompatibleObjectType>>::value,
417 typename BasicJsonType::object_t, CompatibleObjectType >::value;
420 template<
typename BasicJsonType,
typename T>
421 struct is_basic_json_nested_type
423 static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
424 std::is_same<T, typename BasicJsonType::const_iterator>::value or
425 std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
426 std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value or
427 std::is_same<T, typename BasicJsonType::json_pointer>::value;
430 template<
class BasicJsonType,
class CompatibleArrayType>
431 struct is_compatible_array_type
433 static auto constexpr value =
434 conjunction<negation<std::is_same<void, CompatibleArrayType>>,
435 negation<is_compatible_object_type<
436 BasicJsonType, CompatibleArrayType>>,
437 negation<std::is_constructible<
typename BasicJsonType::string_t,
438 CompatibleArrayType>>,
439 negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
440 has_value_type<CompatibleArrayType>,
441 has_iterator<CompatibleArrayType>>::value;
444 template<
bool,
typename,
typename>
445 struct is_compatible_integer_type_impl : std::false_type {};
447 template<
typename RealIntegerType,
typename CompatibleNumberIntegerType>
448 struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
451 using RealLimits = std::numeric_limits<RealIntegerType>;
452 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
454 static constexpr
auto value =
455 std::is_constructible<RealIntegerType,
456 CompatibleNumberIntegerType>::value and
457 CompatibleLimits::is_integer and
458 RealLimits::is_signed == CompatibleLimits::is_signed;
461 template<
typename RealIntegerType,
typename CompatibleNumberIntegerType>
462 struct is_compatible_integer_type
464 static constexpr
auto value =
465 is_compatible_integer_type_impl <
466 std::is_integral<CompatibleNumberIntegerType>::value and
467 not std::is_same<bool, CompatibleNumberIntegerType>::value,
468 RealIntegerType, CompatibleNumberIntegerType > ::value;
473 template<
typename BasicJsonType,
typename T>
478 template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
479 std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
480 static int detect(U&&);
481 static void detect(...);
484 static constexpr
bool value = std::is_integral<decltype(
485 detect(std::declval<
typename BasicJsonType::template json_serializer<T, void>>()))>::value;
490 template<
typename BasicJsonType,
typename T>
491 struct has_non_default_from_json
496 typename = enable_if_t<std::is_same<
497 T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
498 static int detect(U&&);
499 static void detect(...);
502 static constexpr
bool value = std::is_integral<decltype(detect(
503 std::declval<
typename BasicJsonType::template json_serializer<T, void>>()))>::value;
507 template<
typename BasicJsonType,
typename T>
511 template<typename U, typename = decltype(uncvref_t<U>::to_json(
512 std::declval<BasicJsonType&>(), std::declval<T>()))>
513 static int detect(U&&);
514 static void detect(...);
517 static constexpr
bool value = std::is_integral<decltype(detect(
518 std::declval<
typename BasicJsonType::template json_serializer<T, void>>()))>::value;
526 template<
typename BasicJsonType>
527 void to_json(BasicJsonType& j,
typename BasicJsonType::boolean_t b) noexcept
529 external_constructor<value_t::boolean>::construct(j, b);
532 template<
typename BasicJsonType,
typename CompatibleString,
533 enable_if_t<std::is_constructible<
typename BasicJsonType::string_t,
534 CompatibleString>::value,
int> = 0>
535 void to_json(BasicJsonType& j,
const CompatibleString& s)
537 external_constructor<value_t::string>::construct(j, s);
540 template<
typename BasicJsonType,
typename FloatType,
541 enable_if_t<std::is_floating_point<FloatType>::value,
int> = 0>
542 void to_json(BasicJsonType& j, FloatType val) noexcept
544 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
548 typename BasicJsonType,
typename CompatibleNumberUnsignedType,
549 enable_if_t<is_compatible_integer_type<
typename BasicJsonType::number_unsigned_t,
550 CompatibleNumberUnsignedType>::value,
int> = 0 >
551 void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
553 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
557 typename BasicJsonType,
typename CompatibleNumberIntegerType,
558 enable_if_t<is_compatible_integer_type<
typename BasicJsonType::number_integer_t,
559 CompatibleNumberIntegerType>::value,
int> = 0 >
560 void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
562 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
565 template<
typename BasicJsonType,
typename UnscopedEnumType,
566 enable_if_t<is_unscoped_enum<UnscopedEnumType>::value,
int> = 0>
567 void to_json(BasicJsonType& j, UnscopedEnumType e) noexcept
569 external_constructor<value_t::number_integer>::construct(j, e);
573 typename BasicJsonType,
typename CompatibleArrayType,
575 is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
576 std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
578 void to_json(BasicJsonType& j,
const CompatibleArrayType& arr)
580 external_constructor<value_t::array>::construct(j, arr);
584 typename BasicJsonType,
typename CompatibleObjectType,
585 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
587 void to_json(BasicJsonType& j,
const CompatibleObjectType& arr)
589 external_constructor<value_t::object>::construct(j, arr);
598 template<
typename BasicJsonType,
typename ArithmeticType,
599 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
600 not std::is_same<ArithmeticType,
601 typename BasicJsonType::boolean_t>::value,
603 void get_arithmetic_value(
const BasicJsonType& j, ArithmeticType& val)
605 switch (static_cast<value_t>(j))
607 case value_t::number_unsigned:
609 val =
static_cast<ArithmeticType
>(
610 *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
613 case value_t::number_integer:
615 val =
static_cast<ArithmeticType
>(
616 *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
619 case value_t::number_float:
621 val =
static_cast<ArithmeticType
>(
622 *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
628 std::domain_error(
"type must be number, but is " + j.type_name()));
633 template<
typename BasicJsonType>
634 void from_json(
const BasicJsonType& j,
typename BasicJsonType::boolean_t& b)
636 if (not j.is_boolean())
638 JSON_THROW(std::domain_error(
"type must be boolean, but is " + j.type_name()));
640 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
643 template<
typename BasicJsonType>
644 void from_json(
const BasicJsonType& j,
typename BasicJsonType::string_t& s)
646 if (not j.is_string())
648 JSON_THROW(std::domain_error(
"type must be string, but is " + j.type_name()));
650 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
653 template<
typename BasicJsonType>
654 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_float_t& val)
656 get_arithmetic_value(j, val);
659 template<
typename BasicJsonType>
660 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_unsigned_t& val)
662 get_arithmetic_value(j, val);
665 template<
typename BasicJsonType>
666 void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_integer_t& val)
668 get_arithmetic_value(j, val);
671 template<
typename BasicJsonType,
typename UnscopedEnumType,
672 enable_if_t<is_unscoped_enum<UnscopedEnumType>::value,
int> = 0>
673 void from_json(
const BasicJsonType& j, UnscopedEnumType& e)
675 typename std::underlying_type<UnscopedEnumType>::type val = e;
676 get_arithmetic_value(j, val);
677 e =
static_cast<UnscopedEnumType
>(val);
680 template<
typename BasicJsonType>
681 void from_json(
const BasicJsonType& j,
typename BasicJsonType::array_t& arr)
683 if (not j.is_array())
685 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
687 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
691 template<
typename BasicJsonType,
typename T,
typename Allocator>
692 void from_json(
const BasicJsonType& j, std::forward_list<T, Allocator>& l)
698 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
700 if (not std::is_same<T, BasicJsonType>::value)
702 if (not j.is_array())
704 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
707 for (
auto it = j.rbegin(), end = j.rend(); it != end; ++it)
709 l.push_front(it->template get<T>());
713 template<
typename BasicJsonType,
typename CompatibleArrayType>
714 void from_json_array_impl(
const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0>)
719 std::transform(j.begin(), j.end(),
720 std::inserter(arr, end(arr)), [](
const BasicJsonType & i)
724 return i.template get<typename CompatibleArrayType::value_type>();
728 template<
typename BasicJsonType,
typename CompatibleArrayType>
729 auto from_json_array_impl(
const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1>)
731 arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
737 arr.reserve(j.size());
739 j.begin(), j.end(), std::inserter(arr, end(arr)), [](
const BasicJsonType & i)
743 return i.template get<typename CompatibleArrayType::value_type>();
747 template<
typename BasicJsonType,
typename CompatibleArrayType,
748 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
749 not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
int> = 0>
750 void from_json(
const BasicJsonType& j, CompatibleArrayType& arr)
754 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
758 if (not std::is_same<typename CompatibleArrayType::value_type, BasicJsonType>::value)
760 if (not j.is_array())
762 JSON_THROW(std::domain_error(
"type must be array, but is " + j.type_name()));
765 from_json_array_impl(j, arr, priority_tag<1> {});
768 template<
typename BasicJsonType,
typename CompatibleObjectType,
769 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
int> = 0>
770 void from_json(
const BasicJsonType& j, CompatibleObjectType& obj)
772 if (not j.is_object())
774 JSON_THROW(std::domain_error(
"type must be object, but is " + j.type_name()));
777 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
783 obj = CompatibleObjectType(begin(*inner_object), end(*inner_object));
790 template<
typename BasicJsonType,
typename ArithmeticType,
792 std::is_arithmetic<ArithmeticType>::value and
793 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
794 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
795 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
796 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
798 void from_json(
const BasicJsonType& j, ArithmeticType& val)
800 switch (static_cast<value_t>(j))
802 case value_t::number_unsigned:
804 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
807 case value_t::number_integer:
809 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
812 case value_t::number_float:
814 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
817 case value_t::boolean:
819 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
824 JSON_THROW(std::domain_error(
"type must be number, but is " + j.type_name()));
832 template<
typename BasicJsonType,
typename T>
833 auto call(BasicJsonType& j, T&& val, priority_tag<1>)
const noexcept(noexcept(to_json(j, std::forward<T>(val))))
834 -> decltype(to_json(j, std::forward<T>(val)),
void())
836 return to_json(j, std::forward<T>(val));
839 template<
typename BasicJsonType,
typename T>
840 void call(BasicJsonType&, T&&, priority_tag<0>)
const noexcept
842 static_assert(
sizeof(BasicJsonType) == 0,
843 "could not find to_json() method in T's namespace");
847 template<
typename BasicJsonType,
typename T>
848 void operator()(BasicJsonType& j, T&& val)
const 849 noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
851 return call(j, std::forward<T>(val), priority_tag<1> {});
858 template<
typename BasicJsonType,
typename T>
859 auto call(
const BasicJsonType& j, T& val, priority_tag<1>)
const 860 noexcept(noexcept(from_json(j, val)))
861 -> decltype(from_json(j, val),
void())
863 return from_json(j, val);
866 template<
typename BasicJsonType,
typename T>
867 void call(
const BasicJsonType&, T&, priority_tag<0>)
const noexcept
869 static_assert(
sizeof(BasicJsonType) == 0,
870 "could not find from_json() method in T's namespace");
874 template<
typename BasicJsonType,
typename T>
875 void operator()(
const BasicJsonType& j, T& val)
const 876 noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
878 return call(j, val, priority_tag<1> {});
886 static constexpr T value{};
890 constexpr T static_const<T>::value;
897 constexpr
const auto&
to_json = detail::static_const<detail::to_json_fn>::value;
898 constexpr
const auto&
from_json = detail::static_const<detail::from_json_fn>::value;
909 template<
typename =
void,
typename =
void>
921 template<
typename BasicJsonType,
typename ValueType>
922 static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
923 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
925 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
937 template<
typename BasicJsonType,
typename ValueType>
938 static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
939 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
941 ::nlohmann::to_json(j, std::forward<ValueType>(val));
1028 template<
typename U,
typename V,
typename... Args>
class ObjectType = std::map,
1029 template<
typename U,
typename... Args>
class ArrayType = std::vector,
1030 class StringType = std::string,
1031 class BooleanType = bool,
1032 class NumberIntegerType = std::int64_t,
1033 class NumberUnsignedType = std::uint64_t,
1034 class NumberFloatType = double,
1035 template<
typename U>
class AllocatorType = std::allocator,
1036 template<
typename T,
typename SFINAE =
void>
class JSONSerializer =
adl_serializer 1041 template<detail::value_t>
friend struct detail::external_constructor;
1044 BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
1045 AllocatorType, JSONSerializer>;
1048 using value_t = detail::value_t;
1053 template<
typename T,
typename SFINAE>
1082 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
1084 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
1133 result[
"copyright"] =
"(C) 2013-2017 Niels Lohmann";
1134 result[
"name"] =
"JSON for Modern C++";
1135 result[
"url"] =
"https://github.com/nlohmann/json";
1138 {
"string",
"2.1.0"},
1145 result[
"platform"] =
"win32";
1146 #elif defined __linux__ 1147 result[
"platform"] =
"linux";
1148 #elif defined __APPLE__ 1149 result[
"platform"] =
"apple";
1150 #elif defined __unix__ 1151 result[
"platform"] =
"unix";
1153 result[
"platform"] =
"unknown";
1156 #if defined(__clang__) 1157 result[
"compiler"] = {{
"family",
"clang"}, {
"version", __clang_version__}};
1158 #elif defined(__ICC) || defined(__INTEL_COMPILER) 1159 result[
"compiler"] = {{
"family",
"icc"}, {
"version", __INTEL_COMPILER}};
1160 #elif defined(__GNUC__) || defined(__GNUG__) 1161 result[
"compiler"] = {{
"family",
"gcc"}, {
"version", std::to_string(__GNUC__) +
"." + std::to_string(__GNUC_MINOR__) +
"." + std::to_string(__GNUC_PATCHLEVEL__)}};
1162 #elif defined(__HP_cc) || defined(__HP_aCC) 1163 result[
"compiler"] =
"hp" 1164 #elif defined(__IBMCPP__) 1165 result[
"compiler"] = {{
"family",
"ilecpp"}, {
"version", __IBMCPP__}};
1166 #elif defined(_MSC_VER) 1167 result[
"compiler"] = {{
"family",
"msvc"}, {
"version", _MSC_VER}};
1168 #elif defined(__PGI) 1169 result[
"compiler"] = {{
"family",
"pgcpp"}, {
"version", __PGI}};
1170 #elif defined(__SUNPRO_CC) 1171 result[
"compiler"] = {{
"family",
"sunpro"}, {
"version", __SUNPRO_CC}};
1173 result[
"compiler"] = {{
"family",
"unknown"}, {
"version",
"unknown"}};
1177 result[
"compiler"][
"c++"] = std::to_string(__cplusplus);
1179 result[
"compiler"][
"c++"] =
"unknown";
1277 using object_t = ObjectType<StringType,
1279 std::less<StringType>,
1280 AllocatorType<std::pair<
const StringType,
1327 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
1624 template<
typename T,
typename... Args>
1625 static T* create(Args&& ... args)
1627 AllocatorType<T> alloc;
1628 auto deleter = [&](T * object)
1630 alloc.deallocate(
object, 1);
1632 std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
1633 alloc.construct(
object.
get(), std::forward<Args>(args)...);
1634 assert(
object !=
nullptr);
1635 return object.release();
1684 json_value() =
default;
1686 json_value(
boolean_t v) noexcept : boolean(v) {}
1694 json_value(value_t t)
1698 case value_t::object:
1700 object = create<object_t>();
1704 case value_t::array:
1706 array = create<array_t>();
1710 case value_t::string:
1712 string = create<string_t>(
"");
1716 case value_t::boolean:
1722 case value_t::number_integer:
1728 case value_t::number_unsigned:
1734 case value_t::number_float:
1747 if (t == value_t::null)
1749 JSON_THROW(std::domain_error(
"961c151d2e87f2686a955a9be24d316f1362bf21 2.1.0"));
1759 string = create<string_t>(value);
1765 object = create<object_t>(value);
1769 json_value(
const array_t& value)
1771 array = create<array_t>(value);
1784 void assert_invariant()
const 1786 assert(m_type != value_t::object or m_value.object !=
nullptr);
1787 assert(m_type != value_t::array or m_value.array !=
nullptr);
1788 assert(m_type != value_t::string or m_value.string !=
nullptr);
1876 basic_json& parsed)>;
1916 : m_type(value_type), m_value(value_type)
1998 template<
typename CompatibleType,
typename U = detail::uncvref_t<CompatibleType>,
1999 detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
2000 not std::is_same<U, basic_json_t>::value and
2001 not detail::is_basic_json_nested_type<
2002 basic_json_t, U>::value and
2003 detail::has_to_json<basic_json, U>::value,
2005 basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer<U>::to_json(
2006 std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))
2008 JSONSerializer<U>::to_json(*
this, std::forward<CompatibleType>(val));
2082 bool type_deduction =
true,
2083 value_t manual_type = value_t::array)
2087 bool is_an_object = std::all_of(init.begin(), init.end(),
2090 return element.is_array() and element.size() == 2 and element[0].is_string();
2094 if (not type_deduction)
2097 if (manual_type == value_t::array)
2099 is_an_object =
false;
2103 if (manual_type == value_t::object and not is_an_object)
2105 JSON_THROW(std::domain_error(
"cannot create object from initializer list"));
2112 m_type = value_t::object;
2113 m_value = value_t::object;
2115 std::for_each(init.begin(), init.end(), [
this](
const basic_json & element)
2117 m_value.object->emplace(*(element[0].m_value.string), element[1]);
2123 m_type = value_t::array;
2124 m_value.array = create<array_t>(init);
2165 std::initializer_list<basic_json>())
2167 return basic_json(init,
false, value_t::array);
2205 std::initializer_list<basic_json>())
2207 return basic_json(init,
false, value_t::object);
2229 : m_type(value_t::array)
2231 m_value.array = create<array_t>(cnt, val);
2272 template<
class InputIT,
typename std::enable_if<
2273 std::is_same<InputIT, typename basic_json_t::iterator>::value or
2274 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>::type = 0>
2277 assert(first.m_object !=
nullptr);
2278 assert(last.m_object !=
nullptr);
2281 if (first.m_object != last.m_object)
2283 JSON_THROW(std::domain_error(
"iterators are not compatible"));
2287 m_type = first.m_object->m_type;
2292 case value_t::boolean:
2293 case value_t::number_float:
2294 case value_t::number_integer:
2295 case value_t::number_unsigned:
2296 case value_t::string:
2298 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
2300 JSON_THROW(std::out_of_range(
"iterators out of range"));
2313 case value_t::number_integer:
2315 m_value.number_integer = first.m_object->m_value.number_integer;
2319 case value_t::number_unsigned:
2321 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
2325 case value_t::number_float:
2327 m_value.number_float = first.m_object->m_value.number_float;
2331 case value_t::boolean:
2333 m_value.boolean = first.m_object->m_value.boolean;
2337 case value_t::string:
2339 m_value = *first.m_object->m_value.string;
2343 case value_t::object:
2345 m_value.object = create<object_t>(first.m_it.object_iterator,
2346 last.m_it.object_iterator);
2350 case value_t::array:
2352 m_value.array = create<array_t>(first.m_it.array_iterator,
2353 last.m_it.array_iterator);
2359 JSON_THROW(std::domain_error(
"cannot use construct with iterators from " + first.m_object->type_name()));
2397 *
this = parser(i, cb).parse();
2428 : m_type(other.m_type)
2431 other.assert_invariant();
2435 case value_t::object:
2437 m_value = *other.m_value.object;
2441 case value_t::array:
2443 m_value = *other.m_value.array;
2447 case value_t::string:
2449 m_value = *other.m_value.string;
2453 case value_t::boolean:
2455 m_value = other.m_value.boolean;
2459 case value_t::number_integer:
2461 m_value = other.m_value.number_integer;
2465 case value_t::number_unsigned:
2467 m_value = other.m_value.number_unsigned;
2471 case value_t::number_float:
2473 m_value = other.m_value.number_float;
2505 : m_type(std::move(other.m_type)),
2506 m_value(std::move(other.m_value))
2509 other.assert_invariant();
2512 other.m_type = value_t::null;
2542 std::is_nothrow_move_constructible<value_t>::value and
2543 std::is_nothrow_move_assignable<value_t>::value and
2544 std::is_nothrow_move_constructible<json_value>::value and
2545 std::is_nothrow_move_assignable<json_value>::value
2549 other.assert_invariant();
2552 swap(m_type, other.m_type);
2553 swap(m_value, other.m_value);
2580 case value_t::object:
2582 AllocatorType<object_t> alloc;
2583 alloc.destroy(m_value.object);
2584 alloc.deallocate(m_value.object, 1);
2588 case value_t::array:
2590 AllocatorType<array_t> alloc;
2591 alloc.destroy(m_value.array);
2592 alloc.deallocate(m_value.array, 1);
2596 case value_t::string:
2598 AllocatorType<string_t> alloc;
2599 alloc.destroy(m_value.string);
2600 alloc.deallocate(m_value.string, 1);
2648 std::stringstream ss;
2650 ss.imbue(std::locale::classic());
2656 ss.precision(std::numeric_limits<double>::digits10);
2660 dump(ss,
true, static_cast<unsigned int>(indent));
2688 constexpr value_t
type() const noexcept
2720 return is_null() or is_string() or is_boolean() or is_number();
2747 return is_array() or is_object();
2769 return m_type == value_t::null;
2791 return m_type == value_t::boolean;
2821 return is_number_integer() or is_number_float();
2850 return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
2878 return m_type == value_t::number_unsigned;
2906 return m_type == value_t::number_float;
2928 return m_type == value_t::object;
2950 return m_type == value_t::array;
2972 return m_type == value_t::string;
2999 return m_type == value_t::discarded;
3020 constexpr
operator value_t() const noexcept
3037 return m_value.boolean;
3041 JSON_THROW(std::domain_error(
"type must be boolean, but is " + type_name()));
3048 return is_object() ? m_value.object :
nullptr;
3054 return is_object() ? m_value.object :
nullptr;
3060 return is_array() ? m_value.array :
nullptr;
3064 constexpr
const array_t* get_impl_ptr(
const array_t* )
const noexcept
3066 return is_array() ? m_value.array :
nullptr;
3072 return is_string() ? m_value.string :
nullptr;
3078 return is_string() ? m_value.string :
nullptr;
3084 return is_boolean() ? &m_value.boolean :
nullptr;
3090 return is_boolean() ? &m_value.boolean :
nullptr;
3096 return is_number_integer() ? &m_value.number_integer :
nullptr;
3102 return is_number_integer() ? &m_value.number_integer :
nullptr;
3108 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
3114 return is_number_unsigned() ? &m_value.number_unsigned :
nullptr;
3120 return is_number_float() ? &m_value.number_float :
nullptr;
3126 return is_number_float() ? &m_value.number_float :
nullptr;
3140 template<
typename ReferenceType,
typename ThisType>
3141 static ReferenceType get_ref_impl(ThisType& obj)
3144 using PointerType =
typename std::add_pointer<ReferenceType>::type;
3147 auto ptr = obj.template get_ptr<PointerType>();
3154 throw std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
3178 typename BasicJsonType,
3179 detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
3227 typename ValueTypeCV,
3228 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3229 detail::enable_if_t <
3230 not std::is_same<basic_json_t, ValueType>::value and
3231 detail::has_from_json<basic_json_t, ValueType>::value and
3232 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3234 ValueType
get()
const noexcept(noexcept(
3235 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
3240 static_assert(not std::is_reference<ValueTypeCV>::value,
3241 "get() cannot be used with reference types, you might want to use get_ref()");
3242 static_assert(std::is_default_constructible<ValueType>::value,
3243 "types must be DefaultConstructible when used with get()");
3246 JSONSerializer<ValueType>::from_json(*
this, ret);
3282 typename ValueTypeCV,
3283 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3284 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
3286 ValueType>::value,
int> = 0 >
3287 ValueType
get()
const noexcept(noexcept(
3288 JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
3290 static_assert(not std::is_reference<ValueTypeCV>::value,
3291 "get() cannot be used with reference types, you might want to use get_ref()");
3292 return JSONSerializer<ValueTypeCV>::from_json(*
this);
3322 template<
typename PointerType,
typename std::enable_if<
3323 std::is_pointer<PointerType>::value,
int>::type = 0>
3324 PointerType
get() noexcept
3327 return get_ptr<PointerType>();
3334 template<
typename PointerType,
typename std::enable_if<
3335 std::is_pointer<PointerType>::value,
int>::type = 0>
3336 constexpr
const PointerType
get()
const noexcept
3339 return get_ptr<PointerType>();
3368 template<
typename PointerType,
typename std::enable_if<
3369 std::is_pointer<PointerType>::value,
int>::type = 0>
3373 using pointee_t =
typename std::remove_const<
typename 3374 std::remove_pointer<
typename 3375 std::remove_const<PointerType>::type>::type>::type;
3378 std::is_same<object_t, pointee_t>::value
3379 or std::is_same<array_t, pointee_t>::value
3380 or std::is_same<string_t, pointee_t>::value
3381 or std::is_same<boolean_t, pointee_t>::value
3382 or std::is_same<number_integer_t, pointee_t>::value
3383 or std::is_same<number_unsigned_t, pointee_t>::value
3384 or std::is_same<number_float_t, pointee_t>::value
3385 ,
"incompatible pointer type");
3388 return get_impl_ptr(static_cast<PointerType>(
nullptr));
3395 template<
typename PointerType,
typename std::enable_if<
3396 std::is_pointer<PointerType>::value and
3397 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int>::type = 0>
3398 constexpr
const PointerType
get_ptr() const noexcept
3401 using pointee_t =
typename std::remove_const<
typename 3402 std::remove_pointer<
typename 3403 std::remove_const<PointerType>::type>::type>::type;
3406 std::is_same<object_t, pointee_t>::value
3407 or std::is_same<array_t, pointee_t>::value
3408 or std::is_same<string_t, pointee_t>::value
3409 or std::is_same<boolean_t, pointee_t>::value
3410 or std::is_same<number_integer_t, pointee_t>::value
3411 or std::is_same<number_unsigned_t, pointee_t>::value
3412 or std::is_same<number_float_t, pointee_t>::value
3413 ,
"incompatible pointer type");
3416 return get_impl_ptr(static_cast<const PointerType>(
nullptr));
3445 template<
typename ReferenceType,
typename std::enable_if<
3446 std::is_reference<ReferenceType>::value,
int>::type = 0>
3450 return get_ref_impl<ReferenceType>(*this);
3457 template<
typename ReferenceType,
typename std::enable_if<
3458 std::is_reference<ReferenceType>::value and
3459 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int>::type = 0>
3463 return get_ref_impl<ReferenceType>(*this);
3494 template <
typename ValueType,
typename std::enable_if <
3495 not std::is_pointer<ValueType>::value and
3496 not std::is_same<ValueType, typename string_t::value_type>::value
3497 #ifndef _MSC_VER // fix for issue #167 operator<< abiguity under VS2015 3498 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
3501 operator ValueType()
const 3504 return get<ValueType>();
3547 return m_value.array->at(idx);
3549 JSON_CATCH (std::out_of_range&)
3552 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
3557 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3590 return m_value.array->at(idx);
3592 JSON_CATCH (std::out_of_range&)
3595 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
3600 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3637 return m_value.object->at(key);
3639 JSON_CATCH (std::out_of_range&)
3642 JSON_THROW(std::out_of_range(
"key '" + key +
"' not found"));
3647 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3684 return m_value.object->at(key);
3686 JSON_CATCH (std::out_of_range&)
3689 JSON_THROW(std::out_of_range(
"key '" + key +
"' not found"));
3694 JSON_THROW(std::domain_error(
"cannot use at() with " + type_name()));
3728 m_type = value_t::array;
3729 m_value.
array = create<array_t>();
3737 if (idx >= m_value.array->size())
3739 m_value.array->insert(m_value.array->end(),
3740 idx - m_value.array->size() + 1,
3744 return m_value.array->operator[](idx);
3747 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3774 return m_value.
array->operator[](idx);
3777 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3812 m_type = value_t::object;
3813 m_value.
object = create<object_t>();
3820 return m_value.object->operator[](key);
3823 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3861 assert(m_value.object->find(key) != m_value.object->end());
3865 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
3895 template<
typename T, std::
size_t n>
3898 return operator[](static_cast<const T>(key));
3930 template<
typename T, std::
size_t n>
3933 return operator[](static_cast<const T>(key));
3963 template<
typename T>
3969 m_type = value_t::object;
3970 m_value = value_t::object;
3977 return m_value.object->operator[](key);
3980 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
4013 template<
typename T>
4019 assert(m_value.object->find(key) != m_value.object->end());
4023 JSON_THROW(std::domain_error(
"cannot use operator[] with " + type_name()));
4074 template<
class ValueType,
typename std::enable_if<
4075 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
4076 ValueType
value(
const typename object_t::key_type& key, ValueType default_value)
const 4082 const auto it = find(key);
4088 return default_value;
4092 JSON_THROW(std::domain_error(
"cannot use value() with " + type_name()));
4100 string_t value(
const typename object_t::key_type& key,
const char* default_value)
const 4102 return value(key,
string_t(default_value));
4146 template<
class ValueType,
typename std::enable_if<
4147 std::is_convertible<basic_json_t, ValueType>::value,
int>::type = 0>
4156 return ptr.get_checked(
this);
4158 JSON_CATCH (std::out_of_range&)
4160 return default_value;
4164 JSON_THROW(std::domain_error(
"cannot use value() with " + type_name()));
4173 return value(ptr,
string_t(default_value));
4306 template<
class IteratorType,
typename std::enable_if<
4307 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4308 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4313 if (
this != pos.m_object)
4315 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
4318 IteratorType result = end();
4322 case value_t::boolean:
4323 case value_t::number_float:
4324 case value_t::number_integer:
4325 case value_t::number_unsigned:
4326 case value_t::string:
4328 if (not pos.m_it.primitive_iterator.is_begin())
4330 JSON_THROW(std::out_of_range(
"iterator out of range"));
4335 AllocatorType<string_t> alloc;
4336 alloc.destroy(m_value.string);
4337 alloc.deallocate(m_value.string, 1);
4338 m_value.string =
nullptr;
4341 m_type = value_t::null;
4346 case value_t::object:
4348 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
4352 case value_t::array:
4354 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
4360 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4413 template<
class IteratorType,
typename std::enable_if<
4414 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
4415 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>::type
4417 IteratorType
erase(IteratorType first, IteratorType last)
4420 if (
this != first.m_object or
this != last.m_object)
4422 JSON_THROW(std::domain_error(
"iterators do not fit current value"));
4425 IteratorType result = end();
4429 case value_t::boolean:
4430 case value_t::number_float:
4431 case value_t::number_integer:
4432 case value_t::number_unsigned:
4433 case value_t::string:
4435 if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
4437 JSON_THROW(std::out_of_range(
"iterators out of range"));
4442 AllocatorType<string_t> alloc;
4443 alloc.destroy(m_value.string);
4444 alloc.deallocate(m_value.string, 1);
4445 m_value.string =
nullptr;
4448 m_type = value_t::null;
4453 case value_t::object:
4455 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
4456 last.m_it.object_iterator);
4460 case value_t::array:
4462 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
4463 last.m_it.array_iterator);
4469 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4510 return m_value.object->erase(key);
4513 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4547 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
4550 m_value.array->erase(m_value.array->begin() +
static_cast<difference_type>(idx));
4554 JSON_THROW(std::domain_error(
"cannot use erase() with " + type_name()));
4592 auto result = end();
4596 result.m_it.object_iterator = m_value.object->find(key);
4608 auto result = cend();
4612 result.m_it.object_iterator = m_value.object->find(key);
4642 return is_object() ? m_value.object->count(key) : 0;
4930 template<
typename IteratorType>
class iteration_proxy;
4946 return iteration_proxy<iterator>(cont);
4954 return iteration_proxy<const_iterator>(cont);
5014 case value_t::array:
5017 return m_value.array->empty();
5020 case value_t::object:
5023 return m_value.object->empty();
5082 case value_t::array:
5085 return m_value.array->size();
5088 case value_t::object:
5091 return m_value.object->size();
5142 case value_t::array:
5145 return m_value.array->max_size();
5148 case value_t::object:
5151 return m_value.object->max_size();
5198 case value_t::number_integer:
5200 m_value.number_integer = 0;
5204 case value_t::number_unsigned:
5206 m_value.number_unsigned = 0;
5210 case value_t::number_float:
5212 m_value.number_float = 0.0;
5216 case value_t::boolean:
5218 m_value.boolean =
false;
5222 case value_t::string:
5224 m_value.string->clear();
5228 case value_t::array:
5230 m_value.array->clear();
5234 case value_t::object:
5236 m_value.object->clear();
5270 if (not(is_null() or is_array()))
5272 JSON_THROW(std::domain_error(
"cannot use push_back() with " + type_name()));
5278 m_type = value_t::array;
5279 m_value = value_t::array;
5284 m_value.array->push_back(std::move(val));
5286 val.m_type = value_t::null;
5295 push_back(std::move(val));
5306 if (not(is_null() or is_array()))
5308 JSON_THROW(std::domain_error(
"cannot use push_back() with " + type_name()));
5314 m_type = value_t::array;
5315 m_value = value_t::array;
5320 m_value.array->push_back(val);
5356 if (not(is_null() or is_object()))
5358 JSON_THROW(std::domain_error(
"cannot use push_back() with " + type_name()));
5364 m_type = value_t::object;
5365 m_value = value_t::object;
5370 m_value.object->insert(val);
5410 if (is_object() and init.size() == 2 and init.begin()->is_string())
5412 const string_t key = *init.begin();
5413 push_back(
typename object_t::value_type(key, *(init.begin() + 1)));
5452 template<
class... Args>
5456 if (not(is_null() or is_array()))
5458 JSON_THROW(std::domain_error(
"cannot use emplace_back() with " + type_name()));
5464 m_type = value_t::array;
5465 m_value = value_t::array;
5470 m_value.array->emplace_back(std::forward<Args>(args)...);
5500 template<
class... Args>
5501 std::pair<iterator, bool>
emplace(Args&& ... args)
5504 if (not(is_null() or is_object()))
5506 JSON_THROW(std::domain_error(
"cannot use emplace() with " + type_name()));
5512 m_type = value_t::object;
5513 m_value = value_t::object;
5518 auto res = m_value.object->emplace(std::forward<Args>(args)...);
5521 it.m_it.object_iterator = res.first;
5524 return {it, res.second};
5555 if (pos.m_object !=
this)
5557 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5562 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
5566 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5575 return insert(pos, val);
5608 if (pos.m_object !=
this)
5610 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5615 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
5619 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5657 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5661 if (pos.m_object !=
this)
5663 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5667 if (first.m_object != last.m_object)
5669 JSON_THROW(std::domain_error(
"iterators do not fit"));
5672 if (first.m_object ==
this or last.m_object ==
this)
5674 JSON_THROW(std::domain_error(
"passed iterators may not belong to container"));
5679 result.m_it.array_iterator = m_value.array->insert(
5680 pos.m_it.array_iterator,
5681 first.m_it.array_iterator,
5682 last.m_it.array_iterator);
5715 JSON_THROW(std::domain_error(
"cannot use insert() with " + type_name()));
5719 if (pos.m_object !=
this)
5721 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5726 result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
5748 std::is_nothrow_move_constructible<value_t>::value and
5749 std::is_nothrow_move_assignable<value_t>::value and
5750 std::is_nothrow_move_constructible<json_value>::value and
5751 std::is_nothrow_move_assignable<json_value>::value
5754 std::swap(m_type, other.m_type);
5755 std::swap(m_value, other.m_value);
5784 std::swap(*(m_value.array), other);
5788 JSON_THROW(std::domain_error(
"cannot use swap() with " + type_name()));
5817 std::swap(*(m_value.object), other);
5821 JSON_THROW(std::domain_error(
"cannot use swap() with " + type_name()));
5850 std::swap(*(m_value.string), other);
5854 JSON_THROW(std::domain_error(
"cannot use swap() with " + type_name()));
5893 const auto lhs_type = lhs.type();
5894 const auto rhs_type = rhs.type();
5896 if (lhs_type == rhs_type)
5900 case value_t::array:
5902 return *lhs.m_value.array == *rhs.m_value.array;
5904 case value_t::object:
5906 return *lhs.m_value.object == *rhs.m_value.object;
5912 case value_t::string:
5914 return *lhs.m_value.string == *rhs.m_value.string;
5916 case value_t::boolean:
5918 return lhs.m_value.boolean == rhs.m_value.boolean;
5920 case value_t::number_integer:
5922 return lhs.m_value.number_integer == rhs.m_value.number_integer;
5924 case value_t::number_unsigned:
5926 return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
5928 case value_t::number_float:
5930 return lhs.m_value.number_float == rhs.m_value.number_float;
5938 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
5940 return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
5942 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
5944 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_integer);
5946 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
5948 return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
5950 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
5952 return lhs.m_value.number_float ==
static_cast<number_float_t>(rhs.m_value.number_unsigned);
5954 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
5956 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
5958 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
5960 return lhs.m_value.number_integer ==
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6016 return not (lhs == rhs);
6039 return not v.is_null();
6048 return not v.is_null();
6077 const auto lhs_type = lhs.type();
6078 const auto rhs_type = rhs.type();
6080 if (lhs_type == rhs_type)
6084 case value_t::array:
6086 return *lhs.m_value.array < *rhs.m_value.array;
6088 case value_t::object:
6090 return *lhs.m_value.object < *rhs.m_value.object;
6096 case value_t::string:
6098 return *lhs.m_value.string < *rhs.m_value.string;
6100 case value_t::boolean:
6102 return lhs.m_value.boolean < rhs.m_value.boolean;
6104 case value_t::number_integer:
6106 return lhs.m_value.number_integer < rhs.m_value.number_integer;
6108 case value_t::number_unsigned:
6110 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
6112 case value_t::number_float:
6114 return lhs.m_value.number_float < rhs.m_value.number_float;
6122 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
6124 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
6126 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
6128 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_integer);
6130 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
6132 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
6134 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
6136 return lhs.m_value.number_float <
static_cast<number_float_t>(rhs.m_value.number_unsigned);
6138 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
6140 return lhs.m_value.number_integer <
static_cast<number_integer_t>(rhs.m_value.number_unsigned);
6142 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
6144 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
6150 return operator<(lhs_type, rhs_type);
6172 return not (rhs < lhs);
6194 return not (lhs <= rhs);
6216 return not (lhs < rhs);
6258 const bool pretty_print = (o.width() > 0);
6259 const auto indentation = (pretty_print ? o.width() : 0);
6265 const auto old_locale = o.imbue(std::locale::classic());
6272 const auto old_precision = o.precision(std::numeric_limits<double>::digits10);
6275 j.
dump(o, pretty_print, static_cast<unsigned int>(indentation));
6278 o.imbue(old_locale);
6279 o.precision(old_precision);
6329 template<
class T, std::
size_t N>
6334 return parse(std::begin(array), std::end(array), cb);
6364 template<
typename CharT,
typename std::enable_if<
6365 std::is_pointer<CharT>::value and
6366 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
6367 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
6371 return parser(reinterpret_cast<const char*>(s), cb).
parse();
6401 return parser(i, cb).
parse();
6410 return parser(i, cb).
parse();
6454 template<
class IteratorType,
typename std::enable_if<
6456 std::random_access_iterator_tag,
6457 typename std::iterator_traits<IteratorType>::iterator_category>::value,
int>::type = 0>
6463 assert(std::accumulate(first, last, std::pair<bool, int>(
true, 0),
6464 [&first](std::pair<bool, int> res, decltype(*first) val)
6466 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
6471 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6472 "each element in the iterator range must have the size of 1 byte");
6476 if (std::distance(first, last) <= 0)
6478 return parser(
"").parse();
6481 return parser(first, last, cb).parse();
6524 template<
class ContiguousContainer,
typename std::enable_if<
6525 not std::is_pointer<ContiguousContainer>::value and
6527 std::random_access_iterator_tag,
6528 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value
6534 return parse(std::begin(c), std::end(c), cb);
6562 j = parser(i).
parse();
6572 j = parser(i).
parse();
6586 template<
typename T>
6587 static void add_to_vector(std::vector<uint8_t>& vec,
size_t bytes,
const T number)
6589 assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
6595 vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
6596 vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
6597 vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
6598 vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
6604 vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
6605 vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
6611 vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
6617 vec.push_back(static_cast<uint8_t>(number & 0xff));
6659 template<
typename T>
6660 static T get_from_vector(
const std::vector<uint8_t>& vec,
const size_t current_index)
6662 if (current_index +
sizeof(T) + 1 > vec.size())
6664 JSON_THROW(std::out_of_range(
"cannot read " + std::to_string(
sizeof(T)) +
" bytes from vector"));
6668 auto* ptr =
reinterpret_cast<uint8_t*
>(&result);
6669 for (
size_t i = 0; i <
sizeof(T); ++i)
6671 *ptr++ = vec[current_index +
sizeof(T) - i];
6686 static void to_msgpack_internal(
const basic_json& j, std::vector<uint8_t>& v)
6697 case value_t::boolean:
6700 v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
6704 case value_t::number_integer:
6706 if (j.m_value.number_integer >= 0)
6712 if (j.m_value.number_unsigned < 128)
6715 add_to_vector(v, 1, j.m_value.number_unsigned);
6717 else if (j.m_value.number_unsigned <= UINT8_MAX)
6721 add_to_vector(v, 1, j.m_value.number_unsigned);
6723 else if (j.m_value.number_unsigned <= UINT16_MAX)
6727 add_to_vector(v, 2, j.m_value.number_unsigned);
6729 else if (j.m_value.number_unsigned <= UINT32_MAX)
6733 add_to_vector(v, 4, j.m_value.number_unsigned);
6735 else if (j.m_value.number_unsigned <= UINT64_MAX)
6739 add_to_vector(v, 8, j.m_value.number_unsigned);
6744 if (j.m_value.number_integer >= -32)
6747 add_to_vector(v, 1, j.m_value.number_integer);
6749 else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
6753 add_to_vector(v, 1, j.m_value.number_integer);
6755 else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
6759 add_to_vector(v, 2, j.m_value.number_integer);
6761 else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
6765 add_to_vector(v, 4, j.m_value.number_integer);
6767 else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
6771 add_to_vector(v, 8, j.m_value.number_integer);
6777 case value_t::number_unsigned:
6779 if (j.m_value.number_unsigned < 128)
6782 add_to_vector(v, 1, j.m_value.number_unsigned);
6784 else if (j.m_value.number_unsigned <= UINT8_MAX)
6788 add_to_vector(v, 1, j.m_value.number_unsigned);
6790 else if (j.m_value.number_unsigned <= UINT16_MAX)
6794 add_to_vector(v, 2, j.m_value.number_unsigned);
6796 else if (j.m_value.number_unsigned <= UINT32_MAX)
6800 add_to_vector(v, 4, j.m_value.number_unsigned);
6802 else if (j.m_value.number_unsigned <= UINT64_MAX)
6806 add_to_vector(v, 8, j.m_value.number_unsigned);
6811 case value_t::number_float:
6815 const auto* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
6816 for (
size_t i = 0; i < 8; ++i)
6818 v.push_back(helper[7 - i]);
6823 case value_t::string:
6825 const auto N = j.m_value.string->size();
6829 v.push_back(static_cast<uint8_t>(0xa0 | N));
6835 add_to_vector(v, 1, N);
6837 else if (N <= 65535)
6841 add_to_vector(v, 2, N);
6843 else if (N <= 4294967295)
6847 add_to_vector(v, 4, N);
6851 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
6852 std::back_inserter(v));
6856 case value_t::array:
6858 const auto N = j.m_value.array->size();
6862 v.push_back(static_cast<uint8_t>(0x90 | N));
6864 else if (N <= 0xffff)
6868 add_to_vector(v, 2, N);
6870 else if (N <= 0xffffffff)
6874 add_to_vector(v, 4, N);
6878 for (
const auto& el : *j.m_value.array)
6880 to_msgpack_internal(el, v);
6885 case value_t::object:
6887 const auto N = j.m_value.object->size();
6891 v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
6893 else if (N <= 65535)
6897 add_to_vector(v, 2, N);
6899 else if (N <= 4294967295)
6903 add_to_vector(v, 4, N);
6907 for (
const auto& el : *j.m_value.object)
6909 to_msgpack_internal(el.first, v);
6910 to_msgpack_internal(el.second, v);
6932 static void to_cbor_internal(
const basic_json& j, std::vector<uint8_t>& v)
6942 case value_t::boolean:
6944 v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
6948 case value_t::number_integer:
6950 if (j.m_value.number_integer >= 0)
6955 if (j.m_value.number_integer <= 0x17)
6957 add_to_vector(v, 1, j.m_value.number_integer);
6959 else if (j.m_value.number_integer <= UINT8_MAX)
6963 add_to_vector(v, 1, j.m_value.number_integer);
6965 else if (j.m_value.number_integer <= UINT16_MAX)
6969 add_to_vector(v, 2, j.m_value.number_integer);
6971 else if (j.m_value.number_integer <= UINT32_MAX)
6975 add_to_vector(v, 4, j.m_value.number_integer);
6981 add_to_vector(v, 8, j.m_value.number_integer);
6988 const auto positive_number = -1 - j.m_value.number_integer;
6989 if (j.m_value.number_integer >= -24)
6991 v.push_back(static_cast<uint8_t>(0x20 + positive_number));
6993 else if (positive_number <= UINT8_MAX)
6997 add_to_vector(v, 1, positive_number);
6999 else if (positive_number <= UINT16_MAX)
7003 add_to_vector(v, 2, positive_number);
7005 else if (positive_number <= UINT32_MAX)
7009 add_to_vector(v, 4, positive_number);
7015 add_to_vector(v, 8, positive_number);
7021 case value_t::number_unsigned:
7023 if (j.m_value.number_unsigned <= 0x17)
7025 v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
7027 else if (j.m_value.number_unsigned <= 0xff)
7031 add_to_vector(v, 1, j.m_value.number_unsigned);
7033 else if (j.m_value.number_unsigned <= 0xffff)
7037 add_to_vector(v, 2, j.m_value.number_unsigned);
7039 else if (j.m_value.number_unsigned <= 0xffffffff)
7043 add_to_vector(v, 4, j.m_value.number_unsigned);
7045 else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
7049 add_to_vector(v, 8, j.m_value.number_unsigned);
7054 case value_t::number_float:
7058 const auto* helper =
reinterpret_cast<const uint8_t*
>(&(j.m_value.number_float));
7059 for (
size_t i = 0; i < 8; ++i)
7061 v.push_back(helper[7 - i]);
7066 case value_t::string:
7068 const auto N = j.m_value.string->size();
7071 v.push_back(0x60 + N);
7076 add_to_vector(v, 1, N);
7078 else if (N <= 0xffff)
7081 add_to_vector(v, 2, N);
7083 else if (N <= 0xffffffff)
7086 add_to_vector(v, 4, N);
7089 else if (N <= 0xffffffffffffffff)
7092 add_to_vector(v, 8, N);
7097 std::copy(j.m_value.string->begin(), j.m_value.string->end(),
7098 std::back_inserter(v));
7102 case value_t::array:
7104 const auto N = j.m_value.array->size();
7107 v.push_back(0x80 + N);
7112 add_to_vector(v, 1, N);
7114 else if (N <= 0xffff)
7117 add_to_vector(v, 2, N);
7119 else if (N <= 0xffffffff)
7122 add_to_vector(v, 4, N);
7125 else if (N <= 0xffffffffffffffff)
7128 add_to_vector(v, 8, N);
7133 for (
const auto& el : *j.m_value.array)
7135 to_cbor_internal(el, v);
7140 case value_t::object:
7142 const auto N = j.m_value.object->size();
7145 v.push_back(0xa0 + N);
7150 add_to_vector(v, 1, N);
7152 else if (N <= 0xffff)
7155 add_to_vector(v, 2, N);
7157 else if (N <= 0xffffffff)
7160 add_to_vector(v, 4, N);
7163 else if (N <= 0xffffffffffffffff)
7166 add_to_vector(v, 8, N);
7171 for (
const auto& el : *j.m_value.object)
7173 to_cbor_internal(el.first, v);
7174 to_cbor_internal(el.second, v);
7209 static void check_length(
const size_t size,
const size_t len,
const size_t offset)
7212 if (len > size or offset > size)
7214 JSON_THROW(std::out_of_range(
"len out of range"));
7218 if ((size > (std::numeric_limits<size_t>::max() - offset)))
7220 JSON_THROW(std::out_of_range(
"len+offset out of range"));
7224 if (len + offset > size)
7226 JSON_THROW(std::out_of_range(
"len+offset out of range"));
7244 static basic_json from_msgpack_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7247 check_length(v.size(), 1, idx);
7250 const size_t current_idx = idx++;
7252 if (v[current_idx] <= 0xbf)
7254 if (v[current_idx] <= 0x7f)
7256 return v[current_idx];
7258 if (v[current_idx] <= 0x8f)
7261 const size_t len = v[current_idx] & 0x0f;
7262 for (
size_t i = 0; i < len; ++i)
7264 std::string key = from_msgpack_internal(v, idx);
7265 result[key] = from_msgpack_internal(v, idx);
7269 else if (v[current_idx] <= 0x9f)
7272 const size_t len = v[current_idx] & 0x0f;
7273 for (
size_t i = 0; i < len; ++i)
7275 result.
push_back(from_msgpack_internal(v, idx));
7281 const size_t len = v[current_idx] & 0x1f;
7282 const size_t offset = current_idx + 1;
7284 check_length(v.size(), len, offset);
7285 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7288 else if (v[current_idx] >= 0xe0)
7290 return static_cast<int8_t
>(v[current_idx]);
7294 switch (v[current_idx])
7298 return value_t::null;
7315 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7317 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v.at(current_idx + 1 + byte);
7319 idx +=
sizeof(float);
7327 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7329 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v.at(current_idx + 1 + byte);
7331 idx +=
sizeof(double);
7338 return get_from_vector<uint8_t>(v, current_idx);
7344 return get_from_vector<uint16_t>(v, current_idx);
7350 return get_from_vector<uint32_t>(v, current_idx);
7356 return get_from_vector<uint64_t>(v, current_idx);
7362 return get_from_vector<int8_t>(v, current_idx);
7368 return get_from_vector<int16_t>(v, current_idx);
7374 return get_from_vector<int32_t>(v, current_idx);
7380 return get_from_vector<int64_t>(v, current_idx);
7385 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7386 const size_t offset = current_idx + 2;
7388 check_length(v.size(), len, offset);
7389 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7394 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7395 const size_t offset = current_idx + 3;
7397 check_length(v.size(), len, offset);
7398 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7403 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7404 const size_t offset = current_idx + 5;
7406 check_length(v.size(), len, offset);
7407 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7413 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7415 for (
size_t i = 0; i < len; ++i)
7417 result.
push_back(from_msgpack_internal(v, idx));
7425 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7427 for (
size_t i = 0; i < len; ++i)
7429 result.
push_back(from_msgpack_internal(v, idx));
7437 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7439 for (
size_t i = 0; i < len; ++i)
7441 std::string key = from_msgpack_internal(v, idx);
7442 result[key] = from_msgpack_internal(v, idx);
7450 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7452 for (
size_t i = 0; i < len; ++i)
7454 std::string key = from_msgpack_internal(v, idx);
7455 result[key] = from_msgpack_internal(v, idx);
7462 JSON_THROW(std::invalid_argument(
"error parsing a msgpack @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx]))));
7482 static basic_json from_cbor_internal(
const std::vector<uint8_t>& v,
size_t& idx)
7485 const size_t current_idx = idx++;
7487 switch (v.at(current_idx))
7515 return v[current_idx];
7521 return get_from_vector<uint8_t>(v, current_idx);
7527 return get_from_vector<uint16_t>(v, current_idx);
7533 return get_from_vector<uint32_t>(v, current_idx);
7539 return get_from_vector<uint64_t>(v, current_idx);
7568 return static_cast<int8_t
>(0x20 - 1 - v[current_idx]);
7575 return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
7581 return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
7587 return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
7593 return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
7622 const auto len =
static_cast<size_t>(v[current_idx] - 0x60);
7623 const size_t offset = current_idx + 1;
7625 check_length(v.size(), len, offset);
7626 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7631 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7632 const size_t offset = current_idx + 2;
7634 check_length(v.size(), len, offset);
7635 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7640 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7641 const size_t offset = current_idx + 3;
7643 check_length(v.size(), len, offset);
7644 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7649 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7650 const size_t offset = current_idx + 5;
7652 check_length(v.size(), len, offset);
7653 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7658 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7659 const size_t offset = current_idx + 9;
7661 check_length(v.size(), len, offset);
7662 return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
7668 while (v.at(idx) != 0xff)
7670 string_t s = from_cbor_internal(v, idx);
7705 const auto len =
static_cast<size_t>(v[current_idx] - 0x80);
7706 for (
size_t i = 0; i < len; ++i)
7708 result.
push_back(from_cbor_internal(v, idx));
7716 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7718 for (
size_t i = 0; i < len; ++i)
7720 result.
push_back(from_cbor_internal(v, idx));
7728 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7730 for (
size_t i = 0; i < len; ++i)
7732 result.
push_back(from_cbor_internal(v, idx));
7740 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7742 for (
size_t i = 0; i < len; ++i)
7744 result.
push_back(from_cbor_internal(v, idx));
7752 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7754 for (
size_t i = 0; i < len; ++i)
7756 result.
push_back(from_cbor_internal(v, idx));
7764 while (v.at(idx) != 0xff)
7766 result.
push_back(from_cbor_internal(v, idx));
7800 const auto len =
static_cast<size_t>(v[current_idx] - 0xa0);
7801 for (
size_t i = 0; i < len; ++i)
7803 std::string key = from_cbor_internal(v, idx);
7804 result[key] = from_cbor_internal(v, idx);
7812 const auto len =
static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
7814 for (
size_t i = 0; i < len; ++i)
7816 std::string key = from_cbor_internal(v, idx);
7817 result[key] = from_cbor_internal(v, idx);
7825 const auto len =
static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
7827 for (
size_t i = 0; i < len; ++i)
7829 std::string key = from_cbor_internal(v, idx);
7830 result[key] = from_cbor_internal(v, idx);
7838 const auto len =
static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
7840 for (
size_t i = 0; i < len; ++i)
7842 std::string key = from_cbor_internal(v, idx);
7843 result[key] = from_cbor_internal(v, idx);
7851 const auto len =
static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
7853 for (
size_t i = 0; i < len; ++i)
7855 std::string key = from_cbor_internal(v, idx);
7856 result[key] = from_cbor_internal(v, idx);
7864 while (v.at(idx) != 0xff)
7866 std::string key = from_cbor_internal(v, idx);
7867 result[key] = from_cbor_internal(v, idx);
7886 return value_t::null;
7900 const int half = (v.at(current_idx + 1) << 8) + v.at(current_idx + 2);
7901 const int exp = (half >> 10) & 0x1f;
7902 const int mant = half & 0x3ff;
7906 val = std::ldexp(mant, -24);
7910 val = std::ldexp(mant + 1024, exp - 25);
7914 val = mant == 0 ? INFINITY : NAN;
7916 return (half & 0x8000) != 0 ? -val : val;
7923 for (
size_t byte = 0; byte <
sizeof(float); ++byte)
7925 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
float) - byte - 1] = v.at(current_idx + 1 + byte);
7927 idx +=
sizeof(float);
7935 for (
size_t byte = 0; byte <
sizeof(double); ++byte)
7937 reinterpret_cast<uint8_t*
>(&res)[
sizeof(
double) - byte - 1] = v.at(current_idx + 1 + byte);
7939 idx +=
sizeof(double);
7945 JSON_THROW(std::invalid_argument(
"error parsing a CBOR @ " + std::to_string(current_idx) +
": " + std::to_string(static_cast<int>(v[current_idx]))));
7973 std::vector<uint8_t> result;
7974 to_msgpack_internal(j, result);
8003 return from_msgpack_internal(v, i);
8029 std::vector<uint8_t> result;
8030 to_cbor_internal(j, result);
8060 return from_cbor_internal(v, i);
8084 std::string type_name()
const 8091 case value_t::object:
8093 case value_t::array:
8095 case value_t::string:
8097 case value_t::boolean:
8099 case value_t::discarded:
8116 static std::size_t extra_space(
const string_t& s) noexcept
8118 return std::accumulate(s.begin(), s.end(),
size_t{},
8119 [](
size_t res,
typename string_t::value_type c)
8137 if (c >= 0x00 and c <= 0x1f)
8164 const auto space = extra_space(s);
8171 string_t result(s.size() + space,
'\\');
8172 std::size_t pos = 0;
8174 for (
const auto& c : s)
8181 result[pos + 1] =
'"';
8197 result[pos + 1] =
'b';
8205 result[pos + 1] =
'f';
8213 result[pos + 1] =
'n';
8221 result[pos + 1] =
'r';
8229 result[pos + 1] =
't';
8236 if (c >= 0x00 and c <= 0x1f)
8240 static const char hexify[16] =
8242 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
8243 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' 8248 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
8286 void dump(std::ostream& o,
8287 const bool pretty_print,
8288 const unsigned int indent_step,
8289 const unsigned int current_indent = 0)
const 8292 unsigned int new_indent = current_indent;
8296 case value_t::object:
8298 if (m_value.object->empty())
8309 new_indent += indent_step;
8313 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
8315 if (i != m_value.object->cbegin())
8317 o << (pretty_print ?
",\n" :
",");
8319 o <<
string_t(new_indent,
' ') <<
"\"" 8320 << escape_string(i->first) <<
"\":" 8321 << (pretty_print ?
" " :
"");
8322 i->second.dump(o, pretty_print, indent_step, new_indent);
8328 new_indent -= indent_step;
8332 o <<
string_t(new_indent,
' ') +
"}";
8336 case value_t::array:
8338 if (m_value.array->empty())
8349 new_indent += indent_step;
8353 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8355 if (i != m_value.array->cbegin())
8357 o << (pretty_print ?
",\n" :
",");
8360 i->dump(o, pretty_print, indent_step, new_indent);
8366 new_indent -= indent_step;
8370 o <<
string_t(new_indent,
' ') <<
"]";
8374 case value_t::string:
8376 o <<
string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
8380 case value_t::boolean:
8382 o << (m_value.boolean ?
"true" :
"false");
8386 case value_t::number_integer:
8388 o << m_value.number_integer;
8392 case value_t::number_unsigned:
8394 o << m_value.number_unsigned;
8398 case value_t::number_float:
8400 if (m_value.number_float == 0)
8403 o << (std::signbit(m_value.number_float) ?
"-0.0" :
"0.0");
8407 o << m_value.number_float;
8412 case value_t::discarded:
8432 value_t m_type = value_t::null;
8435 json_value m_value = {};
8452 class primitive_iterator_t
8461 void set_begin() noexcept
8467 void set_end() noexcept
8473 constexpr
bool is_begin()
const noexcept
8475 return (m_it == begin_value);
8479 constexpr
bool is_end()
const noexcept
8481 return (m_it == end_value);
8484 friend constexpr
bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8486 return lhs.m_it == rhs.m_it;
8489 friend constexpr
bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8491 return !(lhs == rhs);
8494 friend constexpr
bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8496 return lhs.m_it < rhs.m_it;
8499 friend constexpr
bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8501 return lhs.m_it <= rhs.m_it;
8504 friend constexpr
bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8506 return lhs.m_it > rhs.m_it;
8509 friend constexpr
bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8511 return lhs.m_it >= rhs.m_it;
8516 auto result = *
this;
8521 friend constexpr
difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
8523 return lhs.m_it - rhs.m_it;
8526 friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
8528 return os << it.m_it;
8531 primitive_iterator_t& operator++()
8537 primitive_iterator_t& operator++(
int)
8543 primitive_iterator_t& operator--()
8549 primitive_iterator_t& operator--(
int)
8572 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8582 struct internal_iterator
8585 typename object_t::iterator object_iterator;
8587 typename array_t::iterator array_iterator;
8589 primitive_iterator_t primitive_iterator;
8592 internal_iterator() noexcept
8593 : object_iterator(), array_iterator(), primitive_iterator()
8598 template<
typename IteratorType>
8599 class iteration_proxy
8603 class iteration_proxy_internal
8607 IteratorType anchor;
8609 size_t array_index = 0;
8612 explicit iteration_proxy_internal(IteratorType it) noexcept
8617 iteration_proxy_internal& operator*()
8623 iteration_proxy_internal& operator++()
8632 bool operator!= (
const iteration_proxy_internal& o)
const 8634 return anchor != o.anchor;
8640 assert(anchor.m_object !=
nullptr);
8642 switch (anchor.m_object->type())
8645 case value_t::array:
8647 return std::to_string(array_index);
8651 case value_t::object:
8653 return anchor.key();
8665 typename IteratorType::reference value()
const 8667 return anchor.value();
8672 typename IteratorType::reference container;
8676 explicit iteration_proxy(
typename IteratorType::reference cont)
8681 iteration_proxy_internal begin() noexcept
8683 return iteration_proxy_internal(container.begin());
8687 iteration_proxy_internal end() noexcept
8689 return iteration_proxy_internal(container.end());
8713 template<
typename U>
8714 class iter_impl :
public std::iterator<std::random_access_iterator_tag, U>
8720 static_assert(std::is_same<U, basic_json>::value
8721 or std::is_same<U, const basic_json>::value,
8722 "iter_impl only accepts (const) basic_json");
8730 using pointer =
typename std::conditional<std::is_const<U>::value,
8734 using reference =
typename std::conditional<std::is_const<U>::value,
8752 assert(m_object !=
nullptr);
8754 switch (m_object->m_type)
8756 case basic_json::value_t::object:
8758 m_it.object_iterator =
typename object_t::iterator();
8762 case basic_json::value_t::array:
8764 m_it.array_iterator =
typename array_t::iterator();
8770 m_it.primitive_iterator = primitive_iterator_t();
8790 ret.m_object = m_object;
8803 : m_object(other.m_object), m_it(other.m_it)
8812 std::is_nothrow_move_constructible<pointer>::value and
8813 std::is_nothrow_move_assignable<pointer>::value and
8814 std::is_nothrow_move_constructible<internal_iterator>::value and
8815 std::is_nothrow_move_assignable<internal_iterator>::value
8818 std::swap(m_object, other.m_object);
8819 std::swap(m_it, other.m_it);
8828 void set_begin() noexcept
8830 assert(m_object !=
nullptr);
8832 switch (m_object->m_type)
8834 case basic_json::value_t::object:
8836 m_it.object_iterator = m_object->m_value.object->begin();
8840 case basic_json::value_t::array:
8842 m_it.array_iterator = m_object->m_value.array->begin();
8846 case basic_json::value_t::null:
8849 m_it.primitive_iterator.set_end();
8855 m_it.primitive_iterator.set_begin();
8865 void set_end() noexcept
8867 assert(m_object !=
nullptr);
8869 switch (m_object->m_type)
8871 case basic_json::value_t::object:
8873 m_it.object_iterator = m_object->m_value.object->end();
8877 case basic_json::value_t::array:
8879 m_it.array_iterator = m_object->m_value.array->end();
8885 m_it.primitive_iterator.set_end();
8898 assert(m_object !=
nullptr);
8900 switch (m_object->m_type)
8902 case basic_json::value_t::object:
8904 assert(m_it.object_iterator != m_object->m_value.object->end());
8905 return m_it.object_iterator->second;
8908 case basic_json::value_t::array:
8910 assert(m_it.array_iterator != m_object->m_value.array->end());
8911 return *m_it.array_iterator;
8914 case basic_json::value_t::null:
8916 JSON_THROW(std::out_of_range(
"cannot get value"));
8921 if (m_it.primitive_iterator.is_begin())
8926 JSON_THROW(std::out_of_range(
"cannot get value"));
8937 assert(m_object !=
nullptr);
8939 switch (m_object->m_type)
8941 case basic_json::value_t::object:
8943 assert(m_it.object_iterator != m_object->m_value.object->end());
8944 return &(m_it.object_iterator->second);
8947 case basic_json::value_t::array:
8949 assert(m_it.array_iterator != m_object->m_value.array->end());
8950 return &*m_it.array_iterator;
8955 if (m_it.primitive_iterator.is_begin())
8960 JSON_THROW(std::out_of_range(
"cannot get value"));
8971 auto result = *
this;
8982 assert(m_object !=
nullptr);
8984 switch (m_object->m_type)
8986 case basic_json::value_t::object:
8988 std::advance(m_it.object_iterator, 1);
8992 case basic_json::value_t::array:
8994 std::advance(m_it.array_iterator, 1);
9000 ++m_it.primitive_iterator;
9014 auto result = *
this;
9025 assert(m_object !=
nullptr);
9027 switch (m_object->m_type)
9029 case basic_json::value_t::object:
9031 std::advance(m_it.object_iterator, -1);
9035 case basic_json::value_t::array:
9037 std::advance(m_it.array_iterator, -1);
9043 --m_it.primitive_iterator;
9058 if (m_object != other.m_object)
9060 JSON_THROW(std::domain_error(
"cannot compare iterators of different containers"));
9063 assert(m_object !=
nullptr);
9065 switch (m_object->m_type)
9067 case basic_json::value_t::object:
9069 return (m_it.object_iterator == other.m_it.object_iterator);
9072 case basic_json::value_t::array:
9074 return (m_it.array_iterator == other.m_it.array_iterator);
9079 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9090 return not operator==(other);
9100 if (m_object != other.m_object)
9102 JSON_THROW(std::domain_error(
"cannot compare iterators of different containers"));
9105 assert(m_object !=
nullptr);
9107 switch (m_object->m_type)
9109 case basic_json::value_t::object:
9111 JSON_THROW(std::domain_error(
"cannot compare order of object iterators"));
9114 case basic_json::value_t::array:
9116 return (m_it.array_iterator < other.m_it.array_iterator);
9121 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9132 return not other.operator < (*this);
9141 return not operator<=(other);
9150 return not operator<(other);
9159 assert(m_object !=
nullptr);
9161 switch (m_object->m_type)
9163 case basic_json::value_t::object:
9165 JSON_THROW(std::domain_error(
"cannot use offsets with object iterators"));
9168 case basic_json::value_t::array:
9170 std::advance(m_it.array_iterator, i);
9176 m_it.primitive_iterator += i;
9190 return operator+=(-i);
9199 auto result = *
this;
9210 auto result = *
this;
9221 assert(m_object !=
nullptr);
9223 switch (m_object->m_type)
9225 case basic_json::value_t::object:
9227 JSON_THROW(std::domain_error(
"cannot use offsets with object iterators"));
9230 case basic_json::value_t::array:
9232 return m_it.array_iterator - other.m_it.array_iterator;
9237 return m_it.primitive_iterator - other.m_it.primitive_iterator;
9248 assert(m_object !=
nullptr);
9250 switch (m_object->m_type)
9252 case basic_json::value_t::object:
9254 JSON_THROW(std::domain_error(
"cannot use operator[] for object iterators"));
9257 case basic_json::value_t::array:
9259 return *std::next(m_it.array_iterator, n);
9262 case basic_json::value_t::null:
9264 JSON_THROW(std::out_of_range(
"cannot get value"));
9269 if (m_it.primitive_iterator.get_value() == -n)
9274 JSON_THROW(std::out_of_range(
"cannot get value"));
9283 typename object_t::key_type
key()
const 9285 assert(m_object !=
nullptr);
9287 if (m_object->is_object())
9289 return m_it.object_iterator->first;
9292 JSON_THROW(std::domain_error(
"cannot use key() for non-object iterators"));
9308 internal_iterator m_it = internal_iterator();
9328 template<
typename Base>
9350 return base_iterator::operator++(1);
9356 base_iterator::operator++();
9363 return base_iterator::operator--(1);
9369 base_iterator::operator--();
9376 base_iterator::operator+=(i);
9383 auto result = *
this;
9391 auto result = *
this;
9399 return this->base() - other.base();
9405 return *(this->operator+(n));
9409 typename object_t::key_type
key()
const 9411 auto it = --this->base();
9418 auto it = --this->base();
9419 return it.operator * ();
9440 enum class token_type
9459 using lexer_char_t =
unsigned char;
9462 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
9465 assert(m_content !=
nullptr);
9466 m_start = m_cursor = m_content;
9467 m_limit = m_content + len;
9471 explicit lexer(std::istream& s)
9472 : m_stream(&s), m_line_buffer()
9477 JSON_THROW(std::invalid_argument(
"stream error"));
9484 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
9486 m_line_buffer[0] =
' ';
9487 m_line_buffer[1] =
' ';
9488 m_line_buffer[2] =
' ';
9494 lexer(
const lexer&) =
delete;
9495 lexer operator=(
const lexer&) =
delete;
9520 static string_t to_unicode(
const std::size_t codepoint1,
9521 const std::size_t codepoint2 = 0)
9524 std::size_t codepoint = codepoint1;
9527 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9530 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9544 JSON_THROW(std::invalid_argument(
"missing or wrong low surrogate"));
9550 if (codepoint < 0x80)
9553 result.append(1, static_cast<typename string_t::value_type>(codepoint));
9555 else if (codepoint <= 0x7ff)
9558 result.append(1, static_cast<typename string_t::value_type>(0xC0 | ((codepoint >> 6) & 0x1F)));
9559 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9561 else if (codepoint <= 0xffff)
9564 result.append(1, static_cast<typename string_t::value_type>(0xE0 | ((codepoint >> 12) & 0x0F)));
9565 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9566 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9568 else if (codepoint <= 0x10ffff)
9571 result.append(1, static_cast<typename string_t::value_type>(0xF0 | ((codepoint >> 18) & 0x07)));
9572 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 12) & 0x3F)));
9573 result.append(1, static_cast<typename string_t::value_type>(0x80 | ((codepoint >> 6) & 0x3F)));
9574 result.append(1, static_cast<typename string_t::value_type>(0x80 | (codepoint & 0x3F)));
9578 JSON_THROW(std::out_of_range(
"code points above 0x10FFFF are invalid"));
9585 static std::string token_type_name(
const token_type t)
9589 case token_type::uninitialized:
9590 return "<uninitialized>";
9591 case token_type::literal_true:
9592 return "true literal";
9593 case token_type::literal_false:
9594 return "false literal";
9595 case token_type::literal_null:
9596 return "null literal";
9597 case token_type::value_string:
9598 return "string literal";
9599 case token_type::value_number:
9600 return "number literal";
9601 case token_type::begin_array:
9603 case token_type::begin_object:
9605 case token_type::end_array:
9607 case token_type::end_object:
9609 case token_type::name_separator:
9611 case token_type::value_separator:
9613 case token_type::parse_error:
9614 return "<parse error>";
9615 case token_type::end_of_input:
9616 return "end of input";
9620 return "unknown token";
9655 assert(m_start !=
nullptr);
9660 unsigned int yyaccept = 0;
9661 static const unsigned char yybm[] =
9663 0, 0, 0, 0, 0, 0, 0, 0,
9664 0, 32, 32, 0, 0, 32, 0, 0,
9665 0, 0, 0, 0, 0, 0, 0, 0,
9666 0, 0, 0, 0, 0, 0, 0, 0,
9667 160, 128, 0, 128, 128, 128, 128, 128,
9668 128, 128, 128, 128, 128, 128, 128, 128,
9669 192, 192, 192, 192, 192, 192, 192, 192,
9670 192, 192, 128, 128, 128, 128, 128, 128,
9671 128, 128, 128, 128, 128, 128, 128, 128,
9672 128, 128, 128, 128, 128, 128, 128, 128,
9673 128, 128, 128, 128, 128, 128, 128, 128,
9674 128, 128, 128, 128, 0, 128, 128, 128,
9675 128, 128, 128, 128, 128, 128, 128, 128,
9676 128, 128, 128, 128, 128, 128, 128, 128,
9677 128, 128, 128, 128, 128, 128, 128, 128,
9678 128, 128, 128, 128, 128, 128, 128, 128,
9679 0, 0, 0, 0, 0, 0, 0, 0,
9680 0, 0, 0, 0, 0, 0, 0, 0,
9681 0, 0, 0, 0, 0, 0, 0, 0,
9682 0, 0, 0, 0, 0, 0, 0, 0,
9683 0, 0, 0, 0, 0, 0, 0, 0,
9684 0, 0, 0, 0, 0, 0, 0, 0,
9685 0, 0, 0, 0, 0, 0, 0, 0,
9686 0, 0, 0, 0, 0, 0, 0, 0,
9687 0, 0, 0, 0, 0, 0, 0, 0,
9688 0, 0, 0, 0, 0, 0, 0, 0,
9689 0, 0, 0, 0, 0, 0, 0, 0,
9690 0, 0, 0, 0, 0, 0, 0, 0,
9691 0, 0, 0, 0, 0, 0, 0, 0,
9692 0, 0, 0, 0, 0, 0, 0, 0,
9693 0, 0, 0, 0, 0, 0, 0, 0,
9694 0, 0, 0, 0, 0, 0, 0, 0,
9696 if ((m_limit - m_cursor) < 5)
9698 fill_line_buffer(5);
9701 if (yybm[0 + yych] & 32)
9703 goto basic_json_parser_6;
9713 goto basic_json_parser_2;
9717 goto basic_json_parser_4;
9719 goto basic_json_parser_9;
9725 goto basic_json_parser_4;
9729 goto basic_json_parser_10;
9731 goto basic_json_parser_12;
9740 goto basic_json_parser_4;
9744 goto basic_json_parser_13;
9746 goto basic_json_parser_15;
9752 goto basic_json_parser_17;
9756 goto basic_json_parser_4;
9758 goto basic_json_parser_19;
9770 goto basic_json_parser_21;
9772 goto basic_json_parser_4;
9778 goto basic_json_parser_23;
9782 goto basic_json_parser_4;
9784 goto basic_json_parser_24;
9793 goto basic_json_parser_25;
9795 goto basic_json_parser_4;
9801 goto basic_json_parser_26;
9805 goto basic_json_parser_28;
9807 goto basic_json_parser_4;
9811 basic_json_parser_2:
9814 last_token_type = token_type::end_of_input;
9817 basic_json_parser_4:
9819 basic_json_parser_5:
9821 last_token_type = token_type::parse_error;
9824 basic_json_parser_6:
9826 if (m_limit <= m_cursor)
9828 fill_line_buffer(1);
9831 if (yybm[0 + yych] & 32)
9833 goto basic_json_parser_6;
9838 basic_json_parser_9:
9840 yych = *(m_marker = ++m_cursor);
9843 goto basic_json_parser_5;
9847 goto basic_json_parser_31;
9851 goto basic_json_parser_5;
9855 goto basic_json_parser_31;
9857 goto basic_json_parser_5;
9858 basic_json_parser_10:
9861 last_token_type = token_type::value_separator;
9864 basic_json_parser_12:
9868 goto basic_json_parser_5;
9872 goto basic_json_parser_13;
9876 goto basic_json_parser_15;
9878 goto basic_json_parser_5;
9879 basic_json_parser_13:
9881 yych = *(m_marker = ++m_cursor);
9886 goto basic_json_parser_43;
9893 goto basic_json_parser_44;
9897 goto basic_json_parser_44;
9900 basic_json_parser_14:
9902 last_token_type = token_type::value_number;
9905 basic_json_parser_15:
9907 m_marker = ++m_cursor;
9908 if ((m_limit - m_cursor) < 3)
9910 fill_line_buffer(3);
9913 if (yybm[0 + yych] & 64)
9915 goto basic_json_parser_15;
9921 goto basic_json_parser_43;
9923 goto basic_json_parser_14;
9929 goto basic_json_parser_44;
9933 goto basic_json_parser_44;
9935 goto basic_json_parser_14;
9937 basic_json_parser_17:
9940 last_token_type = token_type::name_separator;
9943 basic_json_parser_19:
9946 last_token_type = token_type::begin_array;
9949 basic_json_parser_21:
9952 last_token_type = token_type::end_array;
9955 basic_json_parser_23:
9957 yych = *(m_marker = ++m_cursor);
9960 goto basic_json_parser_45;
9962 goto basic_json_parser_5;
9963 basic_json_parser_24:
9965 yych = *(m_marker = ++m_cursor);
9968 goto basic_json_parser_46;
9970 goto basic_json_parser_5;
9971 basic_json_parser_25:
9973 yych = *(m_marker = ++m_cursor);
9976 goto basic_json_parser_47;
9978 goto basic_json_parser_5;
9979 basic_json_parser_26:
9982 last_token_type = token_type::begin_object;
9985 basic_json_parser_28:
9988 last_token_type = token_type::end_object;
9991 basic_json_parser_30:
9993 if (m_limit <= m_cursor)
9995 fill_line_buffer(1);
9998 basic_json_parser_31:
9999 if (yybm[0 + yych] & 128)
10001 goto basic_json_parser_30;
10009 goto basic_json_parser_32;
10013 goto basic_json_parser_33;
10015 goto basic_json_parser_35;
10021 goto basic_json_parser_32;
10025 goto basic_json_parser_36;
10027 goto basic_json_parser_37;
10036 goto basic_json_parser_39;
10038 goto basic_json_parser_38;
10044 goto basic_json_parser_40;
10048 goto basic_json_parser_41;
10052 goto basic_json_parser_42;
10056 basic_json_parser_32:
10057 m_cursor = m_marker;
10060 goto basic_json_parser_5;
10064 goto basic_json_parser_14;
10066 basic_json_parser_33:
10069 last_token_type = token_type::value_string;
10072 basic_json_parser_35:
10074 if (m_limit <= m_cursor)
10076 fill_line_buffer(1);
10085 goto basic_json_parser_30;
10089 goto basic_json_parser_32;
10091 goto basic_json_parser_30;
10099 goto basic_json_parser_32;
10101 goto basic_json_parser_30;
10107 goto basic_json_parser_30;
10109 goto basic_json_parser_32;
10119 goto basic_json_parser_30;
10123 goto basic_json_parser_30;
10125 goto basic_json_parser_32;
10133 goto basic_json_parser_30;
10135 goto basic_json_parser_32;
10141 goto basic_json_parser_30;
10145 goto basic_json_parser_48;
10147 goto basic_json_parser_32;
10151 basic_json_parser_36:
10153 if (m_limit <= m_cursor)
10155 fill_line_buffer(1);
10160 goto basic_json_parser_32;
10164 goto basic_json_parser_30;
10166 goto basic_json_parser_32;
10167 basic_json_parser_37:
10169 if (m_limit <= m_cursor)
10171 fill_line_buffer(1);
10176 goto basic_json_parser_32;
10180 goto basic_json_parser_36;
10182 goto basic_json_parser_32;
10183 basic_json_parser_38:
10185 if (m_limit <= m_cursor)
10187 fill_line_buffer(1);
10192 goto basic_json_parser_32;
10196 goto basic_json_parser_36;
10198 goto basic_json_parser_32;
10199 basic_json_parser_39:
10201 if (m_limit <= m_cursor)
10203 fill_line_buffer(1);
10208 goto basic_json_parser_32;
10212 goto basic_json_parser_36;
10214 goto basic_json_parser_32;
10215 basic_json_parser_40:
10217 if (m_limit <= m_cursor)
10219 fill_line_buffer(1);
10224 goto basic_json_parser_32;
10228 goto basic_json_parser_38;
10230 goto basic_json_parser_32;
10231 basic_json_parser_41:
10233 if (m_limit <= m_cursor)
10235 fill_line_buffer(1);
10240 goto basic_json_parser_32;
10244 goto basic_json_parser_38;
10246 goto basic_json_parser_32;
10247 basic_json_parser_42:
10249 if (m_limit <= m_cursor)
10251 fill_line_buffer(1);
10256 goto basic_json_parser_32;
10260 goto basic_json_parser_38;
10262 goto basic_json_parser_32;
10263 basic_json_parser_43:
10264 yych = *++m_cursor;
10267 goto basic_json_parser_32;
10271 goto basic_json_parser_49;
10273 goto basic_json_parser_32;
10274 basic_json_parser_44:
10275 yych = *++m_cursor;
10280 goto basic_json_parser_51;
10282 goto basic_json_parser_32;
10288 goto basic_json_parser_51;
10292 goto basic_json_parser_32;
10296 goto basic_json_parser_52;
10298 goto basic_json_parser_32;
10300 basic_json_parser_45:
10301 yych = *++m_cursor;
10304 goto basic_json_parser_54;
10306 goto basic_json_parser_32;
10307 basic_json_parser_46:
10308 yych = *++m_cursor;
10311 goto basic_json_parser_55;
10313 goto basic_json_parser_32;
10314 basic_json_parser_47:
10315 yych = *++m_cursor;
10318 goto basic_json_parser_56;
10320 goto basic_json_parser_32;
10321 basic_json_parser_48:
10323 if (m_limit <= m_cursor)
10325 fill_line_buffer(1);
10332 goto basic_json_parser_32;
10336 goto basic_json_parser_57;
10338 goto basic_json_parser_32;
10344 goto basic_json_parser_57;
10348 goto basic_json_parser_32;
10352 goto basic_json_parser_57;
10354 goto basic_json_parser_32;
10356 basic_json_parser_49:
10358 m_marker = ++m_cursor;
10359 if ((m_limit - m_cursor) < 3)
10361 fill_line_buffer(3);
10368 goto basic_json_parser_14;
10372 goto basic_json_parser_49;
10374 goto basic_json_parser_14;
10380 goto basic_json_parser_44;
10384 goto basic_json_parser_44;
10386 goto basic_json_parser_14;
10388 basic_json_parser_51:
10389 yych = *++m_cursor;
10392 goto basic_json_parser_32;
10396 goto basic_json_parser_32;
10398 basic_json_parser_52:
10400 if (m_limit <= m_cursor)
10402 fill_line_buffer(1);
10407 goto basic_json_parser_14;
10411 goto basic_json_parser_52;
10413 goto basic_json_parser_14;
10414 basic_json_parser_54:
10415 yych = *++m_cursor;
10418 goto basic_json_parser_58;
10420 goto basic_json_parser_32;
10421 basic_json_parser_55:
10422 yych = *++m_cursor;
10425 goto basic_json_parser_59;
10427 goto basic_json_parser_32;
10428 basic_json_parser_56:
10429 yych = *++m_cursor;
10432 goto basic_json_parser_61;
10434 goto basic_json_parser_32;
10435 basic_json_parser_57:
10437 if (m_limit <= m_cursor)
10439 fill_line_buffer(1);
10446 goto basic_json_parser_32;
10450 goto basic_json_parser_63;
10452 goto basic_json_parser_32;
10458 goto basic_json_parser_63;
10462 goto basic_json_parser_32;
10466 goto basic_json_parser_63;
10468 goto basic_json_parser_32;
10470 basic_json_parser_58:
10471 yych = *++m_cursor;
10474 goto basic_json_parser_64;
10476 goto basic_json_parser_32;
10477 basic_json_parser_59:
10480 last_token_type = token_type::literal_null;
10483 basic_json_parser_61:
10486 last_token_type = token_type::literal_true;
10489 basic_json_parser_63:
10491 if (m_limit <= m_cursor)
10493 fill_line_buffer(1);
10500 goto basic_json_parser_32;
10504 goto basic_json_parser_66;
10506 goto basic_json_parser_32;
10512 goto basic_json_parser_66;
10516 goto basic_json_parser_32;
10520 goto basic_json_parser_66;
10522 goto basic_json_parser_32;
10524 basic_json_parser_64:
10527 last_token_type = token_type::literal_false;
10530 basic_json_parser_66:
10532 if (m_limit <= m_cursor)
10534 fill_line_buffer(1);
10541 goto basic_json_parser_32;
10545 goto basic_json_parser_30;
10547 goto basic_json_parser_32;
10553 goto basic_json_parser_30;
10557 goto basic_json_parser_32;
10561 goto basic_json_parser_30;
10563 goto basic_json_parser_32;
10569 return last_token_type;
10600 void fill_line_buffer(
size_t n = 0)
10603 assert(m_line_buffer.empty()
10604 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
10607 assert(m_line_buffer.empty()
10608 or m_limit == m_content + m_line_buffer.size());
10611 assert(m_content <= m_start);
10612 assert(m_start <= m_cursor);
10613 assert(m_cursor <= m_limit);
10614 assert(m_marker ==
nullptr or m_marker <= m_limit);
10617 const auto num_processed_chars =
static_cast<size_t>(m_start - m_content);
10619 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
10621 const auto offset_cursor = m_cursor - m_start;
10624 if (m_stream ==
nullptr or m_stream->eof())
10629 m_line_buffer.assign(m_start, m_limit);
10633 m_line_buffer.append(1,
'\x00');
10636 m_line_buffer.append(n - 1,
'\x01');
10642 m_line_buffer.erase(0, num_processed_chars);
10644 m_line_buffer_tmp.clear();
10645 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
10648 m_line_buffer += m_line_buffer_tmp;
10649 m_line_buffer.push_back(
'\n');
10653 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
10654 assert(m_content !=
nullptr);
10655 m_start = m_content;
10656 m_marker = m_start + offset_marker;
10657 m_cursor = m_start + offset_cursor;
10658 m_limit = m_start + m_line_buffer.size();
10664 assert(m_start !=
nullptr);
10665 return string_t(reinterpret_cast<typename string_t::const_pointer>(m_start),
10666 static_cast<size_t>(m_cursor - m_start));
10728 assert(m_cursor - m_start >= 2);
10731 result.reserve(static_cast<size_t>(m_cursor - m_start - 2));
10734 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10737 auto e = std::find(i, m_cursor - 1,
'\\');
10741 for (
auto k = i; k < e; k++)
10743 result.push_back(static_cast<typename string_t::value_type>(*k));
10801 auto codepoint = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>(i + 1),
10802 4).c_str(),
nullptr, 16);
10805 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10808 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
10810 JSON_THROW(std::invalid_argument(
"missing low surrogate"));
10814 auto codepoint2 = std::strtoul(std::string(reinterpret_cast<typename string_t::const_pointer>
10815 (i + 7), 4).c_str(),
nullptr, 16);
10816 result += to_unicode(codepoint, codepoint2);
10820 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10823 JSON_THROW(std::invalid_argument(
"missing high surrogate"));
10828 result += to_unicode(codepoint);
10854 long double str_to_float_t(
long double* ,
char** endptr)
const 10856 return std::strtold(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10872 double str_to_float_t(
double* ,
char** endptr)
const 10874 return std::strtod(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10890 float str_to_float_t(
float* ,
char** endptr)
const 10892 return std::strtof(reinterpret_cast<typename string_t::const_pointer>(m_start), endptr);
10918 assert(m_start !=
nullptr);
10920 const lexer::lexer_char_t* curptr = m_start;
10932 if (*curptr ==
'-')
10934 type = value_t::number_integer;
10935 max =
static_cast<uint64_t
>((std::numeric_limits<number_integer_t>::max)()) + 1;
10940 type = value_t::number_unsigned;
10941 max =
static_cast<uint64_t
>((std::numeric_limits<number_unsigned_t>::max)());
10945 for (; curptr < m_cursor; curptr++)
10948 if (*curptr < '0' or* curptr >
'9')
10950 if (*curptr ==
'.')
10953 type = value_t::number_float;
10958 type = value_t::number_float;
10963 if (type != value_t::number_float)
10969 if (value > (max - digit) / 10)
10972 type = value_t::number_float;
10977 value = value * 10 + digit;
10983 if (type == value_t::number_unsigned)
10985 result.m_value.number_unsigned = value;
10987 else if (type == value_t::number_integer)
10991 assert(value >= 0);
10992 assert(value <= max);
11009 result.m_value.number_float = str_to_float_t(static_cast<number_float_t*>(
nullptr),
nullptr);
11012 if (not std::isfinite(result.m_value.number_float))
11014 type = value_t::null;
11015 result.m_value = basic_json::json_value();
11020 result.m_type = type;
11025 std::istream* m_stream =
nullptr;
11031 const lexer_char_t* m_content =
nullptr;
11033 const lexer_char_t* m_start =
nullptr;
11035 const lexer_char_t* m_marker =
nullptr;
11037 const lexer_char_t* m_cursor =
nullptr;
11039 const lexer_char_t* m_limit =
nullptr;
11041 token_type last_token_type = token_type::end_of_input;
11055 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff), std::strlen(buff))
11060 : callback(cb), m_lexer(is)
11064 template<
class IteratorType,
typename std::enable_if<
11065 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
11068 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
11070 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
11071 static_cast<size_t>(std::distance(first, last)))
11081 result.assert_invariant();
11083 expect(lexer::token_type::end_of_input);
11094 auto result =
basic_json(value_t::discarded);
11096 switch (last_token)
11098 case lexer::token_type::begin_object:
11100 if (keep and (not callback
11101 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
11104 result.m_type = value_t::object;
11105 result.m_value = value_t::object;
11112 if (last_token == lexer::token_type::end_object)
11115 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
11123 unexpect(lexer::token_type::value_separator);
11129 if (last_token == lexer::token_type::value_separator)
11135 expect(lexer::token_type::value_string);
11136 const auto key = m_lexer.get_string();
11138 bool keep_tag =
false;
11144 keep_tag = callback(depth, parse_event_t::key, k);
11154 expect(lexer::token_type::name_separator);
11158 auto value = parse_internal(keep);
11159 if (keep and keep_tag and not value.is_discarded())
11161 result[key] = std::move(value);
11164 while (last_token == lexer::token_type::value_separator);
11167 expect(lexer::token_type::end_object);
11169 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
11177 case lexer::token_type::begin_array:
11179 if (keep and (not callback
11180 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
11183 result.m_type = value_t::array;
11184 result.m_value = value_t::array;
11191 if (last_token == lexer::token_type::end_array)
11194 if (callback and not callback(--depth, parse_event_t::array_end, result))
11202 unexpect(lexer::token_type::value_separator);
11208 if (last_token == lexer::token_type::value_separator)
11214 auto value = parse_internal(keep);
11215 if (keep and not value.is_discarded())
11217 result.push_back(std::move(value));
11220 while (last_token == lexer::token_type::value_separator);
11223 expect(lexer::token_type::end_array);
11225 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
11233 case lexer::token_type::literal_null:
11236 result.m_type = value_t::null;
11240 case lexer::token_type::value_string:
11242 const auto s = m_lexer.get_string();
11248 case lexer::token_type::literal_true:
11251 result.m_type = value_t::boolean;
11252 result.m_value =
true;
11256 case lexer::token_type::literal_false:
11259 result.m_type = value_t::boolean;
11260 result.m_value =
false;
11264 case lexer::token_type::value_number:
11266 m_lexer.get_number(result);
11274 unexpect(last_token);
11278 if (keep and callback and not callback(depth, parse_event_t::value, result))
11286 typename lexer::token_type get_token()
11288 last_token = m_lexer.scan();
11292 void expect(
typename lexer::token_type t)
const 11294 if (t != last_token)
11296 std::string error_msg =
"parse error - unexpected ";
11297 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
11299 lexer::token_type_name(last_token));
11300 error_msg +=
"; expected " + lexer::token_type_name(t);
11301 JSON_THROW(std::invalid_argument(error_msg));
11305 void unexpect(
typename lexer::token_type t)
const 11307 if (t == last_token)
11309 std::string error_msg =
"parse error - unexpected ";
11310 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
11312 lexer::token_type_name(last_token));
11313 JSON_THROW(std::invalid_argument(error_msg));
11323 typename lexer::token_type last_token = lexer::token_type::uninitialized;
11369 : reference_tokens(split(s))
11387 std::string to_string()
const noexcept
11389 return std::accumulate(reference_tokens.begin(),
11390 reference_tokens.end(), std::string{},
11391 [](
const std::string & a,
const std::string & b)
11393 return a +
"/" + escape(b);
11398 operator std::string()
const 11400 return to_string();
11405 std::string pop_back()
11409 JSON_THROW(std::domain_error(
"JSON pointer has no parent"));
11412 auto last = reference_tokens.back();
11413 reference_tokens.pop_back();
11418 bool is_root()
const 11420 return reference_tokens.empty();
11427 JSON_THROW(std::domain_error(
"JSON pointer has no parent"));
11431 result.reference_tokens = {reference_tokens[0]};
11446 for (
const auto& reference_token : reference_tokens)
11448 switch (result->m_type)
11450 case value_t::null:
11452 if (reference_token ==
"0")
11455 result = &result->operator[](0);
11460 result = &result->operator[](reference_token);
11465 case value_t::object:
11468 result = &result->operator[](reference_token);
11472 case value_t::array:
11475 result = &result->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11488 JSON_THROW(std::domain_error(
"invalid value to unflatten"));
11517 for (
const auto& reference_token : reference_tokens)
11520 if (ptr->m_type == value_t::null)
11523 const bool nums = std::all_of(reference_token.begin(),
11524 reference_token.end(),
11527 return std::isdigit(x);
11532 if (nums or reference_token ==
"-")
11534 *ptr = value_t::array;
11538 *ptr = value_t::object;
11542 switch (ptr->m_type)
11544 case value_t::object:
11547 ptr = &ptr->operator[](reference_token);
11551 case value_t::array:
11554 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11556 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11559 if (reference_token ==
"-")
11562 ptr = &ptr->operator[](ptr->m_value.array->size());
11567 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11574 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11584 for (
const auto& reference_token : reference_tokens)
11586 switch (ptr->m_type)
11588 case value_t::object:
11591 ptr = &ptr->
at(reference_token);
11595 case value_t::array:
11597 if (reference_token ==
"-")
11600 throw std::out_of_range(
"array index '-' (" +
11601 std::to_string(ptr->m_value.array->size()) +
11602 ") is out of range");
11606 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11608 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11612 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11618 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11636 for (
const auto& reference_token : reference_tokens)
11638 switch (ptr->m_type)
11640 case value_t::object:
11643 ptr = &ptr->operator[](reference_token);
11647 case value_t::array:
11649 if (reference_token ==
"-")
11652 throw std::out_of_range(
"array index '-' (" +
11653 std::to_string(ptr->m_value.array->size()) +
11654 ") is out of range");
11658 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11660 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11664 ptr = &ptr->operator[](
static_cast<size_type>(std::stoi(reference_token)));
11670 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11680 for (
const auto& reference_token : reference_tokens)
11682 switch (ptr->m_type)
11684 case value_t::object:
11687 ptr = &ptr->
at(reference_token);
11691 case value_t::array:
11693 if (reference_token ==
"-")
11696 throw std::out_of_range(
"array index '-' (" +
11697 std::to_string(ptr->m_value.array->size()) +
11698 ") is out of range");
11702 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11704 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11708 ptr = &ptr->at(static_cast<size_type>(std::stoi(reference_token)));
11714 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11723 static std::vector<std::string> split(
const std::string& reference_string)
11725 std::vector<std::string> result;
11728 if (reference_string.empty())
11734 if (reference_string[0] !=
'/')
11736 JSON_THROW(std::domain_error(
"JSON pointer must be empty or begin with '/'"));
11744 size_t slash = reference_string.find_first_of(
'/', 1),
11753 slash = reference_string.find_first_of(
'/', start))
11757 auto reference_token = reference_string.substr(start, slash - start);
11760 for (
size_t pos = reference_token.find_first_of(
'~');
11761 pos != std::string::npos;
11762 pos = reference_token.find_first_of(
'~', pos + 1))
11764 assert(reference_token[pos] ==
'~');
11767 if (pos == reference_token.size() - 1 or
11768 (reference_token[pos + 1] !=
'0' and
11769 reference_token[pos + 1] !=
'1'))
11771 JSON_THROW(std::domain_error(
"escape error: '~' must be followed with '0' or '1'"));
11776 unescape(reference_token);
11777 result.push_back(reference_token);
11796 static void replace_substring(std::string& s,
11797 const std::string& f,
11798 const std::string& t)
11800 assert(not f.empty());
11803 size_t pos = s.find(f);
11804 pos != std::string::npos;
11805 s.replace(pos, f.size(), t),
11806 pos = s.find(f, pos + t.size())
11811 static std::string escape(std::string s)
11814 replace_substring(s,
"~",
"~0");
11815 replace_substring(s,
"/",
"~1");
11820 static void unescape(std::string& s)
11823 replace_substring(s,
"~1",
"/");
11825 replace_substring(s,
"~0",
"~");
11835 static void flatten(
const std::string& reference_string,
11839 switch (value.m_type)
11841 case value_t::array:
11843 if (value.m_value.array->empty())
11846 result[reference_string] =
nullptr;
11851 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
11853 flatten(reference_string +
"/" + std::to_string(i),
11854 value.m_value.array->operator[](i), result);
11860 case value_t::object:
11862 if (value.m_value.object->empty())
11865 result[reference_string] =
nullptr;
11870 for (
const auto& element : *value.m_value.object)
11872 flatten(reference_string +
"/" + escape(element.first),
11873 element.second, result);
11882 result[reference_string] = value;
11897 JSON_THROW(std::domain_error(
"only objects can be unflattened"));
11903 for (
const auto& element : *value.m_value.object)
11905 if (not element.second.is_primitive())
11907 JSON_THROW(std::domain_error(
"values in object must be primitive"));
11915 json_pointer(element.first).get_and_create(result) = element.second;
11925 return lhs.reference_tokens == rhs.reference_tokens;
11931 return !(lhs == rhs);
11935 std::vector<std::string> reference_tokens {};
11980 return ptr.get_unchecked(
this);
12007 return ptr.get_unchecked(
this);
12032 return ptr.get_checked(
this);
12057 return ptr.get_checked(
this);
12085 json_pointer::flatten(
"", *
this, result);
12118 return json_pointer::unflatten(*
this);
12172 enum class patch_operations {add,
remove, replace, move, copy, test, invalid};
12174 const auto get_op = [](
const std::string op)
12178 return patch_operations::add;
12180 if (op ==
"remove")
12182 return patch_operations::remove;
12184 if (op ==
"replace")
12186 return patch_operations::replace;
12190 return patch_operations::move;
12194 return patch_operations::copy;
12198 return patch_operations::test;
12201 return patch_operations::invalid;
12216 if (top_pointer != ptr)
12218 result.
at(top_pointer);
12222 const auto last_path = ptr.pop_back();
12225 switch (parent.m_type)
12227 case value_t::null:
12228 case value_t::object:
12231 parent[last_path] = val;
12235 case value_t::array:
12237 if (last_path ==
"-")
12244 const auto idx = std::stoi(last_path);
12245 if (static_cast<size_type>(idx) > parent.
size())
12248 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
12269 const auto operation_remove = [&result](
json_pointer & ptr)
12272 const auto last_path = ptr.pop_back();
12279 auto it = parent.
find(last_path);
12280 if (it != parent.
end())
12286 JSON_THROW(std::out_of_range(
"key '" + last_path +
"' not found"));
12292 parent.
erase(static_cast<size_type>(std::stoi(last_path)));
12300 JSON_THROW(std::invalid_argument(
"JSON patch must be an array of objects"));
12304 for (
const auto& val : json_patch)
12307 const auto get_value = [&val](
const std::string & op,
12308 const std::string & member,
12312 auto it = val.m_value.object->find(member);
12315 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
12318 if (it == val.m_value.object->end())
12320 JSON_THROW(std::invalid_argument(error_msg +
" must have member '" + member +
"'"));
12324 if (string_type and not it->second.is_string())
12326 JSON_THROW(std::invalid_argument(error_msg +
" must have string member '" + member +
"'"));
12334 if (not val.is_object())
12336 JSON_THROW(std::invalid_argument(
"JSON patch must be an array of objects"));
12340 const std::string op = get_value(
"op",
"op",
true);
12341 const std::string path = get_value(op,
"path",
true);
12344 switch (get_op(op))
12346 case patch_operations::add:
12348 operation_add(ptr, get_value(
"add",
"value",
false));
12352 case patch_operations::remove:
12354 operation_remove(ptr);
12358 case patch_operations::replace:
12361 result.
at(ptr) = get_value(
"replace",
"value",
false);
12365 case patch_operations::move:
12367 const std::string from_path = get_value(
"move",
"from",
true);
12377 operation_remove(from_ptr);
12378 operation_add(ptr, v);
12382 case patch_operations::copy:
12384 const std::string from_path = get_value(
"copy",
"from",
true);;
12388 result[ptr] = result.
at(from_ptr);
12392 case patch_operations::test:
12394 bool success =
false;
12399 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
12401 JSON_CATCH (std::out_of_range&)
12409 JSON_THROW(std::domain_error(
"unsuccessful: " + val.dump()));
12415 case patch_operations::invalid:
12419 JSON_THROW(std::invalid_argument(
"operation value '" + op +
"' is invalid"));
12461 const std::string& path =
"")
12467 if (source == target)
12472 if (source.
type() != target.
type())
12484 switch (source.
type())
12486 case value_t::array:
12490 while (i < source.
size() and i < target.
size())
12493 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
12494 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12503 while (i < source.
size())
12507 result.insert(result.begin() + end_index, object(
12510 {
"path", path +
"/" + std::to_string(i)}
12516 while (i < target.
size())
12521 {
"path", path +
"/" + std::to_string(i)},
12522 {
"value", target[i]}
12530 case value_t::object:
12533 for (
auto it = source.
begin(); it != source.
end(); ++it)
12536 const auto key = json_pointer::escape(it.key());
12538 if (target.
find(it.key()) != target.
end())
12541 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
12542 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
12547 result.push_back(
object(
12550 {
"path", path +
"/" + key}
12556 for (
auto it = target.
begin(); it != target.
end(); ++it)
12558 if (source.
find(it.key()) == source.
end())
12561 const auto key = json_pointer::escape(it.key());
12565 {
"path", path +
"/" + key},
12566 {
"value", it.value()}
12625 is_nothrow_move_constructible<nlohmann::json>::value and
12626 is_nothrow_move_assignable<nlohmann::json>::value
12644 const auto& h = hash<nlohmann::json::string_t>();
12663 inline nlohmann::json operator "" _json(
const char* s, std::size_t n)
12687 #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) 12688 #pragma GCC diagnostic pop 12695 #undef JSON_DEPRECATED typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
const_reference front() const
access the first element
JSONSerializer< T, SFINAE > json_serializer
NumberFloatType number_float_t
a type for a number (floating-point)
static basic_json from_msgpack(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in MessagePack format
BooleanType boolean_t
a type for a boolean
typename basic_json::value_type value_type
the type of the values when the iterator is dereferenced
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
static iteration_proxy< const_iterator > iterator_wrapper(const_reference cont)
wrapper to access iterator member functions in range-based for
const_reference operator[](size_type idx) const
access specified array element
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adaptor
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
iterator begin() noexcept
returns an iterator to the first element
static basic_json parse(const CharT s, const parser_callback_t cb=nullptr)
deserialize from string literal
difference_type operator-(const iter_impl &other) const
return difference
iterator end() noexcept
returns an iterator to one past the last element
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
reference operator+=(const basic_json &val)
add an object to an array
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
static basic_json object(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an object from an initializer list
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
iter_impl(const iter_impl &other) noexcept
copy constructor
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
ReferenceType get_ref()
get a reference value (implicit)
void push_back(std::initializer_list< basic_json > init)
add an object to an object
a class to store JSON values
iterator insert(const_iterator pos, std::initializer_list< basic_json > ilist)
inserts elements
void erase(const size_type idx)
remove element from a JSON array given an index
friend bool operator==(std::nullptr_t, const_reference v) noexcept
comparison: equal
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)
const_iterator end() const noexcept
returns a const iterator to one past the last element
const_iterator find(typename object_t::key_type key) const
find an element in a JSON object
static allocator_type get_allocator()
returns the allocator associated with the container
reference operator[](size_type idx)
access specified array element
default JSONSerializer template argument
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
iterator find(typename object_t::key_type key)
find an element in a JSON object
constexpr bool is_structured() const noexcept
return whether type is structured
ObjectType< StringType, basic_json, std::less< StringType >, AllocatorType< std::pair< const StringType, basic_json > >> object_t
a type for an object
static basic_json from_cbor(const std::vector< uint8_t > &v)
create a JSON value from a byte vector in CBOR format
static basic_json parse(T(&array)[N], const parser_callback_t cb=nullptr)
deserialize from an array
bool operator!=(const iter_impl &other) const
comparison: not equal
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)
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
void swap(string_t &other)
exchanges the values
void swap(object_t &other)
exchanges the values
static basic_json parse(std::istream &i, const parser_callback_t cb=nullptr)
deserialize from stream
reference operator+=(std::initializer_list< basic_json > init)
add an object to an object
size_type count(typename object_t::key_type key) const
returns the number of occurrences of a key in a JSON object
object_t::key_type key() const
return the key of an object iterator
json_reverse_iterator & operator--()
pre-decrement (–it)
std::bidirectional_iterator_tag iterator_category
the category of the iterator
json_reverse_iterator operator--(int)
post-decrement (it–)
iter_impl operator-(difference_type i)
subtract from iterator
size_type max_size() const noexcept
returns the maximum possible number of elements
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
reference at(size_type idx)
access specified array element with bounds checking
JSON_DEPRECATED basic_json(std::istream &i, const parser_callback_t cb=nullptr)
construct a JSON value given an input stream
friend class basic_json
allow basic_json to access private members
reference operator[](difference_type n) const
access to successor
constexpr bool is_number() const noexcept
return whether value is a number
const value_type & const_reference
the type of an element const reference
bool operator==(const iter_impl &other) const
comparison: equal
constexpr bool is_primitive() const noexcept
return whether type is primitive
reference front()
access the first element
reference operator*() const
return a reference to the value pointed to by the iterator
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
const_reference operator[](T *(&key)[n]) const
read-only access specified object element
std::size_t size_type
a type to represent container sizes
const_iterator begin() const noexcept
returns a const iterator to the first element
ReferenceType get_ref() const
get a reference value (implicit)
iter_impl & operator++()
pre-increment (++it)
reference operator[](const typename object_t::key_type &key)
access specified object element
static iteration_proxy< iterator > iterator_wrapper(reference cont)
wrapper to access iterator member functions in range-based for
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
iter_impl operator+(difference_type i)
add to iterator
NumberIntegerType number_integer_t
a type for a number (integer)
constexpr bool is_array() const noexcept
return whether value is an array
const_reference at(size_type idx) const
access specified array element with bounds checking
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
size_type size() const noexcept
returns the number of elements
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
const_iterator cbegin() const noexcept
returns a const iterator to the first element
reference operator[](T *key)
access specified object element
static basic_json meta()
returns version information on the library
static basic_json parse(std::istream &&i, const parser_callback_t cb=nullptr)
deserialize from stream
ValueType value(const json_pointer &ptr, ValueType default_value) const
access specified object element via JSON Pointer with default value
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
json_reverse_iterator operator++(int)
post-increment (it++)
constexpr const auto & from_json
reference value() const
return the value of an iterator
constexpr bool is_boolean() const noexcept
return whether value is a boolean
friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
PointerType get_ptr() noexcept
get a pointer value (implicit)
namespace for Niels Lohmann
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
basic_json(const value_t value_type)
create an empty value with a given type
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
reference operator+=(const typename object_t::value_type &val)
add an object to an object
constexpr bool is_object() const noexcept
return whether value is an object
reference operator+=(basic_json &&val)
add an object to an array
difference_type operator-(const json_reverse_iterator &other) const
return difference
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr)
deserialize from an iterator range with contiguous storage
json_reverse_iterator & operator+=(difference_type i)
add to iterator
iter_impl operator++(int)
post-increment (it++)
bool operator<=(const iter_impl &other) const
comparison: less than or equal
iter_impl operator--(int)
post-decrement (it–)
iter_impl & operator--()
pre-decrement (–it)
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
reference back()
access the last element
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
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
iter_impl(pointer object) noexcept
constructor for a given JSON instance
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
std::function< bool(int depth, parse_event_t event, basic_json &parsed)> parser_callback_t
per-element parser callback type
void emplace_back(Args &&... args)
add an object to an array
constexpr bool is_string() const noexcept
return whether value is a string
json_reverse_iterator operator+(difference_type i) const
add to iterator
const_iterator cend() const noexcept
returns a const iterator to one past the last element
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
void push_back(const basic_json &val)
add an object to an array
void push_back(const typename object_t::value_type &val)
add an object to an object
void swap(array_t &other)
exchanges the values
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
constexpr const auto & to_json
bool empty() const noexcept
checks whether the container is empty
const_reference back() const
access the last element
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
bool operator<(const iter_impl &other) const
comparison: smaller
friend bool operator!=(const_reference v, std::nullptr_t) noexcept
comparison: not equal
pointer operator->() const
dereference the iterator
string_t dump(const int indent=-1) const
serialization
ValueType value(const typename object_t::key_type &key, ValueType default_value) const
access specified object element with default value
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
std::ptrdiff_t difference_type
a type to represent differences between iterators
static basic_json parse(const ContiguousContainer &c, const parser_callback_t cb=nullptr)
deserialize from a container with contiguous storage
AllocatorType< basic_json > allocator_type
the allocator type
json_pointer(const std::string &s="")
create JSON pointer
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
friend bool operator!=(std::nullptr_t, const_reference v) noexcept
comparison: not equal
reference value() const
return the value of an iterator
iterator insert(const_iterator pos, basic_json &&val)
inserts element
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
basic_json(CompatibleType &&val) noexcept(noexcept(JSONSerializer< U >::to_json(std::declval< basic_json_t &>(), std::forward< CompatibleType >(val))))
create a JSON value
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
constexpr bool is_null() const noexcept
return whether value is null
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
StringType string_t
a type for a string
reference operator[](difference_type n) const
access to successor
static basic_json array(std::initializer_list< basic_json > init=std::initializer_list< basic_json >())
explicitly create an array from an initializer list
basic_json(basic_json &&other) noexcept
move constructor
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
typename basic_json::difference_type difference_type
a type to represent differences between iterators
constexpr const PointerType get_ptr() const noexcept
get a pointer value (implicit)
iter_impl & operator-=(difference_type i)
subtract from iterator
typename Base::reference reference
the reference type for the pointed-to element
a template for a reverse iterator class
void push_back(basic_json &&val)
add an object to an array
iterator insert(const_iterator pos, const basic_json &val)
inserts element
void clear() noexcept
clears the contents
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a MessagePack serialization of a given JSON value
friend bool operator==(const_reference v, std::nullptr_t) noexcept
comparison: equal
basic_json value_type
the type of elements in a basic_json container
iter_impl & operator+=(difference_type i)
add to iterator
object_t::key_type key() const
return the key of an object iterator
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
friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
const_reference operator[](T *key) const
read-only access specified object element
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
basic_json(const basic_json &other)
copy constructor
bool operator>(const iter_impl &other) const
comparison: greater than
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
IteratorType erase(IteratorType pos)
remove element given an iterator
a template for a random access iterator for the basic_json class
json_reverse_iterator & operator++()
pre-increment (++it)
constexpr bool is_discarded() const noexcept
return whether value is discarded
parse_event_t
JSON callback events.
reference operator[](T *(&key)[n])
access specified object element
reverse_iterator rend() noexcept
returns an iterator to the reverse-end