Algorithms
This page describes the algorithms provided for working with buffer sequences. After reading, you will know how to measure, copy, slice, and iterate buffer sequences efficiently.
| Code snippets on this page assume the following declarations are in effect: |
#include <boost/buffers.hpp>
using namespace boost::buffers;
Measuring Size
The function size returns the total number of bytes across all buffers in
a sequence. This differs from the number of buffers, which length returns.
std::array<const_buffer, 3> buffers = {
const_buffer("Hello", 5),
const_buffer(", ", 2),
const_buffer("World!", 6)
};
std::size_t total_bytes = size(buffers); // 13
std::size_t num_buffers = length(buffers); // 3
For custom buffer sequence types, the size calculation can be optimized through
the size_tag customization point. See Customization.
Copying Data
The function copy transfers bytes from a source buffer sequence to a
destination buffer sequence:
template<class MutableBufferSequence, class ConstBufferSequence>
std::size_t
copy(
MutableBufferSequence const& dest,
ConstBufferSequence const& src,
std::size_t at_most = std::size_t(-1));
The function copies up to at_most bytes, limited by the sizes of both
sequences. It returns the actual number of bytes copied.
Basic Usage
char source[] = "Hello, Buffers!";
char dest[32];
const_buffer src(source, 15);
mutable_buffer dst(dest, sizeof(dest));
std::size_t n = copy(dst, src);
// n == 15
// dest contains "Hello, Buffers!"
Copying Between Sequences
The function handles scatter/gather copying transparently:
// Source: two separate regions
std::array<const_buffer, 2> src = {
const_buffer("Hello, ", 7),
const_buffer("World!", 6)
};
// Destination: one contiguous region
char storage[32];
mutable_buffer dst(storage, sizeof(storage));
std::size_t n = copy(dst, src);
// n == 13
// storage contains "Hello, World!"
Partial Copies
The at_most parameter limits the number of bytes copied:
char source[] = "Hello, Buffers!";
char dest[5];
const_buffer src(source, 15);
mutable_buffer dst(dest, sizeof(dest));
std::size_t n = copy(dst, src);
// n == 5 (limited by destination size)
// dest contains "Hello"
n = copy(dst, src, 3);
// n == 3 (limited by at_most)
// dest contains "Hel"
Getting the First Buffer
The function front returns the first buffer in a sequence. If the sequence
is empty, it returns an empty buffer:
std::array<const_buffer, 2> buffers = {
const_buffer("First", 5),
const_buffer("Second", 6)
};
const_buffer first = front(buffers);
// first.data() points to "First"
// first.size() == 5
This is useful when you need to examine or process the beginning of a buffer sequence without iterating:
template<class ConstBufferSequence>
bool starts_with_http(ConstBufferSequence const& bs)
{
const_buffer b = front(bs);
if(b.size() < 4)
return false;
return std::memcmp(b.data(), "HTTP", 4) == 0;
}
Slicing Buffer Sequences
Slicing creates a view of a subset of bytes from a buffer sequence. The library provides two families of functions:
-
Copy functions return a new sequence representing the slice
-
In-place functions modify the sequence object directly
Copy Slicing Functions
These functions return a new buffer sequence without modifying the original:
| Function | Description |
|---|---|
Return the first |
|
Return the last |
|
Return all bytes except the first |
|
Return all bytes except the last |
char data[] = "Hello, World!";
const_buffer original(data, 13);
auto first_five = prefix(original, 5);
// size(first_five) == 5, represents "Hello"
auto last_six = suffix(original, 6);
// size(last_six) == 6, represents "World!"
auto without_hello = sans_prefix(original, 7);
// size(without_hello) == 6, represents "World!"
auto without_world = sans_suffix(original, 7);
// size(without_world) == 6, represents "Hello,"
In-Place Slicing Functions
These functions modify the buffer sequence object directly. They require the
sequence type to support the slice customization point (built-in types like
const_buffer and mutable_buffer support this):
| Function | Description |
|---|---|
Remove all but the first |
|
Remove all but the last |
|
Remove the first |
|
Remove the last |
char data[] = "Hello, World!";
const_buffer buf(data, 13);
remove_prefix(buf, 7);
// buf now represents "World!" (6 bytes)
keep_prefix(buf, 5);
// buf now represents "World" (5 bytes)
The slice_of Wrapper
For buffer sequence types that do not natively support slicing, the library
provides slice_of, a wrapper that tracks prefix and suffix offsets:
std::vector<const_buffer> buffers = /* ... */;
// slice_of wraps the sequence and enables slicing
slice_of<std::vector<const_buffer>> sliced(buffers);
remove_prefix(sliced, 100);
// sliced now represents buffers with 100 bytes removed from the front
The type alias slice_type selects the appropriate type: the original type
if it supports slicing natively, or slice_of<T> otherwise.
Iterating Buffer Sequences
template<class ConstBufferSequence>
void process(ConstBufferSequence const& bs)
{
for(auto it = buffers::begin(bs); it != buffers::end(bs); ++it)
{
const_buffer b(*it);
// Process b.data() and b.size()
}
}
These functions handle both range types and single-buffer types uniformly. Using
std::begin and std::end would fail for single-buffer types.
Complete Iteration Example
#include <boost/buffers.hpp>
#include <iostream>
#include <iomanip>
using namespace boost::buffers;
template<class ConstBufferSequence>
void hex_dump(ConstBufferSequence const& bs)
{
std::size_t offset = 0;
for(auto it = buffers::begin(bs); it != buffers::end(bs); ++it)
{
const_buffer b(*it);
auto const* p = static_cast<unsigned char const*>(b.data());
for(std::size_t i = 0; i < b.size(); ++i, ++offset)
{
if(offset % 16 == 0)
std::cout << std::hex << std::setw(8)
<< std::setfill('0') << offset << ": ";
std::cout << std::hex << std::setw(2)
<< std::setfill('0') << static_cast<int>(p[i]) << ' ';
if(offset % 16 == 15)
std::cout << '\n';
}
}
if(offset % 16 != 0)
std::cout << '\n';
}
Algorithm Summary
| Algorithm | Purpose | Header |
|---|---|---|
Return total bytes in sequence |
|
|
Return number of buffers in sequence |
|
|
Copy bytes between sequences |
|
|
Return first buffer in sequence |
|
|
Return first |
|
|
Return last |
|
|
Return sequence without first |
|
|
Return sequence without last |
|
|
Remove first |
|
|
Remove last |
|
|
Keep only first |
|
|
Keep only last |
|
|
Return iterator to first buffer |
|
|
Return iterator past last buffer |
|