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 43template <class _CharT, class _Traits, class _Alloc> 44basic_stringbuf<_CharT, _Traits, _Alloc> 45 ::basic_stringbuf(ios_base::openmode __mode) 46 : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str() 47{} 48 49template <class _CharT, class _Traits, class _Alloc> 50basic_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 57template <class _CharT, class _Traits, class _Alloc> 58basic_stringbuf<_CharT, _Traits, _Alloc>::~basic_stringbuf() 59{} 60 61// Set the underlying string to a new value. 62template <class _CharT, class _Traits, class _Alloc> 63void 64basic_stringbuf<_CharT, _Traits, _Alloc>::str(const basic_string<_CharT, _Traits, _Alloc>& __s) 65{ 66 _M_str = __s; 67 _M_set_ptrs(); 68} 69 70template <class _CharT, class _Traits, class _Alloc> 71void 72basic_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. 94template <class _CharT, class _Traits, class _Alloc> 95__BSB_int_type__ 96basic_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(). 103template <class _CharT, class _Traits, class _Alloc> 104__BSB_int_type__ 105basic_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 115template <class _CharT, class _Traits, class _Alloc> 116__BSB_int_type__ 117basic_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 141template <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 168template <class _CharT, class _Traits, class _Alloc> 169streamsize 170basic_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 211template <class _CharT, class _Traits, class _Alloc> 212streamsize 213basic_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. 260template <class _CharT, class _Traits, class _Alloc> 261basic_streambuf<_CharT, _Traits>* 262basic_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 297template <class _CharT, class _Traits, class _Alloc> 298__BSB_pos_type__ 299basic_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 355template <class _CharT, class _Traits, class _Alloc> 356__BSB_pos_type__ 357basic_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 392template <class _CharT, class _Traits, class _Alloc> 393basic_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 400template <class _CharT, class _Traits, class _Alloc> 401basic_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 408template <class _CharT, class _Traits, class _Alloc> 409basic_istringstream<_CharT, _Traits, _Alloc>::~basic_istringstream() 410{} 411 412//---------------------------------------------------------------------- 413// Non-inline ostringstream member functions. 414 415template <class _CharT, class _Traits, class _Alloc> 416basic_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 423template <class _CharT, class _Traits, class _Alloc> 424basic_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 431template <class _CharT, class _Traits, class _Alloc> 432basic_ostringstream<_CharT, _Traits, _Alloc>::~basic_ostringstream() 433{} 434 435//---------------------------------------------------------------------- 436// Non-inline stringstream member functions. 437 438template <class _CharT, class _Traits, class _Alloc> 439basic_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 445template <class _CharT, class _Traits, class _Alloc> 446basic_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 452template <class _CharT, class _Traits, class _Alloc> 453basic_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