22 NLOHMANN_BASIC_JSON_TPL_DECLARATION
48 : reference_tokens(split(s))
67 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
69 [](
const std::string & a,
const std::string & b)
71 return a +
"/" + detail::escape(b);
76 operator std::string()
const
99 reference_tokens.insert(reference_tokens.end(),
100 ptr.reference_tokens.begin(),
101 ptr.reference_tokens.end());
145 return *
this /= std::to_string(array_idx);
249 if (JSON_HEDLEY_UNLIKELY(
empty()))
251 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent", BasicJsonType()));
254 reference_tokens.pop_back();
271 const std::string&
back()
const
273 if (JSON_HEDLEY_UNLIKELY(
empty()))
275 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent", BasicJsonType()));
278 return reference_tokens.back();
295 reference_tokens.push_back(token);
301 reference_tokens.push_back(std::move(token));
320 return reference_tokens.empty();
334 static typename BasicJsonType::size_type array_index(
const std::string& s)
336 using size_type =
typename BasicJsonType::size_type;
339 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] ==
'0'))
345 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >=
'1' && s[0] <=
'9')))
350 std::size_t processed_chars = 0;
351 unsigned long long res = 0;
354 res = std::stoull(s, &processed_chars);
356 JSON_CATCH(std::out_of_range&)
358 JSON_THROW(detail::out_of_range::create(404,
"unresolved reference token '" + s +
"'", BasicJsonType()));
362 if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
364 JSON_THROW(detail::out_of_range::create(404,
"unresolved reference token '" + s +
"'", BasicJsonType()));
369 if (res >=
static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
371 JSON_THROW(detail::out_of_range::create(410,
"array index " + s +
" exceeds size_type", BasicJsonType()));
374 return static_cast<size_type
>(res);
377 JSON_PRIVATE_UNLESS_TESTED:
380 if (JSON_HEDLEY_UNLIKELY(
empty()))
382 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent", BasicJsonType()));
386 result.reference_tokens = {reference_tokens[0]};
399 BasicJsonType& get_and_create(BasicJsonType& j)
const
405 for (
const auto& reference_token : reference_tokens)
407 switch (result->type())
411 if (reference_token ==
"0")
414 result = &result->operator[](0);
419 result = &result->operator[](reference_token);
427 result = &result->operator[](reference_token);
434 result = &result->operator[](array_index(reference_token));
452 JSON_THROW(detail::type_error::create(313,
"invalid value to unflatten", j));
478 BasicJsonType& get_unchecked(BasicJsonType* ptr)
const
480 for (
const auto& reference_token : reference_tokens)
487 std::all_of(reference_token.begin(), reference_token.end(),
488 [](
const unsigned char x)
490 return std::isdigit(x);
494 *ptr = (nums || reference_token ==
"-")
504 ptr = &ptr->operator[](reference_token);
510 if (reference_token ==
"-")
513 ptr = &ptr->operator[](ptr->m_value.array->size());
518 ptr = &ptr->operator[](array_index(reference_token));
532 JSON_THROW(detail::out_of_range::create(404,
"unresolved reference token '" + reference_token +
"'", *ptr));
545 BasicJsonType& get_checked(BasicJsonType* ptr)
const
547 for (
const auto& reference_token : reference_tokens)
554 ptr = &ptr->at(reference_token);
560 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
563 JSON_THROW(detail::out_of_range::create(402,
564 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
565 ") is out of range", *ptr));
569 ptr = &ptr->at(array_index(reference_token));
582 JSON_THROW(detail::out_of_range::create(404,
"unresolved reference token '" + reference_token +
"'", *ptr));
602 const BasicJsonType& get_unchecked(
const BasicJsonType* ptr)
const
604 for (
const auto& reference_token : reference_tokens)
611 ptr = &ptr->operator[](reference_token);
617 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
620 JSON_THROW(detail::out_of_range::create(402,
"array index '-' (" + std::to_string(ptr->m_value.array->size()) +
") is out of range", *ptr));
624 ptr = &ptr->operator[](array_index(reference_token));
637 JSON_THROW(detail::out_of_range::create(404,
"unresolved reference token '" + reference_token +
"'", *ptr));
650 const BasicJsonType& get_checked(
const BasicJsonType* ptr)
const
652 for (
const auto& reference_token : reference_tokens)
659 ptr = &ptr->at(reference_token);
665 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
668 JSON_THROW(detail::out_of_range::create(402,
669 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
670 ") is out of range", *ptr));
674 ptr = &ptr->at(array_index(reference_token));
687 JSON_THROW(detail::out_of_range::create(404,
"unresolved reference token '" + reference_token +
"'", *ptr));
698 bool contains(
const BasicJsonType* ptr)
const
700 for (
const auto& reference_token : reference_tokens)
706 if (!ptr->contains(reference_token))
712 ptr = &ptr->operator[](reference_token);
718 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
723 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !(
"0" <= reference_token && reference_token <=
"9")))
728 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
730 if (JSON_HEDLEY_UNLIKELY(!(
'1' <= reference_token[0] && reference_token[0] <=
'9')))
735 for (std::size_t i = 1; i < reference_token.size(); i++)
737 if (JSON_HEDLEY_UNLIKELY(!(
'0' <= reference_token[i] && reference_token[i] <=
'9')))
745 const auto idx = array_index(reference_token);
746 if (idx >= ptr->size())
752 ptr = &ptr->operator[](idx);
786 static std::vector<std::string> split(
const std::string& reference_string)
788 std::vector<std::string> result;
791 if (reference_string.empty())
797 if (JSON_HEDLEY_UNLIKELY(reference_string[0] !=
'/'))
799 JSON_THROW(
detail::parse_error::create(107, 1,
"JSON pointer must be empty or begin with '/' - was: '" + reference_string +
"'", BasicJsonType()));
807 std::size_t slash = reference_string.find_first_of(
'/', 1),
814 start = (slash == std::string::npos) ? 0 : slash + 1,
816 slash = reference_string.find_first_of(
'/', start))
820 auto reference_token = reference_string.substr(start, slash - start);
823 for (std::size_t pos = reference_token.find_first_of(
'~');
824 pos != std::string::npos;
825 pos = reference_token.find_first_of(
'~', pos + 1))
827 JSON_ASSERT(reference_token[pos] ==
'~');
830 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
831 (reference_token[pos + 1] !=
'0' &&
832 reference_token[pos + 1] !=
'1')))
839 detail::unescape(reference_token);
840 result.push_back(reference_token);
854 static void flatten(
const std::string& reference_string,
855 const BasicJsonType& value,
856 BasicJsonType& result)
858 switch (value.type())
862 if (value.m_value.array->empty())
865 result[reference_string] =
nullptr;
870 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
872 flatten(reference_string +
"/" + std::to_string(i),
873 value.m_value.array->operator[](i), result);
881 if (value.m_value.object->empty())
884 result[reference_string] =
nullptr;
889 for (
const auto& element : *value.m_value.
object)
891 flatten(reference_string +
"/" +
detail::escape(element.first), element.second, result);
908 result[reference_string] = value;
925 unflatten(
const BasicJsonType& value)
927 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
929 JSON_THROW(detail::type_error::create(314,
"only objects can be unflattened", value));
932 BasicJsonType result;
935 for (
const auto& element : *value.m_value.
object)
937 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
939 JSON_THROW(detail::type_error::create(315,
"values in object must be primitive", element.second));
946 json_pointer(element.first).get_and_create(result) = element.second;
966 return lhs.reference_tokens == rhs.reference_tokens;
983 return !(lhs == rhs);
987 std::vector<std::string> reference_tokens;