strstream.cc revision 117397
1234353Sdim// strstream definitions -*- C++ -*- 2193323Sed 3193323Sed// Copyright (C) 2001, 2002, 2003 Free Software Foundation 4193323Sed// 5193323Sed// This file is part of the GNU ISO C++ Library. This library is free 6193323Sed// software; you can redistribute it and/or modify it under the 7193323Sed// terms of the GNU General Public License as published by the 8193323Sed// Free Software Foundation; either version 2, or (at your option) 9193323Sed// any later version. 10193323Sed 11193323Sed// This library is distributed in the hope that it will be useful, 12193323Sed// but WITHOUT ANY WARRANTY; without even the implied warranty of 13193323Sed// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14193323Sed// GNU General Public License for more details. 15193323Sed 16193323Sed// You should have received a copy of the GNU General Public License along 17193323Sed// with this library; see the file COPYING. If not, write to the Free 18193323Sed// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19193323Sed// USA. 20193323Sed 21193323Sed// As a special exception, you may use this file as part of a free software 22193323Sed// library without restriction. Specifically, if other files instantiate 23193323Sed// templates or use macros or inline functions from this file, or you compile 24193323Sed// this file and link it with other files to produce an executable, this 25193323Sed// file does not by itself cause the resulting executable to be covered by 26193323Sed// the GNU General Public License. This exception does not however 27193323Sed// invalidate any other reasons why the executable file might be covered by 28193323Sed// the GNU General Public License. 29193323Sed 30200581Srdivacky/* 31200581Srdivacky * Copyright (c) 1998 32200581Srdivacky * Silicon Graphics Computer Systems, Inc. 33193323Sed * 34193323Sed * Permission to use, copy, modify, distribute and sell this software 35193323Sed * and its documentation for any purpose is hereby granted without fee, 36193323Sed * provided that the above copyright notice appear in all copies and 37193323Sed * that both that copyright notice and this permission notice appear 38193323Sed * in supporting documentation. Silicon Graphics makes no 39198090Srdivacky * representations about the suitability of this software for any 40193323Sed * purpose. It is provided "as is" without express or implied warranty. 41193323Sed */ 42193323Sed 43193323Sed// Implementation of the classes in header <strstream>. 44193323Sed// WARNING: The classes defined in <strstream> are DEPRECATED. This 45193323Sed// header is defined in section D.7.1 of the C++ standard, and it 46193323Sed// MAY BE REMOVED in a future standard revision. You should use the 47193323Sed// header <sstream> instead. 48193323Sed 49193323Sed#include <strstream> 50200581Srdivacky#include <algorithm> 51193323Sed#include <new> 52193323Sed#include <stdlib.h> 53193323Sed#include <string.h> 54193323Sed#include <limits.h> 55193323Sed 56193323Sednamespace std 57193323Sed{ 58193323Sed strstreambuf::strstreambuf(streamsize initial_capacity) 59193323Sed : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), 60200581Srdivacky _M_frozen(false), _M_constant(false) 61193323Sed { 62200581Srdivacky streamsize n = max(initial_capacity, streamsize(16)); 63200581Srdivacky 64200581Srdivacky char* buf = _M_alloc(n); 65200581Srdivacky if (buf) 66193323Sed { 67193323Sed setp(buf, buf + n); 68193323Sed setg(buf, buf, buf); 69193323Sed } 70193323Sed } 71193323Sed 72193323Sed strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) 73193323Sed : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), 74193323Sed _M_frozen(false), _M_constant(false) 75193323Sed { 76249423Sdim streamsize n = 16; 77219077Sdim 78193323Sed char* buf = _M_alloc(n); 79207618Srdivacky if (buf) 80193323Sed { 81193323Sed setp(buf, buf + n); 82193323Sed setg(buf, buf, buf); 83193323Sed } 84193323Sed } 85207618Srdivacky 86207618Srdivacky strstreambuf::strstreambuf(char* get, streamsize n, char* put) 87207618Srdivacky : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 88207618Srdivacky _M_frozen(false), _M_constant(false) 89207618Srdivacky { _M_setup(get, put, n); } 90207618Srdivacky 91207618Srdivacky strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) 92207618Srdivacky : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 93207618Srdivacky _M_frozen(false), _M_constant(false) 94207618Srdivacky { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 95249423Sdim 96207618Srdivacky strstreambuf::strstreambuf(unsigned char* get, streamsize n, 97193323Sed unsigned char* put) 98198090Srdivacky : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 99198090Srdivacky _M_frozen(false), _M_constant(false) 100198090Srdivacky { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 101198090Srdivacky 102193323Sed strstreambuf::strstreambuf(const char* get, streamsize n) 103202878Srdivacky : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 104202878Srdivacky _M_frozen(false), _M_constant(true) 105202878Srdivacky { _M_setup(const_cast<char*>(get), 0, n); } 106226633Sdim 107202878Srdivacky strstreambuf::strstreambuf(const signed char* get, streamsize n) 108202878Srdivacky : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 109202878Srdivacky _M_frozen(false), _M_constant(true) 110202878Srdivacky { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } 111202878Srdivacky 112202878Srdivacky strstreambuf::strstreambuf(const unsigned char* get, streamsize n) 113202878Srdivacky : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 114202878Srdivacky _M_frozen(false), _M_constant(true) 115202878Srdivacky { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } 116202878Srdivacky 117226633Sdim strstreambuf::~strstreambuf() 118202878Srdivacky { 119249423Sdim if (_M_dynamic && !_M_frozen) 120202878Srdivacky _M_free(eback()); 121193323Sed } 122207618Srdivacky 123200581Srdivacky void 124207618Srdivacky strstreambuf::freeze(bool frozenflag) 125193323Sed { 126193323Sed if (_M_dynamic) 127198090Srdivacky _M_frozen = frozenflag; 128198090Srdivacky } 129198090Srdivacky 130198090Srdivacky char* 131210299Sed strstreambuf::str() 132198090Srdivacky { 133198090Srdivacky freeze(true); 134207618Srdivacky return eback(); 135198090Srdivacky } 136198090Srdivacky 137198090Srdivacky int 138198090Srdivacky strstreambuf::pcount() const 139198090Srdivacky { return pptr() ? pptr() - pbase() : 0; } 140198090Srdivacky 141198090Srdivacky strstreambuf::int_type 142207618Srdivacky strstreambuf::overflow(int_type c) 143198090Srdivacky { 144198090Srdivacky if (c == traits_type::eof()) 145198090Srdivacky return traits_type::not_eof(c); 146198090Srdivacky 147198090Srdivacky // Try to expand the buffer. 148207618Srdivacky if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) 149198090Srdivacky { 150198090Srdivacky ptrdiff_t old_size = epptr() - pbase(); 151198090Srdivacky ptrdiff_t new_size = max(ptrdiff_t(2 * old_size), ptrdiff_t(1)); 152198090Srdivacky 153198090Srdivacky char* buf = _M_alloc(new_size); 154198090Srdivacky if (buf) 155207618Srdivacky { 156198090Srdivacky memcpy(buf, pbase(), old_size); 157239462Sdim char* old_buffer = pbase(); 158207618Srdivacky bool reposition_get = false; 159198090Srdivacky ptrdiff_t old_get_offset; 160198090Srdivacky if (gptr() != 0) 161198090Srdivacky { 162198090Srdivacky reposition_get = true; 163198090Srdivacky old_get_offset = gptr() - eback(); 164210299Sed } 165207618Srdivacky 166198090Srdivacky setp(buf, buf + new_size); 167199481Srdivacky pbump(old_size); 168199481Srdivacky 169199481Srdivacky if (reposition_get) 170199481Srdivacky setg(buf, buf + old_get_offset, buf + 171199481Srdivacky max(old_get_offset, old_size)); 172199481Srdivacky 173193323Sed _M_free(old_buffer); 174243830Sdim } 175193323Sed } 176193323Sed 177193323Sed if (pptr() != epptr()) 178193323Sed { 179 *pptr() = c; 180 pbump(1); 181 return c; 182 } 183 else 184 return traits_type::eof(); 185 } 186 187 strstreambuf::int_type 188 strstreambuf::pbackfail(int_type c) 189 { 190 if (gptr() != eback()) 191 { 192 if (c == _Traits::eof()) 193 { 194 gbump(-1); 195 return _Traits::not_eof(c); 196 } 197 else if (c == static_cast<int_type>(gptr()[-1])) 198 { // KLUDGE 199 gbump(-1); 200 return c; 201 } 202 else if (!_M_constant) 203 { 204 gbump(-1); 205 *gptr() = c; 206 return c; 207 } 208 } 209 return _Traits::eof(); 210 } 211 212 strstreambuf::int_type 213 strstreambuf::underflow() 214 { 215 if (gptr() == egptr() && pptr() && pptr() > egptr()) 216 setg(eback(), gptr(), pptr()); 217 218 if (gptr() != egptr()) 219 return (unsigned char) *gptr(); 220 else 221 return _Traits::eof(); 222 } 223 224 basic_streambuf<char, char_traits<char> >* 225 strstreambuf::setbuf(char*, streamsize) 226 { return this; } 227 228 strstreambuf::pos_type 229 strstreambuf::seekoff(off_type off, ios_base::seekdir dir, 230 ios_base::openmode mode) 231 { 232 bool do_get = false; 233 bool do_put = false; 234 235 if ((mode & (ios_base::in | ios_base::out)) 236 == (ios_base::in | ios_base::out) && 237 (dir == ios_base::beg || dir == ios_base::end)) 238 do_get = do_put = true; 239 else if (mode & ios_base::in) 240 do_get = true; 241 else if (mode & ios_base::out) 242 do_put = true; 243 244 // !gptr() is here because, according to D.7.1 paragraph 4, the seekable 245 // area is undefined if there is no get area. 246 if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr()) 247 return pos_type(off_type(-1)); 248 249 char* seeklow = eback(); 250 char* seekhigh = epptr() ? epptr() : egptr(); 251 252 off_type newoff; 253 switch (dir) 254 { 255 case ios_base::beg: 256 newoff = 0; 257 break; 258 case ios_base::end: 259 newoff = seekhigh - seeklow; 260 break; 261 case ios_base::cur: 262 newoff = do_put ? pptr() - seeklow : gptr() - seeklow; 263 break; 264 default: 265 return pos_type(off_type(-1)); 266 } 267 268 off += newoff; 269 if (off < 0 || off > seekhigh - seeklow) 270 return pos_type(off_type(-1)); 271 272 if (do_put) 273 { 274 if (seeklow + off < pbase()) 275 { 276 setp(seeklow, epptr()); 277 pbump(off); 278 } 279 else 280 { 281 setp(pbase(), epptr()); 282 pbump(off - (pbase() - seeklow)); 283 } 284 } 285 if (do_get) 286 { 287 if (off <= egptr() - seeklow) 288 setg(seeklow, seeklow + off, egptr()); 289 else if (off <= pptr() - seeklow) 290 setg(seeklow, seeklow + off, pptr()); 291 else 292 setg(seeklow, seeklow + off, epptr()); 293 } 294 return pos_type(newoff); 295 } 296 297 strstreambuf::pos_type 298 strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) 299 { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); } 300 301 char* 302 strstreambuf::_M_alloc(size_t n) 303 { 304 if (_M_alloc_fun) 305 return static_cast<char*>(_M_alloc_fun(n)); 306 else 307 return new char[n]; 308 } 309 310 void 311 strstreambuf::_M_free(char* p) 312 { 313 if (p) 314 if (_M_free_fun) 315 _M_free_fun(p); 316 else 317 delete[] p; 318 } 319 320 void 321 strstreambuf::_M_setup(char* get, char* put, streamsize n) 322 { 323 if (get) 324 { 325 size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX); 326 327 if (put) 328 { 329 setg(get, get, put); 330 setp(put, put + N); 331 } 332 else 333 setg(get, get, get + N); 334 } 335 } 336 337 istrstream::istrstream(char* s) 338 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 339 { basic_ios<char>::init(&_M_buf); } 340 341 istrstream::istrstream(const char* s) 342 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 343 { basic_ios<char>::init(&_M_buf); } 344 345 istrstream::istrstream(char* s, streamsize n) 346 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 347 { basic_ios<char>::init(&_M_buf); } 348 349 istrstream::istrstream(const char* s, streamsize n) 350 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 351 { basic_ios<char>::init(&_M_buf); } 352 353 istrstream::~istrstream() { } 354 355 strstreambuf* 356 istrstream::rdbuf() const 357 { return const_cast<strstreambuf*>(&_M_buf); } 358 359 char* 360 istrstream::str() 361 { return _M_buf.str(); } 362 363 ostrstream::ostrstream() 364 : basic_ios<char>(), basic_ostream<char>(0), _M_buf() 365 { basic_ios<char>::init(&_M_buf); } 366 367 ostrstream::ostrstream(char* s, int n, ios_base::openmode mode) 368 : basic_ios<char>(), basic_ostream<char>(0), 369 _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 370 { basic_ios<char>::init(&_M_buf); } 371 372 ostrstream::~ostrstream() {} 373 374 strstreambuf* 375 ostrstream::rdbuf() const 376 { return const_cast<strstreambuf*>(&_M_buf); } 377 378 void 379 ostrstream::freeze(bool freezeflag) 380 { _M_buf.freeze(freezeflag); } 381 382 char* 383 ostrstream::str() 384 { return _M_buf.str(); } 385 386 int 387 ostrstream::pcount() const 388 { return _M_buf.pcount(); } 389 390 strstream::strstream() 391 : basic_ios<char>(), basic_iostream<char>(0), _M_buf() 392 { basic_ios<char>::init(&_M_buf); } 393 394 strstream::strstream(char* s, int n, ios_base::openmode mode) 395 : basic_ios<char>(), basic_iostream<char>(0), 396 _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 397 { basic_ios<char>::init(&_M_buf); } 398 399 strstream::~strstream() { } 400 401 strstreambuf* 402 strstream::rdbuf() const 403 { return const_cast<strstreambuf*>(&_M_buf); } 404 405 void 406 strstream::freeze(bool freezeflag) 407 { _M_buf.freeze(freezeflag); } 408 409 int 410 strstream::pcount() const 411 { return _M_buf.pcount(); } 412 413 char* 414 strstream::str() 415 { return _M_buf.str(); } 416} // namespace std 417