Files
boost_beast/include/beast/core/static_string.hpp
T

1109 lines
25 KiB
C++
Raw Normal View History

2016-05-07 17:06:46 -04:00
//
2017-02-06 20:07:03 -05:00
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
2016-05-07 17:06:46 -04:00
//
// 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)
//
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
#ifndef BEAST_STATIC_STRING_HPP
#define BEAST_STATIC_STRING_HPP
2016-04-30 13:00:33 -04:00
#include <beast/config.hpp>
2017-05-05 14:45:15 -07:00
#include <beast/core/string_view.hpp>
2017-04-27 22:24:54 -07:00
#include <beast/core/detail/static_string.hpp>
#include <algorithm>
2016-04-30 13:00:33 -04:00
#include <cstdint>
2017-04-27 22:24:54 -07:00
#include <initializer_list>
2016-04-30 13:00:33 -04:00
#include <iterator>
2017-04-27 22:24:54 -07:00
#include <ostream>
2016-04-30 13:00:33 -04:00
#include <stdexcept>
#include <string>
2017-04-27 22:24:54 -07:00
#include <type_traits>
2016-04-30 13:00:33 -04:00
namespace beast {
2017-06-03 18:40:28 -07:00
/** A modifiable string with a fixed-size storage area.
2016-04-30 13:00:33 -04:00
These objects behave like `std::string` except that the storage
is not dynamically allocated but rather fixed in size.
2016-04-30 13:00:33 -04:00
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.
2017-05-07 18:40:22 -07:00
@see @ref to_static_string
2016-04-30 13:00:33 -04:00
*/
template<
std::size_t N,
class CharT = char,
class Traits = std::char_traits<CharT>>
class static_string
{
template<std::size_t, class, class>
friend class static_string;
2017-04-27 22:24:54 -07:00
void
term()
{
Traits::assign(s_[n_], 0);
}
2016-04-30 13:00:33 -04:00
std::size_t n_;
2017-04-27 22:24:54 -07:00
CharT s_[N+1];
2016-04-30 13:00:33 -04:00
public:
2017-04-27 22:24:54 -07:00
//
// Member types
//
2016-04-30 13:00:33 -04:00
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<iterator>;
using const_reverse_iterator =
std::reverse_iterator<const_iterator>;
2017-05-05 14:45:15 -07:00
/// The type of `string_view` returned by the interface
using string_view_type =
beast::basic_string_view<CharT, Traits>;
2017-04-27 22:24:54 -07:00
//
// Constants
//
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
/// 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).
2016-04-30 13:00:33 -04:00
static_string();
2017-04-27 22:24:54 -07:00
/** 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<std::size_t M>
static_string(static_string<M, CharT, Traits> const& other,
size_type pos);
/// Construct with a substring (pos, count) of `other`.
template<std::size_t M>
static_string(static_string<M, CharT, Traits> 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<class InputIt>
static_string(InputIt first, InputIt last);
2016-04-30 13:00:33 -04:00
/// Copy constructor.
2017-04-27 22:24:54 -07:00
static_string(static_string const& other);
2016-04-30 13:00:33 -04:00
/// Copy constructor.
template<std::size_t M>
2017-04-27 22:24:54 -07:00
static_string(static_string<M, CharT, Traits> const& other);
/// Construct from an initializer list
static_string(std::initializer_list<CharT> init);
2017-05-05 14:45:15 -07:00
/// Construct from a `string_view`
2017-04-27 22:24:54 -07:00
explicit
2017-05-05 14:45:15 -07:00
static_string(string_view_type sv);
2017-04-27 22:24:54 -07:00
2017-05-05 14:45:15 -07:00
/** Construct from any object convertible to `string_view_type`.
2017-04-27 22:24:54 -07:00
The range (pos, n) is extracted from the value
2017-05-05 14:45:15 -07:00
obtained by converting `t` to `string_view_type`,
2017-04-27 22:24:54 -07:00
and used to construct the string.
*/
#if BEAST_DOXYGEN
template<class T>
#else
2017-05-05 14:45:15 -07:00
template<class T, class = typename std::enable_if<
std::is_convertible<T, string_view_type>::value>::type>
2017-04-27 22:24:54 -07:00
#endif
static_string(T const& t, size_type pos, size_type n);
//
// (assignment)
//
2016-04-30 13:00:33 -04:00
/// Copy assignment.
static_string&
2017-04-27 22:24:54 -07:00
operator=(static_string const& str)
{
return assign(str);
}
2016-04-30 13:00:33 -04:00
/// Copy assignment.
template<std::size_t M>
static_string&
2017-04-27 22:24:54 -07:00
operator=(static_string<M, CharT, Traits> const& str)
{
return assign(str);
}
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
/// Assign from null-terminated string.
static_string&
operator=(CharT const* s)
{
return assign(s);
}
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
/// Assign from single character.
static_string&
operator=(CharT ch)
{
return assign_char(ch,
std::integral_constant<bool, (N>0)>{});
}
/// Assign from initializer list.
static_string&
operator=(std::initializer_list<CharT> init)
{
return assign(init);
}
2017-05-05 14:45:15 -07:00
/// Assign from `string_view_type`.
2017-04-27 22:24:54 -07:00
static_string&
2017-05-05 14:45:15 -07:00
operator=(string_view_type sv)
2017-04-27 22:24:54 -07:00
{
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 N<M, and skip the exception
// check when N>M
/// Assign from another `static_string`
2016-04-30 13:00:33 -04:00
template<std::size_t M>
2017-04-27 22:24:54 -07:00
static_string&
assign(static_string<M, CharT, Traits> const& str)
{
return assign(str.data(), str.size());
}
/// Assign `count` characterss starting at `npos` from `other`.
template<std::size_t M>
static_string&
assign(static_string<M, CharT, Traits> 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<class InputIt>
static_string&
assign(InputIt first, InputIt last);
/// Assign from initializer list.
static_string&
assign(std::initializer_list<CharT> init)
{
return assign(init.begin(), init.end());
}
2017-05-05 14:45:15 -07:00
/// Assign from `string_view_type`.
2017-04-27 22:24:54 -07:00
static_string&
2017-05-05 14:45:15 -07:00
assign(string_view_type str)
2017-04-27 22:24:54 -07:00
{
return assign(str.data(), str.size());
}
2017-05-05 14:45:15 -07:00
/** Assign from any object convertible to `string_view_type`.
2017-04-27 22:24:54 -07:00
The range (pos, n) is extracted from the value
2017-05-05 14:45:15 -07:00
obtained by converting `t` to `string_view_type`,
2017-04-27 22:24:54 -07:00
and used to assign the string.
*/
template<class T>
#if BEAST_DOXYGEN
static_string&
#else
2017-05-05 14:45:15 -07:00
typename std::enable_if<std::is_convertible<T,
string_view_type>::value, static_string&>::type
2017-04-27 22:24:54 -07:00
#endif
assign(T const& t,
size_type pos, size_type count = npos);
//
// Element access
//
2016-04-30 13:00:33 -04:00
/// 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
{
2017-04-27 22:24:54 -07:00
return data();
2016-04-30 13:00:33 -04:00
}
2017-05-05 14:45:15 -07:00
/// Convert a static string to a `string_view_type`
operator string_view_type() const
2017-04-27 22:24:54 -07:00
{
return boost::basic_string_ref<
CharT, Traits>{data(), size()};
}
//
// Iterators
//
2016-04-30 13:00:33 -04:00
/// 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()};
}
2017-04-27 22:24:54 -07:00
//
// Capacity
//
2016-04-30 13:00:33 -04:00
/// 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_;
}
2017-04-27 22:24:54 -07:00
/// Returns the number of characters, excluding the null terminator.
size_type
length() const
{
return size();
}
2016-04-30 13:00:33 -04:00
/// Returns the maximum number of characters that can be stored, excluding the null terminator.
size_type constexpr
max_size() const
{
return N;
}
2017-04-27 22:24:54 -07:00
/** 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);
2016-04-30 13:00:33 -04:00
/// Returns the number of characters that can be held in currently allocated storage.
2017-04-27 22:24:54 -07:00
size_type constexpr
2016-04-30 13:00:33 -04:00
capacity() const
{
2017-04-27 22:24:54 -07:00
return max_size();
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
/** Reduces memory usage by freeing unused memory.
This actually does nothing, since the storage is fixed.
*/
void
shrink_to_fit()
{
}
//
// Operations
//
2016-04-30 13:00:33 -04:00
/// Clears the contents.
void
2017-04-27 22:24:54 -07:00
clear();
static_string&
insert(size_type index, size_type count, CharT ch);
static_string&
insert(size_type index, CharT const* s)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return insert(index, s, Traits::length(s));
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
static_string&
insert(size_type index, CharT const* s, size_type count);
template<std::size_t M>
static_string&
insert(size_type index,
static_string<M, CharT, Traits> const& str)
{
return insert(index, str.data(), str.size());
}
template<std::size_t M>
static_string&
insert(size_type index,
static_string<M, CharT, Traits> 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<class InputIt>
#if BEAST_DOXYGEN
iterator
#else
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
iterator>::type
#endif
insert(const_iterator pos, InputIt first, InputIt last);
iterator
insert(const_iterator pos, std::initializer_list<CharT> init)
{
return insert(pos, init.begin(), init.end());
}
static_string&
2017-05-05 14:45:15 -07:00
insert(size_type index, string_view_type str)
2017-04-27 22:24:54 -07:00
{
return insert(index, str.data(), str.size());
}
template<class T>
#if BEAST_DOXYGEN
static_string&
#else
typename std::enable_if<
2017-05-05 14:45:15 -07:00
std::is_convertible<T const&, string_view_type>::value &&
2017-04-27 22:24:54 -07:00
! std::is_convertible<T const&, CharT const*>::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<std::size_t M>
static_string&
append(static_string<M, CharT, Traits> const& str)
{
insert(size(), str);
return *this;
}
template<std::size_t M>
static_string&
append(static_string<M, CharT, Traits> 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<class InputIt>
#if BEAST_DOXYGEN
static_string&
#else
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
static_string&>::type
#endif
append(InputIt first, InputIt last)
{
insert(end(), first, last);
return *this;
}
static_string&
append(std::initializer_list<CharT> init)
{
insert(end(), init);
return *this;
}
static_string&
2017-05-05 14:45:15 -07:00
append(string_view_type sv)
2017-04-27 22:24:54 -07:00
{
insert(size(), sv);
return *this;
}
template<class T>
typename std::enable_if<
2017-05-05 14:45:15 -07:00
std::is_convertible<T const&, string_view_type>::value &&
2017-04-27 22:24:54 -07:00
! std::is_convertible<T const&, CharT const*>::value,
static_string&>::type
append(T const& t, size_type pos, size_type count = npos)
{
insert(size(), t, pos, count);
return *this;
}
template<std::size_t M>
static_string&
operator+=(static_string<M, CharT, Traits> 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<CharT> init)
{
return append(init);
}
static_string&
2017-05-05 14:45:15 -07:00
operator+=(string_view_type const& str)
2017-04-27 22:24:54 -07:00
{
return append(str);
}
template<std::size_t M>
int
compare(static_string<M, CharT, Traits> const& str) const
{
return detail::lexicographical_compare<CharT, Traits>(
&s_[0], n_, &str.s_[0], str.n_);
}
template<std::size_t M>
int
compare(size_type pos1, size_type count1,
static_string<M, CharT, Traits> const& str) const
{
return detail::lexicographical_compare<CharT, Traits>(
substr(pos1, count1), str.data(), str.size());
}
template<std::size_t M>
int
compare(size_type pos1, size_type count1,
static_string<M, CharT, Traits> 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<CharT, Traits>(
&s_[0], n_, s, Traits::length(s));
}
int
compare(size_type pos1, size_type count1,
CharT const* s) const
{
return detail::lexicographical_compare<CharT, Traits>(
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<CharT, Traits>(
substr(pos1, count1), s, count2);
}
int
2017-05-05 14:45:15 -07:00
compare(string_view_type str) const
2017-04-27 22:24:54 -07:00
{
return detail::lexicographical_compare<CharT, Traits>(
&s_[0], n_, str.data(), str.size());
}
int
compare(size_type pos1, size_type count1,
2017-05-05 14:45:15 -07:00
string_view_type str) const
2017-04-27 22:24:54 -07:00
{
return detail::lexicographical_compare<CharT, Traits>(
substr(pos1, count1), str);
}
template<class T>
#if BEAST_DOXYGEN
int
#else
typename std::enable_if<
2017-05-05 14:45:15 -07:00
std::is_convertible<T const&, string_view_type>::value &&
2017-04-27 22:24:54 -07:00
! std::is_convertible<T const&, CharT const*>::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,
2017-05-05 14:45:15 -07:00
string_view_type(t).substr(pos2, count2));
2017-04-27 22:24:54 -07:00
}
2017-05-05 14:45:15 -07:00
string_view_type
2017-04-27 22:24:54 -07:00
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;
2016-04-30 13:00:33 -04:00
/** Changes the number of characters stored.
2017-04-27 22:24:54 -07:00
If the resulting string is larger, the new
2017-05-07 18:40:22 -07:00
characters are uninitialized.
2016-04-30 13:00:33 -04:00
*/
void
2017-05-07 18:40:22 -07:00
resize(std::size_t n);
2016-04-30 13:00:33 -04:00
/** 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);
2017-04-27 22:24:54 -07:00
/// Exchange the contents of this string with another.
void
swap(static_string& str);
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
/// Exchange the contents of this string with another.
template<std::size_t M>
void
swap(static_string<M, CharT, Traits>& str);
//
// Search
//
2016-04-30 13:00:33 -04:00
private:
2017-04-27 22:24:54 -07:00
static_string&
assign_char(CharT ch, std::true_type);
static_string&
assign_char(CharT ch, std::false_type);
2016-04-30 13:00:33 -04:00
};
2017-04-27 22:24:54 -07:00
//
2017-05-23 12:33:31 -07:00
// Disallowed operations
2017-04-27 22:24:54 -07:00
//
2016-04-30 13:00:33 -04:00
2017-05-23 12:33:31 -07:00
// These operations are explicitly deleted since
// there is no reasonable implementation possible.
2016-04-30 13:00:33 -04:00
template<std::size_t N, std::size_t M, class CharT, class Traits>
2017-04-27 22:24:54 -07:00
void
operator+(
static_string<N, CharT, Traits>const& lhs,
2017-05-23 12:33:31 -07:00
static_string<M, CharT, Traits>const& rhs) = delete;
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
void
operator+(CharT const* lhs,
2017-05-23 12:33:31 -07:00
static_string<N, CharT, Traits>const& rhs) = delete;
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
void
operator+(CharT lhs,
2017-05-23 12:33:31 -07:00
static_string<N, CharT, Traits> const& rhs) = delete;
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
void
operator+(static_string<N, CharT, Traits> const& lhs,
2017-05-23 12:33:31 -07:00
CharT const* rhs) = delete;
2016-04-30 13:00:33 -04:00
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
void
operator+(static_string<N, CharT, Traits> const& lhs,
2017-05-23 12:33:31 -07:00
CharT rhs) = delete;
//
// Non-member functions
//
2017-04-27 22:24:54 -07:00
template<std::size_t N, std::size_t M,
class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator==(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) == 0;
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, std::size_t M,
class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator!=(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) != 0;
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, std::size_t M,
class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator<(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) < 0;
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, std::size_t M,
class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator<=(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) <= 0;
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, std::size_t M,
class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator>(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) > 0;
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, std::size_t M,
class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator>=(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
static_string<M, CharT, Traits> const& rhs)
{
return lhs.compare(rhs) >= 0;
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator==(
2017-04-27 22:24:54 -07:00
CharT const* lhs,
static_string<N, CharT, Traits> const& rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) == 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator==(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
2017-04-27 22:24:54 -07:00
CharT const* rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) == 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator!=(
2017-04-27 22:24:54 -07:00
CharT const* lhs,
static_string<N, CharT, Traits> const& rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) != 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator!=(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
2017-04-27 22:24:54 -07:00
CharT const* rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) != 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator<(
2017-04-27 22:24:54 -07:00
CharT const* lhs,
static_string<N, CharT, Traits> const& rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) < 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator<(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
2017-04-27 22:24:54 -07:00
CharT const* rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) < 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator<=(
2017-04-27 22:24:54 -07:00
CharT const* lhs,
static_string<N, CharT, Traits> const& rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) <= 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator<=(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
2017-04-27 22:24:54 -07:00
CharT const* rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) <= 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator>(
2017-04-27 22:24:54 -07:00
CharT const* lhs,
static_string<N, CharT, Traits> const& rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) > 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator>(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
2017-04-27 22:24:54 -07:00
CharT const* rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) > 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator>=(
2017-04-27 22:24:54 -07:00
CharT const* lhs,
static_string<N, CharT, Traits> const& rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs, Traits::length(lhs),
rhs.data(), rhs.size()) >= 0;
2016-04-30 13:00:33 -04:00
}
2017-04-27 22:24:54 -07:00
template<std::size_t N, class CharT, class Traits>
2016-05-04 17:27:50 -04:00
bool
operator>=(
2016-04-30 13:00:33 -04:00
static_string<N, CharT, Traits> const& lhs,
2017-04-27 22:24:54 -07:00
CharT const* rhs)
2016-04-30 13:00:33 -04:00
{
2017-04-27 22:24:54 -07:00
return detail::lexicographical_compare<CharT, Traits>(
lhs.data(), lhs.size(),
rhs, Traits::length(rhs)) >= 0;
}
//
// swap
//
template<std::size_t N, class CharT, class Traits>
void
swap(
static_string<N, CharT, Traits>& lhs,
static_string<N, CharT, Traits>& rhs)
{
lhs.swap(rhs);
}
template<std::size_t N, std::size_t M,
class CharT, class Traits>
void
swap(
static_string<N, CharT, Traits>& lhs,
static_string<M, CharT, Traits>& rhs)
{
lhs.swap(rhs);
}
//
// Input/Output
//
template<std::size_t N, class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
static_string<N, CharT, Traits> const& str)
{
return os << static_cast<
2017-05-05 14:45:15 -07:00
beast::basic_string_view<CharT, Traits>>(str);
2016-04-30 13:00:33 -04:00
}
2017-05-07 18:40:22 -07:00
//
// 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>
static_string<detail::max_digits(sizeof(Integer))>
to_static_string(Integer x);
2016-04-30 13:00:33 -04:00
} // beast
2017-04-27 22:24:54 -07:00
#include <beast/core/impl/static_string.ipp>
2016-04-30 13:00:33 -04:00
#endif