#ifndef cathlibcpp_streambuf_H
#define cathlibcpp_streambuf_H

// File:       streambuf.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ streambuf header


#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_ios_H
#include "ios.h"
#endif

#ifndef cathlibcpp_string_H
#include "string.h"              // for char_traits_char
#endif


class basic_streambuf_char
{
  friend class basic_istream_char_sentry;
  friend class basic_ostream_char_sentry;

  public:

    // types
    typedef char_traits_char traits;

    // constructors
    virtual ~basic_streambuf_char();

    // buffer and positioning
    basic_streambuf_char* pubsetbuf(char* s, streamsize n);
    int pubseekoff(int off, ios::seekdir way, ios::openmode which = ios::in|ios::out);
    int pubseekpos(int sp, ios::openmode which = ios::in|ios::out);
    int pubsync();

    // get area
    int in_avail();
    int snextc();
    int sbumpc();
    int sgetc();
    int sgetn(char* s, streamsize n);

    // putback

    int sputbackc(char c);
    int sungetc();

    // put area
    int sputc(char c);
    int sputn(char const* s, streamsize n);

  protected:

    // constructors
    basic_streambuf_char();

    // get area
    char* eback() const;
    char* gptr() const;
    char* egptr() const;

    void gbump(int n);
    void setg(char* gbeg, char* gnext, char* gend);

    // put area
    char* pbase() const;
    char* pptr() const;
    char* epptr() const;

    void pbump(int n);
    void setp(char* pbeg, char* pend);

    // buffer management and positioning
    virtual basic_streambuf_char* setbuf(char* s, streamsize n);
    virtual int seekoff(int off, ios::seekdir way, ios::openmode which = ios::in|ios::out);
    virtual int seekpos(int ps, ios::openmode which = ios::in|ios::out);
    virtual int sync();

    // get area
    virtual int showmanyc();
    virtual streamsize xsgetn(char* s, streamsize n);
    virtual int underflow();
    virtual int uflow();

    // putback
    virtual int pbackfail(int c = traits::eof());

    // put area
    virtual streamsize xsputn(char const* s, streamsize n);
    virtual int overflow(int c = traits::eof());

  private:

    // stdio synchronization
    virtual void sync_stdio_with_stream();
    virtual void sync_stream_with_stdio();

    bool gavail() const;
    bool pavail() const;
    bool pbavail() const;

    char* gbeg_;
    char* gnext_;
    char* gend_;
    char* pbeg_;
    char* pnext_;
    char* pend_;
};


// Implementation of basic_streambuf_char

inline basic_streambuf_char* basic_streambuf_char::pubsetbuf(char* s, streamsize n)
  { return setbuf(s, n); }

inline int basic_streambuf_char::pubseekoff(int off, ios::seekdir way, ios::openmode which)
  { return seekoff(off, way, which); }

inline int basic_streambuf_char::pubseekpos(int sp, ios::openmode which)
  { return seekpos(sp, which); }

inline int basic_streambuf_char::pubsync()
  { return sync(); }

inline int basic_streambuf_char::sgetn(char* s, streamsize n)
  { return xsgetn(s, n); }

inline int basic_streambuf_char::sputn(char const* s, streamsize n)
  { return xsputn(s, n); }

inline char* basic_streambuf_char::eback() const
  { return gbeg_; }

inline char* basic_streambuf_char::gptr() const
  { return gnext_; }

inline char* basic_streambuf_char::egptr() const
  { return gend_; }

inline void basic_streambuf_char::gbump(int n)
  { gnext_ += n; }

inline void basic_streambuf_char::setg(char* gbeg, char* gnext, char* gend)
  {
    gbeg_ = gbeg;
    gnext_ = gnext;
    gend_ = gend;
  }

inline char* basic_streambuf_char::pbase() const
  { return pbeg_; }

inline char* basic_streambuf_char::pptr() const
  { return pnext_; }

inline char* basic_streambuf_char::epptr() const
  { return pend_; }

inline void basic_streambuf_char::pbump(int n)
  { pnext_ += n; }

inline void basic_streambuf_char::setp(char* pbeg, char* pend)
  {
    pbeg_ = pbeg;
    pnext_ = pbeg;
    pend_ = pend;
  }

#endif
