2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_STATIC_STRING_HPP
11 #define BOOST_BEAST_STATIC_STRING_HPP
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/string.hpp>
15 #include <boost/beast/core/detail/static_string.hpp>
18 #include <initializer_list>
22 #include <type_traits>
27 /** A modifiable string with a fixed-size storage area.
29 These objects behave like `std::string` except that the storage
30 is not dynamically allocated but rather fixed in size.
32 These strings offer performance advantages when a protocol
33 imposes a natural small upper limit on the size of a value.
35 @note The stored string is always null-terminated.
42 class Traits = std::char_traits<CharT>>
45 template<std::size_t, class, class>
46 friend class static_string;
51 Traits::assign(s_[n_], 0);
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>;
77 /// The type of `string_view` returned by the interface
78 using string_view_type =
79 basic_string_view<CharT, Traits>;
85 /// Maximum size of the string excluding the null terminator
86 static std::size_t constexpr max_size_n = N;
89 static constexpr size_type npos = size_type(-1);
95 /// Default constructor (empty string).
98 /** Construct with count copies of character `ch`.
100 The behavior is undefined if `count >= npos`
102 static_string(size_type count, CharT ch);
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,
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);
114 /// Construct with the first `count` characters of `s`, including nulls.
115 static_string(CharT const* s, size_type count);
117 /// Construct from a null terminated string.
118 static_string(CharT const* s);
120 /// Construct from a range of characters
121 template<class InputIt>
122 static_string(InputIt first, InputIt last);
124 /// Copy constructor.
125 static_string(static_string const& other);
127 /// Copy constructor.
128 template<std::size_t M>
129 static_string(static_string<M, CharT, Traits> const& other);
131 /// Construct from an initializer list
132 static_string(std::initializer_list<CharT> init);
134 /// Construct from a `string_view`
136 static_string(string_view_type sv);
138 /** Construct from any object convertible to `string_view_type`.
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.
144 #if BOOST_BEAST_DOXYGEN
147 template<class T, class = typename std::enable_if<
148 std::is_convertible<T, string_view_type>::value>::type>
150 static_string(T const& t, size_type pos, size_type n);
158 operator=(static_string const& str)
164 template<std::size_t M>
166 operator=(static_string<M, CharT, Traits> const& str)
171 /// Assign from null-terminated string.
173 operator=(CharT const* s);
175 /// Assign from single character.
179 return assign_char(ch,
180 std::integral_constant<bool, (N>0)>{});
183 /// Assign from initializer list.
185 operator=(std::initializer_list<CharT> init)
190 /// Assign from `string_view_type`.
192 operator=(string_view_type sv)
197 /// Assign `count` copies of `ch`.
199 assign(size_type count, CharT ch);
201 /// Assign from another `static_string`
203 assign(static_string const& str);
205 // VFALCO NOTE this could come in two flavors,
206 // N>M and N<M, and skip the exception
209 /// Assign from another `static_string`
210 template<std::size_t M>
212 assign(static_string<M, CharT, Traits> const& str)
214 return assign(str.data(), str.size());
217 /// Assign `count` characterss starting at `npos` from `other`.
218 template<std::size_t M>
220 assign(static_string<M, CharT, Traits> const& str,
221 size_type pos, size_type count = npos);
223 /// Assign the first `count` characters of `s`, including nulls.
225 assign(CharT const* s, size_type count);
227 /// Assign a null terminated string.
229 assign(CharT const* s)
231 return assign(s, Traits::length(s));
234 /// Assign from an iterator range of characters.
235 template<class InputIt>
237 assign(InputIt first, InputIt last);
239 /// Assign from initializer list.
241 assign(std::initializer_list<CharT> init)
243 return assign(init.begin(), init.end());
246 /// Assign from `string_view_type`.
248 assign(string_view_type str)
250 return assign(str.data(), str.size());
253 /** Assign from any object convertible to `string_view_type`.
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.
260 #if BOOST_BEAST_DOXYGEN
263 typename std::enable_if<std::is_convertible<T,
264 string_view_type>::value, static_string&>::type
267 size_type pos, size_type count = npos);
273 /// Access specified character with bounds checking.
277 /// Access specified character with bounds checking.
279 at(size_type pos) const;
281 /// Access specified character.
283 operator[](size_type pos)
288 /// Access specified character.
290 operator[](size_type pos) const
295 /// Accesses the first character.
302 /// Accesses the first character.
309 /// Accesses the last character.
316 /// Accesses the last character.
323 /// Returns a pointer to the first character of a string.
330 /// Returns a pointer to the first character of a string.
337 /// Returns a non-modifiable standard C character array version of the string.
344 /// Convert a static string to a `string_view_type`
345 operator string_view_type() const
347 return basic_string_view<
348 CharT, Traits>{data(), size()};
355 /// Returns an iterator to the beginning.
362 /// Returns an iterator to the beginning.
369 /// Returns an iterator to the beginning.
376 /// Returns an iterator to the end.
383 /// Returns an iterator to the end.
390 /// Returns an iterator to the end.
397 /// Returns a reverse iterator to the beginning.
401 return reverse_iterator{end()};
404 /// Returns a reverse iterator to the beginning.
405 const_reverse_iterator
408 return const_reverse_iterator{cend()};
411 /// Returns a reverse iterator to the beginning.
412 const_reverse_iterator
415 return const_reverse_iterator{cend()};
418 /// Returns a reverse iterator to the end.
422 return reverse_iterator{begin()};
425 /// Returns a reverse iterator to the end.
426 const_reverse_iterator
429 return const_reverse_iterator{cbegin()};
432 /// Returns a reverse iterator to the end.
433 const_reverse_iterator
436 return const_reverse_iterator{cbegin()};
443 /// Returns `true` if the string is empty.
450 /// Returns the number of characters, excluding the null terminator.
457 /// Returns the number of characters, excluding the null terminator.
464 /// Returns the maximum number of characters that can be stored, excluding the null terminator.
471 /** Reserves storage.
473 This actually just throws an exception if `n > N`,
474 otherwise does nothing since the storage is fixed.
477 reserve(std::size_t n);
479 /// Returns the number of characters that can be held in currently allocated storage.
486 /** Reduces memory usage by freeing unused memory.
488 This actually does nothing, since the storage is fixed.
499 /// Clears the contents.
504 insert(size_type index, size_type count, CharT ch);
507 insert(size_type index, CharT const* s)
509 return insert(index, s, Traits::length(s));
513 insert(size_type index, CharT const* s, size_type count);
515 template<std::size_t M>
517 insert(size_type index,
518 static_string<M, CharT, Traits> const& str)
520 return insert(index, str.data(), str.size());
523 template<std::size_t M>
525 insert(size_type index,
526 static_string<M, CharT, Traits> const& str,
527 size_type index_str, size_type count = npos);
530 insert(const_iterator pos, CharT ch)
532 return insert(pos, 1, ch);
536 insert(const_iterator pos, size_type count, CharT ch);
538 template<class InputIt>
539 #if BOOST_BEAST_DOXYGEN
542 typename std::enable_if<
543 detail::is_input_iterator<InputIt>::value,
546 insert(const_iterator pos, InputIt first, InputIt last);
549 insert(const_iterator pos, std::initializer_list<CharT> init)
551 return insert(pos, init.begin(), init.end());
555 insert(size_type index, string_view_type str)
557 return insert(index, str.data(), str.size());
561 #if BOOST_BEAST_DOXYGEN
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
569 insert(size_type index, T const& t,
570 size_type index_str, size_type count = npos);
573 erase(size_type index = 0, size_type count = npos);
576 erase(const_iterator pos);
579 erase(const_iterator first, const_iterator last);
587 Traits::assign(s_[--n_], 0);
591 append(size_type count, CharT ch)
593 insert(end(), count, ch);
597 template<std::size_t M>
599 append(static_string<M, CharT, Traits> const& str)
605 template<std::size_t M>
607 append(static_string<M, CharT, Traits> const& str,
608 size_type pos, size_type count = npos);
611 append(CharT const* s, size_type count)
613 insert(size(), s, count);
618 append(CharT const* s)
624 template<class InputIt>
625 #if BOOST_BEAST_DOXYGEN
628 typename std::enable_if<
629 detail::is_input_iterator<InputIt>::value,
630 static_string&>::type
632 append(InputIt first, InputIt last)
634 insert(end(), first, last);
639 append(std::initializer_list<CharT> init)
646 append(string_view_type sv)
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)
659 insert(size(), t, pos, count);
663 template<std::size_t M>
665 operator+=(static_string<M, CharT, Traits> const& str)
667 return append(str.data(), str.size());
678 operator+=(CharT const* s)
684 operator+=(std::initializer_list<CharT> init)
690 operator+=(string_view_type const& str)
695 template<std::size_t M>
697 compare(static_string<M, CharT, Traits> const& str) const
699 return detail::lexicographical_compare<CharT, Traits>(
700 &s_[0], n_, &str.s_[0], str.n_);
703 template<std::size_t M>
705 compare(size_type pos1, size_type count1,
706 static_string<M, CharT, Traits> const& str) const
708 return detail::lexicographical_compare<CharT, Traits>(
709 substr(pos1, count1), str.data(), str.size());
712 template<std::size_t M>
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
718 return detail::lexicographical_compare(
719 substr(pos1, count1), str.substr(pos2, count2));
723 compare(CharT const* s) const
725 return detail::lexicographical_compare<CharT, Traits>(
726 &s_[0], n_, s, Traits::length(s));
730 compare(size_type pos1, size_type count1,
731 CharT const* s) const
733 return detail::lexicographical_compare<CharT, Traits>(
734 substr(pos1, count1), s, Traits::length(s));
738 compare(size_type pos1, size_type count1,
739 CharT const*s, size_type count2) const
741 return detail::lexicographical_compare<CharT, Traits>(
742 substr(pos1, count1), s, count2);
746 compare(string_view_type str) const
748 return detail::lexicographical_compare<CharT, Traits>(
749 &s_[0], n_, str.data(), str.size());
753 compare(size_type pos1, size_type count1,
754 string_view_type str) const
756 return detail::lexicographical_compare<CharT, Traits>(
757 substr(pos1, count1), str);
761 #if BOOST_BEAST_DOXYGEN
764 typename std::enable_if<
765 std::is_convertible<T const&, string_view_type>::value &&
766 ! std::is_convertible<T const&, CharT const*>::value,
769 compare(size_type pos1, size_type count1,
770 T const& t, size_type pos2,
771 size_type count2 = npos) const
773 return compare(pos1, count1,
774 string_view_type(t).substr(pos2, count2));
778 substr(size_type pos = 0, size_type count = npos) const;
780 /// Copy a substring (pos, pos+count) to character string pointed to by `dest`.
782 copy(CharT* dest, size_type count, size_type pos = 0) const;
784 /** Changes the number of characters stored.
786 If the resulting string is larger, the new
787 characters are uninitialized.
790 resize(std::size_t n);
792 /** Changes the number of characters stored.
794 If the resulting string is larger, the new
795 characters are initialized to the value of `c`.
798 resize(std::size_t n, CharT c);
800 /// Exchange the contents of this string with another.
802 swap(static_string& str);
804 /// Exchange the contents of this string with another.
805 template<std::size_t M>
807 swap(static_string<M, CharT, Traits>& str);
815 assign_char(CharT ch, std::true_type);
818 assign_char(CharT ch, std::false_type);
822 // Disallowed operations
825 // These operations are explicitly deleted since
826 // there is no reasonable implementation possible.
828 template<std::size_t N, std::size_t M, class CharT, class Traits>
831 static_string<N, CharT, Traits>const&,
832 static_string<M, CharT, Traits>const&) = delete;
834 template<std::size_t N, class CharT, class Traits>
836 operator+(CharT const*,
837 static_string<N, CharT, Traits>const&) = delete;
839 template<std::size_t N, class CharT, class Traits>
842 static_string<N, CharT, Traits> const&) = delete;
844 template<std::size_t N, class CharT, class Traits>
846 operator+(static_string<N, CharT, Traits> const&,
847 CharT const*) = delete;
849 template<std::size_t N, class CharT, class Traits>
851 operator+(static_string<N, CharT, Traits> const&, CharT) = delete;
854 // Non-member functions
857 template<std::size_t N, std::size_t M,
858 class CharT, class Traits>
861 static_string<N, CharT, Traits> const& lhs,
862 static_string<M, CharT, Traits> const& rhs)
864 return lhs.compare(rhs) == 0;
867 template<std::size_t N, std::size_t M,
868 class CharT, class Traits>
871 static_string<N, CharT, Traits> const& lhs,
872 static_string<M, CharT, Traits> const& rhs)
874 return lhs.compare(rhs) != 0;
877 template<std::size_t N, std::size_t M,
878 class CharT, class Traits>
881 static_string<N, CharT, Traits> const& lhs,
882 static_string<M, CharT, Traits> const& rhs)
884 return lhs.compare(rhs) < 0;
887 template<std::size_t N, std::size_t M,
888 class CharT, class Traits>
891 static_string<N, CharT, Traits> const& lhs,
892 static_string<M, CharT, Traits> const& rhs)
894 return lhs.compare(rhs) <= 0;
897 template<std::size_t N, std::size_t M,
898 class CharT, class Traits>
901 static_string<N, CharT, Traits> const& lhs,
902 static_string<M, CharT, Traits> const& rhs)
904 return lhs.compare(rhs) > 0;
907 template<std::size_t N, std::size_t M,
908 class CharT, class Traits>
911 static_string<N, CharT, Traits> const& lhs,
912 static_string<M, CharT, Traits> const& rhs)
914 return lhs.compare(rhs) >= 0;
917 template<std::size_t N, class CharT, class Traits>
921 static_string<N, CharT, Traits> const& rhs)
923 return detail::lexicographical_compare<CharT, Traits>(
924 lhs, Traits::length(lhs),
925 rhs.data(), rhs.size()) == 0;
928 template<std::size_t N, class CharT, class Traits>
931 static_string<N, CharT, Traits> const& lhs,
934 return detail::lexicographical_compare<CharT, Traits>(
935 lhs.data(), lhs.size(),
936 rhs, Traits::length(rhs)) == 0;
939 template<std::size_t N, class CharT, class Traits>
943 static_string<N, CharT, Traits> const& rhs)
945 return detail::lexicographical_compare<CharT, Traits>(
946 lhs, Traits::length(lhs),
947 rhs.data(), rhs.size()) != 0;
950 template<std::size_t N, class CharT, class Traits>
953 static_string<N, CharT, Traits> const& lhs,
956 return detail::lexicographical_compare<CharT, Traits>(
957 lhs.data(), lhs.size(),
958 rhs, Traits::length(rhs)) != 0;
961 template<std::size_t N, class CharT, class Traits>
965 static_string<N, CharT, Traits> const& rhs)
967 return detail::lexicographical_compare<CharT, Traits>(
968 lhs, Traits::length(lhs),
969 rhs.data(), rhs.size()) < 0;
972 template<std::size_t N, class CharT, class Traits>
975 static_string<N, CharT, Traits> const& lhs,
978 return detail::lexicographical_compare<CharT, Traits>(
979 lhs.data(), lhs.size(),
980 rhs, Traits::length(rhs)) < 0;
983 template<std::size_t N, class CharT, class Traits>
987 static_string<N, CharT, Traits> const& rhs)
989 return detail::lexicographical_compare<CharT, Traits>(
990 lhs, Traits::length(lhs),
991 rhs.data(), rhs.size()) <= 0;
994 template<std::size_t N, class CharT, class Traits>
997 static_string<N, CharT, Traits> const& lhs,
1000 return detail::lexicographical_compare<CharT, Traits>(
1001 lhs.data(), lhs.size(),
1002 rhs, Traits::length(rhs)) <= 0;
1005 template<std::size_t N, class CharT, class Traits>
1009 static_string<N, CharT, Traits> const& rhs)
1011 return detail::lexicographical_compare<CharT, Traits>(
1012 lhs, Traits::length(lhs),
1013 rhs.data(), rhs.size()) > 0;
1016 template<std::size_t N, class CharT, class Traits>
1019 static_string<N, CharT, Traits> const& lhs,
1022 return detail::lexicographical_compare<CharT, Traits>(
1023 lhs.data(), lhs.size(),
1024 rhs, Traits::length(rhs)) > 0;
1027 template<std::size_t N, class CharT, class Traits>
1031 static_string<N, CharT, Traits> const& rhs)
1033 return detail::lexicographical_compare<CharT, Traits>(
1034 lhs, Traits::length(lhs),
1035 rhs.data(), rhs.size()) >= 0;
1038 template<std::size_t N, class CharT, class Traits>
1041 static_string<N, CharT, Traits> const& lhs,
1044 return detail::lexicographical_compare<CharT, Traits>(
1045 lhs.data(), lhs.size(),
1046 rhs, Traits::length(rhs)) >= 0;
1053 template<std::size_t N, class CharT, class Traits>
1056 static_string<N, CharT, Traits>& lhs,
1057 static_string<N, CharT, Traits>& rhs)
1062 template<std::size_t N, std::size_t M,
1063 class CharT, class Traits>
1066 static_string<N, CharT, Traits>& lhs,
1067 static_string<M, CharT, Traits>& rhs)
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)
1081 return os << static_cast<
1082 beast::basic_string_view<CharT, Traits>>(str);
1086 // Numeric conversions
1089 /** Returns a static string representing an integer as a decimal.
1091 @param x The signed or unsigned integer to convert.
1092 This must be an integral type.
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.
1100 #ifndef BOOST_BEAST_DOXYGEN
1101 ,class = typename std::enable_if<
1102 std::is_integral<Integer>::value>::type
1105 static_string<detail::max_digits(sizeof(Integer))>
1106 to_static_string(Integer x);
1111 #include <boost/beast/core/impl/static_string.hpp>