1049 using value_t = detail::value_t;
1054 template<
typename T,
typename SFINAE>
1083 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
1085 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
1134 result[
"copyright"] =
"(C) 2013-2017 Niels Lohmann";
1135 result[
"name"] =
"JSON for Modern C++";
1136 result[
"url"] =
"https://github.com/nlohmann/json";
1139 {
"string",
"2.1.1"},
1146 result[
"platform"] =
"win32";
1147#elif defined __linux__
1148 result[
"platform"] =
"linux";
1149#elif defined __APPLE__
1150 result[
"platform"] =
"apple";
1151#elif defined __unix__
1152 result[
"platform"] =
"unix";
1154 result[
"platform"] =
"unknown";
1157#if defined(__clang__)
1159#elif defined(__ICC) || defined(__INTEL_COMPILER)
1161#elif defined(__GNUC__) || defined(__GNUG__)
1163#elif defined(__HP_cc) || defined(__HP_aCC)
1164 result[
"compiler"] =
"hp"
1165#elif defined(__IBMCPP__)
1167#elif defined(_MSC_VER)
1168 result[
"compiler"] = {{
"family",
"msvc"}, {
"version",
_MSC_VER}};
1170 result[
"compiler"] = {{
"family",
"pgcpp"}, {
"version",
__PGI}};
1171#elif defined(__SUNPRO_CC)
1174 result[
"compiler"] = {{
"family",
"unknown"}, {
"version",
"unknown"}};
1180 result[
"compiler"][
"c++"] =
"unknown";
1280 std::less<StringType>,
1625 template<
typename T,
typename...
Args>
1631 alloc.deallocate(
object, 1);
1634 alloc.construct(
object.
get(), std::forward<Args>(
args)...);
1635 assert(
object !=
nullptr);
1636 return object.release();
1685 json_value() =
default;
1687 json_value(
boolean_t v) noexcept : boolean(v) {}
1699 case value_t::object:
1701 object = create<object_t>();
1705 case value_t::array:
1707 array = create<array_t>();
1711 case value_t::string:
1713 string = create<string_t>(
"");
1717 case value_t::boolean:
1723 case value_t::number_integer:
1729 case value_t::number_unsigned:
1735 case value_t::number_float:
1748 if (t == value_t::null)
1750 JSON_THROW(std::domain_error(
"961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1"));
1760 string = create<string_t>(
value);
1766 object = create<object_t>(
value);
1772 array = create<array_t>(
value);
1785 void assert_invariant()
const
1787 assert(m_type != value_t::object
or m_value.object !=
nullptr);
1788 assert(m_type != value_t::array
or m_value.array !=
nullptr);
1789 assert(m_type != value_t::string
or m_value.string !=
nullptr);
1999 template<
typename CompatibleType,
typename U = detail::uncvref_t<CompatibleType>,
2000 detail::enable_if_t<not std::is_base_of<std::istream, U>::value and
2001 not std::is_same<U, basic_json_t>::value and
2002 not detail::is_basic_json_nested_type<
2003 basic_json_t, U>::value and
2004 detail::has_to_json<basic_json, U>::value,
2007 std::declval<basic_json_t&>(), std::forward<CompatibleType>(
val))))
2009 JSONSerializer<U>::to_json(*
this, std::forward<CompatibleType>(
val));
2091 return element.is_array() and element.size() == 2 and element[0].is_string();
2106 JSON_THROW(std::domain_error(
"cannot create object from initializer list"));
2113 m_type = value_t::object;
2114 m_value = value_t::object;
2118 m_value.object->emplace(*(element[0].m_value.string), element[1]);
2124 m_type = value_t::array;
2166 std::initializer_list<basic_json>())
2206 std::initializer_list<basic_json>())
2230 : m_type(value_t::
array)
2273 template<
class InputIT,
typename std::enable_if<
2274 std::is_same<InputIT, typename basic_json_t::iterator>::value
or
2275 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int>
::type = 0>
2284 JSON_THROW(std::domain_error(
"iterators are not compatible"));
2288 m_type =
first.m_object->m_type;
2293 case value_t::boolean:
2294 case value_t::number_float:
2295 case value_t::number_integer:
2296 case value_t::number_unsigned:
2297 case value_t::string:
2299 if (
not first.m_it.primitive_iterator.is_begin()
or not last.m_it.primitive_iterator.is_end())
2301 JSON_THROW(std::out_of_range(
"iterators out of range"));
2314 case value_t::number_integer:
2316 m_value.number_integer =
first.m_object->m_value.number_integer;
2320 case value_t::number_unsigned:
2322 m_value.number_unsigned =
first.m_object->m_value.number_unsigned;
2326 case value_t::number_float:
2328 m_value.number_float =
first.m_object->m_value.number_float;
2332 case value_t::boolean:
2334 m_value.boolean =
first.m_object->m_value.boolean;
2338 case value_t::string:
2340 m_value = *
first.m_object->m_value.string;
2344 case value_t::object:
2347 last.m_it.object_iterator);
2351 case value_t::array:
2354 last.m_it.array_iterator);
2360 JSON_THROW(std::domain_error(
"cannot use construct with iterators from " +
first.m_object->
type_name()));
2398 *
this = parser(
i,
cb).parse();
2429 : m_type(
other.m_type)
2432 other.assert_invariant();
2436 case value_t::object:
2438 m_value = *
other.m_value.object;
2442 case value_t::array:
2444 m_value = *
other.m_value.array;
2448 case value_t::string:
2450 m_value = *
other.m_value.string;
2454 case value_t::boolean:
2456 m_value =
other.m_value.boolean;
2460 case value_t::number_integer:
2462 m_value =
other.m_value.number_integer;
2466 case value_t::number_unsigned:
2468 m_value =
other.m_value.number_unsigned;
2472 case value_t::number_float:
2474 m_value =
other.m_value.number_float;
2506 : m_type(std::move(
other.m_type)),
2507 m_value(std::move(
other.m_value))
2510 other.assert_invariant();
2513 other.m_type = value_t::null;
2543 std::is_nothrow_move_constructible<value_t>::value
and
2544 std::is_nothrow_move_assignable<value_t>::value
and
2545 std::is_nothrow_move_constructible<json_value>::value
and
2546 std::is_nothrow_move_assignable<json_value>::value
2550 other.assert_invariant();
2581 case value_t::object:
2584 alloc.destroy(m_value.object);
2585 alloc.deallocate(m_value.object, 1);
2589 case value_t::array:
2592 alloc.destroy(m_value.array);
2593 alloc.deallocate(m_value.array, 1);
2597 case value_t::string:
2600 alloc.destroy(m_value.string);
2601 alloc.deallocate(m_value.string, 1);
2649 std::stringstream
ss;
2762 return m_type == value_t::null;
2784 return m_type == value_t::boolean;
2843 return m_type == value_t::number_integer
or m_type == value_t::number_unsigned;
2871 return m_type == value_t::number_unsigned;
2899 return m_type == value_t::number_float;
2921 return m_type == value_t::object;
2943 return m_type == value_t::array;
2965 return m_type == value_t::string;
2992 return m_type == value_t::discarded;
3030 return m_value.boolean;
3033 JSON_THROW(std::domain_error(
"type must be boolean, but is " +
type_name()));
3039 return is_object() ? m_value.object :
nullptr;
3045 return is_object() ? m_value.object :
nullptr;
3051 return is_array() ? m_value.array :
nullptr;
3055 constexpr const array_t* get_impl_ptr(
const array_t* )
const noexcept
3057 return is_array() ? m_value.array :
nullptr;
3063 return is_string() ? m_value.string :
nullptr;
3069 return is_string() ? m_value.string :
nullptr;
3075 return is_boolean() ? &m_value.boolean :
nullptr;
3081 return is_boolean() ? &m_value.boolean :
nullptr;
3131 template<
typename ReferenceType,
typename ThisType>
3135 using PointerType =
typename std::add_pointer<ReferenceType>::type;
3145 JSON_THROW(std::domain_error(
"incompatible ReferenceType for get_ref, actual type is " +
3170 detail::enable_if_t<std::is_same<typename std::remove_const<BasicJsonType>::type,
3219 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3220 detail::enable_if_t <
3221 not std::is_same<basic_json_t, ValueType>::value
and
3222 detail::has_from_json<basic_json_t, ValueType>::value
and
3223 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
3231 static_assert(
not std::is_reference<ValueTypeCV>::value,
3232 "get() cannot be used with reference types, you might want to use get_ref()");
3233 static_assert(std::is_default_constructible<ValueType>::value,
3234 "types must be DefaultConstructible when used with get()");
3237 JSONSerializer<ValueType>::from_json(*
this,
ret);
3274 typename ValueType = detail::uncvref_t<ValueTypeCV>,
3275 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value
and
3276 detail::has_non_default_from_json<basic_json_t,
3281 static_assert(
not std::is_reference<ValueTypeCV>::value,
3282 "get() cannot be used with reference types, you might want to use get_ref()");
3283 return JSONSerializer<ValueTypeCV>::from_json(*
this);
3313 template<
typename PointerType,
typename std::enable_if<
3314 std::is_pointer<PointerType>::value,
int>
::type = 0>
3325 template<
typename PointerType,
typename std::enable_if<
3326 std::is_pointer<PointerType>::value,
int>
::type = 0>
3359 template<
typename PointerType,
typename std::enable_if<
3360 std::is_pointer<PointerType>::value,
int>
::type = 0>
3364 using pointee_t =
typename std::remove_const<
typename
3365 std::remove_pointer<
typename
3369 std::is_same<object_t, pointee_t>::value
3370 or std::is_same<array_t, pointee_t>::value
3371 or std::is_same<string_t, pointee_t>::value
3372 or std::is_same<boolean_t, pointee_t>::value
3373 or std::is_same<number_integer_t, pointee_t>::value
3374 or std::is_same<number_unsigned_t, pointee_t>::value
3375 or std::is_same<number_float_t, pointee_t>::value
3376 ,
"incompatible pointer type");
3379 return get_impl_ptr(
static_cast<PointerType>(
nullptr));
3386 template<
typename PointerType,
typename std::enable_if<
3387 std::is_pointer<PointerType>::value
and
3388 std::is_const<typename std::remove_pointer<PointerType>::type>
::value,
int>
::type = 0>
3392 using pointee_t =
typename std::remove_const<
typename
3393 std::remove_pointer<
typename
3397 std::is_same<object_t, pointee_t>::value
3398 or std::is_same<array_t, pointee_t>::value
3399 or std::is_same<string_t, pointee_t>::value
3400 or std::is_same<boolean_t, pointee_t>::value
3401 or std::is_same<number_integer_t, pointee_t>::value
3402 or std::is_same<number_unsigned_t, pointee_t>::value
3403 or std::is_same<number_float_t, pointee_t>::value
3404 ,
"incompatible pointer type");
3407 return get_impl_ptr(
static_cast<const PointerType>(
nullptr));
3437 std::is_reference<ReferenceType>::value,
int>
::type = 0>
3449 std::is_reference<ReferenceType>::value
and
3450 std::is_const<typename std::remove_reference<ReferenceType>::type>
::value,
int>
::type = 0>
3485 template <
typename ValueType,
typename std::enable_if <
3486 not std::is_pointer<ValueType>::value
and
3487 not std::is_same<ValueType, typename string_t::value_type>::value
3489 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>
::value
3538 return m_value.array->at(
idx);
3540 JSON_CATCH (std::out_of_range&)
3543 JSON_THROW(std::out_of_range(
"array index " + std::to_string(
idx) +
" is out of range"));
3548 JSON_THROW(std::domain_error(
"cannot use at() with " +
type_name()));
3581 return m_value.array->at(
idx);
3583 JSON_CATCH (std::out_of_range&)
3586 JSON_THROW(std::out_of_range(
"array index " + std::to_string(
idx) +
" is out of range"));
3591 JSON_THROW(std::domain_error(
"cannot use at() with " +
type_name()));
3628 return m_value.object->at(
key);
3630 JSON_CATCH (std::out_of_range&)
3633 JSON_THROW(std::out_of_range(
"key '" +
key +
"' not found"));
3638 JSON_THROW(std::domain_error(
"cannot use at() with " +
type_name()));
3675 return m_value.object->at(
key);
3677 JSON_CATCH (std::out_of_range&)
3680 JSON_THROW(std::out_of_range(
"key '" +
key +
"' not found"));
3685 JSON_THROW(std::domain_error(
"cannot use at() with " +
type_name()));
3719 m_type = value_t::array;
3728 if (
idx >= m_value.array->size())
3730 m_value.array->insert(m_value.array->end(),
3731 idx - m_value.array->size() + 1,
3735 return m_value.array->operator[](
idx);
3738 JSON_THROW(std::domain_error(
"cannot use operator[] with " +
type_name()));
3765 return m_value.array->operator[](
idx);
3768 JSON_THROW(std::domain_error(
"cannot use operator[] with " +
type_name()));
3803 m_type = value_t::object;
3811 return m_value.object->operator[](
key);
3814 JSON_THROW(std::domain_error(
"cannot use operator[] with " +
type_name()));
3852 assert(m_value.object->find(
key) != m_value.object->end());
3853 return m_value.object->find(
key)->second;
3856 JSON_THROW(std::domain_error(
"cannot use operator[] with " +
type_name()));
3886 template<
typename T, std::
size_t n>
3921 template<
typename T, std::
size_t n>
3954 template<
typename T>
3960 m_type = value_t::object;
3961 m_value = value_t::object;
3968 return m_value.object->operator[](
key);
3971 JSON_THROW(std::domain_error(
"cannot use operator[] with " +
type_name()));
4004 template<
typename T>
4010 assert(m_value.object->find(
key) != m_value.object->end());
4011 return m_value.object->find(
key)->second;
4014 JSON_THROW(std::domain_error(
"cannot use operator[] with " +
type_name()));
4065 template<
class ValueType,
typename std::enable_if<
4066 std::is_convertible<basic_json_t, ValueType>::value,
int>
::type = 0>
4083 JSON_THROW(std::domain_error(
"cannot use value() with " +
type_name()));
4137 template<
class ValueType,
typename std::enable_if<
4138 std::is_convertible<basic_json_t, ValueType>::value,
int>
::type = 0>
4147 return ptr.get_checked(
this);
4149 JSON_CATCH (std::out_of_range&)
4155 JSON_THROW(std::domain_error(
"cannot use value() with " +
type_name()));
4298 std::is_same<IteratorType, typename basic_json_t::iterator>::value
or
4299 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>
::type
4304 if (
this !=
pos.m_object)
4306 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
4313 case value_t::boolean:
4314 case value_t::number_float:
4315 case value_t::number_integer:
4316 case value_t::number_unsigned:
4317 case value_t::string:
4319 if (
not pos.m_it.primitive_iterator.is_begin())
4321 JSON_THROW(std::out_of_range(
"iterator out of range"));
4327 alloc.destroy(m_value.string);
4328 alloc.deallocate(m_value.string, 1);
4329 m_value.string =
nullptr;
4332 m_type = value_t::null;
4337 case value_t::object:
4339 result.m_it.object_iterator = m_value.object->erase(
pos.m_it.object_iterator);
4343 case value_t::array:
4345 result.m_it.array_iterator = m_value.array->erase(
pos.m_it.array_iterator);
4351 JSON_THROW(std::domain_error(
"cannot use erase() with " +
type_name()));
4405 std::is_same<IteratorType, typename basic_json_t::iterator>::value
or
4406 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int>
::type
4411 if (
this !=
first.m_object
or this !=
last.m_object)
4413 JSON_THROW(std::domain_error(
"iterators do not fit current value"));
4420 case value_t::boolean:
4421 case value_t::number_float:
4422 case value_t::number_integer:
4423 case value_t::number_unsigned:
4424 case value_t::string:
4426 if (
not first.m_it.primitive_iterator.is_begin()
or not last.m_it.primitive_iterator.is_end())
4428 JSON_THROW(std::out_of_range(
"iterators out of range"));
4434 alloc.destroy(m_value.string);
4435 alloc.deallocate(m_value.string, 1);
4436 m_value.string =
nullptr;
4439 m_type = value_t::null;
4444 case value_t::object:
4446 result.m_it.object_iterator = m_value.object->erase(
first.m_it.object_iterator,
4447 last.m_it.object_iterator);
4451 case value_t::array:
4453 result.m_it.array_iterator = m_value.array->erase(
first.m_it.array_iterator,
4454 last.m_it.array_iterator);
4460 JSON_THROW(std::domain_error(
"cannot use erase() with " +
type_name()));
4501 return m_value.object->erase(
key);
4504 JSON_THROW(std::domain_error(
"cannot use erase() with " +
type_name()));
4538 JSON_THROW(std::out_of_range(
"array index " + std::to_string(
idx) +
" is out of range"));
4545 JSON_THROW(std::domain_error(
"cannot use erase() with " +
type_name()));
4587 result.m_it.object_iterator = m_value.object->find(
key);
4603 result.m_it.object_iterator = m_value.object->find(
key);
4921 template<
typename IteratorType>
class iteration_proxy;
5005 case value_t::array:
5008 return m_value.array->empty();
5011 case value_t::object:
5014 return m_value.object->empty();
5073 case value_t::array:
5076 return m_value.array->size();
5079 case value_t::object:
5082 return m_value.object->size();
5133 case value_t::array:
5136 return m_value.array->max_size();
5139 case value_t::object:
5142 return m_value.object->max_size();
5189 case value_t::number_integer:
5191 m_value.number_integer = 0;
5195 case value_t::number_unsigned:
5197 m_value.number_unsigned = 0;
5201 case value_t::number_float:
5203 m_value.number_float = 0.0;
5207 case value_t::boolean:
5209 m_value.boolean =
false;
5213 case value_t::string:
5215 m_value.string->clear();
5219 case value_t::array:
5221 m_value.array->clear();
5225 case value_t::object:
5227 m_value.object->clear();
5263 JSON_THROW(std::domain_error(
"cannot use push_back() with " +
type_name()));
5269 m_type = value_t::array;
5270 m_value = value_t::array;
5275 m_value.array->push_back(std::move(
val));
5277 val.m_type = value_t::null;
5299 JSON_THROW(std::domain_error(
"cannot use push_back() with " +
type_name()));
5305 m_type = value_t::array;
5306 m_value = value_t::array;
5311 m_value.array->push_back(
val);
5349 JSON_THROW(std::domain_error(
"cannot use push_back() with " +
type_name()));
5355 m_type = value_t::object;
5356 m_value = value_t::object;
5361 m_value.object->insert(
val);
5443 template<
class...
Args>
5449 JSON_THROW(std::domain_error(
"cannot use emplace_back() with " +
type_name()));
5455 m_type = value_t::array;
5456 m_value = value_t::array;
5461 m_value.array->emplace_back(std::forward<Args>(
args)...);
5491 template<
class...
Args>
5497 JSON_THROW(std::domain_error(
"cannot use emplace() with " +
type_name()));
5503 m_type = value_t::object;
5504 m_value = value_t::object;
5509 auto res = m_value.object->emplace(std::forward<Args>(
args)...);
5512 it.m_it.object_iterator =
res.first;
5515 return {
it,
res.second};
5546 if (
pos.m_object !=
this)
5548 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5553 result.m_it.array_iterator = m_value.array->insert(
pos.m_it.array_iterator,
val);
5557 JSON_THROW(std::domain_error(
"cannot use insert() with " +
type_name()));
5599 if (
pos.m_object !=
this)
5601 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5606 result.m_it.array_iterator = m_value.array->insert(
pos.m_it.array_iterator,
cnt,
val);
5610 JSON_THROW(std::domain_error(
"cannot use insert() with " +
type_name()));
5648 JSON_THROW(std::domain_error(
"cannot use insert() with " +
type_name()));
5652 if (
pos.m_object !=
this)
5654 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5660 JSON_THROW(std::domain_error(
"iterators do not fit"));
5663 if (
first.m_object ==
this or last.m_object ==
this)
5665 JSON_THROW(std::domain_error(
"passed iterators may not belong to container"));
5670 result.m_it.array_iterator = m_value.array->insert(
5671 pos.m_it.array_iterator,
5672 first.m_it.array_iterator,
5673 last.m_it.array_iterator);
5706 JSON_THROW(std::domain_error(
"cannot use insert() with " +
type_name()));
5710 if (
pos.m_object !=
this)
5712 JSON_THROW(std::domain_error(
"iterator does not fit current value"));
5717 result.m_it.array_iterator = m_value.array->insert(
pos.m_it.array_iterator,
ilist);
5739 std::is_nothrow_move_constructible<value_t>::value
and
5740 std::is_nothrow_move_assignable<value_t>::value
and
5741 std::is_nothrow_move_constructible<json_value>::value
and
5742 std::is_nothrow_move_assignable<json_value>::value
5745 std::swap(m_type,
other.m_type);
5746 std::swap(m_value,
other.m_value);
5775 std::swap(*(m_value.array),
other);
5779 JSON_THROW(std::domain_error(
"cannot use swap() with " +
type_name()));
5808 std::swap(*(m_value.object),
other);
5812 JSON_THROW(std::domain_error(
"cannot use swap() with " +
type_name()));
5841 std::swap(*(m_value.string),
other);
5845 JSON_THROW(std::domain_error(
"cannot use swap() with " +
type_name()));
5891 case value_t::array:
5893 return *
lhs.m_value.array == *
rhs.m_value.array;
5895 case value_t::object:
5897 return *
lhs.m_value.object == *
rhs.m_value.object;
5903 case value_t::string:
5905 return *
lhs.m_value.string == *
rhs.m_value.string;
5907 case value_t::boolean:
5909 return lhs.m_value.boolean ==
rhs.m_value.boolean;
5911 case value_t::number_integer:
5913 return lhs.m_value.number_integer ==
rhs.m_value.number_integer;
5915 case value_t::number_unsigned:
5917 return lhs.m_value.number_unsigned ==
rhs.m_value.number_unsigned;
5919 case value_t::number_float:
5921 return lhs.m_value.number_float ==
rhs.m_value.number_float;
5961 template<
typename ScalarType,
typename std::enable_if<
5962 std::is_scalar<ScalarType>::value,
int>
::type = 0>
5972 template<
typename ScalarType,
typename std::enable_if<
5973 std::is_scalar<ScalarType>::value,
int>
::type = 0>
6004 template<
typename ScalarType,
typename std::enable_if<
6005 std::is_scalar<ScalarType>::value,
int>
::type = 0>
6015 template<
typename ScalarType,
typename std::enable_if<
6016 std::is_scalar<ScalarType>::value,
int>
::type = 0>
6055 case value_t::array:
6057 return *
lhs.m_value.array < *
rhs.m_value.array;
6059 case value_t::object:
6061 return *
lhs.m_value.object < *
rhs.m_value.object;
6067 case value_t::string:
6069 return *
lhs.m_value.string < *
rhs.m_value.string;
6071 case value_t::boolean:
6073 return lhs.m_value.boolean <
rhs.m_value.boolean;
6075 case value_t::number_integer:
6077 return lhs.m_value.number_integer <
rhs.m_value.number_integer;
6079 case value_t::number_unsigned:
6081 return lhs.m_value.number_unsigned <
rhs.m_value.number_unsigned;
6083 case value_t::number_float:
6085 return lhs.m_value.number_float <
rhs.m_value.number_float;
6283 template<
class T, std::
size_t N>
6318 template<
typename CharT,
typename std::enable_if<
6319 std::is_pointer<CharT>::value
and
6320 std::is_integral<typename std::remove_pointer<CharT>::type>
::value and
6321 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
int>
::type = 0>
6325 return parser(
reinterpret_cast<const char*
>(
s),
cb).
parse();
6410 std::random_access_iterator_tag,
6411 typename std::iterator_traits<IteratorType>::iterator_category>
::value,
int>
::type = 0>
6420 res.first &= (
val == *(std::next(std::addressof(*
first),
res.second++)));
6425 static_assert(
sizeof(
typename std::iterator_traits<IteratorType>::value_type) == 1,
6426 "each element in the iterator range must have the size of 1 byte");
6432 return parser(
"").parse();
6479 not std::is_pointer<ContiguousContainer>::value
and
6481 std::random_access_iterator_tag,
6482 typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>
::value
6488 return parse(std::begin(
c), std::end(
c),
cb);
6545 template<
typename T>
6546 static void add_to_vector(std::vector<uint8_t>&
vec,
size_t bytes,
const T
number)
6625 template<
typename T>
6626 static T get_from_vector(
const std::vector<uint8_t>&
vec,
const size_t current_index)
6630 JSON_THROW(std::out_of_range(
"cannot read " + std::to_string(
sizeof(T)) +
" bytes from vector"));
6635 for (
size_t i = 0;
i <
sizeof(T); ++
i)
6652 static void to_msgpack_internal(
const basic_json&
j, std::vector<uint8_t>&
v)
6663 case value_t::boolean:
6670 case value_t::number_integer:
6672 if (
j.m_value.number_integer >= 0)
6678 if (
j.m_value.number_unsigned < 128)
6681 add_to_vector(
v, 1,
j.m_value.number_unsigned);
6683 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6687 add_to_vector(
v, 1,
j.m_value.number_unsigned);
6689 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6693 add_to_vector(
v, 2,
j.m_value.number_unsigned);
6695 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6699 add_to_vector(
v, 4,
j.m_value.number_unsigned);
6701 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6705 add_to_vector(
v, 8,
j.m_value.number_unsigned);
6710 if (
j.m_value.number_integer >= -32)
6713 add_to_vector(
v, 1,
j.m_value.number_integer);
6715 else if (
j.m_value.number_integer >= std::numeric_limits<int8_t>::min()
and j.m_value.number_integer <= std::numeric_limits<int8_t>::max())
6719 add_to_vector(
v, 1,
j.m_value.number_integer);
6721 else if (
j.m_value.number_integer >= std::numeric_limits<int16_t>::min()
and j.m_value.number_integer <= std::numeric_limits<int16_t>::max())
6725 add_to_vector(
v, 2,
j.m_value.number_integer);
6727 else if (
j.m_value.number_integer >= std::numeric_limits<int32_t>::min()
and j.m_value.number_integer <= std::numeric_limits<int32_t>::max())
6731 add_to_vector(
v, 4,
j.m_value.number_integer);
6733 else if (
j.m_value.number_integer >= std::numeric_limits<int64_t>::min()
and j.m_value.number_integer <= std::numeric_limits<int64_t>::max())
6737 add_to_vector(
v, 8,
j.m_value.number_integer);
6743 case value_t::number_unsigned:
6745 if (
j.m_value.number_unsigned < 128)
6748 add_to_vector(
v, 1,
j.m_value.number_unsigned);
6750 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint8_t>::max())
6754 add_to_vector(
v, 1,
j.m_value.number_unsigned);
6756 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint16_t>::max())
6760 add_to_vector(
v, 2,
j.m_value.number_unsigned);
6762 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint32_t>::max())
6766 add_to_vector(
v, 4,
j.m_value.number_unsigned);
6768 else if (
j.m_value.number_unsigned <= std::numeric_limits<uint64_t>::max())
6772 add_to_vector(
v, 8,
j.m_value.number_unsigned);
6777 case value_t::number_float:
6781 const auto*
helper =
reinterpret_cast<const uint8_t*
>(&(
j.m_value.number_float));
6782 for (
size_t i = 0;
i < 8; ++
i)
6789 case value_t::string:
6791 const auto N =
j.m_value.string->size();
6801 add_to_vector(
v, 1,
N);
6803 else if (
N <= 65535)
6807 add_to_vector(
v, 2,
N);
6809 else if (
N <= 4294967295)
6813 add_to_vector(
v, 4,
N);
6817 std::copy(
j.m_value.string->begin(),
j.m_value.string->end(),
6818 std::back_inserter(
v));
6822 case value_t::array:
6824 const auto N =
j.m_value.array->size();
6830 else if (
N <= 0xffff)
6834 add_to_vector(
v, 2,
N);
6836 else if (
N <= 0xffffffff)
6840 add_to_vector(
v, 4,
N);
6844 for (
const auto&
el : *
j.m_value.
array)
6846 to_msgpack_internal(
el,
v);
6851 case value_t::object:
6853 const auto N =
j.m_value.object->size();
6859 else if (
N <= 65535)
6863 add_to_vector(
v, 2,
N);
6865 else if (
N <= 4294967295)
6869 add_to_vector(
v, 4,
N);
6873 for (
const auto&
el : *
j.m_value.
object)
6875 to_msgpack_internal(
el.first,
v);
6876 to_msgpack_internal(
el.second,
v);
6898 static void to_cbor_internal(
const basic_json&
j, std::vector<uint8_t>&
v)
6908 case value_t::boolean:
6914 case value_t::number_integer:
6916 if (
j.m_value.number_integer >= 0)
6921 if (
j.m_value.number_integer <= 0x17)
6923 add_to_vector(
v, 1,
j.m_value.number_integer);
6925 else if (
j.m_value.number_integer <= std::numeric_limits<uint8_t>::max())
6929 add_to_vector(
v, 1,
j.m_value.number_integer);
6931 else if (
j.m_value.number_integer <= std::numeric_limits<uint16_t>::max())
6935 add_to_vector(
v, 2,
j.m_value.number_integer);
6937 else if (
j.m_value.number_integer <= std::numeric_limits<uint32_t>::max())
6941 add_to_vector(
v, 4,
j.m_value.number_integer);
6947 add_to_vector(
v, 8,
j.m_value.number_integer);
6955 if (
j.m_value.number_integer >= -24)
6987 case value_t::number_unsigned:
6989 if (
j.m_value.number_unsigned <= 0x17)
6993 else if (
j.m_value.number_unsigned <= 0xff)
6997 add_to_vector(
v, 1,
j.m_value.number_unsigned);
6999 else if (
j.m_value.number_unsigned <= 0xffff)
7003 add_to_vector(
v, 2,
j.m_value.number_unsigned);
7005 else if (
j.m_value.number_unsigned <= 0xffffffff)
7009 add_to_vector(
v, 4,
j.m_value.number_unsigned);
7011 else if (
j.m_value.number_unsigned <= 0xffffffffffffffff)
7015 add_to_vector(
v, 8,
j.m_value.number_unsigned);
7020 case value_t::number_float:
7024 const auto*
helper =
reinterpret_cast<const uint8_t*
>(&(
j.m_value.number_float));
7025 for (
size_t i = 0;
i < 8; ++
i)
7032 case value_t::string:
7034 const auto N =
j.m_value.string->size();
7042 add_to_vector(
v, 1,
N);
7044 else if (
N <= 0xffff)
7047 add_to_vector(
v, 2,
N);
7049 else if (
N <= 0xffffffff)
7052 add_to_vector(
v, 4,
N);
7055 else if (
N <= 0xffffffffffffffff)
7058 add_to_vector(
v, 8,
N);
7063 std::copy(
j.m_value.string->begin(),
j.m_value.string->end(),
7064 std::back_inserter(
v));
7068 case value_t::array:
7070 const auto N =
j.m_value.array->size();
7078 add_to_vector(
v, 1,
N);
7080 else if (
N <= 0xffff)
7083 add_to_vector(
v, 2,
N);
7085 else if (
N <= 0xffffffff)
7088 add_to_vector(
v, 4,
N);
7091 else if (
N <= 0xffffffffffffffff)
7094 add_to_vector(
v, 8,
N);
7099 for (
const auto&
el : *
j.m_value.
array)
7101 to_cbor_internal(
el,
v);
7106 case value_t::object:
7108 const auto N =
j.m_value.object->size();
7116 add_to_vector(
v, 1,
N);
7118 else if (
N <= 0xffff)
7121 add_to_vector(
v, 2,
N);
7123 else if (
N <= 0xffffffff)
7126 add_to_vector(
v, 4,
N);
7129 else if (
N <= 0xffffffffffffffff)
7132 add_to_vector(
v, 8,
N);
7137 for (
const auto&
el : *
j.m_value.
object)
7139 to_cbor_internal(
el.first,
v);
7140 to_cbor_internal(
el.second,
v);
7175 static void check_length(
const size_t size,
const size_t len,
const size_t offset)
7180 JSON_THROW(std::out_of_range(
"len out of range"));
7184 if ((
size > (std::numeric_limits<size_t>::max() -
offset)))
7186 JSON_THROW(std::out_of_range(
"len+offset out of range"));
7192 JSON_THROW(std::out_of_range(
"len+offset out of range"));
7210 static basic_json from_msgpack_internal(
const std::vector<uint8_t>&
v,
size_t&
idx)
7226 basic_json
result = value_t::object;
7228 for (
size_t i = 0;
i <
len; ++
i)
7230 std::string
key = from_msgpack_internal(
v,
idx);
7237 basic_json
result = value_t::array;
7239 for (
size_t i = 0;
i <
len; ++
i)
7251 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7264 return value_t::null;
7281 for (
size_t byte = 0;
byte <
sizeof(
float); ++
byte)
7293 for (
size_t byte = 0;
byte <
sizeof(
double); ++
byte)
7355 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7364 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7373 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7378 basic_json
result = value_t::array;
7381 for (
size_t i = 0;
i <
len; ++
i)
7390 basic_json
result = value_t::array;
7393 for (
size_t i = 0;
i <
len; ++
i)
7402 basic_json
result = value_t::object;
7405 for (
size_t i = 0;
i <
len; ++
i)
7407 std::string
key = from_msgpack_internal(
v,
idx);
7415 basic_json
result = value_t::object;
7418 for (
size_t i = 0;
i <
len; ++
i)
7420 std::string
key = from_msgpack_internal(
v,
idx);
7428 JSON_THROW(std::invalid_argument(
"error parsing a msgpack @ " + std::to_string(
current_idx) +
": " + std::to_string(
static_cast<int>(
v[
current_idx]))));
7448 static basic_json from_cbor_internal(
const std::vector<uint8_t>&
v,
size_t&
idx)
7592 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7601 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7610 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7619 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7628 return std::string(
reinterpret_cast<const char*
>(
v.data()) +
offset,
len);
7634 while (
v.
at(
idx) != 0xff)
7670 basic_json
result = value_t::array;
7672 for (
size_t i = 0;
i <
len; ++
i)
7681 basic_json
result = value_t::array;
7684 for (
size_t i = 0;
i <
len; ++
i)
7693 basic_json
result = value_t::array;
7696 for (
size_t i = 0;
i <
len; ++
i)
7705 basic_json
result = value_t::array;
7708 for (
size_t i = 0;
i <
len; ++
i)
7717 basic_json
result = value_t::array;
7720 for (
size_t i = 0;
i <
len; ++
i)
7729 basic_json
result = value_t::array;
7730 while (
v.
at(
idx) != 0xff)
7765 basic_json
result = value_t::object;
7767 for (
size_t i = 0;
i <
len; ++
i)
7769 std::string
key = from_cbor_internal(
v,
idx);
7777 basic_json
result = value_t::object;
7780 for (
size_t i = 0;
i <
len; ++
i)
7782 std::string
key = from_cbor_internal(
v,
idx);
7790 basic_json
result = value_t::object;
7793 for (
size_t i = 0;
i <
len; ++
i)
7795 std::string
key = from_cbor_internal(
v,
idx);
7803 basic_json
result = value_t::object;
7806 for (
size_t i = 0;
i <
len; ++
i)
7808 std::string
key = from_cbor_internal(
v,
idx);
7816 basic_json
result = value_t::object;
7819 for (
size_t i = 0;
i <
len; ++
i)
7821 std::string
key = from_cbor_internal(
v,
idx);
7829 basic_json
result = value_t::object;
7830 while (
v.
at(
idx) != 0xff)
7832 std::string
key = from_cbor_internal(
v,
idx);
7852 return value_t::null;
7867 const int exp = (
half >> 10) & 0x1f;
7881 ? std::numeric_limits<double>::infinity()
7891 for (
size_t byte = 0;
byte <
sizeof(
float); ++
byte)
7903 for (
size_t byte = 0;
byte <
sizeof(
double); ++
byte)
7913 JSON_THROW(std::invalid_argument(
"error parsing a CBOR @ " + std::to_string(
current_idx) +
": " + std::to_string(
static_cast<int>(
v[
current_idx]))));
7943 std::vector<uint8_t>
result;
7944 to_msgpack_internal(
j,
result);
7978 return from_msgpack_internal(
v,
i);
8006 std::vector<uint8_t>
result;
8041 return from_cbor_internal(
v,
i);
8072 case value_t::object:
8074 case value_t::array:
8076 case value_t::string:
8078 case value_t::boolean:
8080 case value_t::discarded:
8097 static std::size_t extra_space(
const string_t&
s)
noexcept
8099 return std::accumulate(
s.
begin(),
s.
end(),
size_t{},
8100 [](
size_t res,
typename string_t::value_type
c)
8118 if (c >= 0x00 and c <= 0x1f)
8143 static string_t escape_string(
const string_t& s)
8145 const auto space = extra_space(s);
8152 string_t result(s.size() + space,
'\\');
8153 std::size_t pos = 0;
8155 for (
const auto& c : s)
8162 result[pos + 1] =
'"';
8178 result[pos + 1] =
'b';
8186 result[pos + 1] =
'f';
8194 result[pos + 1] =
'n';
8202 result[pos + 1] =
'r';
8210 result[pos + 1] =
't';
8217 if (c >= 0x00 and c <= 0x1f)
8221 static const char hexify[16] =
8223 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
8224 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'
8229 {
'u',
'0',
'0', hexify[c >> 4], hexify[c & 0x0f]
8257 template<
typename NumberType>
8258 numtostr(NumberType value)
8260 x_write(value, std::is_integral<NumberType>());
8263 const char* c_str()
const
8265 return m_buf.data();
8270 std::array < char, 64 > m_buf{{}};
8272 template<
typename NumberType>
8273 void x_write(NumberType x, std::true_type)
8282 const bool is_negative = x < 0;
8286 while (x != 0 and i < m_buf.size() - 1)
8288 const auto digit = std::labs(
static_cast<long>(x % 10));
8289 m_buf[i++] =
static_cast<char>(
'0' + digit);
8299 assert(i < m_buf.size() - 2);
8303 std::reverse(m_buf.begin(), m_buf.begin() + i);
8306 template<
typename NumberType>
8307 void x_write(NumberType x, std::false_type)
8313 if (std::signbit(x))
8324 static constexpr auto d = std::numeric_limits<NumberType>::digits10;
8327 const auto written_bytes = snprintf(m_buf.data(), m_buf.size(),
"%.*g", d, x);
8330 assert(written_bytes > 0);
8332 assert(
static_cast<size_t>(written_bytes) < m_buf.size());
8335 const auto loc = localeconv();
8336 assert(loc !=
nullptr);
8337 const char thousands_sep = !loc->thousands_sep ?
'\0'
8338 : loc->thousands_sep[0];
8340 const char decimal_point = !loc->decimal_point ?
'\0'
8341 : loc->decimal_point[0];
8344 if (thousands_sep !=
'\0')
8346 const auto end = std::remove(m_buf.begin(), m_buf.begin() + written_bytes, thousands_sep);
8347 std::fill(end, m_buf.end(),
'\0');
8351 if (decimal_point !=
'\0' and decimal_point !=
'.')
8353 for (
auto& c : m_buf)
8355 if (c == decimal_point)
8365 bool value_is_int_like =
true;
8366 for (i = 0; i < m_buf.size(); ++i)
8369 if (m_buf[i] ==
'\0')
8375 value_is_int_like = value_is_int_like and m_buf[i] !=
'.' and
8376 m_buf[i] !=
'e' and m_buf[i] !=
'E';
8379 if (value_is_int_like)
8382 assert((i + 2) < m_buf.size());
8384 assert(m_buf[i] ==
'\0');
8385 assert(m_buf[i - 1] !=
'\0');
8392 assert(m_buf[i + 2] ==
'\0');
8415 void dump(std::ostream& o,
8416 const bool pretty_print,
8417 const unsigned int indent_step,
8418 const unsigned int current_indent = 0)
const
8421 unsigned int new_indent = current_indent;
8425 case value_t::object:
8427 if (m_value.object->empty())
8438 new_indent += indent_step;
8442 for (
auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i)
8444 if (i != m_value.object->cbegin())
8446 o << (pretty_print ?
",\n" :
",");
8448 o << string_t(new_indent,
' ') <<
"\""
8449 << escape_string(i->first) <<
"\":"
8450 << (pretty_print ?
" " :
"");
8451 i->second.dump(o, pretty_print, indent_step, new_indent);
8457 new_indent -= indent_step;
8461 o << string_t(new_indent,
' ') +
"}";
8465 case value_t::array:
8467 if (m_value.array->empty())
8478 new_indent += indent_step;
8482 for (
auto i = m_value.array->cbegin(); i != m_value.array->cend(); ++i)
8484 if (i != m_value.array->cbegin())
8486 o << (pretty_print ?
",\n" :
",");
8488 o << string_t(new_indent,
' ');
8489 i->dump(o, pretty_print, indent_step, new_indent);
8495 new_indent -= indent_step;
8499 o << string_t(new_indent,
' ') <<
"]";
8503 case value_t::string:
8505 o << string_t(
"\"") << escape_string(*m_value.string) <<
"\"";
8509 case value_t::boolean:
8511 o << (m_value.boolean ?
"true" :
"false");
8515 case value_t::number_integer:
8517 o << numtostr(m_value.number_integer).c_str();
8521 case value_t::number_unsigned:
8523 o << numtostr(m_value.number_unsigned).c_str();
8527 case value_t::number_float:
8529 o << numtostr(m_value.number_float).c_str();
8533 case value_t::discarded:
8553 value_t m_type = value_t::null;
8556 json_value m_value = {};
8573 class primitive_iterator_t
8577 difference_type get_value() const noexcept
8582 void set_begin() noexcept
8588 void set_end() noexcept
8594 constexpr bool is_begin() const noexcept
8596 return (m_it == begin_value);
8600 constexpr bool is_end() const noexcept
8602 return (m_it == end_value);
8605 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8607 return lhs.m_it == rhs.m_it;
8610 friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8612 return !(lhs == rhs);
8615 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8617 return lhs.m_it < rhs.m_it;
8620 friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8622 return lhs.m_it <= rhs.m_it;
8625 friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8627 return lhs.m_it > rhs.m_it;
8630 friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8632 return lhs.m_it >= rhs.m_it;
8635 primitive_iterator_t operator+(difference_type i)
8637 auto result = *
this;
8642 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
8644 return lhs.m_it - rhs.m_it;
8647 friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
8649 return os << it.m_it;
8652 primitive_iterator_t& operator++()
8658 primitive_iterator_t operator++(
int)
8660 auto result = *
this;
8665 primitive_iterator_t& operator--()
8671 primitive_iterator_t operator--(
int)
8673 auto result = *
this;
8678 primitive_iterator_t& operator+=(difference_type n)
8684 primitive_iterator_t& operator-=(difference_type n)
8691 static constexpr difference_type begin_value = 0;
8692 static constexpr difference_type end_value = begin_value + 1;
8695 difference_type m_it = std::numeric_limits<std::ptrdiff_t>::denorm_min();
8705 struct internal_iterator
8708 typename object_t::iterator object_iterator;
8710 typename array_t::iterator array_iterator;
8712 primitive_iterator_t primitive_iterator;
8715 internal_iterator() noexcept
8716 : object_iterator(), array_iterator(), primitive_iterator()
8721 template<
typename IteratorType>
8722 class iteration_proxy
8726 class iteration_proxy_internal
8730 IteratorType anchor;
8732 size_t array_index = 0;
8735 explicit iteration_proxy_internal(IteratorType it) noexcept
8740 iteration_proxy_internal& operator*()
8746 iteration_proxy_internal& operator++()
8755 bool operator!= (
const iteration_proxy_internal& o)
const
8757 return anchor != o.anchor;
8761 typename basic_json::string_t key()
const
8763 assert(anchor.m_object !=
nullptr);
8765 switch (anchor.m_object->type())
8768 case value_t::array:
8770 return std::to_string(array_index);
8774 case value_t::object:
8776 return anchor.key();
8788 typename IteratorType::reference value()
const
8790 return anchor.value();
8795 typename IteratorType::reference container;
8799 explicit iteration_proxy(
typename IteratorType::reference cont)
8804 iteration_proxy_internal begin() noexcept
8806 return iteration_proxy_internal(container.begin());
8810 iteration_proxy_internal end() noexcept
8812 return iteration_proxy_internal(container.end());
8836 template<
typename U>
8837 class iter_impl :
public std::iterator<std::random_access_iterator_tag, U>
8843 static_assert(std::is_same<U, basic_json>::value
8844 or std::is_same<U, const basic_json>::value,
8845 "iter_impl only accepts (const) basic_json");
8853 using pointer =
typename std::conditional<std::is_const<U>::value,
8857 using reference =
typename std::conditional<std::is_const<U>::value,
8875 assert(m_object !=
nullptr);
8877 switch (m_object->m_type)
8879 case basic_json::value_t::object:
8881 m_it.object_iterator =
typename object_t::iterator();
8885 case basic_json::value_t::array:
8887 m_it.array_iterator =
typename array_t::iterator();
8893 m_it.primitive_iterator = primitive_iterator_t();
8913 ret.m_object = m_object;
8926 : m_object(other.m_object), m_it(other.m_it)
8935 std::is_nothrow_move_constructible<pointer>::value and
8936 std::is_nothrow_move_assignable<pointer>::value and
8937 std::is_nothrow_move_constructible<internal_iterator>::value and
8938 std::is_nothrow_move_assignable<internal_iterator>::value
8941 std::swap(m_object, other.m_object);
8942 std::swap(m_it, other.m_it);
8951 void set_begin() noexcept
8953 assert(m_object !=
nullptr);
8955 switch (m_object->m_type)
8957 case basic_json::value_t::object:
8959 m_it.object_iterator = m_object->m_value.object->begin();
8963 case basic_json::value_t::array:
8965 m_it.array_iterator = m_object->m_value.array->begin();
8969 case basic_json::value_t::null:
8972 m_it.primitive_iterator.set_end();
8978 m_it.primitive_iterator.set_begin();
8988 void set_end() noexcept
8990 assert(m_object !=
nullptr);
8992 switch (m_object->m_type)
8994 case basic_json::value_t::object:
8996 m_it.object_iterator = m_object->m_value.object->end();
9000 case basic_json::value_t::array:
9002 m_it.array_iterator = m_object->m_value.array->end();
9008 m_it.primitive_iterator.set_end();
9021 assert(m_object !=
nullptr);
9023 switch (m_object->m_type)
9025 case basic_json::value_t::object:
9027 assert(m_it.object_iterator != m_object->m_value.object->end());
9028 return m_it.object_iterator->second;
9031 case basic_json::value_t::array:
9033 assert(m_it.array_iterator != m_object->m_value.array->end());
9034 return *m_it.array_iterator;
9037 case basic_json::value_t::null:
9039 JSON_THROW(std::out_of_range(
"cannot get value"));
9044 if (m_it.primitive_iterator.is_begin())
9049 JSON_THROW(std::out_of_range(
"cannot get value"));
9060 assert(m_object !=
nullptr);
9062 switch (m_object->m_type)
9064 case basic_json::value_t::object:
9066 assert(m_it.object_iterator != m_object->m_value.object->end());
9067 return &(m_it.object_iterator->second);
9070 case basic_json::value_t::array:
9072 assert(m_it.array_iterator != m_object->m_value.array->end());
9073 return &*m_it.array_iterator;
9078 if (m_it.primitive_iterator.is_begin())
9083 JSON_THROW(std::out_of_range(
"cannot get value"));
9094 auto result = *
this;
9105 assert(m_object !=
nullptr);
9107 switch (m_object->m_type)
9109 case basic_json::value_t::object:
9111 std::advance(m_it.object_iterator, 1);
9115 case basic_json::value_t::array:
9117 std::advance(m_it.array_iterator, 1);
9123 ++m_it.primitive_iterator;
9137 auto result = *
this;
9148 assert(m_object !=
nullptr);
9150 switch (m_object->m_type)
9152 case basic_json::value_t::object:
9154 std::advance(m_it.object_iterator, -1);
9158 case basic_json::value_t::array:
9160 std::advance(m_it.array_iterator, -1);
9166 --m_it.primitive_iterator;
9181 if (m_object != other.m_object)
9183 JSON_THROW(std::domain_error(
"cannot compare iterators of different containers"));
9186 assert(m_object !=
nullptr);
9188 switch (m_object->m_type)
9190 case basic_json::value_t::object:
9192 return (m_it.object_iterator == other.m_it.object_iterator);
9195 case basic_json::value_t::array:
9197 return (m_it.array_iterator == other.m_it.array_iterator);
9202 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
9213 return not operator==(other);
9223 if (m_object != other.m_object)
9225 JSON_THROW(std::domain_error(
"cannot compare iterators of different containers"));
9228 assert(m_object !=
nullptr);
9230 switch (m_object->m_type)
9232 case basic_json::value_t::object:
9234 JSON_THROW(std::domain_error(
"cannot compare order of object iterators"));
9237 case basic_json::value_t::array:
9239 return (m_it.array_iterator < other.m_it.array_iterator);
9244 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
9255 return not other.operator < (*this);
9264 return not operator<=(other);
9273 return not operator<(other);
9282 assert(m_object !=
nullptr);
9284 switch (m_object->m_type)
9286 case basic_json::value_t::object:
9288 JSON_THROW(std::domain_error(
"cannot use offsets with object iterators"));
9291 case basic_json::value_t::array:
9293 std::advance(m_it.array_iterator, i);
9299 m_it.primitive_iterator += i;
9313 return operator+=(-i);
9322 auto result = *
this;
9333 auto result = *
this;
9344 assert(m_object !=
nullptr);
9346 switch (m_object->m_type)
9348 case basic_json::value_t::object:
9350 JSON_THROW(std::domain_error(
"cannot use offsets with object iterators"));
9353 case basic_json::value_t::array:
9355 return m_it.array_iterator - other.m_it.array_iterator;
9360 return m_it.primitive_iterator - other.m_it.primitive_iterator;
9371 assert(m_object !=
nullptr);
9373 switch (m_object->m_type)
9375 case basic_json::value_t::object:
9377 JSON_THROW(std::domain_error(
"cannot use operator[] for object iterators"));
9380 case basic_json::value_t::array:
9382 return *std::next(m_it.array_iterator, n);
9385 case basic_json::value_t::null:
9387 JSON_THROW(std::out_of_range(
"cannot get value"));
9392 if (m_it.primitive_iterator.get_value() == -n)
9397 JSON_THROW(std::out_of_range(
"cannot get value"));
9406 typename object_t::key_type
key()
const
9408 assert(m_object !=
nullptr);
9410 if (m_object->is_object())
9412 return m_it.object_iterator->first;
9415 JSON_THROW(std::domain_error(
"cannot use key() for non-object iterators"));
9431 internal_iterator m_it = internal_iterator();
9451 template<
typename Base>
9473 return base_iterator::operator++(1);
9479 base_iterator::operator++();
9486 return base_iterator::operator--(1);
9492 base_iterator::operator--();
9499 base_iterator::operator+=(i);
9506 auto result = *
this;
9514 auto result = *
this;
9522 return this->base() - other.base();
9528 return *(this->operator+(n));
9532 typename object_t::key_type
key()
const
9534 auto it = --this->base();
9541 auto it = --this->base();
9542 return it.operator * ();
9563 enum class token_type
9584 using lexer_char_t =
unsigned char;
9587 lexer(
const lexer_char_t* buff,
const size_t len) noexcept
9590 assert(m_content !=
nullptr);
9591 m_start = m_cursor = m_content;
9592 m_limit = m_content + len;
9596 explicit lexer(std::istream& s)
9597 : m_stream(&s), m_line_buffer()
9602 JSON_THROW(std::invalid_argument(
"stream error"));
9609 if (m_line_buffer.size() >= 3 and m_line_buffer.substr(0, 3) ==
"\xEF\xBB\xBF")
9611 m_line_buffer[0] =
' ';
9612 m_line_buffer[1] =
' ';
9613 m_line_buffer[2] =
' ';
9619 lexer(
const lexer&) =
delete;
9620 lexer operator=(
const lexer&) =
delete;
9645 static string_t to_unicode(
const std::size_t codepoint1,
9646 const std::size_t codepoint2 = 0)
9649 std::size_t codepoint = codepoint1;
9652 if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
9655 if (codepoint2 >= 0xDC00 and codepoint2 <= 0xDFFF)
9669 JSON_THROW(std::invalid_argument(
"missing or wrong low surrogate"));
9675 if (codepoint < 0x80)
9678 result.append(1,
static_cast<typename string_t::value_type
>(codepoint));
9680 else if (codepoint <= 0x7ff)
9683 result.append(1,
static_cast<typename string_t::value_type
>(0xC0 | ((codepoint >> 6) & 0x1F)));
9684 result.append(1,
static_cast<typename string_t::value_type
>(0x80 | (codepoint & 0x3F)));
9686 else if (codepoint <= 0xffff)
9689 result.append(1,
static_cast<typename string_t::value_type
>(0xE0 | ((codepoint >> 12) & 0x0F)));
9690 result.append(1,
static_cast<typename string_t::value_type
>(0x80 | ((codepoint >> 6) & 0x3F)));
9691 result.append(1,
static_cast<typename string_t::value_type
>(0x80 | (codepoint & 0x3F)));
9693 else if (codepoint <= 0x10ffff)
9696 result.append(1,
static_cast<typename string_t::value_type
>(0xF0 | ((codepoint >> 18) & 0x07)));
9697 result.append(1,
static_cast<typename string_t::value_type
>(0x80 | ((codepoint >> 12) & 0x3F)));
9698 result.append(1,
static_cast<typename string_t::value_type
>(0x80 | ((codepoint >> 6) & 0x3F)));
9699 result.append(1,
static_cast<typename string_t::value_type
>(0x80 | (codepoint & 0x3F)));
9703 JSON_THROW(std::out_of_range(
"code points above 0x10FFFF are invalid"));
9710 static std::string token_type_name(
const token_type t)
9714 case token_type::uninitialized:
9715 return "<uninitialized>";
9716 case token_type::literal_true:
9717 return "true literal";
9718 case token_type::literal_false:
9719 return "false literal";
9720 case token_type::literal_null:
9721 return "null literal";
9722 case token_type::value_string:
9723 return "string literal";
9724 case lexer::token_type::value_unsigned:
9725 case lexer::token_type::value_integer:
9726 case lexer::token_type::value_float:
9727 return "number literal";
9728 case token_type::begin_array:
9730 case token_type::begin_object:
9732 case token_type::end_array:
9734 case token_type::end_object:
9736 case token_type::name_separator:
9738 case token_type::value_separator:
9740 case token_type::parse_error:
9741 return "<parse error>";
9742 case token_type::end_of_input:
9743 return "end of input";
9747 return "unknown token";
9782 assert(m_start !=
nullptr);
9787 unsigned int yyaccept = 0;
9788 static const unsigned char yybm[] = {
9789 0, 0, 0, 0, 0, 0, 0, 0,
9790 0, 32, 32, 0, 0, 32, 0, 0,
9791 0, 0, 0, 0, 0, 0, 0, 0,
9792 0, 0, 0, 0, 0, 0, 0, 0,
9793 160, 128, 0, 128, 128, 128, 128, 128,
9794 128, 128, 128, 128, 128, 128, 128, 128,
9795 192, 192, 192, 192, 192, 192, 192, 192,
9796 192, 192, 128, 128, 128, 128, 128, 128,
9797 128, 128, 128, 128, 128, 128, 128, 128,
9798 128, 128, 128, 128, 128, 128, 128, 128,
9799 128, 128, 128, 128, 128, 128, 128, 128,
9800 128, 128, 128, 128, 0, 128, 128, 128,
9801 128, 128, 128, 128, 128, 128, 128, 128,
9802 128, 128, 128, 128, 128, 128, 128, 128,
9803 128, 128, 128, 128, 128, 128, 128, 128,
9804 128, 128, 128, 128, 128, 128, 128, 128,
9805 0, 0, 0, 0, 0, 0, 0, 0,
9806 0, 0, 0, 0, 0, 0, 0, 0,
9807 0, 0, 0, 0, 0, 0, 0, 0,
9808 0, 0, 0, 0, 0, 0, 0, 0,
9809 0, 0, 0, 0, 0, 0, 0, 0,
9810 0, 0, 0, 0, 0, 0, 0, 0,
9811 0, 0, 0, 0, 0, 0, 0, 0,
9812 0, 0, 0, 0, 0, 0, 0, 0,
9813 0, 0, 0, 0, 0, 0, 0, 0,
9814 0, 0, 0, 0, 0, 0, 0, 0,
9815 0, 0, 0, 0, 0, 0, 0, 0,
9816 0, 0, 0, 0, 0, 0, 0, 0,
9817 0, 0, 0, 0, 0, 0, 0, 0,
9818 0, 0, 0, 0, 0, 0, 0, 0,
9819 0, 0, 0, 0, 0, 0, 0, 0,
9820 0, 0, 0, 0, 0, 0, 0, 0,
9822 if ((m_limit - m_cursor) < 5) fill_line_buffer(5);
9824 if (yybm[0+yych] & 32) {
9825 goto basic_json_parser_4;
9830 if (yych <= 0x00)
goto basic_json_parser_1;
9831 if (yych <=
'!')
goto basic_json_parser_2;
9832 goto basic_json_parser_5;
9834 if (yych <=
'+')
goto basic_json_parser_2;
9835 if (yych <=
',')
goto basic_json_parser_6;
9836 goto basic_json_parser_7;
9840 if (yych <=
'/')
goto basic_json_parser_2;
9841 if (yych <=
'0')
goto basic_json_parser_8;
9842 goto basic_json_parser_10;
9844 if (yych <=
':')
goto basic_json_parser_11;
9845 if (yych <=
'Z')
goto basic_json_parser_2;
9846 goto basic_json_parser_12;
9852 if (yych ==
']')
goto basic_json_parser_13;
9853 goto basic_json_parser_2;
9855 if (yych <=
'f')
goto basic_json_parser_14;
9856 if (yych <=
'm')
goto basic_json_parser_2;
9857 goto basic_json_parser_15;
9861 if (yych ==
't')
goto basic_json_parser_16;
9862 goto basic_json_parser_2;
9864 if (yych <=
'{')
goto basic_json_parser_17;
9865 if (yych ==
'}')
goto basic_json_parser_18;
9866 goto basic_json_parser_2;
9872 { last_token_type = token_type::end_of_input;
break; }
9876 { last_token_type = token_type::parse_error;
break; }
9879 if (m_limit <= m_cursor) fill_line_buffer(1);
9881 if (yybm[0+yych] & 32) {
9882 goto basic_json_parser_4;
9887 yych = *(m_marker = ++m_cursor);
9888 if (yych <= 0x1F)
goto basic_json_parser_3;
9889 if (yych <= 0x7F)
goto basic_json_parser_20;
9890 if (yych <= 0xC1)
goto basic_json_parser_3;
9891 if (yych <= 0xF4)
goto basic_json_parser_20;
9892 goto basic_json_parser_3;
9895 { last_token_type = token_type::value_separator;
break; }
9898 if (yych <=
'/')
goto basic_json_parser_3;
9899 if (yych <=
'0')
goto basic_json_parser_31;
9900 if (yych <=
'9')
goto basic_json_parser_33;
9901 goto basic_json_parser_3;
9904 yych = *(m_marker = ++m_cursor);
9906 if (yych ==
'.')
goto basic_json_parser_34;
9907 if (yych >=
'0')
goto basic_json_parser_35;
9910 if (yych >=
'E')
goto basic_json_parser_37;
9912 if (yych ==
'e')
goto basic_json_parser_37;
9916 { last_token_type = token_type::value_unsigned;
break; }
9917basic_json_parser_10:
9919 m_marker = ++m_cursor;
9920 if ((m_limit - m_cursor) < 3) fill_line_buffer(3);
9922 if (yybm[0+yych] & 64) {
9923 goto basic_json_parser_10;
9926 if (yych ==
'.')
goto basic_json_parser_34;
9927 goto basic_json_parser_9;
9929 if (yych <=
'E')
goto basic_json_parser_37;
9930 if (yych ==
'e')
goto basic_json_parser_37;
9931 goto basic_json_parser_9;
9933basic_json_parser_11:
9935 { last_token_type = token_type::name_separator;
break; }
9936basic_json_parser_12:
9938 { last_token_type = token_type::begin_array;
break; }
9939basic_json_parser_13:
9941 { last_token_type = token_type::end_array;
break; }
9942basic_json_parser_14:
9944 yych = *(m_marker = ++m_cursor);
9945 if (yych ==
'a')
goto basic_json_parser_38;
9946 goto basic_json_parser_3;
9947basic_json_parser_15:
9949 yych = *(m_marker = ++m_cursor);
9950 if (yych ==
'u')
goto basic_json_parser_39;
9951 goto basic_json_parser_3;
9952basic_json_parser_16:
9954 yych = *(m_marker = ++m_cursor);
9955 if (yych ==
'r')
goto basic_json_parser_40;
9956 goto basic_json_parser_3;
9957basic_json_parser_17:
9959 { last_token_type = token_type::begin_object;
break; }
9960basic_json_parser_18:
9962 { last_token_type = token_type::end_object;
break; }
9963basic_json_parser_19:
9965 if (m_limit <= m_cursor) fill_line_buffer(1);
9967basic_json_parser_20:
9968 if (yybm[0+yych] & 128) {
9969 goto basic_json_parser_19;
9973 if (yych <= 0x1F)
goto basic_json_parser_21;
9974 if (yych <=
'"')
goto basic_json_parser_22;
9975 goto basic_json_parser_23;
9977 if (yych <= 0xC1)
goto basic_json_parser_21;
9978 if (yych <= 0xDF)
goto basic_json_parser_24;
9979 goto basic_json_parser_25;
9983 if (yych == 0xED)
goto basic_json_parser_27;
9984 goto basic_json_parser_26;
9986 if (yych <= 0xF0)
goto basic_json_parser_28;
9987 if (yych <= 0xF3)
goto basic_json_parser_29;
9988 if (yych <= 0xF4)
goto basic_json_parser_30;
9991basic_json_parser_21:
9992 m_cursor = m_marker;
9993 if (yyaccept <= 1) {
9994 if (yyaccept == 0) {
9995 goto basic_json_parser_3;
9997 goto basic_json_parser_9;
10000 if (yyaccept == 2) {
10001 goto basic_json_parser_32;
10003 goto basic_json_parser_43;
10006basic_json_parser_22:
10008 { last_token_type = token_type::value_string;
break; }
10009basic_json_parser_23:
10011 if (m_limit <= m_cursor) fill_line_buffer(1);
10015 if (yych ==
'"')
goto basic_json_parser_19;
10016 if (yych <=
'.')
goto basic_json_parser_21;
10017 goto basic_json_parser_19;
10019 if (yych <=
'\\') {
10020 if (yych <=
'[')
goto basic_json_parser_21;
10021 goto basic_json_parser_19;
10023 if (yych ==
'b')
goto basic_json_parser_19;
10024 goto basic_json_parser_21;
10029 if (yych <=
'f')
goto basic_json_parser_19;
10030 if (yych ==
'n')
goto basic_json_parser_19;
10031 goto basic_json_parser_21;
10034 if (yych <=
'r')
goto basic_json_parser_19;
10035 goto basic_json_parser_21;
10037 if (yych <=
't')
goto basic_json_parser_19;
10038 if (yych <=
'u')
goto basic_json_parser_41;
10039 goto basic_json_parser_21;
10043basic_json_parser_24:
10045 if (m_limit <= m_cursor) fill_line_buffer(1);
10047 if (yych <= 0x7F)
goto basic_json_parser_21;
10048 if (yych <= 0xBF)
goto basic_json_parser_19;
10049 goto basic_json_parser_21;
10050basic_json_parser_25:
10052 if (m_limit <= m_cursor) fill_line_buffer(1);
10054 if (yych <= 0x9F)
goto basic_json_parser_21;
10055 if (yych <= 0xBF)
goto basic_json_parser_24;
10056 goto basic_json_parser_21;
10057basic_json_parser_26:
10059 if (m_limit <= m_cursor) fill_line_buffer(1);
10061 if (yych <= 0x7F)
goto basic_json_parser_21;
10062 if (yych <= 0xBF)
goto basic_json_parser_24;
10063 goto basic_json_parser_21;
10064basic_json_parser_27:
10066 if (m_limit <= m_cursor) fill_line_buffer(1);
10068 if (yych <= 0x7F)
goto basic_json_parser_21;
10069 if (yych <= 0x9F)
goto basic_json_parser_24;
10070 goto basic_json_parser_21;
10071basic_json_parser_28:
10073 if (m_limit <= m_cursor) fill_line_buffer(1);
10075 if (yych <= 0x8F)
goto basic_json_parser_21;
10076 if (yych <= 0xBF)
goto basic_json_parser_26;
10077 goto basic_json_parser_21;
10078basic_json_parser_29:
10080 if (m_limit <= m_cursor) fill_line_buffer(1);
10082 if (yych <= 0x7F)
goto basic_json_parser_21;
10083 if (yych <= 0xBF)
goto basic_json_parser_26;
10084 goto basic_json_parser_21;
10085basic_json_parser_30:
10087 if (m_limit <= m_cursor) fill_line_buffer(1);
10089 if (yych <= 0x7F)
goto basic_json_parser_21;
10090 if (yych <= 0x8F)
goto basic_json_parser_26;
10091 goto basic_json_parser_21;
10092basic_json_parser_31:
10094 yych = *(m_marker = ++m_cursor);
10096 if (yych ==
'.')
goto basic_json_parser_34;
10097 if (yych >=
'0')
goto basic_json_parser_35;
10100 if (yych >=
'E')
goto basic_json_parser_37;
10102 if (yych ==
'e')
goto basic_json_parser_37;
10105basic_json_parser_32:
10106 { last_token_type = token_type::value_integer;
break; }
10107basic_json_parser_33:
10109 m_marker = ++m_cursor;
10110 if ((m_limit - m_cursor) < 3) fill_line_buffer(3);
10113 if (yych ==
'.')
goto basic_json_parser_34;
10114 if (yych <=
'/')
goto basic_json_parser_32;
10115 goto basic_json_parser_33;
10118 if (yych <=
'D')
goto basic_json_parser_32;
10119 goto basic_json_parser_37;
10121 if (yych ==
'e')
goto basic_json_parser_37;
10122 goto basic_json_parser_32;
10125basic_json_parser_34:
10126 yych = *++m_cursor;
10127 if (yych <=
'/')
goto basic_json_parser_21;
10128 if (yych <=
'9')
goto basic_json_parser_42;
10129 goto basic_json_parser_21;
10130basic_json_parser_35:
10132 if (m_limit <= m_cursor) fill_line_buffer(1);
10134 if (yych <=
'/')
goto basic_json_parser_36;
10135 if (yych <=
'9')
goto basic_json_parser_35;
10136basic_json_parser_36:
10137 { last_token_type = token_type::parse_error;
break; }
10138basic_json_parser_37:
10139 yych = *++m_cursor;
10141 if (yych ==
'+')
goto basic_json_parser_44;
10142 goto basic_json_parser_21;
10144 if (yych <=
'-')
goto basic_json_parser_44;
10145 if (yych <=
'/')
goto basic_json_parser_21;
10146 if (yych <=
'9')
goto basic_json_parser_45;
10147 goto basic_json_parser_21;
10149basic_json_parser_38:
10150 yych = *++m_cursor;
10151 if (yych ==
'l')
goto basic_json_parser_46;
10152 goto basic_json_parser_21;
10153basic_json_parser_39:
10154 yych = *++m_cursor;
10155 if (yych ==
'l')
goto basic_json_parser_47;
10156 goto basic_json_parser_21;
10157basic_json_parser_40:
10158 yych = *++m_cursor;
10159 if (yych ==
'u')
goto basic_json_parser_48;
10160 goto basic_json_parser_21;
10161basic_json_parser_41:
10163 if (m_limit <= m_cursor) fill_line_buffer(1);
10166 if (yych <=
'/')
goto basic_json_parser_21;
10167 if (yych <=
'9')
goto basic_json_parser_49;
10168 goto basic_json_parser_21;
10170 if (yych <=
'F')
goto basic_json_parser_49;
10171 if (yych <=
'`')
goto basic_json_parser_21;
10172 if (yych <=
'f')
goto basic_json_parser_49;
10173 goto basic_json_parser_21;
10175basic_json_parser_42:
10177 m_marker = ++m_cursor;
10178 if ((m_limit - m_cursor) < 3) fill_line_buffer(3);
10181 if (yych <=
'/')
goto basic_json_parser_43;
10182 if (yych <=
'9')
goto basic_json_parser_42;
10184 if (yych <=
'E')
goto basic_json_parser_37;
10185 if (yych ==
'e')
goto basic_json_parser_37;
10187basic_json_parser_43:
10188 { last_token_type = token_type::value_float;
break; }
10189basic_json_parser_44:
10190 yych = *++m_cursor;
10191 if (yych <=
'/')
goto basic_json_parser_21;
10192 if (yych >=
':')
goto basic_json_parser_21;
10193basic_json_parser_45:
10195 if (m_limit <= m_cursor) fill_line_buffer(1);
10197 if (yych <=
'/')
goto basic_json_parser_43;
10198 if (yych <=
'9')
goto basic_json_parser_45;
10199 goto basic_json_parser_43;
10200basic_json_parser_46:
10201 yych = *++m_cursor;
10202 if (yych ==
's')
goto basic_json_parser_50;
10203 goto basic_json_parser_21;
10204basic_json_parser_47:
10205 yych = *++m_cursor;
10206 if (yych ==
'l')
goto basic_json_parser_51;
10207 goto basic_json_parser_21;
10208basic_json_parser_48:
10209 yych = *++m_cursor;
10210 if (yych ==
'e')
goto basic_json_parser_52;
10211 goto basic_json_parser_21;
10212basic_json_parser_49:
10214 if (m_limit <= m_cursor) fill_line_buffer(1);
10217 if (yych <=
'/')
goto basic_json_parser_21;
10218 if (yych <=
'9')
goto basic_json_parser_53;
10219 goto basic_json_parser_21;
10221 if (yych <=
'F')
goto basic_json_parser_53;
10222 if (yych <=
'`')
goto basic_json_parser_21;
10223 if (yych <=
'f')
goto basic_json_parser_53;
10224 goto basic_json_parser_21;
10226basic_json_parser_50:
10227 yych = *++m_cursor;
10228 if (yych ==
'e')
goto basic_json_parser_54;
10229 goto basic_json_parser_21;
10230basic_json_parser_51:
10232 { last_token_type = token_type::literal_null;
break; }
10233basic_json_parser_52:
10235 { last_token_type = token_type::literal_true;
break; }
10236basic_json_parser_53:
10238 if (m_limit <= m_cursor) fill_line_buffer(1);
10241 if (yych <=
'/')
goto basic_json_parser_21;
10242 if (yych <=
'9')
goto basic_json_parser_55;
10243 goto basic_json_parser_21;
10245 if (yych <=
'F')
goto basic_json_parser_55;
10246 if (yych <=
'`')
goto basic_json_parser_21;
10247 if (yych <=
'f')
goto basic_json_parser_55;
10248 goto basic_json_parser_21;
10250basic_json_parser_54:
10252 { last_token_type = token_type::literal_false;
break; }
10253basic_json_parser_55:
10255 if (m_limit <= m_cursor) fill_line_buffer(1);
10258 if (yych <=
'/')
goto basic_json_parser_21;
10259 if (yych <=
'9')
goto basic_json_parser_19;
10260 goto basic_json_parser_21;
10262 if (yych <=
'F')
goto basic_json_parser_19;
10263 if (yych <=
'`')
goto basic_json_parser_21;
10264 if (yych <=
'f')
goto basic_json_parser_19;
10265 goto basic_json_parser_21;
10271 return last_token_type;
10302 void fill_line_buffer(
size_t n = 0)
10305 assert(m_line_buffer.empty()
10306 or m_content ==
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data()));
10309 assert(m_line_buffer.empty()
10310 or m_limit == m_content + m_line_buffer.size());
10313 assert(m_content <= m_start);
10314 assert(m_start <= m_cursor);
10315 assert(m_cursor <= m_limit);
10316 assert(m_marker ==
nullptr or m_marker <= m_limit);
10319 const auto num_processed_chars =
static_cast<size_t>(m_start - m_content);
10321 const auto offset_marker = (m_marker ==
nullptr) ? 0 : m_marker - m_start;
10323 const auto offset_cursor = m_cursor - m_start;
10326 if (m_stream ==
nullptr or m_stream->eof())
10331 m_line_buffer.assign(m_start, m_limit);
10335 m_line_buffer.append(1,
'\x00');
10338 m_line_buffer.append(n - 1,
'\x01');
10344 m_line_buffer.erase(0, num_processed_chars);
10346 m_line_buffer_tmp.clear();
10347 std::getline(*m_stream, m_line_buffer_tmp,
'\n');
10350 m_line_buffer += m_line_buffer_tmp;
10351 m_line_buffer.push_back(
'\n');
10355 m_content =
reinterpret_cast<const lexer_char_t*
>(m_line_buffer.data());
10356 assert(m_content !=
nullptr);
10357 m_start = m_content;
10358 m_marker = m_start + offset_marker;
10359 m_cursor = m_start + offset_cursor;
10360 m_limit = m_start + m_line_buffer.size();
10364 string_t get_token_string()
const
10366 assert(m_start !=
nullptr);
10367 return string_t(
reinterpret_cast<typename string_t::const_pointer
>(m_start),
10368 static_cast<size_t>(m_cursor - m_start));
10428 string_t get_string()
const
10430 assert(m_cursor - m_start >= 2);
10433 result.reserve(
static_cast<size_t>(m_cursor - m_start - 2));
10436 for (
const lexer_char_t* i = m_start + 1; i < m_cursor - 1; ++i)
10439 auto e = std::find(i, m_cursor - 1,
'\\');
10443 for (
auto k = i; k < e; k++)
10445 result.push_back(
static_cast<typename string_t::value_type
>(*k));
10503 auto codepoint = std::strtoul(std::string(
reinterpret_cast<typename string_t::const_pointer
>(i + 1),
10504 4).c_str(),
nullptr, 16);
10507 if (codepoint >= 0xD800 and codepoint <= 0xDBFF)
10510 if ((i + 6 >= m_limit) or * (i + 5) !=
'\\' or * (i + 6) !=
'u')
10512 JSON_THROW(std::invalid_argument(
"missing low surrogate"));
10516 auto codepoint2 = std::strtoul(std::string(
reinterpret_cast<typename string_t::const_pointer
>
10517 (i + 7), 4).c_str(),
nullptr, 16);
10518 result += to_unicode(codepoint, codepoint2);
10522 else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
10525 JSON_THROW(std::invalid_argument(
"missing high surrogate"));
10530 result += to_unicode(codepoint);
10557 : m_start(start), m_end(end)
10566 template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
10569 return parse(val, std::is_integral<T>());
10573 const char*
const m_start =
nullptr;
10574 const char*
const m_end =
nullptr;
10580 static void strtof(
float& f,
const char* str,
char** endptr)
10582 f = std::strtof(str, endptr);
10585 static void strtof(
double& f,
const char* str,
char** endptr)
10587 f = std::strtod(str, endptr);
10590 static void strtof(
long double& f,
const char* str,
char** endptr)
10592 f = std::strtold(str, endptr);
10595 template<
typename T>
10596 bool parse(T& value, std::false_type)
const
10601 std::string tempstr;
10602 std::array<char, 64> buf;
10603 const size_t len =
static_cast<size_t>(m_end - m_start);
10611 const auto loc = localeconv();
10612 assert(loc !=
nullptr);
10613 const char decimal_point_char = (loc->decimal_point ==
nullptr) ?
'.' : loc->decimal_point[0];
10615 const char* data = m_start;
10617 if (decimal_point_char !=
'.')
10619 const size_t ds_pos =
static_cast<size_t>(std::find(m_start, m_end,
'.') - m_start);
10626 if ((len + 1) < buf.size())
10628 std::copy(m_start, m_end, buf.begin());
10630 buf[ds_pos] = decimal_point_char;
10635 tempstr.assign(m_start, m_end);
10636 tempstr[ds_pos] = decimal_point_char;
10637 data = tempstr.c_str();
10642 char* endptr =
nullptr;
10645 strtof(value, data, &endptr);
10649 const bool ok = (endptr == (data + len));
10651 if (ok and (value ==
static_cast<T
>(0.0)) and (*data ==
'-'))
10662 signed long long parse_integral(
char** endptr, std::true_type)
const
10664 return std::strtoll(m_start, endptr, 10);
10667 unsigned long long parse_integral(
char** endptr, std::false_type)
const
10669 return std::strtoull(m_start, endptr, 10);
10672 template<
typename T>
10673 bool parse(T& value, std::true_type)
const
10675 char* endptr =
nullptr;
10677 const auto x = parse_integral(&endptr, std::is_signed<T>());
10680 static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(),
"");
10682 value =
static_cast<T
>(x);
10684 return (x ==
static_cast<decltype(x)
>(value))
10685 and (x < 0) == (value < 0)
10688 and (m_start < m_end)
10689 and (endptr == m_end);
10712 bool get_number(basic_json& result,
const token_type token)
const
10714 assert(m_start !=
nullptr);
10715 assert(m_start < m_cursor);
10716 assert((token == token_type::value_unsigned) or
10717 (token == token_type::value_integer) or
10718 (token == token_type::value_float));
10720 strtonum num_converter(
reinterpret_cast<const char*
>(m_start),
10721 reinterpret_cast<const char*
>(m_cursor));
10725 case lexer::token_type::value_unsigned:
10727 number_unsigned_t val;
10728 if (num_converter.to(val))
10731 result.m_type = value_t::number_unsigned;
10732 result.m_value = val;
10738 case lexer::token_type::value_integer:
10740 number_integer_t val;
10741 if (num_converter.to(val))
10744 result.m_type = value_t::number_integer;
10745 result.m_value = val;
10759 number_float_t val;
10760 if (num_converter.to(val))
10763 result.m_type = value_t::number_float;
10764 result.m_value = val;
10767 if (not std::isfinite(result.m_value.number_float))
10769 result.m_type = value_t::null;
10770 result.m_value = basic_json::json_value();
10782 std::istream* m_stream =
nullptr;
10784 string_t m_line_buffer {};
10786 string_t m_line_buffer_tmp {};
10788 const lexer_char_t* m_content =
nullptr;
10790 const lexer_char_t* m_start =
nullptr;
10792 const lexer_char_t* m_marker =
nullptr;
10794 const lexer_char_t* m_cursor =
nullptr;
10796 const lexer_char_t* m_limit =
nullptr;
10798 token_type last_token_type = token_type::end_of_input;
10810 parser(
const char* buff,
const parser_callback_t cb =
nullptr)
10812 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(buff),
std::strlen(buff))
10816 parser(std::istream& is,
const parser_callback_t cb =
nullptr)
10817 : callback(cb), m_lexer(is)
10821 template<
class IteratorType,
typename std::enable_if<
10822 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value
10825 parser(IteratorType first, IteratorType last,
const parser_callback_t cb =
nullptr)
10827 m_lexer(reinterpret_cast<const typename lexer::lexer_char_t*>(&(*first)),
10828 static_cast<size_t>(
std::distance(first, last)))
10837 basic_json result = parse_internal(
true);
10838 result.assert_invariant();
10840 expect(lexer::token_type::end_of_input);
10844 return result.is_discarded() ? basic_json() :
std::move(result);
10849 basic_json parse_internal(
bool keep)
10851 auto result = basic_json(value_t::discarded);
10853 switch (last_token)
10855 case lexer::token_type::begin_object:
10857 if (keep and (not callback
10858 or ((keep = callback(depth++, parse_event_t::object_start, result)) != 0)))
10861 result.m_type = value_t::object;
10862 result.m_value = value_t::object;
10869 if (last_token == lexer::token_type::end_object)
10872 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10874 result = basic_json(value_t::discarded);
10880 unexpect(lexer::token_type::value_separator);
10886 if (last_token == lexer::token_type::value_separator)
10892 expect(lexer::token_type::value_string);
10893 const auto key = m_lexer.get_string();
10895 bool keep_tag =
false;
10901 keep_tag = callback(depth, parse_event_t::key, k);
10911 expect(lexer::token_type::name_separator);
10915 auto value = parse_internal(keep);
10916 if (keep and keep_tag and not value.is_discarded())
10918 result[key] = std::move(value);
10921 while (last_token == lexer::token_type::value_separator);
10924 expect(lexer::token_type::end_object);
10926 if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
10928 result = basic_json(value_t::discarded);
10934 case lexer::token_type::begin_array:
10936 if (keep and (not callback
10937 or ((keep = callback(depth++, parse_event_t::array_start, result)) != 0)))
10940 result.m_type = value_t::array;
10941 result.m_value = value_t::array;
10948 if (last_token == lexer::token_type::end_array)
10951 if (callback and not callback(--depth, parse_event_t::array_end, result))
10953 result = basic_json(value_t::discarded);
10959 unexpect(lexer::token_type::value_separator);
10965 if (last_token == lexer::token_type::value_separator)
10971 auto value = parse_internal(keep);
10972 if (keep and not value.is_discarded())
10974 result.push_back(std::move(value));
10977 while (last_token == lexer::token_type::value_separator);
10980 expect(lexer::token_type::end_array);
10982 if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
10984 result = basic_json(value_t::discarded);
10990 case lexer::token_type::literal_null:
10993 result.m_type = value_t::null;
10997 case lexer::token_type::value_string:
10999 const auto s = m_lexer.get_string();
11001 result = basic_json(s);
11005 case lexer::token_type::literal_true:
11008 result.m_type = value_t::boolean;
11009 result.m_value =
true;
11013 case lexer::token_type::literal_false:
11016 result.m_type = value_t::boolean;
11017 result.m_value =
false;
11021 case lexer::token_type::value_unsigned:
11022 case lexer::token_type::value_integer:
11023 case lexer::token_type::value_float:
11025 m_lexer.get_number(result, last_token);
11033 unexpect(last_token);
11037 if (keep and callback and not callback(depth, parse_event_t::value, result))
11039 result = basic_json(value_t::discarded);
11045 typename lexer::token_type get_token()
11047 last_token = m_lexer.scan();
11051 void expect(
typename lexer::token_type t)
const
11053 if (t != last_token)
11055 std::string error_msg =
"parse error - unexpected ";
11056 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
11058 lexer::token_type_name(last_token));
11059 error_msg +=
"; expected " + lexer::token_type_name(t);
11060 JSON_THROW(std::invalid_argument(error_msg));
11064 void unexpect(
typename lexer::token_type t)
const
11066 if (t == last_token)
11068 std::string error_msg =
"parse error - unexpected ";
11069 error_msg += (last_token == lexer::token_type::parse_error ? (
"'" + m_lexer.get_token_string() +
11071 lexer::token_type_name(last_token));
11072 JSON_THROW(std::invalid_argument(error_msg));
11080 const parser_callback_t callback =
nullptr;
11082 typename lexer::token_type last_token = lexer::token_type::uninitialized;
11128 : reference_tokens(split(s))
11146 std::string to_string() const noexcept
11148 return std::accumulate(reference_tokens.begin(),
11149 reference_tokens.end(), std::string{},
11150 [](
const std::string & a,
const std::string & b)
11152 return a +
"/" + escape(b);
11157 operator std::string()
const
11159 return to_string();
11164 std::string pop_back()
11168 JSON_THROW(std::domain_error(
"JSON pointer has no parent"));
11171 auto last = reference_tokens.back();
11172 reference_tokens.pop_back();
11177 bool is_root()
const
11179 return reference_tokens.empty();
11182 json_pointer top()
const
11186 JSON_THROW(std::domain_error(
"JSON pointer has no parent"));
11189 json_pointer result = *
this;
11190 result.reference_tokens = {reference_tokens[0]};
11199 reference get_and_create(reference j)
const
11201 pointer result = &j;
11205 for (
const auto& reference_token : reference_tokens)
11207 switch (result->m_type)
11209 case value_t::null:
11211 if (reference_token ==
"0")
11214 result = &result->operator[](0);
11219 result = &result->operator[](reference_token);
11224 case value_t::object:
11227 result = &result->operator[](reference_token);
11231 case value_t::array:
11234 result = &result->operator[](
static_cast<size_type
>(std::stoi(reference_token)));
11247 JSON_THROW(std::domain_error(
"invalid value to unflatten"));
11274 reference get_unchecked(pointer ptr)
const
11276 for (
const auto& reference_token : reference_tokens)
11279 if (ptr->m_type == value_t::null)
11282 const bool nums = std::all_of(reference_token.begin(),
11283 reference_token.end(),
11286 return std::isdigit(x);
11291 if (nums or reference_token ==
"-")
11293 *ptr = value_t::array;
11297 *ptr = value_t::object;
11301 switch (ptr->m_type)
11303 case value_t::object:
11306 ptr = &ptr->operator[](reference_token);
11310 case value_t::array:
11313 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11315 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11318 if (reference_token ==
"-")
11321 ptr = &ptr->operator[](ptr->m_value.array->size());
11326 ptr = &ptr->operator[](
static_cast<size_type
>(std::stoi(reference_token)));
11333 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11341 reference get_checked(pointer ptr)
const
11343 for (
const auto& reference_token : reference_tokens)
11345 switch (ptr->m_type)
11347 case value_t::object:
11350 ptr = &ptr->at(reference_token);
11354 case value_t::array:
11356 if (reference_token ==
"-")
11359 JSON_THROW(std::out_of_range(
"array index '-' (" +
11360 std::to_string(ptr->m_value.array->size()) +
11361 ") is out of range"));
11365 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11367 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11371 ptr = &ptr->at(
static_cast<size_type
>(std::stoi(reference_token)));
11377 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11393 const_reference get_unchecked(const_pointer ptr)
const
11395 for (
const auto& reference_token : reference_tokens)
11397 switch (ptr->m_type)
11399 case value_t::object:
11402 ptr = &ptr->operator[](reference_token);
11406 case value_t::array:
11408 if (reference_token ==
"-")
11411 JSON_THROW(std::out_of_range(
"array index '-' (" +
11412 std::to_string(ptr->m_value.array->size()) +
11413 ") is out of range"));
11417 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11419 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11423 ptr = &ptr->operator[](
static_cast<size_type
>(std::stoi(reference_token)));
11429 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11437 const_reference get_checked(const_pointer ptr)
const
11439 for (
const auto& reference_token : reference_tokens)
11441 switch (ptr->m_type)
11443 case value_t::object:
11446 ptr = &ptr->at(reference_token);
11450 case value_t::array:
11452 if (reference_token ==
"-")
11455 JSON_THROW(std::out_of_range(
"array index '-' (" +
11456 std::to_string(ptr->m_value.array->size()) +
11457 ") is out of range"));
11461 if (reference_token.size() > 1 and reference_token[0] ==
'0')
11463 JSON_THROW(std::domain_error(
"array index must not begin with '0'"));
11467 ptr = &ptr->at(
static_cast<size_type
>(std::stoi(reference_token)));
11473 JSON_THROW(std::out_of_range(
"unresolved reference token '" + reference_token +
"'"));
11482 static std::vector<std::string> split(
const std::string& reference_string)
11484 std::vector<std::string> result;
11487 if (reference_string.empty())
11493 if (reference_string[0] !=
'/')
11495 JSON_THROW(std::domain_error(
"JSON pointer must be empty or begin with '/'"));
11503 size_t slash = reference_string.find_first_of(
'/', 1),
11512 slash = reference_string.find_first_of(
'/', start))
11516 auto reference_token = reference_string.substr(start, slash - start);
11519 for (
size_t pos = reference_token.find_first_of(
'~');
11520 pos != std::string::npos;
11521 pos = reference_token.find_first_of(
'~', pos + 1))
11523 assert(reference_token[pos] ==
'~');
11526 if (pos == reference_token.size() - 1 or
11527 (reference_token[pos + 1] !=
'0' and
11528 reference_token[pos + 1] !=
'1'))
11530 JSON_THROW(std::domain_error(
"escape error: '~' must be followed with '0' or '1'"));
11535 unescape(reference_token);
11536 result.push_back(reference_token);
11555 static void replace_substring(std::string& s,
11556 const std::string& f,
11557 const std::string& t)
11559 assert(not f.empty());
11562 size_t pos = s.find(f);
11563 pos != std::string::npos;
11564 s.replace(pos, f.size(), t),
11565 pos = s.find(f, pos + t.size())
11570 static std::string escape(std::string s)
11573 replace_substring(s,
"~",
"~0");
11574 replace_substring(s,
"/",
"~1");
11579 static void unescape(std::string& s)
11582 replace_substring(s,
"~1",
"/");
11584 replace_substring(s,
"~0",
"~");
11594 static void flatten(
const std::string& reference_string,
11595 const basic_json& value,
11596 basic_json& result)
11598 switch (value.m_type)
11600 case value_t::array:
11602 if (value.m_value.array->empty())
11605 result[reference_string] =
nullptr;
11610 for (
size_t i = 0; i < value.m_value.array->size(); ++i)
11612 flatten(reference_string +
"/" + std::to_string(i),
11613 value.m_value.array->operator[](i), result);
11619 case value_t::object:
11621 if (value.m_value.object->empty())
11624 result[reference_string] =
nullptr;
11629 for (
const auto& element : *value.m_value.object)
11631 flatten(reference_string +
"/" + escape(element.first),
11632 element.second, result);
11641 result[reference_string] = value;
11652 static basic_json unflatten(
const basic_json& value)
11654 if (not value.is_object())
11656 JSON_THROW(std::domain_error(
"only objects can be unflattened"));
11662 for (
const auto& element : *value.m_value.object)
11664 if (not element.second.is_primitive())
11666 JSON_THROW(std::domain_error(
"values in object must be primitive"));
11674 json_pointer(element.first).get_and_create(result) = element.second;
11681 friend bool operator==(json_pointer
const& lhs,
11682 json_pointer
const& rhs)
noexcept
11684 return lhs.reference_tokens == rhs.reference_tokens;
11690 return !(lhs == rhs);
11694 std::vector<std::string> reference_tokens {};
11737 reference operator[](
const json_pointer& ptr)
11739 return ptr.get_unchecked(
this);
11766 return ptr.get_unchecked(
this);
11791 return ptr.get_checked(
this);
11816 return ptr.get_checked(
this);
11844 json_pointer::flatten(
"", *
this, result);
11877 return json_pointer::unflatten(*
this);
11931 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
11933 const auto get_op = [](
const std::string op)
11937 return patch_operations::add;
11939 if (op ==
"remove")
11941 return patch_operations::remove;
11943 if (op ==
"replace")
11945 return patch_operations::replace;
11949 return patch_operations::move;
11953 return patch_operations::copy;
11957 return patch_operations::test;
11960 return patch_operations::invalid;
11964 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
11974 json_pointer top_pointer = ptr.top();
11975 if (top_pointer != ptr)
11977 result.
at(top_pointer);
11981 const auto last_path = ptr.pop_back();
11982 basic_json& parent = result[ptr];
11984 switch (parent.m_type)
11986 case value_t::null:
11987 case value_t::object:
11990 parent[last_path] = val;
11994 case value_t::array:
11996 if (last_path ==
"-")
12003 const auto idx = std::stoi(last_path);
12004 if (
static_cast<size_type
>(idx) > parent.size())
12007 JSON_THROW(std::out_of_range(
"array index " + std::to_string(idx) +
" is out of range"));
12012 parent.insert(parent.begin() +
static_cast<difference_type
>(idx), val);
12028 const auto operation_remove = [&result](json_pointer & ptr)
12031 const auto last_path = ptr.pop_back();
12032 basic_json& parent = result.
at(ptr);
12035 if (parent.is_object())
12038 auto it = parent.
find(last_path);
12039 if (it != parent.end())
12045 JSON_THROW(std::out_of_range(
"key '" + last_path +
"' not found"));
12048 else if (parent.is_array())
12051 parent.erase(
static_cast<size_type
>(std::stoi(last_path)));
12059 JSON_THROW(std::invalid_argument(
"JSON patch must be an array of objects"));
12063 for (
const auto& val : json_patch)
12066 const auto get_value = [&val](
const std::string & op,
12067 const std::string & member,
12068 bool string_type) -> basic_json&
12071 auto it = val.m_value.object->find(member);
12074 const auto error_msg = (op ==
"op") ?
"operation" :
"operation '" + op +
"'";
12077 if (it == val.m_value.object->end())
12079 JSON_THROW(std::invalid_argument(error_msg +
" must have member '" + member +
"'"));
12083 if (string_type and not it->second.is_string())
12085 JSON_THROW(std::invalid_argument(error_msg +
" must have string member '" + member +
"'"));
12093 if (not val.is_object())
12095 JSON_THROW(std::invalid_argument(
"JSON patch must be an array of objects"));
12099 const std::string op = get_value(
"op",
"op",
true);
12100 const std::string path = get_value(op,
"path",
true);
12101 json_pointer ptr(path);
12103 switch (get_op(op))
12105 case patch_operations::add:
12107 operation_add(ptr, get_value(
"add",
"value",
false));
12111 case patch_operations::remove:
12113 operation_remove(ptr);
12117 case patch_operations::replace:
12120 result.
at(ptr) = get_value(
"replace",
"value",
false);
12124 case patch_operations::move:
12126 const std::string from_path = get_value(
"move",
"from",
true);
12127 json_pointer from_ptr(from_path);
12130 basic_json v = result.
at(from_ptr);
12136 operation_remove(from_ptr);
12137 operation_add(ptr, v);
12141 case patch_operations::copy:
12143 const std::string from_path = get_value(
"copy",
"from",
true);;
12144 const json_pointer from_ptr(from_path);
12147 result[ptr] = result.
at(from_ptr);
12151 case patch_operations::test:
12153 bool success =
false;
12158 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
12160 JSON_CATCH (std::out_of_range&)
12168 JSON_THROW(std::domain_error(
"unsuccessful: " + val.dump()));
12174 case patch_operations::invalid:
12178 JSON_THROW(std::invalid_argument(
"operation value '" + op +
"' is invalid"));
12218 static basic_json diff(
const basic_json& source,
12219 const basic_json& target,
12220 const std::string& path =
"")
12226 if (source == target)
12231 if (source.type() != target.type())
12243 switch (source.type())
12245 case value_t::array:
12249 while (i < source.size() and i < target.size())
12252 auto temp_diff = diff(source[i], target[i], path +
"/" + std::to_string(i));
12253 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
12261 const auto end_index =
static_cast<difference_type
>(result.
size());
12262 while (i < source.size())
12266 result.
insert(result.
begin() + end_index, object(
12269 {
"path", path +
"/" + std::to_string(i)}
12275 while (i < target.size())
12280 {
"path", path +
"/" + std::to_string(i)},
12281 {
"value", target[i]}
12289 case value_t::object:
12292 for (
auto it = source.begin(); it != source.end(); ++it)
12295 const auto key = json_pointer::escape(it.key());
12297 if (target.find(it.key()) != target.end())
12300 auto temp_diff = diff(it.value(), target[it.key()], path +
"/" + key);
12301 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
12309 {
"path", path +
"/" + key}
12315 for (
auto it = target.begin(); it != target.end(); ++it)
12317 if (source.find(it.key()) == source.end())
12320 const auto key = json_pointer::escape(it.key());
12324 {
"path", path +
"/" + key},
12325 {
"value", it.value()}