| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988 | 
							- //     __ _____ _____ _____
 
- //  __|  |   __|     |   | |  JSON for Modern C++
 
- // |  |  |__   |  |  | | | |  version 3.12.0
 
- // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 
- //
 
- // SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 
- // SPDX-License-Identifier: MIT
 
- #pragma once
 
- #include <algorithm> // all_of
 
- #include <cctype> // isdigit
 
- #include <cerrno> // errno, ERANGE
 
- #include <cstdlib> // strtoull
 
- #ifndef JSON_NO_IO
 
-     #include <iosfwd> // ostream
 
- #endif  // JSON_NO_IO
 
- #include <limits> // max
 
- #include <numeric> // accumulate
 
- #include <string> // string
 
- #include <utility> // move
 
- #include <vector> // vector
 
- #include <nlohmann/detail/exceptions.hpp>
 
- #include <nlohmann/detail/macro_scope.hpp>
 
- #include <nlohmann/detail/string_concat.hpp>
 
- #include <nlohmann/detail/string_escape.hpp>
 
- #include <nlohmann/detail/value_t.hpp>
 
- NLOHMANN_JSON_NAMESPACE_BEGIN
 
- /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
 
- /// @sa https://json.nlohmann.me/api/json_pointer/
 
- template<typename RefStringType>
 
- class json_pointer
 
- {
 
-     // allow basic_json to access private members
 
-     NLOHMANN_BASIC_JSON_TPL_DECLARATION
 
-     friend class basic_json;
 
-     template<typename>
 
-     friend class json_pointer;
 
-     template<typename T>
 
-     struct string_t_helper
 
-     {
 
-         using type = T;
 
-     };
 
-     NLOHMANN_BASIC_JSON_TPL_DECLARATION
 
-     struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
 
-     {
 
-         using type = StringType;
 
-     };
 
-   public:
 
-     // for backwards compatibility accept BasicJsonType
 
-     using string_t = typename string_t_helper<RefStringType>::type;
 
-     /// @brief create JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
 
-     explicit json_pointer(const string_t& s = "")
 
-         : reference_tokens(split(s))
 
-     {}
 
-     /// @brief return a string representation of the JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
 
-     string_t to_string() const
 
-     {
 
-         return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
 
-                                string_t{},
 
-                                [](const string_t& a, const string_t& b)
 
-         {
 
-             return detail::concat(a, '/', detail::escape(b));
 
-         });
 
-     }
 
-     /// @brief return a string representation of the JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
 
-     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
 
-     operator string_t() const
 
-     {
 
-         return to_string();
 
-     }
 
- #ifndef JSON_NO_IO
 
-     /// @brief write string representation of the JSON pointer to stream
 
-     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
 
-     friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
 
-     {
 
-         o << ptr.to_string();
 
-         return o;
 
-     }
 
- #endif
 
-     /// @brief append another JSON pointer at the end of this JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
 
-     json_pointer& operator/=(const json_pointer& ptr)
 
-     {
 
-         reference_tokens.insert(reference_tokens.end(),
 
-                                 ptr.reference_tokens.begin(),
 
-                                 ptr.reference_tokens.end());
 
-         return *this;
 
-     }
 
-     /// @brief append an unescaped reference token at the end of this JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
 
-     json_pointer& operator/=(string_t token)
 
-     {
 
-         push_back(std::move(token));
 
-         return *this;
 
-     }
 
-     /// @brief append an array index at the end of this JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
 
-     json_pointer& operator/=(std::size_t array_idx)
 
-     {
 
-         return *this /= std::to_string(array_idx);
 
-     }
 
-     /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
 
-     friend json_pointer operator/(const json_pointer& lhs,
 
-                                   const json_pointer& rhs)
 
-     {
 
-         return json_pointer(lhs) /= rhs;
 
-     }
 
-     /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
 
-     friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
 
-     {
 
-         return json_pointer(lhs) /= std::move(token);
 
-     }
 
-     /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
 
-     friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
 
-     {
 
-         return json_pointer(lhs) /= array_idx;
 
-     }
 
-     /// @brief returns the parent of this JSON pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
 
