16 #ifndef INCLUDE_NN_NLIB_URI_H_ 17 #define INCLUDE_NN_NLIB_URI_H_ 23 #include "nn/nlib/Swap.h" 29 class MemoryOutputStream;
31 template<
size_t N = 1024>
36 const char*
c_str() const NLIB_NOEXCEPT {
40 operator const char*()
const NLIB_NOEXCEPT {
return c_str(); }
41 std::pair<const char*, const char*>
GetData() const NLIB_NOEXCEPT {
42 return std::make_pair(&buf_[0], cur_);
68 static bool IsEmailAddress(
const nlib_utf8_t* first,
78 static bool IsUriReference(
const nlib_utf8_t* first,
93 static errno_t DecodeUriComponent(
size_t* written,
char* buf,
size_t n,
const char* first,
97 const char* s) NLIB_NOEXCEPT {
98 return DecodeUriComponent(written, buf, N, s);
101 const char* s) NLIB_NOEXCEPT {
102 return DecodeUriComponent(written, buf, n, s, s +
nlib_strlen(s));
106 const char* last) NLIB_NOEXCEPT {
107 return DecodeUriComponent(written, buf, N, first, last);
109 static std::pair<errno_t, size_t>
110 DecodeUriComponent(
char* buf,
size_t n,
const char* first,
const char* last) NLIB_NOEXCEPT {
112 errno_t e = DecodeUriComponent(&written, buf, n, first, last);
113 return std::make_pair(e, written);
116 static std::pair<errno_t, size_t>
117 DecodeUriComponent(
char (&buf)[N],
const char* first,
const char* last) NLIB_NOEXCEPT {
118 return DecodeUriComponent(buf, N, first, last);
120 static std::pair<errno_t, size_t>
121 DecodeUriComponent(
char* buf,
size_t n,
const char* s) NLIB_NOEXCEPT {
122 return DecodeUriComponent(buf, n, s, s +
nlib_strlen(s));
125 static std::pair<errno_t, size_t>
126 DecodeUriComponent(
char(&buf)[N],
const char* s) NLIB_NOEXCEPT {
127 return DecodeUriComponent(buf, N, s, s +
nlib_strlen(s));
130 static errno_t EncodeUriComponent(
size_t* written,
char* buf,
size_t n,
const char* first,
134 const char* last,
bool fragment_mode) NLIB_NOEXCEPT {
135 return EncodeUriComponent(written, buf, N, first, last, fragment_mode);
138 bool fragment_mode) NLIB_NOEXCEPT {
139 return EncodeUriComponent(written, buf, n, s, s +
nlib_strlen(s), fragment_mode);
143 bool fragment_mode) NLIB_NOEXCEPT {
144 return EncodeUriComponent(written, buf, N, s, fragment_mode);
146 static std::pair<errno_t, size_t>
147 EncodeUriComponent(
char* buf,
size_t n,
const char* first,
148 const char* last,
bool fragment_mode) NLIB_NOEXCEPT {
150 errno_t e = EncodeUriComponent(&written, buf, n, first, last, fragment_mode);
151 return std::make_pair(e, written);
154 static std::pair<errno_t, size_t>
155 EncodeUriComponent(
char (&buf)[N],
const char* first,
const char* last,
156 bool fragment_mode) NLIB_NOEXCEPT {
157 return EncodeUriComponent(buf, N, first, last, fragment_mode);
159 static std::pair<errno_t, size_t>
160 EncodeUriComponent(
char* buf,
size_t n,
const char* s,
bool fragment_mode) {
161 return EncodeUriComponent(buf, n, s, s +
nlib_strlen(s), fragment_mode);
164 static std::pair<errno_t, size_t>
165 EncodeUriComponent(
char(&buf)[N],
const char* s,
bool fragment_mode) {
166 return EncodeUriComponent(buf, N, s, s +
nlib_strlen(s), fragment_mode);
172 return DecodePath(written, buf, N, s);
174 static std::pair<errno_t, size_t>
175 DecodePath(
char* buf,
size_t n,
const char* s) NLIB_NOEXCEPT {
177 errno_t e = DecodePath(&written, buf, n, s);
178 return std::make_pair(e, written);
181 static std::pair<errno_t, size_t>
182 DecodePath(
char (&buf)[N],
const char* s) NLIB_NOEXCEPT {
return DecodePath(buf, N, s); }
187 return EncodePath(written, buf, N, s);
189 static std::pair<errno_t, size_t>
190 EncodePath(
char* buf,
size_t n,
const char* s) NLIB_NOEXCEPT {
192 errno_t e = EncodePath(&written, buf, n, s);
193 return std::make_pair(e, written);
196 static std::pair<errno_t, size_t>
197 EncodePath(
char (&buf)[N],
const char* s) NLIB_NOEXCEPT {
return EncodePath(buf, N, s); }
201 ~
Uri() NLIB_NOEXCEPT { Reset(); }
202 NLIB_DEFMOVE_PIMPL(
Uri);
205 swap(prv_, rhs.prv_);
207 bool Parse(
const char* first,
const char* last)
NLIB_NOEXCEPT;
218 bool SetUri(
const char* scheme,
const char* userinfo,
const char* host,
219 const char* port,
const char* path,
const char* query,
221 bool IsAbsolute() const NLIB_NOEXCEPT {
return GetScheme() !=
nullptr; }
222 bool ComposeString(
char* buf,
size_t size)
const NLIB_NOEXCEPT;
225 return this->ComposeString(buf, N);
248 bool SetScheme(
const char* first,
const char* last)
NLIB_NOEXCEPT;
249 bool SetUserInfo(
const char* first,
const char* last)
NLIB_NOEXCEPT;
250 bool SetHost(
const char* first,
const char* last)
NLIB_NOEXCEPT;
251 bool SetPort(
const char* first,
const char* last)
NLIB_NOEXCEPT;
252 bool SetPath(
const char* first,
const char* last)
NLIB_NOEXCEPT;
253 bool SetQuery(
const char* first,
const char* last)
NLIB_NOEXCEPT;
254 bool SetFragment(
const char* first,
const char* last)
NLIB_NOEXCEPT;
256 return scheme ? SetScheme(scheme, scheme +
nlib_strlen(scheme))
257 : SetScheme(
nullptr,
nullptr);
260 return userinfo ? SetUserInfo(userinfo, userinfo +
nlib_strlen(userinfo))
261 : SetUserInfo(
nullptr,
nullptr);
263 bool SetHost(
const char* host) NLIB_NOEXCEPT {
264 return host ? SetHost(host, host +
nlib_strlen(host)) : SetHost(
nullptr,
nullptr);
266 bool SetPort(
const char* port) NLIB_NOEXCEPT {
267 return port ? SetPort(port, port +
nlib_strlen(port)) : SetPort(
nullptr,
nullptr);
273 return SetPort(&buf[0], &buf[0] + cnt);
275 bool SetPath(
const char* path) NLIB_NOEXCEPT {
276 return path ? SetPath(path, path +
nlib_strlen(path)) : SetPath(
nullptr,
nullptr);
279 return query ? SetQuery(query, query +
nlib_strlen(query)) : SetQuery(
nullptr,
nullptr);
282 return fragment ? SetFragment(fragment, fragment +
nlib_strlen(fragment))
283 : SetFragment(
nullptr,
nullptr);
287 std::pair<const char*, const char*> x = encoder.GetData();
288 return SetQueryByQueryEncoder_(x.first, x.second);
303 Error GetError() const NLIB_NOEXCEPT;
307 bool SetQueryByQueryEncoder_(const
char* first, const
char* last) NLIB_NOEXCEPT;
310 friend
bool operator==(const Uri& lhs, const Uri& rhs) NLIB_NOEXCEPT;
311 friend
bool operator<(const Uri& lhs, const Uri& rhs) NLIB_NOEXCEPT;
314 bool operator==(const Uri& lhs, const Uri& rhs) NLIB_NOEXCEPT;
315 NLIB_EQUAL_OPERATOR(Uri)
316 bool operator<(const Uri& lhs, const Uri& rhs) NLIB_NOEXCEPT;
317 NLIB_COMPARE_OPERATOR(Uri)
324 if (p == &buf_[N - 1])
return ERANGE;
330 e = Uri::EncodeUriComponent(&written, p, &buf_[N] - p, key,
false);
331 if (e != 0)
return e;
334 if (p == &buf_[N - 1])
return ERANGE;
337 e = Uri::EncodeUriComponent(&written, p, &buf_[N] - p, value,
false);
338 if (e != 0)
return e;
345 template<
size_t K = 64,
size_t V = 192>
349 : ptr_beg_(
nullptr), ptr_end_(
nullptr), ptr_key_(
nullptr), ptr_eq_(
nullptr),
350 ptr_and_(
nullptr), buf_key_valid_(false), buf_value_valid_(false) {
352 buf_value_[0] =
'\0';
360 std::pair<errno_t, const char*> GetFirstValueByName(
const char* key)
NLIB_NOEXCEPT;
364 static std::pair<errno_t, const char*> Error(
errno_t e) NLIB_NOEXCEPT {
365 return std::make_pair(e, static_cast<const char*>(
nullptr));
367 errno_t GetKeyWithCompare_(
const char* key) NLIB_NOEXCEPT {
368 std::pair<errno_t, const char*> x = GetKey();
369 if (x.first != 0)
return x.first;
370 if (strcmp(key, x.second) == 0)
return 0;
375 const char* ptr_beg_;
376 const char* ptr_end_;
377 const char* ptr_key_;
379 const char* ptr_and_;
381 bool buf_value_valid_;
386 template<
size_t K,
size_t V>
388 if (!uri)
return EINVAL;
389 const char* p = uri.GetQuery();
391 ptr_beg_ = ptr_key_ = p;
394 ptr_beg_ = ptr_end_ = &buf_key_[0];
396 ptr_eq_ = ptr_and_ =
nullptr;
397 buf_key_valid_ = buf_value_valid_ =
false;
401 template<
size_t K,
size_t V>
403 ptr_beg_ = ptr_end_ = ptr_key_ = ptr_eq_ = ptr_and_ =
nullptr;
404 buf_key_valid_ = buf_value_valid_ =
false;
407 template<
size_t K,
size_t V>
409 if (ptr_key_ == ptr_end_)
return false;
411 ptr_eq_ = ptr_and_ =
nullptr;
412 buf_key_valid_ = buf_value_valid_ =
false;
415 }
while (ptr_key_ != ptr_end_ && *ptr_key_ ==
'&');
416 return ptr_key_ != ptr_end_;
419 template<
size_t K,
size_t V>
421 if (!HasNext())
return ENOENT;
423 ptr_key_ = (ptr_and_ != ptr_end_) ? ptr_and_ + 1 : ptr_end_;
425 const void* p =
nlib_memchr(ptr_key_,
'&', std::distance(ptr_key_, ptr_end_));
426 ptr_key_ = (p !=
nullptr) ? static_cast<const char*>(p) + 1 : ptr_end_;
428 ptr_eq_ = ptr_and_ =
nullptr;
429 buf_key_valid_ = buf_value_valid_ =
false;
433 template<
size_t K,
size_t V>
434 std::pair<errno_t, const char*>
436 if (buf_key_valid_)
return std::make_pair(0, &buf_key_[0]);
437 if (!ptr_key_)
return Error(EBADF);
438 if (!HasNext())
return Error(ENOENT);
439 if (!ptr_eq_) SpotKeyValue();
441 errno_t e = Uri::DecodeUriComponent(&w, buf_key_, K, ptr_key_, ptr_eq_);
442 if (e != 0)
return Error(e);
443 buf_key_valid_ =
true;
444 return std::make_pair(0, &buf_key_[0]);
447 template<
size_t K,
size_t V>
448 std::pair<errno_t, const char*>
450 if (buf_value_valid_)
return std::make_pair(0, &buf_value_[0]);
451 if (!ptr_key_)
return Error(EBADF);
452 if (!HasNext())
return Error(ENOENT);
453 if (!ptr_eq_) SpotKeyValue();
454 if (ptr_eq_ != ptr_and_) {
456 errno_t e = Uri::DecodeUriComponent(&w, buf_value_, V, ptr_eq_ + 1, ptr_and_);
457 if (e != 0)
return Error(e);
459 buf_value_[0] =
'\0';
461 buf_value_valid_ =
true;
462 return std::make_pair(0, &buf_value_[0]);
465 template<
size_t K,
size_t V>
466 std::pair<errno_t, const char*>
470 e = GetKeyWithCompare_(key);
471 if (e == 0)
return std::make_pair(0, &buf_key_[0]);
472 if (e != ESRCH)
return Error(e);
473 }
while (MoveNext() == 0);
477 template<
size_t K,
size_t V>
480 ptr_eq_ = ptr_and_ =
nullptr;
481 buf_key_valid_ = buf_value_valid_ =
false;
484 template<
size_t K,
size_t V>
486 const void* p_and =
nlib_memchr(ptr_key_,
'&', std::distance(ptr_key_, ptr_end_));
487 ptr_and_ = p_and ?
static_cast<const char*
>(p_and) : ptr_end_;
488 const void* p_eq =
nlib_memchr(ptr_key_,
'=', std::distance(ptr_key_, ptr_and_));
489 ptr_eq_ = p_eq ?
static_cast<const char*
>(p_eq) : ptr_and_;
493 #ifndef __cpp_rvalue_references 496 #endif // INCLUDE_NN_NLIB_URI_H_ static errno_t DecodeUriComponent(size_t *written, char *buf, size_t n, const char *s) noexcept
Decodes a percent-encoded string.
bool SetQuery(const char *query) noexcept
Sets the query string, excluding the "?" character at its beginning.
bool SetPath(const char *path) noexcept
Sets the path.
static errno_t EncodeUriComponent(size_t *written, char *buf, size_t n, const char *s, bool fragment_mode) noexcept
Percent-encodes a string.
static errno_t DecodePath(size_t *written, char(&buf)[N], const char *s) noexcept
Calls DecodePath(written, buf, N, s) .
static errno_t DecodeUriComponent(size_t *written, char(&buf)[N], const char *s) noexcept
Calls DecodeUriComponent(written, buf, N, s).
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
#define NLIB_SAFE_BOOL(class_name, exp)
Defines a safe operator bool function in the class. Uses the C++11 explicit bool if it is available f...
static bool IsIpv4(const nlib_utf8_t *str) noexcept
Returns IsIpv4(str, str + strlen(str)).
bool SetFragment(const char *fragment) noexcept
Sets the fragment string, excluding the "#" character at its beginning.
#define NLIB_CEXPR14
constexpr is defined if C++14 constexpr is available for use. If not, holds an empty string...
static errno_t EncodePath(size_t *written, char(&buf)[N], const char *s) noexcept
Calls EncodePath(written, buf, N, s).
constexpr Uri() noexcept
Instantiates the object with default parameters (default constructor). Initializes an object...
static errno_t DecodeUriComponent(size_t *written, char(&buf)[N], const char *first, const char *last) noexcept
Calls DecodeUriComponent(written, buf, N, first, last).
constexpr UriQueryDecoder() noexcept
Instantiates the object with default parameters (default constructor).
The object has not been initialized.
Defines the class that resembles std::vector but can store objects that cannot be copied...
bool IsAbsolute() const noexcept
Returns true if the URI is an absolute URI. This function determines the string is an absolute URI if...
bool SetPortNumber(int port) noexcept
Sets the port number.
An absolute URI needs to be specified.
Failed to allocate memory.
bool SetHost(const char *host) noexcept
Sets the hostname.
static errno_t EncodeUriComponent(size_t *written, char(&buf)[N], const char *first, const char *last, bool fragment_mode) noexcept
Calls EncodeUriComponent(written, buf, N, first, last, fragment_mode).
static bool IsEmailAddress(const nlib_utf8_t *str) noexcept
Returns IsEmailAddress(str, str + strlen(str)).
const char * c_str() const noexcept
Returns the encoded query string.
static errno_t EncodeUriComponent(size_t *written, char(&buf)[N], const char *s, bool fragment_mode) noexcept
Calls EncodeUriComponent(written, buf, N, s, fragment_mode).
bool ComposeString(char(&buf)[N]) const noexcept
Writes a URI string.
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
A file that contains the configuration information for each development environment.
Failed to normalize the (absolute) path.
bool SetPort(const char *port) noexcept
Sets the port number as a string, excluding the colon.
static bool IsUriReference(const nlib_utf8_t *str) noexcept
Returns IsUriReference(str, str + strlen(str)).
The class for parsing and constructing regular URIs.
static bool IsHostName(const nlib_utf8_t *str) noexcept
Returns IsHostName(str, str + strlen(str)).
static bool IsIpv6(const nlib_utf8_t *str) noexcept
Returns IsIpv6(str, str + strlen(str)).
bool Parse(const char *str) noexcept
Returns Parse(str, str + strlen(str)).
bool SetScheme(const char *scheme) noexcept
Sets the scheme as a string, excluding the colon at its end.
The class template to parse URI queries.
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
bool SetQuery(const UriQueryEncoder< N > &encoder) noexcept
Sets the query string, excluding the "?" character at its beginning.
UriQueryEncoder() noexcept
Instantiates the object with default parameters (default constructor).
std::pair< const char *, const char * > GetData() const noexcept
Returns the beginning and end of the encoded query string.
The class for creating URI queries.
static bool IsUri(const nlib_utf8_t *str) noexcept
Returns IsUri(str, str + strlen(str)).
bool SetUserInfo(const char *userinfo) noexcept
Sets user-specific information, including the user name and password, associated with the specified U...
Error
An error value, as an enumerator, that can be obtained with GetError().