Home | History | Annotate | Download | only in include
      1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
      2 Copyright (C) 2000 Free Software Foundation
      3 
      4 This file is part of the GNU IO Library.  This library is free
      5 software; you can redistribute it and/or modify it under the
      6 terms of the GNU General Public License as published by the
      7 Free Software Foundation; either version 2, or (at your option)
      8 any later version.
      9 
     10 This library is distributed in the hope that it will be useful,
     11 but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this library; see the file COPYING.  If not, write to the Free
     17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 As a special exception, if you link this library with files
     20 compiled with a GNU compiler to produce an executable, this does not cause
     21 the resulting executable to be covered by the GNU General Public License.
     22 This exception does not however invalidate any other reasons why
     23 the executable file might be covered by the GNU General Public License. */
     24 
     25 /* Written by Magnus Fromreide (magfr (at) lysator.liu.se). */
     26 /* seekoff and ideas for overflow is largely borrowed from libstdc++-v3 */
     27 
     28 #ifndef __SSTREAM__
     29 #define __SSTREAM__
     30 
     31 #include <iostream.h>
     32 #include <streambuf.h>
     33 #include <string>
     34 
     35 namespace std
     36 {
     37   class stringbuf : public streambuf
     38   {
     39   public:
     40     typedef char	char_type;
     41     typedef int		int_type;
     42     typedef streampos	pos_type;
     43     typedef streamoff	off_type;
     44 
     45     explicit
     46     stringbuf(int which=ios::in|ios::out)
     47       : streambuf(), mode(static_cast<ios::open_mode>(which)),
     48 	stream(NULL), stream_len(0)
     49     {
     50       stringbuf_init();
     51     }
     52 
     53     explicit
     54     stringbuf(const string &str, int which=ios::in|ios::out)
     55       : streambuf(), mode(static_cast<ios::open_mode>(which)),
     56 	stream(NULL), stream_len(0)
     57     {
     58       if (mode & (ios::in|ios::out))
     59 	{
     60 	  stream_len = str.size();
     61 	  stream = new char_type[stream_len];
     62 	  str.copy(stream, stream_len);
     63 	}
     64       stringbuf_init();
     65     }
     66 
     67     virtual
     68     ~stringbuf()
     69     {
     70       delete[] stream;
     71     }
     72 
     73     string
     74     str() const
     75     {
     76       if (pbase() != 0)
     77 	return string(stream, pptr()-pbase());
     78       else
     79 	return string();
     80     }
     81 
     82     void
     83     str(const string& str)
     84     {
     85       delete[] stream;
     86       stream_len = str.size();
     87       stream = new char_type[stream_len];
     88       str.copy(stream, stream_len);
     89       stringbuf_init();
     90     }
     91 
     92   protected:
     93     // The buffer is already in gptr, so if it ends then it is out of data.
     94     virtual int
     95     underflow()
     96     {
     97       return EOF;
     98     }
     99 
    100     virtual int
    101     overflow(int c = EOF)
    102     {
    103       int res;
    104       if (mode & ios::out)
    105 	{
    106 	  if (c != EOF)
    107 	    {
    108 	      streamsize old_stream_len = stream_len;
    109 	      stream_len += 1;
    110 	      char_type* new_stream = new char_type[stream_len];
    111 	      memcpy(new_stream, stream, old_stream_len);
    112 	      delete[] stream;
    113 	      stream = new_stream;
    114 	      stringbuf_sync(gptr()-eback(), pptr()-pbase());
    115 	      sputc(c);
    116 	      res = c;
    117 	    }
    118 	  else
    119 	    res = EOF;
    120 	}
    121       else
    122 	res = 0;
    123       return res;
    124     }
    125 
    126     virtual streambuf*
    127     setbuf(char_type* s, streamsize n)
    128     {
    129       if (n != 0)
    130 	{
    131 	  delete[] stream;
    132 	  stream = new char_type[n];
    133 	  memcpy(stream, s, n);
    134 	  stream_len = n;
    135 	  stringbuf_sync(0, 0);
    136 	}
    137       return this;
    138     }
    139 
    140     virtual pos_type
    141     seekoff(off_type off, ios::seek_dir way, int which = ios::in | ios::out)
    142     {
    143       pos_type ret =  pos_type(off_type(-1));
    144       bool testin = which & ios::in && mode & ios::in;
    145       bool testout = which & ios::out && mode & ios::out;
    146       bool testboth = testin && testout && way != ios::cur;
    147 
    148       if (stream_len && ((testin != testout) || testboth))
    149 	{
    150 	  char_type* beg = stream;
    151 	  char_type* curi = NULL;
    152 	  char_type* curo = NULL;
    153 	  char_type* endi = NULL;
    154 	  char_type* endo = NULL;
    155 
    156 	  if (testin)
    157 	    {
    158 	      curi = gptr();
    159 	      endi = egptr();
    160 	    }
    161 	  if (testout)
    162 	    {
    163 	      curo = pptr();
    164 	      endo = epptr();
    165 	    }
    166 
    167 	  off_type newoffi = 0;
    168 	  off_type newoffo = 0;
    169 	  if (way == ios::beg)
    170 	    {
    171 	      newoffi = beg - curi;
    172 	      newoffo = beg - curo;
    173 	    }
    174 	  else if (way == ios::end)
    175 	    {
    176 	      newoffi = endi - curi;
    177 	      newoffo = endo - curo;
    178 	    }
    179 
    180 	  if (testin && newoffi + off + curi - beg >= 0 &&
    181 	      endi - beg >= newoffi + off + curi - beg)
    182 	    {
    183 	      gbump(newoffi + off);
    184 	      ret = pos_type(newoffi + off + curi);
    185 	    }
    186 	  if (testout && newoffo + off + curo - beg >= 0 &&
    187 	      endo - beg >= newoffo + off + curo - beg)
    188 	    {
    189 	      pbump(newoffo + off);
    190 	      ret = pos_type(newoffo + off + curo);
    191 	    }
    192 	}
    193       return ret;
    194     }
    195 
    196     virtual pos_type
    197     seekpos(pos_type sp, int which = ios::in | ios::out)
    198     {
    199       pos_type ret = seekoff(sp, ios::beg, which);
    200       return ret;
    201     }
    202 
    203   private:
    204     void
    205     stringbuf_sync(streamsize i, streamsize o)
    206     {
    207       if (mode & ios::in)
    208 	setg(stream, stream + i, stream + stream_len);
    209       if (mode & ios::out)
    210 	{
    211 	  setp(stream, stream + stream_len);
    212 	  pbump(o);
    213 	}
    214     }
    215     void
    216     stringbuf_init()
    217     {
    218       if (mode & ios::ate)
    219 	stringbuf_sync(0, stream_len);
    220       else
    221 	stringbuf_sync(0, 0);
    222     }
    223 
    224   private:
    225     ios::open_mode	mode;
    226     char_type*		stream;
    227     streamsize		stream_len;
    228   };
    229 
    230   class istringstream : public istream {
    232   public:
    233     typedef char	char_type;
    234     typedef int		int_type;
    235     typedef streampos	pos_type;
    236     typedef streamoff	off_type;
    237 
    238     explicit
    239     istringstream(int which=ios::in)
    240       : istream(&sb), sb(which | ios::in)
    241     { }
    242 
    243     explicit
    244     istringstream(const string& str, int which=ios::in)
    245       : istream(&sb), sb(str, which | ios::in)
    246     { }
    247 
    248     stringbuf*
    249     rdbuf() const
    250     {
    251       return const_cast<stringbuf*>(&sb);
    252     }
    253 
    254     string
    255     str() const
    256     {
    257       return rdbuf()->str();
    258     }
    259     void
    260     str(const string& s)
    261     {
    262       rdbuf()->str(s);
    263     }
    264   private:
    265     stringbuf sb;
    266   };
    267 
    268   class ostringstream : public ostream {
    270   public:
    271     typedef char	char_type;
    272     typedef int		int_type;
    273     typedef streampos	pos_type;
    274     typedef streamoff	off_type;
    275 
    276     explicit
    277     ostringstream(int which=ios::out)
    278       : ostream(&sb), sb(which | ios::out)
    279     { }
    280 
    281     explicit
    282     ostringstream(const string& str, int which=ios::out)
    283       : ostream(&sb), sb(str, which | ios::out)
    284     { }
    285 
    286     stringbuf*
    287     rdbuf() const
    288     {
    289       return const_cast<stringbuf*>(&sb);
    290     }
    291 
    292     string
    293     str() const
    294     {
    295       return rdbuf()->str();
    296     }
    297 
    298     void str(const string& s)
    299     {
    300       rdbuf()->str(s);
    301     }
    302   private:
    303     stringbuf sb;
    304   };
    305 
    306   class stringstream : public iostream {
    308   public:
    309     typedef char	char_type;
    310     typedef int		int_type;
    311     typedef streampos	pos_type;
    312     typedef streamoff	off_type;
    313 
    314     explicit
    315     stringstream(int which=ios::out|ios::in)
    316       : iostream(&sb), sb(which)
    317     { }
    318 
    319     explicit
    320     stringstream(const string& str, int which=ios::out|ios::in)
    321       : iostream(&sb), sb(str, which)
    322     { }
    323 
    324     stringbuf*
    325     rdbuf() const
    326     {
    327       return const_cast<stringbuf*>(&sb);
    328     }
    329 
    330     string
    331     str() const
    332     {
    333       return rdbuf()->str();
    334     }
    335 
    336     void
    337     str(const string& s)
    338     {
    339       rdbuf()->str(s);
    340     }
    341   private:
    342     stringbuf sb;
    343   };
    344 };
    345 
    346 #endif /* not __STRSTREAM__ */
    347