-     json_pointer parent_pointer() const
 
-     {
 
-         if (empty())
 
-         {
 
-             return *this;
 
-         }
 
-         json_pointer res = *this;
 
-         res.pop_back();
 
-         return res;
 
-     }
 
-     /// @brief remove last reference token
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
 
-     void pop_back()
 
-     {
 
-         if (JSON_HEDLEY_UNLIKELY(empty()))
 
-         {
 
-             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
 
-         }
 
-         reference_tokens.pop_back();
 
-     }
 
-     /// @brief return last reference token
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/back/
 
-     const string_t& back() const
 
-     {
 
-         if (JSON_HEDLEY_UNLIKELY(empty()))
 
-         {
 
-             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
 
-         }
 
-         return reference_tokens.back();
 
-     }
 
-     /// @brief append an unescaped token at the end of the reference pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
 
-     void push_back(const string_t& token)
 
-     {
 
-         reference_tokens.push_back(token);
 
-     }
 
-     /// @brief append an unescaped token at the end of the reference pointer
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
 
-     void push_back(string_t&& token)
 
-     {
 
-         reference_tokens.push_back(std::move(token));
 
-     }
 
-     /// @brief return whether pointer points to the root document
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/empty/
 
-     bool empty() const noexcept
 
-     {
 
-         return reference_tokens.empty();
 
-     }
 
-   private:
 
-     /*!
 
-     @param[in] s  reference token to be converted into an array index
 
-     @return integer representation of @a s
 
-     @throw parse_error.106  if an array index begins with '0'
 
-     @throw parse_error.109  if an array index begins not with a digit
 
-     @throw out_of_range.404 if string @a s could not be converted to an integer
 
-     @throw out_of_range.410 if an array index exceeds size_type
 
-     */
 
-     template<typename BasicJsonType>
 
-     static typename BasicJsonType::size_type array_index(const string_t& s)
 
