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 : #ifndef BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
11 : #define BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
12 :
13 : #include <boost/url/detail/config.hpp>
14 : #include <boost/url/detail/string_view.hpp>
15 : #include <boost/core/detail/string_view.hpp>
16 : #include <cstddef>
17 : #include <iterator>
18 : #include <string>
19 : #include <type_traits>
20 : #include <utility>
21 :
22 : namespace boost {
23 : namespace urls {
24 : namespace grammar {
25 :
26 : /** Common functionality for string views
27 :
28 : This base class is used to provide common
29 : member functions for reference types that
30 : behave like string views. This cannot be
31 : instantiated directly; Instead, derive
32 : from the type and provide constructors
33 : which offer any desired preconditions
34 : and invariants.
35 : */
36 : class string_view_base
37 : {
38 : protected:
39 : /** The referenced character buffer
40 : */
41 : core::string_view s_;
42 :
43 : /** Constructor
44 : */
45 : constexpr
46 : string_view_base(
47 : core::string_view s) noexcept
48 : : s_(s)
49 : {
50 : }
51 :
52 : /** Constructor
53 : */
54 : constexpr
55 33744 : string_view_base(
56 : char const* data,
57 : std::size_t size) noexcept
58 33744 : : s_(data, size)
59 : {
60 33744 : }
61 :
62 : /** Swap
63 : */
64 : // VFALCO No idea why this fails in msvc
65 : /*BOOST_CXX14_CONSTEXPR*/ void swap(
66 : string_view_base& s ) noexcept
67 : {
68 : std::swap(s_, s.s_);
69 : }
70 :
71 : /** Constructor
72 : */
73 16229 : string_view_base() = default;
74 :
75 : /** Constructor
76 : */
77 : string_view_base(
78 : string_view_base const&) = default;
79 :
80 : /** Assignment
81 : */
82 : string_view_base& operator=(
83 : string_view_base const&) = default;
84 :
85 : public:
86 : /// The character traits
87 : typedef std::char_traits<char> traits_type;
88 : /// The value type
89 : typedef char value_type;
90 : /// The pointer type
91 : typedef char* pointer;
92 : /// The const pointer type
93 : typedef char const* const_pointer;
94 : /// The reference type
95 : typedef char& reference;
96 : /// The const reference type
97 : typedef char const& const_reference;
98 : /// The const iterator type
99 : typedef char const* const_iterator;
100 : /// The iterator type
101 : typedef const_iterator iterator;
102 : /// The const reverse iterator type
103 : typedef std::reverse_iterator<
104 : const_iterator> const_reverse_iterator;
105 : /// The reverse iterator type
106 : typedef const_reverse_iterator reverse_iterator;
107 : /// The size type
108 : typedef std::size_t size_type;
109 : /// The difference type
110 : typedef std::ptrdiff_t difference_type;
111 :
112 : /// A constant used to represent "no position"
113 : static constexpr std::size_t npos = core::string_view::npos;
114 :
115 : //--------------------------------------------
116 :
117 : /** Conversion
118 : */
119 11581 : operator
120 : core::string_view() const noexcept
121 : {
122 11581 : return s_;
123 : }
124 :
125 : /** Conversion
126 : */
127 : #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
128 : operator
129 : std::string_view() const noexcept
130 : {
131 : return std::string_view(s_);
132 : }
133 : #endif
134 :
135 : /** Conversion
136 :
137 : Conversion to std::string is explicit
138 : because assigning to string using an
139 : implicit constructor does not preserve
140 : capacity.
141 : */
142 : explicit
143 47 : operator
144 : std::string() const noexcept
145 : {
146 47 : return std::string(s_);
147 : }
148 :
149 : //--------------------------------------------
150 :
151 : // iterator support
152 :
153 : /** Return an iterator to the beginning
154 :
155 : See `core::string_view::begin`
156 : */
157 347 : BOOST_CONSTEXPR const_iterator begin() const noexcept
158 : {
159 347 : return s_.begin();
160 : }
161 :
162 : /** Return an iterator to the end
163 :
164 : See `core::string_view::end`
165 : */
166 347 : BOOST_CONSTEXPR const_iterator end() const noexcept
167 : {
168 347 : return s_.end();
169 : }
170 :
171 : /** Return an iterator to the beginning
172 :
173 : See `core::string_view::cbegin`
174 : */
175 : BOOST_CONSTEXPR const_iterator cbegin() const noexcept
176 : {
177 : return s_.cbegin();
178 : }
179 :
180 : /** Return an iterator to the end
181 :
182 : See `core::string_view::cend`
183 : */
184 : BOOST_CONSTEXPR const_iterator cend() const noexcept
185 : {
186 : return s_.cend();
187 : }
188 :
189 : /** Return a reverse iterator to the end
190 :
191 : See `core::string_view::rbegin`
192 : */
193 : #ifdef __cpp_lib_array_constexpr
194 : constexpr
195 : #endif
196 : const_reverse_iterator rbegin() const noexcept
197 : {
198 : return s_.rbegin();
199 : }
200 :
201 : /** Return a reverse iterator to the beginning
202 :
203 : See `core::string_view::rend`
204 : */
205 : #ifdef __cpp_lib_array_constexpr
206 : constexpr
207 : #endif
208 : const_reverse_iterator rend() const noexcept
209 : {
210 : return s_.rend();
211 : }
212 :
213 : /** Return a reverse iterator to the end
214 :
215 : See `core::string_view::crbegin`
216 : */
217 : #ifdef __cpp_lib_array_constexpr
218 : constexpr
219 : #endif
220 : const_reverse_iterator crbegin() const noexcept
221 : {
222 : return s_.crbegin();
223 : }
224 :
225 : /** Return a reverse iterator to the beginning
226 :
227 : See `core::string_view::crend`
228 : */
229 : #ifdef __cpp_lib_array_constexpr
230 : constexpr
231 : #endif
232 : const_reverse_iterator crend() const noexcept
233 : {
234 : return s_.crend();
235 : }
236 :
237 : // capacity
238 :
239 : /** Return the size
240 :
241 : See `core::string_view::size`
242 : */
243 7094 : BOOST_CONSTEXPR size_type size() const noexcept
244 : {
245 7094 : return s_.size();
246 : }
247 :
248 : /** Return the size
249 :
250 : See `core::string_view::length`
251 : */
252 : BOOST_CONSTEXPR size_type length() const noexcept
253 : {
254 : return s_.length();
255 : }
256 :
257 : /** Return the maximum allowed size
258 :
259 : See `core::string_view::max_size`
260 : */
261 : BOOST_CONSTEXPR size_type max_size() const noexcept
262 : {
263 : return s_.max_size();
264 : }
265 :
266 : /** Return true if the string is empty
267 :
268 : See `core::string_view::size`
269 : */
270 5217 : BOOST_CONSTEXPR bool empty() const noexcept
271 : {
272 5217 : return s_.empty();
273 : }
274 :
275 : // element access
276 :
277 : /** Access a character
278 :
279 : See `core::string_view::operator[]`
280 : */
281 : BOOST_CXX14_CONSTEXPR const_reference
282 1 : operator[]( size_type pos ) const noexcept
283 : {
284 1 : return s_[pos];
285 : }
286 :
287 : /** Access a character
288 :
289 : See `core::string_view::at`
290 : */
291 : BOOST_CXX14_CONSTEXPR const_reference
292 : at( size_type pos ) const
293 : {
294 : return s_.at(pos);
295 : }
296 :
297 : /** Return the first character
298 :
299 : See `core::string_view::front`
300 : */
301 : BOOST_CXX14_CONSTEXPR const_reference
302 79 : front() const noexcept
303 : {
304 79 : return s_.front();
305 : }
306 :
307 : /** Return the last character
308 :
309 : See `core::string_view::back`
310 : */
311 : BOOST_CXX14_CONSTEXPR const_reference
312 16 : back() const noexcept
313 : {
314 16 : return s_.back();
315 : }
316 :
317 : /** Return a pointer to the character buffer
318 :
319 : See `core::string_view::data`
320 : */
321 : BOOST_CONSTEXPR const_pointer
322 587 : data() const noexcept
323 : {
324 587 : return s_.data();
325 : }
326 :
327 : // string operations
328 :
329 : /** Copy the characters to another buffer
330 :
331 : See `core::string_view::copy`
332 : */
333 : BOOST_CXX14_CONSTEXPR size_type copy(
334 : char* s, size_type n, size_type pos = 0 ) const
335 : {
336 : return s_.copy(s, n, pos);
337 : }
338 :
339 : /** Return a view to part of the string
340 :
341 : See `core::string_view::substr`
342 : */
343 9900 : BOOST_CXX14_CONSTEXPR core::string_view substr(
344 : size_type pos = 0, size_type n = core::string_view::npos ) const
345 : {
346 9900 : return s_.substr(pos, n);
347 : }
348 :
349 : // comparison
350 :
351 : /** Return the result of comparing to another string
352 :
353 : See `core::string_view::compare`
354 : */
355 : BOOST_CXX14_CONSTEXPR int
356 : compare( core::string_view str ) const noexcept
357 : {
358 : return s_.compare(str);
359 : }
360 :
361 : /** Return the result of comparing to another string
362 :
363 : See `core::string_view::compare`
364 : */
365 : BOOST_CONSTEXPR int compare(
366 : size_type pos1, size_type n1, core::string_view str ) const
367 : {
368 : return s_.compare(pos1, n1, str);
369 : }
370 :
371 : /** Return the result of comparing to another string
372 :
373 : See `core::string_view::compare`
374 : */
375 : BOOST_CONSTEXPR int compare(
376 : size_type pos1, size_type n1, core::string_view str,
377 : size_type pos2, size_type n2 ) const
378 : {
379 : return s_.compare(pos1, n1, str, pos2, n2);
380 : }
381 :
382 : /** Return the result of comparing to another string
383 :
384 : See `core::string_view::compare`
385 : */
386 : BOOST_CONSTEXPR int compare(
387 : char const* s ) const noexcept
388 : {
389 : return s_.compare(s);
390 : }
391 :
392 : /** Return the result of comparing to another string
393 :
394 : See `core::string_view::compare`
395 : */
396 : BOOST_CONSTEXPR int compare(
397 : size_type pos1, size_type n1, char const* s ) const
398 : {
399 : return s_.compare(pos1, n1, s);
400 : }
401 :
402 : /** Return the result of comparing to another string
403 :
404 : See `core::string_view::compare`
405 : */
406 : BOOST_CONSTEXPR int compare(
407 : size_type pos1, size_type n1,
408 : char const* s, size_type n2 ) const
409 : {
410 : return s_.compare(pos1, n1, s, n2);
411 : }
412 :
413 : // starts_with
414 :
415 : /** Return true if a matching prefix exists
416 :
417 : See `core::string_view::starts_with`
418 : */
419 : BOOST_CONSTEXPR bool starts_with(
420 : core::string_view x ) const noexcept
421 : {
422 : return s_.starts_with(x);
423 : }
424 :
425 : /** Return true if a matching prefix exists
426 :
427 : See `core::string_view::starts_with`
428 : */
429 528 : BOOST_CONSTEXPR bool starts_with(
430 : char x ) const noexcept
431 : {
432 528 : return s_.starts_with(x);
433 : }
434 :
435 : /** Return true if a matching prefix exists
436 :
437 : See `core::string_view::starts_with`
438 : */
439 232 : BOOST_CONSTEXPR bool starts_with(
440 : char const* x ) const noexcept
441 : {
442 232 : return s_.starts_with(x);
443 : }
444 :
445 : // ends_with
446 :
447 : /** Return true if a matching suffix exists
448 :
449 : See `core::string_view::ends_with`
450 : */
451 : BOOST_CONSTEXPR bool ends_with(
452 : core::string_view x ) const noexcept
453 : {
454 : return s_.ends_with(x);
455 : }
456 :
457 : /** Return true if a matching suffix exists
458 :
459 : See `core::string_view::ends_with`
460 : */
461 513 : BOOST_CONSTEXPR bool ends_with(
462 : char x ) const noexcept
463 : {
464 513 : return s_.ends_with(x);
465 : }
466 :
467 : /** Return true if a matching suffix exists
468 :
469 : See `core::string_view::ends_with`
470 : */
471 : BOOST_CONSTEXPR bool ends_with(
472 : char const* x ) const noexcept
473 : {
474 : return s_.ends_with(x);
475 : }
476 :
477 : // find
478 :
479 : /** Return the position of matching characters
480 :
481 : See `core::string_view::find`
482 : */
483 : BOOST_CONSTEXPR size_type find(
484 : core::string_view str, size_type pos = 0 ) const noexcept
485 : {
486 : return s_.find(str, pos);
487 : }
488 :
489 : /** Return the position of matching characters
490 :
491 : See `core::string_view::find`
492 : */
493 10 : BOOST_CXX14_CONSTEXPR size_type find(
494 : char c, size_type pos = 0 ) const noexcept
495 : {
496 10 : return s_.find(c, pos);
497 : }
498 :
499 : /** Return the position of matching characters
500 :
501 : See `core::string_view::find`
502 : */
503 : BOOST_CXX14_CONSTEXPR size_type find(
504 : char const* s, size_type pos, size_type n ) const noexcept
505 : {
506 : return s_.find(s, pos, n);
507 : }
508 :
509 : /** Return the position of matching characters
510 :
511 : See `core::string_view::find`
512 : */
513 : BOOST_CONSTEXPR size_type find(
514 : char const* s, size_type pos = 0 ) const noexcept
515 : {
516 : return s_.find(s, pos);
517 : }
518 :
519 : // rfind
520 :
521 : /** Return the position of matching characters
522 :
523 : See `core::string_view::rfind`
524 : */
525 : BOOST_CONSTEXPR size_type rfind(
526 : core::string_view str, size_type pos = core::string_view::npos ) const noexcept
527 : {
528 : return s_.rfind(str, pos);
529 : }
530 :
531 : /** Return the position of matching characters
532 :
533 : See `core::string_view::rfind`
534 : */
535 : BOOST_CXX14_CONSTEXPR size_type rfind(
536 : char c, size_type pos = core::string_view::npos ) const noexcept
537 : {
538 : return s_.rfind(c, pos);
539 : }
540 :
541 : /** Return the position of matching characters
542 :
543 : See `core::string_view::rfind`
544 : */
545 : BOOST_CXX14_CONSTEXPR size_type rfind(
546 : char const* s, size_type pos, size_type n ) const noexcept
547 : {
548 : return s_.rfind(s, pos, n);
549 : }
550 :
551 : /** Return the position of matching characters
552 :
553 : See `core::string_view::rfind`
554 : */
555 : BOOST_CONSTEXPR size_type rfind(
556 : char const* s, size_type pos = core::string_view::npos ) const noexcept
557 : {
558 : return s_.rfind(s, pos);
559 : }
560 :
561 : // find_first_of
562 :
563 : /** Return the position of the first match
564 :
565 : See `core::string_view::find_first_of`
566 : */
567 : BOOST_CXX14_CONSTEXPR size_type find_first_of(
568 : core::string_view str, size_type pos = 0 ) const noexcept
569 : {
570 : return s_.find_first_of(str, pos);
571 : }
572 :
573 : /** Return the position of the first match
574 :
575 : See `core::string_view::find_first_of`
576 : */
577 52 : BOOST_CONSTEXPR size_type find_first_of(
578 : char c, size_type pos = 0 ) const noexcept
579 : {
580 52 : return s_.find_first_of(c, pos);
581 : }
582 :
583 : /** Return the position of the first match
584 :
585 : See `core::string_view::find_first_of`
586 : */
587 : BOOST_CXX14_CONSTEXPR size_type find_first_of(
588 : char const* s, size_type pos, size_type n ) const noexcept
589 : {
590 : return s_.find_first_of(s, pos, n);
591 : }
592 :
593 : /** Return the position of the first match
594 :
595 : See `core::string_view::find_first_of`
596 : */
597 5 : BOOST_CXX14_CONSTEXPR size_type find_first_of(
598 : char const* s, size_type pos = 0 ) const noexcept
599 : {
600 5 : return s_.find_first_of(s, pos);
601 : }
602 :
603 : // find_last_of
604 :
605 : /** Return the position of the last match
606 :
607 : See `core::string_view::find_last_of`
608 : */
609 : BOOST_CXX14_CONSTEXPR size_type find_last_of(
610 : core::string_view str, size_type pos = core::string_view::npos ) const noexcept
611 : {
612 : return s_.find_last_of(str, pos);
613 : }
614 :
615 : /** Return the position of the last match
616 :
617 : See `core::string_view::find_last_of`
618 : */
619 : BOOST_CONSTEXPR size_type find_last_of(
620 : char c, size_type pos = core::string_view::npos ) const noexcept
621 : {
622 : return s_.find_last_of(c, pos);
623 : }
624 :
625 : /** Return the position of the last match
626 :
627 : See `core::string_view::find_last_of`
628 : */
629 : BOOST_CXX14_CONSTEXPR size_type find_last_of(
630 : char const* s, size_type pos, size_type n ) const noexcept
631 : {
632 : return s_.find_last_of(s, pos, n);
633 : }
634 :
635 : /** Return the position of the last match
636 :
637 : See `core::string_view::find_last_of`
638 : */
639 : BOOST_CXX14_CONSTEXPR size_type find_last_of(
640 : char const* s, size_type pos = core::string_view::npos ) const noexcept
641 : {
642 : return s_.find_last_of(s, pos);
643 : }
644 :
645 : // find_first_not_of
646 :
647 : /** Return the position of the first non-match
648 :
649 : See `core::string_view::find_first_not_of`
650 : */
651 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
652 : core::string_view str, size_type pos = 0 ) const noexcept
653 : {
654 : return s_.find_first_not_of(str, pos);
655 : }
656 :
657 : /** Return the position of the first non-match
658 :
659 : See `core::string_view::find_first_not_of`
660 : */
661 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
662 : char c, size_type pos = 0 ) const noexcept
663 : {
664 : return s_.find_first_not_of(c, pos);
665 : }
666 :
667 : /** Return the position of the first non-match
668 :
669 : See `core::string_view::find_first_not_of`
670 : */
671 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
672 : char const* s, size_type pos, size_type n ) const noexcept
673 : {
674 : return s_.find_first_not_of(s, pos, n);
675 : }
676 :
677 : /** Return the position of the first non-match
678 :
679 : See `core::string_view::find_first_not_of`
680 : */
681 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
682 : char const* s, size_type pos = 0 ) const noexcept
683 : {
684 : return s_.find_first_not_of(s, pos);
685 : }
686 :
687 : // find_last_not_of
688 :
689 : /** Return the position of the last non-match
690 :
691 : See `core::string_view::find_last_not_of`
692 : */
693 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
694 : core::string_view str, size_type pos = core::string_view::npos ) const noexcept
695 : {
696 : return s_.find_last_not_of(str, pos);
697 : }
698 :
699 : /** Return the position of the last non-match
700 :
701 : See `core::string_view::find_last_not_of`
702 : */
703 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
704 : char c, size_type pos = core::string_view::npos ) const noexcept
705 : {
706 : return s_.find_last_not_of(c, pos);
707 : }
708 :
709 : /** Return the position of the last non-match
710 :
711 : See `core::string_view::find_last_not_of`
712 : */
713 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
714 : char const* s, size_type pos, size_type n ) const noexcept
715 : {
716 : return s_.find_last_not_of(s, pos, n);
717 : }
718 :
719 : /** Return the position of the last non-match
720 :
721 : See `core::string_view::find_last_not_of`
722 : */
723 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
724 : char const* s, size_type pos = core::string_view::npos ) const noexcept
725 : {
726 : return s_.find_last_not_of(s, pos);
727 : }
728 :
729 : // contains
730 :
731 : /** Return true if matching characters are found
732 :
733 : See `core::string_view::contains`
734 : */
735 : BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept
736 : {
737 : return s_.contains(sv);
738 : }
739 :
740 : /** Return true if matching characters are found
741 :
742 : See `core::string_view::contains`
743 : */
744 5 : BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept
745 : {
746 5 : return s_.contains(c);
747 : }
748 :
749 : /** Return true if matching characters are found
750 :
751 : See `core::string_view::contains`
752 : */
753 : BOOST_CONSTEXPR bool contains( char const* s ) const noexcept
754 : {
755 : return s_.contains(s);
756 : }
757 :
758 : // relational operators
759 : #ifndef BOOST_URL_DOCS
760 : private:
761 : template<class S0, class S1>
762 : using is_match = std::integral_constant<bool,
763 : std::is_convertible<S0, core::string_view>::value &&
764 : std::is_convertible<S1, core::string_view>::value && (
765 : (std::is_base_of<string_view_base,
766 : typename std::decay<S0>::type>::value &&
767 : std::is_convertible<S0 const volatile*,
768 : string_view_base const volatile*>::value) ||
769 : (std::is_base_of<string_view_base,
770 : typename std::decay<S1>::type>::value &&
771 : std::is_convertible<S1 const volatile*,
772 : string_view_base const volatile*>::value))>;
773 : public:
774 :
775 : template<class S0, class S1>
776 3003 : BOOST_CXX14_CONSTEXPR friend auto operator==(
777 : S0 const& s0, S1 const& s1) noexcept ->
778 : typename std::enable_if<
779 : is_match<S0, S1>::value, bool>::type
780 : {
781 3003 : return urls::detail::to_sv(s0) == urls::detail::to_sv(s1);
782 : }
783 :
784 : template<class S0, class S1>
785 73 : BOOST_CXX14_CONSTEXPR friend auto operator!=(
786 : S0 const& s0, S1 const& s1) noexcept ->
787 : typename std::enable_if<
788 : is_match<S0, S1>::value, bool>::type
789 : {
790 73 : return urls::detail::to_sv(s0) != urls::detail::to_sv(s1);
791 : }
792 :
793 : template<class S0, class S1>
794 7 : BOOST_CXX14_CONSTEXPR friend auto operator<(
795 : S0 const& s0, S1 const& s1) noexcept ->
796 : typename std::enable_if<
797 : is_match<S0, S1>::value, bool>::type
798 : {
799 7 : return urls::detail::to_sv(s0) < urls::detail::to_sv(s1);
800 : }
801 :
802 : template<class S0, class S1>
803 7 : BOOST_CXX14_CONSTEXPR friend auto operator<=(
804 : S0 const& s0, S1 const& s1) noexcept ->
805 : typename std::enable_if<
806 : is_match<S0, S1>::value, bool>::type
807 : {
808 7 : return urls::detail::to_sv(s0) <= urls::detail::to_sv(s1);
809 : }
810 :
811 : template<class S0, class S1>
812 7 : BOOST_CXX14_CONSTEXPR friend auto operator>(
813 : S0 const& s0, S1 const& s1) noexcept ->
814 : typename std::enable_if<
815 : is_match<S0, S1>::value, bool>::type
816 : {
817 7 : return urls::detail::to_sv(s0) > urls::detail::to_sv(s1);
818 : }
819 :
820 : template<class S0, class S1>
821 7 : BOOST_CXX14_CONSTEXPR friend auto operator>=(
822 : S0 const& s0, S1 const& s1) noexcept ->
823 : typename std::enable_if<
824 : is_match<S0, S1>::value, bool>::type
825 : {
826 7 : return urls::detail::to_sv(s0) >= urls::detail::to_sv(s1);
827 : }
828 : #endif
829 :
830 : //--------------------------------------------
831 :
832 : /** Return the hash of this value
833 : */
834 : friend
835 : std::size_t
836 : hash_value(
837 : string_view_base const& s) noexcept
838 : {
839 : return hash_value(s.s_);
840 : }
841 :
842 : BOOST_URL_DECL
843 : friend
844 : std::ostream&
845 : operator<<(
846 : std::ostream& os,
847 : string_view_base const& s);
848 : };
849 :
850 : //------------------------------------------------
851 :
852 : /** Format a string to an output stream
853 : */
854 : BOOST_URL_DECL
855 : std::ostream&
856 : operator<<(
857 : std::ostream& os,
858 : string_view_base const& s);
859 :
860 : } // grammar
861 :
862 : #ifndef BOOST_URL_DOCS
863 : namespace detail {
864 : template <>
865 : inline
866 : core::string_view
867 32 : to_sv(grammar::string_view_base const& s) noexcept
868 : {
869 32 : return s.operator core::string_view();
870 : }
871 : } // detail
872 : #endif
873 :
874 : } // urls
875 : } // boost
876 :
877 : #endif
|