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