$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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.