# strstream.cc

    00001 // strstream definitions -*- C++ -*-
    00002
    00003 // Copyright (C) 2001, 2002 Free Software Foundation
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 2, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License along
    00017 // with this library; see the file COPYING.  If not, write to the Free
    00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    00019 // USA.
    00020
    00021 // As a special exception, you may use this file as part of a free software
    00022 // library without restriction.  Specifically, if other files instantiate
    00023 // templates or use macros or inline functions from this file, or you compile
    00024 // this file and link it with other files to produce an executable, this
    00025 // file does not by itself cause the resulting executable to be covered by
    00026 // the GNU General Public License.  This exception does not however
    00027 // invalidate any other reasons why the executable file might be covered by
    00028 // the GNU General Public License.
    00029
    00030 /*
    00031  * Copyright (c) 1998
    00032  * Silicon Graphics Computer Systems, Inc.
    00033  *
    00034  * Permission to use, copy, modify, distribute and sell this software
    00035  * and its documentation for any purpose is hereby granted without fee,
    00036  * provided that the above copyright notice appear in all copies and
    00037  * that both that copyright notice and this permission notice appear
    00038  * in supporting documentation.  Silicon Graphics makes no
    00039  * representations about the suitability of this software for any
    00040  * purpose.  It is provided "as is" without express or implied warranty.
    00041  */
    00042
    00043 // Implementation of the classes in header <strstream>.
    00044 // WARNING: The classes defined in <strstream> are DEPRECATED.  This
    00045 // header is defined in section D.7.1 of the C++ standard, and it
    00046 // MAY BE REMOVED in a future standard revision.  You should use the
    00047 // header <sstream> instead.
    00048
    00049 #include <strstream>
    00050 #include <algorithm>
    00051 #include <new>
    00052 #include <stdlib.h>
    00053 #include <string.h>
    00054 #include <limits.h>
    00055
    00056 namespace std
    00057 {
    00058   strstreambuf::strstreambuf(streamsize initial_capacity)
    00059   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true),
    00060     _M_frozen(false), _M_constant(false)
    00061   {
    00062     streamsize n = max(initial_capacity, streamsize(16));
    00063
    00064     char* buf = _M_alloc(n);
    00065     if (buf)
    00066       {
    00067     setp(buf, buf + n);
    00068     setg(buf, buf, buf);
    00069       }
    00070   }
    00071
    00072   strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*))
    00073   : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true),
    00074     _M_frozen(false), _M_constant(false)
    00075   {
    00076     streamsize n = 16;
    00077
    00078     char* buf = _M_alloc(n);
    00079     if (buf)
    00080       {
    00081     setp(buf, buf + n);
    00082     setg(buf, buf, buf);
    00083       }
    00084   }
    00085
    00086   strstreambuf::strstreambuf(char* get, streamsize n, char* put)
    00087   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false),
    00088     _M_frozen(false), _M_constant(false)
    00089   { _M_setup(get, put, n); }
    00090
    00091   strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put)
    00092   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false),
    00093   _M_frozen(false), _M_constant(false)
    00094   { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); }
    00095
    00096   strstreambuf::strstreambuf(unsigned char* get, streamsize n,
    00097                  unsigned char* put)
    00098   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false),
    00099     _M_frozen(false), _M_constant(false)
    00100   { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); }
    00101
    00102   strstreambuf::strstreambuf(const char* get, streamsize n)
    00103   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false),
    00104     _M_frozen(false), _M_constant(true)
    00105   { _M_setup(const_cast<char*>(get), 0, n); }
    00106
    00107   strstreambuf::strstreambuf(const signed char* get, streamsize n)
    00108   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false),
    00109     _M_frozen(false), _M_constant(true)
    00110   { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); }
    00111
    00112   strstreambuf::strstreambuf(const unsigned char* get, streamsize n)
    00113   : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false),
    00114     _M_frozen(false), _M_constant(true)
    00115   { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); }
    00116
    00117   strstreambuf::~strstreambuf()
    00118   {
    00119     if (_M_dynamic && !_M_frozen)
    00120       _M_free(eback());
    00121   }
    00122
    00123   void
    00124   strstreambuf::freeze(bool frozenflag)
    00125   {
    00126     if (_M_dynamic)
    00127       _M_frozen = frozenflag;
    00128   }
    00129
    00130   char*
    00131   strstreambuf::str()
    00132   {
    00133     freeze(true);
    00134     return eback();
    00135   }
    00136
    00137   int
    00138   strstreambuf::pcount() const
    00139   { return pptr() ? pptr() - pbase() : 0; }
    00140
    00141   strstreambuf::int_type
    00142   strstreambuf::overflow(int_type c)
    00143   {
    00144     if (c == traits_type::eof())
    00145       return traits_type::not_eof(c);
    00146
    00147     // Try to expand the buffer.
    00148     if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant)
    00149       {
    00150     ptrdiff_t old_size = epptr() - pbase();
    00151     ptrdiff_t new_size = max(2 * old_size, ptrdiff_t(1));
    00152
    00153     char* buf = _M_alloc(new_size);
    00154     if (buf)
    00155       {
    00156         memcpy(buf, pbase(), old_size);
    00157         char* old_buffer = pbase();
    00158         bool reposition_get = false;
    00159         ptrdiff_t old_get_offset;
    00160         if (gptr() != 0)
    00161           {
    00162         reposition_get = true;
    00163         old_get_offset = gptr() - eback();
    00164           }
    00165
    00166         setp(buf, buf + new_size);
    00167         pbump(old_size);
    00168
    00169         if (reposition_get)
    00170           setg(buf, buf + old_get_offset, buf +
    00171            max(old_get_offset, old_size));
    00172
    00173         _M_free(old_buffer);
    00174       }
    00175       }
    00176
    00177     if (pptr() != epptr())
    00178       {
    00179     *pptr() = c;
    00180     pbump(1);
    00181     return c;
    00182       }
    00183     else
    00184       return traits_type::eof();
    00185   }
    00186
    00187   strstreambuf::int_type
    00188   strstreambuf::pbackfail(int_type c)
    00189   {
    00190     if (gptr() != eback())
    00191       {
    00192       if (c == _Traits::eof())
    00193     {
    00194       gbump(-1);
    00195       return _Traits::not_eof(c);
    00196     }
    00197       else if (c == static_cast<int_type>(gptr()[-1]))
    00198     {  // KLUDGE
    00199       gbump(-1);
    00200       return c;
    00201     }
    00202       else if (!_M_constant)
    00203     {
    00204       gbump(-1);
    00205       *gptr() = c;
    00206       return c;
    00207     }
    00208     }
    00209     return _Traits::eof();
    00210   }
    00211
    00212   strstreambuf::int_type
    00213   strstreambuf::underflow()
    00214   {
    00215     if (gptr() == egptr() && pptr() && pptr() > egptr())
    00216       setg(eback(), gptr(), pptr());
    00217
    00218     if (gptr() != egptr())
    00219       return (unsigned char) *gptr();
    00220     else
    00221       return _Traits::eof();
    00222   }
    00223
    00224   basic_streambuf<char, char_traits<char> >*
    00225   strstreambuf::setbuf(char*, streamsize)
    00226   { return this; }
    00227
    00228   strstreambuf::pos_type
    00229   strstreambuf::seekoff(off_type off, ios_base::seekdir dir,
    00230             ios_base::openmode mode)
    00231   {
    00232     bool do_get = false;
    00233     bool do_put = false;
    00234
    00235     if ((mode & (ios_base::in | ios_base::out))
    00236     == (ios_base::in | ios_base::out) &&
    00237     (dir == ios_base::beg || dir == ios_base::end))
    00238       do_get = do_put = true;
    00239     else if (mode & ios_base::in)
    00240       do_get = true;
    00241     else if (mode & ios_base::out)
    00242       do_put = true;
    00243
    00244     // !gptr() is here because, according to D.7.1 paragraph 4, the seekable
    00245     // area is undefined if there is no get area.
    00246     if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr())
    00247       return pos_type(off_type(-1));
    00248
    00249     char* seeklow  = eback();
    00250     char* seekhigh = epptr() ? epptr() : egptr();
    00251
    00252     off_type newoff;
    00253     switch (dir)
    00254       {
    00255       case ios_base::beg:
    00256     newoff = 0;
    00257     break;
    00258       case ios_base::end:
    00259     newoff = seekhigh - seeklow;
    00260     break;
    00261       case ios_base::cur:
    00262     newoff = do_put ? pptr() - seeklow : gptr() - seeklow;
    00263     break;
    00264       default:
    00265     return pos_type(off_type(-1));
    00266       }
    00267
    00268     off += newoff;
    00269     if (off < 0 || off > seekhigh - seeklow)
    00270       return pos_type(off_type(-1));
    00271
    00272     if (do_put)
    00273       {
    00274     if (seeklow + off < pbase())
    00275       {
    00276         setp(seeklow, epptr());
    00277         pbump(off);
    00278       }
    00279     else
    00280       {
    00281         setp(pbase(), epptr());
    00282         pbump(off - (pbase() - seeklow));
    00283       }
    00284       }
    00285     if (do_get)
    00286       {
    00287     if (off <= egptr() - seeklow)
    00288       setg(seeklow, seeklow + off, egptr());
    00289     else if (off <= pptr() - seeklow)
    00290       setg(seeklow, seeklow + off, pptr());
    00291     else
    00292       setg(seeklow, seeklow + off, epptr());
    00293       }
    00294     return pos_type(newoff);
    00295   }
    00296
    00297   strstreambuf::pos_type
    00298   strstreambuf::seekpos(pos_type pos, ios_base::openmode mode)
    00299   { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); }
    00300
    00301   char*
    00302   strstreambuf::_M_alloc(size_t n)
    00303   {
    00304     if (_M_alloc_fun)
    00305       return static_cast<char*>(_M_alloc_fun(n));
    00306     else
    00307       return new char[n];
    00308   }
    00309
    00310   void
    00311   strstreambuf::_M_free(char* p)
    00312   {
    00313     if (p)
    00314       if (_M_free_fun)
    00315     _M_free_fun(p);
    00316       else
    00317     delete[] p;
    00318   }
    00319
    00320   void
    00321   strstreambuf::_M_setup(char* get, char* put, streamsize n)
    00322   {
    00323     if (get)
    00324       {
    00325     size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX);
    00326
    00327     if (put)
    00328       {
    00329         setg(get, get, put);
    00330         setp(put, put + N);
    00331       }
    00332     else
    00333       setg(get, get, get + N);
    00334       }
    00335   }
    00336
    00337   istrstream::istrstream(char* s)
    00338   : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0)
    00339   { basic_ios<char>::init(&_M_buf); }
    00340
    00341   istrstream::istrstream(const char* s)
    00342   : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0)
    00343   { basic_ios<char>::init(&_M_buf); }
    00344
    00345   istrstream::istrstream(char* s, streamsize n)
    00346   : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n)
    00347   { basic_ios<char>::init(&_M_buf); }
    00348
    00349   istrstream::istrstream(const char* s, streamsize n)
    00350   : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n)
    00351   { basic_ios<char>::init(&_M_buf); }
    00352
    00353   istrstream::~istrstream() { }
    00354
    00355   strstreambuf*
    00356   istrstream::rdbuf() const
    00357   { return const_cast<strstreambuf*>(&_M_buf); }
    00358
    00359   char*
    00360   istrstream::str()
    00361   { return _M_buf.str(); }
    00362
    00363   ostrstream::ostrstream()
    00364   : basic_ios<char>(), basic_ostream<char>(0), _M_buf()
    00365   { basic_ios<char>::init(&_M_buf); }
    00366
    00367   ostrstream::ostrstream(char* s, int n, ios_base::openmode mode)
    00368   : basic_ios<char>(), basic_ostream<char>(0),
    00369     _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s)
    00370   { basic_ios<char>::init(&_M_buf); }
    00371
    00372   ostrstream::~ostrstream() {}
    00373
    00374   strstreambuf*
    00375   ostrstream::rdbuf() const
    00376   { return const_cast<strstreambuf*>(&_M_buf); }
    00377
    00378   void
    00379   ostrstream::freeze(bool freezeflag)
    00380   { _M_buf.freeze(freezeflag); }
    00381
    00382   char*
    00383   ostrstream::str()
    00384   { return _M_buf.str(); }
    00385
    00386   int
    00387   ostrstream::pcount() const
    00388   { return _M_buf.pcount(); }
    00389
    00390   strstream::strstream()
    00391   : basic_ios<char>(), basic_iostream<char>(0), _M_buf()
    00392   { basic_ios<char>::init(&_M_buf); }
    00393
    00394   strstream::strstream(char* s, int n, ios_base::openmode mode)
    00395   : basic_ios<char>(), basic_iostream<char>(0),
    00396     _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s)
    00397   { basic_ios<char>::init(&_M_buf); }
    00398
    00399   strstream::~strstream() { }
    00400
    00401   strstreambuf*
    00402   strstream::rdbuf() const
    00403   { return const_cast<strstreambuf*>(&_M_buf); }
    00404
    00405   void
    00406   strstream::freeze(bool freezeflag)
    00407   { _M_buf.freeze(freezeflag); }
    00408
    00409   int
    00410   strstream::pcount() const
    00411   { return _M_buf.pcount(); }
    00412
    00413   char*
    00414   strstream::str()
    00415   { return _M_buf.str(); }
    00416 } // namespace std