# strstream.cc

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