Skip to content
Open

Any #45

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/boost/buffers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#ifndef BOOST_BUFFERS_HPP
#define BOOST_BUFFERS_HPP

#include <boost/buffers/any.hpp>
#include <boost/buffers/buffer.hpp>
#include <boost/buffers/buffer_pair.hpp>
#include <boost/buffers/circular_buffer.hpp>
Expand Down
291 changes: 291 additions & 0 deletions include/boost/buffers/any.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
//
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
//
// 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/cppalliance/buffers
//

#ifndef BOOST_BUFFERS_ANY_HPP
#define BOOST_BUFFERS_ANY_HPP

#include <boost/buffers/detail/config.hpp>
#include <boost/buffers/buffer.hpp>
#include <boost/assert.hpp>
#include <iterator>
#include <new>
#include <type_traits>

namespace boost {
namespace buffers {

//------------------------------------------------

template<bool IsConst>
class any
{
public:
class iterator;

virtual ~any() = default;
virtual iterator begin() const noexcept = 0;
virtual iterator end() const noexcept = 0;
};

using any_const_buffers = any<true>;
using any_mutable_buffers = any<false>;

//------------------------------------------------

template<bool IsConst>
class any_ref
{
any<IsConst> const& bs_;

public:
using iterator = typename any<IsConst>::iterator;

any_ref(any<IsConst> const& bs) noexcept
: bs_(bs)
{
}

iterator begin() const noexcept
{
return bs_.begin();
}

iterator end() const noexcept
{
return bs_.end();
}
};

using any_const_ref = any_ref<true>;
using any_mutable_ref = any_ref<false>;

//------------------------------------------------

template<
class BufferRange,
bool IsConst = is_const_buffer_sequence<BufferRange>::value>
class any_impl : public any<IsConst>
{
BufferRange b_;

public:
using iterator = typename any<IsConst>::iterator;

explicit
any_impl(
BufferRange const& b)
: b_(b)
{
}

iterator begin() const noexcept override
{
return iterator(buffers::begin(b_));
}

iterator end() const noexcept override
{
return iterator(buffers::end(b_));
}
};

//------------------------------------------------

template<bool IsConst>
class any<IsConst>::iterator
{
public:
static constexpr std::size_t Bytes = 64;
using value_type = typename std::conditional<
IsConst, const_buffer, mutable_buffer>::type;
using reference = value_type;
using pointer = void;
using difference_type = std::ptrdiff_t;
using iterator_category =
std::bidirectional_iterator_tag;
#if defined(__cpp_concepts) || defined(__cpp_lib_concepts)
using iterator_concept = std::bidirectional_iterator_tag; // (since C++20)
#endif

~iterator()
{
get().destroy();
}

iterator() noexcept
{
::new(buf_) base;
}

iterator(
iterator const& other) noexcept
{
other.get().copy(buf_);
}

iterator&
operator=(iterator const& other) noexcept
{
other.get().assign(buf_);
return *this;
}

template<class It>
iterator(It const& it) noexcept
{
::new(buf_) impl<It>(it);
}

bool
operator==(iterator const& other) const noexcept
{
return get().equal(other.buf_);
}

bool
operator!=(
iterator const& other) const noexcept
{
return !(get().equal(other.buf_));
}

reference
operator*() const noexcept
{
return get().deref();
}

iterator&
operator++() noexcept
{
get().increment();
return *this;
}

iterator
operator++(int) noexcept
{
auto temp = *this;
get().increment();
return temp;
}

iterator&
operator--() noexcept
{
get().decrement();
return *this;
}

iterator
operator--(int) noexcept
{
auto temp = *this;
get().decrement();
return temp;
}

private:
// this is also a default-constructed iterator
struct base
{
base() noexcept {}
virtual ~base() {}
virtual void destroy() const noexcept {}
virtual void copy(void*) const noexcept {}
virtual void assign(void*) const noexcept {}
virtual bool equal(void const*) const noexcept { return true; }
virtual reference deref() const noexcept { return {}; }
virtual void increment() noexcept {}
virtual void decrement() noexcept {}
};

template<class It>
struct impl;

base& get() noexcept
{
return *reinterpret_cast<base*>(buf_);
}

base const& get() const noexcept
{
return *reinterpret_cast<base const*>(buf_);
}

char buf_[Bytes];
};

//------------------------------------------------

template<bool IsConst>
template<class It>
struct any<IsConst>::iterator::impl : base
{
It it_{};

impl() noexcept
{
}

impl(It const& it) noexcept
: it_(it)
{
}

void destroy() const noexcept override
{
this->~impl();
}

void copy(void* p) const noexcept override
{
::new(p) impl(*this);
}

void assign(void* p) const noexcept override
{
reinterpret_cast<impl*>(p)->it_ = it_;
}

bool equal(void const* p) const noexcept override
{
return reinterpret_cast<impl const*>(p)->it_ == it_;
}

reference deref() const noexcept override
{
return *it_;
}

void increment() noexcept override
{
++it_;
}

void decrement() noexcept override
{
--it_;
}
};

//------------------------------------------------

template<class BufferRange>
auto make_any(
BufferRange const& b) ->
any_impl<BufferRange>
{
return any_impl<BufferRange>(b);
}

} // buffers
} // boost

