Files
boost_static_string/include/boost/fixed_string/impl/fixed_string.hpp

811 lines
20 KiB
C++
Raw Normal View History

2019-09-09 13:56:14 -07:00
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
2019-11-06 18:58:22 -05:00
// Copyright (c) 2019 Krystian Stasiowski (sdkrystian at gmail dot com)
2019-09-09 13:56:14 -07: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)
//
// Official repository: https://github.com/boostorg/fixed_string
//
#ifndef BOOST_FIXED_STRING_IMPL_FIXED_STRING_HPP
#define BOOST_FIXED_STRING_IMPL_FIXED_STRING_HPP
2019-10-27 16:12:06 -04:00
#include <boost/fixed_string/config.hpp>
2019-09-09 13:56:14 -07:00
#include <boost/fixed_string/detail/fixed_string.hpp>
namespace boost {
namespace fixed_string {
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
//
2019-09-16 08:31:09 -07:00
// Construction
2019-09-09 13:56:14 -07:00
//
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
fixed_string()
{
n_ = 0;
term();
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
fixed_string(size_type count, CharT ch)
{
assign(count, ch);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<std::size_t M>
fixed_string<N, CharT, Traits>::
fixed_string(fixed_string<M, CharT, Traits> const& other,
size_type pos)
{
assign(other, pos);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<std::size_t M>
fixed_string<N, CharT, Traits>::
2019-09-13 14:27:09 -07:00
fixed_string(
fixed_string<M, CharT, Traits> const& other,
size_type pos,
size_type count)
2019-09-09 13:56:14 -07:00
{
assign(other, pos, count);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
fixed_string(CharT const* s, size_type count)
{
assign(s, count);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
fixed_string(CharT const* s)
{
auto const count = Traits::length(s);
if(count > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"count > max_size()"});
n_ = count;
2019-10-31 16:42:04 -04:00
Traits::copy(s_, s, n_ + 1);
2019-09-09 13:56:14 -07:00
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<class InputIt>
fixed_string<N, CharT, Traits>::
2019-09-13 14:27:09 -07:00
fixed_string(
InputIt first,
InputIt last,
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
iterator>::type*)
2019-09-09 13:56:14 -07:00
{
assign(first, last);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
2019-09-13 14:27:09 -07:00
fixed_string(
fixed_string const& s)
2019-09-09 13:56:14 -07:00
{
assign(s);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<std::size_t M>
fixed_string<N, CharT, Traits>::
2019-09-13 14:27:09 -07:00
fixed_string(
fixed_string<M, CharT, Traits> const& s)
2019-09-09 13:56:14 -07:00
{
assign(s);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
fixed_string(std::initializer_list<CharT> init)
{
assign(init.begin(), init.end());
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
fixed_string<N, CharT, Traits>::
fixed_string(string_view_type sv)
{
assign(sv);
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<class T, class>
fixed_string<N, CharT, Traits>::
fixed_string(T const& t, size_type pos, size_type n)
{
assign(t, pos, n);
}
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
//
2019-09-16 08:31:09 -07:00
// Assignment
2019-09-09 13:56:14 -07:00
//
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
assign(
size_type count,
CharT ch) ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
if(count > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"count > max_size()"});
n_ = count;
2019-10-31 16:42:04 -04:00
Traits::assign(s_, n_, ch);
2019-09-09 13:56:14 -07:00
term();
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
assign(
fixed_string const& s) noexcept ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
2019-09-16 08:31:09 -07:00
if(this == &s)
return *this;
2019-09-13 14:27:09 -07:00
n_ = s.n_;
2019-09-09 13:56:14 -07:00
auto const n = n_ + 1;
2019-09-16 08:31:09 -07:00
// VFALCO This informs the static analyzer
2019-09-09 13:56:14 -07:00
//BOOST_BEAST_ASSUME(n != 0);
2019-10-31 16:42:04 -04:00
Traits::copy(s_, &s.s_[0], n);
2019-09-09 13:56:14 -07:00
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<std::size_t M>
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
assign(
fixed_string<M, CharT, Traits> const& s,
size_type pos,
size_type count) ->
2019-09-09 13:56:14 -07:00
fixed_string&
{
2019-09-13 14:27:09 -07:00
auto const ss = s.substr(pos, count);
2019-09-09 13:56:14 -07:00
return assign(ss.data(), ss.size());
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
assign(
CharT const* s,
size_type count) ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
if(count > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"count > max_size()"});
n_ = count;
// check for overlap, then move if needed
2019-10-31 16:42:04 -04:00
if (s <= &s_[size()] && s >= s_)
Traits::move(s_, s, n_);
else
2019-10-31 16:42:04 -04:00
Traits::copy(s_, s, n_);
2019-09-09 13:56:14 -07:00
term();
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<class InputIt>
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
assign(
InputIt first,
InputIt last) ->
typename std::enable_if<
detail::is_input_iterator<InputIt>::value,
fixed_string&>::type
2019-09-09 13:56:14 -07:00
{
std::size_t const n = std::distance(first, last);
if(n > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"n > max_size()"});
n_ = n;
2019-10-31 16:42:04 -04:00
for(auto it = s_; first != last; ++it, ++first)
2019-09-09 13:56:14 -07:00
Traits::assign(*it, *first);
term();
return *this;
}
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
//
// Element access
//
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
at(size_type pos) ->
reference
{
if(pos >= size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-09-09 13:56:14 -07:00
"pos >= size()"});
return s_[pos];
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
at(size_type pos) const ->
const_reference
{
if(pos >= size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-09-09 13:56:14 -07:00
"pos >= size()"});
return s_[pos];
}
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
//
// Capacity
//
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
void
fixed_string<N, CharT, Traits>::
reserve(std::size_t n)
{
if(n > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"n > max_size()"});
}
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
//
// Operations
//
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-09 13:56:14 -07:00
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
void
fixed_string<N, CharT, Traits>::
clear()
{
n_ = 0;
term();
}
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
insert(
size_type index,
size_type count,
CharT ch) ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
if(index > size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-09-09 13:56:14 -07:00
"index > size()"});
insert(begin() + index, count, ch);
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
insert(
size_type index,
CharT const* s,
size_type count) ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
if(index > size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-09-09 13:56:14 -07:00
"index > size()"});
if(size() + count > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"size() + count > max_size()"});
2019-10-31 16:42:04 -04:00
const bool inside = s <= &s_[size()] && s >= s_;
if (!inside || (inside && ((s - s_) + count <= index)))
{
Traits::move(&s_[index + count], &s_[index], size() - index + 1);
Traits::copy(&s_[index], s, count);
}
else
{
2019-10-31 16:42:04 -04:00
const size_type offset = s - s_;
Traits::move(&s_[index + count], &s_[index], size() - index + 1);
if (offset < index)
{
const size_type diff = index - offset;
Traits::copy(&s_[index], &s_[offset], diff);
Traits::copy(&s_[index + diff], &s_[index + count], count - diff);
}
else
{
Traits::copy(&s_[index], &s_[offset + count], count);
}
}
2019-09-09 13:56:14 -07:00
n_ += count;
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
insert(
const_iterator pos,
size_type count,
CharT ch) ->
iterator
2019-09-09 13:56:14 -07:00
{
if(size() + count > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"size() + count() > max_size()"});
2019-10-31 16:42:04 -04:00
auto const index = pos - s_;
2019-09-09 13:56:14 -07:00
Traits::move(
&s_[index + count], &s_[index], size() - index);
n_ += count;
Traits::assign(&s_[index], count, ch);
term();
return &s_[index];
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<class InputIt>
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
insert(
const_iterator pos,
InputIt first,
InputIt last) ->
typename std::enable_if<
detail::is_input_iterator<
InputIt>::value, iterator>::type
2019-09-09 13:56:14 -07:00
{
const size_type index = pos - begin();
return insert(index, &*first, std::distance(first, last)).begin() + index;
2019-09-09 13:56:14 -07:00
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<class T>
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
insert(
size_type index,
T const & t) ->
typename std::enable_if<
std::is_convertible<
T const&, string_view_type>::value &&
! std::is_convertible<
T const&, CharT const*>::value, fixed_string&
>::type
{
return insert(index, t, 0, npos);
}
template<std::size_t N, typename CharT, typename Traits>
template<class T>
auto
fixed_string<N, CharT, Traits>::
insert(
size_type index,
T const & t,
size_type index_str,
size_type count) ->
typename std::enable_if<
std::is_convertible<
T const&, string_view_type>::value &&
! std::is_convertible<
T const&, CharT const*>::value, fixed_string&
>::type
2019-09-09 13:56:14 -07:00
{
2019-09-13 14:27:09 -07:00
auto const s =
2019-09-09 13:56:14 -07:00
string_view_type(t).substr(index_str, count);
2019-09-13 14:27:09 -07:00
return insert(index, s.data(), s.size());
2019-09-09 13:56:14 -07:00
}
2019-09-16 08:31:09 -07:00
//------------------------------------------------------------------------------
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
erase(
size_type index,
size_type count) ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
if(index > size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-09-09 13:56:14 -07:00
"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;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
erase(
const_iterator pos) ->
iterator
2019-09-09 13:56:14 -07:00
{
erase(pos - begin(), 1);
return begin() + (pos - begin());
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
erase(
const_iterator first,
const_iterator last) ->
iterator
2019-09-09 13:56:14 -07:00
{
erase(first - begin(),
std::distance(first, last));
return begin() + (first - begin());
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
void
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
push_back(
CharT ch)
2019-09-09 13:56:14 -07:00
{
if(size() >= max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"size() >= max_size()"});
Traits::assign(s_[n_++], ch);
term();
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
2019-09-16 08:31:09 -07:00
append(
CharT const* s,
size_type count) ->
fixed_string&
2019-09-09 13:56:14 -07:00
{
2019-09-16 08:31:09 -07:00
if(size() + count > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-16 08:31:09 -07:00
"size() + count > max_size()"});
Traits::move(
&s_[n_ + count], &s_[n_], size() - n_);
Traits::copy(&s_[n_], s, count);
n_ += count;
term();
2019-09-09 13:56:14 -07:00
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
substr(size_type pos, size_type count) const ->
string_view
2019-09-09 13:56:14 -07:00
{
if(pos > size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-09-09 13:56:14 -07:00
"pos > size()"});
2019-10-27 16:12:06 -04:00
return {&s_[pos], (std::min)(count, size() - pos)};
2019-09-09 13:56:14 -07:00
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
copy(CharT* dest, size_type count, size_type pos) const ->
size_type
{
2019-09-13 14:27:09 -07:00
auto const s = substr(pos, count);
Traits::copy(dest, s.data(), s.size());
return s.size();
2019-09-09 13:56:14 -07:00
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
void
fixed_string<N, CharT, Traits>::
resize(std::size_t n)
{
if(n > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"n > max_size()"});
if(n > n_)
Traits::assign(&s_[n_], n - n_, CharT{});
n_ = n;
term();
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
void
fixed_string<N, CharT, Traits>::
resize(std::size_t n, CharT c)
{
if(n > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"n > max_size()"});
if(n > n_)
Traits::assign(&s_[n_], n - n_, c);
n_ = n;
term();
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
void
fixed_string<N, CharT, Traits>::
2019-09-13 14:27:09 -07:00
swap(fixed_string& s)
2019-09-09 13:56:14 -07:00
{
2019-09-13 14:27:09 -07:00
fixed_string tmp(s);
s.n_ = n_;
2019-10-31 16:42:04 -04:00
Traits::copy(&s.s_[0], s_, n_ + 1);
2019-09-09 13:56:14 -07:00
n_ = tmp.n_;
2019-10-31 16:42:04 -04:00
Traits::copy(s_, &tmp.s_[0], n_ + 1);
2019-09-09 13:56:14 -07:00
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
template<std::size_t M>
void
fixed_string<N, CharT, Traits>::
2019-09-13 14:27:09 -07:00
swap(fixed_string<M, CharT, Traits>& s)
2019-09-09 13:56:14 -07:00
{
2019-09-13 14:27:09 -07:00
if(size() > s.max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-13 14:27:09 -07:00
"size() > s.max_size()"});
if(s.size() > max_size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-13 14:27:09 -07:00
"s.size() > max_size()"});
fixed_string tmp(s);
s.n_ = n_;
2019-10-31 16:42:04 -04:00
Traits::copy(&s.s_[0], s_, n_ + 1);
2019-09-09 13:56:14 -07:00
n_ = tmp.n_;
2019-10-31 16:42:04 -04:00
Traits::copy(s_, &tmp.s_[0], n_ + 1);
2019-09-09 13:56:14 -07:00
}
2019-10-18 20:52:07 -04:00
template<std::size_t N, typename CharT, typename Traits>
2019-10-18 20:50:42 -04:00
auto
fixed_string<N, CharT, Traits>::
replace(
size_type pos,
size_type n1,
const CharT* s,
size_type n2) -> fixed_string<N, CharT, Traits>&
{
if (pos > size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-10-18 20:50:42 -04:00
"pos > size()"});
2019-10-30 14:05:52 -04:00
if (size() - (std::min)(n1, size() - pos) >= max_size() - n2)
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
"replaced string exceeds max_size()"});
if (pos + n1 >= size())
n1 = size() - pos;
2019-10-31 16:42:04 -04:00
const bool inside = s <= &s_[size()] && s >= s_;
if (inside && size_type(s - s_) == pos && n1 == n2)
return *this;
if (!inside || (inside && ((s - s_) + n2 <= pos)))
{
// source outside
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1);
Traits::copy(&s_[pos], s, n2);
}
else
{
// source inside
2019-10-31 16:42:04 -04:00
const size_type offset = s - s_;
if (n2 >= n1)
{
// grow/unchanged
2019-10-31 16:42:04 -04:00
// shift all right of splice point by n2 - n1 to the right
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1);
2019-10-31 16:42:04 -04:00
const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0;
// copy all before splice point
Traits::move(&s_[pos], &s_[offset], diff);
2019-10-31 16:42:04 -04:00
// copy all after splice point
Traits::move(&s_[pos + diff], &s_[offset + (n2 - n1) + diff], n2 - diff);
}
else
{
// shrink
2019-10-31 16:42:04 -04:00
// copy all elements into place
Traits::move(&s_[pos], &s_[offset], n2);
2019-10-31 16:42:04 -04:00
// shift all elements after splice point left
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1);
}
}
2019-10-18 20:50:42 -04:00
n_ += (n2 - n1);
return *this;
}
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
replace(
size_type pos,
size_type n1,
size_type n2,
CharT c) -> fixed_string<N, CharT, Traits> &
{
if (pos > size())
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::out_of_range{
2019-10-18 20:50:42 -04:00
"pos > size()"});
2019-10-30 14:05:52 -04:00
if (size() - (std::min)(n1, size() - pos) >= max_size() - n2)
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-10-18 20:50:42 -04:00
"replaced string exceeds max_size()"});
if (pos + n1 >= size())
n1 = size() - pos;
2019-10-18 20:50:42 -04:00
Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1);
Traits::assign(&s_[pos], n2, c);
n_ += (n2 - n1);
return *this;
}
2019-10-27 16:12:06 -04:00
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
find(
const CharT* s,
size_type pos,
size_type n) const ->
size_type
{
2019-10-27 16:26:49 -04:00
if (pos > n_ || n > n_ - pos)
2019-10-27 16:12:06 -04:00
return npos;
if (!n)
return pos;
const auto res = std::search(&s_[pos], &s_[n_], s, &s[n], Traits::eq);
return res == end() ? npos : std::distance(s_, res);
}
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
rfind(
const CharT* s,
size_type pos,
size_type n) const ->
size_type
{
if (n_ < n)
2019-10-27 16:12:06 -04:00
return npos;
if (pos > n_ - n)
pos = n_ - n;
if (!n)
return pos;
2019-10-27 16:12:06 -04:00
for (auto sub = &s_[pos]; sub >= s_; --sub)
if (!Traits::compare(sub, s, n))
return std::distance(s_, sub);
return npos;
}
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
find_first_of(
const CharT* s,
size_type pos,
size_type n) const ->
size_type
{
if (pos >= n_ || !n)
return npos;
const auto res = std::find_first_of(&s_[pos], &s_[n_], s, &s[n], Traits::eq);
return res == end() ? npos : std::distance(s_, res);
}
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
find_last_of(
const CharT* s,
size_type pos,
size_type n) const ->
size_type
{
if (!n)
return npos;
if (pos >= n_)
pos = 0;
else
pos = n_ - (pos + 1);
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);
}
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
find_first_not_of(
const CharT* s,
size_type pos,
size_type n) const ->
size_type
{
if (pos >= n_)
return npos;
if (!n)
return pos;
const auto res = detail::find_not_of<Traits>(&s_[pos], &s_[n_], s, n);
return res == end() ? npos : std::distance(s_, res);
}
template<std::size_t N, typename CharT, typename Traits>
auto
fixed_string<N, CharT, Traits>::
find_last_not_of(
const CharT* s,
size_type pos,
size_type n) const ->
size_type
{
if (pos >= n_)
pos = n_ - 1;
if (!n)
return pos;
pos = n_ - (pos + 1);
const auto res = detail::find_not_of<Traits>(rbegin() + pos, rend(), s, n);
return res == rend() ? npos : n_ - 1 - std::distance(rbegin(), res);
}
2019-09-09 13:56:14 -07:00
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
assign_char(CharT ch, std::true_type) ->
fixed_string&
{
n_ = 1;
Traits::assign(s_[0], ch);
term();
return *this;
}
2019-09-13 14:27:09 -07:00
template<std::size_t N, typename CharT, typename Traits>
2019-09-09 13:56:14 -07:00
auto
fixed_string<N, CharT, Traits>::
assign_char(CharT, std::false_type) ->
fixed_string&
{
2019-10-27 16:12:06 -04:00
BOOST_FIXED_STRING_THROW(std::length_error{
2019-09-09 13:56:14 -07:00
"max_size() == 0"});
}
template<class Integer, class>
2019-10-27 21:01:44 -04:00
inline
2019-09-09 13:56:14 -07:00
fixed_string<detail::max_digits(sizeof(Integer))>
to_fixed_string(Integer x)
{
using CharT = char;
using Traits = std::char_traits<CharT>;
2019-10-27 19:40:29 -04:00
BOOST_FIXED_STRING_STATIC_ASSERT(std::is_integral<Integer>::value, "Integer must be an integral type");
2019-09-09 13:56:14 -07:00
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);
fixed_string<detail::max_digits(sizeof(Integer))> s;
s.resize(static_cast<std::size_t>(last - it));
auto p = s.data();
while(it < last)
Traits::assign(*p++, *it++);
return s;
}
} // fixed_string
} // boost
#endif