1 // strstream definitions -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // You should have received a copy of the GNU General Public License along 17 // with this library; see the file COPYING. If not, write to the Free 18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19 // USA. 20 21 // As a special exception, you may use this file as part of a free software 22 // library without restriction. Specifically, if other files instantiate 23 // templates or use macros or inline functions from this file, or you compile 24 // this file and link it with other files to produce an executable, this 25 // file does not by itself cause the resulting executable to be covered by 26 // the GNU General Public License. This exception does not however 27 // invalidate any other reasons why the executable file might be covered by 28 // the GNU General Public License. 29 30 /* 31 * Copyright (c) 1998 32 * Silicon Graphics Computer Systems, Inc. 33 * 34 * Permission to use, copy, modify, distribute and sell this software 35 * and its documentation for any purpose is hereby granted without fee, 36 * provided that the above copyright notice appear in all copies and 37 * that both that copyright notice and this permission notice appear 38 * in supporting documentation. Silicon Graphics makes no 39 * representations about the suitability of this software for any 40 * purpose. It is provided "as is" without express or implied warranty. 41 */ 42 43 // Implementation of the classes in header <strstream>. 44 // WARNING: The classes defined in <strstream> are DEPRECATED. This 45 // header is defined in section D.7.1 of the C++ standard, and it 46 // MAY BE REMOVED in a future standard revision. You should use the 47 // header <sstream> instead. 48 49 #include <strstream> 50 #include <algorithm> 51 #include <new> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <limits.h> 55 56 _GLIBCXX_BEGIN_NAMESPACE(std) 57 58 strstreambuf::strstreambuf(streamsize initial_capacity) 59 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(true), 60 _M_frozen(false), _M_constant(false) 61 { 62 streamsize n = std::max(initial_capacity, streamsize(16)); 63 64 char* buf = _M_alloc(n); 65 if (buf) 66 { 67 setp(buf, buf + n); 68 setg(buf, buf, buf); 69 } 70 } 71 72 strstreambuf::strstreambuf(void* (*alloc_f)(size_t), void (*free_f)(void*)) 73 : _Base(), _M_alloc_fun(alloc_f), _M_free_fun(free_f), _M_dynamic(true), 74 _M_frozen(false), _M_constant(false) 75 { 76 streamsize n = 16; 77 78 char* buf = _M_alloc(n); 79 if (buf) 80 { 81 setp(buf, buf + n); 82 setg(buf, buf, buf); 83 } 84 } 85 86 strstreambuf::strstreambuf(char* get, streamsize n, char* put) 87 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 88 _M_frozen(false), _M_constant(false) 89 { _M_setup(get, put, n); } 90 91 strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put) 92 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 93 _M_frozen(false), _M_constant(false) 94 { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 95 96 strstreambuf::strstreambuf(unsigned char* get, streamsize n, 97 unsigned char* put) 98 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 99 _M_frozen(false), _M_constant(false) 100 { _M_setup(reinterpret_cast<char*>(get), reinterpret_cast<char*>(put), n); } 101 102 strstreambuf::strstreambuf(const char* get, streamsize n) 103 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 104 _M_frozen(false), _M_constant(true) 105 { _M_setup(const_cast<char*>(get), 0, n); } 106 107 strstreambuf::strstreambuf(const signed char* get, streamsize n) 108 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 109 _M_frozen(false), _M_constant(true) 110 { _M_setup(reinterpret_cast<char*>(const_cast<signed char*>(get)), 0, n); } 111 112 strstreambuf::strstreambuf(const unsigned char* get, streamsize n) 113 : _Base(), _M_alloc_fun(0), _M_free_fun(0), _M_dynamic(false), 114 _M_frozen(false), _M_constant(true) 115 { _M_setup(reinterpret_cast<char*>(const_cast<unsigned char*>(get)), 0, n); } 116 117 strstreambuf::~strstreambuf() 118 { 119 if (_M_dynamic && !_M_frozen) 120 _M_free(eback()); 121 } 122 123 void 124 strstreambuf::freeze(bool frozenflag) 125 { 126 if (_M_dynamic) 127 _M_frozen = frozenflag; 128 } 129 130 char* 131 strstreambuf::str() 132 { 133 freeze(true); 134 return eback(); 135 } 136 137 int 138 strstreambuf::pcount() const 139 { return pptr() ? pptr() - pbase() : 0; } 140 141 strstreambuf::int_type 142 strstreambuf::overflow(int_type c) 143 { 144 if (c == traits_type::eof()) 145 return traits_type::not_eof(c); 146 147 // Try to expand the buffer. 148 if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) 149 { 150 ptrdiff_t old_size = epptr() - pbase(); 151 ptrdiff_t new_size = std::max(ptrdiff_t(2 * old_size), ptrdiff_t(1)); 152 153 char* buf = _M_alloc(new_size); 154 if (buf) 155 { 156 memcpy(buf, pbase(), old_size); 157 char* old_buffer = pbase(); 158 bool reposition_get = false; 159 ptrdiff_t old_get_offset; 160 if (gptr() != 0) 161 { 162 reposition_get = true; 163 old_get_offset = gptr() - eback(); 164 } 165 166 setp(buf, buf + new_size); 167 pbump(old_size); 168 169 if (reposition_get) 170 setg(buf, buf + old_get_offset, buf + 171 std::max(old_get_offset, old_size)); 172 173 _M_free(old_buffer); 174 } 175 } 176 177 if (pptr() != epptr()) 178 { 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 == _Traits::to_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 417 _GLIBCXX_END_NAMESPACE 418