Adapter

The core component contains types that are used by all protocols

When generating a protocol-specific encoded output, the result is written to an output buffer. Several types of output buffers can be used, such as arrays, strings, and I/O streams. As these have different interfaces, each type is wrapped by an adapter. Custom output buffer types can be added with adapter traits. The output buffer is passed via the constructor of the protocol generator.

Trial.protocol has support for a number of commonly used output buffer types. Using any of these requires the inclusion of an associated header file as shown in the table below.

Type

Header File

CharT[N]

<trial/protocol/buffer/array.hpp>

std::array<CharT, N>

<trial/protocol/buffer/array.hpp>

std::basic_ostream<CharT>

<trial/protocol/buffer/ostream.hpp>

std::basic_string<CharT>

<trial/protocol/buffer/string.hpp>

std::vector<CharT>

<trial/protocol/buffer/vector.hpp>

where CharT can be char or unsigned char. Wide characters are not supported.

Support for other output buffer types can be added via adapter traits.

Adapter Traits

The encoded output can be written to other output buffer types. This is done by specifying a buffer adapter and a trait to select this buffer adapter for the output buffer type.

The buffer adapter must inherit from buffer::base and implement the following API:

Member

Description

bool grow(size_type)

Reserve space in the output buffer. Returns false if the requested space cannot be reserved, in which case no further data will be written to the output buffer.

void write(value_type)

Output a single character.

void write(const view_type&)

Output a sequence of characters.

Tutorial: Deque Adapter

Assume that we add support for std::deque. First the buffer wrapper for std::deque is written like this:

#include <deque>
#include <trial/protocol/buffer/base.hpp>

namespace my {

template <CharT>
class deque_wrapper : public buffer::base<CharT>
{
public:
    using value_type = typename buffer::base<CharT>::value_type;
    using size_type = typename buffer::base<CharT>::size_type;
    using view_type = typename buffer::base<CharT>::view_type;

    deque_wrapper(std::deque<value_type>& buffer)
        : buffer(buffer)
    {}

protected:
    virtual bool grow(size_type delta)
    {
        buffer.resize(buffer.size() + delta);
    }

    virtual void write(value_type value)
    {
        buffer.push_back(value);
    }

    virtual void write(const view_type& view)
    {
        buffer.insert(buffer.end(), view.begin(), view.end());
    }

private:
    std::deque<value_type>& buffer;
};

} // namespace my

Next we must make this wrapper known to the protocol generator, which is done as follows:

namespace trial { namespace protocol { namespace buffer {

template <typename T>
struct traits< std::deque<T> >
{
    using buffer_type = my::deque_wrapper<T>;
};

}}}
The traits struct must be located inside the trial::protocol::buffer namespace.