-     {
 
-         using size_type = typename BasicJsonType::size_type;
 
-         // error condition (cf. RFC 6901, Sect. 4)
 
-         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
 
-         {
 
-             JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
 
-         }
 
-         // error condition (cf. RFC 6901, Sect. 4)
 
-         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
 
-         {
 
-             JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
 
-         }
 
-         const char* p = s.c_str();
 
-         char* p_end = nullptr; // NOLINT(misc-const-correctness)
 
-         errno = 0; // strtoull doesn't reset errno
 
-         const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
 
-         if (p == p_end // invalid input or empty string
 
-                 || errno == ERANGE // out of range
 
-                 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
 
-         {
 
-             JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
 
-         }
 
-         // only triggered on special platforms (like 32bit), see also
 
-         // https://github.com/nlohmann/json/pull/2203
 
-         if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
 
-         {
 
-             JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
 
-         }
 
-         return static_cast<size_type>(res);
 
-     }
 
-   JSON_PRIVATE_UNLESS_TESTED:
 
-     json_pointer top() const
 
-     {
 
-         if (JSON_HEDLEY_UNLIKELY(empty()))
 
-         {
 
-             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
 
-         }
 
-         json_pointer result = *this;
 
-         result.reference_tokens = {reference_tokens[0]};
 
-         return result;
 
-     }
 
-   private:
 
-     /*!
 
-     @brief create and return a reference to the pointed to value
 
-     @complexity Linear in the number of reference tokens.
 
-     @throw parse_error.109 if array index is not a number
 
-     @throw type_error.313 if value cannot be unflattened
 
-     */
 
-     template<typename BasicJsonType>
 
-     BasicJsonType& get_and_create(BasicJsonType& j) const
 
-     {
 
-         auto* result = &j;
 
-         // in case no reference tokens exist, return a reference to the JSON value
 
-         // j which will be overwritten by a primitive value
 
-         for (const auto& reference_token : reference_tokens)
 
-         {
 
-             switch (result->type())
 
-             {
 
-                 case detail::value_t::null:
 
-                 {
 
-                     if (reference_token == "0")
 
-                     {
 
-                         // start a new array if reference token is 0
 
-                         result = &result->operator[](0);
 
-                     }
 
-                     else
 
-                     {
 
-                         // start a new object otherwise
 
-                         result = &result->operator[](reference_token);
 
-                     }
 
-                     break;
 
-                 }
 
-                 case detail::value_t::object:
 
-                 {
 
-                     // create an entry in the object
 
-                     result = &result->operator[](reference_token);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::array:
 
-                 {
 
-                     // create an entry in the array
 
-                     result = &result->operator[](array_index<BasicJsonType>(reference_token));
 
-                     break;
 
-                 }
 
-                 /*
 
-                 The following code is only reached if there exists a reference
 
-                 token _and_ the current value is primitive. In this case, we have
 
-                 an error situation, because primitive values may only occur as
 
-                 single value; that is, with an empty list of reference tokens.
 
-                 */
 
-                 case detail::value_t::string:
 
-                 case detail::value_t::boolean:
 
-                 case detail::value_t::number_integer:
 
-                 case detail::value_t::number_unsigned:
 
-                 case detail::value_t::number_float:
 
-                 case detail::value_t::binary:
 
-                 case detail::value_t::discarded:
 
-                 default:
 
-                     JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
 
-             }
 
-         }
 
-         return *result;
 
-     }
 
-     /*!
 
-     @brief return a reference to the pointed to value
 
-     @note This version does not throw if a value is not present, but tries to
 
-           create nested values instead. For instance, calling this function
 
-           with pointer `"/this/that"` on a null value is equivalent to calling
 
-           `operator[]("this").operator[]("that")` on that value, effectively
 
-           changing the null value to an object.
 
-     @param[in] ptr  a JSON value
 
-     @return reference to the JSON value pointed to by the JSON pointer
 
-     @complexity Linear in the length of the JSON pointer.
 
-     @throw parse_error.106   if an array index begins with '0'
 
-     @throw parse_error.109   if an array index was not a number
 
-     @throw out_of_range.404  if the JSON pointer can not be resolved
 
-     */
 
-     template<typename BasicJsonType>
 
-     BasicJsonType& get_unchecked(BasicJsonType* ptr) const
 
-     {
 
-         for (const auto& reference_token : reference_tokens)
 
-         {
 
-             // convert null values to arrays or objects before continuing
 
-             if (ptr->is_null())
 
-             {
 
-                 // check if reference token is a number
 
-                 const bool nums =
 
-                     std::all_of(reference_token.begin(), reference_token.end(),
 
-                                 [](const unsigned char x)
 
-                 {
 
-                     return std::isdigit(x);
 
-                 });
 
-                 // change value to array for numbers or "-" or to object otherwise
 
-                 *ptr = (nums || reference_token == "-")
 
-                        ? detail::value_t::array
 
-                        : detail::value_t::object;
 
-             }
 
-             switch (ptr->type())
 
-             {
 
-                 case detail::value_t::object:
 
-                 {
 
-                     // use unchecked object access
 
-                     ptr = &ptr->operator[](reference_token);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::array:
 
-                 {
 
-                     if (reference_token == "-")
 
-                     {
 
-                         // explicitly treat "-" as index beyond the end
 
-                         ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
 
-                     }
 
-                     else
 
-                     {
 
-                         // convert array index to number; unchecked access
 
-                         ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
 
-                     }
 
-                     break;
 
-                 }
 
-                 case detail::value_t::null:
 
-                 case detail::value_t::string:
 
-                 case detail::value_t::boolean:
 
-                 case detail::value_t::number_integer:
 
-                 case detail::value_t::number_unsigned:
 
-                 case detail::value_t::number_float:
 
-                 case detail::value_t::binary:
 
-                 case detail::value_t::discarded:
 
-                 default:
 
-                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
 
-             }
 
-         }
 
-         return *ptr;
 
-     }
 
-     /*!
 
-     @throw parse_error.106   if an array index begins with '0'
 
-     @throw parse_error.109   if an array index was not a number
 
-     @throw out_of_range.402  if the array index '-' is used
 
-     @throw out_of_range.404  if the JSON pointer can not be resolved
 
-     */
 
-     template<typename BasicJsonType>
 
-     BasicJsonType& get_checked(BasicJsonType* ptr) const
 
-     {
 
-         for (const auto& reference_token : reference_tokens)
 
-         {
 
-             switch (ptr->type())
 
-             {
 
-                 case detail::value_t::object:
 
-                 {
 
-                     // note: at performs range check
 
-                     ptr = &ptr->at(reference_token);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::array:
 
-                 {
 
-                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
 
-                     {
 
-                         // "-" always fails the range check
 
-                         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));
 
-                     }
 
-                     // note: at performs range check
 
-                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
 
-                     break;
 
-                 }
 
-                 case detail::value_t::null:
 
-                 case detail::value_t::string:
 
-                 case detail::value_t::boolean:
 
-                 case detail::value_t::number_integer:
 
-                 case detail::value_t::number_unsigned:
 
-                 case detail::value_t::number_float:
 
-                 case detail::value_t::binary:
 
-                 case detail::value_t::discarded:
 
-                 default:
 
-                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
 
-             }
 
-         }
 
-         return *ptr;
 
-     }
 
-     /*!
 
-     @brief return a const reference to the pointed to value
 
-     @param[in] ptr  a JSON value
 
-     @return const reference to the JSON value pointed to by the JSON
 
-     pointer
 
-     @throw parse_error.106   if an array index begins with '0'
 
-     @throw parse_error.109   if an array index was not a number
 
-     @throw out_of_range.402  if the array index '-' is used
 
-     @throw out_of_range.404  if the JSON pointer can not be resolved
 
-     */
 
-     template<typename BasicJsonType>
 
-     const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
 
-     {
 
-         for (const auto& reference_token : reference_tokens)
 
-         {
 
-             switch (ptr->type())
 
-             {
 
-                 case detail::value_t::object:
 
-                 {
 
-                     // use unchecked object access
 
-                     ptr = &ptr->operator[](reference_token);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::array:
 
-                 {
 
-                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
 
-                     {
 
-                         // "-" cannot be used for const access
 
-                         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));
 
-                     }
 
-                     // use unchecked array access
 
-                     ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
 
-                     break;
 
-                 }
 
-                 case detail::value_t::null:
 
-                 case detail::value_t::string:
 
-                 case detail::value_t::boolean:
 
-                 case detail::value_t::number_integer:
 
-                 case detail::value_t::number_unsigned:
 
-                 case detail::value_t::number_float:
 
-                 case detail::value_t::binary:
 
-                 case detail::value_t::discarded:
 
-                 default:
 
-                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
 
-             }
 
-         }
 
-         return *ptr;
 
-     }
 
-     /*!
 
-     @throw parse_error.106   if an array index begins with '0'
 
-     @throw parse_error.109   if an array index was not a number
 
-     @throw out_of_range.402  if the array index '-' is used
 
-     @throw out_of_range.404  if the JSON pointer can not be resolved
 
-     */
 
-     template<typename BasicJsonType>
 
-     const BasicJsonType& get_checked(const BasicJsonType* ptr) const
 
-     {
 
-         for (const auto& reference_token : reference_tokens)
 
-         {
 
-             switch (ptr->type())
 
-             {
 
-                 case detail::value_t::object:
 
-                 {
 
-                     // note: at performs range check
 
-                     ptr = &ptr->at(reference_token);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::array:
 
-                 {
 
-                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
 
-                     {
 
-                         // "-" always fails the range check
 
-                         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));
 
-                     }
 
-                     // note: at performs range check
 
-                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
 
-                     break;
 
-                 }
 
-                 case detail::value_t::null:
 
-                 case detail::value_t::string:
 
-                 case detail::value_t::boolean:
 
-                 case detail::value_t::number_integer:
 
-                 case detail::value_t::number_unsigned:
 
-                 case detail::value_t::number_float:
 
-                 case detail::value_t::binary:
 
-                 case detail::value_t::discarded:
 
-                 default:
 
-                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
 
-             }
 
-         }
 
-         return *ptr;
 
-     }
 
