MQTTSuite
Loading...
Searching...
No Matches
json-uri.cpp
Go to the documentation of this file.
1/*
2 * JSON schema validator for JSON for modern C++
3 *
4 * Copyright (c) 2016-2019 Patrick Boettcher <p@yai.se>.
5 *
6 * SPDX-License-Identifier: MIT
7 *
8 */
9#include <nlohmann/json-schema.hpp>
10
11#include <sstream>
12
13namespace nlohmann
14{
15
16void json_uri::update(const std::string &uri)
17{
18 std::string pointer = ""; // default pointer is document-root
19
20 // first split the URI into location and pointer
21 auto pointer_separator = uri.find('#');
22 if (pointer_separator != std::string::npos) { // and extract the pointer-string if found
23 pointer = uri.substr(pointer_separator + 1); // remove #
24
25 // unescape %-values IOW, decode JSON-URI-formatted JSON-pointer
26 std::size_t pos = pointer.size() - 1;
27 do {
28 pos = pointer.rfind('%', pos);
29 if (pos == std::string::npos)
30 break;
31
32 if (pos >= pointer.size() - 2) {
33 pos--;
34 continue;
35 }
36
37 std::string hex = pointer.substr(pos + 1, 2);
38 char ascii = static_cast<char>(std::strtoul(hex.c_str(), nullptr, 16));
39 pointer.replace(pos, 3, 1, ascii);
40
41 pos--;
42 } while (1);
43 }
44
45 auto location = uri.substr(0, pointer_separator);
46
47 if (location.size()) { // a location part has been found
48
49 // if it is an URN take it as it is
50 if (location.find("urn:") == 0) {
51 urn_ = location;
52
53 // and clear URL members
54 scheme_ = "";
55 authority_ = "";
56 path_ = "";
57
58 } else { // it is an URL
59
60 // split URL in protocol, hostname and path
61 std::size_t pos = 0;
62 auto proto = location.find("://", pos);
63 if (proto != std::string::npos) { // extract the protocol
64
65 urn_ = ""; // clear URN-member if URL is parsed
66
67 scheme_ = location.substr(pos, proto - pos);
68 pos = 3 + proto; // 3 == "://"
69
70 auto authority = location.find("/", pos);
71 if (authority != std::string::npos) { // and the hostname (no proto without hostname)
72 authority_ = location.substr(pos, authority - pos);
73 pos = authority;
74 }
75 }
76
77 auto path = location.substr(pos);
78
79 // URNs cannot of have paths
80 if (urn_.size() && path.size())
81 throw std::invalid_argument("Cannot add a path (" + path + ") to an URN URI (" + urn_ + ")");
82
83 if (path[0] == '/') // if it starts with a / it is root-path
84 path_ = path;
85 else if (pos == 0) { // the URL contained only a path and the current path has no / at the end, strip last element until / and append
86 auto last_slash = path_.rfind('/');
87 path_ = path_.substr(0, last_slash) + '/' + path;
88 } else // otherwise it is a subfolder
89 path_.append(path);
90 }
91 }
92
93 pointer_ = ""_json_pointer;
94 identifier_ = "";
95
96 if (pointer[0] == '/')
97 pointer_ = json::json_pointer(pointer);
98 else
99 identifier_ = pointer;
100}
101
102std::string json_uri::location() const
103{
104 if (urn_.size())
105 return urn_;
106
107 std::stringstream s;
108
109 if (scheme_.size() > 0)
110 s << scheme_ << "://";
111
112 s << authority_
113 << path_;
114
115 return s.str();
116}
117
118std::string json_uri::to_string() const
119{
120 std::stringstream s;
121
122 s << location() << " # ";
123
124 if (identifier_ == "")
125 s << pointer_.to_string();
126 else
127 s << identifier_;
128
129 return s.str();
130}
131
132std::ostream &operator<<(std::ostream &os, const json_uri &u)
133{
134 return os << u.to_string();
135}
136
137std::string json_uri::escape(const std::string &src)
138{
139 std::vector<std::pair<std::string, std::string>> chars = {
140 {"~", "~0"},
141 {"/", "~1"}};
142
143 std::string l = src;
144
145 for (const auto &c : chars) {
146 std::size_t pos = 0;
147 do {
148 pos = l.find(c.first, pos);
149 if (pos == std::string::npos)
150 break;
151 l.replace(pos, 1, c.second);
152 pos += c.second.size();
153 } while (1);
154 }
155
156 return l;
157}
158
159} // namespace nlohmann
std::string authority_
std::string to_string() const
Definition json-uri.cpp:118
std::string scheme_
std::string location() const
Definition json-uri.cpp:102
void update(const std::string &uri)
Definition json-uri.cpp:16
static std::string escape(const std::string &)
Definition json-uri.cpp:137
std::string identifier_
json::json_pointer pointer_