#ifndef STRZSTREAM_H
#define STRZSTREAM_H

#include <streambuf>
#include <iostream>


template <typename C, class T = std::char_traits<C> >
class StrzStreamBufT : public std::basic_streambuf<C, T> {
public:
    typedef std::size_t size_type;

    StrzStreamBufT(C* buf, std::size_t size, std::size_t capa) {
        assert(buf!=0 && capa > 1);
        init(buf, buf+size, buf+capa-1);
    }

    C*          c_str()          { *this->pptr() = 0; return this->pbase(); }
    size_type   capacity() const { return 1 + this->epptr() - this->pbase(); }
    size_type   size()     const { return this->pptr() - this->pbase(); }
    void        clear_buf()      { init(this->pbase(), this->pbase(), this->epptr()); }

private:
    void        init(C* bgn, C* cur, C* end) { setp( bgn, end ); setg( bgn, cur, end ); }
};



template <typename C, class T = std::char_traits<C> >
class StrzStreamT : public StrzStreamBufT<C,T>, public std::basic_iostream<C, T> {
public:
   StrzStreamT(C* buf, std::size_t size, std::size_t capa)
      : StrzStreamBufT<C,T>(buf, size, capa)
      , std::basic_iostream<C,T>( static_cast< StrzStreamBufT<C,T>* >(this) )
   {
   }
};


typedef StrzStreamT<char>               StrzStream;
typedef StrzStreamT<wchar_t>            WcszStream;


template <unsigned N>
class CharAryStream : public StrzStream {
public:
   CharAryStream() : StrzStream(buf_, 0, N) { }
    std::size_t capacity() const { return N; }

private:
    char    buf_[ N ];
};


template <unsigned N>
class WcharAryStream : public WcszStream {
public:
   WcharAryStream() : WcszStream(buf_, 0, N) { }
    std::size_t capacity() const { return N; }

private:
    wchar_t     buf_[ N ];
};



#endif  // STRZSTREAM_H