Skip to content

Commit

Permalink
Added buffer_view class (#9)
Browse files Browse the repository at this point in the history
Added buffer_view class
  • Loading branch information
JohanMabille authored Mar 5, 2024
1 parent c2c5c93 commit fe95a4d
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 6 deletions.
62 changes: 62 additions & 0 deletions include/sparrow/buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,34 @@ namespace sparrow
template <class T>
bool operator==(const buffer<T>& lhs, const buffer<T>& rhs);

/*
* @class buffer_view
* @brief Object that references but does not own a piece of contiguous memory
*/
template <class T>
class buffer_view : private impl::buffer_data<T>
{
public:

using base_type = impl::buffer_data<T>;
using value_type = typename base_type::value_type;
using pointer = typename base_type::pointer;
using size_type = typename base_type::size_type;

explicit buffer_view(buffer<T>& buffer);
buffer_view(pointer data, size_type size);

using base_type::empty;
using base_type::size;
using base_type::data;

void swap(buffer_view&) noexcept;
bool equal(const buffer_view& rhs) const;
};

template <class T>
bool operator==(const buffer_view<T>& lhs, const buffer_view<T>& rhs);

/******************************
* buffer_data implementation *
******************************/
Expand Down Expand Up @@ -232,5 +260,39 @@ namespace sparrow
{
return lhs.equal(rhs);
}

/******************************
* buffer_view implementation *
******************************/

template <class T>
buffer_view<T>::buffer_view(buffer<T>& buffer)
: base_type{buffer.data(), buffer.size()}
{
}

template <class T>
buffer_view<T>::buffer_view(pointer data, size_type size)
: base_type{data, size}
{
}

template <class T>
void buffer_view<T>::swap(buffer_view& rhs) noexcept
{
base_type::swap(rhs);
}

template <class T>
bool buffer_view<T>::equal(const buffer_view& rhs) const
{
return base_type::equal(rhs);
}

template <class T>
bool operator==(const buffer_view<T>& lhs, const buffer_view<T>& rhs)
{
return lhs.equal(rhs);
}
}

