Merge review changes with master

* Initial constexpr support

* Remove invisible unicode

* Fix const function qualification

* Working constexpr
This commit is contained in:
Krystian Stasiowski
2019-12-16 00:51:47 -05:00
committed by GitHub
parent aa0fad2304
commit c3110b1b6c
5 changed files with 2948 additions and 2295 deletions

View File

@ -12,7 +12,7 @@
#define BOOST_FIXED_STRING_CONFIG_HPP #define BOOST_FIXED_STRING_CONFIG_HPP
// Are we dependent on Boost? // Are we dependent on Boost?
#define BOOST_FIXED_STRING_USE_BOOST // #define BOOST_FIXED_STRING_STANDALONE
// Can we have deduction guides? // Can we have deduction guides?
#ifdef __cpp_deduction_guides #ifdef __cpp_deduction_guides
@ -30,8 +30,45 @@
#define BOOST_FIXED_STRING_NODISCARD #define BOOST_FIXED_STRING_NODISCARD
#endif #endif
#ifdef BOOST_FIXED_STRING_USE_BOOST //#undef _<>_<EFBFBD>cplusplus
//#define _<>_<EFBFBD>cplusplus 201703L
#if __cplusplus > 201703L
#define BOOST_FIXED_STRING_CPP20_CXPER constexpr
#define BOOST_FIXED_STRING_CPP17_CXPER constexpr
#define BOOST_FIXED_STRING_CPP14_CXPER constexpr
#define BOOST_FIXED_STRING_CPP11_CXPER constexpr
#define BOOST_FIXED_STRING_CPP20_CXPER_USED
#define BOOST_FIXED_STRING_CPP17_CXPER_USED
#define BOOST_FIXED_STRING_CPP14_CXPER_USED
#define BOOST_FIXED_STRING_CPP11_CXPER_USED
#define BOOST_FIXED_STRING_ALLOW_UNINIT_MEM
#elif __cplusplus >= 201703L
#define BOOST_FIXED_STRING_CPP20_CXPER
#define BOOST_FIXED_STRING_CPP17_CXPER constexpr
#define BOOST_FIXED_STRING_CPP14_CXPER constexpr
#define BOOST_FIXED_STRING_CPP11_CXPER constexpr
#define BOOST_FIXED_STRING_CPP17_CXPER_USED
#define BOOST_FIXED_STRING_CPP14_CXPER_USED
#define BOOST_FIXED_STRING_CPP11_CXPER_USED
#elif __cplusplus >= 201402L
#define BOOST_FIXED_STRING_CPP20_CXPER
#define BOOST_FIXED_STRING_CPP17_CXPER
#define BOOST_FIXED_STRING_CPP14_CXPER constexpr
#define BOOST_FIXED_STRING_CPP11_CXPER constexpr
#define BOOST_FIXED_STRING_CPP14_CXPER_USED
#define BOOST_FIXED_STRING_CPP11_CXPER_USED
#else
#define BOOST_FIXED_STRING_CPP20_CXPER
#define BOOST_FIXED_STRING_CPP17_CXPER
#define BOOST_FIXED_STRING_CPP14_CXPER
#define BOOST_FIXED_STRING_CPP11_CXPER constexpr
#define BOOST_FIXED_STRING_CPP11_CXPER_USED
#endif
#ifndef BOOST_FIXED_STRING_STANDALONE
#include <boost/utility/string_view.hpp> #include <boost/utility/string_view.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
@ -41,7 +78,7 @@
#endif #endif
// Boost and non-Boost versions of utilities // Boost and non-Boost versions of utilities
#ifdef BOOST_FIXED_STRING_USE_BOOST #ifndef BOOST_FIXED_STRING_STANDALONE
#ifndef BOOST_FIXED_STRING_THROW #ifndef BOOST_FIXED_STRING_THROW
#define BOOST_FIXED_STRING_THROW(ex) BOOST_THROW_EXCEPTION(ex) #define BOOST_FIXED_STRING_THROW(ex) BOOST_THROW_EXCEPTION(ex)
#endif #endif
@ -66,18 +103,10 @@
namespace boost { namespace boost {
namespace fixed_string { namespace fixed_string {
/// The type of `string_view` used by the library
using string_view =
#ifdef BOOST_FIXED_STRING_USE_BOOST
boost::string_view;
#else
std::string_view;
#endif
/// The type of `basic_string_view` used by the library /// The type of `basic_string_view` used by the library
template<typename CharT, typename Traits> template<typename CharT, typename Traits>
using basic_string_view = using basic_string_view =
#ifdef BOOST_FIXED_STRING_USE_BOOST #ifndef BOOST_FIXED_STRING_STANDALONE
boost::basic_string_view<CharT, Traits>; boost::basic_string_view<CharT, Traits>;
#else #else
std::basic_string_view<CharT, Traits>; std::basic_string_view<CharT, Traits>;

View File

@ -14,6 +14,7 @@
#include <boost/fixed_string/config.hpp> #include <boost/fixed_string/config.hpp>
#include <iterator> #include <iterator>
#include <type_traits> #include <type_traits>
#include <limits>
namespace boost { namespace boost {
namespace fixed_string { namespace fixed_string {
@ -22,12 +23,186 @@ namespace detail {
template<std::size_t, typename, typename> template<std::size_t, typename, typename>
class fixed_string; class fixed_string;
// Because k-ballo said so // At minimum an integral type shall not qualify as an iterator (Agustin Berge)
template<class T> template<class T>
using is_input_iterator = using is_input_iterator =
std::integral_constant<bool, std::integral_constant<bool,
! std::is_integral<T>::value>; ! std::is_integral<T>::value>;
// Find the smallest width integral type that can hold a value as large as N (Glen Fernandes)
template<std::size_t N>
using smallest_width =
typename std::conditional<(N <= (std::numeric_limits<unsigned char>::max)()), unsigned char,
typename std::conditional<(N <= (std::numeric_limits<unsigned short>::max)()), unsigned short,
typename std::conditional<(N <= (std::numeric_limits<unsigned int>::max)()), unsigned int,
typename std::conditional<(N <= (std::numeric_limits<unsigned long>::max)()), unsigned long,
typename std::conditional<(N <= (std::numeric_limits<unsigned long long>::max)()), unsigned long long,
void>::type>::type>::type>::type>::type;
// Optimization for using the smallest possible type
template<std::size_t N, typename CharT, typename Traits>
class fixed_string_base_zero
{
public:
BOOST_FIXED_STRING_CPP11_CXPER
fixed_string_base_zero() noexcept { };
BOOST_FIXED_STRING_CPP11_CXPER
fixed_string_base_zero(std::size_t n) noexcept : size_(n) { }
BOOST_FIXED_STRING_CPP14_CXPER
CharT*
data_impl() noexcept
{
return data_;
}
BOOST_FIXED_STRING_CPP14_CXPER
CharT const*
data_impl() const noexcept
{
return data_;
}
BOOST_FIXED_STRING_CPP11_CXPER
std::size_t
size_impl() const noexcept
{
return size_;
}
BOOST_FIXED_STRING_CPP14_CXPER
std::size_t
set_size(std::size_t n) noexcept
{
return size_ = n;
}
BOOST_FIXED_STRING_CPP14_CXPER
void
term_impl() noexcept
{
Traits::assign(data_[size_], 0);
}
smallest_width<N> size_{0};
#ifdef BOOST_FIXED_STRING_ALLOW_UNINIT_MEM
CharT data_[N + 1];
#else
CharT data_[N + 1]{};
#endif
};
// Optimization for when the size is 0
template<typename CharT, typename Traits>
class fixed_string_base_zero<0, CharT, Traits>
{
public:
BOOST_FIXED_STRING_CPP11_CXPER
fixed_string_base_zero() noexcept { }
BOOST_FIXED_STRING_CPP11_CXPER
fixed_string_base_zero(std::size_t) noexcept { }
// not possible to constexpr with the static there
CharT*
data_impl() const noexcept
{
static CharT null{};
return &null;
}
BOOST_FIXED_STRING_CPP11_CXPER
std::size_t
size_impl() const noexcept
{
return 0;
}
BOOST_FIXED_STRING_CPP11_CXPER
std::size_t
set_size(std::size_t) noexcept
{
return 0;
}
BOOST_FIXED_STRING_CPP14_CXPER
void
term_impl() noexcept
{
}
};
// Optimization for storing the size in the last element
template<std::size_t N, typename CharT, typename Traits>
class fixed_string_base_null
{
public:
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string_base_null() noexcept { set_size(0); }
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string_base_null(std::size_t n) noexcept { set_size(n); }
BOOST_FIXED_STRING_CPP14_CXPER
CharT*
data_impl() noexcept
{
return data_;
}
BOOST_FIXED_STRING_CPP14_CXPER
CharT const*
data_impl() const noexcept
{
return data_;
}
BOOST_FIXED_STRING_CPP11_CXPER
std::size_t
size_impl() const noexcept
{
return N - data_[N];
}
BOOST_FIXED_STRING_CPP14_CXPER
std::size_t
set_size(std::size_t n) noexcept
{
return data_[N] = (N - n);
}
BOOST_FIXED_STRING_CPP14_CXPER
void
term_impl() noexcept
{
Traits::assign(data_[size_impl()], 0);
}
#ifdef BOOST_FIXED_STRING_ALLOW_UNINIT_MEM
CharT data_[N + 1];
#else
CharT data_[N + 1]{};
#endif
};
//#define BOOST_FIXED_STRING_NO_NULL_OPTIMIZATION
// Decides which size optimization to use
// If the size is zero, the object will have no members
// Otherwise, if CharT can hold the max size of the string, store the size in the last char
// Otherwise, store the size of the string using a member of the smallest type possible
template<std::size_t N, typename CharT, typename Traits>
using optimization_base =
#ifndef BOOST_FIXED_STRING_NO_NULL_OPTIMIZATION
typename std::conditional<(N <= (std::numeric_limits<CharT>::max)()) && (N != 0),
fixed_string_base_null<N, CharT, Traits>,
fixed_string_base_zero<N, CharT, Traits>>::type;
#else
fixed_string_base_zero<N, CharT, Traits>;
#endif
template<typename CharT, typename Traits> template<typename CharT, typename Traits>
inline inline
int int

File diff suppressed because it is too large Load Diff

View File

@ -24,14 +24,17 @@ namespace fixed_string {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP11_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string() fixed_string() noexcept
{ {
n_ = 0; #ifdef BOOST_FIXED_STRING_CPP20_CXPER_USED
term(); term();
#endif
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(size_type count, CharT ch) fixed_string(size_type count, CharT ch)
{ {
@ -40,6 +43,7 @@ fixed_string(size_type count, CharT ch)
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<std::size_t M> template<std::size_t M>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(fixed_string<M, CharT, Traits> const& other, fixed_string(fixed_string<M, CharT, Traits> const& other,
size_type pos) size_type pos)
@ -49,6 +53,7 @@ fixed_string(fixed_string<M, CharT, Traits> const& other,
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<std::size_t M> template<std::size_t M>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string( fixed_string(
fixed_string<M, CharT, Traits> const& other, fixed_string<M, CharT, Traits> const& other,
@ -59,6 +64,7 @@ fixed_string(
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(CharT const* s, size_type count) fixed_string(CharT const* s, size_type count)
{ {
@ -66,6 +72,7 @@ fixed_string(CharT const* s, size_type count)
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(CharT const* s) fixed_string(CharT const* s)
{ {
@ -73,12 +80,13 @@ fixed_string(CharT const* s)
if(count > max_size()) if(count > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"count > max_size()"}); "count > max_size()"});
n_ = count; this->set_size(count);
Traits::copy(s_, s, n_ + 1); Traits::copy(data(), s, size() + 1);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<class InputIterator> template<class InputIterator>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string( fixed_string(
InputIterator first, InputIterator first,
@ -91,15 +99,17 @@ fixed_string(
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string( fixed_string(
fixed_string const& s) fixed_string const& s) noexcept
{ {
assign(s); assign(s);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<std::size_t M> template<std::size_t M>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string( fixed_string(
fixed_string<M, CharT, Traits> const& s) fixed_string<M, CharT, Traits> const& s)
@ -108,6 +118,7 @@ fixed_string(
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(std::initializer_list<CharT> init) fixed_string(std::initializer_list<CharT> init)
{ {
@ -115,6 +126,7 @@ fixed_string(std::initializer_list<CharT> init)
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(string_view_type sv) fixed_string(string_view_type sv)
{ {
@ -123,6 +135,7 @@ fixed_string(string_view_type sv)
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<class T, class> template<class T, class>
BOOST_FIXED_STRING_CPP14_CXPER
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
fixed_string(T const& t, size_type pos, size_type n) fixed_string(T const& t, size_type pos, size_type n)
{ {
@ -136,6 +149,7 @@ fixed_string(T const& t, size_type pos, size_type n)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
assign( assign(
@ -146,13 +160,14 @@ assign(
if(count > max_size()) if(count > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"count > max_size()"}); "count > max_size()"});
n_ = count; this->set_size(count);
Traits::assign(s_, n_, ch); Traits::assign(data(), size(), ch);
term(); term();
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
assign( assign(
@ -161,16 +176,17 @@ assign(
{ {
if(this == &s) if(this == &s)
return *this; return *this;
n_ = s.n_; this->set_size(s.size());
auto const n = n_ + 1; auto const n = size() + 1;
// VFALCO This informs the static analyzer // VFALCO This informs the static analyzer
//BOOST_BEAST_ASSUME(n != 0); //BOOST_BEAST_ASSUME(n != 0);
Traits::copy(s_, &s.s_[0], n); Traits::copy(data(), &s.data()[0], n);
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<std::size_t M> template<std::size_t M>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
assign( assign(
@ -179,11 +195,12 @@ assign(
size_type count) -> size_type count) ->
fixed_string& fixed_string&
{ {
auto const ss = s.substr(pos, count); auto const ss = s.subview(pos, count);
return assign(ss.data(), ss.size()); return assign(ss.data(), ss.size());
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
assign( assign(
@ -194,18 +211,15 @@ assign(
if(count > max_size()) if(count > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"count > max_size()"}); "count > max_size()"});
n_ = count; this->set_size(count);
// check for overlap, then move if needed Traits::move(data(), s, size());
if (s <= &s_[size()] && s >= s_)
Traits::move(s_, s, n_);
else
Traits::copy(s_, s, n_);
term(); term();
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<class InputIterator> template<class InputIterator>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
assign( assign(
@ -219,8 +233,8 @@ assign(
if(n > max_size()) if(n > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"n > max_size()"}); "n > max_size()"});
n_ = n; this->set_size(n);
for(auto it = s_; first != last; ++it, ++first) for(auto it = data(); first != last; ++it, ++first)
Traits::assign(*it, *first); Traits::assign(*it, *first);
term(); term();
return *this; return *this;
@ -233,6 +247,7 @@ assign(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
at(size_type pos) -> at(size_type pos) ->
@ -241,10 +256,11 @@ at(size_type pos) ->
if(pos >= size()) if(pos >= size())
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"pos >= size()"}); "pos >= size()"});
return s_[pos]; return data()[pos];
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
at(size_type pos) const -> at(size_type pos) const ->
@ -253,7 +269,7 @@ at(size_type pos) const ->
if(pos >= size()) if(pos >= size())
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"pos >= size()"}); "pos >= size()"});
return s_[pos]; return data()[pos];
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -263,6 +279,7 @@ at(size_type pos) const ->
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
reserve(std::size_t n) reserve(std::size_t n)
@ -279,17 +296,19 @@ reserve(std::size_t n)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
clear() clear() noexcept
{ {
n_ = 0; this->set_size(0);
term(); term();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
insert( insert(
@ -306,6 +325,7 @@ insert(
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
insert( insert(
@ -314,38 +334,41 @@ insert(
size_type count) -> size_type count) ->
fixed_string& fixed_string&
{ {
if(index > size()) const auto curr_size = size();
const auto curr_data = data();
if(index > curr_size)
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"index > size()"}); "index > size()"});
if(size() + count > max_size()) if(count > max_size() - curr_size)
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"size() + count > max_size()"}); "size() + count > max_size()"});
const bool inside = s <= &s_[size()] && s >= s_; const bool inside = s <= &curr_data[curr_size] && s >= curr_data;
if (!inside || (inside && ((s - s_) + count <= index))) if (!inside || (inside && ((s - curr_data) + count <= index)))
{ {
Traits::move(&s_[index + count], &s_[index], size() - index + 1); Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
Traits::copy(&s_[index], s, count); Traits::copy(&curr_data[index], s, count);
} }
else else
{ {
const size_type offset = s - s_; const size_type offset = s - curr_data;
Traits::move(&s_[index + count], &s_[index], size() - index + 1); Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
if (offset < index) if (offset < index)
{ {
const size_type diff = index - offset; const size_type diff = index - offset;
Traits::copy(&s_[index], &s_[offset], diff); Traits::copy(&curr_data[index], &curr_data[offset], diff);
Traits::copy(&s_[index + diff], &s_[index + count], count - diff); Traits::copy(&curr_data[index + diff], &curr_data[index + count], count - diff);
} }
else else
{ {
Traits::copy(&s_[index], &s_[offset + count], count); Traits::copy(&curr_data[index], &curr_data[offset + count], count);
} }
} }
n_ += count; this->set_size(curr_size + count);
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
insert( insert(
@ -354,20 +377,22 @@ insert(
CharT ch) -> CharT ch) ->
iterator iterator
{ {
if(size() + count > max_size()) const auto curr_size = size();
const auto curr_data = data();
if(count > max_size() - curr_size)
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"size() + count() > max_size()"}); "size() + count() > max_size()"});
auto const index = pos - s_; auto const index = pos - curr_data;
Traits::move( Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index);
&s_[index + count], &s_[index], size() - index); this->set_size(curr_size + count);
n_ += count; Traits::assign(&curr_data[index], count, ch);
Traits::assign(&s_[index], count, ch);
term(); term();
return &s_[index]; return &curr_data[index];
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<class InputIterator> template<class InputIterator>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
insert( insert(
@ -384,6 +409,7 @@ insert(
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<class T> template<class T>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
insert( insert(
@ -401,6 +427,7 @@ insert(
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<class T> template<class T>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
insert( insert(
@ -423,6 +450,7 @@ insert(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
erase( erase(
@ -430,17 +458,19 @@ erase(
size_type count) -> size_type count) ->
fixed_string& fixed_string&
{ {
if(index > size()) const auto curr_size = size();
const auto curr_data = data();
if(index > curr_size)
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"index > size()"}); "index > size()"});
auto const n = (std::min)(count, size() - index); auto const n = (std::min)(count, curr_size - index);
Traits::move( Traits::move(&curr_data[index], &curr_data[index + n], curr_size - (index + n) + 1);
&s_[index], &s_[index + n], size() - (index + n) + 1); this->set_size(curr_size - n);
n_ -= n;
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
erase( erase(
@ -452,6 +482,7 @@ erase(
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
erase( erase(
@ -465,19 +496,23 @@ erase(
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
push_back( push_back(
CharT ch) CharT ch)
{ {
if(size() >= max_size()) const auto curr_size = size();
if(curr_size >= max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"size() >= max_size()"}); "size() >= max_size()"});
Traits::assign(s_[n_++], ch); Traits::assign(data()[curr_size], ch);
this->set_size(curr_size + 1);
term(); term();
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
append( append(
@ -485,100 +520,123 @@ append(
size_type count) -> size_type count) ->
fixed_string& fixed_string&
{ {
if(size() + count > max_size()) const auto curr_size = size();
if(count > max_size() - curr_size)
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"size() + count > max_size()"}); "size() + count > max_size()"});
Traits::move( Traits::copy(&data()[curr_size], s, count);
&s_[n_ + count], &s_[n_], size() - n_); this->set_size(curr_size + count);
Traits::copy(&s_[n_], s, count);
n_ += count;
term(); term();
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
substr(size_type pos, size_type count) const -> substr(size_type pos, size_type count) const ->
string_view fixed_string
{ {
if(pos > size()) if(pos > size())
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"pos > size()"}); "pos > size()"});
return {&s_[pos], (std::min)(count, size() - pos)}; return {&data()[pos], (std::min)(count, size() - pos)};
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
copy(CharT* dest, size_type count, size_type pos) const -> subview(size_type pos, size_type count) const ->
string_view_type
{
if (pos > size())
BOOST_FIXED_STRING_THROW(std::out_of_range{
"pos > size()"});
return {&data()[pos], (std::min)(count, size() - pos)};
}
template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto
fixed_string<N, CharT, Traits>::
copy(CharT* dest, size_type count, size_type pos) const noexcept ->
size_type size_type
{ {
auto const s = substr(pos, count); auto const s = subview(pos, count);
Traits::copy(dest, s.data(), s.size()); Traits::copy(dest, s.data(), s.size());
return s.size(); return s.size();
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
resize(std::size_t n) resize(std::size_t n)
{ {
const auto curr_size = size();
if(n > max_size()) if(n > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"n > max_size()"}); "n > max_size()"});
if(n > n_) if(n > curr_size)
Traits::assign(&s_[n_], n - n_, CharT{}); Traits::assign(&data()[curr_size], n - curr_size, CharT{});
n_ = n; this->set_size(n);
term(); term();
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
resize(std::size_t n, CharT c) resize(std::size_t n, CharT c)
{ {
const auto curr_size = size();
if(n > max_size()) if(n > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"n > max_size()"}); "n > max_size()"});
if(n > n_) if(n > curr_size)
Traits::assign(&s_[n_], n - n_, c); Traits::assign(&data()[curr_size], n - curr_size, c);
n_ = n; this->set_size(n);
term(); term();
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
swap(fixed_string& s) swap(fixed_string& s) noexcept
{ {
const auto curr_size = size();
fixed_string tmp(s); fixed_string tmp(s);
s.n_ = n_; s.set_size(curr_size);
Traits::copy(&s.s_[0], s_, n_ + 1); Traits::copy(&s.data()[0], data(), curr_size + 1);
n_ = tmp.n_; this->set_size(tmp.size());
Traits::copy(s_, &tmp.s_[0], n_ + 1); Traits::copy(data(), tmp.data(), size() + 1);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
template<std::size_t M> template<std::size_t M>
BOOST_FIXED_STRING_CPP14_CXPER
void void
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
swap(fixed_string<M, CharT, Traits>& s) swap(fixed_string<M, CharT, Traits>& s)
{ {
if(size() > s.max_size()) const auto curr_size = size();
if(curr_size > s.max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"size() > s.max_size()"}); "size() > s.max_size()"});
if(s.size() > max_size()) if(s.size() > max_size())
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"s.size() > max_size()"}); "s.size() > max_size()"});
fixed_string tmp(s); fixed_string tmp(s);
s.n_ = n_; s.set_size(curr_size);
Traits::copy(&s.s_[0], s_, n_ + 1); Traits::copy(&s.data()[0], data(), curr_size + 1);
n_ = tmp.n_; this->set_size(tmp.size());
Traits::copy(s_, &tmp.s_[0], n_ + 1); Traits::copy(data(), &tmp.data()[0], size() + 1);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
replace( replace(
@ -587,52 +645,55 @@ replace(
const CharT* s, const CharT* s,
size_type n2) -> fixed_string<N, CharT, Traits>& size_type n2) -> fixed_string<N, CharT, Traits>&
{ {
if (pos > size()) const auto curr_size = size();
const auto curr_data = data();
if (pos > curr_size)
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"pos > size()"}); "pos > size()"});
if (size() - (std::min)(n1, size() - pos) >= max_size() - n2) if (curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2)
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"replaced string exceeds max_size()"}); "replaced string exceeds max_size()"});
if (pos + n1 >= size()) if (pos + n1 >= curr_size)
n1 = size() - pos; n1 = curr_size - pos;
const bool inside = s <= &s_[size()] && s >= s_; const bool inside = s <= &curr_data[curr_size] && s >= curr_data;
if (inside && size_type(s - s_) == pos && n1 == n2) if (inside && size_type(s - curr_data) == pos && n1 == n2)
return *this; return *this;
if (!inside || (inside && ((s - s_) + n2 <= pos))) if (!inside || (inside && ((s - curr_data) + n2 <= pos)))
{ {
// source outside // source outside
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
Traits::copy(&s_[pos], s, n2); Traits::copy(&curr_data[pos], s, n2);
} }
else else
{ {
// source inside // source inside
const size_type offset = s - s_; const size_type offset = s - curr_data;
if (n2 >= n1) if (n2 >= n1)
{ {
// grow/unchanged // grow/unchanged
// shift all right of splice point by n2 - n1 to the right // shift all right of splice point by n2 - n1 to the right
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0;
// copy all before splice point // copy all before splice point
Traits::move(&s_[pos], &s_[offset], diff); Traits::move(&curr_data[pos], &curr_data[offset], diff);
// copy all after splice point // copy all after splice point
Traits::move(&s_[pos + diff], &s_[offset + (n2 - n1) + diff], n2 - diff); Traits::move(&curr_data[pos + diff], &curr_data[offset + (n2 - n1) + diff], n2 - diff);
} }
else else
{ {
// shrink // shrink
// copy all elements into place // copy all elements into place
Traits::move(&s_[pos], &s_[offset], n2); Traits::move(&curr_data[pos], &curr_data[offset], n2);
// shift all elements after splice point left // shift all elements after splice point left
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
} }
} }
n_ += (n2 - n1); this->set_size(curr_size + (n2 - n1));
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
replace( replace(
@ -641,135 +702,150 @@ replace(
size_type n2, size_type n2,
CharT c) -> fixed_string<N, CharT, Traits> & CharT c) -> fixed_string<N, CharT, Traits> &
{ {
if (pos > size()) const auto curr_size = size();
const auto curr_data = data();
if (pos > curr_size)
BOOST_FIXED_STRING_THROW(std::out_of_range{ BOOST_FIXED_STRING_THROW(std::out_of_range{
"pos > size()"}); "pos > size()"});
if (size() - (std::min)(n1, size() - pos) >= max_size() - n2) if (curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2)
BOOST_FIXED_STRING_THROW(std::length_error{ BOOST_FIXED_STRING_THROW(std::length_error{
"replaced string exceeds max_size()"}); "replaced string exceeds max_size()"});
if (pos + n1 >= size()) if (pos + n1 >= curr_size)
n1 = size() - pos; n1 = curr_size - pos;
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
Traits::assign(&s_[pos], n2, c); Traits::assign(&curr_data[pos], n2, c);
n_ += (n2 - n1); this->set_size(curr_size + (n2 - n1));
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
find( find(
const CharT* s, const CharT* s,
size_type pos, size_type pos,
size_type n) const -> size_type n) const noexcept ->
size_type size_type
{ {
if (pos > n_ || n > n_ - pos) const auto curr_size = size();
if (pos > curr_size || n > curr_size - pos)
return npos; return npos;
if (!n) if (!n)
return pos; return pos;
const auto res = std::search(&s_[pos], &s_[n_], s, &s[n], Traits::eq); const auto res = std::search(&data()[pos], &data()[curr_size], s, &s[n], Traits::eq);
return res == end() ? npos : std::distance(s_, res); return res == end() ? npos : std::distance(data(), res);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
rfind( rfind(
const CharT* s, const CharT* s,
size_type pos, size_type pos,
size_type n) const -> size_type n) const noexcept ->
size_type size_type
{ {
if (n_ < n) const auto curr_size = size();
const auto curr_data = data();
if (curr_size < n)
return npos; return npos;
if (pos > n_ - n) if (pos > curr_size - n)
pos = n_ - n; pos = curr_size - n;
if (!n) if (!n)
return pos; return pos;
for (auto sub = &s_[pos]; sub >= s_; --sub) for (auto sub = &curr_data[pos]; sub >= curr_data; --sub)
if (!Traits::compare(sub, s, n)) if (!Traits::compare(sub, s, n))
return std::distance(s_, sub); return std::distance(curr_data, sub);
return npos; return npos;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
find_first_of( find_first_of(
const CharT* s, const CharT* s,
size_type pos, size_type pos,
size_type n) const -> size_type n) const noexcept ->
size_type size_type
{ {
if (pos >= n_ || !n) const auto curr_data = data();
if (pos >= size() || !n)
return npos; return npos;
const auto res = std::find_first_of(&s_[pos], &s_[n_], s, &s[n], Traits::eq); const auto res = std::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], Traits::eq);
return res == end() ? npos : std::distance(s_, res); return res == end() ? npos : std::distance(curr_data, res);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
find_last_of( find_last_of(
const CharT* s, const CharT* s,
size_type pos, size_type pos,
size_type n) const -> size_type n) const noexcept ->
size_type size_type
{ {
const auto curr_size = size();
if (!n) if (!n)
return npos; return npos;
if (pos >= n_) if (pos >= curr_size)
pos = 0; pos = 0;
else else
pos = n_ - (pos + 1); pos = curr_size - (pos + 1);
const auto res = std::find_first_of(rbegin() + pos, rend(), s, &s[n], Traits::eq); const auto res = std::find_first_of(rbegin() + pos, rend(), s, &s[n], Traits::eq);
return res == rend() ? npos : n_ - 1 - std::distance(rbegin(), res); return res == rend() ? npos : curr_size - 1 - std::distance(rbegin(), res);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
find_first_not_of( find_first_not_of(
const CharT* s, const CharT* s,
size_type pos, size_type pos,
size_type n) const -> size_type n) const noexcept ->
size_type size_type
{ {
if (pos >= n_) if (pos >= size())
return npos; return npos;
if (!n) if (!n)
return pos; return pos;
const auto res = detail::find_not_of<Traits>(&s_[pos], &s_[n_], s, n); const auto res = detail::find_not_of<Traits>(&data()[pos], &data()[size()], s, n);
return res == end() ? npos : std::distance(s_, res); return res == end() ? npos : std::distance(data(), res);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
find_last_not_of( find_last_not_of(
const CharT* s, const CharT* s,
size_type pos, size_type pos,
size_type n) const -> size_type n) const noexcept ->
size_type size_type
{ {
if (pos >= n_) const auto curr_size = size();
pos = n_ - 1; if (pos >= curr_size)
pos = curr_size - 1;
if (!n) if (!n)
return pos; return pos;
pos = n_ - (pos + 1); pos = curr_size - (pos + 1);
const auto res = detail::find_not_of<Traits>(rbegin() + pos, rend(), s, n); const auto res = detail::find_not_of<Traits>(rbegin() + pos, rend(), s, n);
return res == rend() ? npos : n_ - 1 - std::distance(rbegin(), res); return res == rend() ? npos : curr_size - 1 - std::distance(rbegin(), res);
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_FIXED_STRING_CPP14_CXPER
auto auto
fixed_string<N, CharT, Traits>:: fixed_string<N, CharT, Traits>::
assign_char(CharT ch, std::true_type) -> assign_char(CharT ch, std::true_type) noexcept ->
fixed_string& fixed_string&
{ {
n_ = 1; this->set_size(1);
Traits::assign(s_[0], ch); Traits::assign(data()[0], ch);
term(); term();
return *this; return *this;
} }

View File

@ -9,7 +9,7 @@
// //
// Test that header file is self-contained. // Test that header file is self-contained.
#include <boost/fixed_string/fixed_string.hpp> #include "boost/fixed_string/fixed_string.hpp"
#include <boost/core/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
@ -23,7 +23,7 @@ testS(const S& s, typename S::size_type pos, typename S::size_type n)
{ {
if (pos <= s.size()) if (pos <= s.size())
{ {
typename S::string_view_type str = s.substr(pos, n); S str = s.substr(pos, n);
typename S::size_type rlen = (std::min)(n, s.size() - pos); typename S::size_type rlen = (std::min)(n, s.size() - pos);
return (S::traits_type::compare(s.data() + pos, str.data(), rlen) == 0); return (S::traits_type::compare(s.data() + pos, str.data(), rlen) == 0);
} }
@ -34,6 +34,23 @@ testS(const S& s, typename S::size_type pos, typename S::size_type n)
} }
} }
template <class S>
bool
testSV(const S& s, typename S::size_type pos, typename S::size_type n)
{
if (pos <= s.size())
{
typename S::string_view_type str = s.subview(pos, n);
typename S::size_type rlen = (std::min)(n, s.size() - pos);
return (S::traits_type::compare(s.data() + pos, str.data(), rlen) == 0);
}
else
{
BOOST_TEST_THROWS((s.subview(pos, n)), std::out_of_range);
return true;
}
}
template <class S> template <class S>
bool bool
testAS(S s, const typename S::value_type* str, typename S::size_type n, S expected) testAS(S s, const typename S::value_type* str, typename S::size_type n, S expected)
@ -413,6 +430,7 @@ testAssignment()
s3 = s1, s3 = s1,
std::length_error); std::length_error);
} }
{ {
fixed_string<3> s1; fixed_string<3> s1;
s1 = "123"; s1 = "123";
@ -6732,6 +6750,129 @@ testSubstr()
BOOST_TEST(testS(S("dplqartnfgejichmoskb"), 21, 0)); BOOST_TEST(testS(S("dplqartnfgejichmoskb"), 21, 0));
} }
// done
void
testSubview()
{
using S = fixed_string<400>;
BOOST_TEST(testSV(S(""), 0, 0));
BOOST_TEST(testSV(S(""), 1, 0));
BOOST_TEST(testSV(S("pniot"), 0, 0));
BOOST_TEST(testSV(S("htaob"), 0, 1));
BOOST_TEST(testSV(S("fodgq"), 0, 2));
BOOST_TEST(testSV(S("hpqia"), 0, 4));
BOOST_TEST(testSV(S("qanej"), 0, 5));
BOOST_TEST(testSV(S("dfkap"), 1, 0));
BOOST_TEST(testSV(S("clbao"), 1, 1));
BOOST_TEST(testSV(S("ihqrf"), 1, 2));
BOOST_TEST(testSV(S("mekdn"), 1, 3));
BOOST_TEST(testSV(S("ngtjf"), 1, 4));
BOOST_TEST(testSV(S("srdfq"), 2, 0));
BOOST_TEST(testSV(S("qkdrs"), 2, 1));
BOOST_TEST(testSV(S("ikcrq"), 2, 2));
BOOST_TEST(testSV(S("cdaih"), 2, 3));
BOOST_TEST(testSV(S("dmajb"), 4, 0));
BOOST_TEST(testSV(S("karth"), 4, 1));
BOOST_TEST(testSV(S("lhcdo"), 5, 0));
BOOST_TEST(testSV(S("acbsj"), 6, 0));
BOOST_TEST(testSV(S("pbsjikaole"), 0, 0));
BOOST_TEST(testSV(S("pcbahntsje"), 0, 1));
BOOST_TEST(testSV(S("mprdjbeiak"), 0, 5));
BOOST_TEST(testSV(S("fhepcrntko"), 0, 9));
BOOST_TEST(testSV(S("eqmpaidtls"), 0, 10));
BOOST_TEST(testSV(S("joidhalcmq"), 1, 0));
BOOST_TEST(testSV(S("omigsphflj"), 1, 1));
BOOST_TEST(testSV(S("kocgbphfji"), 1, 4));
BOOST_TEST(testSV(S("onmjekafbi"), 1, 8));
BOOST_TEST(testSV(S("fbslrjiqkm"), 1, 9));
BOOST_TEST(testSV(S("oqmrjahnkg"), 5, 0));
BOOST_TEST(testSV(S("jeidpcmalh"), 5, 1));
BOOST_TEST(testSV(S("schfalibje"), 5, 2));
BOOST_TEST(testSV(S("crliponbqe"), 5, 4));
BOOST_TEST(testSV(S("igdscopqtm"), 5, 5));
BOOST_TEST(testSV(S("qngpdkimlc"), 9, 0));
BOOST_TEST(testSV(S("thdjgafrlb"), 9, 1));
BOOST_TEST(testSV(S("hcjitbfapl"), 10, 0));
BOOST_TEST(testSV(S("mgojkldsqh"), 11, 0));
BOOST_TEST(testSV(S("gfshlcmdjreqipbontak"), 0, 0));
BOOST_TEST(testSV(S("nadkhpfemgclosibtjrq"), 0, 1));
BOOST_TEST(testSV(S("nkodajteqplrbifhmcgs"), 0, 10));
BOOST_TEST(testSV(S("ofdrqmkeblthacpgijsn"), 0, 19));
BOOST_TEST(testSV(S("gbmetiprqdoasckjfhln"), 0, 20));
BOOST_TEST(testSV(S("bdfjqgatlksriohemnpc"), 1, 0));
BOOST_TEST(testSV(S("crnklpmegdqfiashtojb"), 1, 1));
BOOST_TEST(testSV(S("ejqcnahdrkfsmptilgbo"), 1, 9));
BOOST_TEST(testSV(S("jsbtafedocnirgpmkhql"), 1, 18));
BOOST_TEST(testSV(S("prqgnlbaejsmkhdctoif"), 1, 19));
BOOST_TEST(testSV(S("qnmodrtkebhpasifgcjl"), 10, 0));
BOOST_TEST(testSV(S("pejafmnokrqhtisbcdgl"), 10, 1));
BOOST_TEST(testSV(S("cpebqsfmnjdolhkratgi"), 10, 5));
BOOST_TEST(testSV(S("odnqkgijrhabfmcestlp"), 10, 9));
BOOST_TEST(testSV(S("lmofqdhpkibagnrcjste"), 10, 10));
BOOST_TEST(testSV(S("lgjqketopbfahrmnsicd"), 19, 0));
BOOST_TEST(testSV(S("ktsrmnqagdecfhijpobl"), 19, 1));
BOOST_TEST(testSV(S("lsaijeqhtrbgcdmpfkno"), 20, 0));
BOOST_TEST(testSV(S("dplqartnfgejichmoskb"), 21, 0));
BOOST_TEST(testSV(S(""), 0, 0));
BOOST_TEST(testSV(S(""), 1, 0));
BOOST_TEST(testSV(S("pniot"), 0, 0));
BOOST_TEST(testSV(S("htaob"), 0, 1));
BOOST_TEST(testSV(S("fodgq"), 0, 2));
BOOST_TEST(testSV(S("hpqia"), 0, 4));
BOOST_TEST(testSV(S("qanej"), 0, 5));
BOOST_TEST(testSV(S("dfkap"), 1, 0));
BOOST_TEST(testSV(S("clbao"), 1, 1));
BOOST_TEST(testSV(S("ihqrf"), 1, 2));
BOOST_TEST(testSV(S("mekdn"), 1, 3));
BOOST_TEST(testSV(S("ngtjf"), 1, 4));
BOOST_TEST(testSV(S("srdfq"), 2, 0));
BOOST_TEST(testSV(S("qkdrs"), 2, 1));
BOOST_TEST(testSV(S("ikcrq"), 2, 2));
BOOST_TEST(testSV(S("cdaih"), 2, 3));
BOOST_TEST(testSV(S("dmajb"), 4, 0));
BOOST_TEST(testSV(S("karth"), 4, 1));
BOOST_TEST(testSV(S("lhcdo"), 5, 0));
BOOST_TEST(testSV(S("acbsj"), 6, 0));
BOOST_TEST(testSV(S("pbsjikaole"), 0, 0));
BOOST_TEST(testSV(S("pcbahntsje"), 0, 1));
BOOST_TEST(testSV(S("mprdjbeiak"), 0, 5));
BOOST_TEST(testSV(S("fhepcrntko"), 0, 9));
BOOST_TEST(testSV(S("eqmpaidtls"), 0, 10));
BOOST_TEST(testSV(S("joidhalcmq"), 1, 0));
BOOST_TEST(testSV(S("omigsphflj"), 1, 1));
BOOST_TEST(testSV(S("kocgbphfji"), 1, 4));
BOOST_TEST(testSV(S("onmjekafbi"), 1, 8));
BOOST_TEST(testSV(S("fbslrjiqkm"), 1, 9));
BOOST_TEST(testSV(S("oqmrjahnkg"), 5, 0));
BOOST_TEST(testSV(S("jeidpcmalh"), 5, 1));
BOOST_TEST(testSV(S("schfalibje"), 5, 2));
BOOST_TEST(testSV(S("crliponbqe"), 5, 4));
BOOST_TEST(testSV(S("igdscopqtm"), 5, 5));
BOOST_TEST(testSV(S("qngpdkimlc"), 9, 0));
BOOST_TEST(testSV(S("thdjgafrlb"), 9, 1));
BOOST_TEST(testSV(S("hcjitbfapl"), 10, 0));
BOOST_TEST(testSV(S("mgojkldsqh"), 11, 0));
BOOST_TEST(testSV(S("gfshlcmdjreqipbontak"), 0, 0));
BOOST_TEST(testSV(S("nadkhpfemgclosibtjrq"), 0, 1));
BOOST_TEST(testSV(S("nkodajteqplrbifhmcgs"), 0, 10));
BOOST_TEST(testSV(S("ofdrqmkeblthacpgijsn"), 0, 19));
BOOST_TEST(testSV(S("gbmetiprqdoasckjfhln"), 0, 20));
BOOST_TEST(testSV(S("bdfjqgatlksriohemnpc"), 1, 0));
BOOST_TEST(testSV(S("crnklpmegdqfiashtojb"), 1, 1));
BOOST_TEST(testSV(S("ejqcnahdrkfsmptilgbo"), 1, 9));
BOOST_TEST(testSV(S("jsbtafedocnirgpmkhql"), 1, 18));
BOOST_TEST(testSV(S("prqgnlbaejsmkhdctoif"), 1, 19));
BOOST_TEST(testSV(S("qnmodrtkebhpasifgcjl"), 10, 0));
BOOST_TEST(testSV(S("pejafmnokrqhtisbcdgl"), 10, 1));
BOOST_TEST(testSV(S("cpebqsfmnjdolhkratgi"), 10, 5));
BOOST_TEST(testSV(S("odnqkgijrhabfmcestlp"), 10, 9));
BOOST_TEST(testSV(S("lmofqdhpkibagnrcjste"), 10, 10));
BOOST_TEST(testSV(S("lgjqketopbfahrmnsicd"), 19, 0));
BOOST_TEST(testSV(S("ktsrmnqagdecfhijpobl"), 19, 1));
BOOST_TEST(testSV(S("lsaijeqhtrbgcdmpfkno"), 20, 0));
BOOST_TEST(testSV(S("dplqartnfgejichmoskb"), 21, 0));
}
// done // done
void void
testStartsEnds() testStartsEnds()
@ -6752,6 +6893,14 @@ testStartsEnds()
BOOST_TEST(S("1234567890").ends_with(string_view("1234567890"))); BOOST_TEST(S("1234567890").ends_with(string_view("1234567890")));
} }
void testHash()
{
using U = fixed_string<30>;
std::hash<U> hasher;
BOOST_TEST(hasher(U("1")) != hasher(U("123456789")));
BOOST_TEST(hasher(U("1234567890")) == hasher(U("1234567890")));
}
int int
runTests() runTests()
{ {
@ -6784,9 +6933,31 @@ runTests()
testSubstr(); testSubstr();
testStartsEnds(); testStartsEnds();
testHash();
return report_errors(); return report_errors();
} }
static_assert(std::is_base_of<
detail::fixed_string_base_zero<0, char, std::char_traits<char>>,
fixed_string<0>>::value,
"the zero size optimization shall be used for N = 0");
//static_assert(std::is_base_of<
// detail::fixed_string_base_null<1, char, std::char_traits<char>>,
// fixed_string<1>>::value,
// "the null terminator optimization shall be used for N <= (std::numeric_limits<char>::max)()");
//
//static_assert(std::is_base_of<
// detail::fixed_string_base_null<(std::numeric_limits<char>::max)(), char, std::char_traits<char>>,
// fixed_string<(std::numeric_limits<char>::max)()>>::value,
// "the null terminator optimization shall be used for N <= std::numeric_limits<char>::max()");
static_assert(std::is_base_of<
detail::fixed_string_base_zero<(std::numeric_limits<char>::max)() + 1, char, std::char_traits<char>>,
fixed_string<(std::numeric_limits<char>::max)() + 1>>::value,
"the minimum size type optimization shall be used for N > std::numeric_limits<char>::max()");
} // fixed_string } // fixed_string
} // boost } // boost