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 #ifndef _STLP_OSTREAM_C
     19 #define _STLP_OSTREAM_C
     20 
     21 #ifndef _STLP_INTERNAL_OSTREAM_H
     22 #  include <stl/_ostream.h>
     23 #endif
     24 
     25 #if !defined (_STLP_INTERNAL_NUM_PUT_H)
     26 #  include <stl/_num_put.h>            // For basic_streambuf and iterators
     27 #endif
     28 
     29 _STLP_BEGIN_NAMESPACE
     30 
     31 //----------------------------------------------------------------------
     32 // Definitions of non-inline member functions.
     33 
     34 // Constructor, destructor
     35 
     36 template <class _CharT, class _Traits>
     37 basic_ostream<_CharT, _Traits>::basic_ostream(basic_streambuf<_CharT, _Traits>* __buf)
     38     : basic_ios<_CharT, _Traits>() {
     39   this->init(__buf);
     40 }
     41 
     42 template <class _CharT, class _Traits>
     43 basic_ostream<_CharT, _Traits>::~basic_ostream()
     44 {}
     45 
     46 // Output directly from a streambuf.
     47 template <class _CharT, class _Traits>
     48 basic_ostream<_CharT, _Traits>&
     49 basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<_CharT, _Traits>* __from) {
     50   sentry __sentry(*this);
     51   if (__sentry) {
     52     if (__from) {
     53       bool __any_inserted = __from->gptr() != __from->egptr()
     54         ? this->_M_copy_buffered(__from, this->rdbuf())
     55         : this->_M_copy_unbuffered(__from, this->rdbuf());
     56       if (!__any_inserted)
     57         this->setstate(ios_base::failbit);
     58     }
     59     else
     60       this->setstate(ios_base::badbit);
     61   }
     62 
     63   return *this;
     64 }
     65 
     66 // Helper functions for the streambuf version of operator<<.  The
     67 // exception-handling code is complicated because exceptions thrown
     68 // while extracting characters are treated differently than exceptions
     69 // thrown while inserting characters.
     70 
     71 template <class _CharT, class _Traits>
     72 bool basic_ostream<_CharT, _Traits>
     73   ::_M_copy_buffered(basic_streambuf<_CharT, _Traits>* __from,
     74                      basic_streambuf<_CharT, _Traits>* __to) {
     75   bool __any_inserted = false;
     76 
     77   while (__from->egptr() != __from->gptr()) {
     78     const ptrdiff_t __avail = __from->egptr() - __from->gptr();
     79 
     80     streamsize __nwritten;
     81     _STLP_TRY {
     82       __nwritten = __to->sputn(__from->gptr(), __avail);
     83       __from->gbump((int)__nwritten);
     84     }
     85     _STLP_CATCH_ALL {
     86       this->_M_handle_exception(ios_base::badbit);
     87       return __any_inserted;
     88     }
     89 
     90     if (__nwritten == __avail) {
     91       _STLP_TRY {
     92         if (this->_S_eof(__from->sgetc()))
     93           return true;
     94         else
     95           __any_inserted = true;
     96       }
     97       _STLP_CATCH_ALL {
     98         this->_M_handle_exception(ios_base::failbit);
     99         return false;
    100       }
    101     }
    102     else if (__nwritten != 0)
    103       return true;
    104     else
    105       return __any_inserted;
    106   }
    107 
    108   // No characters are in the buffer, but we aren't at EOF.  Switch to
    109   // unbuffered mode.
    110   return __any_inserted || this->_M_copy_unbuffered(__from, __to);
    111 }
    112 
    113 /*
    114  * Helper struct (guard) to put back a character in a streambuf
    115  * whenever an exception or an eof occur.
    116  */
    117 template <class _CharT, class _Traits>
    118 struct _SPutBackC {
    119   typedef basic_streambuf<_CharT, _Traits> _StreamBuf;
    120   typedef typename _StreamBuf::int_type int_type;
    121   _SPutBackC(_StreamBuf *pfrom)
    122     : __pfrom(pfrom), __c(0), __do_guard(false) {}
    123   ~_SPutBackC() {
    124     if (__do_guard) {
    125       __pfrom->sputbackc(_Traits::to_char_type(__c));
    126     }
    127   }
    128 
    129   void guard(int_type c) {
    130     __c = c;
    131     __do_guard = true;
    132   }
    133   void release() {
    134     __do_guard = false;
    135   }
    136 
    137 private:
    138   _StreamBuf *__pfrom;
    139   int_type __c;
    140   bool __do_guard;
    141 };
    142 
    143 template <class _CharT, class _Traits>
    144 bool basic_ostream<_CharT, _Traits>
    145   ::_M_copy_unbuffered(basic_streambuf<_CharT, _Traits>* __from,
    146                        basic_streambuf<_CharT, _Traits>* __to) {
    147   typedef _SPutBackC<_CharT, _Traits> _SPutBackCGuard;
    148   bool __any_inserted = false;
    149   int_type __c;
    150 
    151   _STLP_TRY {
    152     _SPutBackCGuard __cguard(__from);
    153     for (;;) {
    154       _STLP_TRY {
    155         __c = __from->sbumpc();
    156       }
    157       _STLP_CATCH_ALL {
    158         this->_M_handle_exception(ios_base::failbit);
    159         break;
    160       }
    161 
    162       if (this->_S_eof(__c))
    163         break;
    164 
    165       __cguard.guard(__c);
    166 #if defined (__DMC__)
    167       _STLP_TRY {
    168 #endif
    169       if (this->_S_eof(__to->sputc(_Traits::to_char_type(__c))))
    170         break;
    171 
    172 #if defined (__DMC__)
    173       }
    174       _STLP_CATCH_ALL {
    175         this->_M_handle_exception(ios_base::badbit);
    176         break;
    177       }
    178 #endif
    179       __cguard.release();
    180       __any_inserted = true;
    181     }
    182   }
    183   _STLP_CATCH_ALL {
    184     this->_M_handle_exception(ios_base::badbit);
    185   }
    186   return __any_inserted;
    187 }
    188 
    189 _STLP_MOVE_TO_PRIV_NAMESPACE
    190 
    191 // Helper function for numeric output.
    192 template <class _CharT, class _Traits, class _Number>
    193 basic_ostream<_CharT, _Traits>&  _STLP_CALL
    194 __put_num(basic_ostream<_CharT, _Traits>& __os, _Number __x) {
    195   typedef typename basic_ostream<_CharT, _Traits>::sentry _Sentry;
    196   _Sentry __sentry(__os);
    197   bool __failed = true;
    198 
    199   if (__sentry) {
    200     _STLP_TRY {
    201       typedef num_put<_CharT, ostreambuf_iterator<_CharT, _Traits> > _NumPut;
    202       __failed = (use_facet<_NumPut>(__os.getloc())).put(ostreambuf_iterator<_CharT, _Traits>(__os.rdbuf()),
    203                                                          __os, __os.fill(),
    204                                                          __x).failed();
    205     }
    206     _STLP_CATCH_ALL {
    207       __os._M_handle_exception(ios_base::badbit);
    208     }
    209   }
    210   if (__failed)
    211     __os.setstate(ios_base::badbit);
    212   return __os;
    213 }
    214 
    215 _STLP_MOVE_TO_STD_NAMESPACE
    216 
    217 /*
    218  * In the following operators we try to limit code bloat by limiting the
    219  * number of __put_num instanciations.
    220  */
    221 template <class _CharT, class _Traits>
    222 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(short __x) {
    223   _STLP_STATIC_ASSERT( sizeof(short) <= sizeof(long) )
    224   long __tmp = ((this->flags() & _Basic_ios::basefield) != ios_base::dec) ?
    225                   __STATIC_CAST(long, __STATIC_CAST(unsigned short, __x)): __x;
    226   return _STLP_PRIV __put_num(*this, __tmp);
    227 }
    228 
    229 template <class _CharT, class _Traits>
    230 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned short __x) {
    231   _STLP_STATIC_ASSERT( sizeof(unsigned short) <= sizeof(unsigned long) )
    232   return _STLP_PRIV __put_num(*this, __STATIC_CAST(unsigned long,__x));
    233 }
    234 
    235 template <class _CharT, class _Traits>
    236 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(int __x) {
    237   _STLP_STATIC_ASSERT( sizeof(int) <= sizeof(long) )
    238   long __tmp = ((this->flags() & _Basic_ios::basefield) != ios_base::dec) ?
    239                   __STATIC_CAST(long, __STATIC_CAST(unsigned int, __x)): __x;
    240   return _STLP_PRIV __put_num(*this, __tmp);
    241 }
    242 
    243 template <class _CharT, class _Traits>
    244 #if defined (_WIN64) || !defined (_STLP_MSVC) || (_STLP_MSVC < 1300)
    245 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned int __x) {
    246   _STLP_STATIC_ASSERT( sizeof(unsigned int) <= sizeof(unsigned long) )
    247 #else
    248 /* We define this operator with size_t rather than unsigned int to avoid
    249  * 64 bits warning.
    250  */
    251 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(size_t __x) {
    252   _STLP_STATIC_ASSERT( sizeof(size_t) <= sizeof(unsigned long) )
    253 #endif
    254   return _STLP_PRIV __put_num(*this,  __STATIC_CAST(unsigned long,__x));
    255 }
    256 
    257 template <class _CharT, class _Traits>
    258 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long __x)
    259 { return _STLP_PRIV __put_num(*this,  __x); }
    260 
    261 template <class _CharT, class _Traits>
    262 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long __x)
    263 { return _STLP_PRIV __put_num(*this,  __x); }
    264 
    265 #ifdef _STLP_LONG_LONG
    266 template <class _CharT, class _Traits>
    267 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (_STLP_LONG_LONG __x)
    268 { return _STLP_PRIV __put_num(*this,  __x); }
    269 
    270 template <class _CharT, class _Traits>
    271 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (unsigned _STLP_LONG_LONG __x)
    272 { return _STLP_PRIV __put_num(*this,  __x); }
    273 #endif
    274 
    275 template <class _CharT, class _Traits>
    276 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(float __x)
    277 { return _STLP_PRIV __put_num(*this,  __STATIC_CAST(double,__x)); }
    278 
    279 template <class _CharT, class _Traits>
    280 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(double __x)
    281 { return _STLP_PRIV __put_num(*this,  __x); }
    282 
    283 #ifndef _STLP_NO_LONG_DOUBLE
    284 template <class _CharT, class _Traits>
    285 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long double __x)
    286 { return _STLP_PRIV __put_num(*this,  __x); }
    287 #endif
    288 
    289 template <class _CharT, class _Traits>
    290 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(const void* __x)
    291 { return _STLP_PRIV __put_num(*this,  __x); }
    292 
    293 #ifndef _STLP_NO_BOOL
    294 template <class _CharT, class _Traits>
    295 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(bool __x)
    296 { return _STLP_PRIV __put_num(*this,  __x); }
    297 #endif
    298 
    299 template <class _CharT, class _Traits>
    300 void basic_ostream<_CharT, _Traits>::_M_put_char(_CharT __c) {
    301   sentry __sentry(*this);
    302   if (__sentry) {
    303     bool __failed = true;
    304     _STLP_TRY {
    305       streamsize __npad = this->width() > 0 ? this->width() - 1 : 0;
    306       //      if (__npad <= 1)
    307       if (__npad == 0)
    308         __failed = this->_S_eof(this->rdbuf()->sputc(__c));
    309       else if ((this->flags() & ios_base::adjustfield) == ios_base::left) {
    310         __failed = this->_S_eof(this->rdbuf()->sputc(__c));
    311         __failed = __failed ||
    312                    this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
    313       }
    314       else {
    315         __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
    316         __failed = __failed || this->_S_eof(this->rdbuf()->sputc(__c));
    317       }
    318 
    319       this->width(0);
    320     }
    321     _STLP_CATCH_ALL {
    322       this->_M_handle_exception(ios_base::badbit);
    323     }
    324 
    325     if (__failed)
    326       this->setstate(ios_base::badbit);
    327   }
    328 }
    329 
    330 template <class _CharT, class _Traits>
    331 void basic_ostream<_CharT, _Traits>::_M_put_nowiden(const _CharT* __s) {
    332   sentry __sentry(*this);
    333   if (__sentry) {
    334     bool __failed = true;
    335     streamsize __n = _Traits::length(__s);
    336     streamsize __npad = this->width() > __n ? this->width() - __n : 0;
    337 
    338     _STLP_TRY {
    339       if (__npad == 0)
    340         __failed = this->rdbuf()->sputn(__s, __n) != __n;
    341       else if ((this->flags() & ios_base::adjustfield) == ios_base::left) {
    342         __failed = this->rdbuf()->sputn(__s, __n) != __n;
    343         __failed = __failed ||
    344                    this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
    345       }
    346       else {
    347         __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
    348         __failed = __failed || this->rdbuf()->sputn(__s, __n) != __n;
    349       }
    350 
    351       this->width(0);
    352     }
    353     _STLP_CATCH_ALL {
    354       this->_M_handle_exception(ios_base::badbit);
    355     }
    356 
    357     if (__failed)
    358       this->setstate(ios_base::failbit);
    359   }
    360 }
    361 
    362 template <class _CharT, class _Traits>
    363 void basic_ostream<_CharT, _Traits>::_M_put_widen(const char* __s) {
    364   sentry __sentry(*this);
    365   if (__sentry) {
    366     bool __failed = true;
    367     streamsize __n = char_traits<char>::length(__s);
    368     streamsize __npad = this->width() > __n ? this->width() - __n : 0;
    369 
    370     _STLP_TRY {
    371       if (__npad == 0)
    372         __failed = !this->_M_put_widen_aux(__s, __n);
    373       else if ((this->flags() & ios_base::adjustfield) == ios_base::left) {
    374         __failed = !this->_M_put_widen_aux(__s, __n);
    375         __failed = __failed ||
    376                    this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
    377       }
    378       else {
    379         __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad;
    380         __failed = __failed || !this->_M_put_widen_aux(__s, __n);
    381       }
    382 
    383       this->width(0);
    384     }
    385     _STLP_CATCH_ALL {
    386       this->_M_handle_exception(ios_base::badbit);
    387     }
    388 
    389     if (__failed)
    390       this->setstate(ios_base::failbit);
    391   }
    392 }
    393 
    394 template <class _CharT, class _Traits>
    395 bool basic_ostream<_CharT, _Traits>::_M_put_widen_aux(const char* __s,
    396                                                       streamsize __n) {
    397   basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf();
    398 
    399   for ( ; __n > 0 ; --__n)
    400     if (this->_S_eof(__buf->sputc(this->widen(*__s++))))
    401       return false;
    402   return true;
    403 }
    404 
    405 // Unformatted output of a single character.
    406 template <class _CharT, class _Traits>
    407 basic_ostream<_CharT, _Traits>&
    408 basic_ostream<_CharT, _Traits>::put(char_type __c) {
    409   sentry __sentry(*this);
    410   bool __failed = true;
    411 
    412   if (__sentry) {
    413     _STLP_TRY {
    414       __failed = this->_S_eof(this->rdbuf()->sputc(__c));
    415     }
    416     _STLP_CATCH_ALL {
    417       this->_M_handle_exception(ios_base::badbit);
    418     }
    419   }
    420 
    421   if (__failed)
    422     this->setstate(ios_base::badbit);
    423 
    424   return *this;
    425 }
    426 
    427 // Unformatted output of a single character.
    428 template <class _CharT, class _Traits>
    429 basic_ostream<_CharT, _Traits>&
    430 basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) {
    431   sentry __sentry(*this);
    432   bool __failed = true;
    433 
    434   if (__sentry) {
    435     _STLP_TRY {
    436       __failed = this->rdbuf()->sputn(__s, __n) != __n;
    437     }
    438     _STLP_CATCH_ALL {
    439       this->_M_handle_exception(ios_base::badbit);
    440     }
    441   }
    442 
    443   if (__failed)
    444     this->setstate(ios_base::badbit);
    445 
    446   return *this;
    447 }
    448 
    449 _STLP_END_NAMESPACE
    450 
    451 #endif /* _STLP_OSTREAM_C */
    452 
    453 // Local Variables:
    454 // mode:C++
    455 // End:
    456