1*03a78d15Sespie // strstream definitions -*- C++ -*- 2*03a78d15Sespie 3*03a78d15Sespie // Copyright (C) 2001, 2002, 2003 Free Software Foundation 4*03a78d15Sespie // 5*03a78d15Sespie // This file is part of the GNU ISO C++ Library. This library is free 6*03a78d15Sespie // software; you can redistribute it and/or modify it under the 7*03a78d15Sespie // terms of the GNU General Public License as published by the 8*03a78d15Sespie // Free Software Foundation; either version 2, or (at your option) 9*03a78d15Sespie // any later version. 10*03a78d15Sespie 11*03a78d15Sespie // This library is distributed in the hope that it will be useful, 12*03a78d15Sespie // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*03a78d15Sespie // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*03a78d15Sespie // GNU General Public License for more details. 15*03a78d15Sespie 16*03a78d15Sespie // You should have received a copy of the GNU General Public License along 17*03a78d15Sespie // with this library; see the file COPYING. If not, write to the Free 18*03a78d15Sespie // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19*03a78d15Sespie // USA. 20*03a78d15Sespie 21*03a78d15Sespie // As a special exception, you may use this file as part of a free software 22*03a78d15Sespie // library without restriction. Specifically, if other files instantiate 23*03a78d15Sespie // templates or use macros or inline functions from this file, or you compile 24*03a78d15Sespie // this file and link it with other files to produce an executable, this 25*03a78d15Sespie // file does not by itself cause the resulting executable to be covered by 26*03a78d15Sespie // the GNU General Public License. This exception does not however 27*03a78d15Sespie // invalidate any other reasons why the executable file might be covered by 28*03a78d15Sespie // the GNU General Public License. 29*03a78d15Sespie 30*03a78d15Sespie /* 31*03a78d15Sespie * Copyright (c) 1998 32*03a78d15Sespie * Silicon Graphics Computer Systems, Inc. 33*03a78d15Sespie * 34*03a78d15Sespie * Permission to use, copy, modify, distribute and sell this software 35*03a78d15Sespie * and its documentation for any purpose is hereby granted without fee, 36*03a78d15Sespie * provided that the above copyright notice appear in all copies and 37*03a78d15Sespie * that both that copyright notice and this permission notice appear 38*03a78d15Sespie * in supporting documentation. Silicon Graphics makes no 39*03a78d15Sespie * representations about the suitability of this software for any 40*03a78d15Sespie * purpose. It is provided "as is" without express or implied warranty. 41*03a78d15Sespie */ 42*03a78d15Sespie 43*03a78d15Sespie // Implementation of the classes in header <strstream>. 44*03a78d15Sespie // WARNING: The classes defined in <strstream> are DEPRECATED. This 45*03a78d15Sespie // header is defined in section D.7.1 of the C++ standard, and it 46*03a78d15Sespie // MAY BE REMOVED in a future standard revision. You should use the 47*03a78d15Sespie // header <sstream> instead. 48*03a78d15Sespie 49*03a78d15Sespie #include <strstream> 50*03a78d15Sespie #include <algorithm> 51*03a78d15Sespie #include <new> 52*03a78d15Sespie #include <stdlib.h> 53*03a78d15Sespie #include <string.h> 54*03a78d15Sespie #include <limits.h> 55*03a78d15Sespie 56*03a78d15Sespie namespace std 57*03a78d15Sespie { strstreambuf(streamsize initial_capacity)58*03a78d15Sespie strstreambuf::strstreambuf(streamsize initial_capacity) 59*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), 60*03a78d15Sespie _M_frozen(false), _M_constant(false) 61*03a78d15Sespie { 62*03a78d15Sespie streamsize n = max(initial_capacity, streamsize(16)); 63*03a78d15Sespie 64*03a78d15Sespie char* buf = _M_alloc(n); 65*03a78d15Sespie if (buf) 66*03a78d15Sespie { 67*03a78d15Sespie setp(buf, buf + n); 68*03a78d15Sespie setg(buf, buf, buf); 69*03a78d15Sespie } 70*03a78d15Sespie } 71*03a78d15Sespie strstreambuf(void * (* alloc_f)(size_t),void (* free_f)(void *))72*03a78d15Sespie strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) 73*03a78d15Sespie : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), 74*03a78d15Sespie _M_frozen(false), _M_constant(false) 75*03a78d15Sespie { 76*03a78d15Sespie streamsize n = 16; 77*03a78d15Sespie 78*03a78d15Sespie char* buf = _M_alloc(n); 79*03a78d15Sespie if (buf) 80*03a78d15Sespie { 81*03a78d15Sespie setp(buf, buf + n); 82*03a78d15Sespie setg(buf, buf, buf); 83*03a78d15Sespie } 84*03a78d15Sespie } 85*03a78d15Sespie strstreambuf(char * get,streamsize n,char * put)86*03a78d15Sespie strstreambuf::strstreambuf(char* get, streamsize n, char* put) 87*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 88*03a78d15Sespie _M_frozen(false), _M_constant(false) 89*03a78d15Sespie { _M_setup(get, put, n); } 90*03a78d15Sespie strstreambuf(signed char * get,streamsize n,signed char * put)91*03a78d15Sespie strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) 92*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 93*03a78d15Sespie _M_frozen(false), _M_constant(false) 94*03a78d15Sespie { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 95*03a78d15Sespie strstreambuf(unsigned char * get,streamsize n,unsigned char * put)96*03a78d15Sespie strstreambuf::strstreambuf(unsigned char* get, streamsize n, 97*03a78d15Sespie unsigned char* put) 98*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 99*03a78d15Sespie _M_frozen(false), _M_constant(false) 100*03a78d15Sespie { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 101*03a78d15Sespie strstreambuf(const char * get,streamsize n)102*03a78d15Sespie strstreambuf::strstreambuf(const char* get, streamsize n) 103*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 104*03a78d15Sespie _M_frozen(false), _M_constant(true) 105*03a78d15Sespie { _M_setup(const_cast<char*>(get), 0, n); } 106*03a78d15Sespie strstreambuf(const signed char * get,streamsize n)107*03a78d15Sespie strstreambuf::strstreambuf(const signed char* get, streamsize n) 108*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 109*03a78d15Sespie _M_frozen(false), _M_constant(true) 110*03a78d15Sespie { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } 111*03a78d15Sespie strstreambuf(const unsigned char * get,streamsize n)112*03a78d15Sespie strstreambuf::strstreambuf(const unsigned char* get, streamsize n) 113*03a78d15Sespie : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 114*03a78d15Sespie _M_frozen(false), _M_constant(true) 115*03a78d15Sespie { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } 116*03a78d15Sespie ~strstreambuf()117*03a78d15Sespie strstreambuf::~strstreambuf() 118*03a78d15Sespie { 119*03a78d15Sespie if (_M_dynamic && !_M_frozen) 120*03a78d15Sespie _M_free(eback()); 121*03a78d15Sespie } 122*03a78d15Sespie 123*03a78d15Sespie void freeze(bool frozenflag)124*03a78d15Sespie strstreambuf::freeze(bool frozenflag) 125*03a78d15Sespie { 126*03a78d15Sespie if (_M_dynamic) 127*03a78d15Sespie _M_frozen = frozenflag; 128*03a78d15Sespie } 129*03a78d15Sespie 130*03a78d15Sespie char* str()131*03a78d15Sespie strstreambuf::str() 132*03a78d15Sespie { 133*03a78d15Sespie freeze(true); 134*03a78d15Sespie return eback(); 135*03a78d15Sespie } 136*03a78d15Sespie 137*03a78d15Sespie int pcount() const138*03a78d15Sespie strstreambuf::pcount() const 139*03a78d15Sespie { return pptr() ? pptr() - pbase() : 0; } 140*03a78d15Sespie 141*03a78d15Sespie strstreambuf::int_type overflow(int_type c)142*03a78d15Sespie strstreambuf::overflow(int_type c) 143*03a78d15Sespie { 144*03a78d15Sespie if (c == traits_type::eof()) 145*03a78d15Sespie return traits_type::not_eof(c); 146*03a78d15Sespie 147*03a78d15Sespie // Try to expand the buffer. 148*03a78d15Sespie if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) 149*03a78d15Sespie { 150*03a78d15Sespie ptrdiff_t old_size = epptr() - pbase(); 151*03a78d15Sespie ptrdiff_t new_size = max(ptrdiff_t(2 * old_size), ptrdiff_t(1)); 152*03a78d15Sespie 153*03a78d15Sespie char* buf = _M_alloc(new_size); 154*03a78d15Sespie if (buf) 155*03a78d15Sespie { 156*03a78d15Sespie memcpy(buf, pbase(), old_size); 157*03a78d15Sespie char* old_buffer = pbase(); 158*03a78d15Sespie bool reposition_get = false; 159*03a78d15Sespie ptrdiff_t old_get_offset; 160*03a78d15Sespie if (gptr() != 0) 161*03a78d15Sespie { 162*03a78d15Sespie reposition_get = true; 163*03a78d15Sespie old_get_offset = gptr() - eback(); 164*03a78d15Sespie } 165*03a78d15Sespie 166*03a78d15Sespie setp(buf, buf + new_size); 167*03a78d15Sespie pbump(old_size); 168*03a78d15Sespie 169*03a78d15Sespie if (reposition_get) 170*03a78d15Sespie setg(buf, buf + old_get_offset, buf + 171*03a78d15Sespie max(old_get_offset, old_size)); 172*03a78d15Sespie 173*03a78d15Sespie _M_free(old_buffer); 174*03a78d15Sespie } 175*03a78d15Sespie } 176*03a78d15Sespie 177*03a78d15Sespie if (pptr() != epptr()) 178*03a78d15Sespie { 179*03a78d15Sespie *pptr() = c; 180*03a78d15Sespie pbump(1); 181*03a78d15Sespie return c; 182*03a78d15Sespie } 183*03a78d15Sespie else 184*03a78d15Sespie return traits_type::eof(); 185*03a78d15Sespie } 186*03a78d15Sespie 187*03a78d15Sespie strstreambuf::int_type pbackfail(int_type c)188*03a78d15Sespie strstreambuf::pbackfail(int_type c) 189*03a78d15Sespie { 190*03a78d15Sespie if (gptr() != eback()) 191*03a78d15Sespie { 192*03a78d15Sespie if (c == _Traits::eof()) 193*03a78d15Sespie { 194*03a78d15Sespie gbump(-1); 195*03a78d15Sespie return _Traits::not_eof(c); 196*03a78d15Sespie } 197*03a78d15Sespie else if (c == static_cast<int_type>(gptr()[-1])) 198*03a78d15Sespie { // KLUDGE 199*03a78d15Sespie gbump(-1); 200*03a78d15Sespie return c; 201*03a78d15Sespie } 202*03a78d15Sespie else if (!_M_constant) 203*03a78d15Sespie { 204*03a78d15Sespie gbump(-1); 205*03a78d15Sespie *gptr() = c; 206*03a78d15Sespie return c; 207*03a78d15Sespie } 208*03a78d15Sespie } 209*03a78d15Sespie return _Traits::eof(); 210*03a78d15Sespie } 211*03a78d15Sespie 212*03a78d15Sespie strstreambuf::int_type underflow()213*03a78d15Sespie strstreambuf::underflow() 214*03a78d15Sespie { 215*03a78d15Sespie if (gptr() == egptr() && pptr() && pptr() > egptr()) 216*03a78d15Sespie setg(eback(), gptr(), pptr()); 217*03a78d15Sespie 218*03a78d15Sespie if (gptr() != egptr()) 219*03a78d15Sespie return (unsigned char) *gptr(); 220*03a78d15Sespie else 221*03a78d15Sespie return _Traits::eof(); 222*03a78d15Sespie } 223*03a78d15Sespie 224*03a78d15Sespie basic_streambuf<char, char_traits<char> >* setbuf(char *,streamsize)225*03a78d15Sespie strstreambuf::setbuf(char*, streamsize) 226*03a78d15Sespie { return this; } 227*03a78d15Sespie 228*03a78d15Sespie strstreambuf::pos_type seekoff(off_type off,ios_base::seekdir dir,ios_base::openmode mode)229*03a78d15Sespie strstreambuf::seekoff(off_type off, ios_base::seekdir dir, 230*03a78d15Sespie ios_base::openmode mode) 231*03a78d15Sespie { 232*03a78d15Sespie bool do_get = false; 233*03a78d15Sespie bool do_put = false; 234*03a78d15Sespie 235*03a78d15Sespie if ((mode & (ios_base::in | ios_base::out)) 236*03a78d15Sespie == (ios_base::in | ios_base::out) && 237*03a78d15Sespie (dir == ios_base::beg || dir == ios_base::end)) 238*03a78d15Sespie do_get = do_put = true; 239*03a78d15Sespie else if (mode & ios_base::in) 240*03a78d15Sespie do_get = true; 241*03a78d15Sespie else if (mode & ios_base::out) 242*03a78d15Sespie do_put = true; 243*03a78d15Sespie 244*03a78d15Sespie // !gptr() is here because, according to D.7.1 paragraph 4, the seekable 245*03a78d15Sespie // area is undefined if there is no get area. 246*03a78d15Sespie if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr()) 247*03a78d15Sespie return pos_type(off_type(-1)); 248*03a78d15Sespie 249*03a78d15Sespie char* seeklow = eback(); 250*03a78d15Sespie char* seekhigh = epptr() ? epptr() : egptr(); 251*03a78d15Sespie 252*03a78d15Sespie off_type newoff; 253*03a78d15Sespie switch (dir) 254*03a78d15Sespie { 255*03a78d15Sespie case ios_base::beg: 256*03a78d15Sespie newoff = 0; 257*03a78d15Sespie break; 258*03a78d15Sespie case ios_base::end: 259*03a78d15Sespie newoff = seekhigh - seeklow; 260*03a78d15Sespie break; 261*03a78d15Sespie case ios_base::cur: 262*03a78d15Sespie newoff = do_put ? pptr() - seeklow : gptr() - seeklow; 263*03a78d15Sespie break; 264*03a78d15Sespie default: 265*03a78d15Sespie return pos_type(off_type(-1)); 266*03a78d15Sespie } 267*03a78d15Sespie 268*03a78d15Sespie off += newoff; 269*03a78d15Sespie if (off < 0 || off > seekhigh - seeklow) 270*03a78d15Sespie return pos_type(off_type(-1)); 271*03a78d15Sespie 272*03a78d15Sespie if (do_put) 273*03a78d15Sespie { 274*03a78d15Sespie if (seeklow + off < pbase()) 275*03a78d15Sespie { 276*03a78d15Sespie setp(seeklow, epptr()); 277*03a78d15Sespie pbump(off); 278*03a78d15Sespie } 279*03a78d15Sespie else 280*03a78d15Sespie { 281*03a78d15Sespie setp(pbase(), epptr()); 282*03a78d15Sespie pbump(off - (pbase() - seeklow)); 283*03a78d15Sespie } 284*03a78d15Sespie } 285*03a78d15Sespie if (do_get) 286*03a78d15Sespie { 287*03a78d15Sespie if (off <= egptr() - seeklow) 288*03a78d15Sespie setg(seeklow, seeklow + off, egptr()); 289*03a78d15Sespie else if (off <= pptr() - seeklow) 290*03a78d15Sespie setg(seeklow, seeklow + off, pptr()); 291*03a78d15Sespie else 292*03a78d15Sespie setg(seeklow, seeklow + off, epptr()); 293*03a78d15Sespie } 294*03a78d15Sespie return pos_type(newoff); 295*03a78d15Sespie } 296*03a78d15Sespie 297*03a78d15Sespie strstreambuf::pos_type seekpos(pos_type pos,ios_base::openmode mode)298*03a78d15Sespie strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) 299*03a78d15Sespie { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); } 300*03a78d15Sespie 301*03a78d15Sespie char* _M_alloc(size_t n)302*03a78d15Sespie strstreambuf::_M_alloc(size_t n) 303*03a78d15Sespie { 304*03a78d15Sespie if (_M_alloc_fun) 305*03a78d15Sespie return static_cast<char*>(_M_alloc_fun(n)); 306*03a78d15Sespie else 307*03a78d15Sespie return new char[n]; 308*03a78d15Sespie } 309*03a78d15Sespie 310*03a78d15Sespie void _M_free(char * p)311*03a78d15Sespie strstreambuf::_M_free(char* p) 312*03a78d15Sespie { 313*03a78d15Sespie if (p) 314*03a78d15Sespie if (_M_free_fun) 315*03a78d15Sespie _M_free_fun(p); 316*03a78d15Sespie else 317*03a78d15Sespie delete[] p; 318*03a78d15Sespie } 319*03a78d15Sespie 320*03a78d15Sespie void _M_setup(char * get,char * put,streamsize n)321*03a78d15Sespie strstreambuf::_M_setup(char* get, char* put, streamsize n) 322*03a78d15Sespie { 323*03a78d15Sespie if (get) 324*03a78d15Sespie { 325*03a78d15Sespie size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX); 326*03a78d15Sespie 327*03a78d15Sespie if (put) 328*03a78d15Sespie { 329*03a78d15Sespie setg(get, get, put); 330*03a78d15Sespie setp(put, put + N); 331*03a78d15Sespie } 332*03a78d15Sespie else 333*03a78d15Sespie setg(get, get, get + N); 334*03a78d15Sespie } 335*03a78d15Sespie } 336*03a78d15Sespie istrstream(char * s)337*03a78d15Sespie istrstream::istrstream(char* s) 338*03a78d15Sespie : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 339*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 340*03a78d15Sespie istrstream(const char * s)341*03a78d15Sespie istrstream::istrstream(const char* s) 342*03a78d15Sespie : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 343*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 344*03a78d15Sespie istrstream(char * s,streamsize n)345*03a78d15Sespie istrstream::istrstream(char* s, streamsize n) 346*03a78d15Sespie : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 347*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 348*03a78d15Sespie istrstream(const char * s,streamsize n)349*03a78d15Sespie istrstream::istrstream(const char* s, streamsize n) 350*03a78d15Sespie : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 351*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 352*03a78d15Sespie ~istrstream()353*03a78d15Sespie istrstream::~istrstream() { } 354*03a78d15Sespie 355*03a78d15Sespie strstreambuf* rdbuf() const356*03a78d15Sespie istrstream::rdbuf() const 357*03a78d15Sespie { return const_cast<strstreambuf*>(&_M_buf); } 358*03a78d15Sespie 359*03a78d15Sespie char* str()360*03a78d15Sespie istrstream::str() 361*03a78d15Sespie { return _M_buf.str(); } 362*03a78d15Sespie ostrstream()363*03a78d15Sespie ostrstream::ostrstream() 364*03a78d15Sespie : basic_ios<char>(), basic_ostream<char>(0), _M_buf() 365*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 366*03a78d15Sespie ostrstream(char * s,int n,ios_base::openmode mode)367*03a78d15Sespie ostrstream::ostrstream(char* s, int n, ios_base::openmode mode) 368*03a78d15Sespie : basic_ios<char>(), basic_ostream<char>(0), 369*03a78d15Sespie _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 370*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 371*03a78d15Sespie ~ostrstream()372*03a78d15Sespie ostrstream::~ostrstream() {} 373*03a78d15Sespie 374*03a78d15Sespie strstreambuf* rdbuf() const375*03a78d15Sespie ostrstream::rdbuf() const 376*03a78d15Sespie { return const_cast<strstreambuf*>(&_M_buf); } 377*03a78d15Sespie 378*03a78d15Sespie void freeze(bool freezeflag)379*03a78d15Sespie ostrstream::freeze(bool freezeflag) 380*03a78d15Sespie { _M_buf.freeze(freezeflag); } 381*03a78d15Sespie 382*03a78d15Sespie char* str()383*03a78d15Sespie ostrstream::str() 384*03a78d15Sespie { return _M_buf.str(); } 385*03a78d15Sespie 386*03a78d15Sespie int pcount() const387*03a78d15Sespie ostrstream::pcount() const 388*03a78d15Sespie { return _M_buf.pcount(); } 389*03a78d15Sespie strstream()390*03a78d15Sespie strstream::strstream() 391*03a78d15Sespie : basic_ios<char>(), basic_iostream<char>(0), _M_buf() 392*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 393*03a78d15Sespie strstream(char * s,int n,ios_base::openmode mode)394*03a78d15Sespie strstream::strstream(char* s, int n, ios_base::openmode mode) 395*03a78d15Sespie : basic_ios<char>(), basic_iostream<char>(0), 396*03a78d15Sespie _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 397*03a78d15Sespie { basic_ios<char>::init(&_M_buf); } 398*03a78d15Sespie ~strstream()399*03a78d15Sespie strstream::~strstream() { } 400*03a78d15Sespie 401*03a78d15Sespie strstreambuf* rdbuf() const402*03a78d15Sespie strstream::rdbuf() const 403*03a78d15Sespie { return const_cast<strstreambuf*>(&_M_buf); } 404*03a78d15Sespie 405*03a78d15Sespie void freeze(bool freezeflag)406*03a78d15Sespie strstream::freeze(bool freezeflag) 407*03a78d15Sespie { _M_buf.freeze(freezeflag); } 408*03a78d15Sespie 409*03a78d15Sespie int pcount() const410*03a78d15Sespie strstream::pcount() const 411*03a78d15Sespie { return _M_buf.pcount(); } 412*03a78d15Sespie 413*03a78d15Sespie char* str()414*03a78d15Sespie strstream::str() 415*03a78d15Sespie { return _M_buf.str(); } 416*03a78d15Sespie } // namespace std 417