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 36template <class _CharT, class _Traits> 37basic_ostream<_CharT, _Traits>::basic_ostream(basic_streambuf<_CharT, _Traits>* __buf) 38 : basic_ios<_CharT, _Traits>() { 39 this->init(__buf); 40} 41 42template <class _CharT, class _Traits> 43basic_ostream<_CharT, _Traits>::~basic_ostream() 44{} 45 46// Output directly from a streambuf. 47template <class _CharT, class _Traits> 48basic_ostream<_CharT, _Traits>& 49basic_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 71template <class _CharT, class _Traits> 72bool 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 */ 117template <class _CharT, class _Traits> 118struct _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 137private: 138 _StreamBuf *__pfrom; 139 int_type __c; 140 bool __do_guard; 141}; 142 143template <class _CharT, class _Traits> 144bool 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. 192template <class _CharT, class _Traits, class _Number> 193basic_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 */ 221template <class _CharT, class _Traits> 222basic_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 229template <class _CharT, class _Traits> 230basic_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 235template <class _CharT, class _Traits> 236basic_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 243template <class _CharT, class _Traits> 244#if defined (_WIN64) || !defined (_STLP_MSVC) || (_STLP_MSVC < 1300) 245basic_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 */ 251basic_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 257template <class _CharT, class _Traits> 258basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long __x) 259{ return _STLP_PRIV __put_num(*this, __x); } 260 261template <class _CharT, class _Traits> 262basic_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 266template <class _CharT, class _Traits> 267basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (_STLP_LONG_LONG __x) 268{ return _STLP_PRIV __put_num(*this, __x); } 269 270template <class _CharT, class _Traits> 271basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (unsigned _STLP_LONG_LONG __x) 272{ return _STLP_PRIV __put_num(*this, __x); } 273#endif 274 275template <class _CharT, class _Traits> 276basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(float __x) 277{ return _STLP_PRIV __put_num(*this, __STATIC_CAST(double,__x)); } 278 279template <class _CharT, class _Traits> 280basic_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 284template <class _CharT, class _Traits> 285basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long double __x) 286{ return _STLP_PRIV __put_num(*this, __x); } 287#endif 288 289template <class _CharT, class _Traits> 290basic_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 294template <class _CharT, class _Traits> 295basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(bool __x) 296{ return _STLP_PRIV __put_num(*this, __x); } 297#endif 298 299template <class _CharT, class _Traits> 300void 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 330template <class _CharT, class _Traits> 331void 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 362template <class _CharT, class _Traits> 363void 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 394template <class _CharT, class _Traits> 395bool 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. 406template <class _CharT, class _Traits> 407basic_ostream<_CharT, _Traits>& 408basic_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. 428template <class _CharT, class _Traits> 429basic_ostream<_CharT, _Traits>& 430basic_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