/** -*- C++ -*-
 **
 **  KAI C++ Compiler
 **
 **  Copyright (C) 1996-2001 Intel Corp. All rights reserved.
 **/
// Copied from ISO C++ Standard, Annex D.
// Plus additions to support some old-style code.

#ifndef __KAI_STRSTREAM
#define __KAI_STRSTREAM

#include <ios>
#include <streambuf>
#include <iostreambase>

namespace std {

class strstreambuf : public streambuf {
public:
    explicit strstreambuf( streamsize alsize_arg = 0 );
    strstreambuf( void* (*palloc_arg)(size_t), void (*pfree_arg)(void*) );
    strstreambuf( char* gnext_arg, streamsize n, char* pbeg_arg = 0 );
    strstreambuf( const char* gnext_arg, streamsize n, const char* pbeg_arg = 0 );
    strstreambuf( signed char* gnext_arg, streamsize n, signed char* pbeg_arg = 0 );
    strstreambuf( const signed char* gnext_arg, streamsize n, const signed char* pbeg_arg = 0 );
    strstreambuf( unsigned char* gnext_arg, streamsize n, unsigned char* pbeg_arg = 0 );
    strstreambuf( const unsigned char* gnext_arg, streamsize n, const unsigned char* pbeg_arg = 0 );
    virtual ~strstreambuf();

    void freeze( bool freezefl=1 );
    char* str() { freeze(); return eback(); }
    int pcount() const { return pptr()!=NULL ? pptr()-pbase() : 0; }
    int out_waiting() const { return pcount(); }
    void stossc() { if ( gptr() >= egptr() ) underflow(); else gbump(1); }

    virtual streamsize xsputn (const char * s, streamsize n);

protected:
    virtual int_type overflow( int_type c = traits_type::eof() );
    virtual int_type pbackfail( int_type c = traits_type::eof() );
    virtual int_type underflow();
    virtual pos_type seekoff(off_type off, ios_base::seekdir way,
			     ios_base::openmode which = ios_base::in | ios_base::out);
    virtual pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out);

private:
    enum strstate {ALLOCATED=1,CONSTANT=2,DYNAMIC=4,FROZEN=8};
    strstate strmode;
    streamsize alsize;
    streamsize bsize;
    void* (*palloc)(streamsize);
    void (*pfree)(void*);
    static void * default_alloc( streamsize n ) {return new char[n];}
    static void default_free( void * p ) {delete[] (char*)p;}
    void initialize( char* gnext_arg, streamsize n, char* pbeg_arg );
    static const size_t min_size = 16;
	    // The 16 is arbitrary.  Any positive value will do.
	    // ADR is assuming that malloc'ing less than 16 bytes
	    // costs as much as malloc'ing 16 bytes.
};    

} // namespace std

namespace __kai {

class isstream : public std::istream {
public:
    isstream( std::streambuf * s ) : istream(s) {}
    virtual ~isstream();
    isstream& seekg( pos_type );
    isstream& seekg( off_type, ios_base::seekdir );
};

} // namespace __kai 

namespace std {

class istrstream : public __kai::isstream {
public:
    explicit istrstream( const char * s );
    explicit istrstream( char * s );
    istrstream( const char * s, streamsize n );
    istrstream( char * s, streamsize n );
    virtual ~istrstream();

    strstreambuf* rdbuf() const {return const_cast<strstreambuf*>(&strbuf);}
    char* str() {return strbuf.str();}
private:
    strstreambuf strbuf;
};

class ostrstream : public ostream {
public:
    ostrstream( );
    ostrstream( char * s, streamsize n, ios_base::openmode mode = ios_base::out );
    virtual ~ostrstream();

    void freeze( bool freezefl=1 ) { strbuf.freeze(freezefl); }
    int pcount() const { return strbuf.pcount(); }
    strstreambuf* rdbuf() const {return const_cast<strstreambuf*>(&strbuf);}
    char* str() {return strbuf.str();}
private:
    strstreambuf strbuf;
};

typedef basic_iostream<char,char_traits<char> > iostream;

class strstream : public iostream {
public:
    strstream() : iostream(&strbuf) { }
    strstream( char * s, streamsize n, ios_base::openmode mode = ios_base::out|ios_base::in );
    virtual ~strstream();

    char* str() {return strbuf.str();}
private:
    strstreambuf strbuf;
};

} /* namepace std */
#endif	/* __KAI_STRSTREAM */
