Fix and refactor buffers_cat:

Elements of zero size are correctly skipped during iteration.

* Tidy up tests
* Increase code coverage
* Remove move special members
* Correct behavior for default constructed iterators
This commit is contained in:
Vinnie Falco committed 2018-12-19 20:59:20 -08:00
1 parent ca728e4022
commit 719fe66b77
4 files changed
+350 -380

No files matched your search

-6
View File
@@ -46,15 +46,9 @@ public:
/// Copy Constructor
buffers_cat_view(buffers_cat_view const&) = default;
/// Move Constructor
buffers_cat_view(buffers_cat_view&&) = default;
/// Copy Assignment
buffers_cat_view& operator=(buffers_cat_view const&) = default;
/// Move Assignment
buffers_cat_view& operator=(buffers_cat_view&&) = default;
/** Constructor
@param buffers The list of buffer sequences to concatenate.
+133 -117
View File
@@ -35,6 +35,7 @@ struct buffers_cat_view_iterator_base
net::mutable_buffer
operator*() const
{
// Dereferencing a one-past-the-end iterator
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
@@ -77,9 +78,7 @@ public:
std::bidirectional_iterator_tag;
const_iterator() = default;
const_iterator(const_iterator&& other) = default;
const_iterator(const_iterator const& other) = default;
const_iterator& operator=(const_iterator&& other) = default;
const_iterator& operator=(const_iterator const& other) = default;
bool
@@ -103,11 +102,9 @@ public:
const_iterator
operator++(int);
// deprecated
const_iterator&
operator--();
// deprecated
const_iterator
operator--(int);
@@ -115,53 +112,6 @@ private:
const_iterator(
detail::tuple<Bn...> const& bn, bool at_end);
template<std::size_t I>
void
next(C<I> const&)
{
if(net::buffer_size(
detail::get<I>(*bn_)) != 0)
{
it_.template emplace<I+1>(
net::buffer_sequence_begin(
detail::get<I>(*bn_)));
return;
}
next(C<I+1>{});
}
void
next(C<sizeof...(Bn)> const&)
{
// end
auto constexpr I = sizeof...(Bn);
it_.template emplace<I+1>();
}
template<std::size_t I>
void
prev(C<I> const&)
{
if(net::buffer_size(
detail::get<I>(*bn_)) != 0)
{
it_.template emplace<I+1>(
net::buffer_sequence_end(
detail::get<I>(*bn_)));
return;
}
prev(C<I-1>{});
}
void
prev(C<0> const&)
{
auto constexpr I = 0;
it_.template emplace<I+1>(
net::buffer_sequence_end(
detail::get<I>(*bn_)));
}
struct dereference
{
const_iterator const& self;
@@ -190,15 +140,107 @@ private:
void
operator()(mp11::mp_size_t<0>)
{
// Incrementing a default-constructed iterator
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
template<std::size_t I>
void
operator()(mp11::mp_size_t<I>)
{
++self.it_.template get<I>();
next(mp11::mp_size_t<I>{});
}
template<std::size_t I>
void
next(mp11::mp_size_t<I>)
{
auto& it = self.it_.template get<I>();
for(;;)
{
if (it == net::buffer_sequence_end(
detail::get<I-1>(*self.bn_)))
break;
if(net::const_buffer(*it).size() > 0)
return;
++it;
}
self.it_.template emplace<I+1>(
net::buffer_sequence_begin(
detail::get<I>(*self.bn_)));
next(mp11::mp_size_t<I+1>{});
}
void
operator()(mp11::mp_size_t<sizeof...(Bn)>)
{
auto constexpr I = sizeof...(Bn);
++self.it_.template get<I>();
next(mp11::mp_size_t<I>{});
}
void
next(mp11::mp_size_t<sizeof...(Bn)>)
{
auto constexpr I = sizeof...(Bn);
auto& it = self.it_.template get<I>();
for(;;)
{
if (it == net::buffer_sequence_end(
detail::get<I-1>(*self.bn_)))
break;
if(net::const_buffer(*it).size() > 0)
return;
++it;
}
// end
self.it_.template emplace<I+1>();
}
[[noreturn]]
void
operator()(mp11::mp_size_t<sizeof...(Bn) + 1>)
operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
{
(*this)(mp11::mp_size_t<0>{});
// Incrementing a one-past-the-end iterator
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
};
struct decrement
{
const_iterator& self;
[[noreturn]]
void
operator()(mp11::mp_size_t<0>)
{
// Decrementing a default-constructed iterator
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
void
operator()(mp11::mp_size_t<1>)
{
auto constexpr I = 1;
auto& it = self.it_.template get<I>();
for(;;)
{
if(it == net::buffer_sequence_begin(
detail::get<I-1>(*self.bn_)))
{
// Decrementing an iterator to the beginning
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
--it;
if(net::const_buffer(*it).size() > 0)
return;
}
}
template<std::size_t I>
@@ -206,53 +248,31 @@ private:
operator()(mp11::mp_size_t<I>)
{
auto& it = self.it_.template get<I>();
if (++it == net::buffer_sequence_end(
detail::get<I - 1>(*self.bn_)))
self.next(C<I>());
for(;;)
{
if(it == net::buffer_sequence_begin(
detail::get<I-1>(*self.bn_)))
break;
--it;
if(net::const_buffer(*it).size() > 0)
return;
}
self.it_.template emplace<I-1>(
net::buffer_sequence_end(
detail::get<I-2>(*self.bn_)));
(*this)(mp11::mp_size_t<I-1>{});
}
void
operator()(mp11::mp_size_t<sizeof...(Bn)+1>)
{
auto constexpr I = sizeof...(Bn)+1;
self.it_.template emplace<I-1>(
net::buffer_sequence_end(
detail::get<I-2>(*self.bn_)));
(*this)(mp11::mp_size_t<I-1>{});
}
};
void
decrement(C<sizeof...(Bn)> const&)
{
auto constexpr I = sizeof...(Bn);
if(it_.index() == I+1)
prev(C<I-1>{});
decrement(C<I-1>{});
}
template<std::size_t I>
void
decrement(C<I> const&)
{
if(it_.index() == I+1)
{
if(it_.template get<I+1>() !=
net::buffer_sequence_begin(
detail::get<I>(*bn_)))
{
--it_.template get<I+1>();
return;
}
prev(C<I-1>{});
}
decrement(C<I-1>{});
}
void
decrement(C<0> const&)
{
auto constexpr I = 0;
if(it_.template get<I+1>() !=
net::buffer_sequence_begin(
detail::get<I>(*bn_)))
{
--it_.template get<I+1>();
return;
}
BOOST_THROW_EXCEPTION(std::logic_error{
"invalid iterator"});
}
};
//------------------------------------------------------------------------------
@@ -265,9 +285,17 @@ const_iterator(
: bn_(&bn)
{
if(! at_end)
next(C<0>{});
{
it_.template emplace<1>(
net::buffer_sequence_begin(
detail::get<0>(*bn_)));
increment{*this}.next(
mp11::mp_size_t<1>{});
}
else
next(C<sizeof...(Bn)>{});
{
it_.template emplace<sizeof...(Bn)+1>();
}
}
template<class... Bn>
@@ -276,20 +304,7 @@ buffers_cat_view<Bn...>::
const_iterator::
operator==(const_iterator const& other) const
{
return
(bn_ == nullptr) ?
(
other.bn_ == nullptr ||
other.it_.index() == sizeof...(Bn) + 1
):(
(other.bn_ == nullptr) ?
(
it_.index() == sizeof...(Bn) + 1
): (
bn_ == other.bn_ &&
it_ == other.it_
)
);
return bn_ == other.bn_ && it_ == other.it_;
}
template<class... Bn>
@@ -338,7 +353,10 @@ const_iterator::
operator--() ->
const_iterator&
{
decrement(C<sizeof...(Bn)>{});
mp11::mp_with_index<
sizeof...(Bn) + 2>(
it_.index(),
decrement{*this});
return *this;
}
@@ -365,7 +383,6 @@ buffers_cat_view(Bn const&... bn)
template<class... Bn>
inline
auto
buffers_cat_view<Bn...>::begin() const ->
const_iterator
@@ -374,7 +391,6 @@ buffers_cat_view<Bn...>::begin() const ->
}
template<class... Bn>
inline
auto
buffers_cat_view<Bn...>::end() const->
const_iterator