/* This is part of libio/iostream, providing -*- C++ -*- input/output.
Copyright (C) 2000 Free Software Foundation

This file is part of the GNU IO Library.  This library is free
software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option)
any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this library; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

As a special exception, if you link this library with files
compiled with a GNU compiler to produce an executable, this does not cause
the resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */

/* Written by Magnus Fromreide (magfr@lysator.liu.se). */
/* seekoff and ideas for overflow is largely borrowed from libstdc++-v3 */

#ifndef __SSTREAM__
#define __SSTREAM__

#include <iostream.h>
#include <streambuf.h>
#include <string>

namespace std
{
  class stringbuf : public streambuf
  {
  public:
    typedef char	char_type;
    typedef int		int_type;
    typedef streampos	pos_type;
    typedef streamoff	off_type;

    explicit
    stringbuf(int which=ios::in|ios::out)
      : streambuf(), mode(static_cast<ios::open_mode>(which)),
	stream(NULL), stream_len(0)
    {
      stringbuf_init();
    }

    explicit
    stringbuf(const string &str, int which=ios::in|ios::out)
      : streambuf(), mode(static_cast<ios::open_mode>(which)),
	stream(NULL), stream_len(0)
    {
      if (mode & (ios::in|ios::out))
	{
	  stream_len = str.size();
	  stream = new char_type[stream_len];
	  str.copy(stream, stream_len);
	}
      stringbuf_init();
    }

    virtual
    ~stringbuf()
    {
      delete[] stream;
    }

    string
    str() const
    {
      if (pbase() != 0)
	return string(stream, pptr()-pbase());
      else
	return string();
    }

    void
    str(const string& str)
    {
      delete[] stream;
      stream_len = str.size();
      stream = new char_type[stream_len];
      str.copy(stream, stream_len);
      stringbuf_init();
    }

  protected:
    // The buffer is already in gptr, so if it ends then it is out of data.
    virtual int
    underflow()
    {
      return EOF;
    }

    virtual int
    overflow(int c = EOF)
    {
      int res;
      if (mode & ios::out)
	{
	  if (c != EOF)
	    {
	      streamsize old_stream_len = stream_len;
	      stream_len += 1;
	      char_type* new_stream = new char_type[stream_len];
	      memcpy(new_stream, stream, old_stream_len);
	      delete[] stream;
	      stream = new_stream;
	      stringbuf_sync(gptr()-eback(), pptr()-pbase());
	      sputc(c);
	      res = c;
	    }
	  else
	    res = EOF;
	}
      else
	res = 0;
      return res;
    }

    virtual streambuf*
    setbuf(char_type* s, streamsize n)
    {
      if (n != 0)
	{
	  delete[] stream;
	  stream = new char_type[n];
	  memcpy(stream, s, n);
	  stream_len = n;
	  stringbuf_sync(0, 0);
	}
      return this;
    }

    virtual pos_type
    seekoff(off_type off, ios::seek_dir way, int which = ios::in | ios::out)
    {
      pos_type ret =  pos_type(off_type(-1));
      bool testin = which & ios::in && mode & ios::in;
      bool testout = which & ios::out && mode & ios::out;
      bool testboth = testin && testout && way != ios::cur;

      if (stream_len && ((testin != testout) || testboth))
	{
	  char_type* beg = stream;
	  char_type* curi = NULL;
	  char_type* curo = NULL;
	  char_type* endi = NULL;
	  char_type* endo = NULL;

	  if (testin)
	    {
	      curi = gptr();
	      endi = egptr();
	    }
	  if (testout)
	    {
	      curo = pptr();
	      endo = epptr();
	    }

	  off_type newoffi = 0;
	  off_type newoffo = 0;
	  if (way == ios::beg)
	    {
	      newoffi = beg - curi;
	      newoffo = beg - curo;
	    }
	  else if (way == ios::end)
	    {
	      newoffi = endi - curi;
	      newoffo = endo - curo;
	    }

	  if (testin && newoffi + off + curi - beg >= 0 &&
	      endi - beg >= newoffi + off + curi - beg)
	    {
	      gbump(newoffi + off);
	      ret = pos_type(newoffi + off + curi);
	    }
	  if (testout && newoffo + off + curo - beg >= 0 &&
	      endo - beg >= newoffo + off + curo - beg)
	    {
	      pbump(newoffo + off);
	      ret = pos_type(newoffo + off + curo);
	    }
	}
      return ret;
    }

    virtual pos_type
    seekpos(pos_type sp, int which = ios::in | ios::out)
    {
      pos_type ret = seekoff(sp, ios::beg, which);
      return ret;
    }

  private:
    void
    stringbuf_sync(streamsize i, streamsize o)
    {
      if (mode & ios::in)
	setg(stream, stream + i, stream + stream_len);
      if (mode & ios::out)
	{
	  setp(stream, stream + stream_len);
	  pbump(o);
	}
    }
    void
    stringbuf_init()
    {
      if (mode & ios::ate)
	stringbuf_sync(0, stream_len);
      else
	stringbuf_sync(0, 0);
    }

  private:
    ios::open_mode	mode;
    char_type*		stream;
    streamsize		stream_len;
  };

  class istringstream : public istream {
  public:
    typedef char	char_type;
    typedef int		int_type;
    typedef streampos	pos_type;
    typedef streamoff	off_type;

    explicit
    istringstream(int which=ios::in)
      : istream(&sb), sb(which | ios::in)
    { }

    explicit
    istringstream(const string& str, int which=ios::in)
      : istream(&sb), sb(str, which | ios::in)
    { }

    stringbuf*
    rdbuf() const
    {
      return const_cast<stringbuf*>(&sb);
    }

    string
    str() const
    {
      return rdbuf()->str();
    }
    void
    str(const string& s)
    {
      rdbuf()->str(s);
    }
  private:
    stringbuf sb;
  };

  class ostringstream : public ostream {
  public:
    typedef char	char_type;
    typedef int		int_type;
    typedef streampos	pos_type;
    typedef streamoff	off_type;

    explicit
    ostringstream(int which=ios::out)
      : ostream(&sb), sb(which | ios::out)
    { }

    explicit
    ostringstream(const string& str, int which=ios::out)
      : ostream(&sb), sb(str, which | ios::out)
    { }

    stringbuf*
    rdbuf() const
    {
      return const_cast<stringbuf*>(&sb);
    }

    string
    str() const
    {
      return rdbuf()->str();
    }

    void str(const string& s)
    {
      rdbuf()->str(s);
    }
  private:
    stringbuf sb;
  };

  class stringstream : public iostream {
  public:
    typedef char	char_type;
    typedef int		int_type;
    typedef streampos	pos_type;
    typedef streamoff	off_type;

    explicit
    stringstream(int which=ios::out|ios::in)
      : iostream(&sb), sb(which)
    { }

    explicit
    stringstream(const string& str, int which=ios::out|ios::in)
      : iostream(&sb), sb(str, which)
    { }

    stringbuf*
    rdbuf() const
    {
      return const_cast<stringbuf*>(&sb);
    }

    string
    str() const
    {
      return rdbuf()->str();
    }

    void
    str(const string& s)
    {
      rdbuf()->str(s);
    }
  private:
    stringbuf sb;
  };
};

#endif /* not __STRSTREAM__ */
