1 // strstream definitions -*- C++ -*- 2 3 // Copyright (C) 2001, 2002 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> 51 #include <algorithm> 52 #include <new> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <limits.h> 56 57 namespace std 58 { 59 strstreambuf::strstreambuf(streamsize initial_capacity) 60 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), 61 _M_frozen(false), _M_constant(false) 62 { 63 streamsize n = max(initial_capacity, streamsize(16)); 64 65 char* buf = _M_alloc(n); 66 if (buf) 67 { 68 setp(buf, buf + n); 69 setg(buf, buf, buf); 70 } 71 } 72 73 strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) 74 : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), 75 _M_frozen(false), _M_constant(false) 76 { 77 streamsize n = 16; 78 79 char* buf = _M_alloc(n); 80 if (buf) 81 { 82 setp(buf, buf + n); 83 setg(buf, buf, buf); 84 } 85 } 86 87 strstreambuf::strstreambuf(char* get, streamsize n, char* put) 88 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 89 _M_frozen(false), _M_constant(false) 90 { _M_setup(get, put, n); } 91 92 strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) 93 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 94 _M_frozen(false), _M_constant(false) 95 { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 96 97 strstreambuf::strstreambuf(unsigned char* get, streamsize n, 98 unsigned char* put) 99 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 100 _M_frozen(false), _M_constant(false) 101 { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 102 103 strstreambuf::strstreambuf(const char* get, streamsize n) 104 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 105 _M_frozen(false), _M_constant(true) 106 { _M_setup(const_cast<char*>(get), 0, n); } 107 108 strstreambuf::strstreambuf(const signed char* get, streamsize n) 109 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 110 _M_frozen(false), _M_constant(true) 111 { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } 112 113 strstreambuf::strstreambuf(const unsigned char* get, streamsize n) 114 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 115 _M_frozen(false), _M_constant(true) 116 { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } 117 118 strstreambuf::~strstreambuf() 119 { 120 if (_M_dynamic && !_M_frozen) 121 _M_free(eback()); 122 } 123 124 void 125 strstreambuf::freeze(bool frozenflag) 126 { 127 if (_M_dynamic) 128 _M_frozen = frozenflag; 129 } 130 131 char* 132 strstreambuf::str() 133 { 134 freeze(true); 135 return eback(); 136 } 137 138 int 139 strstreambuf::pcount() const 140 { return pptr() ? pptr() - pbase() : 0; } 141 142 strstreambuf::int_type 143 strstreambuf::overflow(int_type c) 144 { 145 if (c == traits_type::eof()) 146 return traits_type::not_eof(c); 147 148 // Try to expand the buffer. 149 if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) 150 { 151 ptrdiff_t old_size = epptr() - pbase(); 152 ptrdiff_t new_size = max(2 * old_size, ptrdiff_t(1)); 153 154 char* buf = _M_alloc(new_size); 155 if (buf) 156 { 157 memcpy(buf, pbase(), old_size); 158 char* old_buffer = pbase(); 159 bool reposition_get = false; 160 ptrdiff_t old_get_offset; 161 if (gptr() != 0) 162 { 163 reposition_get = true; 164 old_get_offset = gptr() - eback(); 165 } 166 167 setp(buf, buf + new_size); 168 pbump(old_size); 169 170 if (reposition_get) 171 setg(buf, buf + old_get_offset, buf + 172 max(old_get_offset, old_size)); 173 174 _M_free(old_buffer); 175 } 176 } 177 178 if (pptr() != epptr()) 179 { 180 *pptr() = c; 181 pbump(1); 182 return c; 183 } 184 else 185 return traits_type::eof(); 186 } 187 188 strstreambuf::int_type 189 strstreambuf::pbackfail(int_type c) 190 { 191 if (gptr() != eback()) 192 { 193 if (c == _Traits::eof()) 194 { 195 gbump(-1); 196 return _Traits::not_eof(c); 197 } 198 else if (c == static_cast<int_type>(gptr()[-1])) 199 { // KLUDGE 200 gbump(-1); 201 return c; 202 } 203 else if (!_M_constant) 204 { 205 gbump(-1); 206 *gptr() = c; 207 return c; 208 } 209 } 210 return _Traits::eof(); 211 } 212 213 strstreambuf::int_type 214 strstreambuf::underflow() 215 { 216 if (gptr() == egptr() && pptr() && pptr() > egptr()) 217 setg(eback(), gptr(), pptr()); 218 219 if (gptr() != egptr()) 220 return (unsigned char) *gptr(); 221 else 222 return _Traits::eof(); 223 } 224 225 basic_streambuf<char, char_traits<char> >* 226 strstreambuf::setbuf(char*, streamsize) 227 { return this; } 228 229 strstreambuf::pos_type 230 strstreambuf::seekoff(off_type off, ios_base::seekdir dir, 231 ios_base::openmode mode) 232 { 233 bool do_get = false; 234 bool do_put = false; 235 236 if ((mode & (ios_base::in | ios_base::out)) 237 == (ios_base::in | ios_base::out) && 238 (dir == ios_base::beg || dir == ios_base::end)) 239 do_get = do_put = true; 240 else if (mode & ios_base::in) 241 do_get = true; 242 else if (mode & ios_base::out) 243 do_put = true; 244 245 // !gptr() is here because, according to D.7.1 paragraph 4, the seekable 246 // area is undefined if there is no get area. 247 if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr()) 248 return pos_type(off_type(-1)); 249 250 char* seeklow = eback(); 251 char* seekhigh = epptr() ? epptr() : egptr(); 252 253 off_type newoff; 254 switch (dir) 255 { 256 case ios_base::beg: 257 newoff = 0; 258 break; 259 case ios_base::end: 260 newoff = seekhigh - seeklow; 261 break; 262 case ios_base::cur: 263 newoff = do_put ? pptr() - seeklow : gptr() - seeklow; 264 break; 265 default: 266 return pos_type(off_type(-1)); 267 } 268 269 off += newoff; 270 if (off < 0 || off > seekhigh - seeklow) 271 return pos_type(off_type(-1)); 272 273 if (do_put) 274 { 275 if (seeklow + off < pbase()) 276 { 277 setp(seeklow, epptr()); 278 pbump(off); 279 } 280 else 281 { 282 setp(pbase(), epptr()); 283 pbump(off - (pbase() - seeklow)); 284 } 285 } 286 if (do_get) 287 { 288 if (off <= egptr() - seeklow) 289 setg(seeklow, seeklow + off, egptr()); 290 else if (off <= pptr() - seeklow) 291 setg(seeklow, seeklow + off, pptr()); 292 else 293 setg(seeklow, seeklow + off, epptr()); 294 } 295 return pos_type(newoff); 296 } 297 298 strstreambuf::pos_type 299 strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) 300 { return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode); } 301 302 char* 303 strstreambuf::_M_alloc(size_t n) 304 { 305 if (_M_alloc_fun) 306 return static_cast<char*>(_M_alloc_fun(n)); 307 else 308 return new char[n]; 309 } 310 311 void 312 strstreambuf::_M_free(char* p) 313 { 314 if (p) 315 if (_M_free_fun) 316 _M_free_fun(p); 317 else 318 delete[] p; 319 } 320 321 void 322 strstreambuf::_M_setup(char* get, char* put, streamsize n) 323 { 324 if (get) 325 { 326 size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX); 327 328 if (put) 329 { 330 setg(get, get, put); 331 setp(put, put + N); 332 } 333 else 334 setg(get, get, get + N); 335 } 336 } 337 338 istrstream::istrstream(char* s) 339 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 340 { basic_ios<char>::init(&_M_buf); } 341 342 istrstream::istrstream(const char* s) 343 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, 0) 344 { basic_ios<char>::init(&_M_buf); } 345 346 istrstream::istrstream(char* s, streamsize n) 347 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 348 { basic_ios<char>::init(&_M_buf); } 349 350 istrstream::istrstream(const char* s, streamsize n) 351 : basic_ios<char>(), basic_istream<char>(0), _M_buf(s, n) 352 { basic_ios<char>::init(&_M_buf); } 353 354 istrstream::~istrstream() { } 355 356 strstreambuf* 357 istrstream::rdbuf() const 358 { return const_cast<strstreambuf*>(&_M_buf); } 359 360 char* 361 istrstream::str() 362 { return _M_buf.str(); } 363 364 ostrstream::ostrstream() 365 : basic_ios<char>(), basic_ostream<char>(0), _M_buf() 366 { basic_ios<char>::init(&_M_buf); } 367 368 ostrstream::ostrstream(char* s, int n, ios_base::openmode mode) 369 : basic_ios<char>(), basic_ostream<char>(0), 370 _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 371 { basic_ios<char>::init(&_M_buf); } 372 373 ostrstream::~ostrstream() {} 374 375 strstreambuf* 376 ostrstream::rdbuf() const 377 { return const_cast<strstreambuf*>(&_M_buf); } 378 379 void 380 ostrstream::freeze(bool freezeflag) 381 { _M_buf.freeze(freezeflag); } 382 383 char* 384 ostrstream::str() 385 { return _M_buf.str(); } 386 387 int 388 ostrstream::pcount() const 389 { return _M_buf.pcount(); } 390 391 strstream::strstream() 392 : basic_ios<char>(), basic_iostream<char>(0), _M_buf() 393 { basic_ios<char>::init(&_M_buf); } 394 395 strstream::strstream(char* s, int n, ios_base::openmode mode) 396 : basic_ios<char>(), basic_iostream<char>(0), 397 _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) 398 { basic_ios<char>::init(&_M_buf); } 399 400 strstream::~strstream() { } 401 402 strstreambuf* 403 strstream::rdbuf() const 404 { return const_cast<strstreambuf*>(&_M_buf); } 405 406 void 407 strstream::freeze(bool freezeflag) 408 { _M_buf.freeze(freezeflag); } 409 410 int 411 strstream::pcount() const 412 { return _M_buf.pcount(); } 413 414 char* 415 strstream::str() 416 { return _M_buf.str(); } 417 } // namespace std 418