-     /*!
 
-     @throw parse_error.106   if an array index begins with '0'
 
-     @throw parse_error.109   if an array index was not a number
 
-     */
 
-     template<typename BasicJsonType>
 
-     bool contains(const BasicJsonType* ptr) const
 
-     {
 
-         for (const auto& reference_token : reference_tokens)
 
-         {
 
-             switch (ptr->type())
 
-             {
 
-                 case detail::value_t::object:
 
-                 {
 
-                     if (!ptr->contains(reference_token))
 
-                     {
 
-                         // we did not find the key in the object
 
-                         return false;
 
-                     }
 
-                     ptr = &ptr->operator[](reference_token);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::array:
 
-                 {
 
-                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
 
-                     {
 
-                         // "-" always fails the range check
 
-                         return false;
 
-                     }
 
-                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
 
-                     {
 
-                         // invalid char
 
-                         return false;
 
-                     }
 
-                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
 
-                     {
 
-                         if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
 
-                         {
 
-                             // first char should be between '1' and '9'
 
-                             return false;
 
-                         }
 
-                         for (std::size_t i = 1; i < reference_token.size(); i++)
 
-                         {
 
-                             if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
 
-                             {
 
-                                 // other char should be between '0' and '9'
 
-                                 return false;
 
-                             }
 
-                         }
 
-                     }
 
-                     const auto idx = array_index<BasicJsonType>(reference_token);
 
-                     if (idx >= ptr->size())
 
-                     {
 
-                         // index out of range
 
-                         return false;
 
-                     }
 
-                     ptr = &ptr->operator[](idx);
 
-                     break;
 
-                 }
 
-                 case detail::value_t::null:
 
-                 case detail::value_t::string:
 
-                 case detail::value_t::boolean:
 
-                 case detail::value_t::number_integer:
 
-                 case detail::value_t::number_unsigned:
 
-                 case detail::value_t::number_float:
 
-                 case detail::value_t::binary:
 
-                 case detail::value_t::discarded:
 
-                 default:
 
-                 {
 
-                     // we do not expect primitive values if there is still a
 
-                     // reference token to process
 
-                     return false;
 
-                 }
 
-             }
 
-         }
 
-         // no reference token left means we found a primitive value
 
-         return true;
 
-     }
 
-     /*!
 
-     @brief split the string input to reference tokens
 
-     @note This function is only called by the json_pointer constructor.
 
-           All exceptions below are documented there.
 
-     @throw parse_error.107  if the pointer is not empty or begins with '/'
 
-     @throw parse_error.108  if character '~' is not followed by '0' or '1'
 
-     */
 
-     static std::vector<string_t> split(const string_t& reference_string)
 
-     {
 
-         std::vector<string_t> result;
 
-         // special case: empty reference string -> no reference tokens
 
-         if (reference_string.empty())
 
-         {
 
-             return result;
 
-         }
 
-         // check if nonempty reference string begins with slash
 
-         if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
 
-         {
 
-             JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
 
-         }
 
-         // extract the reference tokens:
 
-         // - slash: position of the last read slash (or end of string)
 
-         // - start: position after the previous slash
 
-         for (
 
-             // search for the first slash after the first character
 
-             std::size_t slash = reference_string.find_first_of('/', 1),
 
-             // set the beginning of the first reference token
 
-             start = 1;
 
-             // we can stop if start == 0 (if slash == string_t::npos)
 
-             start != 0;
 
-             // set the beginning of the next reference token
 
-             // (will eventually be 0 if slash == string_t::npos)
 
-             start = (slash == string_t::npos) ? 0 : slash + 1,
 
-             // find next slash
 
-             slash = reference_string.find_first_of('/', start))
 
-         {
 
-             // use the text between the beginning of the reference token
 
-             // (start) and the last slash (slash).
 
-             auto reference_token = reference_string.substr(start, slash - start);
 
-             // check reference tokens are properly escaped
 
-             for (std::size_t pos = reference_token.find_first_of('~');
 
-                     pos != string_t::npos;
 
-                     pos = reference_token.find_first_of('~', pos + 1))
 
-             {
 
-                 JSON_ASSERT(reference_token[pos] == '~');
 
-                 // ~ must be followed by 0 or 1
 
-                 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
 
-                                          (reference_token[pos + 1] != '0' &&
 
-                                           reference_token[pos + 1] != '1')))
 
-                 {
 
-                     JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
 
-                 }
 
-             }
 
-             // finally, store the reference token
 
-             detail::unescape(reference_token);
 
-             result.push_back(reference_token);
 
-         }
 