#endif
10 changes: 5 additions & 5 deletions include/boost/buffers/buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,11 @@ struct is_buffer_sequence<

template<class T, class B>
struct is_buffer_sequence<T, B, detail::void_t<typename std::enable_if<
std::is_convertible<decltype(*begin(std::declval<T&>())), B>::value &&
std::is_convertible<decltype(*end(std::declval<T&>())), B>::value &&
detail::is_bidirectional_iterator<decltype(begin(std::declval<T&>()))>::value &&
detail::is_bidirectional_iterator<decltype(end(std::declval<T&>()))>::value &&
std::is_same<decltype(begin(std::declval<T&>())), decltype(end(std::declval<T&>()))>::value
std::is_convertible<decltype(*begin(std::declval<T const&>())), B>::value &&
std::is_convertible<decltype(*end(std::declval<T const&>())), B>::value &&
detail::is_bidirectional_iterator<decltype(begin(std::declval<T const&>()))>::value &&
detail::is_bidirectional_iterator<decltype(end(std::declval<T const&>()))>::value &&
std::is_same<decltype(begin(std::declval<T const&>())), decltype(end(std::declval<T const&>()))>::value
>::type > >
: std::true_type
{
Expand Down
2 changes: 1 addition & 1 deletion include/boost/buffers/detail/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct is_bidirectional_iterator<T, detail::void_t<
typename std::enable_if<

// std::input_iterator
std::is_same<decltype(*std::declval<T&>()), typename std::iterator_traits<T>::reference>::value &&
std::is_same<decltype(*std::declval<T const&>()), typename std::iterator_traits<T>::reference>::value &&

// std::forward_iterator
std::is_destructible<T>::value &&
Expand Down
5 changes: 3 additions & 2 deletions include/boost/buffers/slice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,9 @@ class slice_of
// VFALCO Need to fix this
//using iter_type = decltype(
//std::declval<BufferSequence&>().begin());
using iter_type = typename
BufferSequence::const_iterator;
//using iter_type = typename
//BufferSequence::const_iterator;
using iter_type = decltype(buffers::begin(std::declval<BufferSequence const&>()));

BufferSequence bs_;
iter_type begin_;
Expand Down
10 changes: 10 additions & 0 deletions src/any.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
//
// 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/cppalliance/buffers
//

#include <boost/buffers/any.hpp>
1 change: 1 addition & 0 deletions test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(PFILES
test_buffers.hpp
CMakeLists.txt
Jamfile
any.cpp
asio.cpp
buffer.cpp
buffer_pair.cpp
Expand Down
1 change: 1 addition & 0 deletions test/unit/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ project

local SOURCES =
test_buffers.hpp
any.cpp
asio.cpp
buffer.cpp
buffer_pair.cpp
Expand Down
Loading
Loading