| /* |
| * Modern C++ JSON schema validator |
| * |
| * Licensed under the MIT License <http://opensource.org/licenses/MIT>. |
| * |
| * Copyright (c) 2016 Patrick Boettcher <patrick.boettcher@posteo.de>. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom |
| * the Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT |
| * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR |
| * THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| #include "json-schema.hpp" |
| |
| namespace nlohmann |
| { |
| |
| void json_pointer::from_string(const std::string &r) |
| { |
| str_ = "#"; |
| |
| if (r.size() == 0) |
| return; |
| |
| if (r[0] != '#') |
| throw std::invalid_argument("not a valid JSON pointer - missing # at the beginning"); |
| |
| if (r.size() == 1) |
| return; |
| |
| std::size_t pos = 1; |
| |
| do { |
| std::size_t next = r.find('/', pos + 1); |
| str_.append(r.substr(pos, next - pos)); |
| pos = next; |
| } while (pos != std::string::npos); |
| } |
| |
| void json_uri::from_string(const std::string &uri) |
| { |
| // if it is an urn take it as it is - maybe there is more to be done |
| if (uri.find("urn:") == 0) { |
| urn_ = uri; |
| return; |
| } |
| |
| std::string pointer = "#"; // default pointer is the root |
| |
| // first split the URI into URL and JSON-pointer |
| auto pointer_separator = uri.find('#'); |
| if (pointer_separator != std::string::npos) // and extract the JSON-pointer-string if found |
| pointer = uri.substr(pointer_separator); |
| |
| // the rest is an URL |
| std::string url = uri.substr(0, pointer_separator); |
| if (url.size()) { // if an URL is part of the URI |
| |
| std::size_t pos = 0; |
| auto proto = url.find("://", pos); |
| if (proto != std::string::npos) { // extract the protocol |
| proto_ = url.substr(pos, proto - pos); |
| pos = 3 + proto; // 3 == "://" |
| |
| auto hostname = url.find("/", pos); |
| if (hostname != std::string::npos) { // and the hostname (no proto without hostname) |
| hostname_ = url.substr(pos, hostname - pos); |
| pos = hostname; |
| } |
| } |
| |
| // the rest is the path |
| auto path = url.substr(pos); |
| if (path[0] == '/') // if it starts with a / it is root-path |
| path_ = path; |
| else { // otherwise it is a subfolder |
| // HACK(syoyo): Force append '/' for glTF json schemas |
| path_ = path; |
| //path_.append(path); |
| } |
| |
| pointer_ = json_pointer(""); |
| } |
| |
| if (pointer.size() > 0) |
| pointer_ = pointer; |
| } |
| |
| const std::string json_uri::url() const |
| { |
| std::stringstream s; |
| |
| if (proto_.size() > 0) |
| s << proto_ << "://"; |
| |
| s << hostname_ |
| << path_; |
| |
| return s.str(); |
| } |
| |
| std::string json_uri::to_string() const |
| { |
| std::stringstream s; |
| |
| s << urn_ |
| << url() |
| << pointer_.to_string(); |
| |
| return s.str(); |
| } |
| |
| std::ostream &operator<<(std::ostream &os, const json_uri &u) |
| { |
| return os << u.to_string(); |
| } |
| |
| std::string json_uri::unescape(const std::string &src) |
| { |
| std::string l = src; |
| std::size_t pos = src.size() - 1; |
| |
| do { |
| pos = l.rfind('~', pos); |
| |
| if (pos == std::string::npos) |
| break; |
| |
| if (pos < l.size() - 1) { |
| switch (l[pos + 1]) { |
| case '0': |
| l.replace(pos, 2, "~"); |
| break; |
| |
| case '1': |
| l.replace(pos, 2, "/"); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| if (pos == 0) |
| break; |
| pos--; |
| } while (pos != std::string::npos); |
| |
| // TODO - percent handling |
| |
| return l; |
| } |
| |
| std::string json_uri::escape(const std::string &src) |
| { |
| std::vector<std::pair<std::string, std::string>> chars = { |
| {"~", "~0"}, |
| {"/", "~1"}, |
| {"%", "%25"}}; |
| |
| std::string l = src; |
| |
| for (const auto &c : chars) { |
| std::size_t pos = 0; |
| do { |
| pos = l.find(c.first, pos); |
| if (pos == std::string::npos) |
| break; |
| l.replace(pos, 1, c.second); |
| pos += c.second.size(); |
| } while (1); |
| } |
| |
| return l; |
| } |
| |
| } // nlohmann |