197403Sobrien// strstream definitions -*- C++ -*- 297403Sobrien 3169691Skan// Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation 497403Sobrien// 5103447Skan// This file is part of the GNU ISO C++ Library. This library is free 6103447Skan// software; you can redistribute it and/or modify it under the 7103447Skan// terms of the GNU General Public License as published by the 8103447Skan// Free Software Foundation; either version 2, or (at your option) 997403Sobrien// any later version. 10103447Skan 11103447Skan// This library is distributed in the hope that it will be useful, 1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1497403Sobrien// GNU General Public License for more details. 1597403Sobrien 16103447Skan// You should have received a copy of the GNU General Public License along 17103447Skan// with this library; see the file COPYING. If not, write to the Free 18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19103447Skan// USA. 20103447Skan 2197403Sobrien// As a special exception, you may use this file as part of a free software 2297403Sobrien// library without restriction. Specifically, if other files instantiate 2397403Sobrien// templates or use macros or inline functions from this file, or you compile 2497403Sobrien// this file and link it with other files to produce an executable, this 2597403Sobrien// file does not by itself cause the resulting executable to be covered by 2697403Sobrien// the GNU General Public License. This exception does not however 2797403Sobrien// invalidate any other reasons why the executable file might be covered by 2897403Sobrien// the GNU General Public License. 2997403Sobrien 3097403Sobrien/* 3197403Sobrien * Copyright (c) 1998 3297403Sobrien * Silicon Graphics Computer Systems, Inc. 3397403Sobrien * 3497403Sobrien * Permission to use, copy, modify, distribute and sell this software 3597403Sobrien * and its documentation for any purpose is hereby granted without fee, 3697403Sobrien * provided that the above copyright notice appear in all copies and 3797403Sobrien * that both that copyright notice and this permission notice appear 3897403Sobrien * in supporting documentation. Silicon Graphics makes no 3997403Sobrien * representations about the suitability of this software for any 4097403Sobrien * purpose. It is provided "as is" without express or implied warranty. 4197403Sobrien */ 4297403Sobrien 4397403Sobrien// Implementation of the classes in header <strstream>. 4497403Sobrien// WARNING: The classes defined in <strstream> are DEPRECATED. This 4597403Sobrien// header is defined in section D.7.1 of the C++ standard, and it 4697403Sobrien// MAY BE REMOVED in a future standard revision. You should use the 4797403Sobrien// header <sstream> instead. 4897403Sobrien 49102782Skan#include <strstream> 5097403Sobrien#include <algorithm> 5197403Sobrien#include <new> 5297403Sobrien#include <stdlib.h> 5397403Sobrien#include <string.h> 5497403Sobrien#include <limits.h> 5597403Sobrien 56169691Skan_GLIBCXX_BEGIN_NAMESPACE(std) 57169691Skan 58102782Skan strstreambuf::strstreambuf(streamsize initial_capacity) 59102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), 60102782Skan _M_frozen(false), _M_constant(false) 61102782Skan { 62132720Skan streamsize n = std::max(initial_capacity, streamsize(16)); 63102782Skan 64102782Skan char* buf = _M_alloc(n); 65102782Skan if (buf) 66102782Skan { 67102782Skan setp(buf, buf + n); 68102782Skan setg(buf, buf, buf); 69102782Skan } 7097403Sobrien } 7197403Sobrien 72102782Skan strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) 73102782Skan : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), 74102782Skan _M_frozen(false), _M_constant(false) 75102782Skan { 76102782Skan streamsize n = 16; 7797403Sobrien 78102782Skan char* buf = _M_alloc(n); 79102782Skan if (buf) 80102782Skan { 81102782Skan setp(buf, buf + n); 82102782Skan setg(buf, buf, buf); 83102782Skan } 8497403Sobrien } 8597403Sobrien 86102782Skan strstreambuf::strstreambuf(char* get, streamsize n, char* put) 87102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 88102782Skan _M_frozen(false), _M_constant(false) 89102782Skan { _M_setup(get, put, n); } 9097403Sobrien 91102782Skan strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) 92102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 93102782Skan _M_frozen(false), _M_constant(false) 94102782Skan { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 9597403Sobrien 96102782Skan strstreambuf::strstreambuf(unsigned char* get, streamsize n, 97102782Skan unsigned char* put) 98102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 99102782Skan _M_frozen(false), _M_constant(false) 100102782Skan { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 10197403Sobrien 102102782Skan strstreambuf::strstreambuf(const char* get, streamsize n) 103102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 104102782Skan _M_frozen(false), _M_constant(true) 105102782Skan { _M_setup(const_cast<char*>(get), 0, n); } 10697403Sobrien 107102782Skan strstreambuf::strstreambuf(const signed char* get, streamsize n) 108102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 109102782Skan _M_frozen(false), _M_constant(true) 110102782Skan { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } 11197403Sobrien 112102782Skan strstreambuf::strstreambuf(const unsigned char* get, streamsize n) 113102782Skan : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 114102782Skan _M_frozen(false), _M_constant(true) 115102782Skan { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } 11697403Sobrien 117102782Skan strstreambuf::~strstreambuf() 118102782Skan { 119102782Skan if (_M_dynamic && !_M_frozen) 120102782Skan _M_free(eback()); 121102782Skan } 12297403Sobrien 123102782Skan void 124102782Skan strstreambuf::freeze(bool frozenflag) 125102782Skan { 126102782Skan if (_M_dynamic) 127102782Skan _M_frozen = frozenflag; 128102782Skan } 12997403Sobrien 130102782Skan char* 131102782Skan strstreambuf::str() 132102782Skan { 133102782Skan freeze(true); 134102782Skan return eback(); 135102782Skan } 13697403Sobrien 137102782Skan int 138102782Skan strstreambuf::pcount() const 139102782Skan { return pptr() ? pptr() - pbase() : 0; } 14097403Sobrien 141102782Skan strstreambuf::int_type 142102782Skan strstreambuf::overflow(int_type c) 143102782Skan { 144102782Skan if (c == traits_type::eof()) 145102782Skan return traits_type::not_eof(c); 146102782Skan 147102782Skan // Try to expand the buffer. 148102782Skan if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) 149102782Skan { 150102782Skan ptrdiff_t old_size = epptr() - pbase(); 151132720Skan ptrdiff_t new_size = std::max(ptrdiff_t(2 * old_size), ptrdiff_t(1)); 152102782Skan 153102782Skan char* buf = _M_alloc(new_size); 154102782Skan if (buf) 155102782Skan { 156102782Skan memcpy(buf, pbase(), old_size); 157102782Skan char* old_buffer = pbase(); 158102782Skan bool reposition_get = false; 159102782Skan ptrdiff_t old_get_offset; 160102782Skan if (gptr() != 0) 161102782Skan { 162102782Skan reposition_get = true; 163102782Skan old_get_offset = gptr() - eback(); 164102782Skan } 165102782Skan 166102782Skan setp(buf, buf + new_size); 167102782Skan pbump(old_size); 16897403Sobrien 169102782Skan if (reposition_get) 170102782Skan setg(buf, buf + old_get_offset, buf + 171132720Skan std::max(old_get_offset, old_size)); 17297403Sobrien 173102782Skan _M_free(old_buffer); 174102782Skan } 17597403Sobrien } 176102782Skan 177102782Skan if (pptr() != epptr()) 178102782Skan { 179102782Skan *pptr() = c; 180102782Skan pbump(1); 181102782Skan return c; 182102782Skan } 183102782Skan else 184102782Skan return traits_type::eof(); 185102782Skan } 18697403Sobrien 187102782Skan strstreambuf::int_type 188102782Skan strstreambuf::pbackfail(int_type c) 189102782Skan { 190102782Skan if (gptr() != eback()) 191102782Skan { 192102782Skan if (c == _Traits::eof()) 193102782Skan { 194102782Skan gbump(-1); 195102782Skan return _Traits::not_eof(c); 196102782Skan } 197132720Skan else if (c == _Traits::to_int_type(gptr()[-1])) 198102782Skan { // KLUDGE 199102782Skan gbump(-1); 200102782Skan return c; 201102782Skan } 202102782Skan else if (!_M_constant) 203102782Skan { 204102782Skan gbump(-1); 205102782Skan *gptr() = c; 206102782Skan return c; 207102782Skan } 20897403Sobrien } 209102782Skan return _Traits::eof(); 21097403Sobrien } 21197403Sobrien 212102782Skan strstreambuf::int_type 213102782Skan strstreambuf::underflow() 214102782Skan { 215102782Skan if (gptr() == egptr() && pptr() && pptr() > egptr()) 216102782Skan setg(eback(), gptr(), pptr()); 217102782Skan 218102782Skan if (gptr() != egptr()) 219102782Skan return (unsigned char) *gptr(); 220102782Skan else 221102782Skan return _Traits::eof(); 22297403Sobrien } 22397403Sobrien 224102782Skan basic_streambuf<char, char_traits<char> >* 225102782Skan strstreambuf::setbuf(char*, streamsize) 226102782Skan { return this; } 22797403Sobrien 228102782Skan strstreambuf::pos_type 229102782Skan strstreambuf::seekoff(off_type off, ios_base::seekdir dir, 230102782Skan ios_base::openmode mode) 231102782Skan { 232102782Skan bool do_get = false; 233102782Skan bool do_put = false; 23497403Sobrien 235102782Skan if ((mode & (ios_base::in | ios_base::out)) 236102782Skan == (ios_base::in | ios_base::out) && 237102782Skan (dir == ios_base::beg || dir == ios_base::end)) 238102782Skan do_get = do_put = true; 239102782Skan else if (mode & ios_base::in) 240102782Skan do_get = true; 241102782Skan else if (mode & ios_base::out) 242102782Skan do_put = true; 24397403Sobrien 244102782Skan // !gptr() is here because, according to D.7.1 paragraph 4, the seekable 245102782Skan // area is undefined if there is no get area. 246102782Skan if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr()) 247102782Skan return pos_type(off_type(-1)); 24897403Sobrien 249102782Skan char* seeklow = eback(); 250102782Skan char* seekhigh = epptr() ? epptr() : egptr(); 25197403Sobrien 252102782Skan off_type newoff; 253102782Skan switch (dir) 254102782Skan { 255102782Skan case ios_base::beg: 256102782Skan newoff = 0; 257102782Skan break; 258102782Skan case ios_base::end: 259102782Skan newoff = seekhigh - seeklow; 260102782Skan break; 261102782Skan case ios_base::cur: 262102782Skan newoff = do_put ? pptr() - seeklow : gptr() - seeklow; 263102782Skan break; 264102782Skan default: 265102782Skan return pos_type(off_type(-1)); 266102782Skan } 267102782Skan 268102782Skan off += newoff; 269102782Skan if (off < 0 || off > seekhigh - seeklow) 270102782Skan return pos_type(off_type(-1)); 27197403Sobrien 272102782Skan if (do_put) 273102782Skan { 274102782Skan if (seeklow + off < pbase()) 275102782Skan { 276102782Skan setp(seeklow, epptr()); 277102782Skan pbump(off); 278102782Skan } 279102782Skan else 280102782Skan { 281102782Skan setp(pbase(), epptr()); 282102782Skan pbump(off - (pbase() - seeklow)); 283102782Skan } 284102782Skan } 285102782Skan if (do_get) 286102782Skan { 287102782Skan if (off <= egptr() - seeklow) 288102782Skan setg(seeklow, seeklow + off, egptr()); 289102782Skan else if (off <= pptr() - seeklow) 290102782Skan setg(seeklow, seeklow + off, pptr()); 291102782Skan else 292102782Skan setg(seeklow, seeklow + off, epptr()); 293102782Skan } 294102782Skan return pos_type(newoff); 29597403Sobrien } 29697403Sobrien 297102782Skan strstreambuf::pos_type 298102782Skan strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) 299102782Skan { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); } 30097403Sobrien 301102782Skan char* 302102782Skan strstreambuf::_M_alloc(size_t n) 303102782Skan { 304102782Skan if (_M_alloc_fun) 305102782Skan return static_cast<char*>(_M_alloc_fun(n)); 30697403Sobrien else 307102782Skan return new char[n]; 30897403Sobrien } 30997403Sobrien 310102782Skan void 311102782Skan strstreambuf::_M_free(char* p) 312102782Skan { 313102782Skan if (p) 314242347Sdim { 315242347Sdim if (_M_free_fun) 316242347Sdim _M_free_fun(p); 317242347Sdim else 318242347Sdim delete[] p; 319242347Sdim } 320102782Skan } 32197403Sobrien 322102782Skan void 323102782Skan strstreambuf::_M_setup(char* get, char* put, streamsize n) 324102782Skan { 325102782Skan if (get) 326102782Skan { 327102782Skan size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX); 328102782Skan 329102782Skan if (put) 330102782Skan { 331102782Skan setg(get, get, put); 332102782Skan setp(put, put + N); 333102782Skan } 334102782Skan else 335102782Skan setg(get, get, get + N); 336102782Skan } 33797403Sobrien } 33897403Sobrien 339102782Skan istrstream::istrstream(char* s) 34097403Sobrien : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 341102782Skan { basic_ios<char>::init(&_M_buf); } 34297403Sobrien 343102782Skan istrstream::istrstream(const char* s) 34497403Sobrien : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 345102782Skan { basic_ios<char>::init(&_M_buf); } 34697403Sobrien 347102782Skan istrstream::istrstream(char* s, streamsize n) 34897403Sobrien : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 349102782Skan { basic_ios<char>::init(&_M_buf); } 35097403Sobrien 351102782Skan istrstream::istrstream(const char* s, streamsize n) 35297403Sobrien : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 353102782Skan { basic_ios<char>::init(&_M_buf); } 35497403Sobrien 355102782Skan istrstream::~istrstream() { } 35697403Sobrien 357102782Skan strstreambuf* 358102782Skan istrstream::rdbuf() const 359102782Skan { return const_cast<strstreambuf*>(&_M_buf); } 36097403Sobrien 361102782Skan char* 362102782Skan istrstream::str() 363102782Skan { return _M_buf.str(); } 36497403Sobrien 365102782Skan ostrstream::ostrstream() 36697403Sobrien : basic_ios<char>(), basic_ostream<char>(0), _M_buf() 367102782Skan { basic_ios<char>::init(&_M_buf); } 36897403Sobrien 369102782Skan ostrstream::ostrstream(char* s, int n, ios_base::openmode mode) 370102782Skan : basic_ios<char>(), basic_ostream<char>(0), 37197403Sobrien _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 372102782Skan { basic_ios<char>::init(&_M_buf); } 37397403Sobrien 374102782Skan ostrstream::~ostrstream() {} 37597403Sobrien 376102782Skan strstreambuf* 377102782Skan ostrstream::rdbuf() const 378102782Skan { return const_cast<strstreambuf*>(&_M_buf); } 37997403Sobrien 380102782Skan void 381102782Skan ostrstream::freeze(bool freezeflag) 382102782Skan { _M_buf.freeze(freezeflag); } 38397403Sobrien 384102782Skan char* 385102782Skan ostrstream::str() 386102782Skan { return _M_buf.str(); } 38797403Sobrien 388102782Skan int 389102782Skan ostrstream::pcount() const 390102782Skan { return _M_buf.pcount(); } 39197403Sobrien 392102782Skan strstream::strstream() 39397403Sobrien : basic_ios<char>(), basic_iostream<char>(0), _M_buf() 394102782Skan { basic_ios<char>::init(&_M_buf); } 39597403Sobrien 396102782Skan strstream::strstream(char* s, int n, ios_base::openmode mode) 397102782Skan : basic_ios<char>(), basic_iostream<char>(0), 39897403Sobrien _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 399102782Skan { basic_ios<char>::init(&_M_buf); } 40097403Sobrien 401102782Skan strstream::~strstream() { } 40297403Sobrien 403102782Skan strstreambuf* 404102782Skan strstream::rdbuf() const 405102782Skan { return const_cast<strstreambuf*>(&_M_buf); } 40697403Sobrien 407102782Skan void 408102782Skan strstream::freeze(bool freezeflag) 409102782Skan { _M_buf.freeze(freezeflag); } 41097403Sobrien 411102782Skan int 412102782Skan strstream::pcount() const 413102782Skan { return _M_buf.pcount(); } 41497403Sobrien 415102782Skan char* 416102782Skan strstream::str() 417102782Skan { return _M_buf.str(); } 418169691Skan 419169691Skan_GLIBCXX_END_NAMESPACE 420