-         return result;
 
-     }
 
-   private:
 
-     /*!
 
-     @param[in] reference_string  the reference string to the current value
 
-     @param[in] value             the value to consider
 
-     @param[in,out] result        the result object to insert values to
 
-     @note Empty objects or arrays are flattened to `null`.
 
-     */
 
-     template<typename BasicJsonType>
 
-     static void flatten(const string_t& reference_string,
 
-                         const BasicJsonType& value,
 
-                         BasicJsonType& result)
 
-     {
 
-         switch (value.type())
 
-         {
 
-             case detail::value_t::array:
 
-             {
 
-                 if (value.m_data.m_value.array->empty())
 
-                 {
 
-                     // flatten empty array as null
 
-                     result[reference_string] = nullptr;
 
-                 }
 
-                 else
 
-                 {
 
-                     // iterate array and use index as reference string
 
-                     for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
 
-                     {
 
-                         flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
 
-                                 value.m_data.m_value.array->operator[](i), result);
 
-                     }
 
-                 }
 
-                 break;
 
-             }
 
-             case detail::value_t::object:
 
-             {
 
-                 if (value.m_data.m_value.object->empty())
 
-                 {
 
-                     // flatten empty object as null
 
-                     result[reference_string] = nullptr;
 
-                 }
 
-                 else
 
-                 {
 
-                     // iterate object and use keys as reference string
 
-                     for (const auto& element : *value.m_data.m_value.object)
 
-                     {
 
-                         flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
 
-                     }
 
-                 }
 
-                 break;
 
-             }
 
-             case detail::value_t::null:
 
-             case detail::value_t::string:
 
-             case detail::value_t::boolean:
 
-             case detail::value_t::number_integer:
 
-             case detail::value_t::number_unsigned:
 
-             case detail::value_t::number_float:
 
-             case detail::value_t::binary:
 
-             case detail::value_t::discarded:
 
-             default:
 
-             {
 
-                 // add primitive value with its reference string
 
-                 result[reference_string] = value;
 
-                 break;
 
-             }
 
-         }
 
