diff --git a/CMakeLists.txt b/CMakeLists.txt index 140a8e38..7ea2b2a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries(boost_beast Boost::optional Boost::smart_ptr Boost::static_assert + Boost::static_string Boost::system Boost::throw_exception Boost::type_traits diff --git a/include/boost/beast/core/detail/static_string.hpp b/include/boost/beast/core/detail/static_string.hpp index 3b080e91..13999b06 100644 --- a/include/boost/beast/core/detail/static_string.hpp +++ b/include/boost/beast/core/detail/static_string.hpp @@ -10,56 +10,15 @@ #ifndef BOOST_BEAST_DETAIL_STATIC_STRING_HPP #define BOOST_BEAST_DETAIL_STATIC_STRING_HPP -#include #include -#include +#include +#include #include namespace boost { namespace beast { namespace detail { -// Because k-ballo said so -template -using is_input_iterator = - std::integral_constant::value>; - -template -int -lexicographical_compare( - CharT const* s1, std::size_t n1, - CharT const* s2, std::size_t n2) -{ - if(n1 < n2) - return Traits::compare( - s1, s2, n1) <= 0 ? -1 : 1; - if(n1 > n2) - return Traits::compare( - s1, s2, n2) >= 0 ? 1 : -1; - return Traits::compare(s1, s2, n1); -} - -template -int -lexicographical_compare( - basic_string_view s1, - CharT const* s2, std::size_t n2) -{ - return detail::lexicographical_compare< - CharT, Traits>(s1.data(), s1.size(), s2, n2); -} - -template -int -lexicographical_compare( - basic_string_view s1, - basic_string_view s2) -{ - return detail::lexicographical_compare( - s1.data(), s1.size(), s2.data(), s2.size()); -} - // Maximum number of characters in the decimal // representation of a binary number. This includes // the potential minus sign. diff --git a/include/boost/beast/core/impl/static_string.hpp b/include/boost/beast/core/impl/static_string.hpp deleted file mode 100644 index 2e3e5617..00000000 --- a/include/boost/beast/core/impl/static_string.hpp +++ /dev/null @@ -1,583 +0,0 @@ -// -// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_IMPL_STATIC_STRING_HPP -#define BOOST_BEAST_IMPL_STATIC_STRING_HPP - -#include -#include - -namespace boost { -namespace beast { - -// -// (constructor) -// - -template -static_string:: -static_string() -{ - n_ = 0; - term(); -} - -template -static_string:: -static_string(size_type count, CharT ch) -{ - assign(count, ch); -} - -template -template -static_string:: -static_string(static_string const& other, - size_type pos) -{ - assign(other, pos); -} - -template -template -static_string:: -static_string(static_string const& other, - size_type pos, size_type count) -{ - assign(other, pos, count); -} - -template -static_string:: -static_string(CharT const* s, size_type count) -{ - assign(s, count); -} - -template -static_string:: -static_string(CharT const* s) -{ - auto const count = Traits::length(s); - if(count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "count > max_size()"}); - n_ = count; - Traits::copy(&s_[0], s, n_ + 1); -} - -template -template -static_string:: -static_string(InputIt first, InputIt last) -{ - assign(first, last); -} - -template -static_string:: -static_string(static_string const& s) -{ - assign(s); -} - -template -template -static_string:: -static_string(static_string const& s) -{ - assign(s); -} - -template -static_string:: -static_string(std::initializer_list init) -{ - assign(init.begin(), init.end()); -} - -template -static_string:: -static_string(string_view_type sv) -{ - assign(sv); -} - -template -template -static_string:: -static_string(T const& t, size_type pos, size_type n) -{ - assign(t, pos, n); -} - -// -// (assignment) -// - -template -auto -static_string:: -operator=(CharT const* s) -> - static_string& -{ - auto const count = Traits::length(s); - if(count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "count > max_size()"}); - n_ = count; - Traits::copy(&s_[0], s, n_ + 1); - return *this; -} - -template -auto -static_string:: -assign(size_type count, CharT ch) -> - static_string& -{ - if(count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "count > max_size()"}); - n_ = count; - Traits::assign(&s_[0], n_, ch); - term(); - return *this; -} - -template -auto -static_string:: -assign(static_string const& str) -> - static_string& -{ - n_ = str.n_; - auto const n = n_ + 1; - BOOST_BEAST_ASSUME(n != 0); - Traits::copy(&s_[0], &str.s_[0], n); - return *this; -} - -template -template -auto -static_string:: -assign(static_string const& str, - size_type pos, size_type count) -> - static_string& -{ - auto const ss = str.substr(pos, count); - return assign(ss.data(), ss.size()); -} - -template -auto -static_string:: -assign(CharT const* s, size_type count) -> - static_string& -{ - if(count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "count > max_size()"}); - n_ = count; - Traits::copy(&s_[0], s, n_); - term(); - return *this; -} - -template -template -auto -static_string:: -assign(InputIt first, InputIt last) -> - static_string& -{ - std::size_t const n = std::distance(first, last); - if(n > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "n > max_size()"}); - n_ = n; - for(auto it = &s_[0]; first != last; ++it, ++first) - Traits::assign(*it, *first); - term(); - return *this; -} - -template -template -auto -static_string:: -assign(T const& t, size_type pos, size_type count) -> - typename std::enable_if::value, static_string&>::type -{ - auto const sv = string_view_type(t).substr(pos, count); - if(sv.size() > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "sv.size() > max_size()"}); - n_ = sv.size(); - Traits::copy(&s_[0], &sv[0], n_); - term(); - return *this; -} - -// -// Element access -// - -template -auto -static_string:: -at(size_type pos) -> - reference -{ - if(pos >= size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "pos >= size()"}); - return s_[pos]; -} - -template -auto -static_string:: -at(size_type pos) const -> - const_reference -{ - if(pos >= size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "pos >= size()"}); - return s_[pos]; -} - -// -// Capacity -// - -template -void -static_string:: -reserve(std::size_t n) -{ - if(n > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "n > max_size()"}); -} - -// -// Operations -// - -template -void -static_string:: -clear() -{ - n_ = 0; - term(); -} - -template -auto -static_string:: -insert(size_type index, size_type count, CharT ch) -> - static_string& -{ - if(index > size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "index > size()"}); - insert(begin() + index, count, ch); - return *this; -} - -template -auto -static_string:: -insert(size_type index, CharT const* s, size_type count) -> - static_string& -{ - if(index > size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "index > size()"}); - if(size() + count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "size() + count > max_size()"}); - Traits::move( - &s_[index + count], &s_[index], size() - index); - n_ += count; - Traits::copy(&s_[index], s, count); - term(); - return *this; -} - -template -template -auto -static_string:: -insert(size_type index, - static_string const& str, - size_type index_str, size_type count) -> - static_string& -{ - auto const ss = str.substr(index_str, count); - return insert(index, ss.data(), ss.size()); -} - -template -auto -static_string:: -insert(const_iterator pos, size_type count, CharT ch) -> - iterator -{ - if(size() + count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "size() + count() > max_size()"}); - auto const index = pos - &s_[0]; - Traits::move( - &s_[index + count], &s_[index], size() - index); - n_ += count; - Traits::assign(&s_[index], count, ch); - term(); - return &s_[index]; -} - -template -template -auto -static_string:: -insert(const_iterator pos, InputIt first, InputIt last) -> - typename std::enable_if< - detail::is_input_iterator::value, - iterator>::type -{ - std::size_t const count = std::distance(first, last); - if(size() + count > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "size() + count > max_size()"}); - std::size_t const index = pos - begin(); - Traits::move( - &s_[index + count], &s_[index], size() - index); - n_ += count; - for(auto it = begin() + index; - first != last; ++it, ++first) - Traits::assign(*it, *first); - term(); - return begin() + index; -} - -template -template -auto -static_string:: -insert(size_type index, const T& t, - size_type index_str, size_type count) -> - typename std::enable_if::value && - ! std::is_convertible::value, - static_string&>::type -{ - auto const str = - string_view_type(t).substr(index_str, count); - return insert(index, str.data(), str.size()); -} - -template -auto -static_string:: -erase(size_type index, size_type count) -> - static_string& -{ - if(index > size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "index > size()"}); - auto const n = (std::min)(count, size() - index); - Traits::move( - &s_[index], &s_[index + n], size() - (index + n) + 1); - n_ -= n; - return *this; -} - -template -auto -static_string:: -erase(const_iterator pos) -> - iterator -{ - erase(pos - begin(), 1); - return begin() + (pos - begin()); -} - -template -auto -static_string:: -erase(const_iterator first, const_iterator last) -> - iterator -{ - erase(first - begin(), - std::distance(first, last)); - return begin() + (first - begin()); -} - -template -void -static_string:: -push_back(CharT ch) -{ - if(size() >= max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "size() >= max_size()"}); - Traits::assign(s_[n_++], ch); - term(); -} - -template -template -auto -static_string:: -append(static_string const& str, - size_type pos, size_type count) -> - static_string& -{ - // Valid range is [0, size) - if(pos >= str.size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "pos > str.size()"}); - string_view_type const ss{&str.s_[pos], - (std::min)(count, str.size() - pos)}; - insert(size(), ss.data(), ss.size()); - return *this; -} - -template -auto -static_string:: -substr(size_type pos, size_type count) const -> - string_view_type -{ - if(pos > size()) - BOOST_THROW_EXCEPTION(std::out_of_range{ - "pos > size()"}); - return{&s_[pos], (std::min)(count, size() - pos)}; -} - -template -auto -static_string:: -copy(CharT* dest, size_type count, size_type pos) const -> - size_type -{ - auto const str = substr(pos, count); - Traits::copy(dest, str.data(), str.size()); - return str.size(); -} - -template -void -static_string:: -resize(std::size_t n) -{ - if(n > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "n > max_size()"}); - if(n > n_) - Traits::assign(&s_[n_], n - n_, CharT{}); - n_ = n; - term(); -} - -template -void -static_string:: -resize(std::size_t n, CharT c) -{ - if(n > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "n > max_size()"}); - if(n > n_) - Traits::assign(&s_[n_], n - n_, c); - n_ = n; - term(); -} - -template -void -static_string:: -swap(static_string& str) -{ - static_string tmp(str); - str.n_ = n_; - Traits::copy(&str.s_[0], &s_[0], n_ + 1); - n_ = tmp.n_; - Traits::copy(&s_[0], &tmp.s_[0], n_ + 1); -} - -template -template -void -static_string:: -swap(static_string& str) -{ - if(size() > str.max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "size() > str.max_size()"}); - if(str.size() > max_size()) - BOOST_THROW_EXCEPTION(std::length_error{ - "str.size() > max_size()"}); - static_string tmp(str); - str.n_ = n_; - Traits::copy(&str.s_[0], &s_[0], n_ + 1); - n_ = tmp.n_; - Traits::copy(&s_[0], &tmp.s_[0], n_ + 1); -} - - -template -auto -static_string:: -assign_char(CharT ch, std::true_type) -> - static_string& -{ - n_ = 1; - Traits::assign(s_[0], ch); - term(); - return *this; -} - -template -auto -static_string:: -assign_char(CharT, std::false_type) -> - static_string& -{ - BOOST_THROW_EXCEPTION(std::length_error{ - "max_size() == 0"}); -} - -template -static_string -to_static_string(Integer x) -{ - using CharT = char; - using Traits = std::char_traits; - BOOST_STATIC_ASSERT(std::is_integral::value); - char buf[detail::max_digits(sizeof(Integer))]; - auto last = buf + sizeof(buf); - auto it = detail::raw_to_string< - CharT, Integer, Traits>(last, sizeof(buf), x); - static_string s; - s.resize(static_cast(last - it)); - auto p = s.data(); - while(it < last) - Traits::assign(*p++, *it++); - return s; -} - -} // beast -} // boost - -#endif diff --git a/include/boost/beast/core/static_string.hpp b/include/boost/beast/core/static_string.hpp index 9d0e289c..0ac939d2 100644 --- a/include/boost/beast/core/static_string.hpp +++ b/include/boost/beast/core/static_string.hpp @@ -10,1104 +10,27 @@ #ifndef BOOST_BEAST_STATIC_STRING_HPP #define BOOST_BEAST_STATIC_STRING_HPP -#include -#include #include -#include -#include -#include -#include -#include -#include -#include +#include namespace boost { namespace beast { -/** A modifiable string with a fixed-size storage area. - - These objects behave like `std::string` except that the storage - is not dynamically allocated but rather fixed in size. - - These strings offer performance advantages when a protocol - imposes a natural small upper limit on the size of a value. - - @note The stored string is always null-terminated. - - @see to_static_string -*/ -template< - std::size_t N, +template> -class static_string + class Traits = std::char_traits > +using static_string = boost::static_strings::basic_static_string; + +template +inline auto +to_static_string(Integer x) +-> decltype(boost::static_strings::to_static_string(x)) { - template - friend class static_string; - - void - term() - { - Traits::assign(s_[n_], 0); - } - - std::size_t n_; - CharT s_[N+1]; - -public: - // - // Member types - // - - using traits_type = Traits; - using value_type = typename Traits::char_type; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using pointer = value_type*; - using reference = value_type&; - using const_pointer = value_type const*; - using const_reference = value_type const&; - using iterator = value_type*; - using const_iterator = value_type const*; - using reverse_iterator = - std::reverse_iterator; - using const_reverse_iterator = - std::reverse_iterator; - - /// The type of `string_view` returned by the interface - using string_view_type = - basic_string_view; - - // - // Constants - // - - /// Maximum size of the string excluding the null terminator - static std::size_t constexpr max_size_n = N; - - /// A special index - static constexpr size_type npos = size_type(-1); - - // - // (constructor) - // - - /// Default constructor (empty string). - static_string(); - - /** Construct with count copies of character `ch`. - - The behavior is undefined if `count >= npos` - */ - static_string(size_type count, CharT ch); - - /// Construct with a substring (pos, other.size()) of `other`. - template - static_string(static_string const& other, - size_type pos); - - /// Construct with a substring (pos, count) of `other`. - template - static_string(static_string const& other, - size_type pos, size_type count); - - /// Construct with the first `count` characters of `s`, including nulls. - static_string(CharT const* s, size_type count); - - /// Construct from a null terminated string. - static_string(CharT const* s); - - /// Construct from a range of characters - template - static_string(InputIt first, InputIt last); - - /// Copy constructor. - static_string(static_string const& other); - - /// Copy constructor. - template - static_string(static_string const& other); - - /// Construct from an initializer list - static_string(std::initializer_list init); - - /// Construct from a `string_view` - explicit - static_string(string_view_type sv); - - /** Construct from any object convertible to `string_view_type`. - - The range (pos, n) is extracted from the value - obtained by converting `t` to `string_view_type`, - and used to construct the string. - */ -#if BOOST_BEAST_DOXYGEN - template -#else - template::value>::type> -#endif - static_string(T const& t, size_type pos, size_type n); - - // - // (assignment) - // - - /// Copy assignment. - static_string& - operator=(static_string const& str) - { - return assign(str); - } - - /// Copy assignment. - template - static_string& - operator=(static_string const& str) - { - return assign(str); - } - - /// Assign from null-terminated string. - static_string& - operator=(CharT const* s); - - /// Assign from single character. - static_string& - operator=(CharT ch) - { - return assign_char(ch, - std::integral_constant0)>{}); - } - - /// Assign from initializer list. - static_string& - operator=(std::initializer_list init) - { - return assign(init); - } - - /// Assign from `string_view_type`. - static_string& - operator=(string_view_type sv) - { - return assign(sv); - } - - /// Assign `count` copies of `ch`. - static_string& - assign(size_type count, CharT ch); - - /// Assign from another `static_string` - static_string& - assign(static_string const& str); - - // VFALCO NOTE this could come in two flavors, - // N>M and NM - - /// Assign from another `static_string` - template - static_string& - assign(static_string const& str) - { - return assign(str.data(), str.size()); - } - - /// Assign `count` characterss starting at `npos` from `other`. - template - static_string& - assign(static_string const& str, - size_type pos, size_type count = npos); - - /// Assign the first `count` characters of `s`, including nulls. - static_string& - assign(CharT const* s, size_type count); - - /// Assign a null terminated string. - static_string& - assign(CharT const* s) - { - return assign(s, Traits::length(s)); - } - - /// Assign from an iterator range of characters. - template - static_string& - assign(InputIt first, InputIt last); - - /// Assign from initializer list. - static_string& - assign(std::initializer_list init) - { - return assign(init.begin(), init.end()); - } - - /// Assign from `string_view_type`. - static_string& - assign(string_view_type str) - { - return assign(str.data(), str.size()); - } - - /** Assign from any object convertible to `string_view_type`. - - The range (pos, n) is extracted from the value - obtained by converting `t` to `string_view_type`, - and used to assign the string. - */ - template -#if BOOST_BEAST_DOXYGEN - static_string& -#else - typename std::enable_if::value, static_string&>::type -#endif - assign(T const& t, - size_type pos, size_type count = npos); - - // - // Element access - // - - /// Access specified character with bounds checking. - reference - at(size_type pos); - - /// Access specified character with bounds checking. - const_reference - at(size_type pos) const; - - /// Access specified character. - reference - operator[](size_type pos) - { - return s_[pos]; - } - - /// Access specified character. - const_reference - operator[](size_type pos) const - { - return s_[pos]; - } - - /// Accesses the first character. - CharT& - front() - { - return s_[0]; - } - - /// Accesses the first character. - CharT const& - front() const - { - return s_[0]; - } - - /// Accesses the last character. - CharT& - back() - { - return s_[n_-1]; - } - - /// Accesses the last character. - CharT const& - back() const - { - return s_[n_-1]; - } - - /// Returns a pointer to the first character of a string. - CharT* - data() - { - return &s_[0]; - } - - /// Returns a pointer to the first character of a string. - CharT const* - data() const - { - return &s_[0]; - } - - /// Returns a non-modifiable standard C character array version of the string. - CharT const* - c_str() const - { - return data(); - } - - /// Convert a static string to a `string_view_type` - operator string_view_type() const - { - return basic_string_view< - CharT, Traits>{data(), size()}; - } - - // - // Iterators - // - - /// Returns an iterator to the beginning. - iterator - begin() - { - return &s_[0]; - } - - /// Returns an iterator to the beginning. - const_iterator - begin() const - { - return &s_[0]; - } - - /// Returns an iterator to the beginning. - const_iterator - cbegin() const - { - return &s_[0]; - } - - /// Returns an iterator to the end. - iterator - end() - { - return &s_[n_]; - } - - /// Returns an iterator to the end. - const_iterator - end() const - { - return &s_[n_]; - } - - /// Returns an iterator to the end. - const_iterator - cend() const - { - return &s_[n_]; - } - - /// Returns a reverse iterator to the beginning. - reverse_iterator - rbegin() - { - return reverse_iterator{end()}; - } - - /// Returns a reverse iterator to the beginning. - const_reverse_iterator - rbegin() const - { - return const_reverse_iterator{cend()}; - } - - /// Returns a reverse iterator to the beginning. - const_reverse_iterator - crbegin() const - { - return const_reverse_iterator{cend()}; - } - - /// Returns a reverse iterator to the end. - reverse_iterator - rend() - { - return reverse_iterator{begin()}; - } - - /// Returns a reverse iterator to the end. - const_reverse_iterator - rend() const - { - return const_reverse_iterator{cbegin()}; - } - - /// Returns a reverse iterator to the end. - const_reverse_iterator - crend() const - { - return const_reverse_iterator{cbegin()}; - } - - // - // Capacity - // - - /// Returns `true` if the string is empty. - bool - empty() const - { - return n_ == 0; - } - - /// Returns the number of characters, excluding the null terminator. - size_type - size() const - { - return n_; - } - - /// Returns the number of characters, excluding the null terminator. - size_type - length() const - { - return size(); - } - - /// Returns the maximum number of characters that can be stored, excluding the null terminator. - size_type constexpr - max_size() const - { - return N; - } - - /** Reserves storage. - - This actually just throws an exception if `n > N`, - otherwise does nothing since the storage is fixed. - */ - void - reserve(std::size_t n); - - /// Returns the number of characters that can be held in currently allocated storage. - size_type constexpr - capacity() const - { - return max_size(); - } - - /** Reduces memory usage by freeing unused memory. - - This actually does nothing, since the storage is fixed. - */ - void - shrink_to_fit() - { - } - - // - // Operations - // - - /// Clears the contents. - void - clear(); - - static_string& - insert(size_type index, size_type count, CharT ch); - - static_string& - insert(size_type index, CharT const* s) - { - return insert(index, s, Traits::length(s)); - } - - static_string& - insert(size_type index, CharT const* s, size_type count); - - template - static_string& - insert(size_type index, - static_string const& str) - { - return insert(index, str.data(), str.size()); - } - - template - static_string& - insert(size_type index, - static_string const& str, - size_type index_str, size_type count = npos); - - iterator - insert(const_iterator pos, CharT ch) - { - return insert(pos, 1, ch); - } - - iterator - insert(const_iterator pos, size_type count, CharT ch); - - template -#if BOOST_BEAST_DOXYGEN - iterator -#else - typename std::enable_if< - detail::is_input_iterator::value, - iterator>::type -#endif - insert(const_iterator pos, InputIt first, InputIt last); - - iterator - insert(const_iterator pos, std::initializer_list init) - { - return insert(pos, init.begin(), init.end()); - } - - static_string& - insert(size_type index, string_view_type str) - { - return insert(index, str.data(), str.size()); - } - - template -#if BOOST_BEAST_DOXYGEN - static_string& -#else - typename std::enable_if< - std::is_convertible::value && - ! std::is_convertible::value, - static_string&>::type -#endif - insert(size_type index, T const& t, - size_type index_str, size_type count = npos); - - static_string& - erase(size_type index = 0, size_type count = npos); - - iterator - erase(const_iterator pos); - - iterator - erase(const_iterator first, const_iterator last); - - void - push_back(CharT ch); - - void - pop_back() - { - Traits::assign(s_[--n_], 0); - } - - static_string& - append(size_type count, CharT ch) - { - insert(end(), count, ch); - return *this; - } - - template - static_string& - append(static_string const& str) - { - insert(size(), str); - return *this; - } - - template - static_string& - append(static_string const& str, - size_type pos, size_type count = npos); - - static_string& - append(CharT const* s, size_type count) - { - insert(size(), s, count); - return *this; - } - - static_string& - append(CharT const* s) - { - insert(size(), s); - return *this; - } - - template -#if BOOST_BEAST_DOXYGEN - static_string& -#else - typename std::enable_if< - detail::is_input_iterator::value, - static_string&>::type -#endif - append(InputIt first, InputIt last) - { - insert(end(), first, last); - return *this; - } - - static_string& - append(std::initializer_list init) - { - insert(end(), init); - return *this; - } - - static_string& - append(string_view_type sv) - { - insert(size(), sv); - return *this; - } - - template - typename std::enable_if< - std::is_convertible::value && - ! std::is_convertible::value, - static_string&>::type - append(T const& t, size_type pos, size_type count = npos) - { - insert(size(), t, pos, count); - return *this; - } - - template - static_string& - operator+=(static_string const& str) - { - return append(str.data(), str.size()); - } - - static_string& - operator+=(CharT ch) - { - push_back(ch); - return *this; - } - - static_string& - operator+=(CharT const* s) - { - return append(s); - } - - static_string& - operator+=(std::initializer_list init) - { - return append(init); - } - - static_string& - operator+=(string_view_type const& str) - { - return append(str); - } - - template - int - compare(static_string const& str) const - { - return detail::lexicographical_compare( - &s_[0], n_, &str.s_[0], str.n_); - } - - template - int - compare(size_type pos1, size_type count1, - static_string const& str) const - { - return detail::lexicographical_compare( - substr(pos1, count1), str.data(), str.size()); - } - - template - int - compare(size_type pos1, size_type count1, - static_string const& str, - size_type pos2, size_type count2 = npos) const - { - return detail::lexicographical_compare( - substr(pos1, count1), str.substr(pos2, count2)); - } - - int - compare(CharT const* s) const - { - return detail::lexicographical_compare( - &s_[0], n_, s, Traits::length(s)); - } - - int - compare(size_type pos1, size_type count1, - CharT const* s) const - { - return detail::lexicographical_compare( - substr(pos1, count1), s, Traits::length(s)); - } - - int - compare(size_type pos1, size_type count1, - CharT const*s, size_type count2) const - { - return detail::lexicographical_compare( - substr(pos1, count1), s, count2); - } - - int - compare(string_view_type str) const - { - return detail::lexicographical_compare( - &s_[0], n_, str.data(), str.size()); - } - - int - compare(size_type pos1, size_type count1, - string_view_type str) const - { - return detail::lexicographical_compare( - substr(pos1, count1), str); - } - - template -#if BOOST_BEAST_DOXYGEN - int -#else - typename std::enable_if< - std::is_convertible::value && - ! std::is_convertible::value, - int>::type -#endif - compare(size_type pos1, size_type count1, - T const& t, size_type pos2, - size_type count2 = npos) const - { - return compare(pos1, count1, - string_view_type(t).substr(pos2, count2)); - } - - string_view_type - substr(size_type pos = 0, size_type count = npos) const; - - /// Copy a substring (pos, pos+count) to character string pointed to by `dest`. - size_type - copy(CharT* dest, size_type count, size_type pos = 0) const; - - /** Changes the number of characters stored. - - If the resulting string is larger, the new - characters are uninitialized. - */ - void - resize(std::size_t n); - - /** Changes the number of characters stored. - - If the resulting string is larger, the new - characters are initialized to the value of `c`. - */ - void - resize(std::size_t n, CharT c); - - /// Exchange the contents of this string with another. - void - swap(static_string& str); - - /// Exchange the contents of this string with another. - template - void - swap(static_string& str); - - // - // Search - // - -private: - static_string& - assign_char(CharT ch, std::true_type); - - static_string& - assign_char(CharT ch, std::false_type); -}; - -// -// Disallowed operations -// - -// These operations are explicitly deleted since -// there is no reasonable implementation possible. - -template -void -operator+( - static_stringconst&, - static_stringconst&) = delete; - -template -void -operator+(CharT const*, - static_stringconst&) = delete; - -template -void -operator+(CharT, - static_string const&) = delete; - -template -void -operator+(static_string const&, - CharT const*) = delete; - -template -void -operator+(static_string const&, CharT) = delete; - -// -// Non-member functions -// - -template -bool -operator==( - static_string const& lhs, - static_string const& rhs) -{ - return lhs.compare(rhs) == 0; + return boost::static_strings::to_static_string(x); } -template -bool -operator!=( - static_string const& lhs, - static_string const& rhs) -{ - return lhs.compare(rhs) != 0; -} - -template -bool -operator<( - static_string const& lhs, - static_string const& rhs) -{ - return lhs.compare(rhs) < 0; -} - -template -bool -operator<=( - static_string const& lhs, - static_string const& rhs) -{ - return lhs.compare(rhs) <= 0; -} - -template -bool -operator>( - static_string const& lhs, - static_string const& rhs) -{ - return lhs.compare(rhs) > 0; -} - -template -bool -operator>=( - static_string const& lhs, - static_string const& rhs) -{ - return lhs.compare(rhs) >= 0; -} - -template -bool -operator==( - CharT const* lhs, - static_string const& rhs) -{ - return detail::lexicographical_compare( - lhs, Traits::length(lhs), - rhs.data(), rhs.size()) == 0; -} - -template -bool -operator==( - static_string const& lhs, - CharT const* rhs) -{ - return detail::lexicographical_compare( - lhs.data(), lhs.size(), - rhs, Traits::length(rhs)) == 0; -} - -template -bool -operator!=( - CharT const* lhs, - static_string const& rhs) -{ - return detail::lexicographical_compare( - lhs, Traits::length(lhs), - rhs.data(), rhs.size()) != 0; -} - -template -bool -operator!=( - static_string const& lhs, - CharT const* rhs) -{ - return detail::lexicographical_compare( - lhs.data(), lhs.size(), - rhs, Traits::length(rhs)) != 0; -} - -template -bool -operator<( - CharT const* lhs, - static_string const& rhs) -{ - return detail::lexicographical_compare( - lhs, Traits::length(lhs), - rhs.data(), rhs.size()) < 0; -} - -template -bool -operator<( - static_string const& lhs, - CharT const* rhs) -{ - return detail::lexicographical_compare( - lhs.data(), lhs.size(), - rhs, Traits::length(rhs)) < 0; -} - -template -bool -operator<=( - CharT const* lhs, - static_string const& rhs) -{ - return detail::lexicographical_compare( - lhs, Traits::length(lhs), - rhs.data(), rhs.size()) <= 0; -} - -template -bool -operator<=( - static_string const& lhs, - CharT const* rhs) -{ - return detail::lexicographical_compare( - lhs.data(), lhs.size(), - rhs, Traits::length(rhs)) <= 0; -} - -template -bool -operator>( - CharT const* lhs, - static_string const& rhs) -{ - return detail::lexicographical_compare( - lhs, Traits::length(lhs), - rhs.data(), rhs.size()) > 0; -} - -template -bool -operator>( - static_string const& lhs, - CharT const* rhs) -{ - return detail::lexicographical_compare( - lhs.data(), lhs.size(), - rhs, Traits::length(rhs)) > 0; -} - -template -bool -operator>=( - CharT const* lhs, - static_string const& rhs) -{ - return detail::lexicographical_compare( - lhs, Traits::length(lhs), - rhs.data(), rhs.size()) >= 0; -} - -template -bool -operator>=( - static_string const& lhs, - CharT const* rhs) -{ - return detail::lexicographical_compare( - lhs.data(), lhs.size(), - rhs, Traits::length(rhs)) >= 0; -} - -// -// swap -// - -template -void -swap( - static_string& lhs, - static_string& rhs) -{ - lhs.swap(rhs); -} - -template -void -swap( - static_string& lhs, - static_string& rhs) -{ - lhs.swap(rhs); -} - -// -// Input/Output -// - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - static_string const& str) -{ - return os << static_cast< - beast::basic_string_view>(str); -} - -// -// Numeric conversions -// - -/** Returns a static string representing an integer as a decimal. - - @param x The signed or unsigned integer to convert. - This must be an integral type. - - @return A @ref static_string with an implementation defined - maximum size large enough to hold the longest possible decimal - representation of any integer of the given type. -*/ -template< - class Integer -#ifndef BOOST_BEAST_DOXYGEN - ,class = typename std::enable_if< - std::is_integral::value>::type -#endif -> -static_string -to_static_string(Integer x); - } // beast } // boost -#include - #endif diff --git a/include/boost/beast/core/string_type.hpp b/include/boost/beast/core/string_type.hpp index b6b3f005..c2a5ffcd 100644 --- a/include/boost/beast/core/string_type.hpp +++ b/include/boost/beast/core/string_type.hpp @@ -39,6 +39,13 @@ using basic_string_view = #endif +template +inline string_view +to_string_view(const S& s) +{ + return string_view(s.data(), s.size()); +} + } // beast } // boost diff --git a/include/boost/beast/http/impl/fields.hpp b/include/boost/beast/http/impl/fields.hpp index f8492bd4..b97d49c2 100644 --- a/include/boost/beast/http/impl/fields.hpp +++ b/include/boost/beast/http/impl/fields.hpp @@ -933,8 +933,9 @@ set_content_length_impl( erase(field::content_length); else { + auto s = to_static_string(*value); set(field::content_length, - to_static_string(*value)); + to_string_view(s)); } } diff --git a/include/boost/beast/websocket/detail/hybi13.ipp b/include/boost/beast/websocket/detail/hybi13.ipp index 0cbab153..3e22c313 100644 --- a/include/boost/beast/websocket/detail/hybi13.ipp +++ b/include/boost/beast/websocket/detail/hybi13.ipp @@ -40,7 +40,7 @@ make_sec_ws_accept( sec_ws_accept_type& accept, string_view key) { - BOOST_ASSERT(key.size() <= sec_ws_key_type::max_size_n); + BOOST_ASSERT(key.size() <= sec_ws_key_type::static_capacity); using namespace beast::detail::string_literals; auto const guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_sv; beast::detail::sha1_context ctx; diff --git a/include/boost/beast/websocket/detail/pmd_extension.hpp b/include/boost/beast/websocket/detail/pmd_extension.hpp index cdad99ba..8a52a263 100644 --- a/include/boost/beast/websocket/detail/pmd_extension.hpp +++ b/include/boost/beast/websocket/detail/pmd_extension.hpp @@ -82,7 +82,7 @@ pmd_write(http::basic_fields& fields, pmd_offer const& offer) { auto s = detail::pmd_write_impl(offer); - fields.set(http::field::sec_websocket_extensions, s); + fields.set(http::field::sec_websocket_extensions, to_string_view(s)); } // Negotiate a permessage-deflate client offer @@ -104,7 +104,7 @@ pmd_negotiate( auto s = detail::pmd_negotiate_impl(config, offer, o); if(config.accept) - fields.set(http::field::sec_websocket_extensions, s); + fields.set(http::field::sec_websocket_extensions, to_string_view(s)); } // Normalize the server's response diff --git a/include/boost/beast/websocket/impl/accept.hpp b/include/boost/beast/websocket/impl/accept.hpp index 588aa5da..3eef063a 100644 --- a/include/boost/beast/websocket/impl/accept.hpp +++ b/include/boost/beast/websocket/impl/accept.hpp @@ -120,7 +120,7 @@ build_response( if(it == req.end()) return err(error::no_sec_key); key = it->value(); - if(key.size() > detail::sec_ws_key_type::max_size_n) + if(key.size() > detail::sec_ws_key_type::static_capacity) return err(error::bad_sec_key); } { @@ -149,7 +149,7 @@ build_response( { detail::sec_ws_accept_type acc; detail::make_sec_ws_accept(acc, key); - res.set(http::field::sec_websocket_accept, acc); + res.set(http::field::sec_websocket_accept, to_string_view(acc)); } this->build_response_pmd(res, req); decorate(res); diff --git a/include/boost/beast/websocket/impl/read.hpp b/include/boost/beast/websocket/impl/read.hpp index 71463969..4c586fec 100644 --- a/include/boost/beast/websocket/impl/read.hpp +++ b/include/boost/beast/websocket/impl/read.hpp @@ -248,7 +248,7 @@ public: goto loop; if(impl.ctrl_cb) impl.ctrl_cb( - frame_type::ping, payload); + frame_type::ping, to_string_view(payload)); impl.rd_fb.clear(); impl.template write_ping< flat_static_buffer_base>(impl.rd_fb, @@ -336,7 +336,7 @@ public: impl.rd_buf.consume(len); // Ignore pong when closing if(! impl.wr_close && impl.ctrl_cb) - impl.ctrl_cb(frame_type::pong, payload); + impl.ctrl_cb(frame_type::pong, to_string_view(payload)); goto loop; } @@ -376,7 +376,7 @@ public: impl.rd_buf.consume(len); if(impl.ctrl_cb) impl.ctrl_cb(frame_type::close, - impl.cr.reason); + to_string_view(impl.cr.reason)); // See if we are already closing if(impl.status_ == status::closing) { @@ -1103,7 +1103,7 @@ loop: goto loop; } if(impl.ctrl_cb) - impl.ctrl_cb(frame_type::ping, payload); + impl.ctrl_cb(frame_type::ping, to_string_view(payload)); detail::frame_buffer fb; impl.template write_ping(fb, detail::opcode::pong, payload); @@ -1119,7 +1119,7 @@ loop: detail::read_ping(payload, b); impl.rd_buf.consume(len); if(impl.ctrl_cb) - impl.ctrl_cb(frame_type::pong, payload); + impl.ctrl_cb(frame_type::pong, to_string_view(payload)); goto loop; } // Handle close frame @@ -1139,7 +1139,7 @@ loop: impl.cr = cr; impl.rd_buf.consume(len); if(impl.ctrl_cb) - impl.ctrl_cb(frame_type::close, impl.cr.reason); + impl.ctrl_cb(frame_type::close, to_string_view(impl.cr.reason)); BOOST_ASSERT(! impl.wr_close); // _Start the WebSocket Closing Handshake_ do_fail( diff --git a/include/boost/beast/websocket/impl/stream_impl.hpp b/include/boost/beast/websocket/impl/stream_impl.hpp index 01c0be84..2e5cc11d 100644 --- a/include/boost/beast/websocket/impl/stream_impl.hpp +++ b/include/boost/beast/websocket/impl/stream_impl.hpp @@ -631,7 +631,7 @@ build_request( req.set(http::field::upgrade, "websocket"); req.set(http::field::connection, "upgrade"); detail::make_sec_ws_key(key); - req.set(http::field::sec_websocket_key, key); + req.set(http::field::sec_websocket_key, to_string_view(key)); req.set(http::field::sec_websocket_version, "13"); this->build_request_pmd(req); decorator_opt(req); @@ -677,8 +677,8 @@ on_response( if(it == res.end()) return err(error::no_sec_accept); detail::sec_ws_accept_type acc; - detail::make_sec_ws_accept(acc, key); - if(acc.compare(it->value()) != 0) + detail::make_sec_ws_accept(acc, to_string_view(key)); + if (to_string_view(acc).compare(it->value()) != 0) return err(error::bad_sec_accept); } diff --git a/include/boost/beast/websocket/rfc6455.hpp b/include/boost/beast/websocket/rfc6455.hpp index c3f01269..7611096b 100644 --- a/include/boost/beast/websocket/rfc6455.hpp +++ b/include/boost/beast/websocket/rfc6455.hpp @@ -189,7 +189,7 @@ struct close_reason /// Construct from a reason string. code is @ref close_code::normal. close_reason(string_view s) : code(close_code::normal) - , reason(s) + , reason(s.data(), s.size()) { } @@ -203,7 +203,7 @@ struct close_reason /// Construct from a close code and reason string. close_reason(close_code code_, string_view s) : code(code_) - , reason(s) + , reason(s.data(), s.size()) { } diff --git a/test/beast/core/static_string.cpp b/test/beast/core/static_string.cpp index 6e14715a..7b73e877 100644 --- a/test/beast/core/static_string.cpp +++ b/test/beast/core/static_string.cpp @@ -941,10 +941,15 @@ public: s3.append(s1, 1, 1); BEAST_EXPECT(s3 == "12Y"); BEAST_EXPECT(*s3.end() == 0); - try { static_string<3> s4("12"); s4.append(s1, 3); + BEAST_EXPECT(s4 == "12"); + } + try + { + static_string<3> s4("12"); + s4.append(s1, 4); fail("", __FILE__, __LINE__); } catch(std::out_of_range const&) diff --git a/test/beast/http/basic_parser.cpp b/test/beast/http/basic_parser.cpp index e89d3c0f..ef809e78 100644 --- a/test/beast/http/basic_parser.cpp +++ b/test/beast/http/basic_parser.cpp @@ -1136,7 +1136,7 @@ public: auto const grind = [&](string_view s) { - static_string<100> ss{s}; + static_string<100> ss(s.data(), s.size()); test::fuzz_rand r; test::fuzz(ss, 4, 5, r, [&](string_view s) diff --git a/test/beast/http/chunk_encode.cpp b/test/beast/http/chunk_encode.cpp index 9f779e2e..22d2703f 100644 --- a/test/beast/http/chunk_encode.cpp +++ b/test/beast/http/chunk_encode.cpp @@ -230,7 +230,7 @@ public: [&](string_view s) { error_code ec; - static_string<200> ss{s}; + static_string<200> ss(s.data(), s.size()); test::fuzz_rand r; for(auto i = 3; i--;) { diff --git a/test/beast/http/fields.cpp b/test/beast/http/fields.cpp index 63ff7cd8..0a9fa0eb 100644 --- a/test/beast/http/fields.cpp +++ b/test/beast/http/fields.cpp @@ -94,8 +94,10 @@ public: void fill(std::size_t n, basic_fields& f) { - for(std::size_t i = 1; i<= n; ++i) - f.insert(std::to_string(i), to_static_string(i)); + for(std::size_t i = 1; i<= n; ++i) { + auto s = std::to_string(i); + f.insert(s, s); + } } template @@ -412,10 +414,10 @@ public: { // group fields fields f; - f.insert(field::age, to_static_string(1)); - f.insert(field::body, to_static_string(2)); - f.insert(field::close, to_static_string(3)); - f.insert(field::body, to_static_string(4)); + f.insert(field::age, "1"); + f.insert(field::body, "2"); + f.insert(field::close, "3"); + f.insert(field::body, "4"); BEAST_EXPECT(std::next(f.begin(), 0)->name() == field::age); BEAST_EXPECT(std::next(f.begin(), 1)->name() == field::body); BEAST_EXPECT(std::next(f.begin(), 2)->name() == field::body); @@ -435,10 +437,10 @@ public: { // group fields, case insensitive fields f; - f.insert("a", to_static_string(1)); - f.insert("ab", to_static_string(2)); - f.insert("b", to_static_string(3)); - f.insert("AB", to_static_string(4)); + f.insert("a", "1"); + f.insert("ab", "2"); + f.insert("b", "3"); + f.insert("AB", "4"); BEAST_EXPECT(std::next(f.begin(), 0)->name() == field::unknown); BEAST_EXPECT(std::next(f.begin(), 1)->name() == field::unknown); BEAST_EXPECT(std::next(f.begin(), 2)->name() == field::unknown); @@ -458,14 +460,14 @@ public: { // verify insertion orde fields f; - f.insert( "a", to_static_string(1)); - f.insert("dd", to_static_string(2)); - f.insert("b", to_static_string(3)); - f.insert("dD", to_static_string(4)); - f.insert("c", to_static_string(5)); - f.insert("Dd", to_static_string(6)); - f.insert("DD", to_static_string(7)); - f.insert( "e", to_static_string(8)); + f.insert( "a", "1"); + f.insert("dd", "2"); + f.insert("b", "3"); + f.insert("dD", "4"); + f.insert("c", "5"); + f.insert("Dd", "6"); + f.insert("DD", "7"); + f.insert( "e", "8"); BEAST_EXPECT(f.count("dd") == 4); BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "dd"); BEAST_EXPECT(std::next(f.begin(), 2)->name_string() == "dD"); @@ -479,13 +481,13 @@ public: // equal_range { fields f; - f.insert("E", to_static_string(1)); - f.insert("B", to_static_string(2)); - f.insert("D", to_static_string(3)); - f.insert("B", to_static_string(4)); - f.insert("C", to_static_string(5)); - f.insert("B", to_static_string(6)); - f.insert("A", to_static_string(7)); + f.insert("E", "1"); + f.insert("B", "2"); + f.insert("D", "3"); + f.insert("B", "4"); + f.insert("C", "5"); + f.insert("B", "6"); + f.insert("A", "7"); auto const rng = f.equal_range("B"); BEAST_EXPECT(std::distance(rng.first, rng.second) == 3); BEAST_EXPECT(std::next(rng.first, 0)->value() == "2"); @@ -945,7 +947,7 @@ public: }; res.erase(field::transfer_encoding); - res.set(field::content_length, to_static_string(32)); + res.set(field::content_length, "32"); chunked(true); BEAST_EXPECT(res[field::transfer_encoding] == "chunked"); @@ -954,7 +956,7 @@ public: BEAST_EXPECT(res[field::transfer_encoding] == "chunked"); res.erase(field::transfer_encoding); - res.set(field::content_length, to_static_string(32)); + res.set(field::content_length, "32"); chunked(false); BEAST_EXPECT(res.count(field::transfer_encoding) == 0); diff --git a/test/beast/http/file_body.cpp b/test/beast/http/file_body.cpp index 2c32db4f..106f3512 100644 --- a/test/beast/http/file_body.cpp +++ b/test/beast/http/file_body.cpp @@ -176,7 +176,7 @@ public: header.version(11); header.result(status::accepted); header.set(field::server, "test"); - header.set(field::content_length, to_static_string(4097)); + header.set(field::content_length, "4097"); typename file_body_type::writer w(header, value); auto maybe_range = w.get(ec); diff --git a/test/beast/http/write.cpp b/test/beast/http/write.cpp index e0be03d4..81454383 100644 --- a/test/beast/http/write.cpp +++ b/test/beast/http/write.cpp @@ -643,7 +643,7 @@ public: m.method(verb::get); m.version(11); m.target("/"); - m.set("Content-Length", to_static_string(5)); + m.set("Content-Length", "5"); m.body() = "*****"; async_write(ts, m, handler{}); BEAST_EXPECT(handler::count() > 0); @@ -666,7 +666,7 @@ public: m.method(verb::get); m.version(11); m.target("/"); - m.set("Content-Length", to_static_string(5)); + m.set("Content-Length", "5"); m.body() = "*****"; async_write(ts, m, handler{}); BEAST_EXPECT(handler::count() > 0); diff --git a/tools/get-boost.sh b/tools/get-boost.sh index c614a486..86c86019 100755 --- a/tools/get-boost.sh +++ b/tools/get-boost.sh @@ -36,6 +36,7 @@ git submodule update --init --depth 20 --jobs 4 \ libs/optional \ libs/smart_ptr \ libs/static_assert \ + libs/static_string \ libs/system \ libs/throw_exception \ libs/type_traits \