1 // strstream definitions -*- C++ -*- 2 3 // Copyright (C) 2001-2018 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 51 namespace std _GLIBCXX_VISIBILITY(default) 52 { 53 _GLIBCXX_BEGIN_NAMESPACE_VERSION 54 strstreambuf(streamsize initial_capacity)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 strstreambuf(void * (* alloc_f)(size_t),void (* free_f)(void *))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 strstreambuf(char * get,streamsize n,char * put)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 strstreambuf(signed char * get,streamsize n,signed char * put)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 strstreambuf(unsigned char * get,streamsize n,unsigned char * put)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 strstreambuf(const char * get,streamsize n)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 strstreambuf(const signed char * get,streamsize n)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 strstreambuf(const unsigned char * get,streamsize n)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 ~strstreambuf()114 strstreambuf::~strstreambuf() 115 { 116 if (_M_dynamic && !_M_frozen) 117 _M_free(eback()); 118 } 119 120 void freeze(bool frozenflag)121 strstreambuf::freeze(bool frozenflag) throw () 122 { 123 if (_M_dynamic) 124 _M_frozen = frozenflag; 125 } 126 127 char* str()128 strstreambuf::str() throw () 129 { 130 freeze(true); 131 return eback(); 132 } 133 134 int pcount() const135 strstreambuf::pcount() const throw () 136 { return pptr() ? pptr() - pbase() : 0; } 137 138 strstreambuf::int_type overflow(int_type c)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 pbackfail(int_type c)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 underflow()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> >* setbuf(char *,streamsize)222 strstreambuf::setbuf(char*, streamsize) 223 { return this; } 224 225 strstreambuf::pos_type seekoff(off_type off,ios_base::seekdir dir,ios_base::openmode mode)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 seekpos(pos_type pos,ios_base::openmode mode)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* _M_alloc(size_t n)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 _M_free(char * p)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 _M_setup(char * get,char * put,streamsize n)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 istrstream(char * s)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 istrstream(const char * s)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 istrstream(char * s,streamsize n)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 istrstream(const char * s,streamsize n)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 ~istrstream()352 istrstream::~istrstream() { } 353 354 strstreambuf* rdbuf() const355 istrstream::rdbuf() const throw () 356 { return const_cast<strstreambuf*>(&_M_buf); } 357 358 char* str()359 istrstream::str() throw () 360 { return _M_buf.str(); } 361 ostrstream()362 ostrstream::ostrstream() 363 : basic_ios<char>(), basic_ostream<char>(0), _M_buf() 364 { basic_ios<char>::init(&_M_buf); } 365 ostrstream(char * s,int n,ios_base::openmode mode)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 ~ostrstream()371 ostrstream::~ostrstream() {} 372 373 strstreambuf* rdbuf() const374 ostrstream::rdbuf() const throw () 375 { return const_cast<strstreambuf*>(&_M_buf); } 376 377 void freeze(bool freezeflag)378 ostrstream::freeze(bool freezeflag) throw () 379 { _M_buf.freeze(freezeflag); } 380 381 char* str()382 ostrstream::str() throw () 383 { return _M_buf.str(); } 384 385 int pcount() const386 ostrstream::pcount() const throw () 387 { return _M_buf.pcount(); } 388 strstream()389 strstream::strstream() 390 : basic_ios<char>(), basic_iostream<char>(0), _M_buf() 391 { basic_ios<char>::init(&_M_buf); } 392 strstream(char * s,int n,ios_base::openmode mode)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 ~strstream()398 strstream::~strstream() { } 399 400 strstreambuf* rdbuf() const401 strstream::rdbuf() const throw () 402 { return const_cast<strstreambuf*>(&_M_buf); } 403 404 void freeze(bool freezeflag)405 strstream::freeze(bool freezeflag) throw () 406 { _M_buf.freeze(freezeflag); } 407 408 int pcount() const409 strstream::pcount() const throw () 410 { return _M_buf.pcount(); } 411 412 char* str()413 strstream::str() throw () 414 { return _M_buf.str(); } 415 416 _GLIBCXX_END_NAMESPACE_VERSION 417 } // namespace 418