Listing 3: String_streambuf<> version 3

#ifndef STRING_STREAM_H
#define STRING_STREAM_H

#include <iostream>

template<typename StringT>
class String_streambuf : public std::streambuf {
    // typedefs
    typedef std::streambuf    inherited;
    typedef std::char_traits<char> traits;
    typedef inherited::int_type int_type;
    typedef std::streamsize streamsize;

    // data
    StringT&        _str;
    char            _buf[128];

public:
    String_streambuf(StringT& str);
    virtual ~String_streambuf();

protected:
    virtual int            sync();
    virtual int_type        overflow(int_type c = traits::eof());
};


//
// IOStreams
//
template<typename StringT>
class iString_stream : public std::istream {
    // types
    typedef std::istream inherited;

    // data
    String_streambuf<StringT>    _streambuf;

public:
    iString_stream(StringT& str);
    ~iString_stream();
};


template<typename StringT>
class oString_stream : public std::ostream {
    // types
    typedef std::ostream inherited;

    // data
    String_streambuf<StringT>    _streambuf;

public:
    oString_stream(StringT& str);
    ~oString_stream();
};


template<typename StringT>
class String_stream : public std::iostream {
    // types
    typedef std::IOStream inherited;

    // data
    String_streambuf<StringT>    _streambuf;

public:
    String_stream(StringT& str);
    ~String_stream();
};



//
// implementation
//
template<typename StringT>
String_streambuf<StringT>::String_streambuf(StringT& str)
  : _str(str)
{
    char* gbuf = const_cast<char*>(_str.data());
    setg(gbuf, gbuf, gbuf+_str.size());
    setp(_buf, _buf + sizeof(_buf));
}


template<typename StringT>
String_streambuf<StringT>::~String_streambuf()
{
    // empty
}


template<typename StringT>
int
String_streambuf<StringT>::sync()
{
    size_t l = pptr() - pbase();
    if (l > 0) {
        size_t pos = gptr() - eback();  // remember the get position
        _str.append(_buf, l);
        setp(_buf, _buf+sizeof(_buf));
        char* gbuf = const_cast<char*>(_str.data());
        setg(gbuf, gbuf+pos, gbuf+_str.size()); // reset the get buffer
    }
    return 0;
}


template<typename StringT>
typename String_streambuf<StringT>::int_type
String_streambuf<StringT>::overflow(int_type c)
{
    sync();
    if (c != traits::eof()) {
        *_buf = c;
        pbump(1);
        return c;
    }
    return traits::not_eof(c);
}


template<typename StringT>
iString_stream<StringT>::iString_stream(StringT& str)
  : inherited(0),
    _streambuf(str)
{
    init(&_streambuf);
}


template<typename StringT>
iString_stream<StringT>::~iString_stream()
{
    // empty
}


template<typename StringT>
oString_stream<StringT>::oString_stream(StringT& str)
  : inherited(0),
    _streambuf(str)
{
    init(&_streambuf);
}


template<typename StringT>
oString_stream<StringT>::~oString_stream()
{
    // empty
}


template<typename StringT>
String_stream<StringT>::String_stream(StringT& str)
  : inherited(0),
    _streambuf(str)
{
    init(&_streambuf);
}


template<typename StringT>
String_stream<StringT>::~String_stream()
{
    // empty
}


#endif