include/boost/url/url_base.hpp

100.0% Lines (24/24) 100.0% Functions (11/11) 100.0% Branches (2/2)
include/boost/url/url_base.hpp
Line Branch Hits Source Code
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/url
9 //
10
11 #ifndef BOOST_URL_URL_BASE_HPP
12 #define BOOST_URL_URL_BASE_HPP
13
14 #include <boost/url/detail/config.hpp>
15 #include <boost/url/ipv4_address.hpp>
16 #include <boost/url/ipv6_address.hpp>
17 #include <boost/url/params_encoded_ref.hpp>
18 #include <boost/url/params_ref.hpp>
19 #include <boost/url/pct_string_view.hpp>
20 #include <boost/url/scheme.hpp>
21 #include <boost/url/segments_encoded_ref.hpp>
22 #include <boost/url/segments_ref.hpp>
23 #include <boost/url/url_view_base.hpp>
24 #include <cstdint>
25 #include <initializer_list>
26 #include <memory>
27 #include <string>
28 #include <utility>
29
30 namespace boost {
31 namespace urls {
32
33 namespace detail {
34 struct any_params_iter;
35 struct any_segments_iter;
36 struct params_iter_impl;
37 struct segments_iter_impl;
38 struct pattern;
39 }
40
41 /** Common functionality for containers
42
43 This base class is used by the library
44 to provide common member functions for
45 containers. This cannot be instantiated
46 directly; Instead, use one of the
47 containers or functions:
48
49 @par Containers
50 @li @ref url
51 @li @ref url_view
52 @li @ref static_url
53
54 @par Functions
55 @li @ref parse_absolute_uri
56 @li @ref parse_origin_form
57 @li @ref parse_relative_ref
58 @li @ref parse_uri
59 @li @ref parse_uri_reference
60 */
61 class url_base
62 : public url_view_base
63 {
64 char* s_ = nullptr;
65 std::size_t cap_ = 0;
66
67 friend class url;
68 friend class static_url_base;
69 friend class params_ref;
70 friend class segments_ref;
71 friend class segments_encoded_ref;
72 friend class params_encoded_ref;
73 friend struct detail::pattern;
74
75 struct op_t
76 {
77 ~op_t();
78 op_t(url_base&,
79 core::string_view* = nullptr,
80 core::string_view* = nullptr) noexcept;
81 void move(char*, char const*,
82 std::size_t) noexcept;
83
84 url_base& u;
85 core::string_view* s0 = nullptr;
86 core::string_view* s1 = nullptr;
87 char* old = nullptr;
88 };
89
90 5648 virtual ~url_base() noexcept = default;
91 4145 url_base() noexcept = default;
92 url_base(detail::url_impl const&) noexcept;
93 explicit url_base(core::string_view);
94 void reserve_impl(std::size_t n);
95 void copy(url_view_base const&);
96 virtual void clear_impl() noexcept = 0;
97 virtual void reserve_impl(
98 std::size_t, op_t&) = 0;
99 virtual void cleanup(op_t&) = 0;
100
101 public:
102 //--------------------------------------------
103 //
104 // Observers
105 //
106 //--------------------------------------------
107
108 /** Return the url as a null-terminated string
109
110 This function returns a pointer to a null
111 terminated string representing the url,
112 which may contain percent escapes.
113
114 @return A pointer to a null-terminated string containing the URL.
115
116 @par Example
117 @code
118 assert( std::strlen( url( "http://www.example.com" ).c_str() ) == 22 );
119 @endcode
120
121 @par Complexity
122 Constant.
123
124 @par Exception Safety
125 Throws nothing.
126 */
127 char const*
128 18357 c_str() const noexcept
129 {
130 18357 return impl().cs_;
131 }
132
133 /** Return the number of characters that can be stored without reallocating
134
135 This does not include the null terminator,
136 which is always present.
137
138 @return `*this`
139
140 @par Complexity
141 Constant.
142
143 @par Exception Safety
144 Throws nothing.
145 */
146 std::size_t
147 10 capacity() const noexcept
148 {
149 10 return cap_;
150 }
151
152 /** Clear the contents while preserving the capacity
153
154 @par Postconditions
155 @code
156 this->empty() == true
157 @endcode
158
159 @par Complexity
160 Constant.
161
162 @par Exception Safety
163 No-throw guarantee.
164 */
165 void
166 120 clear() noexcept
167 {
168 120 this->clear_impl();
169 120 }
170
171 /** Adjust the capacity without changing the size
172
173 This function adjusts the capacity
174 of the container in characters, without
175 affecting the current contents. Has
176 no effect if `n <= this->capacity()`.
177
178 @par Exception Safety
179 Strong guarantee.
180 Calls to allocate may throw.
181
182 @throw bad_alloc Allocation failure
183
184 @param n The capacity in characters,
185 excluding any null terminator.
186 */
187 void
188 165 reserve(std::size_t n)
189 {
190 165 reserve_impl(n);
191 164 }
192
193 //--------------------------------------------
194 //
195 // Fluent API
196 //
197
198 //--------------------------------------------
199 //
200 // Scheme
201 //
202 //--------------------------------------------
203
204 /** Set the scheme
205
206 The scheme is set to the specified
207 string, which must contain a valid
208 scheme without any trailing colon
209 (':').
210 Note that schemes are case-insensitive,
211 and the canonical form is lowercased.
212
213 @par Example
214 @code
215 assert( url( "http://www.example.com" ).set_scheme( "https" ).scheme_id() == scheme::https );
216 @endcode
217
218 @par Complexity
219 Linear in `this->size() + s.size()`.
220
221 @par Exception Safety
222 Strong guarantee.
223 Calls to allocate may throw.
224 Exceptions thrown on invalid input.
225
226 @throw system_error
227 `s` contains an invalid scheme.
228
229 @param s The scheme to set.
230
231 @return `*this`
232
233 @par BNF
234 @code
235 scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
236 @endcode
237
238 @par Specification
239 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
240 3.1. Scheme (rfc3986)</a>
241
242 @see
243 @ref remove_scheme.
244 */
245 url_base&
246 set_scheme(core::string_view s);
247
248 /** Set the scheme
249
250 This function sets the scheme to the specified
251 known @ref urls::scheme id, which may not be
252 @ref scheme::unknown or else an exception is
253 thrown. If the id is @ref scheme::none, this
254 function behaves as if @ref remove_scheme
255 were called.
256
257 @par Example
258 @code
259 assert( url( "http://example.com/echo.cgi" ).set_scheme_id( scheme::wss ).buffer() == "wss://example.com/echo.cgi" );
260 @endcode
261
262 @par Complexity
263 Linear in `this->size()`.
264
265 @par Exception Safety
266 Strong guarantee.
267 Calls to allocate may throw.
268 Exceptions thrown on invalid input.
269
270 @throw system_error
271 The scheme is invalid.
272
273 @param id The scheme to set.
274 @return `*this`
275
276 @par Specification
277 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
278 3.1. Scheme (rfc3986)</a>
279 */
280 url_base&
281 set_scheme_id(urls::scheme id);
282
283 /** Remove the scheme
284
285 This function removes the scheme if it
286 is present.
287
288 @par Example
289 @code
290 assert( url("http://www.example.com/index.htm" ).remove_scheme().buffer() == "//www.example.com/index.htm" );
291 @endcode
292
293 @par Postconditions
294 @code
295 this->has_scheme() == false && this->scheme_id() == scheme::none
296 @endcode
297
298 @par Complexity
299 Linear in `this->size()`.
300
301 @par Exception Safety
302 Throws nothing.
303
304 @return `*this`
305
306 @par BNF
307 @code
308 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
309 @endcode
310
311 @par Specification
312 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
313 3.1. Scheme (rfc3986)</a>
314
315 @see
316 @ref set_scheme.
317 */
318 url_base&
319 remove_scheme();
320
321 //--------------------------------------------
322 //
323 // Authority
324 //
325 //--------------------------------------------
326
327 /** Set the authority
328
329 This function sets the authority
330 to the specified string.
331 The string may contain percent-escapes.
332
333 @par Example
334 @code
335 assert( url().set_encoded_authority( "My%20Computer" ).has_authority() );
336 @endcode
337
338 @par Exception Safety
339 Strong guarantee.
340 Calls to allocate may throw.
341 Exceptions thrown on invalid input.
342
343 @throw system_eror
344 The string contains an invalid percent-encoding.
345
346 @param s The authority string to set.
347 @return `*this`
348
349 @par BNF
350 @code
351 authority = [ userinfo "@" ] host [ ":" port ]
352
353 userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
354 host = IP-literal / IPv4address / reg-name
355 port = *DIGIT
356 @endcode
357
358 @par Specification
359 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2">
360 3.2. Authority (rfc3986)</a>
361 @see
362 @ref remove_authority.
363 */
364 url_base&
365 set_encoded_authority(
366 pct_string_view s);
367
368 /** Remove the authority
369
370 This function removes the authority,
371 which includes the userinfo, host, and
372 a port if present.
373
374 @par Example
375 @code
376 assert( url( "http://example.com/echo.cgi" ).remove_authority().buffer() == "http:/echo.cgi" );
377 @endcode
378
379 @par Postconditions
380 @code
381 this->has_authority() == false && this->has_userinfo() == false && this->has_port() == false
382 @endcode
383
384 @par Complexity
385 Linear in `this->size()`.
386
387 @par Exception Safety
388 Throws nothing.
389
390 @return `*this`
391
392 @par BNF
393 @code
394 authority = [ userinfo "@" ] host [ ":" port ]
395
396 userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
397 host = IP-literal / IPv4address / reg-name
398 port = *DIGIT
399 @endcode
400
401 @par Specification
402 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2">
403 3.2. Authority (rfc3986)</a>
404
405 @see
406 @ref set_encoded_authority.
407 */
408 url_base&
409 remove_authority();
410
411 //--------------------------------------------
412 //
413 // Userinfo
414 //
415 //--------------------------------------------
416
417 /** Set the userinfo
418
419 The userinfo is set to the given string,
420 which may contain percent-escapes.
421 Any special or reserved characters in the
422 string are automatically percent-encoded.
423 The effects on the user and password
424 depend on the presence of a colon (':')
425 in the string:
426
427 @li If an unescaped colon exists, the
428 characters up to the colon become
429 the user and the rest of the characters
430 after the colon become the password.
431 In this case @ref has_password returns
432 true. Otherwise,
433
434 @li If there is no colon, the user is
435 set to the string. The function
436 @ref has_password returns false.
437
438 @note
439 The interpretation of the userinfo as
440 individual user and password components
441 is scheme-dependent. Transmitting
442 passwords in URLs is deprecated.
443
444 @par Example
445 @code
446 assert( url( "http://example.com" ).set_userinfo( "user:pass" ).encoded_user() == "user" );
447 @endcode
448
449 @par Complexity
450 Linear in `this->size() + s.size()`.
451
452 @par Exception Safety
453 Strong guarantee.
454 Calls to allocate may throw.
455
456 @param s The string to set.
457 @return `*this`
458
459 @par BNF
460 @code
461 userinfo = [ [ user ] [ ':' password ] ]
462
463 user = *( unreserved / pct-encoded / sub-delims )
464 password = *( unreserved / pct-encoded / sub-delims / ":" )
465 @endcode
466
467 @par Specification
468 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
469 3.2.1. User Information (rfc3986)</a>
470
471 @see
472 @ref remove_userinfo,
473 @ref set_encoded_userinfo.
474 */
475 url_base&
476 set_userinfo(
477 core::string_view s);
478
479 /** Set the userinfo.
480
481 The userinfo is set to the given string,
482 which may contain percent-escapes.
483 Escapes in the string are preserved,
484 and reserved characters in the string
485 are percent-escaped in the result.
486 The effects on the user and password
487 depend on the presence of a colon (':')
488 in the string:
489
490 @li If an unescaped colon exists, the
491 characters up to the colon become
492 the user and the rest of the characters
493 after the colon become the password.
494 In this case @ref has_password returns
495 true. Otherwise,
496
497 @li If there is no colon, the user is
498 set to the string. The function
499 @ref has_password returns false.
500
501 @note
502 The interpretation of the userinfo as
503 individual user and password components
504 is scheme-dependent. Transmitting
505 passwords in URLs is deprecated.
506
507 @par Example
508 @code
509 assert( url( "http://example.com" ).set_encoded_userinfo( "john%20doe" ).user() == "john doe" );
510 @endcode
511
512 @par Complexity
513 Linear in `this->size() + s.size()`.
514
515 @par Exception Safety
516 Strong guarantee.
517 Calls to allocate may throw.
518 Exceptions thrown on invalid input.
519
520 @throw system_error
521 `s` contains an invalid percent-encoding.
522
523 @param s The string to set.
524 @return `*this`
525
526 @par BNF
527 @code
528 userinfo = [ [ user ] [ ':' password ] ]
529
530 user = *( unreserved / pct-encoded / sub-delims )
531 password = *( unreserved / pct-encoded / sub-delims / ":" )
532 @endcode
533
534 @par Specification
535 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
536 3.2.1. User Information (rfc3986)</a>
537
538 @see
539 @ref remove_userinfo,
540 @ref set_userinfo.
541 */
542 url_base&
543 set_encoded_userinfo(
544 pct_string_view s);
545
546 /** Remove the userinfo
547
548 This function removes the userinfo if
549 present, without removing any authority.
550
551 @par Example
552 @code
553 assert( url( "http://user@example.com" ).remove_userinfo().has_userinfo() == false );
554 @endcode
555
556 @par Postconditions
557 @code
558 this->has_userinfo() == false && this->encoded_userinfo().empty == true
559 @endcode
560
561 @par Complexity
562 Linear in `this->size()`.
563
564 @par Exception Safety
565 Throws nothing.
566
567 @return `*this`
568
569 @par BNF
570 @code
571 userinfo = [ [ user ] [ ':' password ] ]
572
573 user = *( unreserved / pct-encoded / sub-delims )
574 password = *( unreserved / pct-encoded / sub-delims / ":" )
575 @endcode
576
577 @par Specification
578 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
579 3.2.1. User Information (rfc3986)</a>
580
581 @see
582 @ref set_encoded_userinfo,
583 @ref set_userinfo.
584 */
585 url_base&
586 remove_userinfo() noexcept;
587
588 //--------------------------------------------
589
590 /** Set the user
591
592 This function sets the user part of the
593 userinfo to the string.
594 Any special or reserved characters in the
595 string are automatically percent-encoded.
596
597 @par Example
598 @code
599 assert( url().set_user("john doe").encoded_userinfo() == "john%20doe" );
600 @endcode
601
602 @par Postconditions
603 @code
604 this->has_authority() == true && this->has_userinfo() == true
605 @endcode
606
607 @par Complexity
608 Linear in `this->size() + s.size()`.
609
610 @par Exception Safety
611 Strong guarantee.
612 Calls to allocate may throw.
613
614 @param s The string to set.
615 @return `*this`
616
617 @par BNF
618 @code
619 userinfo = [ [ user ] [ ':' password ] ]
620
621 user = *( unreserved / pct-encoded / sub-delims )
622 password = *( unreserved / pct-encoded / sub-delims / ":" )
623 @endcode
624
625 @par Specification
626 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
627 3.2.1. User Information (rfc3986)</a>
628
629 @see
630 @ref remove_password,
631 @ref set_encoded_password,
632 @ref set_encoded_user,
633 @ref set_password.
634 */
635 url_base&
636 set_user(
637 core::string_view s);
638
639 /** Set the user
640
641 This function sets the user part of the
642 userinfo the the string, which may
643 contain percent-escapes.
644 Escapes in the string are preserved,
645 and reserved characters in the string
646 are percent-escaped in the result.
647
648 @par Example
649 @code
650 assert( url().set_encoded_user("john%20doe").userinfo() == "john doe" );
651 @endcode
652
653 @par Postconditions
654 @code
655 this->has_authority() == true && this->has_userinfo() == true
656 @endcode
657
658 @par Complexity
659 Linear in `this->size() + s.size()`.
660
661 @par Exception Safety
662 Strong guarantee.
663 Calls to allocate may throw.
664
665 @throw system_error
666 `s` contains an invalid percent-encoding.
667
668 @param s The string to set.
669
670 @return `*this`
671
672 @return `*this`
673
674 @par BNF
675 @code
676 userinfo = [ [ user ] [ ':' password ] ]
677
678 user = *( unreserved / pct-encoded / sub-delims )
679 password = *( unreserved / pct-encoded / sub-delims / ":" )
680 @endcode
681
682 @par Specification
683 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
684 3.2.1. User Information (rfc3986)</a>
685
686 @see
687 @ref remove_password,
688 @ref set_encoded_password,
689 @ref set_password,
690 @ref set_user.
691 */
692 url_base&
693 set_encoded_user(
694 pct_string_view s);
695
696 /** Set the password.
697
698 This function sets the password in
699 the userinfo to the string.
700 Reserved characters in the string are
701 percent-escaped in the result.
702
703 @note
704 The interpretation of the userinfo as
705 individual user and password components
706 is scheme-dependent. Transmitting
707 passwords in URLs is deprecated.
708
709 @par Example
710 @code
711 assert( url("http://user@example.com").set_password( "pass" ).encoded_userinfo() == "user:pass" );
712 @endcode
713
714 @par Postconditions
715 @code
716 this->has_password() == true && this->password() == s
717 @endcode
718
719 @par Exception Safety
720 Strong guarantee.
721 Calls to allocate may throw.
722
723 @param s The string to set. This string may
724 contain any characters, including nulls.
725
726 @return `*this`
727
728 @par BNF
729 @code
730 userinfo = [ [ user ] [ ':' password ] ]
731
732 user = *( unreserved / pct-encoded / sub-delims )
733 password = *( unreserved / pct-encoded / sub-delims / ":" )
734 @endcode
735
736 @par Specification
737 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
738 3.2.1. User Information (rfc3986)</a>
739
740 @see
741 @ref remove_password,
742 @ref set_encoded_password,
743 @ref set_encoded_user,
744 @ref set_user.
745 */
746 url_base&
747 set_password(
748 core::string_view s);
749
750 /** Set the password.
751
752 This function sets the password in
753 the userinfo to the string, which
754 may contain percent-escapes.
755 Escapes in the string are preserved,
756 and reserved characters in the string
757 are percent-escaped in the result.
758
759 @note
760 The interpretation of the userinfo as
761 individual user and password components
762 is scheme-dependent. Transmitting
763 passwords in URLs is deprecated.
764
765 @par Example
766 @code
767 assert( url("http://user@example.com").set_encoded_password( "pass" ).encoded_userinfo() == "user:pass" );
768 @endcode
769
770 @par Postconditions
771 @code
772 this->has_password() == true
773 @endcode
774
775 @par Exception Safety
776 Strong guarantee.
777 Calls to allocate may throw.
778
779 @throw system_error
780 `s` contains an invalid percent-encoding.
781
782 @param s The string to set. This string may
783 contain any characters, including nulls.
784 @return `*this`
785
786 @par BNF
787 @code
788 userinfo = [ [ user ] [ ':' password ] ]
789
790 user = *( unreserved / pct-encoded / sub-delims )
791 password = *( unreserved / pct-encoded / sub-delims / ":" )
792 @endcode
793
794 @par Specification
795 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
796 3.2.1. User Information (rfc3986)</a>
797
798 @see
799 @ref remove_password,
800 @ref set_encoded_password,
801 @ref set_encoded_user,
802 @ref set_user.
803 */
804 url_base&
805 set_encoded_password(
806 pct_string_view s);
807
808 /** Remove the password
809
810 This function removes the password from
811 the userinfo if a password exists. If
812 there is no userinfo or no authority,
813 the call has no effect.
814
815 @note
816 The interpretation of the userinfo as
817 individual user and password components
818 is scheme-dependent. Transmitting
819 passwords in URLs is deprecated.
820
821 @par Example
822 @code
823 assert( url( "http://user:pass@example.com" ).remove_password().authority().buffer() == "user@example.com" );
824 @endcode
825
826 @par Postconditions
827 @code
828 this->has_password() == false && this->encoded_password().empty() == true
829 @endcode
830
831 @par Complexity
832 Linear in `this->size()`.
833
834 @par Exception Safety
835 Throws nothing.
836
837 @par BNF
838 @code
839 userinfo = [ [ user ] [ ':' password ] ]
840
841 user = *( unreserved / pct-encoded / sub-delims )
842 password = *( unreserved / pct-encoded / sub-delims / ":" )
843 @endcode
844
845 @return `*this`
846
847 @par Specification
848 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
849 3.2.1. User Information (rfc3986)</a>
850
851 @see
852 @ref set_encoded_password,
853 @ref set_encoded_user,
854 @ref set_password,
855 @ref set_user.
856 */
857 url_base&
858 remove_password() noexcept;
859
860 //--------------------------------------------
861 //
862 // Host
863 //
864 //--------------------------------------------
865
866 /** Set the host
867
868 Depending on the contents of the passed
869 string, this function sets the host:
870
871 @li If the string is a valid IPv4 address,
872 then the host is set to the address.
873 The host type is @ref host_type::ipv4.
874
875 @li If the string is a valid IPv6 address
876 enclosed in square brackets, then the
877 host is set to that address.
878 The host type is @ref host_type::ipv6.
879
880 @li If the string is a valid IPvFuture
881 address enclosed in square brackets, then
882 the host is set to that address.
883 The host type is @ref host_type::ipvfuture.
884
885 @li Otherwise, the host name is set to
886 the string, which may be empty.
887 Reserved characters in the string are
888 percent-escaped in the result.
889 The host type is @ref host_type::name.
890
891 In all cases, when this function returns,
892 the URL contains an authority.
893
894 @par Example
895 @code
896 assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
897 @endcode
898
899 @par Postconditions
900 @code
901 this->has_authority() == true
902 @endcode
903
904 @par Complexity
905 Linear in `this->size() + s.size()`.
906
907 @par Exception Safety
908 Strong guarantee.
909 Calls to allocate may throw.
910
911 @par BNF
912 @code
913 host = IP-literal / IPv4address / reg-name
914
915 IP-literal = "[" ( IPv6address / IPvFuture ) "]"
916
917 reg-name = *( unreserved / pct-encoded / "-" / ".")
918 @endcode
919
920 @param s The string to set.
921 @return `*this`
922
923 @par Specification
924 @li <a href="https://en.wikipedia.org/wiki/IPv4"
925 >IPv4 (Wikipedia)</a>
926 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
927 >IP Version 6 Addressing Architecture (rfc4291)</a>
928 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
929 3.2.2. Host (rfc3986)</a>
930
931 @see
932 @ref set_encoded_host,
933 @ref set_encoded_host_address,
934 @ref set_encoded_host_name,
935 @ref set_host_address,
936 @ref set_host_ipv4,
937 @ref set_host_ipv6,
938 @ref set_host_ipvfuture,
939 @ref set_host_name.
940 */
941 url_base&
942 set_host(
943 core::string_view s);
944
945 /** Set the host
946
947 Depending on the contents of the passed
948 string, this function sets the host:
949
950 @li If the string is a valid IPv4 address,
951 then the host is set to the address.
952 The host type is @ref host_type::ipv4.
953
954 @li If the string is a valid IPv6 address
955 enclosed in square brackets, then the
956 host is set to that address.
957 The host type is @ref host_type::ipv6.
958
959 @li If the string is a valid IPvFuture
960 address enclosed in square brackets, then
961 the host is set to that address.
962 The host type is @ref host_type::ipvfuture.
963
964 @li Otherwise, the host name is set to
965 the string. This string can contain percent
966 escapes, or can be empty.
967 Escapes in the string are preserved,
968 and reserved characters in the string
969 are percent-escaped in the result.
970 The host type is @ref host_type::name.
971
972 In all cases, when this function returns,
973 the URL contains an authority.
974
975 @par Example
976 @code
977 assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
978 @endcode
979
980 @par Postconditions
981 @code
982 this->has_authority() == true
983 @endcode
984
985 @par Complexity
986 Linear in `this->size() + s.size()`.
987
988 @par Exception Safety
989 Strong guarantee.
990 Calls to allocate may throw.
991 Exceptions thrown on invalid input.
992
993 @throw system_error
994 `s` contains an invalid percent-encoding.
995
996 @param s The string to set.
997
998 @return `*this`
999
1000 @par BNF
1001 @code
1002 host = IP-literal / IPv4address / reg-name
1003
1004 IP-literal = "[" ( IPv6address / IPvFuture ) "]"
1005
1006 reg-name = *( unreserved / pct-encoded / "-" / ".")
1007 @endcode
1008
1009 @par Specification
1010 @li <a href="https://en.wikipedia.org/wiki/IPv4"
1011 >IPv4 (Wikipedia)</a>
1012 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1013 >IP Version 6 Addressing Architecture (rfc4291)</a>
1014 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1015 3.2.2. Host (rfc3986)</a>
1016
1017 @see
1018 @ref set_encoded_host_address,
1019 @ref set_encoded_host_name,
1020 @ref set_host,
1021 @ref set_host_address,
1022 @ref set_host_ipv4,
1023 @ref set_host_ipv6,
1024 @ref set_host_ipvfuture,
1025 @ref set_host_name.
1026 */
1027 url_base&
1028 set_encoded_host(pct_string_view s);
1029
1030 /** Set the host to an address
1031
1032 Depending on the contents of the passed
1033 string, this function sets the host:
1034
1035 @li If the string is a valid IPv4 address,
1036 then the host is set to the address.
1037 The host type is @ref host_type::ipv4.
1038
1039 @li If the string is a valid IPv6 address,
1040 then the host is set to that address.
1041 The host type is @ref host_type::ipv6.
1042
1043 @li If the string is a valid IPvFuture,
1044 then the host is set to that address.
1045 The host type is @ref host_type::ipvfuture.
1046
1047 @li Otherwise, the host name is set to
1048 the string, which may be empty.
1049 Reserved characters in the string are
1050 percent-escaped in the result.
1051 The host type is @ref host_type::name.
1052
1053 In all cases, when this function returns,
1054 the URL contains an authority.
1055
1056 @par Example
1057 @code
1058 assert( url( "http://www.example.com" ).set_host_address( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1059 @endcode
1060
1061 @par Postconditions
1062 @code
1063 this->has_authority() == true
1064 @endcode
1065
1066 @par Complexity
1067 Linear in `s.size()`.
1068
1069 @par Exception Safety
1070 Strong guarantee.
1071 Calls to allocate may throw.
1072
1073 @par BNF
1074 @code
1075 IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1076
1077 dec-octet = DIGIT ; 0-9
1078 / %x31-39 DIGIT ; 10-99
1079 / "1" 2DIGIT ; 100-199
1080 / "2" %x30-34 DIGIT ; 200-249
1081 / "25" %x30-35 ; 250-255
1082
1083 IPv6address = 6( h16 ":" ) ls32
1084 / "::" 5( h16 ":" ) ls32
1085 / [ h16 ] "::" 4( h16 ":" ) ls32
1086 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1087 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1088 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1089 / [ *4( h16 ":" ) h16 ] "::" ls32
1090 / [ *5( h16 ":" ) h16 ] "::" h16
1091 / [ *6( h16 ":" ) h16 ] "::"
1092
1093 ls32 = ( h16 ":" h16 ) / IPv4address
1094 ; least-significant 32 bits of address
1095
1096 h16 = 1*4HEXDIG
1097 ; 16 bits of address represented in hexadecimal
1098
1099 IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1100
1101 reg-name = *( unreserved / pct-encoded / "-" / ".")
1102 @endcode
1103
1104 @param s The string to set.
1105 @return `*this`
1106
1107 @par Specification
1108 @li <a href="https://en.wikipedia.org/wiki/IPv4"
1109 >IPv4 (Wikipedia)</a>
1110 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1111 >IP Version 6 Addressing Architecture (rfc4291)</a>
1112 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1113 3.2.2. Host (rfc3986)</a>
1114
1115 @see
1116 @ref set_encoded_host,
1117 @ref set_encoded_host_address,
1118 @ref set_encoded_host_name,
1119 @ref set_host,
1120 @ref set_host_address,
1121 @ref set_host_ipv4,
1122 @ref set_host_ipv6,
1123 @ref set_host_ipvfuture,
1124 @ref set_host_name.
1125 */
1126 url_base&
1127 set_host_address(core::string_view s);
1128
1129 /** Set the host to an address
1130
1131 Depending on the contents of the passed
1132 string, this function sets the host:
1133
1134 @li If the string is a valid IPv4 address,
1135 then the host is set to the address.
1136 The host type is @ref host_type::ipv4.
1137
1138 @li If the string is a valid IPv6 address,
1139 then the host is set to that address.
1140 The host type is @ref host_type::ipv6.
1141
1142 @li If the string is a valid IPvFuture,
1143 then the host is set to that address.
1144 The host type is @ref host_type::ipvfuture.
1145
1146 @li Otherwise, the host name is set to
1147 the string. This string can contain percent
1148 escapes, or can be empty.
1149 Escapes in the string are preserved,
1150 and reserved characters in the string
1151 are percent-escaped in the result.
1152 The host type is @ref host_type::name.
1153
1154 In all cases, when this function returns,
1155 the URL contains an authority.
1156
1157 @par Example
1158 @code
1159 assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1160 @endcode
1161
1162 @par Postconditions
1163 @code
1164 this->has_authority() == true
1165 @endcode
1166
1167 @par Complexity
1168 Linear in `this->size() + s.size()`.
1169
1170 @par Exception Safety
1171 Strong guarantee.
1172 Calls to allocate may throw.
1173 Exceptions thrown on invalid input.
1174
1175 @throw system_error
1176 `s` contains an invalid percent-encoding.
1177
1178 @par BNF
1179 @code
1180 IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1181
1182 dec-octet = DIGIT ; 0-9
1183 / %x31-39 DIGIT ; 10-99
1184 / "1" 2DIGIT ; 100-199
1185 / "2" %x30-34 DIGIT ; 200-249
1186 / "25" %x30-35 ; 250-255
1187
1188 IPv6address = 6( h16 ":" ) ls32
1189 / "::" 5( h16 ":" ) ls32
1190 / [ h16 ] "::" 4( h16 ":" ) ls32
1191 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1192 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1193 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1194 / [ *4( h16 ":" ) h16 ] "::" ls32
1195 / [ *5( h16 ":" ) h16 ] "::" h16
1196 / [ *6( h16 ":" ) h16 ] "::"
1197
1198 ls32 = ( h16 ":" h16 ) / IPv4address
1199 ; least-significant 32 bits of address
1200
1201 h16 = 1*4HEXDIG
1202 ; 16 bits of address represented in hexadecimal
1203
1204 IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1205
1206 reg-name = *( unreserved / pct-encoded / "-" / ".")
1207 @endcode
1208
1209 @param s The string to set.
1210 @return `*this`
1211
1212 @par Specification
1213 @li <a href="https://en.wikipedia.org/wiki/IPv4"
1214 >IPv4 (Wikipedia)</a>
1215 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1216 >IP Version 6 Addressing Architecture (rfc4291)</a>
1217 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1218 3.2.2. Host (rfc3986)</a>
1219
1220 @see
1221 @ref set_encoded_host,
1222 @ref set_encoded_host_name,
1223 @ref set_host,
1224 @ref set_host_address,
1225 @ref set_host_ipv4,
1226 @ref set_host_ipv6,
1227 @ref set_host_ipvfuture,
1228 @ref set_host_name.
1229 */
1230 url_base&
1231 set_encoded_host_address(
1232 pct_string_view s);
1233
1234 /** Set the host to an address
1235
1236 The host is set to the specified IPv4
1237 address.
1238 The host type is @ref host_type::ipv4.
1239
1240 @par Example
1241 @code
1242 assert( url("http://www.example.com").set_host_ipv4( ipv4_address( "127.0.0.1" ) ).buffer() == "http://127.0.0.1" );
1243 @endcode
1244
1245 @par Complexity
1246 Linear in `this->size()`.
1247
1248 @par Postconditions
1249 @code
1250 this->has_authority() == true && this->host_ipv4_address() == addr && this->host_type() == host_type::ipv4
1251 @endcode
1252
1253 @par Exception Safety
1254 Strong guarantee.
1255 Calls to allocate may throw.
1256
1257 @param addr The address to set.
1258 @return `*this`
1259
1260 @par BNF
1261 @code
1262 IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1263
1264 dec-octet = DIGIT ; 0-9
1265 / %x31-39 DIGIT ; 10-99
1266 / "1" 2DIGIT ; 100-199
1267 / "2" %x30-34 DIGIT ; 200-249
1268 / "25" %x30-35 ; 250-255
1269 @endcode
1270
1271 @par Specification
1272 @li <a href="https://en.wikipedia.org/wiki/IPv4"
1273 >IPv4 (Wikipedia)</a>
1274 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1275 3.2.2. Host (rfc3986)</a>
1276
1277 @see
1278 @ref set_encoded_host,
1279 @ref set_encoded_host_address,
1280 @ref set_encoded_host_name,
1281 @ref set_host,
1282 @ref set_host_address,
1283 @ref set_host_ipv6,
1284 @ref set_host_ipvfuture,
1285 @ref set_host_name.
1286 */
1287 url_base&
1288 set_host_ipv4(
1289 ipv4_address const& addr);
1290
1291 /** Set the host to an address
1292
1293 The host is set to the specified IPv6
1294 address.
1295 The host type is @ref host_type::ipv6.
1296
1297 @par Example
1298 @code
1299 assert( url().set_host_ipv6( ipv6_address( "1::6:c0a8:1" ) ).authority().buffer() == "[1::6:c0a8:1]" );
1300 @endcode
1301
1302 @par Postconditions
1303 @code
1304 this->has_authority() == true && this->host_ipv6_address() == addr && this->host_type() == host_type::ipv6
1305 @endcode
1306
1307 @par Complexity
1308 Linear in `this->size()`.
1309
1310 @par Exception Safety
1311 Strong guarantee.
1312 Calls to allocate may throw.
1313
1314 @param addr The address to set.
1315
1316 @return `*this`
1317
1318 @par BNF
1319 @code
1320 IPv6address = 6( h16 ":" ) ls32
1321 / "::" 5( h16 ":" ) ls32
1322 / [ h16 ] "::" 4( h16 ":" ) ls32
1323 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1324 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1325 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1326 / [ *4( h16 ":" ) h16 ] "::" ls32
1327 / [ *5( h16 ":" ) h16 ] "::" h16
1328 / [ *6( h16 ":" ) h16 ] "::"
1329
1330 ls32 = ( h16 ":" h16 ) / IPv4address
1331 ; least-significant 32 bits of address
1332
1333 h16 = 1*4HEXDIG
1334 ; 16 bits of address represented in hexadecimal
1335 @endcode
1336
1337 @par Specification
1338 @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1339 >IP Version 6 Addressing Architecture (rfc4291)</a>
1340 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1341 3.2.2. Host (rfc3986)</a>
1342
1343 @see
1344 @ref set_encoded_host,
1345 @ref set_encoded_host_address,
1346 @ref set_encoded_host_name,
1347 @ref set_host,
1348 @ref set_host_address,
1349 @ref set_host_ipv4,
1350 @ref set_host_ipvfuture,
1351 @ref set_host_name.
1352 */
1353 url_base&
1354 set_host_ipv6(
1355 ipv6_address const& addr);
1356
1357 /** Set the zone ID for an IPv6 address.
1358
1359 This function sets the zone ID for the host if the host is an IPv6 address.
1360 Reserved characters in the string are percent-escaped in the result.
1361
1362 @par Example
1363 @code
1364 assert( u.set_host_ipv6( ipv6_address( "fe80::1" ) ).set_zone_id( "eth0" ).buffer() == "https://[fe80::1%25eth0]" );
1365 @endcode
1366
1367 @par Complexity
1368 Linear in `this->size()`.
1369
1370 @par Exception Safety
1371 Strong guarantee. Calls to allocate may throw.
1372
1373 @param s The zone ID to set.
1374 @return `*this`
1375
1376 @par Specification
1377 @li <a href="https://datatracker.ietf.org/doc/html/rfc6874">RFC 6874</a>
1378
1379 */
1380 url_base&
1381 set_zone_id(core::string_view s);
1382
1383 /** Set the zone ID for an IPv6 address (percent-encoded).
1384
1385 This function sets the zone ID for the host if the host is an IPv6 address.
1386 Escapes in the string are preserved, and reserved characters in the string
1387 are percent-escaped in the result.
1388
1389 @par Example
1390 @code
1391 assert( u.set_host_ipv6( ipv6_address( "fe80::1" ) ).set_encoded_zone_id( "eth0" ).buffer() == "https://[fe80::1%25eth0]" );
1392 @endcode
1393
1394 @par Complexity
1395 Linear in `this->size()`.
1396
1397 @par Exception Safety
1398 Strong guarantee. Calls to allocate may throw.
1399 Exceptions thrown on invalid input.
1400
1401 @throw system_error
1402 `s` contains an invalid percent-encoding.
1403
1404 @param s The zone ID to set.
1405 @return `*this`
1406
1407 @par Specification
1408 @li <a href="https://datatracker.ietf.org/doc/html/rfc6874">RFC 6874</a>
1409
1410 */
1411 url_base&
1412 set_encoded_zone_id(pct_string_view s);
1413
1414 /** Set the host to an address
1415
1416 The host is set to the specified IPvFuture
1417 string.
1418 The host type is @ref host_type::ipvfuture.
1419
1420 @par Example
1421 @code
1422 assert( url().set_host_ipvfuture( "v42.bis" ).buffer() == "//[v42.bis]" );
1423 @endcode
1424
1425 @par Complexity
1426 Linear in `this->size() + s.size()`.
1427
1428 @par Postconditions
1429 @code
1430 this->has_authority() == true && this->host_ipvfuture) == s && this->host_type() == host_type::ipvfuture
1431 @endcode
1432
1433 @par Exception Safety
1434 Strong guarantee.
1435 Calls to allocate may throw.
1436 Exceptions thrown on invalid input.
1437
1438 @throw system_error
1439 `s` contains an invalid percent-encoding.
1440
1441 @param s The string to set.
1442
1443 @return `*this`
1444
1445 @par BNF
1446 @code
1447 IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1448 @endcode
1449
1450 @par Specification
1451 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1452 3.2.2. Host (rfc3986)</a>
1453
1454 @see
1455 @ref set_encoded_host,
1456 @ref set_encoded_host_address,
1457 @ref set_encoded_host_name,
1458 @ref set_host,
1459 @ref set_host_address,
1460 @ref set_host_ipv4,
1461 @ref set_host_ipv6,
1462 @ref set_host_name.
1463 */
1464 url_base&
1465 set_host_ipvfuture(
1466 core::string_view s);
1467
1468 /** Set the host to a name
1469
1470 The host is set to the specified string,
1471 which may be empty.
1472 Reserved characters in the string are
1473 percent-escaped in the result.
1474 The host type is @ref host_type::name.
1475
1476 @par Example
1477 @code
1478 assert( url( "http://www.example.com/index.htm").set_host_name( "localhost" ).host_address() == "localhost" );
1479 @endcode
1480
1481 @par Postconditions
1482 @code
1483 this->has_authority() == true && this->host_ipv6_address() == addr && this->host_type() == host_type::name
1484 @endcode
1485
1486 @par Exception Safety
1487 Strong guarantee.
1488 Calls to allocate may throw.
1489
1490 @param s The string to set.
1491 @return `*this`
1492
1493 @par BNF
1494 @code
1495 reg-name = *( unreserved / pct-encoded / "-" / ".")
1496 @endcode
1497
1498 @par Specification
1499 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1500 3.2.2. Host (rfc3986)</a>
1501
1502 @see
1503 @ref set_encoded_host,
1504 @ref set_encoded_host_address,
1505 @ref set_encoded_host_name,
1506 @ref set_host,
1507 @ref set_host_address,
1508 @ref set_host_ipv4,
1509 @ref set_host_ipv6,
1510 @ref set_host_ipvfuture.
1511 */
1512 url_base&
1513 set_host_name(
1514 core::string_view s);
1515
1516 /** Set the host to a name
1517
1518 The host is set to the specified string,
1519 which may contain percent-escapes and
1520 can be empty.
1521 Escapes in the string are preserved,
1522 and reserved characters in the string
1523 are percent-escaped in the result.
1524 The host type is @ref host_type::name.
1525
1526 @par Example
1527 @code
1528 assert( url( "http://www.example.com/index.htm").set_encoded_host_name( "localhost" ).host_address() == "localhost" );
1529 @endcode
1530
1531 @par Postconditions
1532 @code
1533 this->has_authority() == true && this->host_ipv6_address() == addr && this->host_type() == host_type::name
1534 @endcode
1535
1536 @par Exception Safety
1537 Strong guarantee.
1538 Calls to allocate may throw.
1539 Exceptions thrown on invalid input.
1540
1541 @throw system_error
1542 `s` contains an invalid percent-encoding.
1543
1544 @param s The string to set.
1545 @return `*this`
1546
1547 @par BNF
1548 @code
1549 reg-name = *( unreserved / pct-encoded / "-" / ".")
1550 @endcode
1551
1552 @par Specification
1553 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1554 3.2.2. Host (rfc3986)</a>
1555
1556 @see
1557 @ref set_encoded_host,
1558 @ref set_encoded_host_address,
1559 @ref set_host,
1560 @ref set_host_address,
1561 @ref set_host_ipv4,
1562 @ref set_host_ipv6,
1563 @ref set_host_ipvfuture,
1564 @ref set_host_name.
1565 */
1566 url_base&
1567 set_encoded_host_name(
1568 pct_string_view s);
1569
1570 //--------------------------------------------
1571
1572 /** Set the port
1573
1574 The port is set to the specified integer.
1575
1576 @par Example
1577 @code
1578 assert( url( "http://www.example.com" ).set_port_number( 8080 ).authority().buffer() == "www.example.com:8080" );
1579 @endcode
1580
1581 @par Postconditions
1582 @code
1583 this->has_authority() == true && this->has_port() == true && this->port_number() == n
1584 @endcode
1585
1586 @par Complexity
1587 Linear in `this->size()`.
1588
1589 @par Exception Safety
1590 Strong guarantee.
1591 Calls to allocate may throw.
1592
1593 @param n The port number to set.
1594
1595 @return `*this`
1596
1597 @par BNF
1598 @code
1599 authority = [ userinfo "@" ] host [ ":" port ]
1600
1601 port = *DIGIT
1602 @endcode
1603
1604 @par Specification
1605 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3">
1606 3.2.3. Port (rfc3986)</a>
1607
1608 @see
1609 @ref remove_port,
1610 @ref set_port.
1611 */
1612 url_base&
1613 set_port_number(std::uint16_t n);
1614
1615 /** Set the port
1616
1617 This port is set to the string, which
1618 must contain only digits or be empty.
1619 An empty port string is distinct from
1620 having no port.
1621
1622 @par Example
1623 @code
1624 assert( url( "http://www.example.com" ).set_port( "8080" ).authority().buffer() == "www.example.com:8080" );
1625 @endcode
1626
1627 @par Postconditions
1628 @code
1629 this->has_port() == true && this->port_number() == n && this->port() == std::to_string(n)
1630 @endcode
1631
1632 @par Exception Safety
1633 Strong guarantee.
1634 Calls to allocate may throw.
1635 Exceptions thrown on invalid input.
1636
1637 @throw system_error
1638 `s` does not contain a valid port.
1639
1640 @param s The port string to set.
1641 @return `*this`
1642
1643 @par BNF
1644 @code
1645 port = *DIGIT
1646 @endcode
1647
1648 @par Specification
1649 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3">
1650 3.2.3. Port (rfc3986)</a>
1651
1652 @see
1653 @ref remove_port,
1654 @ref set_port.
1655 */
1656 url_base&
1657 set_port(core::string_view s);
1658
1659 /** Remove the port
1660
1661 If a port exists, it is removed. The rest
1662 of the authority is unchanged.
1663
1664 @return `*this`
1665
1666 @par Example
1667 @code
1668 assert( url( "http://www.example.com:80" ).remove_port().authority().buffer() == "www.example.com" );
1669 @endcode
1670
1671 @par Postconditions
1672 @code
1673 this->has_port() == false && this->port_number() == 0 && this->port() == ""
1674 @endcode
1675
1676 @par Complexity
1677 Linear in `this->size()`.
1678
1679 @par Exception Safety
1680 Throws nothing.
1681
1682 @par BNF
1683 @code
1684 authority = [ userinfo "@" ] host [ ":" port ]
1685
1686 port = *DIGIT
1687 @endcode
1688
1689 @par Specification
1690 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3">
1691 3.2.3. Port (rfc3986)</a>
1692
1693 @see
1694 @ref set_port.
1695 */
1696 url_base&
1697 remove_port() noexcept;
1698
1699 //--------------------------------------------
1700 //
1701 // Path
1702 //
1703 //--------------------------------------------
1704
1705 /** Set if the path is absolute
1706
1707 This function adjusts the path to make
1708 it absolute or not, depending on the
1709 parameter.
1710
1711 @note
1712 If an authority is present, the path
1713 is always absolute. In this case, the
1714 function has no effect.
1715
1716 @par Example
1717 @code
1718 url u( "path/to/file.txt" );
1719 assert( u.set_path_absolute( true ) );
1720 assert( u.buffer() == "/path/to/file.txt" );
1721 @endcode
1722
1723 @par Postconditions
1724 @code
1725 this->is_path_absolute() == true && this->encoded_path().front() == '/'
1726 @endcode
1727
1728 @param absolute If `true`, the path is made absolute.
1729
1730 @return true on success.
1731
1732 @par Complexity
1733 Linear in `this->size()`.
1734
1735 @par BNF
1736 @code
1737 path = path-abempty ; begins with "/" or is empty
1738 / path-absolute ; begins with "/" but not "//"
1739 / path-noscheme ; begins with a non-colon segment
1740 / path-rootless ; begins with a segment
1741 / path-empty ; zero characters
1742
1743 path-abempty = *( "/" segment )
1744 path-absolute = "/" [ segment-nz *( "/" segment ) ]
1745 path-noscheme = segment-nz-nc *( "/" segment )
1746 path-rootless = segment-nz *( "/" segment )
1747 path-empty = 0<pchar>
1748 @endcode
1749
1750 @par Specification
1751 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1752 >3.3. Path (rfc3986)</a>
1753
1754 @see
1755 @ref encoded_segments,
1756 @ref segments,
1757 @ref set_encoded_path,
1758 @ref set_path.
1759 */
1760 bool
1761 set_path_absolute(bool absolute);
1762
1763 /** Set the path.
1764
1765 This function sets the path to the
1766 string, which may be empty.
1767 Reserved characters in the string are
1768 percent-escaped in the result.
1769
1770 @note
1771 The library may adjust the final result
1772 to ensure that no other parts of the URL
1773 are semantically affected.
1774
1775 @note
1776 This function does not encode '/' chars, which
1777 are unreserved for paths but reserved for
1778 path segments. If a path segment should include
1779 encoded '/'s to differentiate it from path separators,
1780 the functions @ref set_encoded_path or @ref segments
1781 should be used instead.
1782
1783 @par Example
1784 @code
1785 url u( "http://www.example.com" );
1786
1787 u.set_path( "path/to/file.txt" );
1788
1789 assert( u.path() == "/path/to/file.txt" );
1790 @endcode
1791
1792 @par Complexity
1793 Linear in `this->size() + s.size()`.
1794
1795 @par Exception Safety
1796 Strong guarantee.
1797 Calls to allocate may throw.
1798
1799 @param s The string to set.
1800 @return `*this`
1801
1802 @par BNF
1803 @code
1804 path = path-abempty ; begins with "/" or is empty
1805 / path-absolute ; begins with "/" but not "//"
1806 / path-noscheme ; begins with a non-colon segment
1807 / path-rootless ; begins with a segment
1808 / path-empty ; zero characters
1809
1810 path-abempty = *( "/" segment )
1811 path-absolute = "/" [ segment-nz *( "/" segment ) ]
1812 path-noscheme = segment-nz-nc *( "/" segment )
1813 path-rootless = segment-nz *( "/" segment )
1814 path-empty = 0<pchar>
1815 @endcode
1816
1817 @par Specification
1818 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1819 >3.3. Path (rfc3986)</a>
1820
1821 @see
1822 @ref encoded_segments,
1823 @ref segments,
1824 @ref set_encoded_path,
1825 @ref set_path_absolute.
1826 */
1827 url_base&
1828 set_path(
1829 core::string_view s);
1830
1831 /** Set the path.
1832
1833 This function sets the path to the
1834 string, which may contain percent-escapes
1835 and can be empty.
1836 Escapes in the string are preserved,
1837 and reserved characters in the string
1838 are percent-escaped in the result.
1839
1840 @note
1841 The library may adjust the final result
1842 to ensure that no other parts of the url
1843 is semantically affected.
1844
1845 @par Example
1846 @code
1847 url u( "http://www.example.com" );
1848
1849 u.set_encoded_path( "path/to/file.txt" );
1850
1851 assert( u.encoded_path() == "/path/to/file.txt" );
1852 @endcode
1853
1854 @par Complexity
1855 Linear in `this->size() + s.size()`.
1856
1857 @par Exception Safety
1858 Strong guarantee.
1859 Calls to allocate may throw.
1860 Exceptions thrown on invalid input.
1861
1862 @throw system_error
1863 `s` contains an invalid percent-encoding.
1864
1865 @param s The string to set.
1866
1867 @return `*this`
1868
1869 @par BNF
1870 @code
1871 path = path-abempty ; begins with "/" or is empty
1872 / path-absolute ; begins with "/" but not "//"
1873 / path-noscheme ; begins with a non-colon segment
1874 / path-rootless ; begins with a segment
1875 / path-empty ; zero characters
1876
1877 path-abempty = *( "/" segment )
1878 path-absolute = "/" [ segment-nz *( "/" segment ) ]
1879 path-noscheme = segment-nz-nc *( "/" segment )
1880 path-rootless = segment-nz *( "/" segment )
1881 path-empty = 0<pchar>
1882 @endcode
1883
1884 @par Specification
1885 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1886 >3.3. Path (rfc3986)</a>
1887
1888 @see
1889 @ref encoded_segments,
1890 @ref segments,
1891 @ref set_path,
1892 @ref set_path_absolute.
1893 */
1894 url_base&
1895 set_encoded_path(
1896 pct_string_view s);
1897
1898 /** Return the path as a container of segments
1899
1900 This function returns a bidirectional
1901 view of segments over the path.
1902 The returned view references the same
1903 underlying character buffer; ownership
1904 is not transferred.
1905 Any percent-escapes in strings returned
1906 when iterating the view are decoded first.
1907 The container is modifiable; changes
1908 to the container are reflected in the
1909 underlying URL.
1910
1911 @return `*this`
1912
1913 @par Example
1914 @code
1915 url u( "http://example.com/path/to/file.txt" );
1916
1917 segments sv = u.segments();
1918 @endcode
1919
1920 @par Complexity
1921 Constant.
1922
1923 @par Exception Safety
1924 Throws nothing.
1925
1926 @par BNF
1927 @code
1928 path = path-abempty ; begins with "/" or is empty
1929 / path-absolute ; begins with "/" but not "//"
1930 / path-noscheme ; begins with a non-colon segment
1931 / path-rootless ; begins with a segment
1932 / path-empty ; zero characters
1933
1934 path-abempty = *( "/" segment )
1935 path-absolute = "/" [ segment-nz *( "/" segment ) ]
1936 path-noscheme = segment-nz-nc *( "/" segment )
1937 path-rootless = segment-nz *( "/" segment )
1938 path-empty = 0<pchar>
1939 @endcode
1940
1941 @par Specification
1942 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1943 >3.3. Path (rfc3986)</a>
1944
1945 @see
1946 @ref encoded_segments,
1947 @ref set_encoded_path,
1948 @ref set_path,
1949 @ref set_path_absolute.
1950 */
1951 urls::segments_ref
1952 segments() noexcept;
1953
1954 /// @copydoc url_view_base::segments
1955 segments_view
1956 1 segments() const noexcept
1957 {
1958 1 return url_view_base::segments();
1959 }
1960
1961 /** Return the path as a container of segments
1962
1963 This function returns a bidirectional
1964 view of segments over the path.
1965 The returned view references the same
1966 underlying character buffer; ownership
1967 is not transferred.
1968 Strings returned when iterating the
1969 range may contain percent escapes.
1970 The container is modifiable; changes
1971 to the container are reflected in the
1972 underlying URL.
1973
1974 @return `*this`
1975
1976 @par Example
1977 @code
1978 url u( "http://example.com/path/to/file.txt" );
1979
1980 segments_encoded_ref sv = u.encoded_segments();
1981 @endcode
1982
1983 @par Complexity
1984 Constant.
1985
1986 @par Exception Safety
1987 Throws nothing.
1988
1989 @par BNF
1990 @code
1991 path = path-abempty ; begins with "/" or is empty
1992 / path-absolute ; begins with "/" but not "//"
1993 / path-noscheme ; begins with a non-colon segment
1994 / path-rootless ; begins with a segment
1995 / path-empty ; zero characters
1996
1997 path-abempty = *( "/" segment )
1998 path-absolute = "/" [ segment-nz *( "/" segment ) ]
1999 path-noscheme = segment-nz-nc *( "/" segment )
2000 path-rootless = segment-nz *( "/" segment )
2001 path-empty = 0<pchar>
2002 @endcode
2003
2004 @par Specification
2005 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
2006 >3.3. Path (rfc3986)</a>
2007
2008 @see
2009 @ref encoded_segments,
2010 @ref set_encoded_path,
2011 @ref set_path,
2012 @ref set_path_absolute.
2013 */
2014 segments_encoded_ref
2015 encoded_segments() noexcept;
2016
2017 /// @copydoc url_view_base::encoded_segments
2018 segments_encoded_view
2019 1 encoded_segments() const noexcept
2020 {
2021 1 return url_view_base::encoded_segments();
2022 }
2023
2024 //--------------------------------------------
2025 //
2026 // Query
2027 //
2028 //--------------------------------------------
2029
2030 /** Set the query
2031
2032 This sets the query to the string, which
2033 can be empty.
2034 An empty query is distinct from having
2035 no query.
2036 Reserved characters in the string are
2037 percent-escaped in the result.
2038
2039 @par Example
2040 @code
2041 assert( url( "http://example.com" ).set_query( "id=42" ).query() == "id=42" );
2042 @endcode
2043
2044 @par Postconditions
2045 @code
2046 this->has_query() == true && this->query() == s
2047 @endcode
2048
2049 @par Exception Safety
2050 Strong guarantee.
2051 Calls to allocate may throw.
2052
2053 @param s The string to set.
2054 @return `*this`
2055
2056 @par BNF
2057 @code
2058 query = *( pchar / "/" / "?" )
2059
2060 query-param = key [ "=" value ]
2061 query-params = [ query-param ] *( "&" query-param )
2062 @endcode
2063
2064 @par Specification
2065 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2066 >3.4. Query (rfc3986)</a>
2067 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2068 >Query string (Wikipedia)</a>
2069
2070 @see
2071 @ref encoded_params,
2072 @ref params,
2073 @ref remove_query,
2074 @ref set_encoded_query.
2075 */
2076 url_base&
2077 set_query(
2078 core::string_view s);
2079
2080 /** Set the query
2081
2082 This sets the query to the string, which
2083 may contain percent-escapes and can be
2084 empty.
2085 An empty query is distinct from having
2086 no query.
2087 Escapes in the string are preserved,
2088 and reserved characters in the string
2089 are percent-escaped in the result.
2090
2091 @par Example
2092 @code
2093 assert( url( "http://example.com" ).set_encoded_query( "id=42" ).encoded_query() == "id=42" );
2094 @endcode
2095
2096 @par Postconditions
2097 @code
2098 this->has_query() == true && this->query() == decode_view( s );
2099 @endcode
2100
2101 @par Exception Safety
2102 Strong guarantee.
2103 Calls to allocate may throw.
2104 Exceptions thrown on invalid input.
2105
2106 @param s The string to set.
2107 @return `*this`
2108
2109 @throws system_error
2110 `s` contains an invalid percent-encoding.
2111
2112 @par BNF
2113 @code
2114 query = *( pchar / "/" / "?" )
2115
2116 query-param = key [ "=" value ]
2117 query-params = [ query-param ] *( "&" query-param )
2118 @endcode
2119
2120 @par Specification
2121 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2122 >3.4. Query (rfc3986)</a>
2123 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2124 >Query string (Wikipedia)</a>
2125
2126 @see
2127 @ref encoded_params,
2128 @ref params,
2129 @ref remove_query,
2130 @ref set_query.
2131 */
2132 url_base&
2133 set_encoded_query(
2134 pct_string_view s);
2135
2136 /** Return the query as a container of parameters
2137
2138 This function returns a bidirectional
2139 view of key/value pairs over the query.
2140 The returned view references the same
2141 underlying character buffer; ownership
2142 is not transferred.
2143 Any percent-escapes in strings returned
2144 when iterating the view are decoded first.
2145 The container is modifiable; changes
2146 to the container are reflected in the
2147 underlying URL.
2148
2149 @return `*this`
2150
2151 @par Example
2152 @code
2153 params_ref pv = url( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).params();
2154 @endcode
2155
2156 @par Complexity
2157 Constant.
2158
2159 @par Exception Safety
2160 Throws nothing.
2161
2162 @par BNF
2163 @code
2164 query = *( pchar / "/" / "?" )
2165
2166 query-param = key [ "=" value ]
2167 query-params = [ query-param ] *( "&" query-param )
2168 @endcode
2169
2170 @par Specification
2171 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2172 >3.4. Query (rfc3986)</a>
2173 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2174 >Query string (Wikipedia)</a>
2175
2176 @see
2177 @ref encoded_params,
2178 @ref remove_query,
2179 @ref set_encoded_query,
2180 @ref set_query.
2181 */
2182 params_ref
2183 params() noexcept;
2184
2185 /// @copydoc url_view_base::params
2186 params_view
2187 1 params() const noexcept
2188 {
2189 1 return url_view_base::params();
2190 }
2191
2192 /** Return the query as a container of parameters
2193
2194 This function returns a bidirectional
2195 view of key/value pairs over the query.
2196 The returned view references the same
2197 underlying character buffer; ownership
2198 is not transferred.
2199 Any percent-escapes in strings returned
2200 when iterating the view are decoded first.
2201 The container is modifiable; changes
2202 to the container are reflected in the
2203 underlying URL.
2204
2205 @par Example
2206 @code
2207 encoding_opts opt;
2208 opt.space_as_plus = true;
2209 params_ref pv = url( "/sql?id=42&name=jane+doe&page+size=20" ).params(opt);
2210 @endcode
2211
2212 @par Complexity
2213 Constant.
2214
2215 @par Exception Safety
2216 Throws nothing.
2217
2218 @param opt The options for decoding. If
2219 this parameter is omitted, the `space_as_plus`
2220 is used.
2221
2222 @return A range of references to the parameters.
2223
2224 @par BNF
2225 @code
2226 query = *( pchar / "/" / "?" )
2227
2228 query-param = key [ "=" value ]
2229 query-params = [ query-param ] *( "&" query-param )
2230 @endcode
2231
2232 @par Specification
2233 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2234 >3.4. Query (rfc3986)</a>
2235 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2236 >Query string (Wikipedia)</a>
2237
2238 @see
2239 @ref encoded_params,
2240 @ref remove_query,
2241 @ref set_encoded_query,
2242 @ref set_query.
2243 */
2244 params_ref
2245 params(encoding_opts opt) noexcept;
2246
2247 /// @copydoc url_view_base::encoded_params
2248 params_encoded_view
2249 1 encoded_params() const noexcept
2250 {
2251 1 return url_view_base::encoded_params();
2252 }
2253
2254 /** Return the query as a container of parameters
2255
2256 This function returns a bidirectional
2257 view of key/value pairs over the query.
2258 The returned view references the same
2259 underlying character buffer; ownership
2260 is not transferred.
2261 Strings returned when iterating the
2262 range may contain percent escapes.
2263 The container is modifiable; changes
2264 to the container are reflected in the
2265 underlying URL.
2266
2267 @return `*this`
2268
2269 @par Example
2270 @code
2271 params_encoded_ref pv = url( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).encoded_params();
2272 @endcode
2273
2274 @par Complexity
2275 Constant.
2276
2277 @par Exception Safety
2278 Throws nothing.
2279
2280 @par BNF
2281 @code
2282 query = *( pchar / "/" / "?" )
2283
2284 query-param = key [ "=" value ]
2285 query-params = [ query-param ] *( "&" query-param )
2286 @endcode
2287
2288 @par Specification
2289 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2290 >3.4. Query (rfc3986)</a>
2291 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2292 >Query string (Wikipedia)</a>
2293
2294 @see
2295 @ref params,
2296 @ref remove_query,
2297 @ref set_encoded_query,
2298 @ref set_query.
2299 */
2300 params_encoded_ref
2301 encoded_params() noexcept;
2302
2303 /** Set the query params
2304
2305 This sets the query params to the list
2306 of param_view, which can be empty.
2307
2308 An empty list of params is distinct from
2309 having no params.
2310
2311 Reserved characters in the string are
2312 percent-escaped in the result.
2313
2314 @par Example
2315 @code
2316 assert( url( "http://example.com" ).set_params( {"id", "42"} ).query() == "id=42" );
2317 @endcode
2318
2319 @par Postconditions
2320 @code
2321 this->has_query() == true
2322 @endcode
2323
2324 @par Exception Safety
2325 Strong guarantee.
2326 Calls to allocate may throw.
2327
2328 @par Complexity
2329 Linear.
2330
2331 @param ps The params to set.
2332 @param opts The options for encoding.
2333 @return `*this`
2334
2335 @par BNF
2336 @code
2337 query = *( pchar / "/" / "?" )
2338
2339 query-param = key [ "=" value ]
2340 query-params = [ query-param ] *( "&" query-param )
2341 @endcode
2342
2343 @par Specification
2344 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4
2345 >3.4. Query (rfc3986)</a>
2346 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2347 >Query string (Wikipedia)</a>
2348
2349 @see
2350 @ref encoded_params,
2351 @ref remove_query,
2352 @ref set_encoded_query,
2353 @ref set_query.
2354 */
2355 url_base&
2356 set_params(
2357 std::initializer_list<param_view> ps,
2358 encoding_opts opts = {}) noexcept;
2359
2360 /** Set the query params
2361
2362 This sets the query params to the elements
2363 in the list, which may contain
2364 percent-escapes and can be empty.
2365
2366 An empty list of params is distinct from
2367 having no query.
2368
2369 Escapes in the string are preserved,
2370 and reserved characters in the string
2371 are percent-escaped in the result.
2372
2373 @par Example
2374 @code
2375 assert( url( "http://example.com" ).set_encoded_params( {"id", "42"} ).encoded_query() == "id=42" );
2376 @endcode
2377
2378 @par Postconditions
2379 @code
2380 this->has_query() == true
2381 @endcode
2382
2383 @par Complexity
2384 Linear.
2385
2386 @par Exception Safety
2387 Strong guarantee.
2388 Calls to allocate may throw.
2389 Exceptions thrown on invalid input.
2390
2391 @param ps The params to set.
2392
2393 @return `*this`
2394
2395 @throws system_error
2396 some element in `ps` contains an invalid percent-encoding.
2397
2398 @par BNF
2399 @code
2400 query = *( pchar / "/" / "?" )
2401
2402 query-param = key [ "=" value ]
2403 query-params = [ query-param ] *( "&" query-param )
2404 @endcode
2405
2406 @par Specification
2407 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2408 >3.4. Query (rfc3986)</a>
2409 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2410 >Query string (Wikipedia)</a>
2411
2412 @see
2413 @ref set_params,
2414 @ref params,
2415 @ref remove_query,
2416 @ref set_encoded_query,
2417 @ref set_query.
2418 */
2419 url_base&
2420 set_encoded_params( std::initializer_list< param_pct_view > ps ) noexcept;
2421
2422 /** Remove the query
2423
2424 If a query is present, it is removed.
2425 An empty query is distinct from having
2426 no query.
2427
2428 @return `*this`
2429
2430 @par Example
2431 @code
2432 assert( url( "http://www.example.com?id=42" ).remove_query().buffer() == "http://www.example.com" );
2433 @endcode
2434
2435 @par Postconditions
2436 @code
2437 this->has_query() == false && this->params().empty()
2438 @endcode
2439
2440 @par Exception Safety
2441 Throws nothing.
2442
2443 @par BNF
2444 @code
2445 query = *( pchar / "/" / "?" )
2446
2447 query-param = key [ "=" value ]
2448 query-params = [ query-param ] *( "&" query-param )
2449 @endcode
2450
2451 @par Specification
2452 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2453 >3.4. Query (rfc3986)</a>
2454 @li <a href="https://en.wikipedia.org/wiki/Query_string"
2455 >Query string (Wikipedia)</a>
2456
2457 @see
2458 @ref encoded_params,
2459 @ref params,
2460 @ref set_encoded_query,
2461 @ref set_query.
2462 */
2463 url_base&
2464 remove_query() noexcept;
2465
2466 //--------------------------------------------
2467 //
2468 // Fragment
2469 //
2470 //--------------------------------------------
2471
2472 /** Remove the fragment
2473
2474 This function removes the fragment.
2475 An empty fragment is distinct from
2476 having no fragment.
2477
2478 @return `*this`
2479
2480 @par Example
2481 @code
2482 assert( url( "?first=john&last=doe#anchor" ).remove_fragment().buffer() == "?first=john&last=doe" );
2483 @endcode
2484
2485 @par Postconditions
2486 @code
2487 this->has_fragment() == false && this->encoded_fragment() == ""
2488 @endcode
2489
2490 @par Complexity
2491 Constant.
2492
2493 @par Exception Safety
2494 Throws nothing.
2495
2496 @par BNF
2497 @code
2498 fragment = *( pchar / "/" / "?" )
2499 @endcode
2500
2501 @par Specification
2502 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.5"
2503 >3.5. Fragment</a>
2504
2505 @see
2506 @ref remove_fragment,
2507 @ref set_encoded_fragment,
2508 @ref set_fragment.
2509 */
2510 url_base&
2511 remove_fragment() noexcept;
2512
2513 /** Set the fragment.
2514
2515 This function sets the fragment to the
2516 specified string, which may be empty.
2517 An empty fragment is distinct from
2518 having no fragment.
2519 Reserved characters in the string are
2520 percent-escaped in the result.
2521
2522 @par Example
2523 @code
2524 assert( url("?first=john&last=doe" ).set_encoded_fragment( "john doe" ).encoded_fragment() == "john%20doe" );
2525 @endcode
2526
2527 @par Postconditions
2528 @code
2529 this->has_fragment() == true && this->fragment() == s
2530 @endcode
2531
2532 @par Complexity
2533 Linear in `this->size() + s.size()`.
2534
2535 @par Exception Safety
2536 Strong guarantee.
2537 Calls to allocate may throw.
2538
2539 @param s The string to set.
2540
2541 @return `*this`
2542
2543 @par BNF
2544 @code
2545 fragment = *( pchar / "/" / "?" )
2546 @endcode
2547
2548 @par Specification
2549 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.5"
2550 >3.5. Fragment</a>
2551
2552 @see
2553 @ref remove_fragment,
2554 @ref set_encoded_fragment.
2555 */
2556 url_base&
2557 set_fragment(
2558 core::string_view s);
2559
2560 /** Set the fragment.
2561
2562 This function sets the fragment to the
2563 specified string, which may contain
2564 percent-escapes and which may be empty.
2565 An empty fragment is distinct from
2566 having no fragment.
2567 Escapes in the string are preserved,
2568 and reserved characters in the string
2569 are percent-escaped in the result.
2570
2571 @return `*this`
2572
2573 @par Example
2574 @code
2575 assert( url("?first=john&last=doe" ).set_encoded_fragment( "john%2Ddoe" ).fragment() == "john-doe" );
2576 @endcode
2577
2578 @par Postconditions
2579 @code
2580 this->has_fragment() == true && this->fragment() == decode_view( s )
2581 @endcode
2582
2583 @par Complexity
2584 Linear in `this->size() + s.size()`.
2585
2586 @par Exception Safety
2587 Strong guarantee.
2588 Calls to allocate may throw.
2589 Exceptions thrown on invalid input.
2590
2591 @throw system_error
2592 `s` contains an invalid percent-encoding.
2593
2594 @param s The string to set.
2595
2596 @return `*this`
2597
2598 @par BNF
2599 @code
2600 fragment = *( pchar / "/" / "?" )
2601 @endcode
2602
2603 @par Specification
2604 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.5"
2605 >3.5. Fragment</a>
2606
2607 @see
2608 @ref remove_fragment,
2609 @ref set_fragment.
2610 */
2611 url_base&
2612 set_encoded_fragment(
2613 pct_string_view s);
2614
2615 //--------------------------------------------
2616 //
2617 // Compound Fields
2618 //
2619 //--------------------------------------------
2620
2621 /** Remove the origin component
2622
2623 This function removes the origin, which
2624 consists of the scheme and authority.
2625
2626 @return `*this`
2627
2628 @par Example
2629 @code
2630 assert( url( "http://www.example.com/index.htm" ).remove_origin().buffer() == "/index.htm" );
2631 @endcode
2632
2633 @par Postconditions
2634 @code
2635 this->scheme_id() == scheme::none && this->has_authority() == false
2636 @endcode
2637
2638 @par Complexity
2639 Linear in `this->size()`.
2640
2641 @par Exception Safety
2642 Throws nothing.
2643 */
2644 url_base&
2645 remove_origin();
2646
2647 //--------------------------------------------
2648 //
2649 // Normalization
2650 //
2651 //--------------------------------------------
2652
2653 /** Normalize the URL components
2654
2655 Applies Syntax-based normalization to
2656 all components of the URL.
2657
2658 The scheme is normalized to lowercase.
2659
2660 @code
2661 assert( url( "HTTP://www.example.com" ).normalize().buffer() == "http://www.example.com" );
2662 @endcode
2663
2664 The host is normalized to lowercase.
2665 Percent-encoding triplets are normalized
2666 to uppercase letters. Percent-encoded
2667 octets that correspond to unreserved
2668 characters are decoded.
2669
2670 @code
2671 assert( url( "http://www.Example.com" ).normalize().buffer() == "http://www.example.com" );
2672 assert( url( "http://www.%65xample.com" ).normalize().buffer() == "http://www.example.com" );
2673 @endcode
2674
2675 Percent-encoding triplets in the path
2676 are normalized to uppercase letters.
2677 Percent-encoded octets that correspond
2678 to unreserved characters are decoded.
2679 Redundant path-segments "." and ".."
2680 are removed.
2681
2682 @code
2683 assert( url( "http://www.example.com/a/b/../c" ).normalize().buffer() == "http://www.example.com/a/c" );
2684 assert( url( "http://www.example.com/a/./b" ).normalize().buffer() == "http://www.example.com/a/b" );
2685 assert( url( "http://www.example.com/%63ss" ).normalize().buffer() == "http://www.example.com/css" );
2686 @endcode
2687
2688 Percent-encoding triplets in the query
2689 are normalized to uppercase letters.
2690 Percent-encoded octets that correspond
2691 to unreserved characters are decoded.
2692
2693 @code
2694 assert( url( "http://www.example.com?a=%62" ).normalize().buffer() == "http://www.example.com?a=b" );
2695 @endcode
2696
2697 Percent-encoding triplets in the fragment
2698 are normalized to uppercase letters.
2699 Percent-encoded octets that correspond
2700 to unreserved characters are decoded.
2701
2702 @code
2703 assert( url( "http://www.example.com#%61bc" ).normalize().buffer() == "http://www.example.com#abc" );
2704 @endcode
2705
2706 Applying normalization to a URL with all
2707 components percent-encoded:
2708
2709 @code
2710 assert( url( "HTTP://www.Example.com/%70ath?%71uery#%66rag" ).normalize().buffer() == "http://www.example.com/path?query#frag" );
2711 @endcode
2712
2713 @return `*this`
2714
2715 @par Exception Safety
2716 Strong guarantee.
2717 Calls to allocate may throw.
2718
2719 @par Specification
2720 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2721 >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2722
2723 @see
2724 @ref normalize_scheme,
2725 @ref normalize_authority,
2726 @ref normalize_path,
2727 @ref normalize_query,
2728 @ref normalize_fragment
2729
2730 */
2731 url_base&
2732 normalize();
2733
2734 /** Normalize the URL scheme
2735
2736 Applies Syntax-based normalization to the
2737 URL scheme.
2738
2739 The scheme is normalized to lowercase.
2740
2741 @code
2742 assert( url( "HTTP://www.example.com" ).normalize_scheme().buffer() == "http://www.example.com" );
2743 @endcode
2744
2745 @return `*this`
2746
2747 @par Exception Safety
2748 Strong guarantee.
2749 Calls to allocate may throw.
2750
2751 @par Specification
2752 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2753 >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2754
2755 */
2756 url_base&
2757 normalize_scheme();
2758
2759 /** Normalize the URL authority
2760
2761 Applies Syntax-based normalization to the
2762 URL authority.
2763
2764 The host is normalized to lowercase.
2765 Percent-encoding triplets are normalized
2766 to uppercase letters. Percent-encoded
2767 octets that correspond to unreserved
2768 characters are decoded.
2769
2770 @code
2771 assert( url( "http://www.Example.com" ).normalize_authority().buffer() == "http://www.example.com" );
2772 assert( url( "http://www.%65xample.com" ).normalize_authority().buffer() == "http://www.example.com" );
2773 @endcode
2774
2775 @return `*this`
2776
2777 @par Exception Safety
2778 Strong guarantee.
2779 Calls to allocate may throw.
2780
2781 @par Specification
2782 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2783 >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2784
2785 */
2786 url_base&
2787 normalize_authority();
2788
2789 /** Normalize the URL path
2790
2791 Applies Syntax-based normalization to the
2792 URL path.
2793
2794 Percent-encoding triplets are normalized
2795 to uppercase letters. Percent-encoded
2796 octets that correspond to unreserved
2797 characters are decoded. Redundant
2798 path-segments "." and ".." are removed.
2799
2800 @code
2801 assert( url( "http://www.example.com/a/b/../c" ).normalize_path().buffer() == "http://www.example.com/a/c" );
2802 assert( url( "http://www.example.com/a/./b" ).normalize_path().buffer() == "http://www.example.com/a/b" );
2803 assert( url( "http://www.example.com/%63ss" ).normalize_path().buffer() == "http://www.example.com/css" );
2804 @endcode
2805
2806 @return `*this`
2807
2808 @par Exception Safety
2809 Strong guarantee.
2810 Calls to allocate may throw.
2811
2812 @par Specification
2813 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2814 >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2815
2816 */
2817 url_base&
2818 normalize_path();
2819
2820 /** Normalize the URL query
2821
2822 Applies Syntax-based normalization to the
2823 URL query.
2824
2825 Percent-encoding triplets are normalized
2826 to uppercase letters. Percent-encoded
2827 octets that correspond to unreserved
2828 characters are decoded.
2829
2830 @code
2831 assert( url( "http://www.example.com?a=%62" ).normalize_query().buffer() == "http://www.example.com?a=b" );
2832 @endcode
2833
2834 @return `*this`
2835
2836 @par Exception Safety
2837 Strong guarantee.
2838 Calls to allocate may throw.
2839
2840 @par Specification
2841 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2842 >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2843
2844 */
2845 url_base&
2846 normalize_query();
2847
2848 /** Normalize the URL fragment
2849
2850 Applies Syntax-based normalization to the
2851 URL fragment.
2852
2853 Percent-encoding triplets are normalized
2854 to uppercase letters. Percent-encoded
2855 octets that correspond to unreserved
2856 characters are decoded.
2857
2858 @code
2859 assert( url( "http://www.example.com#%61bc" ).normalize_fragment().buffer() == "http://www.example.com#abc" );
2860 @endcode
2861
2862 @return `*this`
2863
2864 @par Exception Safety
2865 Strong guarantee.
2866 Calls to allocate may throw.
2867
2868 @par Specification
2869 @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2870 >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2871
2872 */
2873 url_base&
2874 normalize_fragment();
2875
2876 //
2877 // (end of fluent API)
2878 //
2879 //--------------------------------------------
2880
2881 //--------------------------------------------
2882 //
2883 // Resolution
2884 //
2885 //--------------------------------------------
2886
2887 /** Resolve a URL reference against this base URL
2888
2889 This function attempts to resolve a URL
2890 reference `ref` against this base URL
2891 in a manner similar to that of a web browser
2892 resolving an anchor tag.
2893
2894 This URL must satisfy the <em>URI</em>
2895 grammar. In other words, it must contain
2896 a scheme.
2897
2898 Relative references are only usable when
2899 in the context of a base absolute URI.
2900 This process of resolving a relative
2901 <em>reference</em> within the context of
2902 a <em>base</em> URI is defined in detail
2903 in rfc3986 (see below).
2904
2905 The resolution process works as if the
2906 relative reference is appended to the base
2907 URI and the result is normalized.
2908
2909 Given the input base URL, this function
2910 resolves the relative reference
2911 as if performing the following steps:
2912
2913 @li Ensure the base URI has at least a scheme
2914 @li Normalizing the reference path
2915 @li Merge base and reference paths
2916 @li Normalize the merged path
2917
2918 This function places the result of the
2919 resolution into this URL in place.
2920
2921 If an error occurs, the contents of
2922 this URL are unspecified and a `boost::system::result`
2923 with an `system::error_code` is returned.
2924
2925 @note Abnormal hrefs where the number of ".."
2926 segments exceeds the number of segments in
2927 the base path are handled by including the
2928 unmatched ".." segments in the result, as described
2929 in <a href="https://www.rfc-editor.org/errata/eid4547"
2930 >Errata 4547</a>.
2931
2932 @par Example
2933 @code
2934 url base1( "/one/two/three" );
2935 base1.resolve("four");
2936 assert( base1.buffer() == "/one/two/four" );
2937
2938 url base2( "http://example.com/" )
2939 base2.resolve("/one");
2940 assert( base2.buffer() == "http://example.com/one" );
2941
2942 url base3( "http://example.com/one" );
2943 base3.resolve("/two");
2944 assert( base3.buffer() == "http://example.com/two" );
2945
2946 url base4( "http://a/b/c/d;p?q" );
2947 base4.resolve("g#s");
2948 assert( base4.buffer() == "http://a/b/c/g#s" );
2949 @endcode
2950
2951 @par BNF
2952 @code
2953 absolute-URI = scheme ":" hier-part [ "?" query ]
2954 @endcode
2955
2956 @par Exception Safety
2957 Basic guarantee.
2958 Calls to allocate may throw.
2959
2960 @return An empty `boost::system::result` upon success,
2961 otherwise an error code if `!base.has_scheme()`.
2962
2963 @param ref The URL reference to resolve.
2964
2965 @par Specification
2966 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-5"
2967 >5. Reference Resolution (rfc3986)</a>
2968
2969 @see
2970 @ref url,
2971 @ref url_view.
2972 */
2973 system::result<void>
2974 resolve(
2975 url_view_base const& ref);
2976
2977 friend
2978 system::result<void>
2979 resolve(
2980 url_view_base const& base,
2981 url_view_base const& ref,
2982 url_base& dest);
2983
2984 private:
2985 //--------------------------------------------
2986 //
2987 // implementation
2988 //
2989 //--------------------------------------------
2990
2991 void check_invariants() const noexcept;
2992
2993 char* resize_impl(int, std::size_t, op_t&);
2994 char* resize_impl(int, int, std::size_t, op_t&);
2995 char* shrink_impl(int, std::size_t, op_t&);
2996 char* shrink_impl(int, int, std::size_t, op_t&);
2997
2998 void set_scheme_impl(core::string_view, urls::scheme);
2999 char* set_user_impl(std::size_t n, op_t& op);
3000 char* set_password_impl(std::size_t n, op_t& op);
3001 char* set_userinfo_impl(std::size_t n, op_t& op);
3002 char* set_host_impl(std::size_t n, op_t& op);
3003 char* set_port_impl(std::size_t n, op_t& op);
3004 char* set_path_impl(std::size_t n, op_t& op);
3005
3006 void
3007 set_host_ipv6_and_zone_id(
3008 ipv6_address const& addr,
3009 core::string_view zone_id);
3010
3011 void
3012 set_host_ipv6_and_encoded_zone_id(
3013 ipv6_address const& addr,
3014 pct_string_view zone_id);
3015
3016 core::string_view
3017 first_segment() const noexcept;
3018
3019 detail::segments_iter_impl
3020 edit_segments(
3021 detail::segments_iter_impl const&,
3022 detail::segments_iter_impl const&,
3023 detail::any_segments_iter&& it0,
3024 int absolute = -1);
3025
3026 auto
3027 edit_params(
3028 detail::params_iter_impl const&,
3029 detail::params_iter_impl const&,
3030 detail::any_params_iter&&) ->
3031 detail::params_iter_impl;
3032
3033 // Decode any unnecessary percent-escapes
3034 // and ensures hexadecimals are uppercase.
3035 // The encoding of ignored characters is
3036 // preserved.
3037 template
3038 <class AllowedCharSet,
3039 class IgnoredCharSet>
3040 void
3041 normalize_octets_impl(
3042 int,
3043 AllowedCharSet const& allowed,
3044 IgnoredCharSet const& ignored,
3045 op_t&) noexcept;
3046
3047 template<class CharSet>
3048 void
3049 normalize_octets_impl(
3050 int,
3051 CharSet const& allowed,
3052 op_t&) noexcept;
3053
3054 void decoded_to_lower_impl(int id) noexcept;
3055 void to_lower_impl(int id) noexcept;
3056 };
3057
3058 //------------------------------------------------
3059
3060 /** Resolve a URL reference against a base URL
3061
3062 This function attempts to resolve a URL
3063 reference `ref` against the base URL `base`
3064 in a manner similar to that of a web browser
3065 resolving an anchor tag.
3066
3067 The base URL must satisfy the <em>URI</em>
3068 grammar. In other words, it must contain
3069 a scheme.
3070
3071 Relative references are only usable when
3072 in the context of a base absolute URI.
3073 This process of resolving a relative
3074 <em>reference</em> within the context of
3075 a <em>base</em> URI is defined in detail
3076 in rfc3986 (see below).
3077
3078 The resolution process works as if the
3079 relative reference is appended to the base
3080 URI and the result is normalized.
3081
3082 Given the input base URL, this function
3083 resolves the relative reference
3084 as if performing the following steps:
3085
3086 @li Ensure the base URI has at least a scheme
3087 @li Normalizing the reference path
3088 @li Merge base and reference paths
3089 @li Normalize the merged path
3090
3091 This function places the result of the
3092 resolution into `dest`, which can be
3093 any of the url containers that inherit
3094 from @ref url_base.
3095
3096 If an error occurs, the contents of
3097 `dest` is unspecified and `ec` is set.
3098
3099 @note Abnormal hrefs where the number of ".."
3100 segments exceeds the number of segments in
3101 the base path are handled by including the
3102 unmatched ".." segments in the result, as described
3103 in <a href="https://www.rfc-editor.org/errata/eid4547"
3104 >Errata 4547</a>.
3105
3106 @par Example
3107 @code
3108 url dest;
3109 system::error_code ec;
3110
3111 resolve("/one/two/three", "four", dest, ec);
3112 assert( dest.str() == "/one/two/four" );
3113
3114 resolve("http://example.com/", "/one", dest, ec);
3115 assert( dest.str() == "http://example.com/one" );
3116
3117 resolve("http://example.com/one", "/two", dest, ec);
3118 assert( dest.str() == "http://example.com/two" );
3119
3120 resolve("http://a/b/c/d;p?q", "g#s", dest, ec);
3121 assert( dest.str() == "http://a/b/c/g#s" );
3122 @endcode
3123
3124 @par BNF
3125 @code
3126 absolute-URI = scheme ":" hier-part [ "?" query ]
3127 @endcode
3128
3129 @par Exception Safety
3130 Basic guarantee.
3131 Calls to allocate may throw.
3132
3133 @return An empty `boost::system::result` upon success,
3134 otherwise an error code if `!base.has_scheme()`.
3135
3136 @param base The base URL to resolve against.
3137
3138 @param ref The URL reference to resolve.
3139
3140 @param dest The container where the result
3141 is written, upon success.
3142
3143 @par Specification
3144 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-5"
3145 >5. Reference Resolution (rfc3986)</a>
3146
3147 @see
3148 @ref url,
3149 @ref url_view.
3150 */
3151 inline
3152 system::result<void>
3153 407 resolve(
3154 url_view_base const& base,
3155 url_view_base const& ref,
3156 url_base& dest)
3157 {
3158
2/2
✓ Branch 0 taken 406 times.
✓ Branch 1 taken 1 time.
407 if (&dest != &base)
3159 406 dest.copy(base);
3160 407 return dest.resolve(ref);
3161 }
3162
3163 } // urls
3164 } // boost
3165
3166 // These are here because of circular references
3167 #include <boost/url/impl/url_base.hpp>
3168 #include <boost/url/impl/params_ref.hpp>
3169 #include <boost/url/impl/params_encoded_ref.hpp>
3170 #include <boost/url/impl/segments_ref.hpp>
3171 #include <boost/url/impl/segments_encoded_ref.hpp>
3172
3173 #endif
3174