_ostream.c 13 KB

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