-     }
 
-     /*!
 
-     @param[in] value  flattened JSON
 
-     @return unflattened JSON
 
-     @throw parse_error.109 if array index is not a number
 
-     @throw type_error.314  if value is not an object
 
-     @throw type_error.315  if object values are not primitive
 
-     @throw type_error.313  if value cannot be unflattened
 
-     */
 
-     template<typename BasicJsonType>
 
-     static BasicJsonType
 
-     unflatten(const BasicJsonType& value)
 
-     {
 
-         if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
 
-         {
 
-             JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
 
-         }
 
-         BasicJsonType result;
 
-         // iterate the JSON object values
 
-         for (const auto& element : *value.m_data.m_value.object)
 
-         {
 
-             if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
 
-             {
 
-                 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
 
-             }
 
-             // assign value to reference pointed to by JSON pointer; Note that if
 
-             // the JSON pointer is "" (i.e., points to the whole value), function
 
-             // get_and_create returns a reference to result itself. An assignment
 
-             // will then create a primitive value.
 
-             json_pointer(element.first).get_and_create(result) = element.second;
 
-         }
 
-         return result;
 
-     }
 
-     // can't use conversion operator because of ambiguity
 
-     json_pointer<string_t> convert() const&
 
-     {
 
-         json_pointer<string_t> result;
 
-         result.reference_tokens = reference_tokens;
 
-         return result;
 
-     }
 
-     json_pointer<string_t> convert()&&
 
-     {
 
-         json_pointer<string_t> result;
 
-         result.reference_tokens = std::move(reference_tokens);
 
-         return result;
 
-     }
 
-   public:
 
- #if JSON_HAS_THREE_WAY_COMPARISON
 
