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
%エンコードされた文字列をデコードします。
bool SetQuery(const char *query) noexcept
クエリ文字列(先頭の?は含まない)を設定します。
bool SetPath(const char *path) noexcept
パスを設定します。
static errno_t EncodeUriComponent(size_t *written, char *buf, size_t n, const char *s, bool fragment_mode) noexcept
文字列を%エンコードします。
static errno_t DecodePath(size_t *written, char(&buf)[N], const char *s) noexcept
DecodePath(written, buf, N, s)を呼び出します。
static errno_t DecodeUriComponent(size_t *written, char(&buf)[N], const char *s) noexcept
DecodeUriComponent(written, buf, N, s)を呼び出します。
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
static bool IsIpv4(const nlib_utf8_t *str) noexcept
IsIpv4(str, str + strlen(str))を返します。
bool SetFragment(const char *fragment) noexcept
フラグメント文字列(先頭の::は含まない)を設定します。
#define NLIB_CEXPR14
C++14のconstexprが利用可能であればconstexprが定義されます。そうでない場合は空文字列です。 ...
static errno_t EncodePath(size_t *written, char(&buf)[N], const char *s) noexcept
EncodePath(written, buf, N, s)を呼び出します。
constexpr Uri() noexcept
デフォルトコンストラクタです。オブジェクトを初期化します。
static errno_t DecodeUriComponent(size_t *written, char(&buf)[N], const char *first, const char *last) noexcept
DecodeUriComponent(written, buf, N, first, last)を呼び出します。
constexpr UriQueryDecoder() noexcept
デフォルトコンストラクタです。
std::vectorに似ていますが、コピーできないオブジェクトを格納可能なクラスが定義されています。 ...
bool IsAbsolute() const noexcept
URIが絶対URIであればtrueを返します。この関数ではschemeが指定されていれば絶対URIであると判断しています...
bool SetPortNumber(int port) noexcept
ポート番号を設定します。
bool SetHost(const char *host) noexcept
ホスト名を設定します。
static errno_t EncodeUriComponent(size_t *written, char(&buf)[N], const char *first, const char *last, bool fragment_mode) noexcept
EncodeUriComponent(written, buf, N, first, last, fragment_mode)を呼び出します。
static bool IsEmailAddress(const nlib_utf8_t *str) noexcept
IsEmailAddress(str, str + strlen(str))を返します。
const char * c_str() const noexcept
エンコードされたクエリ文字列を返します。
static errno_t EncodeUriComponent(size_t *written, char(&buf)[N], const char *s, bool fragment_mode) noexcept
EncodeUriComponent(written, buf, N, s, fragment_mode)を呼び出します。
bool ComposeString(char(&buf)[N]) const noexcept
URI文字列を書き出します。
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
bool SetPort(const char *port) noexcept
ポート番号の文字列(:は含まない)を設定します。
static bool IsUriReference(const nlib_utf8_t *str) noexcept
IsUriReference(str, str + strlen(str))を返します。
一般的なURIをパースしたり構築したりするためのクラスです。
static bool IsHostName(const nlib_utf8_t *str) noexcept
IsHostName(str, str + strlen(str))を返します。
static bool IsIpv6(const nlib_utf8_t *str) noexcept
IsIpv6(str, str + strlen(str))を返します。
bool Parse(const char *str) noexcept
Parse(str, str + strlen(str))を返します。
bool SetScheme(const char *scheme) noexcept
スキームの文字列(末尾の:は含まない)を設定します。
URIのクエリをパースするためのクラステンプレートです。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
bool SetQuery(const UriQueryEncoder< N > &encoder) noexcept
クエリ文字列(先頭の?は含まない)を設定します。
UriQueryEncoder() noexcept
デフォルトコンストラクタです。
std::pair< const char *, const char * > GetData() const noexcept
エンコードされたクエリ文字列の先頭と末尾を返します。
static bool IsUri(const nlib_utf8_t *str) noexcept
IsUri(str, str + strlen(str))を返します。
bool SetUserInfo(const char *userinfo) noexcept
指定した URI に関連付けられているユーザー名、パスワードなどのユーザー固有の情報を設定します。 ...
Error
GetError()で取得することのできるエラー値の列挙型です。