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