-     /// @brief compares two JSON pointers for equality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
 
-     template<typename RefStringTypeRhs>
 
-     bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
 
-     {
 
-         return reference_tokens == rhs.reference_tokens;
 
-     }
 
-     /// @brief compares JSON pointer and string for equality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
 
-     JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
 
-     bool operator==(const string_t& rhs) const
 
-     {
 
-         return *this == json_pointer(rhs);
 
-     }
 
-     /// @brief 3-way compares two JSON pointers
 
-     template<typename RefStringTypeRhs>
 
-     std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
 
-     {
 
-         return  reference_tokens <=> rhs.reference_tokens; // *NOPAD*
 
-     }
 
- #else
 
-     /// @brief compares two JSON pointers for equality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
 
-     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
 
-                            const json_pointer<RefStringTypeRhs>& rhs) noexcept;
 
-     /// @brief compares JSON pointer and string for equality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
 
-     template<typename RefStringTypeLhs, typename StringType>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
 
-                            const StringType& rhs);
 
-     /// @brief compares string and JSON pointer for equality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
 
-     template<typename RefStringTypeRhs, typename StringType>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator==(const StringType& lhs,
 
-                            const json_pointer<RefStringTypeRhs>& rhs);
 
-     /// @brief compares two JSON pointers for inequality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
 
-     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
 
-                            const json_pointer<RefStringTypeRhs>& rhs) noexcept;
 
-     /// @brief compares JSON pointer and string for inequality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
 
-     template<typename RefStringTypeLhs, typename StringType>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
 
-                            const StringType& rhs);
 
-     /// @brief compares string and JSON pointer for inequality
 
-     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
 
-     template<typename RefStringTypeRhs, typename StringType>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator!=(const StringType& lhs,
 
-                            const json_pointer<RefStringTypeRhs>& rhs);
 
-     /// @brief compares two JSON pointer for less-than
 
-     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
 
-     // NOLINTNEXTLINE(readability-redundant-declaration)
 
-     friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
 
-                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
 
- #endif
 
-   private:
 
-     /// the reference tokens
 
-     std::vector<string_t> reference_tokens;
 
- };
 
- #if !JSON_HAS_THREE_WAY_COMPARISON
 
- // functions cannot be defined inside class due to ODR violations
 
- template<typename RefStringTypeLhs, typename RefStringTypeRhs>
 
- inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
 
-                        const json_pointer<RefStringTypeRhs>& rhs) noexcept
 
- {
 
-     return lhs.reference_tokens == rhs.reference_tokens;
 
- }
 
- template<typename RefStringTypeLhs,
 
-          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
 
- JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
 
- inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
 
-                        const StringType& rhs)
 
- {
 
-     return lhs == json_pointer<RefStringTypeLhs>(rhs);
 
- }
 
- template<typename RefStringTypeRhs,
 
-          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
 
- JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
 
- inline bool operator==(const StringType& lhs,
 
-                        const json_pointer<RefStringTypeRhs>& rhs)
 
- {
 
-     return json_pointer<RefStringTypeRhs>(lhs) == rhs;
 
- }
 
- template<typename RefStringTypeLhs, typename RefStringTypeRhs>
 
- inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
 
-                        const json_pointer<RefStringTypeRhs>& rhs) noexcept
 
- {
 
-     return !(lhs == rhs);
 
- }
 
- template<typename RefStringTypeLhs,
 
-          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
 
- JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
 
- inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
 
-                        const StringType& rhs)
 
- {
 
-     return !(lhs == rhs);
 
- }
 
- template<typename RefStringTypeRhs,
 
-          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
 
- JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
 
- inline bool operator!=(const StringType& lhs,
 
-                        const json_pointer<RefStringTypeRhs>& rhs)
 
- {
 
-     return !(lhs == rhs);
 
- }
 
- template<typename RefStringTypeLhs, typename RefStringTypeRhs>
 
- inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
 
-                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
 
- {
 
-     return lhs.reference_tokens < rhs.reference_tokens;
 
- }
 
- #endif
 
- NLOHMANN_JSON_NAMESPACE_END
 
 
  |