! @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' */
| 14383 | @throw parse_error.108 if character '~' is not followed by '0' or '1' |
| 14384 | */ |
| 14385 | static std::vector<string_t> split(const string_t& reference_string) |
| 14386 | { |
| 14387 | std::vector<string_t> result; |
| 14388 | |
| 14389 | // special case: empty reference string -> no reference tokens |
| 14390 | if (reference_string.empty()) |
| 14391 | { |
| 14392 | return result; |
| 14393 | } |
| 14394 | |
| 14395 | // check if nonempty reference string begins with slash |
| 14396 | if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) |
| 14397 | { |
| 14398 | JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); |
| 14399 | } |
| 14400 | |
| 14401 | // extract the reference tokens: |
| 14402 | // - slash: position of the last read slash (or end of string) |
| 14403 | // - start: position after the previous slash |
| 14404 | for ( |
| 14405 | // search for the first slash after the first character |
| 14406 | std::size_t slash = reference_string.find_first_of('/', 1), |
| 14407 | // set the beginning of the first reference token |
| 14408 | start = 1; |
| 14409 | // we can stop if start == 0 (if slash == string_t::npos) |
| 14410 | start != 0; |
| 14411 | // set the beginning of the next reference token |
| 14412 | // (will eventually be 0 if slash == string_t::npos) |
| 14413 | start = (slash == string_t::npos) ? 0 : slash + 1, |
| 14414 | // find next slash |
| 14415 | slash = reference_string.find_first_of('/', start)) |
| 14416 | { |
| 14417 | // use the text between the beginning of the reference token |
| 14418 | // (start) and the last slash (slash). |
| 14419 | auto reference_token = reference_string.substr(start, slash - start); |
| 14420 | |
| 14421 | // check reference tokens are properly escaped |
| 14422 | for (std::size_t pos = reference_token.find_first_of('~'); |
| 14423 | pos != string_t::npos; |
| 14424 | pos = reference_token.find_first_of('~', pos + 1)) |
| 14425 | { |
| 14426 | JSON_ASSERT(reference_token[pos] == '~'); |
| 14427 | |
| 14428 | // ~ must be followed by 0 or 1 |
| 14429 | if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || |
| 14430 | (reference_token[pos + 1] != '0' && |
| 14431 | reference_token[pos + 1] != '1'))) |
| 14432 | { |
| 14433 | JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); |
| 14434 | } |
| 14435 | } |
| 14436 | |
| 14437 | // finally, store the reference token |
| 14438 | detail::unescape(reference_token); |
| 14439 | result.push_back(reference_token); |
| 14440 | } |
| 14441 | |
| 14442 | return result; |