2 // Copyright (c) 2013-2017 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)
8 #ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
9 #define BEAST_WEBSOCKET_STATIC_STRING_HPP
11 #include <beast/config.hpp>
12 #include <beast/core/detail/type_traits.hpp>
21 /** A string with a fixed-size storage area.
23 These objects behave like `std::string` except that the storage
24 is not dynamically allocated but rather fixed in size.
26 These strings offer performance advantages when a protocol
27 imposes a natural small upper limit on the size of a value.
29 @note The stored string is always null-terminated.
34 class Traits = std::char_traits<CharT>>
37 template<std::size_t, class, class>
38 friend class static_string;
41 std::array<CharT, N+1> s_;
44 using traits_type = Traits;
45 using value_type = typename Traits::char_type;
46 using size_type = std::size_t;
47 using difference_type = std::ptrdiff_t;
48 using pointer = value_type*;
49 using reference = value_type&;
50 using const_pointer = value_type const*;
51 using const_reference = value_type const&;
52 using iterator = value_type*;
53 using const_iterator = value_type const*;
54 using reverse_iterator =
55 std::reverse_iterator<iterator>;
56 using const_reverse_iterator =
57 std::reverse_iterator<const_iterator>;
59 /** Default constructor.
61 The string is initially empty, and null terminated.
66 static_string(static_string const& s);
69 template<std::size_t M>
70 static_string(static_string<M, CharT, Traits> const& s);
74 operator=(static_string const& s);
77 template<std::size_t M>
79 operator=(static_string<M, CharT, Traits> const& s);
81 /// Construct from string literal.
82 template<std::size_t M>
83 static_string(const CharT (&s)[M]);
85 /// Assign from string literal.
86 template<std::size_t M>
87 static_string& operator=(const CharT (&s)[M]);
89 /// Access specified character with bounds checking.
93 /// Access specified character with bounds checking.
95 at(size_type pos) const;
97 /// Access specified character.
99 operator[](size_type pos)
104 /// Access specified character.
106 operator[](size_type pos) const
111 /// Accesses the first character.
118 /// Accesses the first character.
125 /// Accesses the last character.
132 /// Accesses the last character.
139 /// Returns a pointer to the first character of a string.
146 /// Returns a pointer to the first character of a string.
153 /// Returns a non-modifiable standard C character array version of the string.
160 /// Returns an iterator to the beginning.
167 /// Returns an iterator to the beginning.
174 /// Returns an iterator to the beginning.
181 /// Returns an iterator to the end.
188 /// Returns an iterator to the end.
195 /// Returns an iterator to the end.
202 /// Returns a reverse iterator to the beginning.
206 return reverse_iterator{end()};
209 /// Returns a reverse iterator to the beginning.
210 const_reverse_iterator
213 return const_reverse_iterator{cend()};
216 /// Returns a reverse iterator to the beginning.
217 const_reverse_iterator
220 return const_reverse_iterator{cend()};
223 /// Returns a reverse iterator to the end.
227 return reverse_iterator{begin()};
230 /// Returns a reverse iterator to the end.
231 const_reverse_iterator
234 return const_reverse_iterator{cbegin()};
237 /// Returns a reverse iterator to the end.
238 const_reverse_iterator
241 return const_reverse_iterator{cbegin()};
244 /// Returns `true` if the string is empty.
251 /// Returns the number of characters, excluding the null terminator.
258 /// Returns the maximum number of characters that can be stored, excluding the null terminator.
265 /// Returns the number of characters that can be held in currently allocated storage.
272 /// Clears the contents.
279 /** Changes the number of characters stored.
281 @note No value-initialization is performed.
284 resize(std::size_t n);
286 /** Changes the number of characters stored.
288 If the resulting string is larger, the new
289 characters are initialized to the value of `c`.
292 resize(std::size_t n, CharT c);
294 /// Compare two character sequences.
295 template<std::size_t M>
297 compare(static_string<M, CharT, Traits> const& rhs) const;
299 /// Return the characters as a `basic_string`.
300 std::basic_string<CharT, Traits>
303 return std::basic_string<
304 CharT, Traits>{&s_[0], n_};
309 assign(CharT const* s);
312 template<std::size_t N, class CharT, class Traits>
313 static_string<N, CharT, Traits>::
320 template<std::size_t N, class CharT, class Traits>
321 static_string<N, CharT, Traits>::
322 static_string(static_string const& s)
325 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
328 template<std::size_t N, class CharT, class Traits>
329 template<std::size_t M>
330 static_string<N, CharT, Traits>::
331 static_string(static_string<M, CharT, Traits> const& s)
334 throw detail::make_exception<std::length_error>(
335 "static_string overflow", __FILE__, __LINE__);
337 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
340 template<std::size_t N, class CharT, class Traits>
342 static_string<N, CharT, Traits>::
343 operator=(static_string const& s) ->
347 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
351 template<std::size_t N, class CharT, class Traits>
352 template<std::size_t M>
354 static_string<N, CharT, Traits>::
355 operator=(static_string<M, CharT, Traits> const& s) ->
359 throw detail::make_exception<std::length_error>(
360 "static_string overflow", __FILE__, __LINE__);
362 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
366 template<std::size_t N, class CharT, class Traits>
367 template<std::size_t M>
368 static_string<N, CharT, Traits>::
369 static_string(const CharT (&s)[M])
372 static_assert(M-1 <= N,
373 "static_string overflow");
374 Traits::copy(&s_[0], &s[0], M);
377 template<std::size_t N, class CharT, class Traits>
378 template<std::size_t M>
380 static_string<N, CharT, Traits>::
381 operator=(const CharT (&s)[M]) ->
384 static_assert(M-1 <= N,
385 "static_string overflow");
387 Traits::copy(&s_[0], &s[0], M);
391 template<std::size_t N, class CharT, class Traits>
393 static_string<N, CharT, Traits>::
398 throw detail::make_exception<std::out_of_range>(
399 "invalid pos", __FILE__, __LINE__);
403 template<std::size_t N, class CharT, class Traits>
405 static_string<N, CharT, Traits>::
406 at(size_type pos) const ->
410 throw detail::make_exception<std::out_of_range>(
411 "static_string::at", __FILE__, __LINE__);
415 template<std::size_t N, class CharT, class Traits>
417 static_string<N, CharT, Traits>::
418 resize(std::size_t n)
421 throw detail::make_exception<std::length_error>(
422 "static_string overflow", __FILE__, __LINE__);
427 template<std::size_t N, class CharT, class Traits>
429 static_string<N, CharT, Traits>::
430 resize(std::size_t n, CharT c)
433 throw detail::make_exception<std::length_error>(
434 "static_string overflow", __FILE__, __LINE__);
436 Traits::assign(&s_[n_], n - n_, c);
441 template<std::size_t N, class CharT, class Traits>
442 template<std::size_t M>
444 static_string<N, CharT, Traits>::
445 compare(static_string<M, CharT, Traits> const& rhs) const
447 if(size() < rhs.size())
449 auto const v = Traits::compare(
450 data(), rhs.data(), size());
455 else if(size() > rhs.size())
457 auto const v = Traits::compare(
458 data(), rhs.data(), rhs.size());
463 return Traits::compare(data(), rhs.data(), size());
466 template<std::size_t N, class CharT, class Traits>
468 static_string<N, CharT, Traits>::
469 assign(CharT const* s)
471 auto const n = Traits::length(s);
473 throw detail::make_exception<std::out_of_range>(
474 "too large", __FILE__, __LINE__);
476 Traits::copy(&s_[0], s, n_ + 1);
481 template<std::size_t N, std::size_t M, class CharT, class Traits>
484 static_string<N, CharT, Traits> const& lhs,
489 auto const v = Traits::compare(
490 lhs.data(), &s[0], lhs.size());
495 else if(lhs.size() > M-1)
497 auto const v = Traits::compare(
498 lhs.data(), &s[0], M-1);
503 return Traits::compare(lhs.data(), &s[0], lhs.size());
506 template<std::size_t N, std::size_t M, class CharT, class Traits>
511 static_string<N, CharT, Traits> const& rhs)
513 return -compare(rhs, s);
518 template<std::size_t N, std::size_t M, class CharT, class Traits>
521 static_string<N, CharT, Traits> const& lhs,
522 static_string<M, CharT, Traits> const& rhs)
524 return lhs.compare(rhs) == 0;
527 template<std::size_t N, std::size_t M, class CharT, class Traits>
530 static_string<N, CharT, Traits> const& lhs,
531 static_string<M, CharT, Traits> const& rhs)
533 return lhs.compare(rhs) != 0;
536 template<std::size_t N, std::size_t M, class CharT, class Traits>
539 static_string<N, CharT, Traits> const& lhs,
540 static_string<M, CharT, Traits> const& rhs)
542 return lhs.compare(rhs) < 0;
545 template<std::size_t N, std::size_t M, class CharT, class Traits>
548 static_string<N, CharT, Traits> const& lhs,
549 static_string<M, CharT, Traits> const& rhs)
551 return lhs.compare(rhs) <= 0;
554 template<std::size_t N, std::size_t M, class CharT, class Traits>
557 static_string<N, CharT, Traits> const& lhs,
558 static_string<M, CharT, Traits> const& rhs)
560 return lhs.compare(rhs) > 0;
563 template<std::size_t N, std::size_t M, class CharT, class Traits>
566 static_string<N, CharT, Traits> const& lhs,
567 static_string<M, CharT, Traits> const& rhs)
569 return lhs.compare(rhs) >= 0;
574 template<std::size_t N, std::size_t M, class CharT, class Traits>
578 static_string<M, CharT, Traits> const& rhs)
580 return detail::compare(s, rhs) == 0;
583 template<std::size_t N, class CharT, class Traits, std::size_t M>
586 static_string<N, CharT, Traits> const& lhs,
589 return detail::compare(lhs, s) == 0;
592 template<std::size_t N, std::size_t M, class CharT, class Traits>
596 static_string<M, CharT, Traits> const& rhs)
598 return detail::compare(s, rhs) != 0;
601 template<std::size_t N, class CharT, class Traits, std::size_t M>
604 static_string<N, CharT, Traits> const& lhs,
607 return detail::compare(lhs, s) != 0;
610 template<std::size_t N, std::size_t M, class CharT, class Traits>
614 static_string<M, CharT, Traits> const& rhs)
616 return detail::compare(s, rhs) < 0;
619 template<std::size_t N, class CharT, class Traits, std::size_t M>
622 static_string<N, CharT, Traits> const& lhs,
625 return detail::compare(lhs, s) < 0;
628 template<std::size_t N, std::size_t M, class CharT, class Traits>
632 static_string<M, CharT, Traits> const& rhs)
634 return detail::compare(s, rhs) <= 0;
637 template<std::size_t N, class CharT, class Traits, std::size_t M>
640 static_string<N, CharT, Traits> const& lhs,
643 return detail::compare(lhs, s) <= 0;
646 template<std::size_t N, std::size_t M, class CharT, class Traits>
650 static_string<M, CharT, Traits> const& rhs)
652 return detail::compare(s, rhs) > 0;
655 template<std::size_t N, class CharT, class Traits, std::size_t M>
658 static_string<N, CharT, Traits> const& lhs,
661 return detail::compare(lhs, s) > 0;
664 template<std::size_t N, std::size_t M, class CharT, class Traits>
668 static_string<M, CharT, Traits> const& rhs)
670 return detail::compare(s, rhs) >= 0;
673 template<std::size_t N, class CharT, class Traits, std::size_t M>
676 static_string<N, CharT, Traits> const& lhs,
679 return detail::compare(lhs, s) >= 0;