]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/static_string.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / core / static_string.hpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/beast
8 //
9
10 #ifndef BOOST_BEAST_STATIC_STRING_HPP
11 #define BOOST_BEAST_STATIC_STRING_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/string.hpp>
15 #include <boost/beast/core/detail/static_string.hpp>
16 #include <algorithm>
17 #include <cstdint>
18 #include <initializer_list>
19 #include <iosfwd>
20 #include <stdexcept>
21 #include <string>
22 #include <type_traits>
23
24 namespace boost {
25 namespace beast {
26
27 /** A modifiable string with a fixed-size storage area.
28
29 These objects behave like `std::string` except that the storage
30 is not dynamically allocated but rather fixed in size.
31
32 These strings offer performance advantages when a protocol
33 imposes a natural small upper limit on the size of a value.
34
35 @note The stored string is always null-terminated.
36
37 @see to_static_string
38 */
39 template<
40 std::size_t N,
41 class CharT = char,
42 class Traits = std::char_traits<CharT>>
43 class static_string
44 {
45 template<std::size_t, class, class>
46 friend class static_string;
47
48 void
49 term()
50 {
51 Traits::assign(s_[n_], 0);
52 }
53
54 std::size_t n_;
55 CharT s_[N+1];
56
57 public:
58 //
59 // Member types
60 //
61
62 using traits_type = Traits;
63 using value_type = typename Traits::char_type;
64 using size_type = std::size_t;
65 using difference_type = std::ptrdiff_t;
66 using pointer = value_type*;
67 using reference = value_type&;
68 using const_pointer = value_type const*;
69 using const_reference = value_type const&;
70 using iterator = value_type*;
71 using const_iterator = value_type const*;
72 using reverse_iterator =
73 std::reverse_iterator<iterator>;
74 using const_reverse_iterator =
75 std::reverse_iterator<const_iterator>;
76
77 /// The type of `string_view` returned by the interface
78 using string_view_type =
79 basic_string_view<CharT, Traits>;
80
81 //
82 // Constants
83 //
84
85 /// Maximum size of the string excluding the null terminator
86 static std::size_t constexpr max_size_n = N;
87
88 /// A special index
89 static constexpr size_type npos = size_type(-1);
90
91 //
92 // (constructor)
93 //
94
95 /// Default constructor (empty string).
96 static_string();
97
98 /** Construct with count copies of character `ch`.
99
100 The behavior is undefined if `count >= npos`
101 */
102 static_string(size_type count, CharT ch);
103
104 /// Construct with a substring (pos, other.size()) of `other`.
105 template<std::size_t M>
106 static_string(static_string<M, CharT, Traits> const& other,
107 size_type pos);
108
109 /// Construct with a substring (pos, count) of `other`.
110 template<std::size_t M>
111 static_string(static_string<M, CharT, Traits> const& other,
112 size_type pos, size_type count);
113
114 /// Construct with the first `count` characters of `s`, including nulls.
115 static_string(CharT const* s, size_type count);
116
117 /// Construct from a null terminated string.
118 static_string(CharT const* s);
119
120 /// Construct from a range of characters
121 template<class InputIt>
122 static_string(InputIt first, InputIt last);
123
124 /// Copy constructor.
125 static_string(static_string const& other);
126
127 /// Copy constructor.
128 template<std::size_t M>
129 static_string(static_string<M, CharT, Traits> const& other);
130
131 /// Construct from an initializer list
132 static_string(std::initializer_list<CharT> init);
133
134 /// Construct from a `string_view`
135 explicit
136 static_string(string_view_type sv);
137
138 /** Construct from any object convertible to `string_view_type`.
139
140 The range (pos, n) is extracted from the value
141 obtained by converting `t` to `string_view_type`,
142 and used to construct the string.
143 */
144 #if BOOST_BEAST_DOXYGEN
145 template<class T>
146 #else
147 template<class T, class = typename std::enable_if<
148 std::is_convertible<T, string_view_type>::value>::type>
149 #endif
150 static_string(T const& t, size_type pos, size_type n);
151
152 //
153 // (assignment)
154 //
155
156 /// Copy assignment.
157 static_string&
158 operator=(static_string const& str)
159 {
160 return assign(str);
161 }
162
163 /// Copy assignment.
164 template<std::size_t M>
165 static_string&
166 operator=(static_string<M, CharT, Traits> const& str)
167 {
168 return assign(str);
169 }
170
171 /// Assign from null-terminated string.
172 static_string&
173 operator=(CharT const* s);
174
175 /// Assign from single character.
176 static_string&
177 operator=(CharT ch)
178 {
179 return assign_char(ch,
180 std::integral_constant<bool, (N>0)>{});
181 }
182
183 /// Assign from initializer list.
184 static_string&
185 operator=(std::initializer_list<CharT> init)
186 {
187 return assign(init);
188 }
189
190 /// Assign from `string_view_type`.
191 static_string&
192 operator=(string_view_type sv)
193 {
194 return assign(sv);
195 }
196
197 /// Assign `count` copies of `ch`.
198 static_string&
199 assign(size_type count, CharT ch);
200
201 /// Assign from another `static_string`
202 static_string&
203 assign(static_string const& str);
204
205 // VFALCO NOTE this could come in two flavors,
206 // N>M and N<M, and skip the exception
207 // check when N>M
208
209 /// Assign from another `static_string`
210 template<std::size_t M>
211 static_string&
212 assign(static_string<M, CharT, Traits> const& str)
213 {
214 return assign(str.data(), str.size());
215 }
216
217 /// Assign `count` characterss starting at `npos` from `other`.
218 template<std::size_t M>
219 static_string&
220 assign(static_string<M, CharT, Traits> const& str,
221 size_type pos, size_type count = npos);
222
223 /// Assign the first `count` characters of `s`, including nulls.
224 static_string&
225 assign(CharT const* s, size_type count);
226
227 /// Assign a null terminated string.
228 static_string&
229 assign(CharT const* s)
230 {
231 return assign(s, Traits::length(s));
232 }
233
234 /// Assign from an iterator range of characters.
235 template<class InputIt>
236 static_string&
237 assign(InputIt first, InputIt last);
238
239 /// Assign from initializer list.
240 static_string&
241 assign(std::initializer_list<CharT> init)
242 {
243 return assign(init.begin(), init.end());
244 }
245
246 /// Assign from `string_view_type`.
247 static_string&
248 assign(string_view_type str)
249 {
250 return assign(str.data(), str.size());
251 }
252
253 /** Assign from any object convertible to `string_view_type`.
254
255 The range (pos, n) is extracted from the value
256 obtained by converting `t` to `string_view_type`,
257 and used to assign the string.
258 */
259 template<class T>
260 #if BOOST_BEAST_DOXYGEN
261 static_string&
262 #else
263 typename std::enable_if<std::is_convertible<T,
264 string_view_type>::value, static_string&>::type
265 #endif
266 assign(T const& t,
267 size_type pos, size_type count = npos);
268
269 //
270 // Element access
271 //
272
273 /// Access specified character with bounds checking.
274 reference
275 at(size_type pos);
276
277 /// Access specified character with bounds checking.
278 const_reference
279 at(size_type pos) const;
280
281 /// Access specified character.
282 reference
283 operator[](size_type pos)
284 {
285 return s_[pos];
286 }
287
288 /// Access specified character.
289 const_reference
290 operator[](size_type pos) const
291 {
292 return s_[pos];
293 }
294
295 /// Accesses the first character.
296 CharT&
297 front()
298 {
299 return s_[0];
300 }
301
302 /// Accesses the first character.
303 CharT const&
304 front() const
305 {
306 return s_[0];
307 }
308
309 /// Accesses the last character.
310 CharT&
311 back()
312 {
313 return s_[n_-1];
314 }
315
316 /// Accesses the last character.
317 CharT const&
318 back() const
319 {
320 return s_[n_-1];
321 }
322
323 /// Returns a pointer to the first character of a string.
324 CharT*
325 data()
326 {
327 return &s_[0];
328 }
329
330 /// Returns a pointer to the first character of a string.
331 CharT const*
332 data() const
333 {
334 return &s_[0];
335 }
336
337 /// Returns a non-modifiable standard C character array version of the string.
338 CharT const*
339 c_str() const
340 {
341 return data();
342 }
343
344 /// Convert a static string to a `string_view_type`
345 operator string_view_type() const
346 {
347 return basic_string_view<
348 CharT, Traits>{data(), size()};
349 }
350
351 //
352 // Iterators
353 //
354
355 /// Returns an iterator to the beginning.
356 iterator
357 begin()
358 {
359 return &s_[0];
360 }
361
362 /// Returns an iterator to the beginning.
363 const_iterator
364 begin() const
365 {
366 return &s_[0];
367 }
368
369 /// Returns an iterator to the beginning.
370 const_iterator
371 cbegin() const
372 {
373 return &s_[0];
374 }
375
376 /// Returns an iterator to the end.
377 iterator
378 end()
379 {
380 return &s_[n_];
381 }
382
383 /// Returns an iterator to the end.
384 const_iterator
385 end() const
386 {
387 return &s_[n_];
388 }
389
390 /// Returns an iterator to the end.
391 const_iterator
392 cend() const
393 {
394 return &s_[n_];
395 }
396
397 /// Returns a reverse iterator to the beginning.
398 reverse_iterator
399 rbegin()
400 {
401 return reverse_iterator{end()};
402 }
403
404 /// Returns a reverse iterator to the beginning.
405 const_reverse_iterator
406 rbegin() const
407 {
408 return const_reverse_iterator{cend()};
409 }
410
411 /// Returns a reverse iterator to the beginning.
412 const_reverse_iterator
413 crbegin() const
414 {
415 return const_reverse_iterator{cend()};
416 }
417
418 /// Returns a reverse iterator to the end.
419 reverse_iterator
420 rend()
421 {
422 return reverse_iterator{begin()};
423 }
424
425 /// Returns a reverse iterator to the end.
426 const_reverse_iterator
427 rend() const
428 {
429 return const_reverse_iterator{cbegin()};
430 }
431
432 /// Returns a reverse iterator to the end.
433 const_reverse_iterator
434 crend() const
435 {
436 return const_reverse_iterator{cbegin()};
437 }
438
439 //
440 // Capacity
441 //
442
443 /// Returns `true` if the string is empty.
444 bool
445 empty() const
446 {
447 return n_ == 0;
448 }
449
450 /// Returns the number of characters, excluding the null terminator.
451 size_type
452 size() const
453 {
454 return n_;
455 }
456
457 /// Returns the number of characters, excluding the null terminator.
458 size_type
459 length() const
460 {
461 return size();
462 }
463
464 /// Returns the maximum number of characters that can be stored, excluding the null terminator.
465 size_type constexpr
466 max_size() const
467 {
468 return N;
469 }
470
471 /** Reserves storage.
472
473 This actually just throws an exception if `n > N`,
474 otherwise does nothing since the storage is fixed.
475 */
476 void
477 reserve(std::size_t n);
478
479 /// Returns the number of characters that can be held in currently allocated storage.
480 size_type constexpr
481 capacity() const
482 {
483 return max_size();
484 }
485
486 /** Reduces memory usage by freeing unused memory.
487
488 This actually does nothing, since the storage is fixed.
489 */
490 void
491 shrink_to_fit()
492 {
493 }
494
495 //
496 // Operations
497 //
498
499 /// Clears the contents.
500 void
501 clear();
502
503 static_string&
504 insert(size_type index, size_type count, CharT ch);
505
506 static_string&
507 insert(size_type index, CharT const* s)
508 {
509 return insert(index, s, Traits::length(s));
510 }
511
512 static_string&
513 insert(size_type index, CharT const* s, size_type count);
514
515 template<std::size_t M>
516 static_string&
517 insert(size_type index,
518 static_string<M, CharT, Traits> const& str)
519 {
520 return insert(index, str.data(), str.size());
521 }
522
523 template<std::size_t M>
524 static_string&
525 insert(size_type index,
526 static_string<M, CharT, Traits> const& str,
527 size_type index_str, size_type count = npos);
528
529 iterator
530 insert(const_iterator pos, CharT ch)
531 {
532 return insert(pos, 1, ch);
533 }
534
535 iterator
536 insert(const_iterator pos, size_type count, CharT ch);
537
538 template<class InputIt>
539 #if BOOST_BEAST_DOXYGEN
540 iterator
541 #else
542 typename std::enable_if<
543 detail::is_input_iterator<InputIt>::value,
544 iterator>::type
545 #endif
546 insert(const_iterator pos, InputIt first, InputIt last);
547
548 iterator
549 insert(const_iterator pos, std::initializer_list<CharT> init)
550 {
551 return insert(pos, init.begin(), init.end());
552 }
553
554 static_string&
555 insert(size_type index, string_view_type str)
556 {
557 return insert(index, str.data(), str.size());
558 }
559
560 template<class T>
561 #if BOOST_BEAST_DOXYGEN
562 static_string&
563 #else
564 typename std::enable_if<
565 std::is_convertible<T const&, string_view_type>::value &&
566 ! std::is_convertible<T const&, CharT const*>::value,
567 static_string&>::type
568 #endif
569 insert(size_type index, T const& t,
570 size_type index_str, size_type count = npos);
571
572 static_string&
573 erase(size_type index = 0, size_type count = npos);
574
575 iterator
576 erase(const_iterator pos);
577
578 iterator
579 erase(const_iterator first, const_iterator last);
580
581 void
582 push_back(CharT ch);
583
584 void
585 pop_back()
586 {
587 Traits::assign(s_[--n_], 0);
588 }
589
590 static_string&
591 append(size_type count, CharT ch)
592 {
593 insert(end(), count, ch);
594 return *this;
595 }
596
597 template<std::size_t M>
598 static_string&
599 append(static_string<M, CharT, Traits> const& str)
600 {
601 insert(size(), str);
602 return *this;
603 }
604
605 template<std::size_t M>
606 static_string&
607 append(static_string<M, CharT, Traits> const& str,
608 size_type pos, size_type count = npos);
609
610 static_string&
611 append(CharT const* s, size_type count)
612 {
613 insert(size(), s, count);
614 return *this;
615 }
616
617 static_string&
618 append(CharT const* s)
619 {
620 insert(size(), s);
621 return *this;
622 }
623
624 template<class InputIt>
625 #if BOOST_BEAST_DOXYGEN
626 static_string&
627 #else
628 typename std::enable_if<
629 detail::is_input_iterator<InputIt>::value,
630 static_string&>::type
631 #endif
632 append(InputIt first, InputIt last)
633 {
634 insert(end(), first, last);
635 return *this;
636 }
637
638 static_string&
639 append(std::initializer_list<CharT> init)
640 {
641 insert(end(), init);
642 return *this;
643 }
644
645 static_string&
646 append(string_view_type sv)
647 {
648 insert(size(), sv);
649 return *this;
650 }
651
652 template<class T>
653 typename std::enable_if<
654 std::is_convertible<T const&, string_view_type>::value &&
655 ! std::is_convertible<T const&, CharT const*>::value,
656 static_string&>::type
657 append(T const& t, size_type pos, size_type count = npos)
658 {
659 insert(size(), t, pos, count);
660 return *this;
661 }
662
663 template<std::size_t M>
664 static_string&
665 operator+=(static_string<M, CharT, Traits> const& str)
666 {
667 return append(str.data(), str.size());
668 }
669
670 static_string&
671 operator+=(CharT ch)
672 {
673 push_back(ch);
674 return *this;
675 }
676
677 static_string&
678 operator+=(CharT const* s)
679 {
680 return append(s);
681 }
682
683 static_string&
684 operator+=(std::initializer_list<CharT> init)
685 {
686 return append(init);
687 }
688
689 static_string&
690 operator+=(string_view_type const& str)
691 {
692 return append(str);
693 }
694
695 template<std::size_t M>
696 int
697 compare(static_string<M, CharT, Traits> const& str) const
698 {
699 return detail::lexicographical_compare<CharT, Traits>(
700 &s_[0], n_, &str.s_[0], str.n_);
701 }
702
703 template<std::size_t M>
704 int
705 compare(size_type pos1, size_type count1,
706 static_string<M, CharT, Traits> const& str) const
707 {
708 return detail::lexicographical_compare<CharT, Traits>(
709 substr(pos1, count1), str.data(), str.size());
710 }
711
712 template<std::size_t M>
713 int
714 compare(size_type pos1, size_type count1,
715 static_string<M, CharT, Traits> const& str,
716 size_type pos2, size_type count2 = npos) const
717 {
718 return detail::lexicographical_compare(
719 substr(pos1, count1), str.substr(pos2, count2));
720 }
721
722 int
723 compare(CharT const* s) const
724 {
725 return detail::lexicographical_compare<CharT, Traits>(
726 &s_[0], n_, s, Traits::length(s));
727 }
728
729 int
730 compare(size_type pos1, size_type count1,
731 CharT const* s) const
732 {
733 return detail::lexicographical_compare<CharT, Traits>(
734 substr(pos1, count1), s, Traits::length(s));
735 }
736
737 int
738 compare(size_type pos1, size_type count1,
739 CharT const*s, size_type count2) const
740 {
741 return detail::lexicographical_compare<CharT, Traits>(
742 substr(pos1, count1), s, count2);
743 }
744
745 int
746 compare(string_view_type str) const
747 {
748 return detail::lexicographical_compare<CharT, Traits>(
749 &s_[0], n_, str.data(), str.size());
750 }
751
752 int
753 compare(size_type pos1, size_type count1,
754 string_view_type str) const
755 {
756 return detail::lexicographical_compare<CharT, Traits>(
757 substr(pos1, count1), str);
758 }
759
760 template<class T>
761 #if BOOST_BEAST_DOXYGEN
762 int
763 #else
764 typename std::enable_if<
765 std::is_convertible<T const&, string_view_type>::value &&
766 ! std::is_convertible<T const&, CharT const*>::value,
767 int>::type
768 #endif
769 compare(size_type pos1, size_type count1,
770 T const& t, size_type pos2,
771 size_type count2 = npos) const
772 {
773 return compare(pos1, count1,
774 string_view_type(t).substr(pos2, count2));
775 }
776
777 string_view_type
778 substr(size_type pos = 0, size_type count = npos) const;
779
780 /// Copy a substring (pos, pos+count) to character string pointed to by `dest`.
781 size_type
782 copy(CharT* dest, size_type count, size_type pos = 0) const;
783
784 /** Changes the number of characters stored.
785
786 If the resulting string is larger, the new
787 characters are uninitialized.
788 */
789 void
790 resize(std::size_t n);
791
792 /** Changes the number of characters stored.
793
794 If the resulting string is larger, the new
795 characters are initialized to the value of `c`.
796 */
797 void
798 resize(std::size_t n, CharT c);
799
800 /// Exchange the contents of this string with another.
801 void
802 swap(static_string& str);
803
804 /// Exchange the contents of this string with another.
805 template<std::size_t M>
806 void
807 swap(static_string<M, CharT, Traits>& str);
808
809 //
810 // Search
811 //
812
813 private:
814 static_string&
815 assign_char(CharT ch, std::true_type);
816
817 static_string&
818 assign_char(CharT ch, std::false_type);
819 };
820
821 //
822 // Disallowed operations
823 //
824
825 // These operations are explicitly deleted since
826 // there is no reasonable implementation possible.
827
828 template<std::size_t N, std::size_t M, class CharT, class Traits>
829 void
830 operator+(
831 static_string<N, CharT, Traits>const&,
832 static_string<M, CharT, Traits>const&) = delete;
833
834 template<std::size_t N, class CharT, class Traits>
835 void
836 operator+(CharT const*,
837 static_string<N, CharT, Traits>const&) = delete;
838
839 template<std::size_t N, class CharT, class Traits>
840 void
841 operator+(CharT,
842 static_string<N, CharT, Traits> const&) = delete;
843
844 template<std::size_t N, class CharT, class Traits>
845 void
846 operator+(static_string<N, CharT, Traits> const&,
847 CharT const*) = delete;
848
849 template<std::size_t N, class CharT, class Traits>
850 void
851 operator+(static_string<N, CharT, Traits> const&, CharT) = delete;
852
853 //
854 // Non-member functions
855 //
856
857 template<std::size_t N, std::size_t M,
858 class CharT, class Traits>
859 bool
860 operator==(
861 static_string<N, CharT, Traits> const& lhs,
862 static_string<M, CharT, Traits> const& rhs)
863 {
864 return lhs.compare(rhs) == 0;
865 }
866
867 template<std::size_t N, std::size_t M,
868 class CharT, class Traits>
869 bool
870 operator!=(
871 static_string<N, CharT, Traits> const& lhs,
872 static_string<M, CharT, Traits> const& rhs)
873 {
874 return lhs.compare(rhs) != 0;
875 }
876
877 template<std::size_t N, std::size_t M,
878 class CharT, class Traits>
879 bool
880 operator<(
881 static_string<N, CharT, Traits> const& lhs,
882 static_string<M, CharT, Traits> const& rhs)
883 {
884 return lhs.compare(rhs) < 0;
885 }
886
887 template<std::size_t N, std::size_t M,
888 class CharT, class Traits>
889 bool
890 operator<=(
891 static_string<N, CharT, Traits> const& lhs,
892 static_string<M, CharT, Traits> const& rhs)
893 {
894 return lhs.compare(rhs) <= 0;
895 }
896
897 template<std::size_t N, std::size_t M,
898 class CharT, class Traits>
899 bool
900 operator>(
901 static_string<N, CharT, Traits> const& lhs,
902 static_string<M, CharT, Traits> const& rhs)
903 {
904 return lhs.compare(rhs) > 0;
905 }
906
907 template<std::size_t N, std::size_t M,
908 class CharT, class Traits>
909 bool
910 operator>=(
911 static_string<N, CharT, Traits> const& lhs,
912 static_string<M, CharT, Traits> const& rhs)
913 {
914 return lhs.compare(rhs) >= 0;
915 }
916
917 template<std::size_t N, class CharT, class Traits>
918 bool
919 operator==(
920 CharT const* lhs,
921 static_string<N, CharT, Traits> const& rhs)
922 {
923 return detail::lexicographical_compare<CharT, Traits>(
924 lhs, Traits::length(lhs),
925 rhs.data(), rhs.size()) == 0;
926 }
927
928 template<std::size_t N, class CharT, class Traits>
929 bool
930 operator==(
931 static_string<N, CharT, Traits> const& lhs,
932 CharT const* rhs)
933 {
934 return detail::lexicographical_compare<CharT, Traits>(
935 lhs.data(), lhs.size(),
936 rhs, Traits::length(rhs)) == 0;
937 }
938
939 template<std::size_t N, class CharT, class Traits>
940 bool
941 operator!=(
942 CharT const* lhs,
943 static_string<N, CharT, Traits> const& rhs)
944 {
945 return detail::lexicographical_compare<CharT, Traits>(
946 lhs, Traits::length(lhs),
947 rhs.data(), rhs.size()) != 0;
948 }
949
950 template<std::size_t N, class CharT, class Traits>
951 bool
952 operator!=(
953 static_string<N, CharT, Traits> const& lhs,
954 CharT const* rhs)
955 {
956 return detail::lexicographical_compare<CharT, Traits>(
957 lhs.data(), lhs.size(),
958 rhs, Traits::length(rhs)) != 0;
959 }
960
961 template<std::size_t N, class CharT, class Traits>
962 bool
963 operator<(
964 CharT const* lhs,
965 static_string<N, CharT, Traits> const& rhs)
966 {
967 return detail::lexicographical_compare<CharT, Traits>(
968 lhs, Traits::length(lhs),
969 rhs.data(), rhs.size()) < 0;
970 }
971
972 template<std::size_t N, class CharT, class Traits>
973 bool
974 operator<(
975 static_string<N, CharT, Traits> const& lhs,
976 CharT const* rhs)
977 {
978 return detail::lexicographical_compare<CharT, Traits>(
979 lhs.data(), lhs.size(),
980 rhs, Traits::length(rhs)) < 0;
981 }
982
983 template<std::size_t N, class CharT, class Traits>
984 bool
985 operator<=(
986 CharT const* lhs,
987 static_string<N, CharT, Traits> const& rhs)
988 {
989 return detail::lexicographical_compare<CharT, Traits>(
990 lhs, Traits::length(lhs),
991 rhs.data(), rhs.size()) <= 0;
992 }
993
994 template<std::size_t N, class CharT, class Traits>
995 bool
996 operator<=(
997 static_string<N, CharT, Traits> const& lhs,
998 CharT const* rhs)
999 {
1000 return detail::lexicographical_compare<CharT, Traits>(
1001 lhs.data(), lhs.size(),
1002 rhs, Traits::length(rhs)) <= 0;
1003 }
1004
1005 template<std::size_t N, class CharT, class Traits>
1006 bool
1007 operator>(
1008 CharT const* lhs,
1009 static_string<N, CharT, Traits> const& rhs)
1010 {
1011 return detail::lexicographical_compare<CharT, Traits>(
1012 lhs, Traits::length(lhs),
1013 rhs.data(), rhs.size()) > 0;
1014 }
1015
1016 template<std::size_t N, class CharT, class Traits>
1017 bool
1018 operator>(
1019 static_string<N, CharT, Traits> const& lhs,
1020 CharT const* rhs)
1021 {
1022 return detail::lexicographical_compare<CharT, Traits>(
1023 lhs.data(), lhs.size(),
1024 rhs, Traits::length(rhs)) > 0;
1025 }
1026
1027 template<std::size_t N, class CharT, class Traits>
1028 bool
1029 operator>=(
1030 CharT const* lhs,
1031 static_string<N, CharT, Traits> const& rhs)
1032 {
1033 return detail::lexicographical_compare<CharT, Traits>(
1034 lhs, Traits::length(lhs),
1035 rhs.data(), rhs.size()) >= 0;
1036 }
1037
1038 template<std::size_t N, class CharT, class Traits>
1039 bool
1040 operator>=(
1041 static_string<N, CharT, Traits> const& lhs,
1042 CharT const* rhs)
1043 {
1044 return detail::lexicographical_compare<CharT, Traits>(
1045 lhs.data(), lhs.size(),
1046 rhs, Traits::length(rhs)) >= 0;
1047 }
1048
1049 //
1050 // swap
1051 //
1052
1053 template<std::size_t N, class CharT, class Traits>
1054 void
1055 swap(
1056 static_string<N, CharT, Traits>& lhs,
1057 static_string<N, CharT, Traits>& rhs)
1058 {
1059 lhs.swap(rhs);
1060 }
1061
1062 template<std::size_t N, std::size_t M,
1063 class CharT, class Traits>
1064 void
1065 swap(
1066 static_string<N, CharT, Traits>& lhs,
1067 static_string<M, CharT, Traits>& rhs)
1068 {
1069 lhs.swap(rhs);
1070 }
1071
1072 //
1073 // Input/Output
1074 //
1075
1076 template<std::size_t N, class CharT, class Traits>
1077 std::basic_ostream<CharT, Traits>&
1078 operator<<(std::basic_ostream<CharT, Traits>& os,
1079 static_string<N, CharT, Traits> const& str)
1080 {
1081 return os << static_cast<
1082 beast::basic_string_view<CharT, Traits>>(str);
1083 }
1084
1085 //
1086 // Numeric conversions
1087 //
1088
1089 /** Returns a static string representing an integer as a decimal.
1090
1091 @param x The signed or unsigned integer to convert.
1092 This must be an integral type.
1093
1094 @return A @ref static_string with an implementation defined
1095 maximum size large enough to hold the longest possible decimal
1096 representation of any integer of the given type.
1097 */
1098 template<
1099 class Integer
1100 #ifndef BOOST_BEAST_DOXYGEN
1101 ,class = typename std::enable_if<
1102 std::is_integral<Integer>::value>::type
1103 #endif
1104 >
1105 static_string<detail::max_digits(sizeof(Integer))>
1106 to_static_string(Integer x);
1107
1108 } // beast
1109 } // boost
1110
1111 #include <boost/beast/core/impl/static_string.hpp>
1112
1113 #endif