/home/ntakagi/work/STLport-5.1.5/stlport/stl/_sstream.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * This material is provided "as is", with absolutely no warranty expressed
00009  * or implied. Any use is at your own risk.
00010  *
00011  * Permission to use or copy this software for any purpose is hereby granted
00012  * without fee, provided the above notices are retained on all copies.
00013  * Permission to modify the code and to distribute modified code is granted,
00014  * provided the above notices are retained, and a notice that the code was
00015  * modified is included with the above copyright notice.
00016  *
00017  */
00018 
00019 #ifndef _STLP_SSTREAM_C
00020 #define _STLP_SSTREAM_C
00021 
00022 #ifndef _STLP_INTERNAL_SSTREAM
00023 #  include <stl/_sstream.h>
00024 #endif
00025 
00026 #if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
00027 // no wint_t is supported for this mode
00028 #  define __BSB_int_type__ int
00029 #  define __BSB_pos_type__ streampos
00030 #else
00031 #  define __BSB_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
00032 #  define __BSB_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
00033 #endif
00034 
00035 _STLP_BEGIN_NAMESPACE
00036 
00037 //----------------------------------------------------------------------
00038 // Non-inline stringbuf member functions.
00039 
00040 // Constructors.  Note that the base class constructor sets all of the
00041 // get and area pointers to null.
00042 
00043 template <class _CharT, class _Traits, class _Alloc>
00044 basic_stringbuf<_CharT, _Traits, _Alloc>
00045   ::basic_stringbuf(ios_base::openmode __mode)
00046     : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str()
00047 {}
00048 
00049 template <class _CharT, class _Traits, class _Alloc>
00050 basic_stringbuf<_CharT, _Traits, _Alloc>
00051   ::basic_stringbuf(const basic_string<_CharT, _Traits, _Alloc>& __s, ios_base::openmode __mode)
00052     : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str(__s)
00053 {
00054   _M_set_ptrs();
00055 }
00056 
00057 template <class _CharT, class _Traits, class _Alloc>
00058 basic_stringbuf<_CharT, _Traits, _Alloc>::~basic_stringbuf()
00059 {}
00060 
00061 // Set the underlying string to a new value.
00062 template <class _CharT, class _Traits, class _Alloc>
00063 void
00064 basic_stringbuf<_CharT, _Traits, _Alloc>::str(const basic_string<_CharT, _Traits, _Alloc>& __s)
00065 {
00066   _M_str = __s;
00067   _M_set_ptrs();
00068 }
00069 
00070 template <class _CharT, class _Traits, class _Alloc>
00071 void
00072 basic_stringbuf<_CharT, _Traits, _Alloc>::_M_set_ptrs() {
00073   _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
00074   _CharT* __data_end = __data_ptr + _M_str.size();
00075   // The initial read position is the beginning of the string.
00076   if (_M_mode & ios_base::in) {
00077     if (_M_mode & ios_base::ate)
00078       this->setg(__data_ptr, __data_end, __data_end);
00079     else
00080       this->setg(__data_ptr, __data_ptr, __data_end);
00081   }
00082 
00083   // The initial write position is the beginning of the string.
00084   if (_M_mode & ios_base::out) {
00085     if (_M_mode & (ios_base::app | ios_base::ate))
00086       this->setp(__data_end, __data_end);
00087     else
00088       this->setp(__data_ptr, __data_end);
00089   }
00090 }
00091 
00092 // Precondition: gptr() >= egptr().  Returns a character, if one is available.
00093 template <class _CharT, class _Traits, class _Alloc>
00094 __BSB_int_type__
00095 basic_stringbuf<_CharT, _Traits, _Alloc>::underflow() {
00096   return this->gptr() != this->egptr()
00097     ? _Traits::to_int_type(*this->gptr())
00098     : _Traits::eof();
00099 }
00100 
00101 // Precondition: gptr() >= egptr().
00102 template <class _CharT, class _Traits, class _Alloc>
00103 __BSB_int_type__
00104 basic_stringbuf<_CharT, _Traits, _Alloc>::uflow() {
00105   if (this->gptr() != this->egptr()) {
00106     int_type __c = _Traits::to_int_type(*this->gptr());
00107     this->gbump(1);
00108     return __c;
00109   }
00110   else
00111     return _Traits::eof();
00112 }
00113 
00114 template <class _CharT, class _Traits, class _Alloc>
00115 __BSB_int_type__
00116 basic_stringbuf<_CharT, _Traits, _Alloc>::pbackfail(int_type __c) {
00117   if (this->gptr() != this->eback()) {
00118     if (!_Traits::eq_int_type(__c, _Traits::eof())) {
00119       if (_Traits::eq(_Traits::to_char_type(__c), this->gptr()[-1])) {
00120         this->gbump(-1);
00121         return __c;
00122       }
00123       else if (_M_mode & ios_base::out) {
00124         this->gbump(-1);
00125         *this->gptr() = _Traits::to_char_type(__c);
00126         return __c;
00127       }
00128       else
00129         return _Traits::eof();
00130     }
00131     else {
00132       this->gbump(-1);
00133       return _Traits::not_eof(__c);
00134     }
00135   }
00136   else
00137     return _Traits::eof();
00138 }
00139 
00140 template <class _CharT, class _Traits, class _Alloc>
00141 __BSB_int_type__
00142 basic_stringbuf<_CharT, _Traits, _Alloc>::overflow(int_type __c) {
00143   // fbp : reverse order of "ifs" to pass Dietmar's test.
00144   // Apparently, standard allows overflow with eof even for read-only streams.
00145   if (!_Traits::eq_int_type(__c, _Traits::eof())) {
00146     if (_M_mode & ios_base::out) {
00147       if (!(_M_mode & ios_base::in)) {
00148         // It's a write-only streambuf, so we can use special append buffer.
00149         if (this->pptr() == this->epptr())
00150           this->_M_append_buffer();
00151 
00152         if (this->pptr() != this->epptr()) {
00153           *this->pptr() = _Traits::to_char_type(__c);
00154           this->pbump(1);
00155           return __c;
00156         }
00157         else
00158           return _Traits::eof();
00159       }
00160       else {
00161         // We're not using a special append buffer, just the string itself.
00162         if (this->pptr() == this->epptr()) {
00163           ptrdiff_t __offset = this->gptr() - this->eback();
00164           _M_str.push_back(_Traits::to_char_type(__c));
00165 
00166           _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
00167           size_t __data_size = _M_str.size();
00168 
00169           this->setg(__data_ptr, __data_ptr + __offset, __data_ptr+__data_size);
00170           this->setp(__data_ptr, __data_ptr + __data_size);
00171           this->pbump((int)__data_size);
00172           return __c;
00173         }
00174         else {
00175           *this->pptr() = _Traits::to_char_type(__c);
00176           this->pbump(1);
00177           return __c;
00178         }
00179       }
00180     }
00181     else                          // Overflow always fails if it's read-only
00182       return _Traits::eof();
00183   }
00184   else                        // __c is EOF, so we don't have to do anything
00185     return _Traits::not_eof(__c);
00186 }
00187 
00188 template <class _CharT, class _Traits, class _Alloc>
00189 streamsize
00190 basic_stringbuf<_CharT, _Traits, _Alloc>::xsputn(const char_type* __s,
00191                                                  streamsize __n) {
00192   streamsize __nwritten = 0;
00193 
00194   if ((_M_mode & ios_base::out) && __n > 0) {
00195     // If the put pointer is somewhere in the middle of the string,
00196     // then overwrite instead of append.
00197     if (this->pbase() == _M_str.data() ) {
00198       ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr();
00199       if (__avail > __n) {
00200         _Traits::copy(this->pptr(), __s, __STATIC_CAST(size_t, __n));
00201         this->pbump((int)__n);
00202         return __n;
00203       }
00204       else {
00205         _Traits::copy(this->pptr(), __s, __avail);
00206         __nwritten += __avail;
00207         __n -= __avail;
00208         __s += __avail;
00209         this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz));
00210       }
00211     }
00212 
00213     // At this point we know we're appending.
00214     if (_M_mode & ios_base::in) {
00215       ptrdiff_t __get_offset = this->gptr() - this->eback();
00216       _M_str.append(__s, __s + __STATIC_CAST(ptrdiff_t, __n));
00217 
00218       _CharT* __data_ptr = __CONST_CAST(_CharT*, _M_str.data());
00219       size_t __data_size = _M_str.size();
00220 
00221       this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr + __data_size);
00222       this->setp(__data_ptr, __data_ptr + __data_size);
00223       this->pbump((int)__data_size);
00224     }
00225     else {
00226       _M_append_buffer();
00227       _M_str.append(__s, __s + __STATIC_CAST(ptrdiff_t, __n));
00228     }
00229 
00230     __nwritten += __n;
00231   }
00232 
00233   return __nwritten;
00234 }
00235 
00236 template <class _CharT, class _Traits, class _Alloc>
00237 streamsize
00238 basic_stringbuf<_CharT, _Traits, _Alloc>::_M_xsputnc(char_type __c,
00239                                                      streamsize __n) {
00240   streamsize __nwritten = 0;
00241 
00242   if ((_M_mode & ios_base::out) && __n > 0) {
00243     // If the put pointer is somewhere in the middle of the string,
00244     // then overwrite instead of append.
00245     if (this->pbase() == _M_str.data()) {
00246       ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr();
00247       if (__avail > __n) {
00248         _Traits::assign(this->pptr(), __STATIC_CAST(size_t, __n), __c);
00249         this->pbump(__STATIC_CAST(int, __n));
00250         return __n;
00251       }
00252       else {
00253         _Traits::assign(this->pptr(), __avail, __c);
00254         __nwritten += __avail;
00255         __n -= __avail;
00256         this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz));
00257       }
00258     }
00259 
00260     // At this point we know we're appending.
00261     size_t __app_size = sizeof(streamsize) > sizeof(size_t) ? __STATIC_CAST(size_t, (min)(__n, __STATIC_CAST(streamsize, _M_str.max_size())))
00262                                                             : __STATIC_CAST(size_t, __n);
00263     if (this->_M_mode & ios_base::in) {
00264       ptrdiff_t __get_offset = this->gptr() - this->eback();
00265       _M_str.append(__app_size, __c);
00266 
00267       _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
00268       size_t __data_size = _M_str.size();
00269 
00270       this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr + __data_size);
00271       this->setp(__data_ptr, __data_ptr + __data_size);
00272       this->pbump((int)__data_size);
00273     }
00274     else {
00275       _M_append_buffer();
00276       _M_str.append(__app_size, __c);
00277     }
00278 
00279     __nwritten += __app_size;
00280   }
00281 
00282   return __nwritten;
00283 }
00284 
00285 // According to the C++ standard the effects of setbuf are implementation
00286 // defined, except that setbuf(0, 0) has no effect.  In this implementation,
00287 // setbuf(<anything>, n), for n > 0, calls reserve(n) on the underlying
00288 // string.
00289 template <class _CharT, class _Traits, class _Alloc>
00290 basic_streambuf<_CharT, _Traits>*
00291 basic_stringbuf<_CharT, _Traits, _Alloc>::setbuf(_CharT*, streamsize __n) {
00292   if (__n > 0) {
00293     bool __do_get_area = false;
00294     bool __do_put_area = false;
00295     ptrdiff_t __offg = 0;
00296     ptrdiff_t __offp = 0;
00297 
00298     if (this->pbase() == _M_str.data()) {
00299       __do_put_area = true;
00300       __offp = this->pptr() - this->pbase();
00301     }
00302 
00303     if (this->eback() == _M_str.data()) {
00304       __do_get_area = true;
00305       __offg = this->gptr() - this->eback();
00306     }
00307 
00308     if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
00309       _M_append_buffer();
00310 
00311     _M_str.reserve(sizeof(streamsize) > sizeof(size_t) ? __STATIC_CAST(size_t, (min)(__n, __STATIC_CAST(streamsize, _M_str.max_size())))
00312                                                        : __STATIC_CAST(size_t, __n));
00313 
00314     _CharT* __data_ptr = __CONST_CAST(_CharT*, _M_str.data());
00315     size_t __data_size = _M_str.size();
00316 
00317     if (__do_get_area) {
00318       this->setg(__data_ptr, __data_ptr + __offg, __data_ptr + __data_size);
00319     }
00320 
00321     if (__do_put_area) {
00322       this->setp(__data_ptr, __data_ptr + __data_size);
00323       this->pbump((int)__offp);
00324     }
00325   }
00326 
00327   return this;
00328 }
00329 
00330 template <class _CharT, class _Traits, class _Alloc>
00331 __BSB_pos_type__
00332 basic_stringbuf<_CharT, _Traits, _Alloc>
00333   ::seekoff(off_type __off,
00334             ios_base::seekdir __dir,
00335             ios_base::openmode __mode) {
00336   __mode &= _M_mode;
00337 
00338   bool __imode  = (__mode & ios_base::in) != 0;
00339   bool __omode = (__mode & ios_base::out) != 0;
00340 
00341   if ( !(__imode || __omode) )
00342     return pos_type(off_type(-1));
00343 
00344   if ( (__imode && (this->gptr() == 0)) || (__omode && (this->pptr() == 0)) )
00345     return pos_type(off_type(-1));
00346 
00347   if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
00348     _M_append_buffer();
00349 
00350   streamoff __newoff;
00351   switch(__dir) {
00352   case ios_base::beg:
00353     __newoff = 0;
00354     break;
00355   case ios_base::end:
00356     __newoff = _M_str.size();
00357     break;
00358   case ios_base::cur:
00359     __newoff = __imode ? this->gptr() - this->eback() : this->pptr() - this->pbase();
00360     break;
00361   default:
00362     return pos_type(off_type(-1));
00363   }
00364 
00365   __off += __newoff;
00366 
00367   if (__imode) {
00368     ptrdiff_t __n = this->egptr() - this->eback();
00369 
00370     if (__off < 0 || __off > __n)
00371       return pos_type(off_type(-1));
00372     this->setg(this->eback(), this->eback() + __STATIC_CAST(ptrdiff_t, __off),
00373                               this->eback() + __STATIC_CAST(ptrdiff_t, __n));
00374   }
00375 
00376   if (__omode) {
00377     ptrdiff_t __n = this->epptr() - this->pbase();
00378 
00379     if (__off < 0 || __off > __n)
00380       return pos_type(off_type(-1));
00381     this->setp(this->pbase(), this->pbase() + __n);
00382     this->pbump((int)__off);
00383   }
00384 
00385   return pos_type(__off);
00386 }
00387 
00388 template <class _CharT, class _Traits, class _Alloc>
00389 __BSB_pos_type__
00390 basic_stringbuf<_CharT, _Traits, _Alloc>
00391   ::seekpos(pos_type __pos, ios_base::openmode __mode) {
00392   __mode &= _M_mode;
00393 
00394   bool __imode  = (__mode & ios_base::in) != 0;
00395   bool __omode = (__mode & ios_base::out) != 0;
00396 
00397   if ( !(__imode || __omode) )
00398     return pos_type(off_type(-1));
00399 
00400   if ( (__imode && (this->gptr() == 0)) || (__omode && (this->pptr() == 0)) )
00401     return pos_type(off_type(-1));
00402 
00403   const off_type __n = __pos - pos_type(off_type(0));
00404   if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
00405     _M_append_buffer();
00406 
00407   if (__imode) {
00408     if (__n < 0 || __n > this->egptr() - this->eback())
00409       return pos_type(off_type(-1));
00410     this->setg(this->eback(), this->eback() + __STATIC_CAST(ptrdiff_t, __n), this->egptr());
00411   }
00412 
00413   if (__omode) {
00414     if (__n < 0 || size_t(__n) > _M_str.size())
00415       return pos_type(off_type(-1));
00416 
00417     _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
00418     size_t __data_size = _M_str.size();
00419 
00420     this->setp(__data_ptr, __data_ptr+__data_size);
00421     this->pbump((int)__n);
00422   }
00423 
00424   return __pos;
00425 }
00426 
00427 // This is declared as a const member function because it is
00428 // called by basic_stringbuf<>::str().  Precondition: this is a
00429 // write-only stringbuf.  We can't use an output buffer for read-
00430 // write stringbufs.  Postcondition: pptr is reset to the beginning
00431 // of the buffer.
00432 template <class _CharT, class _Traits, class _Alloc>
00433 void basic_stringbuf<_CharT, _Traits, _Alloc>::_M_append_buffer() const {
00434   // Do we have a buffer to append?
00435   if (this->pbase() == this->_M_Buf && this->pptr() != this->_M_Buf) {
00436     basic_stringbuf<_CharT, _Traits, _Alloc>* __this = __CONST_CAST(_Self*,this);
00437     __this->_M_str.append((const _CharT*)this->pbase(), (const _CharT*)this->pptr());
00438 #ifndef __MWERKS__
00439     __this->setp(__CONST_CAST(_CharT*,_M_Buf),
00440                  __CONST_CAST(_CharT*,_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
00441 #else // CodeWarrior treat const char * and const char [8] as different types
00442     __this->setp((_CharT*)_M_Buf,
00443                  (_CharT*)(_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
00444 #endif
00445   }
00446 
00447   // Have we run off the end of the string?
00448   else if (this->pptr() == this->epptr()) {
00449     basic_stringbuf<_CharT, _Traits, _Alloc>* __this = __CONST_CAST(_Self*,this);
00450 #ifndef __MWERKS__
00451     __this->setp(__CONST_CAST(_CharT*,_M_Buf),
00452                  __CONST_CAST(_CharT*,_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
00453 #else // CodeWarrior treat const char * and const char [8] as different types
00454     __this->setp((_CharT*)_M_Buf,
00455                  (_CharT*)(_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
00456 #endif
00457   }
00458 }
00459 
00460 //----------------------------------------------------------------------
00461 // Non-inline istringstream member functions.
00462 
00463 template <class _CharT, class _Traits, class _Alloc>
00464 basic_istringstream<_CharT, _Traits, _Alloc>
00465   ::basic_istringstream(ios_base::openmode __mode)
00466     : basic_istream<_CharT, _Traits>(0),
00467       _M_buf(__mode | ios_base::in) {
00468   this->init(&_M_buf);
00469 }
00470 
00471 template <class _CharT, class _Traits, class _Alloc>
00472 basic_istringstream<_CharT, _Traits, _Alloc>
00473   ::basic_istringstream(const _String& __str,ios_base::openmode __mode)
00474     : basic_istream<_CharT, _Traits>(0),
00475       _M_buf(__str, __mode | ios_base::in) {
00476   this->init(&_M_buf);
00477 }
00478 
00479 template <class _CharT, class _Traits, class _Alloc>
00480 basic_istringstream<_CharT, _Traits, _Alloc>::~basic_istringstream()
00481 {}
00482 
00483 //----------------------------------------------------------------------
00484 // Non-inline ostringstream member functions.
00485 
00486 template <class _CharT, class _Traits, class _Alloc>
00487 basic_ostringstream<_CharT, _Traits, _Alloc>
00488   ::basic_ostringstream(ios_base::openmode __mode)
00489     : basic_ostream<_CharT, _Traits>(0),
00490       _M_buf(__mode | ios_base::out) {
00491   this->init(&_M_buf);
00492 }
00493 
00494 template <class _CharT, class _Traits, class _Alloc>
00495 basic_ostringstream<_CharT, _Traits, _Alloc>
00496   ::basic_ostringstream(const _String& __str, ios_base::openmode __mode)
00497     : basic_ostream<_CharT, _Traits>(0),
00498       _M_buf(__str, __mode | ios_base::out) {
00499   this->init(&_M_buf);
00500 }
00501 
00502 template <class _CharT, class _Traits, class _Alloc>
00503 basic_ostringstream<_CharT, _Traits, _Alloc>::~basic_ostringstream()
00504 {}
00505 
00506 //----------------------------------------------------------------------
00507 // Non-inline stringstream member functions.
00508 
00509 template <class _CharT, class _Traits, class _Alloc>
00510 basic_stringstream<_CharT, _Traits, _Alloc>
00511   ::basic_stringstream(ios_base::openmode __mode)
00512     : basic_iostream<_CharT, _Traits>(0), _M_buf(__mode) {
00513    this->init(&_M_buf);
00514 }
00515 
00516 template <class _CharT, class _Traits, class _Alloc>
00517 basic_stringstream<_CharT, _Traits, _Alloc>
00518   ::basic_stringstream(const _String& __str, ios_base::openmode __mode)
00519     : basic_iostream<_CharT, _Traits>(0), _M_buf(__str, __mode) {
00520   this->init(&_M_buf);
00521 }
00522 
00523 template <class _CharT, class _Traits, class _Alloc>
00524 basic_stringstream<_CharT, _Traits, _Alloc>::~basic_stringstream()
00525 {}
00526 
00527 _STLP_END_NAMESPACE
00528 
00529 # undef __BSB_int_type__
00530 # undef __BSB_pos_type__
00531 
00532 #endif /* _STLP_SSTREAM_C */
00533 
00534 // Local Variables:
00535 // mode:C++
00536 // End:



Generated on Mon Mar 10 15:32:36 2008 by  doxygen 1.5.1