153 changes: 147 additions & 6 deletions test/test_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
namespace sparrow
{
using buffer_test_type = buffer<uint8_t>;
using view_test_type = buffer_view<uint8_t>;

namespace
{
Expand Down Expand Up @@ -63,12 +64,12 @@ namespace sparrow

TEST_CASE("copy semantic")
{
const std::size_t size = 4;
const std::size_t size = 4u;
buffer_test_type b1(make_test_buffer(size), size);
buffer_test_type b2(b1);
CHECK_EQ(b1, b2);

const std::size_t size2 = 8;
const std::size_t size2 = 8u;
buffer_test_type b3(make_test_buffer(size2, 4), size2);
b2 = b3;
CHECK_EQ(b2, b3);
Expand All @@ -77,7 +78,7 @@ namespace sparrow

TEST_CASE("move semantic")
{
const std::size_t size = 4;
const std::size_t size = 4u;
buffer_test_type b1(make_test_buffer(size), size);
buffer_test_type control(b1);
buffer_test_type b2(std::move(b1));
Expand All @@ -86,17 +87,27 @@ namespace sparrow
CHECK(b1.empty());
CHECK_EQ(b1.data(), nullptr);

const std::size_t size2 = 8;
const std::size_t size2 = 8u;
buffer_test_type b4(make_test_buffer(size2, 4), size2);
buffer_test_type control2(b4);
b2 = std::move(b4);
CHECK_EQ(b2, control2);
CHECK_EQ(b4, control);
}

TEST_CASE("empty")
{
buffer_test_type b1;
CHECK(b1.empty());

const std::size_t size = 4u;
buffer_test_type b2(make_test_buffer(size), size);
CHECK(!b2.empty());
}

TEST_CASE("data")
{
const std::size_t size = 4;
const std::size_t size = 4u;
buffer_test_type b1(make_test_buffer(size), size);

const uint8_t expected_value = 101;
Expand All @@ -111,7 +122,7 @@ namespace sparrow

TEST_CASE("equality comparison")
{
const std::size_t size = 4;
const std::size_t size = 4u;
buffer_test_type b1(make_test_buffer(size), size);
buffer_test_type b2(make_test_buffer(size), size);
CHECK(b1 == b2);
Expand Down Expand Up @@ -147,4 +158,134 @@ namespace sparrow
CHECK_EQ(b.data()[2], 2);
}
}

TEST_SUITE("buffer_view")
{
TEST_CASE("constructors")
{
{
const std::size_t size = 8u;
uint8_t* mem = make_test_buffer(size);
[[maybe_unused]] view_test_type v(mem, size);
}

{

const std::size_t size = 8u;
buffer_test_type b(make_test_buffer(size), size);
[[maybe_unused]] view_test_type v(b);
}

{
const std::size_t size = 8u;
uint8_t* mem = make_test_buffer(size);
view_test_type v(mem, size);

CHECK_EQ(v.data(), mem);
CHECK_EQ(v.size(), size);
CHECK_EQ(v.data()[2], uint8_t(2));
}

{
const std::size_t size = 8u;
buffer_test_type b(make_test_buffer(size), size);
view_test_type v(b);

CHECK_EQ(v.data(), b.data());
CHECK_EQ(v.size(), b.size());
CHECK_EQ(v.data()[2], uint8_t(2));
}
}

TEST_CASE("copy semantic")
{
const std::size_t size = 4u;
buffer_test_type b(make_test_buffer(size), size);
view_test_type v1(b);
view_test_type v2(v1);
CHECK_EQ(v1, v2);

const std::size_t size2 = 8u;
buffer_test_type b2(make_test_buffer(size2, 4), size2);
view_test_type v3(b2);
v2 = v3;
CHECK_EQ(v2, v3);
CHECK_NE(v1, v3);
}

TEST_CASE("move semantic")
{
const std::size_t size = 4u;
buffer_test_type b(make_test_buffer(size), size);
view_test_type v1(b);
view_test_type v2(std::move(v1));
CHECK_EQ(v1, v2);

const std::size_t size2 = 8u;
buffer_test_type b2(make_test_buffer(size2, 4), size2);
view_test_type v3(b2);
v2 = std::move(v3);
CHECK_EQ(v2, v3);
}

TEST_CASE("empty")
{
view_test_type v1(nullptr, 0u);
CHECK(v1.empty());

const std::size_t size = 4u;
buffer_test_type b(make_test_buffer(size), size);
view_test_type v2(b);
CHECK(!v2.empty());
}

TEST_CASE("data")
{
const std::size_t size = 4u;
buffer_test_type b(make_test_buffer(size), size);
view_test_type v1(b);

const uint8_t expected_value = 101;
const std::size_t idx = 3u;
b.data()[idx] = expected_value;
CHECK_EQ(v1.data()[idx], expected_value);

view_test_type v2(v1);
CHECK_EQ(v2.data()[idx], expected_value);

view_test_type v3(std::move(v1));
CHECK_EQ(v3.data()[idx], expected_value);
}

TEST_CASE("equality comparison")
{
const std::size_t size = 4u;
buffer_test_type b1(make_test_buffer(size), size);
buffer_test_type b2(make_test_buffer(size), size);
view_test_type v1(b1), v2(b2);
CHECK(v1 == v2);

const std::size_t size2 = 8u;
buffer_test_type b3(make_test_buffer(size2), size2);
view_test_type v3(b3);
CHECK(v1 != v3);
}

TEST_CASE("swap")
{
const std::size_t size1 = 4u;
const std::size_t size2 = 8u;

buffer_test_type b1(make_test_buffer(size1), size1);
buffer_test_type b2(make_test_buffer(size2), size2);
view_test_type v1(b1), v2(b2);
auto* data1 = b1.data();
auto* data2 = b2.data();
v1.swap(v2);
CHECK_EQ(v1.size(), size2);
CHECK_EQ(v1.data(), data2);
CHECK_EQ(v2.size(), size1);
CHECK_EQ(v2.data(), data1);
}
}
}

0 comments on commit fe95a4d

Please sign in to comment.