! @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' */
| 10848 | @throw parse_error.108 if character '~' is not followed by '0' or '1' |
| 10849 | */ |
| 10850 | static std::vector<std::string> split(const std::string& reference_string) |
| 10851 | { |
| 10852 | std::vector<std::string> result; |
| 10853 | |
| 10854 | // special case: empty reference string -> no reference tokens |
| 10855 | if (reference_string.empty()) |
| 10856 | { |
| 10857 | return result; |
| 10858 | } |
| 10859 | |
| 10860 | // check if nonempty reference string begins with slash |
| 10861 | if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) |
| 10862 | { |
| 10863 | JSON_THROW(detail::parse_error::create(107, 1, |
| 10864 | "JSON pointer must be empty or begin with '/' - was: '" + |
| 10865 | reference_string + "'")); |
| 10866 | } |
| 10867 | |
| 10868 | // extract the reference tokens: |
| 10869 | // - slash: position of the last read slash (or end of string) |
| 10870 | // - start: position after the previous slash |
| 10871 | for ( |
| 10872 | // search for the first slash after the first character |
| 10873 | std::size_t slash = reference_string.find_first_of('/', 1), |
| 10874 | // set the beginning of the first reference token |
| 10875 | start = 1; |
| 10876 | // we can stop if start == 0 (if slash == std::string::npos) |
| 10877 | start != 0; |
| 10878 | // set the beginning of the next reference token |
| 10879 | // (will eventually be 0 if slash == std::string::npos) |
| 10880 | start = (slash == std::string::npos) ? 0 : slash + 1, |
| 10881 | // find next slash |
| 10882 | slash = reference_string.find_first_of('/', start)) |
| 10883 | { |
| 10884 | // use the text between the beginning of the reference token |
| 10885 | // (start) and the last slash (slash). |
| 10886 | auto reference_token = reference_string.substr(start, slash - start); |
| 10887 | |
| 10888 | // check reference tokens are properly escaped |
| 10889 | for (std::size_t pos = reference_token.find_first_of('~'); |
| 10890 | pos != std::string::npos; |
| 10891 | pos = reference_token.find_first_of('~', pos + 1)) |
| 10892 | { |
| 10893 | assert(reference_token[pos] == '~'); |
| 10894 | |
| 10895 | // ~ must be followed by 0 or 1 |
| 10896 | if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or |
| 10897 | (reference_token[pos + 1] != '0' and |
| 10898 | reference_token[pos + 1] != '1'))) |
| 10899 | { |
| 10900 | JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); |
| 10901 | } |
| 10902 | } |
| 10903 | |
| 10904 | // finally, store the reference token |
| 10905 | unescape(reference_token); |
| 10906 | result.push_back(reference_token); |
| 10907 | } |