Home | History | Annotate | Download | only in stl
      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