Buffer Sequences
This page explains how to work with sequences of buffers.
Code snippets assume using namespace boost::capy; is in effect.
|
What is a Buffer Sequence?
A buffer sequence represents a logical contiguous byte stream that may be stored in multiple non-contiguous memory regions. This enables scatter/gather I/O and avoids copying when data spans multiple buffers.
// A sequence of three buffers representing a single message
std::array<const_buffer, 3> buffers = {
const_buffer(header, header_size),
const_buffer(payload, payload_size),
const_buffer(trailer, trailer_size)
};
Buffer Sequence Concepts
Capy defines two concepts for buffer sequences:
| Concept | Description |
|---|---|
|
A range of elements convertible to |
|
A range of elements convertible to |
A type satisfies const_buffer_sequence if it is:
-
Convertible to
const_buffer, OR -
A bidirectional range whose value type is convertible to
const_buffer
Single buffers are valid buffer sequences containing one element.
Iterating Buffer Sequences
Use begin and end to iterate over a buffer sequence:
template<const_buffer_sequence Buffers>
void process(Buffers const& buffers)
{
for (auto it = begin(buffers); it != end(buffers); ++it)
{
const_buffer buf = *it;
// Process each contiguous region
}
}
These functions work uniformly for both single buffers and ranges of buffers.
Buffer Size and Length
Two functions measure buffer sequences differently:
| Function | Returns |
|---|---|
|
Total bytes across all buffers in the sequence |
|
Number of buffers in the sequence |
std::array<const_buffer, 3> buffers = {
const_buffer(a, 10),
const_buffer(b, 20),
const_buffer(c, 30)
};
std::size_t bytes = buffer_size(buffers); // 60 (total bytes)
std::size_t count = buffer_length(buffers); // 3 (number of buffers)
Buffer Pairs
For sequences that always have exactly two elements, use const_buffer_pair
or mutable_buffer_pair:
const_buffer_pair pair(
const_buffer(first, first_size),
const_buffer(second, second_size)
);
// Access elements
const_buffer& b0 = pair[0];
const_buffer& b1 = pair[1];
// Iterate
for (const_buffer const& buf : pair)
{
// ...
}
Buffer pairs are useful for circular buffers where data wraps around.
Slicing Buffer Sequences
The slicing algorithms adjust buffer sequences without copying data:
// Remove bytes from front
tag_invoke(slice_tag{}, buf, slice_how::remove_prefix, n);
// Keep only the first n bytes
tag_invoke(slice_tag{}, buf, slice_how::keep_prefix, n);
These modify the buffer in place.
Type Aliases
| Alias | Definition |
|---|---|
|
|
template<const_buffer_sequence Buffers>
void process(Buffers const& buffers)
{
using buf_t = buffer_type<Buffers>; // const_buffer or mutable_buffer
// ...
}
Common Patterns
Summary
| Component | Purpose |
|---|---|
|
Concept for read-only buffer sequences |
|
Concept for writable buffer sequences |
|
Iterate buffer sequences uniformly |
|
Total bytes in sequence |
|
Number of buffers in sequence |
|
Two-element const buffer sequence |
|
Two-element mutable buffer sequence |
Next Steps
-
Dynamic Buffers — Growable buffer containers
-
Buffer Types — Basic buffer types