Listing 1: String_streambuf<> version 1

#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;
    size_t        _pos;

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

protected:
    virtual inherited*    setbuf(char* s, streamsize n);
    virtual int_type        underflow();
    virtual int_type        uflow();
    virtual int_type        pbackfail(int_type c = traits::eof());
    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),
    _pos(0)
{
    // empty
}


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


template<typename StringT>
String_streambuf<StringT>::inherited*
String_streambuf<StringT>::setbuf(char* s, streamsize n)
{
    return this;
}


template<typename StringT>
typename String_streambuf<StringT>::int_type
String_streambuf<StringT>::underflow()
{
    if (_pos < _str.size())
        return _str[_pos];
    return traits::eof();
}


template<typename StringT>
typename String_streambuf<StringT>::int_type
String_streambuf<StringT>::uflow()
{
    if (_pos < _str.size())
        return _str[_pos++];
    return traits::eof();
}


template<typename StringT>
typename String_streambuf<StringT>::int_type
String_streambuf<StringT>::pbackfail(int_type c)
{
    if (_pos > 0 && _str[_pos-1] == c) {
        --_pos;
        return c;
    }
    return traits::eof();
}


template<typename StringT>
typename String_streambuf<StringT>::int_type
String_streambuf<StringT>::overflow(int_type c)
{
    if (c != traits::eof()) {
        _str += c;
        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