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 34583 : string_view_base(
56 : char const* data,
57 : std::size_t size) noexcept
58 34583 : : s_(data, size)
59 : {
60 34583 : }
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 16491 : 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 11874 : operator
120 : core::string_view() const noexcept
121 : {
122 11874 : 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 : BOOST_URL_LIB_ARRAY_CONSTEXPR
194 : const_reverse_iterator rbegin() const noexcept
195 : {
196 : return s_.rbegin();
197 : }
198 :
199 : /** Return a reverse iterator to the beginning
200 :
201 : See `core::string_view::rend`
202 : */
203 : BOOST_URL_LIB_ARRAY_CONSTEXPR
204 : const_reverse_iterator rend() const noexcept
205 : {
206 : return s_.rend();
207 : }
208 :
209 : /** Return a reverse iterator to the end
210 :
211 : See `core::string_view::crbegin`
212 : */
213 : BOOST_URL_LIB_ARRAY_CONSTEXPR
214 : const_reverse_iterator crbegin() const noexcept
215 : {
216 : return s_.crbegin();
217 : }
218 :
219 : /** Return a reverse iterator to the beginning
220 :
221 : See `core::string_view::crend`
222 : */
223 : BOOST_URL_LIB_ARRAY_CONSTEXPR
224 : const_reverse_iterator crend() const noexcept
225 : {
226 : return s_.crend();
227 : }
228 :
229 : // capacity
230 :
231 : /** Return the size
232 :
233 : See `core::string_view::size`
234 : */
235 7203 : BOOST_CONSTEXPR size_type size() const noexcept
236 : {
237 7203 : return s_.size();
238 : }
239 :
240 : /** Return the size
241 :
242 : See `core::string_view::length`
243 : */
244 : BOOST_CONSTEXPR size_type length() const noexcept
245 : {
246 : return s_.length();
247 : }
248 :
249 : /** Return the maximum allowed size
250 :
251 : See `core::string_view::max_size`
252 : */
253 : BOOST_CONSTEXPR size_type max_size() const noexcept
254 : {
255 : return s_.max_size();
256 : }
257 :
258 : /** Return true if the string is empty
259 :
260 : See `core::string_view::size`
261 : */
262 5330 : BOOST_CONSTEXPR bool empty() const noexcept
263 : {
264 5330 : return s_.empty();
265 : }
266 :
267 : // element access
268 :
269 : /** Access a character
270 :
271 : See `core::string_view::operator[]`
272 : */
273 : BOOST_CXX14_CONSTEXPR const_reference
274 1 : operator[]( size_type pos ) const noexcept
275 : {
276 1 : return s_[pos];
277 : }
278 :
279 : /** Access a character
280 :
281 : See `core::string_view::at`
282 : */
283 : BOOST_CXX14_CONSTEXPR const_reference
284 : at( size_type pos ) const
285 : {
286 : return s_.at(pos);
287 : }
288 :
289 : /** Return the first character
290 :
291 : See `core::string_view::front`
292 : */
293 : BOOST_CXX14_CONSTEXPR const_reference
294 79 : front() const noexcept
295 : {
296 79 : return s_.front();
297 : }
298 :
299 : /** Return the last character
300 :
301 : See `core::string_view::back`
302 : */
303 : BOOST_CXX14_CONSTEXPR const_reference
304 16 : back() const noexcept
305 : {
306 16 : return s_.back();
307 : }
308 :
309 : /** Return a pointer to the character buffer
310 :
311 : See `core::string_view::data`
312 : */
313 : BOOST_CONSTEXPR const_pointer
314 667 : data() const noexcept
315 : {
316 667 : return s_.data();
317 : }
318 :
319 : // string operations
320 :
321 : /** Copy the characters to another buffer
322 :
323 : See `core::string_view::copy`
324 : */
325 : BOOST_CXX14_CONSTEXPR size_type copy(
326 : char* s, size_type n, size_type pos = 0 ) const
327 : {
328 : return s_.copy(s, n, pos);
329 : }
330 :
331 : /** Return a view to part of the string
332 :
333 : See `core::string_view::substr`
334 : */
335 10080 : BOOST_CXX14_CONSTEXPR core::string_view substr(
336 : size_type pos = 0, size_type n = core::string_view::npos ) const
337 : {
338 10080 : return s_.substr(pos, n);
339 : }
340 :
341 : // comparison
342 :
343 : /** Return the result of comparing to another string
344 :
345 : See `core::string_view::compare`
346 : */
347 : BOOST_CXX14_CONSTEXPR int
348 : compare( core::string_view str ) const noexcept
349 : {
350 : return s_.compare(str);
351 : }
352 :
353 : /** Return the result of comparing to another string
354 :
355 : See `core::string_view::compare`
356 : */
357 : BOOST_CONSTEXPR int compare(
358 : size_type pos1, size_type n1, core::string_view str ) const
359 : {
360 : return s_.compare(pos1, n1, str);
361 : }
362 :
363 : /** Return the result of comparing to another string
364 :
365 : See `core::string_view::compare`
366 : */
367 : BOOST_CONSTEXPR int compare(
368 : size_type pos1, size_type n1, core::string_view str,
369 : size_type pos2, size_type n2 ) const
370 : {
371 : return s_.compare(pos1, n1, str, pos2, n2);
372 : }
373 :
374 : /** Return the result of comparing to another string
375 :
376 : See `core::string_view::compare`
377 : */
378 : BOOST_CONSTEXPR int compare(
379 : char const* s ) const noexcept
380 : {
381 : return s_.compare(s);
382 : }
383 :
384 : /** Return the result of comparing to another string
385 :
386 : See `core::string_view::compare`
387 : */
388 : BOOST_CONSTEXPR int compare(
389 : size_type pos1, size_type n1, char const* s ) const
390 : {
391 : return s_.compare(pos1, n1, s);
392 : }
393 :
394 : /** Return the result of comparing to another string
395 :
396 : See `core::string_view::compare`
397 : */
398 : BOOST_CONSTEXPR int compare(
399 : size_type pos1, size_type n1,
400 : char const* s, size_type n2 ) const
401 : {
402 : return s_.compare(pos1, n1, s, n2);
403 : }
404 :
405 : // starts_with
406 :
407 : /** Return true if a matching prefix exists
408 :
409 : See `core::string_view::starts_with`
410 : */
411 : BOOST_CONSTEXPR bool starts_with(
412 : core::string_view x ) const noexcept
413 : {
414 : return s_.starts_with(x);
415 : }
416 :
417 : /** Return true if a matching prefix exists
418 :
419 : See `core::string_view::starts_with`
420 : */
421 538 : BOOST_CONSTEXPR bool starts_with(
422 : char x ) const noexcept
423 : {
424 538 : return s_.starts_with(x);
425 : }
426 :
427 : /** Return true if a matching prefix exists
428 :
429 : See `core::string_view::starts_with`
430 : */
431 232 : BOOST_CONSTEXPR bool starts_with(
432 : char const* x ) const noexcept
433 : {
434 232 : return s_.starts_with(x);
435 : }
436 :
437 : // ends_with
438 :
439 : /** Return true if a matching suffix exists
440 :
441 : See `core::string_view::ends_with`
442 : */
443 : BOOST_CONSTEXPR bool ends_with(
444 : core::string_view x ) const noexcept
445 : {
446 : return s_.ends_with(x);
447 : }
448 :
449 : /** Return true if a matching suffix exists
450 :
451 : See `core::string_view::ends_with`
452 : */
453 521 : BOOST_CONSTEXPR bool ends_with(
454 : char x ) const noexcept
455 : {
456 521 : return s_.ends_with(x);
457 : }
458 :
459 : /** Return true if a matching suffix exists
460 :
461 : See `core::string_view::ends_with`
462 : */
463 : BOOST_CONSTEXPR bool ends_with(
464 : char const* x ) const noexcept
465 : {
466 : return s_.ends_with(x);
467 : }
468 :
469 : // find
470 :
471 : /** Return the position of matching characters
472 :
473 : See `core::string_view::find`
474 : */
475 : BOOST_CONSTEXPR size_type find(
476 : core::string_view str, size_type pos = 0 ) const noexcept
477 : {
478 : return s_.find(str, pos);
479 : }
480 :
481 : /** Return the position of matching characters
482 :
483 : See `core::string_view::find`
484 : */
485 10 : BOOST_CXX14_CONSTEXPR size_type find(
486 : char c, size_type pos = 0 ) const noexcept
487 : {
488 10 : return s_.find(c, pos);
489 : }
490 :
491 : /** Return the position of matching characters
492 :
493 : See `core::string_view::find`
494 : */
495 : BOOST_CXX14_CONSTEXPR size_type find(
496 : char const* s, size_type pos, size_type n ) const noexcept
497 : {
498 : return s_.find(s, pos, n);
499 : }
500 :
501 : /** Return the position of matching characters
502 :
503 : See `core::string_view::find`
504 : */
505 : BOOST_CONSTEXPR size_type find(
506 : char const* s, size_type pos = 0 ) const noexcept
507 : {
508 : return s_.find(s, pos);
509 : }
510 :
511 : // rfind
512 :
513 : /** Return the position of matching characters
514 :
515 : See `core::string_view::rfind`
516 : */
517 : BOOST_CONSTEXPR size_type rfind(
518 : core::string_view str, size_type pos = core::string_view::npos ) const noexcept
519 : {
520 : return s_.rfind(str, pos);
521 : }
522 :
523 : /** Return the position of matching characters
524 :
525 : See `core::string_view::rfind`
526 : */
527 : BOOST_CXX14_CONSTEXPR size_type rfind(
528 : char c, size_type pos = core::string_view::npos ) const noexcept
529 : {
530 : return s_.rfind(c, pos);
531 : }
532 :
533 : /** Return the position of matching characters
534 :
535 : See `core::string_view::rfind`
536 : */
537 : BOOST_CXX14_CONSTEXPR size_type rfind(
538 : char const* s, size_type pos, size_type n ) const noexcept
539 : {
540 : return s_.rfind(s, pos, n);
541 : }
542 :
543 : /** Return the position of matching characters
544 :
545 : See `core::string_view::rfind`
546 : */
547 : BOOST_CONSTEXPR size_type rfind(
548 : char const* s, size_type pos = core::string_view::npos ) const noexcept
549 : {
550 : return s_.rfind(s, pos);
551 : }
552 :
553 : // find_first_of
554 :
555 : /** Return the position of the first match
556 :
557 : See `core::string_view::find_first_of`
558 : */
559 : BOOST_CXX14_CONSTEXPR size_type find_first_of(
560 : core::string_view str, size_type pos = 0 ) const noexcept
561 : {
562 : return s_.find_first_of(str, pos);
563 : }
564 :
565 : /** Return the position of the first match
566 :
567 : See `core::string_view::find_first_of`
568 : */
569 52 : BOOST_CONSTEXPR size_type find_first_of(
570 : char c, size_type pos = 0 ) const noexcept
571 : {
572 52 : return s_.find_first_of(c, pos);
573 : }
574 :
575 : /** Return the position of the first match
576 :
577 : See `core::string_view::find_first_of`
578 : */
579 : BOOST_CXX14_CONSTEXPR size_type find_first_of(
580 : char const* s, size_type pos, size_type n ) const noexcept
581 : {
582 : return s_.find_first_of(s, pos, n);
583 : }
584 :
585 : /** Return the position of the first match
586 :
587 : See `core::string_view::find_first_of`
588 : */
589 5 : BOOST_CXX14_CONSTEXPR size_type find_first_of(
590 : char const* s, size_type pos = 0 ) const noexcept
591 : {
592 5 : return s_.find_first_of(s, pos);
593 : }
594 :
595 : // find_last_of
596 :
597 : /** Return the position of the last match
598 :
599 : See `core::string_view::find_last_of`
600 : */
601 : BOOST_CXX14_CONSTEXPR size_type find_last_of(
602 : core::string_view str, size_type pos = core::string_view::npos ) const noexcept
603 : {
604 : return s_.find_last_of(str, pos);
605 : }
606 :
607 : /** Return the position of the last match
608 :
609 : See `core::string_view::find_last_of`
610 : */
611 : BOOST_CONSTEXPR size_type find_last_of(
612 : char c, size_type pos = core::string_view::npos ) const noexcept
613 : {
614 : return s_.find_last_of(c, pos);
615 : }
616 :
617 : /** Return the position of the last match
618 :
619 : See `core::string_view::find_last_of`
620 : */
621 : BOOST_CXX14_CONSTEXPR size_type find_last_of(
622 : char const* s, size_type pos, size_type n ) const noexcept
623 : {
624 : return s_.find_last_of(s, pos, n);
625 : }
626 :
627 : /** Return the position of the last match
628 :
629 : See `core::string_view::find_last_of`
630 : */
631 : BOOST_CXX14_CONSTEXPR size_type find_last_of(
632 : char const* s, size_type pos = core::string_view::npos ) const noexcept
633 : {
634 : return s_.find_last_of(s, pos);
635 : }
636 :
637 : // find_first_not_of
638 :
639 : /** Return the position of the first non-match
640 :
641 : See `core::string_view::find_first_not_of`
642 : */
643 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
644 : core::string_view str, size_type pos = 0 ) const noexcept
645 : {
646 : return s_.find_first_not_of(str, pos);
647 : }
648 :
649 : /** Return the position of the first non-match
650 :
651 : See `core::string_view::find_first_not_of`
652 : */
653 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
654 : char c, size_type pos = 0 ) const noexcept
655 : {
656 : return s_.find_first_not_of(c, pos);
657 : }
658 :
659 : /** Return the position of the first non-match
660 :
661 : See `core::string_view::find_first_not_of`
662 : */
663 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
664 : char const* s, size_type pos, size_type n ) const noexcept
665 : {
666 : return s_.find_first_not_of(s, pos, n);
667 : }
668 :
669 : /** Return the position of the first non-match
670 :
671 : See `core::string_view::find_first_not_of`
672 : */
673 : BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
674 : char const* s, size_type pos = 0 ) const noexcept
675 : {
676 : return s_.find_first_not_of(s, pos);
677 : }
678 :
679 : // find_last_not_of
680 :
681 : /** Return the position of the last non-match
682 :
683 : See `core::string_view::find_last_not_of`
684 : */
685 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
686 : core::string_view str, size_type pos = core::string_view::npos ) const noexcept
687 : {
688 : return s_.find_last_not_of(str, pos);
689 : }
690 :
691 : /** Return the position of the last non-match
692 :
693 : See `core::string_view::find_last_not_of`
694 : */
695 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
696 : char c, size_type pos = core::string_view::npos ) const noexcept
697 : {
698 : return s_.find_last_not_of(c, pos);
699 : }
700 :
701 : /** Return the position of the last non-match
702 :
703 : See `core::string_view::find_last_not_of`
704 : */
705 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
706 : char const* s, size_type pos, size_type n ) const noexcept
707 : {
708 : return s_.find_last_not_of(s, pos, n);
709 : }
710 :
711 : /** Return the position of the last non-match
712 :
713 : See `core::string_view::find_last_not_of`
714 : */
715 : BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
716 : char const* s, size_type pos = core::string_view::npos ) const noexcept
717 : {
718 : return s_.find_last_not_of(s, pos);
719 : }
720 :
721 : // contains
722 :
723 : /** Return true if matching characters are found
724 :
725 : See `core::string_view::contains`
726 : */
727 : BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept
728 : {
729 : return s_.contains(sv);
730 : }
731 :
732 : /** Return true if matching characters are found
733 :
734 : See `core::string_view::contains`
735 : */
736 5 : BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept
737 : {
738 5 : return s_.contains(c);
739 : }
740 :
741 : /** Return true if matching characters are found
742 :
743 : See `core::string_view::contains`
744 : */
745 : BOOST_CONSTEXPR bool contains( char const* s ) const noexcept
746 : {
747 : return s_.contains(s);
748 : }
749 :
750 : // relational operators
751 : #ifndef BOOST_URL_DOCS
752 : private:
753 : template<class S0, class S1>
754 : using is_match = std::integral_constant<bool,
755 : std::is_convertible<S0, core::string_view>::value &&
756 : std::is_convertible<S1, core::string_view>::value && (
757 : (std::is_base_of<string_view_base,
758 : typename std::decay<S0>::type>::value &&
759 : std::is_convertible<S0 const volatile*,
760 : string_view_base const volatile*>::value) ||
761 : (std::is_base_of<string_view_base,
762 : typename std::decay<S1>::type>::value &&
763 : std::is_convertible<S1 const volatile*,
764 : string_view_base const volatile*>::value))>;
765 : public:
766 :
767 : /// Compare two string views for equality
768 : /**
769 : * This function is only enabled if both arguments
770 : * are convertible to `core::string_view` and at least
771 : * one of the arguments is derived from `string_view_base`.
772 : */
773 : template<class S0, class S1>
774 3015 : BOOST_CXX14_CONSTEXPR friend auto operator==(
775 : S0 const& s0, S1 const& s1) noexcept ->
776 : typename std::enable_if<
777 : is_match<S0, S1>::value, bool>::type
778 : {
779 3015 : return urls::detail::to_sv(s0) == urls::detail::to_sv(s1);
780 : }
781 :
782 : /// Compare two string views for inequality
783 : /**
784 : * This function is only enabled if both arguments
785 : * are convertible to `core::string_view` and at least
786 : * one of the arguments is derived from `string_view_base`.
787 : */
788 : template<class S0, class S1>
789 73 : BOOST_CXX14_CONSTEXPR friend auto operator!=(
790 : S0 const& s0, S1 const& s1) noexcept ->
791 : typename std::enable_if<
792 : is_match<S0, S1>::value, bool>::type
793 : {
794 73 : return urls::detail::to_sv(s0) != urls::detail::to_sv(s1);
795 : }
796 :
797 : /// Compare two string views for less than
798 : /**
799 : * This function is only enabled if both arguments
800 : * are convertible to `core::string_view` and at least
801 : * one of the arguments is derived from `string_view_base`.
802 : */
803 : template<class S0, class S1>
804 7 : BOOST_CXX14_CONSTEXPR friend auto operator<(
805 : S0 const& s0, S1 const& s1) noexcept ->
806 : typename std::enable_if<
807 : is_match<S0, S1>::value, bool>::type
808 : {
809 7 : return urls::detail::to_sv(s0) < urls::detail::to_sv(s1);
810 : }
811 :
812 : /// Compare two string views for less than or equal
813 : /**
814 : * This function is only enabled if both arguments
815 : * are convertible to `core::string_view` and at least
816 : * one of the arguments is derived from `string_view_base`.
817 : */
818 : template<class S0, class S1>
819 7 : BOOST_CXX14_CONSTEXPR friend auto operator<=(
820 : S0 const& s0, S1 const& s1) noexcept ->
821 : typename std::enable_if<
822 : is_match<S0, S1>::value, bool>::type
823 : {
824 7 : return urls::detail::to_sv(s0) <= urls::detail::to_sv(s1);
825 : }
826 :
827 : /// Compare two string views for greater than
828 : /**
829 : * This function is only enabled if both arguments
830 : * are convertible to `core::string_view` and at least
831 : * one of the arguments is derived from `string_view_base`.
832 : */
833 : template<class S0, class S1>
834 7 : BOOST_CXX14_CONSTEXPR friend auto operator>(
835 : S0 const& s0, S1 const& s1) noexcept ->
836 : typename std::enable_if<
837 : is_match<S0, S1>::value, bool>::type
838 : {
839 7 : return urls::detail::to_sv(s0) > urls::detail::to_sv(s1);
840 : }
841 :
842 : /// Compare two string views for greater than or equal
843 : /**
844 : * This function is only enabled if both arguments
845 : * are convertible to `core::string_view` and at least
846 : * one of the arguments is derived from `string_view_base`.
847 : */
848 : template<class S0, class S1>
849 7 : BOOST_CXX14_CONSTEXPR friend auto operator>=(
850 : S0 const& s0, S1 const& s1) noexcept ->
851 : typename std::enable_if<
852 : is_match<S0, S1>::value, bool>::type
853 : {
854 7 : return urls::detail::to_sv(s0) >= urls::detail::to_sv(s1);
855 : }
856 : #endif
857 :
858 : //--------------------------------------------
859 :
860 : /** Return the hash of this value
861 : */
862 : friend
863 : std::size_t
864 : hash_value(
865 : string_view_base const& s) noexcept
866 : {
867 : return hash_value(s.s_);
868 : }
869 :
870 : /** Format a string to an output stream
871 : */
872 : BOOST_URL_DECL
873 : friend
874 : std::ostream&
875 : operator<<(
876 : std::ostream& os,
877 : string_view_base const& s);
878 : };
879 :
880 : //------------------------------------------------
881 :
882 : /** Format a string to an output stream
883 : */
884 : BOOST_URL_DECL
885 : std::ostream&
886 : operator<<(
887 : std::ostream& os,
888 : string_view_base const& s);
889 :
890 : } // grammar
891 :
892 : #ifndef BOOST_URL_DOCS
893 : namespace detail {
894 : template <>
895 : inline
896 : core::string_view
897 32 : to_sv(grammar::string_view_base const& s) noexcept
898 : {
899 32 : return s.operator core::string_view();
900 : }
901 : } // detail
902 : #endif
903 :
904 : } // urls
905 : } // boost
906 :
907 : #endif
|