38 NLOHMANN_BASIC_JSON_TPL_DECLARATION
39 friend class basic_json;
42 friend class json_pointer;
45 struct string_t_helper
50 NLOHMANN_BASIC_JSON_TPL_DECLARATION
51 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
53 using type = StringType;
58 using string_t =
typename string_t_helper<RefStringType>::type;
63 : reference_tokens(split(s))
70 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
72 [](
const string_t& a,
const string_t& b)
74 return detail::concat(a,
'/', detail::escape(b));
80 JSON_HEDLEY_DEPRECATED_FOR(3.11.0,
to_string())
81 operator string_t()
const
89 friend std::ostream&
operator<<(std::ostream& o,
const json_pointer& ptr)
100 reference_tokens.insert(reference_tokens.end(),
101 ptr.reference_tokens.begin(),
102 ptr.reference_tokens.end());
118 return *
this /= std::to_string(array_idx);
124 const json_pointer& rhs)
126 return json_pointer(lhs) /= rhs;
131 friend json_pointer
operator/(
const json_pointer& lhs, string_t token)
133 return json_pointer(lhs) /= std::move(token);
138 friend json_pointer
operator/(
const json_pointer& lhs, std::size_t array_idx)
140 return json_pointer(lhs) /= array_idx;
152 json_pointer res = *
this;
161 if (JSON_HEDLEY_UNLIKELY(
empty()))
163 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent",
nullptr));
166 reference_tokens.pop_back();
173 if (JSON_HEDLEY_UNLIKELY(
empty()))
175 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent",
nullptr));
178 return reference_tokens.back();
185 reference_tokens.push_back(token);
192 reference_tokens.push_back(std::move(token));
199 return reference_tokens.empty();
213 template<
typename BasicJsonType>
214 static typename BasicJsonType::size_type array_index(
const string_t& s)
216 using size_type =
typename BasicJsonType::size_type;
219 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] ==
'0'))
225 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >=
'1' && s[0] <=
'9')))
230 const char* p = s.c_str();
231 char* p_end =
nullptr;
233 const unsigned long long res = std::strtoull(p, &p_end, 10);
236 || JSON_HEDLEY_UNLIKELY(
static_cast<std::size_t
>(p_end - p) != s.size()))
238 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", s,
"'"),
nullptr));
243 if (res >=
static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
245 JSON_THROW(detail::out_of_range::create(410, detail::concat(
"array index ", s,
" exceeds size_type"),
nullptr));
248 return static_cast<size_type
>(res);
251 JSON_PRIVATE_UNLESS_TESTED:
252 json_pointer top()
const
254 if (JSON_HEDLEY_UNLIKELY(
empty()))
256 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent",
nullptr));
259 json_pointer result = *
this;
260 result.reference_tokens = {reference_tokens[0]};
273 template<
typename BasicJsonType>
274 BasicJsonType& get_and_create(BasicJsonType& j)
const
280 for (
const auto& reference_token : reference_tokens)
282 switch (result->type())
286 if (reference_token ==
"0")
289 result = &result->operator[](0);
294 result = &result->operator[](reference_token);
302 result = &result->operator[](reference_token);
309 result = &result->operator[](array_index<BasicJsonType>(reference_token));
327 JSON_THROW(detail::type_error::create(313,
"invalid value to unflatten", &j));
353 template<
typename BasicJsonType>
354 BasicJsonType& get_unchecked(BasicJsonType* ptr)
const
356 for (
const auto& reference_token : reference_tokens)
363 std::all_of(reference_token.begin(), reference_token.end(),
364 [](
const unsigned char x)
366 return std::isdigit(x);
370 *ptr = (nums || reference_token ==
"-")
380 ptr = &ptr->operator[](reference_token);
386 if (reference_token ==
"-")
389 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
394 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
408 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
421 template<
typename BasicJsonType>
422 BasicJsonType& get_checked(BasicJsonType* ptr)
const
424 for (
const auto& reference_token : reference_tokens)
431 ptr = &ptr->at(reference_token);
437 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
440 JSON_THROW(detail::out_of_range::create(402, detail::concat(
441 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
442 ") is out of range"), ptr));
446 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
459 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
479 template<
typename BasicJsonType>
480 const BasicJsonType& get_unchecked(
const BasicJsonType* ptr)
const
482 for (
const auto& reference_token : reference_tokens)
489 ptr = &ptr->operator[](reference_token);
495 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
498 JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
502 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
515 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
528 template<
typename BasicJsonType>
529 const BasicJsonType& get_checked(
const BasicJsonType* ptr)
const
531 for (
const auto& reference_token : reference_tokens)
538 ptr = &ptr->at(reference_token);
544 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
547 JSON_THROW(detail::out_of_range::create(402, detail::concat(
548 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
549 ") is out of range"), ptr));
553 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
566 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
577 template<
typename BasicJsonType>
578 bool contains(
const BasicJsonType* ptr)
const
580 for (
const auto& reference_token : reference_tokens)
586 if (!ptr->contains(reference_token))
592 ptr = &ptr->operator[](reference_token);
598 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
603 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !(
"0" <= reference_token && reference_token <=
"9")))
608 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
610 if (JSON_HEDLEY_UNLIKELY(!(
'1' <= reference_token[0] && reference_token[0] <=
'9')))
615 for (std::size_t i = 1; i < reference_token.size(); i++)
617 if (JSON_HEDLEY_UNLIKELY(!(
'0' <= reference_token[i] && reference_token[i] <=
'9')))
625 const auto idx = array_index<BasicJsonType>(reference_token);
626 if (idx >= ptr->size())
632 ptr = &ptr->operator[](idx);
666 static std::vector<string_t> split(
const string_t& reference_string)
668 std::vector<string_t> result;
671 if (reference_string.empty())
677 if (JSON_HEDLEY_UNLIKELY(reference_string[0] !=
'/'))
679 JSON_THROW(
detail::parse_error::create(107, 1, detail::concat(
"JSON pointer must be empty or begin with '/' - was: '", reference_string,
"'"),
nullptr));
687 std::size_t slash = reference_string.find_first_of(
'/', 1),
694 start = (slash == string_t::npos) ? 0 : slash + 1,
696 slash = reference_string.find_first_of(
'/', start))
700 auto reference_token = reference_string.substr(start, slash - start);
703 for (std::size_t pos = reference_token.find_first_of(
'~');
704 pos != string_t::npos;
705 pos = reference_token.find_first_of(
'~', pos + 1))
707 JSON_ASSERT(reference_token[pos] ==
'~');
710 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
711 (reference_token[pos + 1] !=
'0' &&
712 reference_token[pos + 1] !=
'1')))
720 result.push_back(reference_token);
734 template<
typename BasicJsonType>
735 static void flatten(
const string_t& reference_string,
736 const BasicJsonType& value,
737 BasicJsonType& result)
739 switch (value.type())
743 if (value.m_data.m_value.array->empty())
746 result[reference_string] =
nullptr;
751 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
753 flatten(detail::concat<string_t>(reference_string,
'/', std::to_string(i)),
754 value.m_data.m_value.array->operator[](i), result);
762 if (value.m_data.m_value.object->empty())
765 result[reference_string] =
nullptr;
770 for (
const auto& element : *value.m_data.m_value.object)
772 flatten(detail::concat<string_t>(reference_string,
'/',
detail::escape(element.first)), element.second, result);
789 result[reference_string] = value;
805 template<
typename BasicJsonType>
807 unflatten(
const BasicJsonType& value)
809 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
811 JSON_THROW(detail::type_error::create(314,
"only objects can be unflattened", &value));
814 BasicJsonType result;
817 for (
const auto& element : *value.m_data.m_value.object)
819 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
821 JSON_THROW(detail::type_error::create(315,
"values in object must be primitive", &element.second));
828 json_pointer(element.first).get_and_create(result) = element.second;
835 json_pointer<string_t> convert() const&
837 json_pointer<string_t> result;
838 result.reference_tokens = reference_tokens;
842 json_pointer<string_t> convert()&&
844 json_pointer<string_t> result;
845 result.reference_tokens = std::move(reference_tokens);
850#if JSON_HAS_THREE_WAY_COMPARISON
853 template<
typename RefStringTypeRhs>
854 bool operator==(
const json_pointer<RefStringTypeRhs>& rhs)
const noexcept
856 return reference_tokens == rhs.reference_tokens;
861 JSON_HEDLEY_DEPRECATED_FOR(3.11.2,
operator==(json_pointer))
864 return *
this == json_pointer(rhs);
868 template<
typename RefStringTypeRhs>
869 std::strong_ordering operator<=>(
const json_pointer<RefStringTypeRhs>& rhs)
const noexcept
871 return reference_tokens <=> rhs.reference_tokens;
876 template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
878 friend bool operator==(
const json_pointer<RefStringTypeLhs>& lhs,
879 const json_pointer<RefStringTypeRhs>& rhs)
noexcept;
883 template<
typename RefStringTypeLhs,
typename StringType>
885 friend bool operator==(
const json_pointer<RefStringTypeLhs>& lhs,
886 const StringType& rhs);
890 template<
typename RefStringTypeRhs,
typename StringType>
893 const json_pointer<RefStringTypeRhs>& rhs);
897 template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
899 friend bool operator!=(
const json_pointer<RefStringTypeLhs>& lhs,
900 const json_pointer<RefStringTypeRhs>& rhs)
noexcept;
904 template<
typename RefStringTypeLhs,
typename StringType>
906 friend bool operator!=(
const json_pointer<RefStringTypeLhs>& lhs,
907 const StringType& rhs);
911 template<
typename RefStringTypeRhs,
typename StringType>
914 const json_pointer<RefStringTypeRhs>& rhs);
917 template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
919 friend bool operator<(
const json_pointer<RefStringTypeLhs>& lhs,
920 const json_pointer<RefStringTypeRhs>& rhs)
noexcept;
925 std::vector<string_t> reference_tokens;