Buffer Types

This section introduces Capy’s fundamental buffer types: const_buffer and mutable_buffer.

Prerequisites

Why Not std::byte?

std::byte imposes a semantic opinion. It says "this is raw bytes"—but that is itself an opinion about the data’s nature.

POSIX uses void* for buffers. This expresses semantic neutrality: "I move memory without opining on what it contains." The OS doesn’t care if the bytes represent text, integers, or compressed data—it moves them.

But std::span<void> doesn’t compile. C++ can’t express a type-agnostic buffer abstraction using span.

Capy provides const_buffer and mutable_buffer as semantically neutral buffer types with known layout.

const_buffer

const_buffer represents a contiguous region of read-only memory:

class const_buffer
{
public:
    const_buffer() = default;
    const_buffer(void const* data, std::size_t size) noexcept;
    const_buffer(mutable_buffer const& b) noexcept;  // Implicit conversion

    void const* data() const noexcept;
    std::size_t size() const noexcept;

    const_buffer& operator+=(std::size_t n) noexcept;  // Remove prefix
};

Construction

// From pointer and size
char data[] = "hello";
const_buffer buf(data, 5);

// From mutable_buffer (implicit)
mutable_buffer mbuf(data, 5);
const_buffer cbuf = mbuf;  // OK: mutable -> const

Accessors

const_buffer buf(data, 5);

void const* ptr = buf.data();  // Pointer to first byte
std::size_t len = buf.size();  // Number of bytes

Prefix Removal

The += operator removes bytes from the front of the buffer:

const_buffer buf(data, 10);

buf += 3;  // Remove first 3 bytes
// buf.data() now points 3 bytes later
// buf.size() is now 7

This is useful when processing a buffer incrementally.

mutable_buffer

mutable_buffer represents a contiguous region of writable memory:

class mutable_buffer
{
public:
    mutable_buffer() = default;
    mutable_buffer(void* data, std::size_t size) noexcept;

    void* data() const noexcept;
    std::size_t size() const noexcept;

    mutable_buffer& operator+=(std::size_t n) noexcept;
};

The interface mirrors const_buffer, but data() returns non-const void*.

Conversion

mutable_buffer implicitly converts to const_buffer:

void process(const_buffer buf);

mutable_buffer mbuf(data, size);
process(mbuf);  // OK: implicit conversion

The reverse is not allowed—you cannot implicitly convert const_buffer to mutable_buffer.

make_buffer

The make_buffer function creates buffers from various sources:

#include <boost/capy/buffers/make_buffer.hpp>

// From pointer and size
auto buf = make_buffer(ptr, size);

// From C array
char arr[10];
auto buf = make_buffer(arr);

// From std::array
std::array<char, 10> arr;
auto buf = make_buffer(arr);

// From std::vector
std::vector<char> vec(100);
auto buf = make_buffer(vec);

// From std::string
std::string str = "hello";
auto buf = make_buffer(str);

// From std::string_view
std::string_view sv = "hello";
auto buf = make_buffer(sv);

The returned buffer type depends on constness:

  • Non-const containers → mutable_buffer

  • Const containers, string_viewconst_buffer

Layout Compatibility

const_buffer and mutable_buffer have the same memory layout as OS buffer structures:

  • POSIX: struct iovec { void* iov_base; size_t iov_len; }

  • Windows: struct WSABUF { ULONG len; CHAR* buf; } (note: different order)

This means conversion to OS structures is efficient—often just a reinterpret_cast for arrays of buffers.

Single Buffers as Sequences

A single buffer is a degenerate sequence—a sequence with one element. The ConstBufferSequence and MutableBufferSequence concepts recognize this:

template<ConstBufferSequence Buffers>
void write_data(Buffers const& buffers);

// All of these work:
write_data(make_buffer("hello"));         // Single buffer
write_data(std::array{buf1, buf2, buf3}); // Multiple buffers
write_data(my_composite);                  // Custom sequence

The library provides begin() and end() functions that work uniformly:

const_buffer single;
auto it = begin(single);  // Returns pointer to single
auto e = end(single);     // Returns pointer past single

std::array<const_buffer, 3> multi;
auto it = begin(multi);   // Returns multi.begin()
auto e = end(multi);      // Returns multi.end()

Reference

Header Description

<boost/capy/buffers.hpp>

Core buffer types and concepts

<boost/capy/buffers/make_buffer.hpp>

Buffer creation utilities

You have now learned about const_buffer and mutable_buffer. Continue to Buffer Sequences to understand how these types compose into sequences.