15 #ifndef RAPIDJSON_URI_H_
16 #define RAPIDJSON_URI_H_
20 #if defined(__clang__)
22 RAPIDJSON_DIAG_OFF(c++98-compat)
23 #elif defined(_MSC_VER)
24 RAPIDJSON_DIAG_OFF(4512)
32 template <
typename ValueType,
typename Allocator=CrtAllocator>
35 typedef typename ValueType::Ch
Ch;
36 #if RAPIDJSON_HAS_STDSTRING
37 typedef std::basic_string<Ch>
String;
44 GenericUri(
const Ch* uri,
SizeType len,
Allocator*
allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(
allocator), ownAllocator_() {
49 Parse(uri, internal::StrLen<Ch>(uri));
54 const Ch* u = uri.template Get<const Ch*>();
55 Parse(u, internal::StrLen<Ch>(u));
58 #if RAPIDJSON_HAS_STDSTRING
60 Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
65 GenericUri(
const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() {
100 uri.template Set<const Ch*>(this->
GetString(), allocator);
118 #if RAPIDJSON_HAS_STDSTRING
130 return Match(rhs,
true);
134 return !
Match(rhs,
true);
147 if (s1 == s2)
return true;
148 if (s1 == 0 || s2 == 0)
return false;
149 return internal::StrCmp<Ch>(s1, s2) == 0;
168 resuri.RemoveDotSegments();
177 resuri.RemoveDotSegments();
192 if (path_[0] ==
'/') {
195 resuri.RemoveDotSegments();
200 resuri.path_[pos] =
'/';
204 while (lastslashpos > 0) {
205 if (baseuri.path_[lastslashpos - 1] ==
'/')
break;
208 std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos *
sizeof(
Ch));
211 resuri.RemoveDotSegments();
234 std::size_t Allocate(std::size_t len) {
242 size_t total = (3 * len + 7) *
sizeof(
Ch);
243 scheme_ =
static_cast<Ch*
>(allocator_->Malloc(total));
277 void Parse(
const Ch* uri, std::size_t len) {
278 std::size_t start = 0, pos1 = 0, pos2 = 0;
284 if (uri[pos1] ==
':')
break;
289 if (uri[pos2] ==
'/')
break;
290 if (uri[pos2] ==
'?')
break;
291 if (uri[pos2] ==
'#')
break;
296 std::memcpy(scheme_, &uri[start], pos1 *
sizeof(
Ch));
297 scheme_[pos1] =
'\0';
307 if (start < len - 1 && uri[start] ==
'/' && uri[start + 1] ==
'/') {
310 if (uri[pos2] ==
'/')
break;
311 if (uri[pos2] ==
'?')
break;
312 if (uri[pos2] ==
'#')
break;
315 std::memcpy(auth_, &uri[start], (pos2 - start) *
sizeof(
Ch));
316 auth_[pos2 - start] =
'\0';
327 if (uri[pos2] ==
'?')
break;
328 if (uri[pos2] ==
'#')
break;
332 std::memcpy(path_, &uri[start], (pos2 - start) *
sizeof(
Ch));
333 path_[pos2 - start] =
'\0';
344 if (start < len && uri[start] ==
'?') {
347 if (uri[pos2] ==
'#')
break;
351 std::memcpy(query_, &uri[start], (pos2 - start) *
sizeof(
Ch));
352 query_[pos2 - start] =
'\0';
361 if (start < len && uri[start] ==
'#') {
362 std::memcpy(frag_, &uri[start], (len - start) *
sizeof(
Ch));
363 frag_[len - start] =
'\0';
399 Ch* CopyPart(
Ch* to,
Ch*
from, std::size_t len) {
402 std::memcpy(to,
from, len *
sizeof(
Ch));
404 Ch* next = to + len + 1;
411 void RemoveDotSegments() {
413 std::size_t pathpos = 0;
414 std::size_t newpos = 0;
417 while (pathpos < pathlen) {
420 while ((pathpos + slashpos) < pathlen) {
421 if (path_[pathpos + slashpos] ==
'/')
break;
425 if (slashpos == 2 && path_[pathpos] ==
'.' && path_[pathpos + 1] ==
'.') {
429 size_t lastslashpos = newpos;
431 if (lastslashpos > 1) {
434 while (lastslashpos > 0) {
435 if (path_[lastslashpos - 1] ==
'/')
break;
439 newpos = lastslashpos;
441 }
else if (slashpos == 1 && path_[pathpos] ==
'.') {
446 std::memmove(&path_[newpos], &path_[pathpos], slashpos *
sizeof(
Ch));
449 if ((pathpos + slashpos) < pathlen) {
455 pathpos += slashpos + 1;
457 path_[newpos] =
'\0';
477 #if defined(__clang__)
481 #endif // RAPIDJSON_URI_H_