strstream.cc

00001 // strstream definitions -*- C++ -*-
00002 
00003 // Copyright (C) 2001, 2002, 2003 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 = std::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 = std::max(ptrdiff_t(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            std::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 == _Traits::to_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

Generated on Fri May 6 01:09:14 2005 for libstdc++-v3 Source by  doxygen 1.4.2