Line data Source code
1 : //
2 : // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/url
8 : //
9 :
10 :
11 : #include <boost/url/detail/config.hpp>
12 : #include "path.hpp"
13 : #include <boost/url/detail/url_impl.hpp>
14 : #include <boost/url/authority_view.hpp>
15 : #include <boost/assert.hpp>
16 : #include <cstring>
17 :
18 : namespace boost {
19 : namespace urls {
20 : namespace detail {
21 :
22 : #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
23 : #pragma GCC diagnostic push
24 : #pragma GCC diagnostic ignored "-Warray-bounds"
25 : #endif
26 :
27 : //------------------------------------------------
28 : //
29 : // url_impl
30 : //
31 : //------------------------------------------------
32 :
33 : void
34 2287 : url_impl::
35 : apply_scheme(
36 : core::string_view s) noexcept
37 : {
38 2287 : scheme_ = string_to_scheme(s);
39 2287 : set_size(id_scheme, s.size() + 1);
40 2287 : }
41 :
42 : void
43 381 : url_impl::
44 : apply_userinfo(
45 : pct_string_view const& user,
46 : pct_string_view const* pass) noexcept
47 : {
48 : // this function is for
49 : // authority_view_rule only
50 381 : BOOST_ASSERT(from_ == from::authority);
51 :
52 : // userinfo
53 381 : set_size(id_user, user.size());
54 381 : decoded_[id_user] =
55 381 : user.decoded_size();
56 381 : if(pass)
57 : {
58 252 : set_size(id_pass,
59 252 : pass->size() + 2);
60 252 : decoded_[id_pass] =
61 252 : pass->decoded_size();
62 : }
63 : else
64 : {
65 : // trailing '@'
66 129 : set_size(id_pass, 1 );
67 : }
68 381 : }
69 :
70 : void
71 1888 : url_impl::
72 : apply_host(
73 : host_type ht,
74 : pct_string_view s,
75 : unsigned char const* addr) noexcept
76 : {
77 : // this function is for
78 : // authority_view_rule only
79 1888 : BOOST_ASSERT(from_ == from::authority);
80 :
81 : // host, port
82 1888 : host_type_ = ht;
83 1888 : set_size(id_host, s.size());
84 1888 : decoded_[id_host] =
85 1888 : s.decoded_size();
86 1888 : std::memcpy(
87 1888 : ip_addr_,
88 : addr,
89 : sizeof(ip_addr_));
90 1888 : }
91 :
92 : void
93 260 : url_impl::
94 : apply_port(
95 : core::string_view s,
96 : unsigned short pn) noexcept
97 : {
98 : // this function is for
99 : // authority_view_rule only
100 260 : BOOST_ASSERT(from_ == from::authority);
101 :
102 260 : port_number_ = pn;
103 260 : set_size(id_port, 1 + s.size());
104 260 : }
105 :
106 : void
107 1830 : url_impl::
108 : apply_authority(
109 : authority_view const& a) noexcept
110 : {
111 1830 : BOOST_ASSERT(from_ != from::authority);
112 :
113 : // userinfo
114 1830 : set_size(id_user,
115 1830 : a.u_.len(id_user) +
116 1830 : (from_ == from::authority ? 0 : 2));
117 1830 : set_size(id_pass, a.u_.len(id_pass));
118 1830 : decoded_[id_user] = a.u_.decoded_[id_user];
119 1830 : decoded_[id_pass] = a.u_.decoded_[id_pass];
120 :
121 : // host, port
122 1830 : host_type_ = a.u_.host_type_;
123 1830 : port_number_ = a.u_.port_number_;
124 1830 : set_size(id_host, a.u_.len(id_host));
125 1830 : set_size(id_port, a.u_.len(id_port));
126 1830 : std::memcpy(
127 1830 : ip_addr_,
128 1830 : a.u_.ip_addr_,
129 : sizeof(ip_addr_));
130 1830 : decoded_[id_host] = a.u_.decoded_[id_host];
131 1830 : }
132 :
133 : void
134 3573 : url_impl::
135 : apply_path(
136 : pct_string_view s,
137 : std::size_t nseg) noexcept
138 : {
139 3573 : set_size(id_path, s.size());
140 3573 : decoded_[id_path] = s.decoded_size();
141 3573 : nseg_ = detail::path_segments(s, nseg);
142 3573 : }
143 :
144 : void
145 447 : url_impl::
146 : apply_query(
147 : pct_string_view s,
148 : std::size_t n) noexcept
149 : {
150 447 : nparam_ = n;
151 447 : set_size(id_query, 1 + s.size());
152 447 : decoded_[id_query] = s.decoded_size();
153 447 : }
154 :
155 : void
156 214 : url_impl::
157 : apply_frag(
158 : pct_string_view s) noexcept
159 : {
160 214 : set_size(id_frag, s.size() + 1);
161 214 : decoded_[id_frag] = s.decoded_size();
162 214 : }
163 :
164 : // return length of [first, last)
165 : auto
166 20450 : url_impl::
167 : len(
168 : int first,
169 : int last) const noexcept ->
170 : std::size_t
171 : {
172 20450 : BOOST_ASSERT(first <= last);
173 20450 : BOOST_ASSERT(last <= id_end);
174 20450 : return offset(last) - offset(first);
175 : }
176 :
177 : // return length of part
178 : auto
179 269128 : url_impl::
180 : len(int id) const noexcept ->
181 : std::size_t
182 : {
183 : return id == id_end
184 538256 : ? zero_
185 269128 : : ( offset(id + 1) -
186 538256 : offset(id) );
187 : }
188 :
189 : // return offset of id
190 : auto
191 704415 : url_impl::
192 : offset(int id) const noexcept ->
193 : std::size_t
194 : {
195 : return
196 : id == id_scheme
197 704415 : ? zero_
198 704415 : : offset_[id];
199 : }
200 :
201 : // return id as string
202 : core::string_view
203 47922 : url_impl::
204 : get(int id) const noexcept
205 : {
206 : return {
207 47922 : cs_ + offset(id), len(id) };
208 : }
209 :
210 : // return [first, last) as string
211 : core::string_view
212 889 : url_impl::
213 : get(int first,
214 : int last) const noexcept
215 : {
216 889 : return { cs_ + offset(first),
217 889 : offset(last) - offset(first) };
218 : }
219 :
220 : // return id as pct-string
221 : pct_string_view
222 2203 : url_impl::
223 : pct_get(
224 : int id) const noexcept
225 : {
226 2203 : return make_pct_string_view_unsafe(
227 2203 : cs_ + offset(id),
228 : len(id),
229 4406 : decoded_[id]);
230 : }
231 :
232 : // return [first, last) as pct-string
233 : pct_string_view
234 120 : url_impl::
235 : pct_get(
236 : int first,
237 : int last) const noexcept
238 : {
239 120 : auto const pos = offset(first);
240 120 : std::size_t n = 0;
241 360 : for(auto i = first; i < last;)
242 240 : n += decoded_[i++];
243 120 : return make_pct_string_view_unsafe(
244 120 : cs_ + pos,
245 120 : offset(last) - pos,
246 120 : n);
247 : }
248 :
249 : //------------------------------------------------
250 :
251 : // change id to size n
252 : void
253 19467 : url_impl::
254 : set_size(
255 : int id,
256 : std::size_t n) noexcept
257 : {
258 19467 : auto d = n - len(id);
259 19467 : for(auto i = id + 1;
260 118243 : i <= id_end; ++i)
261 98776 : offset_[i] += d;
262 19467 : }
263 :
264 : // trim id to size n,
265 : // moving excess into id+1
266 : void
267 831 : url_impl::
268 : split(
269 : int id,
270 : std::size_t n) noexcept
271 : {
272 831 : BOOST_ASSERT(id < id_end - 1);
273 : //BOOST_ASSERT(n <= len(id));
274 831 : offset_[id + 1] = offset(id) + n;
275 831 : }
276 :
277 : // add n to [first, last]
278 : void
279 921 : url_impl::
280 : adjust_right(
281 : int first,
282 : int last,
283 : std::size_t n) noexcept
284 : {
285 921 : for(int i = first;
286 5363 : i <= last; ++i)
287 4442 : offset_[i] += n;
288 921 : }
289 :
290 : // remove n from [first, last]
291 : void
292 690 : url_impl::
293 : adjust_left(
294 : int first,
295 : int last,
296 : std::size_t n) noexcept
297 : {
298 690 : for(int i = first;
299 3394 : i <= last; ++i)
300 2704 : offset_[i] -= n;
301 690 : }
302 :
303 : // set [first, last) offset
304 : void
305 1592 : url_impl::
306 : collapse(
307 : int first,
308 : int last,
309 : std::size_t n) noexcept
310 : {
311 1592 : for(int i = first + 1;
312 2137 : i < last; ++i)
313 545 : offset_[i] = n;
314 1592 : }
315 :
316 :
317 : //------------------------------------------------
318 : //
319 : // path_ref
320 : //
321 : //------------------------------------------------
322 :
323 2044 : path_ref::
324 : path_ref(
325 2044 : url_impl const& impl) noexcept
326 : {
327 2044 : if(impl.from_ == url_impl::from::url)
328 : {
329 1587 : impl_ = &impl;
330 : }
331 : else
332 : {
333 457 : core::string_view s = impl.get(id_path);
334 457 : data_ = s.data();
335 457 : size_ = s.size();
336 457 : nseg_ = impl.nseg_;
337 457 : dn_ = impl.decoded_[id_path];
338 : }
339 2044 : }
340 :
341 181 : path_ref::
342 : path_ref(
343 : core::string_view s,
344 : std::size_t dn,
345 181 : std::size_t nseg) noexcept
346 362 : : data_(s.data())
347 181 : , size_(s.size())
348 181 : , nseg_(nseg)
349 181 : , dn_(dn)
350 : {
351 181 : }
352 :
353 : pct_string_view
354 4701 : path_ref::
355 : buffer() const noexcept
356 : {
357 4701 : if(impl_)
358 2389 : return make_pct_string_view_unsafe(
359 2389 : impl_->cs_ +
360 2389 : impl_->offset(id_path),
361 2389 : impl_->len(id_path),
362 4778 : impl_->decoded_[id_path]);
363 2312 : return make_pct_string_view_unsafe(
364 2312 : data_, size_, dn_);
365 : }
366 :
367 : std::size_t
368 4431 : path_ref::
369 : size() const noexcept
370 : {
371 4431 : if(impl_)
372 3116 : return impl_->len(id_path);
373 1315 : return size_;
374 : }
375 :
376 : char const*
377 12801 : path_ref::
378 : data() const noexcept
379 : {
380 12801 : if(impl_)
381 7466 : return impl_->cs_ +
382 7466 : impl_->offset(id_path);
383 5335 : return data_;
384 : }
385 :
386 : char const*
387 4363 : path_ref::
388 : end() const noexcept
389 : {
390 4363 : if(impl_)
391 2839 : return impl_->cs_ +
392 2839 : impl_->offset(id_query);
393 1524 : return data_ + size_;
394 : }
395 :
396 : std::size_t
397 9398 : path_ref::
398 : nseg() const noexcept
399 : {
400 9398 : if(impl_)
401 6155 : return impl_->nseg_;
402 3243 : return nseg_;
403 : }
404 :
405 : std::size_t
406 2012 : path_ref::
407 : decoded_size() const noexcept
408 : {
409 2012 : if(impl_)
410 1359 : return impl_->decoded_[id_path];
411 653 : return dn_;
412 : }
413 :
414 : //------------------------------------------------
415 : //
416 : // query_ref
417 : //
418 : //------------------------------------------------
419 :
420 701 : query_ref::
421 : query_ref(
422 : core::string_view s,
423 : std::size_t dn,
424 701 : std::size_t nparam) noexcept
425 1402 : : data_(s.data())
426 701 : , size_(s.size())
427 701 : , nparam_(nparam)
428 701 : , dn_(dn)
429 : {
430 701 : }
431 :
432 450 : query_ref::
433 : query_ref(
434 450 : url_impl const& impl) noexcept
435 : {
436 450 : if(impl.from_ == url_impl::from::url)
437 : {
438 353 : impl_ = &impl;
439 : }
440 : else
441 : {
442 97 : core::string_view s = impl.get(id_query);
443 97 : if (!s.empty())
444 : {
445 91 : s.remove_prefix(1);
446 91 : question_mark_ = true;
447 : }
448 97 : data_ = s.data();
449 97 : size_ = s.size();
450 97 : nparam_ = impl.nparam_;
451 97 : dn_ = impl.decoded_[id_query];
452 : }
453 450 : }
454 :
455 : pct_string_view
456 471 : query_ref::
457 : buffer() const noexcept
458 : {
459 471 : if(impl_)
460 : {
461 2 : auto pos = impl_->offset_[id_query];
462 2 : auto pos1 = impl_->offset_[id_frag];
463 2 : if(pos < pos1)
464 : {
465 0 : ++pos; // no '?'
466 0 : return make_pct_string_view_unsafe(
467 0 : impl_->cs_ + pos,
468 : pos1 - pos,
469 0 : impl_->decoded_[id_query]);
470 : }
471 : // empty
472 2 : return make_pct_string_view_unsafe(
473 2 : impl_->cs_ + pos,
474 : 0,
475 2 : 0);
476 : }
477 : // no '?'
478 469 : return make_pct_string_view_unsafe(
479 469 : data_, size_, dn_);
480 : }
481 :
482 : // with '?'
483 : std::size_t
484 5331 : query_ref::
485 : size() const noexcept
486 : {
487 5331 : if(impl_)
488 2011 : return impl_->len(id_query);
489 3320 : if(size_ > 0)
490 3284 : return size_ + 1;
491 36 : return question_mark_;
492 : }
493 :
494 : // no '?'
495 : char const*
496 5854 : query_ref::
497 : begin() const noexcept
498 : {
499 5854 : if(impl_)
500 : {
501 : // using the offset array here
502 2278 : auto pos = impl_->offset_[id_query];
503 2278 : auto pos1 = impl_->offset_[id_frag];
504 2278 : if(pos < pos1)
505 2278 : return impl_->cs_ + pos + 1; // no '?'
506 : // empty
507 0 : return impl_->cs_ + pos;
508 : }
509 3576 : return data_;
510 :
511 : }
512 :
513 : char const*
514 2298 : query_ref::
515 : end() const noexcept
516 : {
517 2298 : if(impl_)
518 910 : return impl_->cs_ +
519 910 : impl_->offset(id_frag);
520 1388 : return data_ + size_;
521 : }
522 :
523 : std::size_t
524 8992 : query_ref::
525 : nparam() const noexcept
526 : {
527 8992 : if(impl_)
528 3151 : return impl_->nparam_;
529 5841 : return nparam_;
530 : }
531 :
532 : #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
533 : #pragma GCC diagnostic pop
534 : #endif
535 :
536 : } // detail
537 : } // urls
538 : } // boost
|