Fixed exception checks for ranges, less repetition

This commit is contained in:
Krystian Stasiowski
2020-01-01 15:01:39 -05:00
parent cd32cadc08
commit 3a4f2e9d83
2 changed files with 348 additions and 401 deletions

View File

@ -317,30 +317,7 @@ insert(
const auto curr_data = data(); const auto curr_data = data();
BOOST_STATIC_STRING_THROW_IF( BOOST_STATIC_STRING_THROW_IF(
index > curr_size, std::out_of_range{"index > size()"}); index > curr_size, std::out_of_range{"index > size()"});
BOOST_STATIC_STRING_THROW_IF( insert(curr_data + index, s, s + count);
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; return *this;
} }
@ -384,8 +361,6 @@ insert(
const auto count = detail::distance(first, last); const auto count = detail::distance(first, last);
const auto index = pos - curr_data; const auto index = pos - curr_data;
const auto s = &*first; const auto s = &*first;
BOOST_STATIC_STRING_THROW_IF(
index > curr_size, std::out_of_range{"index > size()"});
BOOST_STATIC_STRING_THROW_IF( BOOST_STATIC_STRING_THROW_IF(
count > max_size() - curr_size, std::length_error{"count > max_size() - size()"}); count > max_size() - curr_size, std::length_error{"count > max_size() - size()"});
const bool inside = s <= &curr_data[curr_size] && s >= curr_data; const bool inside = s <= &curr_data[curr_size] && s >= curr_data;
@ -410,7 +385,7 @@ insert(
} }
} }
this->set_size(curr_size + count); this->set_size(curr_size + count);
return begin() + index; return curr_data + index;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
@ -649,52 +624,16 @@ replace(
size_type pos, size_type pos,
size_type n1, size_type n1,
const CharT* s, const CharT* s,
size_type n2) BOOST_STATIC_STRING_COND_NOEXCEPT -> basic_static_string<N, CharT, Traits>& size_type n2) BOOST_STATIC_STRING_COND_NOEXCEPT ->
basic_static_string<N, CharT, Traits>&
{ {
const auto curr_size = size(); const auto curr_size = size();
const auto curr_data = data(); const auto curr_data = data();
BOOST_STATIC_STRING_THROW_IF( BOOST_STATIC_STRING_THROW_IF(
pos > curr_size, std::out_of_range{"pos > size()"}); 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) if (pos + n1 >= curr_size)
n1 = curr_size - pos; n1 = curr_size - pos;
const bool inside = s <= &curr_data[curr_size] && s >= curr_data; return replace(curr_data + pos, curr_data + pos + n1, s, s + n2);
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;
} }
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
@ -742,8 +681,6 @@ replace(
const std::size_t n2 = detail::distance(j1, j2); const std::size_t n2 = detail::distance(j1, j2);
const std::size_t pos = i1 - curr_data; const std::size_t pos = i1 - curr_data;
const auto s = &*j1; const auto s = &*j1;
BOOST_STATIC_STRING_THROW_IF(
pos > curr_size, std::out_of_range{"pos > size()"});
BOOST_STATIC_STRING_THROW_IF( BOOST_STATIC_STRING_THROW_IF(
curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2, curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2,
std::length_error{"replaced string exceeds max_size()"}); std::length_error{"replaced string exceeds max_size()"});
@ -824,33 +761,6 @@ replace(
return *this; return *this;
} }
template<std::size_t N, typename CharT, typename Traits>
BOOST_STATIC_STRING_CPP14_CONSTEXPR
auto
basic_static_string<N, CharT, Traits>::
replace(
const_iterator i1,
const_iterator i2,
std::initializer_list<CharT> 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 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(),
std::length_error{"replaced string exceeds max_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<Traits>(il.begin(), il.end(), &curr_data[pos]);
this->set_size(curr_size + (il.size() - n1));
return *this;
}
template<std::size_t N, typename CharT, typename Traits> template<std::size_t N, typename CharT, typename Traits>
BOOST_STATIC_STRING_CPP14_CONSTEXPR BOOST_STATIC_STRING_CPP14_CONSTEXPR
auto auto
@ -1014,6 +924,32 @@ read_back(
return new_size - size(); return new_size - size();
} }
template<std::size_t N, typename CharT, typename Traits>
BOOST_STATIC_STRING_CPP14_CONSTEXPR
auto
basic_static_string<N, CharT, Traits>::
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 // string
static_string<std::numeric_limits<int>::digits10 + 1> static_string<std::numeric_limits<int>::digits10 + 1>

View File

@ -1625,7 +1625,7 @@ public:
size_type n1, size_type n1,
const basic_static_string<M, CharT, Traits>& str) BOOST_STATIC_STRING_COND_NOEXCEPT const basic_static_string<M, CharT, Traits>& 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. /** Replace a subset of the string.
@ -1933,7 +1933,10 @@ public:
replace( replace(
const_iterator i1, const_iterator i1,
const_iterator i2, const_iterator i2,
std::initializer_list<CharT> il) BOOST_STATIC_STRING_COND_NOEXCEPT; std::initializer_list<CharT> 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 std::size_t
read_back( read_back(
InputIterator first, 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;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------