36 typedef typename ValueType::Ch Ch;
37#if RAPIDJSON_HAS_STDSTRING
38 typedef std::basic_string<Ch> String;
45 GenericUri(
const Ch* uri,
SizeType len,
Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(),
allocator_(allocator),
ownAllocator_() {
50 Parse(uri, internal::StrLen<Ch>(uri));
54 template<
typename T>
GenericUri(
const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(),
allocator_(allocator),
ownAllocator_() {
56 Parse(u, internal::StrLen<Ch>(u));
59#if RAPIDJSON_HAS_STDSTRING
60 GenericUri(
const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(),
allocator_(allocator),
ownAllocator_() {
61 Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
86 Allocate(rhs.GetStringLength());
87 auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength());
88 path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength());
89 query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength());
90 frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength());
91 base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength());
92 uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength());
93 CopyPart(uri_, rhs.uri_, rhs.GetStringLength());
101 uri.template Set<const Ch*>(this->GetString(), allocator);
104 const Ch* GetString()
const {
return uri_; }
105 SizeType GetStringLength()
const {
return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); }
106 const Ch* GetBaseString()
const {
return base_; }
107 SizeType GetBaseStringLength()
const {
return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); }
108 const Ch* GetSchemeString()
const {
return scheme_; }
109 SizeType GetSchemeStringLength()
const {
return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_); }
110 const Ch* GetAuthString()
const {
return auth_; }
111 SizeType GetAuthStringLength()
const {
return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); }
112 const Ch* GetPathString()
const {
return path_; }
113 SizeType GetPathStringLength()
const {
return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); }
114 const Ch* GetQueryString()
const {
return query_; }
115 SizeType GetQueryStringLength()
const {
return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); }
116 const Ch* GetFragString()
const {
return frag_; }
117 SizeType GetFragStringLength()
const {
return frag_ == 0 ? 0 : internal::StrLen<Ch>(frag_); }
119#if RAPIDJSON_HAS_STDSTRING
120 static String
Get(
const GenericUri& uri) {
return String(uri.GetString(), uri.GetStringLength()); }
121 static String GetBase(
const GenericUri& uri) {
return String(uri.GetBaseString(), uri.GetBaseStringLength()); }
122 static String GetScheme(
const GenericUri& uri) {
return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); }
123 static String GetAuth(
const GenericUri& uri) {
return String(uri.GetAuthString(), uri.GetAuthStringLength()); }
124 static String GetPath(
const GenericUri& uri) {
return String(uri.GetPathString(), uri.GetPathStringLength()); }
125 static String GetQuery(
const GenericUri& uri) {
return String(uri.GetQueryString(), uri.GetQueryStringLength()); }
126 static String GetFrag(
const GenericUri& uri) {
return String(uri.GetFragString(), uri.GetFragStringLength()); }
131 return Match(rhs,
true);
134 bool operator!=(
const GenericUri& rhs)
const {
135 return !Match(rhs,
true);
138 bool Match(
const GenericUri& uri,
bool full =
true)
const {
148 if (s1 == s2)
return true;
149 if (s1 == 0 || s2 == 0)
return false;
150 return internal::StrCmp<Ch>(s1, s2) == 0;
161 resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1);
163 if (!(GetSchemeStringLength() == 0)) {
165 resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength());
166 resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
167 resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
168 resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
169 resuri.RemoveDotSegments();
172 resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength());
173 if (!(GetAuthStringLength() == 0)) {
175 resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
176 resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
177 resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
178 resuri.RemoveDotSegments();
181 resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength());
182 if (GetPathStringLength() == 0) {
184 resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength());
185 if (GetQueryStringLength() == 0) {
187 resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength());
190 resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
193 if (path_[0] ==
'/') {
195 resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
196 resuri.RemoveDotSegments();
200 if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) {
201 resuri.path_[pos] =
'/';
204 size_t lastslashpos = baseuri.GetPathStringLength();
205 while (lastslashpos > 0) {
206 if (baseuri.path_[lastslashpos - 1] ==
'/')
break;
209 std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos *
sizeof(Ch));
211 resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength());
212 resuri.RemoveDotSegments();
215 resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
220 resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength());
224 resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1;
235 std::size_t Allocate(std::size_t len) {
243 size_t total = (3 * len + 7) *
sizeof(Ch);
244 scheme_ =
static_cast<Ch*
>(
allocator_->Malloc(total));
270 Allocator::Free(scheme_);
278 void Parse(
const Ch* uri, std::size_t len) {
279 std::size_t start = 0, pos1 = 0, pos2 = 0;
285 if (uri[pos1] ==
':')
break;
290 if (uri[pos2] ==
'/')
break;
291 if (uri[pos2] ==
'?')
break;
292 if (uri[pos2] ==
'#')
break;
297 std::memcpy(scheme_, &uri[start], pos1 *
sizeof(Ch));
298 scheme_[pos1] =
'\0';
305 auth_ = scheme_ + GetSchemeStringLength();
308 if (start < len - 1 && uri[start] ==
'/' && uri[start + 1] ==
'/') {
311 if (uri[pos2] ==
'/')
break;
312 if (uri[pos2] ==
'?')
break;
313 if (uri[pos2] ==
'#')
break;
316 std::memcpy(auth_, &uri[start], (pos2 - start) *
sizeof(Ch));
317 auth_[pos2 - start] =
'\0';
322 path_ = auth_ + GetAuthStringLength();
328 if (uri[pos2] ==
'?')
break;
329 if (uri[pos2] ==
'#')
break;
333 std::memcpy(path_, &uri[start], (pos2 - start) *
sizeof(Ch));
334 path_[pos2 - start] =
'\0';
342 query_ = path_ + GetPathStringLength();
345 if (start < len && uri[start] ==
'?') {
348 if (uri[pos2] ==
'#')
break;
352 std::memcpy(query_, &uri[start], (pos2 - start) *
sizeof(Ch));
353 query_[pos2 - start] =
'\0';
359 frag_ = query_ + GetQueryStringLength();
362 if (start < len && uri[start] ==
'#') {
363 std::memcpy(frag_, &uri[start], (len - start) *
sizeof(Ch));
364 frag_[
len - start] =
'\0';
368 base_ = frag_ + GetFragStringLength() + 1;
370 uri_ = base_ + GetBaseStringLength() + 1;
377 std::memcpy(next, scheme_, GetSchemeStringLength() *
sizeof(Ch));
378 next+= GetSchemeStringLength();
379 std::memcpy(next, auth_, GetAuthStringLength() *
sizeof(Ch));
380 next+= GetAuthStringLength();
381 std::memcpy(next, path_, GetPathStringLength() *
sizeof(Ch));
382 next+= GetPathStringLength();
383 std::memcpy(next, query_, GetQueryStringLength() *
sizeof(Ch));
384 next+= GetQueryStringLength();
391 std::memcpy(next, base_, GetBaseStringLength() *
sizeof(Ch));
392 next+= GetBaseStringLength();
393 std::memcpy(next, frag_, GetFragStringLength() *
sizeof(Ch));
394 next+= GetFragStringLength();
400 Ch* CopyPart(Ch* to, Ch* from, std::size_t len) {
403 std::memcpy(to, from, len *
sizeof(Ch));
405 Ch* next = to +
len + 1;
412 void RemoveDotSegments() {
413 std::size_t pathlen = GetPathStringLength();
414 std::size_t pathpos = 0;
415 std::size_t newpos = 0;
418 while (pathpos < pathlen) {
421 while ((pathpos + slashpos) < pathlen) {
422 if (path_[pathpos + slashpos] ==
'/')
break;
426 if (slashpos == 2 && path_[pathpos] ==
'.' && path_[pathpos + 1] ==
'.') {
430 size_t lastslashpos = newpos;
432 if (lastslashpos > 1) {
435 while (lastslashpos > 0) {
436 if (path_[lastslashpos - 1] ==
'/')
break;
440 newpos = lastslashpos;
442 }
else if (slashpos == 1 && path_[pathpos] ==
'.') {
447 std::memmove(&path_[newpos], &path_[pathpos], slashpos *
sizeof(Ch));
450 if ((pathpos + slashpos) < pathlen) {
456 pathpos += slashpos + 1;
458 path_[newpos] =
'\0';