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