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:

Generated on Wed May 1 19:19:38 2002 for libstdc++-v3 Source by doxygen1.2.15