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 #ifndef _STLP_SSTREAM_C 20 #define _STLP_SSTREAM_C 21 22 #ifndef _STLP_INTERNAL_SSTREAM 23 # include <stl/_sstream.h> 24 #endif 25 26 #if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) 27 // no wint_t is supported for this mode 28 # define __BSB_int_type__ int 29 # define __BSB_pos_type__ streampos 30 #else 31 # define __BSB_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 32 # define __BSB_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 33 #endif 34 35 _STLP_BEGIN_NAMESPACE 36 37 //---------------------------------------------------------------------- 38 // Non-inline stringbuf member functions. 39 40 // Constructors. Note that the base class constructor sets all of the 41 // get and area pointers to null. 42 43 template <class _CharT, class _Traits, class _Alloc> 44 basic_stringbuf<_CharT, _Traits, _Alloc> 45 ::basic_stringbuf(ios_base::openmode __mode) 46 : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str() 47 {} 48 49 template <class _CharT, class _Traits, class _Alloc> 50 basic_stringbuf<_CharT, _Traits, _Alloc> 51 ::basic_stringbuf(const basic_string<_CharT, _Traits, _Alloc>& __s, ios_base::openmode __mode) 52 : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str(__s) 53 { 54 _M_set_ptrs(); 55 } 56 57 template <class _CharT, class _Traits, class _Alloc> 58 basic_stringbuf<_CharT, _Traits, _Alloc>::~basic_stringbuf() 59 {} 60 61 // Set the underlying string to a new value. 62 template <class _CharT, class _Traits, class _Alloc> 63 void 64 basic_stringbuf<_CharT, _Traits, _Alloc>::str(const basic_string<_CharT, _Traits, _Alloc>& __s) 65 { 66 _M_str = __s; 67 _M_set_ptrs(); 68 } 69 70 template <class _CharT, class _Traits, class _Alloc> 71 void 72 basic_stringbuf<_CharT, _Traits, _Alloc>::_M_set_ptrs() 73 { 74 _CharT* __data_ptr = _S_start(_M_str); 75 _CharT* __data_end = _S_finish(_M_str); 76 // The initial read position is the beginning of the string. 77 if (_M_mode & ios_base::in) { 78 this->setg(__data_ptr, (_M_mode & ios_base::ate) ? __data_end : __data_ptr, __data_end); 79 } 80 81 // The initial write position is the beginning of the string. 82 if (_M_mode & ios_base::out) { 83 if ( _M_mode & (ios_base::app | ios_base::ate) ) { 84 this->setp( __data_end, __data_end ); 85 } else { 86 this->setp( __data_ptr, __data_end ); 87 this->pbump((int)_M_str.size()); // initial write position, if we initialized with string 88 } 89 // this->setp((_M_mode & (ios_base::app | ios_base::ate))? __data_end : __data_ptr, __data_end); 90 } 91 } 92 93 // Precondition: gptr() >= egptr(). Returns a character, if one is available. 94 template <class _CharT, class _Traits, class _Alloc> 95 __BSB_int_type__ 96 basic_stringbuf<_CharT, _Traits, _Alloc>::underflow() { 97 return this->gptr() != this->egptr() 98 ? _Traits::to_int_type(*this->gptr()) 99 : _Traits::eof(); 100 } 101 102 // Precondition: gptr() >= egptr(). 103 template <class _CharT, class _Traits, class _Alloc> 104 __BSB_int_type__ 105 basic_stringbuf<_CharT, _Traits, _Alloc>::uflow() { 106 if (this->gptr() != this->egptr()) { 107 int_type __c = _Traits::to_int_type(*this->gptr()); 108 this->gbump(1); 109 return __c; 110 } 111 else 112 return _Traits::eof(); 113 } 114 115 template <class _CharT, class _Traits, class _Alloc> 116 __BSB_int_type__ 117 basic_stringbuf<_CharT, _Traits, _Alloc>::pbackfail(int_type __c) { 118 if (this->gptr() != this->eback()) { 119 if (!_Traits::eq_int_type(__c, _Traits::eof())) { 120 if (_Traits::eq(_Traits::to_char_type(__c), this->gptr()[-1])) { 121 this->gbump(-1); 122 return __c; 123 } 124 else if (_M_mode & ios_base::out) { 125 this->gbump(-1); 126 *this->gptr() = _Traits::to_char_type(__c); 127 return __c; 128 } 129 else 130 return _Traits::eof(); 131 } 132 else { 133 this->gbump(-1); 134 return _Traits::not_eof(__c); 135 } 136 } 137 else 138 return _Traits::eof(); 139 } 140 141 template <class _CharT, class _Traits, class _Alloc> 142 __BSB_int_type__ basic_stringbuf<_CharT, _Traits, _Alloc>::overflow(int_type __c) 143 { 144 if (!_Traits::eq_int_type(__c, _Traits::eof())) { 145 if (_M_mode & ios_base::out) { 146 if ( this->pptr() < this->epptr() ) { // just put back in any case 147 _M_str.push_back( _Traits::to_char_type(__c) ); 148 this->pbump(1); 149 } else if ( _M_mode & ios_base::in ) { 150 ptrdiff_t __offset = this->gptr() - this->eback(); 151 _M_str.push_back(_Traits::to_char_type(__c)); 152 _CharT* __data_ptr = _S_start(_M_str); 153 this->setg(__data_ptr, __data_ptr + __offset, _S_finish(_M_str)); 154 this->setp(__data_ptr, _S_finish(_M_str)); 155 this->pbump((int)_M_str.size()); 156 } else { 157 _M_str.push_back( _Traits::to_char_type(__c) ); 158 this->setp(_S_start(_M_str), _S_finish(_M_str)); 159 this->pbump((int)_M_str.size()); 160 } 161 return __c; 162 } 163 return _Traits::eof(); // Overflow always fails if it's read-only 164 } 165 return _Traits::not_eof(__c); // __c is EOF, so we don't have to do anything 166 } 167 168 template <class _CharT, class _Traits, class _Alloc> 169 streamsize 170 basic_stringbuf<_CharT, _Traits, _Alloc>::xsputn(const char_type* __s, 171 streamsize __n) { 172 streamsize __nwritten = 0; 173 174 if ((_M_mode & ios_base::out) && __n > 0) { 175 // If the put pointer is somewhere in the middle of the string, 176 // then overwrite instead of append. 177 if ( !_M_str.empty() && this->pbase() == _S_start(_M_str)) { 178 ptrdiff_t __avail = _S_finish(_M_str) - this->pptr(); 179 if (__avail > __n) { 180 _Traits::copy(this->pptr(), __s, __STATIC_CAST(size_t, __n)); 181 this->pbump((int)__n); 182 return __n; 183 } else { 184 _Traits::copy(this->pptr(), __s, __avail); 185 __nwritten += __avail; 186 __n -= __avail; 187 __s += __avail; 188 } 189 } 190 191 // At this point we know we're appending. 192 _CharT* __data_ptr; 193 if (_M_mode & ios_base::in) { 194 ptrdiff_t __get_offset = this->gptr() - this->eback(); 195 _M_str.append(__s, __s + __STATIC_CAST(ptrdiff_t, __n)); 196 __data_ptr = _S_start(_M_str); 197 this->setg(__data_ptr, __data_ptr + __get_offset, _S_finish(_M_str)); 198 } else { 199 _M_str.append(__s, __s + __STATIC_CAST(ptrdiff_t, __n)); 200 __data_ptr = _S_start(_M_str); 201 } 202 203 this->setp(__data_ptr, _S_finish(_M_str)); 204 this->pbump((int)_M_str.size()); 205 __nwritten += __n; 206 } 207 208 return __nwritten; 209 } 210 211 template <class _CharT, class _Traits, class _Alloc> 212 streamsize 213 basic_stringbuf<_CharT, _Traits, _Alloc>::_M_xsputnc(char_type __c, 214 streamsize __n) { 215 streamsize __nwritten = 0; 216 217 if ((_M_mode & ios_base::out) && __n > 0) { 218 // If the put pointer is somewhere in the middle of the string, 219 // then overwrite instead of append. 220 if (this->pbase() == _S_start(_M_str)) { 221 ptrdiff_t __avail = _S_finish(_M_str) - this->pptr(); 222 if (__avail > __n) { 223 _Traits::assign(this->pptr(), __STATIC_CAST(size_t, __n), __c); 224 this->pbump(__STATIC_CAST(int, __n)); 225 return __n; 226 } 227 else { 228 _Traits::assign(this->pptr(), __avail, __c); 229 __nwritten += __avail; 230 __n -= __avail; 231 } 232 } 233 234 // At this point we know we're appending. 235 size_t __app_size = sizeof(streamsize) > sizeof(size_t) ? __STATIC_CAST(size_t, (min)(__n, __STATIC_CAST(streamsize, _M_str.max_size()))) 236 : __STATIC_CAST(size_t, __n); 237 _CharT* __data_ptr; 238 if (this->_M_mode & ios_base::in) { 239 ptrdiff_t __get_offset = this->gptr() - this->eback(); 240 _M_str.append(__app_size, __c); 241 __data_ptr = _S_start(_M_str); 242 this->setg(__data_ptr, __data_ptr + __get_offset, _S_finish(_M_str)); 243 } else { 244 _M_str.append(__app_size, __c); 245 __data_ptr = _S_start(_M_str); 246 } 247 248 this->setp(__data_ptr, _S_finish(_M_str)); 249 this->pbump((int)_M_str.size()); 250 __nwritten += __app_size; 251 } 252 253 return __nwritten; 254 } 255 256 // According to the C++ standard the effects of setbuf are implementation 257 // defined, except that setbuf(0, 0) has no effect. In this implementation, 258 // setbuf(<anything>, n), for n > 0, calls reserve(n) on the underlying 259 // string. 260 template <class _CharT, class _Traits, class _Alloc> 261 basic_streambuf<_CharT, _Traits>* 262 basic_stringbuf<_CharT, _Traits, _Alloc>::setbuf(_CharT*, streamsize __n) { 263 if (__n > 0) { 264 bool __do_get_area = false; 265 bool __do_put_area = false; 266 ptrdiff_t __offg = 0; 267 ptrdiff_t __offp = 0; 268 269 if (this->pbase() == _S_start(_M_str)) { 270 __do_put_area = true; 271 __offp = this->pptr() - this->pbase(); 272 } 273 274 if (this->eback() == _S_start(_M_str)) { 275 __do_get_area = true; 276 __offg = this->gptr() - this->eback(); 277 } 278 279 _M_str.reserve(sizeof(streamsize) > sizeof(size_t) ? __STATIC_CAST(size_t, (min)(__n, __STATIC_CAST(streamsize, _M_str.max_size()))) 280 : __STATIC_CAST(size_t, __n)); 281 282 _CharT* __data_ptr = _S_start(_M_str); 283 284 if (__do_get_area) { 285 this->setg(__data_ptr, __data_ptr + __offg, _S_finish(_M_str)); 286 } 287 288 if (__do_put_area) { 289 this->setp(__data_ptr, _S_finish(_M_str)); 290 this->pbump((int)__offp); 291 } 292 } 293 294 return this; 295 } 296 297 template <class _CharT, class _Traits, class _Alloc> 298 __BSB_pos_type__ 299 basic_stringbuf<_CharT, _Traits, _Alloc> 300 ::seekoff(off_type __off, 301 ios_base::seekdir __dir, 302 ios_base::openmode __mode) { 303 __mode &= _M_mode; 304 305 bool __imode = (__mode & ios_base::in) != 0; 306 bool __omode = (__mode & ios_base::out) != 0; 307 308 if ( !(__imode || __omode) ) 309 return pos_type(off_type(-1)); 310 311 if ( (__imode && (this->gptr() == 0)) || (__omode && (this->pptr() == 0)) ) 312 return pos_type(off_type(-1)); 313 314 streamoff __newoff; 315 switch(__dir) { 316 case ios_base::beg: 317 __newoff = 0; 318 break; 319 case ios_base::end: 320 __newoff = _M_str.size(); 321 break; 322 case ios_base::cur: 323 __newoff = __imode ? this->gptr() - this->eback() : this->pptr() - this->pbase(); 324 if ( __off == 0 ) { 325 return pos_type(__newoff); 326 } 327 break; 328 default: 329 return pos_type(off_type(-1)); 330 } 331 332 __off += __newoff; 333 334 if (__imode) { 335 ptrdiff_t __n = this->egptr() - this->eback(); 336 337 if (__off < 0 || __off > __n) 338 return pos_type(off_type(-1)); 339 this->setg(this->eback(), this->eback() + __STATIC_CAST(ptrdiff_t, __off), 340 this->eback() + __STATIC_CAST(ptrdiff_t, __n)); 341 } 342 343 if (__omode) { 344 ptrdiff_t __n = this->epptr() - this->pbase(); 345 346 if (__off < 0 || __off > __n) 347 return pos_type(off_type(-1)); 348 this->setp(this->pbase(), this->pbase() + __n); 349 this->pbump((int)__off); 350 } 351 352 return pos_type(__off); 353 } 354 355 template <class _CharT, class _Traits, class _Alloc> 356 __BSB_pos_type__ 357 basic_stringbuf<_CharT, _Traits, _Alloc> 358 ::seekpos(pos_type __pos, ios_base::openmode __mode) { 359 __mode &= _M_mode; 360 361 bool __imode = (__mode & ios_base::in) != 0; 362 bool __omode = (__mode & ios_base::out) != 0; 363 364 if ( !(__imode || __omode) ) 365 return pos_type(off_type(-1)); 366 367 if ( (__imode && (this->gptr() == 0)) || (__omode && (this->pptr() == 0)) ) 368 return pos_type(off_type(-1)); 369 370 const off_type __n = __pos - pos_type(off_type(0)); 371 372 if (__imode) { 373 if (__n < 0 || __n > this->egptr() - this->eback()) 374 return pos_type(off_type(-1)); 375 this->setg(this->eback(), this->eback() + __STATIC_CAST(ptrdiff_t, __n), this->egptr()); 376 } 377 378 if (__omode) { 379 if (__n < 0 || size_t(__n) > _M_str.size()) 380 return pos_type(off_type(-1)); 381 382 this->setp(_S_start(_M_str), _S_finish(_M_str)); 383 this->pbump((int)__n); 384 } 385 386 return __pos; 387 } 388 389 //---------------------------------------------------------------------- 390 // Non-inline istringstream member functions. 391 392 template <class _CharT, class _Traits, class _Alloc> 393 basic_istringstream<_CharT, _Traits, _Alloc> 394 ::basic_istringstream(ios_base::openmode __mode) 395 : basic_istream<_CharT, _Traits>(0), 396 _M_buf(__mode | ios_base::in) { 397 this->init(&_M_buf); 398 } 399 400 template <class _CharT, class _Traits, class _Alloc> 401 basic_istringstream<_CharT, _Traits, _Alloc> 402 ::basic_istringstream(const _String& __str,ios_base::openmode __mode) 403 : basic_istream<_CharT, _Traits>(0), 404 _M_buf(__str, __mode | ios_base::in) { 405 this->init(&_M_buf); 406 } 407 408 template <class _CharT, class _Traits, class _Alloc> 409 basic_istringstream<_CharT, _Traits, _Alloc>::~basic_istringstream() 410 {} 411 412 //---------------------------------------------------------------------- 413 // Non-inline ostringstream member functions. 414 415 template <class _CharT, class _Traits, class _Alloc> 416 basic_ostringstream<_CharT, _Traits, _Alloc> 417 ::basic_ostringstream(ios_base::openmode __mode) 418 : basic_ostream<_CharT, _Traits>(0), 419 _M_buf(__mode | ios_base::out) { 420 this->init(&_M_buf); 421 } 422 423 template <class _CharT, class _Traits, class _Alloc> 424 basic_ostringstream<_CharT, _Traits, _Alloc> 425 ::basic_ostringstream(const _String& __str, ios_base::openmode __mode) 426 : basic_ostream<_CharT, _Traits>(0), 427 _M_buf(__str, __mode | ios_base::out) { 428 this->init(&_M_buf); 429 } 430 431 template <class _CharT, class _Traits, class _Alloc> 432 basic_ostringstream<_CharT, _Traits, _Alloc>::~basic_ostringstream() 433 {} 434 435 //---------------------------------------------------------------------- 436 // Non-inline stringstream member functions. 437 438 template <class _CharT, class _Traits, class _Alloc> 439 basic_stringstream<_CharT, _Traits, _Alloc> 440 ::basic_stringstream(ios_base::openmode __mode) 441 : basic_iostream<_CharT, _Traits>(0), _M_buf(__mode) { 442 this->init(&_M_buf); 443 } 444 445 template <class _CharT, class _Traits, class _Alloc> 446 basic_stringstream<_CharT, _Traits, _Alloc> 447 ::basic_stringstream(const _String& __str, ios_base::openmode __mode) 448 : basic_iostream<_CharT, _Traits>(0), _M_buf(__str, __mode) { 449 this->init(&_M_buf); 450 } 451 452 template <class _CharT, class _Traits, class _Alloc> 453 basic_stringstream<_CharT, _Traits, _Alloc>::~basic_stringstream() 454 {} 455 456 _STLP_END_NAMESPACE 457 458 # undef __BSB_int_type__ 459 # undef __BSB_pos_type__ 460 461 #endif /* _STLP_SSTREAM_C */ 462 463 // Local Variables: 464 // mode:C++ 465 // End: 466