/home/ntakagi/work/STLport-5.1.5/stlport/stl/_ostream.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 #ifndef _STLP_OSTREAM_C
00019 #define _STLP_OSTREAM_C
00020 
00021 #ifndef _STLP_INTERNAL_OSTREAM_H
00022 #  include <stl/_ostream.h>
00023 #endif
00024 
00025 #if !defined (_STLP_INTERNAL_NUM_PUT_H)
00026 #  include <stl/_num_put.h>            // For basic_streambuf and iterators
00027 #endif
00028 
00029 _STLP_BEGIN_NAMESPACE
00030 
00031 //----------------------------------------------------------------------
00032 // Definitions of non-inline member functions.
00033 
00034 // Constructor, destructor
00035 
00036 template <class _CharT, class _Traits>
00037 basic_ostream<_CharT, _Traits>::basic_ostream(basic_streambuf<_CharT, _Traits>* __buf)
00038     : basic_ios<_CharT, _Traits>() {
00039   this->init(__buf);
00040 }
00041 
00042 template <class _CharT, class _Traits>
00043 basic_ostream<_CharT, _Traits>::~basic_ostream()
00044 {}
00045 
00046 // Output directly from a streambuf.
00047 template <class _CharT, class _Traits>
00048 basic_ostream<_CharT, _Traits>&
00049 basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<_CharT, _Traits>* __from) {
00050   sentry __sentry(*this);
00051   if (__sentry) {
00052     if (__from) {
00053       bool __any_inserted = __from->gptr() != __from->egptr()
00054         ? this->_M_copy_buffered(__from, this->rdbuf())
00055         : this->_M_copy_unbuffered(__from, this->rdbuf());
00056       if (!__any_inserted)
00057         this->setstate(ios_base::failbit);
00058     }
00059     else
00060       this->setstate(ios_base::badbit);
00061   }
00062 
00063   return *this;
00064 }
00065 
00066 // Helper functions for the streambuf version of operator<<.  The
00067 // exception-handling code is complicated because exceptions thrown
00068 // while extracting characters are treated differently than exceptions
00069 // thrown while inserting characters.
00070 
00071 template <class _CharT, class _Traits>
00072 bool basic_ostream<_CharT, _Traits>
00073   ::_M_copy_buffered(basic_streambuf<_CharT, _Traits>* __from,
00074                      basic_streambuf<_CharT, _Traits>* __to) {
00075   bool __any_inserted = false;
00076 
00077   while (__from->egptr() != __from->gptr()) {
00078     const ptrdiff_t __avail = __from->egptr() - __from->gptr();
00079 
00080     streamsize __nwritten;
00081     _STLP_TRY {
00082       __nwritten = __to->sputn(__from->gptr(), __avail);
00083       __from->gbump((int)__nwritten);
00084     }
00085     _STLP_CATCH_ALL {
00086       this->_M_handle_exception(ios_base::badbit);
00087       return __any_inserted;
00088     }
00089 
00090     if (__nwritten == __avail) {
00091       _STLP_TRY {
00092         if (this->_S_eof(__from->sgetc()))
00093           return true;
00094         else
00095           __any_inserted = true;
00096       }
00097       _STLP_CATCH_ALL {
00098         this->_M_handle_exception(ios_base::failbit);
00099         return false;
00100       }
00101     }
00102     else if (__nwritten != 0)
00103       return true;
00104     else
00105       return __any_inserted;
00106   }
00107 
00108   // No characters are in the buffer, but we aren't at EOF.  Switch to
00109   // unbuffered mode.
00110   return __any_inserted || this->_M_copy_unbuffered(__from, __to);
00111 }
00112 
00113 /*
00114  * Helper struct (guard) to put back a character in a streambuf
00115  * whenever an exception or an eof occur.
00116  */
00117 template <class _CharT, class _Traits>
00118 struct _SPutBackC {
00119   typedef basic_streambuf<_CharT, _Traits> _StreamBuf;
00120   typedef typename _StreamBuf::int_type int_type;
00121   _SPutBackC(_StreamBuf *pfrom)
00122     : __pfrom(pfrom), __c(0), __do_guard(false) {}
00123   ~_SPutBackC() {
00124     if (__do_guard) {
00125       __pfrom->sputbackc(_Traits::to_char_type(__c));
00126     }
00127   }
00128 
00129   void guard(int_type c) {
00130     __c = c;
00131     __do_guard = true;
00132   }
00133   void release() {
00134     __do_guard = false;
00135   }
00136 
00137 private:
00138   _StreamBuf *__pfrom;
00139   int_type __c;
00140   bool __do_guard;
00141 };
00142 
00143 template <class _CharT, class _Traits>
00144 bool basic_ostream<_CharT, _Traits>
00145   ::_M_copy_unbuffered(basic_streambuf<_CharT, _Traits>* __from,
00146                        basic_streambuf<_CharT, _Traits>* __to) {
00147   typedef _SPutBackC<_CharT, _Traits> _SPutBackCGuard;
00148   bool __any_inserted = false;
00149   int_type __c;
00150 
00151   _STLP_TRY {
00152     _SPutBackCGuard __cguard(__from);
00153     for (;;) {
00154       _STLP_TRY {
00155         __c = __from->sbumpc();
00156       }
00157       _STLP_CATCH_ALL {
00158         this->_M_handle_exception(ios_base::failbit);
00159         return __any_inserted;
00160       }
00161 
00162       if ( this->_S_eof(__c) )
00163         return __any_inserted;
00164 
00165       __cguard.guard(__c);
00166       if ( this->_S_eof( __to->sputc(_Traits::to_char_type(__c)) ) ) {
00167         return __any_inserted;
00168       }
00169 
00170       __cguard.release();
00171       __any_inserted = true;
00172     }
00173   }
00174   _STLP_CATCH_ALL {
00175     this->_M_handle_exception(ios_base::badbit);
00176     return __any_inserted;
00177   }
00178 }
00179 
00180 _STLP_MOVE_TO_PRIV_NAMESPACE
00181 
00182 // Helper function for numeric output.
00183 template <class _CharT, class _Traits, class _Number>
00184 basic_ostream<_CharT, _Traits>&  _STLP_CALL
00185 __put_num(basic_ostream<_CharT, _Traits>& __os, _Number __x) {
00186   typedef typename basic_ostream<_CharT, _Traits>::sentry _Sentry;
00187   _Sentry __sentry(__os);
00188   bool __failed = true;
00189 
00190   if (__sentry) {
00191     _STLP_TRY {
00192       typedef num_put<_CharT, ostreambuf_iterator<_CharT, _Traits> > _NumPut;
00193       __failed = (use_facet<_NumPut>(__os.getloc())).put(ostreambuf_iterator<_CharT, _Traits>(__os.rdbuf()),
00194                                                          __os, __os.fill(),
00195                                                          __x).failed();
00196     }
00197     _STLP_CATCH_ALL {
00198       __os._M_handle_exception(ios_base::badbit);
00199     }
00200   }
00201   if (__failed)
00202     __os.setstate(ios_base::badbit);
00203   return __os;
00204 }
00205 
00206 _STLP_MOVE_TO_STD_NAMESPACE
00207 
00208 /*
00209  * In the following operators we try to limit code bloat by limiting the
00210  * number of __put_num instanciations.
00211  */
00212 template <class _CharT, class _Traits>
00213 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(short __x) {
00214   _STLP_STATIC_ASSERT( sizeof(short) <= sizeof(long) )
00215   long __tmp = ((this->flags() & _Basic_ios::basefield) != ios_base::dec) ?
00216                   __STATIC_CAST(long, __STATIC_CAST(unsigned short, __x)): __x;
00217   return _STLP_PRIV __put_num(*this, __tmp);
00218 }
00219 
00220 template <class _CharT, class _Traits>
00221 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned short __x) {
00222   _STLP_STATIC_ASSERT( sizeof(unsigned short) <= sizeof(unsigned long) )
00223   return _STLP_PRIV __put_num(*this, __STATIC_CAST(unsigned long,__x));
00224 }
00225 
00226 template <class _CharT, class _Traits>
00227 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(int __x) {
00228   _STLP_STATIC_ASSERT( sizeof(int) <= sizeof(long) )
00229   long __tmp = ((this->flags() & _Basic_ios::basefield) != ios_base::dec) ?
00230                   __STATIC_CAST(long, __STATIC_CAST(unsigned int, __x)): __x;
00231   return _STLP_PRIV __put_num(*this, __tmp);
00232 }
00233 
00234 template <class _CharT, class _Traits>
00235 #if defined (_WIN64) || !defined (_STLP_MSVC) || (_STLP_MSVC < 1300)
00236 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned int __x) {
00237   _STLP_STATIC_ASSERT( sizeof(unsigned int) <= sizeof(unsigned long) )
00238 #else
00239 /* We define this operator with size_t rather than unsigned int to avoid
00240  * 64 bits warning.
00241  */
00242 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(size_t __x) {
00243   _STLP_STATIC_ASSERT( sizeof(size_t) <= sizeof(unsigned long) )
00244 #endif
00245   return _STLP_PRIV __put_num(*this,  __STATIC_CAST(unsigned long,__x));
00246 }
00247 
00248 template <class _CharT, class _Traits>
00249 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long __x)
00250 { return _STLP_PRIV __put_num(*this,  __x); }
00251 
00252 template <class _CharT, class _Traits>
00253 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long __x)
00254 { return _STLP_PRIV __put_num(*this,  __x); }
00255 
00256 #ifdef _STLP_LONG_LONG
00257 template <class _CharT, class _Traits>
00258 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (_STLP_LONG_LONG __x)
00259 { return _STLP_PRIV __put_num(*this,  __x); }
00260 
00261 template <class _CharT, class _Traits>
00262 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (unsigned _STLP_LONG_LONG __x)
00263 { return _STLP_PRIV __put_num(*this,  __x); }
00264 #endif
00265 
00266 template <class _CharT, class _Traits>
00267 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(float __x)
00268 { return _STLP_PRIV __put_num(*this,  __STATIC_CAST(double,__x)); }
00269 
00270 template <class _CharT, class _Traits>
00271 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(double __x)
00272 { return _STLP_PRIV __put_num(*this,  __x); }
00273 
00274 #ifndef _STLP_NO_LONG_DOUBLE
00275 template <class _CharT, class _Traits>
00276 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long double __x)
00277 { return _STLP_PRIV __put_num(*this,  __x); }
00278 #endif
00279 
00280 template <class _CharT, class _Traits>
00281 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(const void* __x)
00282 { return _STLP_PRIV __put_num(*this,  __x); }
00283 
00284 #ifndef _STLP_NO_BOOL
00285 template <class _CharT, class _Traits>
00286 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(bool __x)
00287 { return _STLP_PRIV __put_num(*this,  __x); }
00288 #endif
00289 
00290 template <class _CharT, class _Traits>
00291 void basic_ostream<_CharT, _Traits>::_M_put_char(_CharT __c) {
00292   sentry __sentry(*this);
00293   if (__sentry) {
00294     bool __failed = true;
00295     _STLP_TRY {
00296       streamsize __npad = this->width() > 0 ? this->width() - 1 : 0;
00297       //      if (__npad <= 1)
00298       if (__npad == 0)
00299         __failed = this->_S_eof(this->rdbuf()->sputc(__c));
00300       else if ((this->flags() & ios_base::adjustfield) == ios_base::left) {
00301         __failed = this->_S_eof(this->rdbuf()->sputc(__c));
00302         __failed = __failed ||
00303                    this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
00304       }
00305       else {
00306         __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
00307         __failed = __failed || this->_S_eof(this->rdbuf()->sputc(__c));
00308       }
00309 
00310       this->width(0);
00311     }
00312     _STLP_CATCH_ALL {
00313       this->_M_handle_exception(ios_base::badbit);
00314     }
00315 
00316     if (__failed)
00317       this->setstate(ios_base::badbit);
00318   }
00319 }
00320 
00321 template <class _CharT, class _Traits>
00322 void basic_ostream<_CharT, _Traits>::_M_put_nowiden(const _CharT* __s) {
00323   sentry __sentry(*this);
00324   if (__sentry) {
00325     bool __failed = true;
00326     streamsize __n = _Traits::length(__s);
00327     streamsize __npad = this->width() > __n ? this->width() - __n : 0;
00328 
00329     _STLP_TRY {
00330       if (__npad == 0)
00331         __failed = this->rdbuf()->sputn(__s, __n) != __n;
00332       else if ((this->flags() & ios_base::adjustfield) == ios_base::left) {
00333         __failed = this->rdbuf()->sputn(__s, __n) != __n;
00334         __failed = __failed ||
00335                    this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
00336       }
00337       else {
00338         __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
00339         __failed = __failed || this->rdbuf()->sputn(__s, __n) != __n;
00340       }
00341 
00342       this->width(0);
00343     }
00344     _STLP_CATCH_ALL {
00345       this->_M_handle_exception(ios_base::badbit);
00346     }
00347 
00348     if (__failed)
00349       this->setstate(ios_base::failbit);
00350   }
00351 }
00352 
00353 template <class _CharT, class _Traits>
00354 void basic_ostream<_CharT, _Traits>::_M_put_widen(const char* __s) {
00355   sentry __sentry(*this);
00356   if (__sentry) {
00357     bool __failed = true;
00358     streamsize __n = char_traits<char>::length(__s);
00359     streamsize __npad = this->width() > __n ? this->width() - __n : 0;
00360 
00361     _STLP_TRY {
00362       if (__npad == 0)
00363         __failed = !this->_M_put_widen_aux(__s, __n);
00364       else if ((this->flags() & ios_base::adjustfield) == ios_base::left) {
00365         __failed = !this->_M_put_widen_aux(__s, __n);
00366         __failed = __failed ||
00367                    this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
00368       }
00369       else {
00370         __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
00371         __failed = __failed || !this->_M_put_widen_aux(__s, __n);
00372       }
00373 
00374       this->width(0);
00375     }
00376     _STLP_CATCH_ALL {
00377       this->_M_handle_exception(ios_base::badbit);
00378     }
00379 
00380     if (__failed)
00381       this->setstate(ios_base::failbit);
00382   }
00383 }
00384 
00385 template <class _CharT, class _Traits>
00386 bool basic_ostream<_CharT, _Traits>::_M_put_widen_aux(const char* __s,
00387                                                       streamsize __n) {
00388   basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf();
00389 
00390   for ( ; __n > 0 ; --__n)
00391     if (this->_S_eof(__buf->sputc(this->widen(*__s++))))
00392       return false;
00393   return true;
00394 }
00395 
00396 // Unformatted output of a single character.
00397 template <class _CharT, class _Traits>
00398 basic_ostream<_CharT, _Traits>&
00399 basic_ostream<_CharT, _Traits>::put(char_type __c) {
00400   sentry __sentry(*this);
00401   bool __failed = true;
00402 
00403   if (__sentry) {
00404     _STLP_TRY {
00405       __failed = this->_S_eof(this->rdbuf()->sputc(__c));
00406     }
00407     _STLP_CATCH_ALL {
00408       this->_M_handle_exception(ios_base::badbit);
00409     }
00410   }
00411 
00412   if (__failed)
00413     this->setstate(ios_base::badbit);
00414 
00415   return *this;
00416 }
00417 
00418 // Unformatted output of a single character.
00419 template <class _CharT, class _Traits>
00420 basic_ostream<_CharT, _Traits>&
00421 basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) {
00422   sentry __sentry(*this);
00423   bool __failed = true;
00424 
00425   if (__sentry) {
00426     _STLP_TRY {
00427       __failed = this->rdbuf()->sputn(__s, __n) != __n;
00428     }
00429     _STLP_CATCH_ALL {
00430       this->_M_handle_exception(ios_base::badbit);
00431     }
00432   }
00433 
00434   if (__failed)
00435     this->setstate(ios_base::badbit);
00436 
00437   return *this;
00438 }
00439 
00440 _STLP_END_NAMESPACE
00441 
00442 #endif /* _STLP_OSTREAM_C */
00443 
00444 // Local Variables:
00445 // mode:C++
00446 // End:



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