Boost logo

Boost :

From: Maxim Egorushkin (e-maxim_at_[hidden])
Date: 2003-05-04 09:15:35


Hi, all.

I've written std::streambuf<> adapters and I think you might find it
useful enough to include it in boost.

The main idea is simple: make implementation of custom streambuf easier.
This is done by obviating the user from buffer memory management and by
presenting more simple then std::basic_streambuf<> interface to the
controled sequence (sequence model) for the user to implement.

Here is the synosis of it:

<code>
namespace sequence_buffer
{

// adaptable sequence concepts
template<class model> class input_sequence_concept;
template<class model> class output_sequence_concept;

// examples of sequence models
template<class iterator> class stl_input_sequence;
template<class iterator> class stl_output_sequence;
template<class container> class push_back_sequence;

// named optional parameters for buffer adapters
template<class T> struct allocator_is;
template<class T> struct element_is;
template<class T> struct element_traits_is;
template<size_t size> struct buffer_size_is;

namespace detail { struct default_parameter; }

// buffer adapters
template<
        // mandatory parameters
                class sequence_model
        // optional parameters
        , class P1 = detail::default_parameter
        , class P2 = detail::default_parameter
        , class P3 = detail::default_parameter
        , class P4 = detail::default_parameter
>
class input_buffer;

template<
        // mandatory parameters
                class sequence_model
        // optional parameters
        , class P1 = detail::default_parameter
        , class P2 = detail::default_parameter
        , class P3 = detail::default_parameter
        , class P4 = detail::default_parameter
>
class output_buffer;

} // namespace sequence_buffer
</code>

I implemented 3 examples of the sequence model: stl_input_sequence<>,
stl_output_sequence<>, push_back_sequence<>. I don't think they are
quite useful but they are good as examples.

Here is the example of usage (useless but clear):

<code>
#include <iostream>
#include <algorithm>
#include <vector>

#include "sequence_buffer.hpp"

int main()
{
        using namespace std;
        namespace sb = sequence_buffer;

        vector<char> v1;

        // make an output buffer from the vector
        typedef sb::push_back_sequence<vector<char> > seq1;
        seq1 s1(v1);
        sb::output_buffer<seq1> b1(s1);

        // redirect cout to the buffer
        basic_streambuf<char>* cout_buf = cout.rdbuf(&b1);

        cout << "Redirect this text" << endl;

        // make an input buffer from the vector
        typedef sb::stl_input_sequence<vector<char>::const_iterator>
seq2;
        seq2 s2(v1.begin(), v1.end());
        sb::input_buffer<seq2> b2(s2);

        // copy the input buffer-vector to the original cout buffer
        copy(istreambuf_iterator<char>(&b2),
istreambuf_iterator<char>(),
                ostreambuf_iterator<char>(cout_buf));

        cout.rdbuf(cout_buf);

        return 0;
}
</code>

Of course, in a real project I made more conscious use of it: I use the
adapters to make ftp files look like std::streambuf<>.

The buffer adapters have optional parameters: element type (default is
char), element traits (default is std::char_traits<element>), buffer
size (default is 0x100 elements) and buffer memory allocator (default is
std::allocator<element>). When parametrizing a buffer adapter the
parameters can be specified in any orded (the idea comes from boost
iterator adapters library):

<code>
typedef output_buffer<my_sequence, element_is<wchar_t> > buf1;
typedef output_buffer<my_sequence, buffer_size_is<0x4000>,
allocator_is<my_allocator<wchar_t> >, element_is<wchar_t> > buf2;
</code>

The code uses boost mpl library and type traits. It was written using MS
VC++ 7.1 and tested on gcc 3.2.

That's all.

Thank you for reading to this point,
Maxim Egorushkin.





Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk