diff --git a/include/boost/static_string/impl/static_string.hpp b/include/boost/static_string/impl/static_string.hpp index ebfdf22..5438bbb 100644 --- a/include/boost/static_string/impl/static_string.hpp +++ b/include/boost/static_string/impl/static_string.hpp @@ -29,7 +29,7 @@ basic_static_string:: basic_static_string() noexcept { #ifdef BOOST_STATIC_STRING_CPP20_CONSTEXPR_USED - term(); + term(); #endif } @@ -38,7 +38,7 @@ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string:: basic_static_string(size_type count, CharT ch) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(count, ch); + assign(count, ch); } template @@ -48,7 +48,7 @@ basic_static_string:: basic_static_string(basic_static_string const& other, size_type pos) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(other, pos); + assign(other, pos); } template @@ -60,7 +60,7 @@ basic_static_string( size_type pos, size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(other, pos, count); + assign(other, pos, count); } template @@ -68,7 +68,7 @@ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string:: basic_static_string(CharT const* s, size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(s, count); + assign(s, count); } template @@ -76,11 +76,11 @@ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string:: basic_static_string(CharT const* s) BOOST_STATIC_STRING_COND_NOEXCEPT { - auto const count = Traits::length(s); - BOOST_STATIC_STRING_THROW_IF(count > max_size(), - std::length_error{"count > max_size()"}); - this->set_size(count); - Traits::copy(data(), s, size() + 1); + auto const count = Traits::length(s); + BOOST_STATIC_STRING_THROW_IF(count > max_size(), + std::length_error{"count > max_size()"}); + this->set_size(count); + Traits::copy(data(), s, size() + 1); } template @@ -94,7 +94,7 @@ basic_static_string( detail::is_input_iterator::value, iterator>::type*) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(first, last); + assign(first, last); } template @@ -103,7 +103,7 @@ basic_static_string:: basic_static_string( basic_static_string const& s) noexcept { - assign(s); + assign(s); } template @@ -113,7 +113,7 @@ basic_static_string:: basic_static_string( basic_static_string const& s) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(s); + assign(s); } template @@ -121,7 +121,7 @@ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string:: basic_static_string(std::initializer_list init) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(init.begin(), init.end()); + assign(init.begin(), init.end()); } template @@ -129,7 +129,7 @@ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string:: basic_static_string(string_view_type sv) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(sv); + assign(sv); } template @@ -138,7 +138,7 @@ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string:: basic_static_string(T const& t, size_type pos, size_type n) BOOST_STATIC_STRING_COND_NOEXCEPT { - assign(t, pos, n); + assign(t, pos, n); } //------------------------------------------------------------------------------ @@ -156,12 +156,12 @@ assign( CharT ch) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - BOOST_STATIC_STRING_THROW_IF(count > max_size(), - std::length_error{"count > max_size()"}); - this->set_size(count); - Traits::assign(data(), size(), ch); - term(); - return *this; + BOOST_STATIC_STRING_THROW_IF(count > max_size(), + std::length_error{"count > max_size()"}); + this->set_size(count); + Traits::assign(data(), size(), ch); + term(); + return *this; } template @@ -172,12 +172,12 @@ assign( basic_static_string const& s) noexcept -> basic_static_string& { - if(this == &s) - return *this; - this->set_size(s.size()); - auto const n = size() + 1; - Traits::copy(data(), &s.data()[0], n); - return *this; + if(this == &s) + return *this; + this->set_size(s.size()); + auto const n = size() + 1; + Traits::copy(data(), &s.data()[0], n); + return *this; } template @@ -191,8 +191,8 @@ assign( size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - auto const ss = s.subview(pos, count); - return assign(ss.data(), ss.size()); + auto const ss = s.subview(pos, count); + return assign(ss.data(), ss.size()); } template @@ -204,12 +204,12 @@ assign( size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - BOOST_STATIC_STRING_THROW_IF(count > max_size(), - std::length_error{"count > max_size()"}); - this->set_size(count); - Traits::move(data(), s, size()); - term(); - return *this; + BOOST_STATIC_STRING_THROW_IF(count > max_size(), + std::length_error{"count > max_size()"}); + this->set_size(count); + Traits::move(data(), s, size()); + term(); + return *this; } template @@ -224,19 +224,19 @@ assign( detail::is_input_iterator::value, basic_static_string&>::type { - auto ptr = data(); - for (std::size_t i = 0; first != last; ++first, ++ptr, ++i) + auto ptr = data(); + for (std::size_t i = 0; first != last; ++first, ++ptr, ++i) + { + if (1 > max_size() - i) { - if (1 > max_size() - i) - { - this->set_size(i); - BOOST_STATIC_STRING_THROW(std::length_error{"n > max_size()"}); - } - Traits::assign(*ptr, *first); + this->set_size(i); + BOOST_STATIC_STRING_THROW(std::length_error{"n > max_size()"}); } - this->set_size(ptr - data()); - term(); - return *this; + Traits::assign(*ptr, *first); + } + this->set_size(ptr - data()); + term(); + return *this; } //------------------------------------------------------------------------------ @@ -252,9 +252,9 @@ basic_static_string:: at(size_type pos) BOOST_STATIC_STRING_COND_NOEXCEPT -> reference { - BOOST_STATIC_STRING_THROW_IF( - pos >= size(), std::out_of_range{"pos >= size()"}); - return data()[pos]; + BOOST_STATIC_STRING_THROW_IF( + pos >= size(), std::out_of_range{"pos >= size()"}); + return data()[pos]; } template @@ -264,9 +264,9 @@ basic_static_string:: at(size_type pos) const BOOST_STATIC_STRING_COND_NOEXCEPT -> const_reference { - BOOST_STATIC_STRING_THROW_IF( - pos >= size(), std::out_of_range{"pos >= size()"}); - return data()[pos]; + BOOST_STATIC_STRING_THROW_IF( + pos >= size(), std::out_of_range{"pos >= size()"}); + return data()[pos]; } //------------------------------------------------------------------------------ @@ -281,8 +281,8 @@ void basic_static_string:: reserve(std::size_t n) BOOST_STATIC_STRING_COND_NOEXCEPT { - BOOST_STATIC_STRING_THROW_IF( - n > max_size(), std::length_error{"n > max_size()"}); + BOOST_STATIC_STRING_THROW_IF( + n > max_size(), std::length_error{"n > max_size()"}); } //------------------------------------------------------------------------------ @@ -297,8 +297,8 @@ void basic_static_string:: clear() noexcept { - this->set_size(0); - term(); + this->set_size(0); + term(); } //------------------------------------------------------------------------------ @@ -313,35 +313,12 @@ insert( size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - const auto curr_size = size(); - const auto curr_data = data(); - BOOST_STATIC_STRING_THROW_IF( - index > curr_size, std::out_of_range{"index > size()"}); - BOOST_STATIC_STRING_THROW_IF( - count > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); - const bool inside = s <= &curr_data[curr_size] && s >= curr_data; - if (!inside || (inside && ((s - curr_data) + count <= index))) - { - Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); - Traits::copy(&curr_data[index], s, count); - } - else - { - const size_type offset = s - curr_data; - Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); - if (offset < index) - { - const size_type diff = index - offset; - Traits::copy(&curr_data[index], &curr_data[offset], diff); - Traits::copy(&curr_data[index + diff], &curr_data[index + count], count - diff); - } - else - { - Traits::copy(&curr_data[index], &curr_data[offset + count], count); - } - } - this->set_size(curr_size + count); - return *this; + const auto curr_size = size(); + const auto curr_data = data(); + BOOST_STATIC_STRING_THROW_IF( + index > curr_size, std::out_of_range{"index > size()"}); + insert(curr_data + index, s, s + count); + return *this; } template @@ -354,16 +331,16 @@ insert( CharT ch) BOOST_STATIC_STRING_COND_NOEXCEPT -> iterator { - const auto curr_size = size(); - const auto curr_data = data(); - BOOST_STATIC_STRING_THROW_IF( - count > max_size() - curr_size, std::length_error{"count() > max_size() - size()"}); - auto const index = pos - curr_data; - Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index); - this->set_size(curr_size + count); - Traits::assign(&curr_data[index], count, ch); - term(); - return &curr_data[index]; + const auto curr_size = size(); + const auto curr_data = data(); + BOOST_STATIC_STRING_THROW_IF( + count > max_size() - curr_size, std::length_error{"count() > max_size() - size()"}); + auto const index = pos - curr_data; + Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index); + this->set_size(curr_size + count); + Traits::assign(&curr_data[index], count, ch); + term(); + return &curr_data[index]; } template @@ -379,38 +356,36 @@ insert( detail::is_forward_iterator< ForwardIterator>::value, iterator>::type { - const auto curr_size = size(); - const auto curr_data = data(); - const auto count = detail::distance(first, last); - const auto index = pos - curr_data; - const auto s = &*first; - BOOST_STATIC_STRING_THROW_IF( - index > curr_size, std::out_of_range{"index > size()"}); - BOOST_STATIC_STRING_THROW_IF( - count > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); - const bool inside = s <= &curr_data[curr_size] && s >= curr_data; - if (!inside || (inside && ((s - curr_data) + count <= index))) + const auto curr_size = size(); + const auto curr_data = data(); + const auto count = detail::distance(first, last); + const auto index = pos - curr_data; + const auto s = &*first; + BOOST_STATIC_STRING_THROW_IF( + count > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); + const bool inside = s <= &curr_data[curr_size] && s >= curr_data; + if (!inside || (inside && ((s - curr_data) + count <= index))) + { + Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); + detail::copy_with_traits(first, last, &curr_data[index]); + } + else + { + const size_type offset = s - curr_data; + Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); + if (offset < index) { - Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); - detail::copy_with_traits(first, last, &curr_data[index]); + const size_type diff = index - offset; + Traits::copy(&curr_data[index], &curr_data[offset], diff); + Traits::copy(&curr_data[index + diff], &curr_data[index + count], count - diff); } else { - const size_type offset = s - curr_data; - Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); - if (offset < index) - { - const size_type diff = index - offset; - Traits::copy(&curr_data[index], &curr_data[offset], diff); - Traits::copy(&curr_data[index + diff], &curr_data[index + count], count - diff); - } - else - { - Traits::copy(&curr_data[index], &curr_data[offset + count], count); - } + Traits::copy(&curr_data[index], &curr_data[offset + count], count); } - this->set_size(curr_size + count); - return begin() + index; + } + this->set_size(curr_size + count); + return curr_data + index; } template @@ -428,16 +403,16 @@ insert( ! detail::is_forward_iterator< InputIterator>::value, iterator>::type { - const auto curr_size = size(); - const auto curr_data = data(); - const auto count = read_back(first, last); - const auto index = pos - curr_data; - const auto s = curr_data + curr_size + 1; - BOOST_STATIC_STRING_THROW_IF( - index > curr_size, std::out_of_range{"index > size()"}); - std::rotate(&curr_data[index], &curr_data[curr_size + 1], &curr_data[curr_size + count + 1]); - this->set_size(curr_size + count); - return curr_data + index; + const auto curr_size = size(); + const auto curr_data = data(); + const auto count = read_back(first, last); + const auto index = pos - curr_data; + const auto s = curr_data + curr_size + 1; + BOOST_STATIC_STRING_THROW_IF( + index > curr_size, std::out_of_range{"index > size()"}); + std::rotate(&curr_data[index], &curr_data[curr_size + 1], &curr_data[curr_size + count + 1]); + this->set_size(curr_size + count); + return curr_data + index; } template @@ -449,17 +424,17 @@ insert( std::initializer_list ilist) BOOST_STATIC_STRING_COND_NOEXCEPT -> iterator { - const auto curr_size = size(); - const auto curr_data = data(); - const auto index = pos - curr_data; - BOOST_STATIC_STRING_THROW_IF( - index > curr_size, std::out_of_range{"index > size()"}); - BOOST_STATIC_STRING_THROW_IF( - ilist.size() > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); - Traits::move(&curr_data[index + ilist.size()], &curr_data[index], curr_size - index + 1); - detail::copy_with_traits(ilist.begin(), ilist.end(), &curr_data[index]); - this->set_size(curr_size + ilist.size()); - return curr_data + index; + const auto curr_size = size(); + const auto curr_data = data(); + const auto index = pos - curr_data; + BOOST_STATIC_STRING_THROW_IF( + index > curr_size, std::out_of_range{"index > size()"}); + BOOST_STATIC_STRING_THROW_IF( + ilist.size() > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); + Traits::move(&curr_data[index + ilist.size()], &curr_data[index], curr_size - index + 1); + detail::copy_with_traits(ilist.begin(), ilist.end(), &curr_data[index]); + this->set_size(curr_size + ilist.size()); + return curr_data + index; } //------------------------------------------------------------------------------ @@ -473,14 +448,14 @@ erase( size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - const auto curr_size = size(); - const auto curr_data = data(); - BOOST_STATIC_STRING_THROW_IF( - index > curr_size, std::out_of_range{"index > size()"}); - auto const n = (std::min)(count, curr_size - index); - Traits::move(&curr_data[index], &curr_data[index + n], curr_size - (index + n) + 1); - this->set_size(curr_size - n); - return *this; + const auto curr_size = size(); + const auto curr_data = data(); + BOOST_STATIC_STRING_THROW_IF( + index > curr_size, std::out_of_range{"index > size()"}); + auto const n = (std::min)(count, curr_size - index); + Traits::move(&curr_data[index], &curr_data[index + n], curr_size - (index + n) + 1); + this->set_size(curr_size - n); + return *this; } template @@ -491,8 +466,8 @@ erase( const_iterator pos) BOOST_STATIC_STRING_COND_NOEXCEPT -> iterator { - erase(pos - begin(), 1); - return begin() + (pos - begin()); + erase(pos - begin(), 1); + return begin() + (pos - begin()); } template @@ -504,9 +479,9 @@ erase( const_iterator last) BOOST_STATIC_STRING_COND_NOEXCEPT -> iterator { - erase(first - begin(), - detail::distance(first, last)); - return begin() + (first - begin()); + erase(first - begin(), + detail::distance(first, last)); + return begin() + (first - begin()); } template @@ -516,12 +491,12 @@ basic_static_string:: push_back( CharT ch) BOOST_STATIC_STRING_COND_NOEXCEPT { - const auto curr_size = size(); - BOOST_STATIC_STRING_THROW_IF( - curr_size >= max_size(), std::length_error{"size() >= max_size()"}); - Traits::assign(data()[curr_size], ch); - this->set_size(curr_size + 1); - term(); + const auto curr_size = size(); + BOOST_STATIC_STRING_THROW_IF( + curr_size >= max_size(), std::length_error{"size() >= max_size()"}); + Traits::assign(data()[curr_size], ch); + this->set_size(curr_size + 1); + term(); } template @@ -533,13 +508,13 @@ append( size_type count) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - const auto curr_size = size(); - BOOST_STATIC_STRING_THROW_IF( - count > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); - Traits::copy(&data()[curr_size], s, count); - this->set_size(curr_size + count); - term(); - return *this; + const auto curr_size = size(); + BOOST_STATIC_STRING_THROW_IF( + count > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); + Traits::copy(&data()[curr_size], s, count); + this->set_size(curr_size + count); + term(); + return *this; } template @@ -549,9 +524,9 @@ basic_static_string:: substr(size_type pos, size_type count) const BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string { - BOOST_STATIC_STRING_THROW_IF( - pos > size(), std::out_of_range{"pos > size()"}); - return {&data()[pos], (std::min)(count, size() - pos)}; + BOOST_STATIC_STRING_THROW_IF( + pos > size(), std::out_of_range{"pos > size()"}); + return {&data()[pos], (std::min)(count, size() - pos)}; } template @@ -561,9 +536,9 @@ basic_static_string:: subview(size_type pos, size_type count) const BOOST_STATIC_STRING_COND_NOEXCEPT -> string_view_type { - BOOST_STATIC_STRING_THROW_IF( - pos > size(), std::out_of_range{"pos > size()"}); - return {&data()[pos], (std::min)(count, size() - pos)}; + BOOST_STATIC_STRING_THROW_IF( + pos > size(), std::out_of_range{"pos > size()"}); + return {&data()[pos], (std::min)(count, size() - pos)}; } template @@ -573,9 +548,9 @@ basic_static_string:: copy(CharT* dest, size_type count, size_type pos) const noexcept -> size_type { - auto const s = subview(pos, count); - Traits::copy(dest, s.data(), s.size()); - return s.size(); + auto const s = subview(pos, count); + Traits::copy(dest, s.data(), s.size()); + return s.size(); } template @@ -584,13 +559,13 @@ void basic_static_string:: resize(std::size_t n) BOOST_STATIC_STRING_COND_NOEXCEPT { - const auto curr_size = size(); - BOOST_STATIC_STRING_THROW_IF( - n > max_size(), std::length_error{"n > max_size()"}); - if(n > curr_size) - Traits::assign(&data()[curr_size], n - curr_size, CharT{}); - this->set_size(n); - term(); + const auto curr_size = size(); + BOOST_STATIC_STRING_THROW_IF( + n > max_size(), std::length_error{"n > max_size()"}); + if(n > curr_size) + Traits::assign(&data()[curr_size], n - curr_size, CharT{}); + this->set_size(n); + term(); } template @@ -599,13 +574,13 @@ void basic_static_string:: resize(std::size_t n, CharT c) BOOST_STATIC_STRING_COND_NOEXCEPT { - const auto curr_size = size(); - BOOST_STATIC_STRING_THROW_IF( - n > max_size(), std::length_error{"n > max_size()"}); - if(n > curr_size) - Traits::assign(&data()[curr_size], n - curr_size, c); - this->set_size(n); - term(); + const auto curr_size = size(); + BOOST_STATIC_STRING_THROW_IF( + n > max_size(), std::length_error{"n > max_size()"}); + if(n > curr_size) + Traits::assign(&data()[curr_size], n - curr_size, c); + this->set_size(n); + term(); } template @@ -614,12 +589,12 @@ void basic_static_string:: swap(basic_static_string& s) noexcept { - const auto curr_size = size(); - basic_static_string tmp(s); - s.set_size(curr_size); - Traits::copy(&s.data()[0], data(), curr_size + 1); - this->set_size(tmp.size()); - Traits::copy(data(), tmp.data(), size() + 1); + const auto curr_size = size(); + basic_static_string tmp(s); + s.set_size(curr_size); + Traits::copy(&s.data()[0], data(), curr_size + 1); + this->set_size(tmp.size()); + Traits::copy(data(), tmp.data(), size() + 1); } template @@ -629,16 +604,16 @@ void basic_static_string:: swap(basic_static_string& s) BOOST_STATIC_STRING_COND_NOEXCEPT { - const auto curr_size = size(); - BOOST_STATIC_STRING_THROW_IF( - curr_size > s.max_size(), std::length_error{"size() > s.max_size()"}); - BOOST_STATIC_STRING_THROW_IF( - s.size() > max_size(), std::length_error{"s.size() > max_size()"}); - basic_static_string tmp(s); - s.set_size(curr_size); - Traits::copy(&s.data()[0], data(), curr_size + 1); - this->set_size(tmp.size()); - Traits::copy(data(), &tmp.data()[0], size() + 1); + const auto curr_size = size(); + BOOST_STATIC_STRING_THROW_IF( + curr_size > s.max_size(), std::length_error{"size() > s.max_size()"}); + BOOST_STATIC_STRING_THROW_IF( + s.size() > max_size(), std::length_error{"s.size() > max_size()"}); + basic_static_string tmp(s); + s.set_size(curr_size); + Traits::copy(&s.data()[0], data(), curr_size + 1); + this->set_size(tmp.size()); + Traits::copy(data(), &tmp.data()[0], size() + 1); } template @@ -649,52 +624,16 @@ replace( size_type pos, size_type n1, const CharT* s, - size_type n2) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& + size_type n2) BOOST_STATIC_STRING_COND_NOEXCEPT -> + basic_static_string& { - const auto curr_size = size(); - const auto curr_data = data(); - BOOST_STATIC_STRING_THROW_IF( - pos > curr_size, std::out_of_range{"pos > size()"}); - BOOST_STATIC_STRING_THROW_IF( - curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, - std::length_error{"replaced string exceeds max_size()"}); - if (pos + n1 >= curr_size) - n1 = curr_size - pos; - const bool inside = s <= &curr_data[curr_size] && s >= curr_data; - if (inside && size_type(s - curr_data) == pos && n1 == n2) - return *this; - if (!inside || (inside && ((s - curr_data) + n2 <= pos))) - { - // source outside - Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); - Traits::copy(&curr_data[pos], s, n2); - } - else - { - // source inside - const size_type offset = s - curr_data; - if (n2 >= n1) - { - // grow/unchanged - // shift all right of splice point by n2 - n1 to the right - 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; - // copy all before splice point - Traits::move(&curr_data[pos], &curr_data[offset], diff); - // copy all after splice point - Traits::move(&curr_data[pos + diff], &curr_data[offset + (n2 - n1) + diff], n2 - diff); - } - else - { - // shrink - // copy all elements into place - Traits::move(&curr_data[pos], &curr_data[offset], n2); - // shift all elements after splice point left - Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); - } - } - this->set_size(curr_size + (n2 - n1)); - return *this; + const auto curr_size = size(); + const auto curr_data = data(); + BOOST_STATIC_STRING_THROW_IF( + pos > curr_size, std::out_of_range{"pos > size()"}); + if (pos + n1 >= curr_size) + n1 = curr_size - pos; + return replace(curr_data + pos, curr_data + pos + n1, s, s + n2); } template @@ -707,19 +646,19 @@ replace( size_type n2, CharT c) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string & { - const auto curr_size = size(); - const auto curr_data = data(); - BOOST_STATIC_STRING_THROW_IF( - pos > curr_size, std::out_of_range{"pos > size()"}); - BOOST_STATIC_STRING_THROW_IF( - curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, - std::length_error{"replaced string exceeds max_size()"}); - if (pos + n1 >= curr_size) - n1 = curr_size - pos; - Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); - Traits::assign(&curr_data[pos], n2, c); - this->set_size(curr_size + (n2 - n1)); - return *this; + const auto curr_size = size(); + const auto curr_data = data(); + BOOST_STATIC_STRING_THROW_IF( + pos > curr_size, std::out_of_range{"pos > size()"}); + BOOST_STATIC_STRING_THROW_IF( + curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, + std::length_error{"replaced string exceeds max_size()"}); + if (pos + n1 >= curr_size) + n1 = curr_size - pos; + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + Traits::assign(&curr_data[pos], n2, c); + this->set_size(curr_size + (n2 - n1)); + return *this; } template @@ -736,54 +675,52 @@ replace( detail::is_forward_iterator::value, basic_static_string&>::type { - const auto curr_size = size(); - const auto curr_data = data(); - std::size_t n1 = detail::distance(i1, i2); - const std::size_t n2 = detail::distance(j1, j2); - const std::size_t pos = i1 - curr_data; - const auto s = &*j1; - BOOST_STATIC_STRING_THROW_IF( - pos > curr_size, std::out_of_range{"pos > size()"}); - BOOST_STATIC_STRING_THROW_IF( - curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, - std::length_error{"replaced string exceeds max_size()"}); - if (pos + n1 >= curr_size) - n1 = curr_size - pos; - const bool inside = s <= &curr_data[curr_size] && s >= curr_data; - if (inside && size_type(s - curr_data) == pos && n1 == n2) - return *this; - if (!inside || (inside && ((s - curr_data) + n2 <= pos))) + const auto curr_size = size(); + const auto curr_data = data(); + std::size_t n1 = detail::distance(i1, i2); + const std::size_t n2 = detail::distance(j1, j2); + const std::size_t pos = i1 - curr_data; + const auto s = &*j1; + BOOST_STATIC_STRING_THROW_IF( + curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, + std::length_error{"replaced string exceeds max_size()"}); + if (pos + n1 >= curr_size) + n1 = curr_size - pos; + const bool inside = s <= &curr_data[curr_size] && s >= curr_data; + if (inside && size_type(s - curr_data) == pos && n1 == n2) + return *this; + if (!inside || (inside && ((s - curr_data) + n2 <= pos))) + { + // source outside + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + detail::copy_with_traits(j1, j2, &curr_data[pos]); + } + else + { + // source inside + const size_type offset = s - curr_data; + if (n2 >= n1) { - // source outside + // grow/unchanged + // shift all right of splice point by n2 - n1 to the right Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); - detail::copy_with_traits(j1, j2, &curr_data[pos]); + const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; + // copy all before splice point + Traits::move(&curr_data[pos], &curr_data[offset], diff); + // copy all after splice point + Traits::move(&curr_data[pos + diff], &curr_data[offset + (n2 - n1) + diff], n2 - diff); } else { - // source inside - const size_type offset = s - curr_data; - if (n2 >= n1) - { - // grow/unchanged - // shift all right of splice point by n2 - n1 to the right - 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; - // copy all before splice point - Traits::move(&curr_data[pos], &curr_data[offset], diff); - // copy all after splice point - Traits::move(&curr_data[pos + diff], &curr_data[offset + (n2 - n1) + diff], n2 - diff); - } - else - { - // shrink - // copy all elements into place - Traits::move(&curr_data[pos], &curr_data[offset], n2); - // shift all elements after splice point left - Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); - } + // shrink + // copy all elements into place + Traits::move(&curr_data[pos], &curr_data[offset], n2); + // shift all elements after splice point left + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); } - this->set_size(curr_size + (n2 - n1)); - return *this; + } + this->set_size(curr_size + (n2 - n1)); + return *this; } template @@ -802,52 +739,25 @@ replace( ! detail::is_forward_iterator< InputIterator>::value, basic_static_string&>::type -{ - const auto curr_size = size(); - const auto curr_data = data(); - std::size_t n1 = detail::distance(i1, i2); - const std::size_t n2 = read_back(j1, j2); - const std::size_t pos = i1 - curr_data; - BOOST_STATIC_STRING_THROW_IF( - pos > curr_size, std::out_of_range{"pos > size()"}); - BOOST_STATIC_STRING_THROW_IF( - curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, - std::length_error{"replaced string exceeds max_size()"}); - // Rotate to the correct order. [i2, end] will now start with the replaced string, continue to the existing string not being replaced, and end with a null terminator - std::rotate(&curr_data[pos], &curr_data[curr_size + 1], &curr_data[curr_size + n2 + 1]); - // Cap the size - if (pos + n1 >= curr_size) - n1 = curr_size - pos; - // Move everything from the end of the splice point to the end of the rotated string to the begining of the splice point - Traits::move(&curr_data[pos + n2], &curr_data[pos + n2 + n1], (curr_size + (n2 - n1)) - pos); - this->set_size(curr_size + (n2 - n1)); - return *this; -} - -template -BOOST_STATIC_STRING_CPP14_CONSTEXPR -auto -basic_static_string:: -replace( - const_iterator i1, - const_iterator i2, - std::initializer_list il) BOOST_STATIC_STRING_COND_NOEXCEPT -> - basic_static_string& { const auto curr_size = size(); const auto curr_data = data(); std::size_t n1 = detail::distance(i1, i2); + const std::size_t n2 = read_back(j1, j2); const std::size_t pos = i1 - curr_data; BOOST_STATIC_STRING_THROW_IF( pos > curr_size, std::out_of_range{"pos > size()"}); BOOST_STATIC_STRING_THROW_IF( - curr_size - (std::min)(n1, curr_size - pos) >= max_size() - il.size(), + curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, std::length_error{"replaced string exceeds max_size()"}); + // Rotate to the correct order. [i2, end] will now start with the replaced string, continue to the existing string not being replaced, and end with a null terminator + std::rotate(&curr_data[pos], &curr_data[curr_size + 1], &curr_data[curr_size + n2 + 1]); + // Cap the size if (pos + n1 >= curr_size) n1 = curr_size - pos; - Traits::move(&curr_data[pos + il.size()], &curr_data[pos + n1], curr_size - pos - n1 + 1); - detail::copy_with_traits(il.begin(), il.end(), &curr_data[pos]); - this->set_size(curr_size + (il.size() - n1)); + // Move everything from the end of the splice point to the end of the rotated string to the begining of the splice point + Traits::move(&curr_data[pos + n2], &curr_data[pos + n2 + n1], (curr_size + (n2 - n1)) - pos); + this->set_size(curr_size + (n2 - n1)); return *this; } @@ -861,13 +771,13 @@ find( size_type n) const noexcept -> size_type { - const auto curr_size = size(); - if (pos > curr_size || n > curr_size - pos) - return npos; - if (!n) - return pos; - const auto res = std::search(&data()[pos], &data()[curr_size], s, &s[n], Traits::eq); - return res == end() ? npos : detail::distance(data(), res); + const auto curr_size = size(); + if (pos > curr_size || n > curr_size - pos) + return npos; + if (!n) + return pos; + const auto res = std::search(&data()[pos], &data()[curr_size], s, &s[n], Traits::eq); + return res == end() ? npos : detail::distance(data(), res); } template @@ -880,18 +790,18 @@ rfind( size_type n) const noexcept -> size_type { - const auto curr_size = size(); - const auto curr_data = data(); - if (curr_size < n) - return npos; - if (pos > curr_size - n) - pos = curr_size - n; - if (!n) - return pos; - for (auto sub = &curr_data[pos]; sub >= curr_data; --sub) - if (!Traits::compare(sub, s, n)) - return detail::distance(curr_data, sub); + const auto curr_size = size(); + const auto curr_data = data(); + if (curr_size < n) return npos; + if (pos > curr_size - n) + pos = curr_size - n; + if (!n) + return pos; + for (auto sub = &curr_data[pos]; sub >= curr_data; --sub) + if (!Traits::compare(sub, s, n)) + return detail::distance(curr_data, sub); + return npos; } template @@ -904,11 +814,11 @@ find_first_of( size_type n) const noexcept -> size_type { - const auto curr_data = data(); - if (pos >= size() || !n) - return npos; - const auto res = std::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], Traits::eq); - return res == end() ? npos : detail::distance(curr_data, res); + const auto curr_data = data(); + if (pos >= size() || !n) + return npos; + const auto res = std::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], Traits::eq); + return res == end() ? npos : detail::distance(curr_data, res); } template @@ -921,15 +831,15 @@ find_last_of( size_type n) const noexcept -> size_type { - const auto curr_size = size(); - if (!n) - return npos; - if (pos >= curr_size) - pos = 0; - else - pos = curr_size - (pos + 1); - const auto res = std::find_first_of(rbegin() + pos, rend(), s, &s[n], Traits::eq); - return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res); + const auto curr_size = size(); + if (!n) + return npos; + if (pos >= curr_size) + pos = 0; + else + pos = curr_size - (pos + 1); + const auto res = std::find_first_of(rbegin() + pos, rend(), s, &s[n], Traits::eq); + return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res); } template @@ -942,12 +852,12 @@ find_first_not_of( size_type n) const noexcept -> size_type { - if (pos >= size()) - return npos; - if (!n) - return pos; - const auto res = detail::find_not_of(&data()[pos], &data()[size()], s, n); - return res == end() ? npos : detail::distance(data(), res); + if (pos >= size()) + return npos; + if (!n) + return pos; + const auto res = detail::find_not_of(&data()[pos], &data()[size()], s, n); + return res == end() ? npos : detail::distance(data(), res); } template @@ -960,14 +870,14 @@ find_last_not_of( size_type n) const noexcept -> size_type { - const auto curr_size = size(); - if (pos >= curr_size) - pos = curr_size - 1; - if (!n) - return pos; - pos = curr_size - (pos + 1); - const auto res = detail::find_not_of(rbegin() + pos, rend(), s, n); - return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res); + const auto curr_size = size(); + if (pos >= curr_size) + pos = curr_size - 1; + if (!n) + return pos; + pos = curr_size - (pos + 1); + const auto res = detail::find_not_of(rbegin() + pos, rend(), s, n); + return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res); } template @@ -977,10 +887,10 @@ basic_static_string:: assign_char(CharT ch, std::true_type) noexcept -> basic_static_string& { - this->set_size(1); - Traits::assign(data()[0], ch); - term(); - return *this; + this->set_size(1); + Traits::assign(data()[0], ch); + term(); + return *this; } template @@ -989,8 +899,8 @@ basic_static_string:: assign_char(CharT, std::false_type) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string& { - BOOST_STATIC_STRING_THROW(std::length_error{"max_size() == 0"}); - return *this; + BOOST_STATIC_STRING_THROW(std::length_error{"max_size() == 0"}); + return *this; } template @@ -1014,6 +924,32 @@ read_back( return new_size - size(); } +template +BOOST_STATIC_STRING_CPP14_CONSTEXPR +auto +basic_static_string:: +replace_unchecked( + size_type pos, + size_type n1, + const CharT* s, + size_type n2) BOOST_STATIC_STRING_COND_NOEXCEPT -> + basic_static_string& +{ + const auto curr_data = data(); + const auto curr_size = size(); + BOOST_STATIC_STRING_THROW_IF( + pos > curr_size, std::out_of_range{"pos > size()"}); + BOOST_STATIC_STRING_THROW_IF( + curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, + std::length_error{"replaced string exceeds max_size()"}); + if (pos + n1 >= curr_size) + n1 = curr_size - pos; + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + Traits::copy(&curr_data[pos], s, n2); + this->set_size(curr_size + (n2 - n1)); + return *this; +} + // string static_string::digits10 + 1> diff --git a/include/boost/static_string/static_string.hpp b/include/boost/static_string/static_string.hpp index 704569a..4a74e13 100644 --- a/include/boost/static_string/static_string.hpp +++ b/include/boost/static_string/static_string.hpp @@ -1625,7 +1625,7 @@ public: size_type n1, const basic_static_string& str) BOOST_STATIC_STRING_COND_NOEXCEPT { - return replace(pos1, n1, str.data(), str.size()); + return replace_unchecked(pos1, n1, str.data(), str.size()); } /** Replace a subset of the string. @@ -1929,11 +1929,14 @@ public: @return `*this` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR - basic_static_string& - replace( + basic_static_string& + replace( const_iterator i1, const_iterator i2, - std::initializer_list il) BOOST_STATIC_STRING_COND_NOEXCEPT; + std::initializer_list il) BOOST_STATIC_STRING_COND_NOEXCEPT + { + return replace_unchecked(i1 - begin(), i2 - i1, il.begin(), il.size()); + } //-------------------------------------------------------------------------- // @@ -2489,7 +2492,15 @@ private: std::size_t read_back( InputIterator first, - InputIterator last); + InputIterator last) BOOST_STATIC_STRING_COND_NOEXCEPT; + + BOOST_STATIC_STRING_CPP14_CONSTEXPR + basic_static_string& + replace_unchecked( + size_type pos, + size_type n1, + const CharT* s, + size_type n2) BOOST_STATIC_STRING_COND_NOEXCEPT; }; //------------------------------------------------------------------------------