|
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 return __any_inserted; |
|
160 } |
|
161 |
|
162 if ( this->_S_eof(__c) ) |
|
163 return __any_inserted; |
|
164 |
|
165 __cguard.guard(__c); |
|
166 if ( this->_S_eof( __to->sputc(_Traits::to_char_type(__c)) ) ) { |
|
167 return __any_inserted; |
|
168 } |
|
169 |
|
170 __cguard.release(); |
|
171 __any_inserted = true; |
|
172 } |
|
173 } |
|
174 _STLP_CATCH_ALL { |
|
175 this->_M_handle_exception(ios_base::badbit); |
|
176 return __any_inserted; |
|
177 } |
|
178 } |
|
179 |
|
180 _STLP_MOVE_TO_PRIV_NAMESPACE |
|
181 |
|
182 // Helper function for numeric output. |
|
183 template <class _CharT, class _Traits, class _Number> |
|
184 basic_ostream<_CharT, _Traits>& _STLP_CALL |
|
185 __put_num(basic_ostream<_CharT, _Traits>& __os, _Number __x) { |
|
186 typedef typename basic_ostream<_CharT, _Traits>::sentry _Sentry; |
|
187 _Sentry __sentry(__os); |
|
188 bool __failed = true; |
|
189 |
|
190 if (__sentry) { |
|
191 _STLP_TRY { |
|
192 typedef num_put<_CharT, ostreambuf_iterator<_CharT, _Traits> > _NumPut; |
|
193 __failed = (use_facet<_NumPut>(__os.getloc())).put(ostreambuf_iterator<_CharT, _Traits>(__os.rdbuf()), |
|
194 __os, __os.fill(), |
|
195 __x).failed(); |
|
196 } |
|
197 _STLP_CATCH_ALL { |
|
198 __os._M_handle_exception(ios_base::badbit); |
|
199 } |
|
200 } |
|
201 if (__failed) |
|
202 __os.setstate(ios_base::badbit); |
|
203 return __os; |
|
204 } |
|
205 |
|
206 _STLP_MOVE_TO_STD_NAMESPACE |
|
207 |
|
208 /* |
|
209 * In the following operators we try to limit code bloat by limiting the |
|
210 * number of __put_num instanciations. |
|
211 */ |
|
212 template <class _CharT, class _Traits> |
|
213 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(short __x) { |
|
214 _STLP_STATIC_ASSERT( sizeof(short) <= sizeof(long) ) |
|
215 long __tmp = ((this->flags() & _Basic_ios::basefield) != ios_base::dec) ? |
|
216 __STATIC_CAST(long, __STATIC_CAST(unsigned short, __x)): __x; |
|
217 return _STLP_PRIV __put_num(*this, __tmp); |
|
218 } |
|
219 |
|
220 template <class _CharT, class _Traits> |
|
221 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned short __x) { |
|
222 _STLP_STATIC_ASSERT( sizeof(unsigned short) <= sizeof(unsigned long) ) |
|
223 return _STLP_PRIV __put_num(*this, __STATIC_CAST(unsigned long,__x)); |
|
224 } |
|
225 |
|
226 template <class _CharT, class _Traits> |
|
227 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(int __x) { |
|
228 _STLP_STATIC_ASSERT( sizeof(int) <= sizeof(long) ) |
|
229 long __tmp = ((this->flags() & _Basic_ios::basefield) != ios_base::dec) ? |
|
230 __STATIC_CAST(long, __STATIC_CAST(unsigned int, __x)): __x; |
|
231 return _STLP_PRIV __put_num(*this, __tmp); |
|
232 } |
|
233 |
|
234 template <class _CharT, class _Traits> |
|
235 #if defined (_WIN64) || !defined (_STLP_MSVC) || (_STLP_MSVC < 1300) |
|
236 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned int __x) { |
|
237 _STLP_STATIC_ASSERT( sizeof(unsigned int) <= sizeof(unsigned long) ) |
|
238 #else |
|
239 /* We define this operator with size_t rather than unsigned int to avoid |
|
240 * 64 bits warning. |
|
241 */ |
|
242 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(size_t __x) { |
|
243 _STLP_STATIC_ASSERT( sizeof(size_t) <= sizeof(unsigned long) ) |
|
244 #endif |
|
245 return _STLP_PRIV __put_num(*this, __STATIC_CAST(unsigned long,__x)); |
|
246 } |
|
247 |
|
248 template <class _CharT, class _Traits> |
|
249 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long __x) |
|
250 { return _STLP_PRIV __put_num(*this, __x); } |
|
251 |
|
252 template <class _CharT, class _Traits> |
|
253 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long __x) |
|
254 { return _STLP_PRIV __put_num(*this, __x); } |
|
255 |
|
256 #ifdef _STLP_LONG_LONG |
|
257 template <class _CharT, class _Traits> |
|
258 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<< (_STLP_LONG_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 _STLP_LONG_LONG __x) |
|
263 { return _STLP_PRIV __put_num(*this, __x); } |
|
264 #endif |
|
265 |
|
266 template <class _CharT, class _Traits> |
|
267 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(float __x) |
|
268 { return _STLP_PRIV __put_num(*this, __STATIC_CAST(double,__x)); } |
|
269 |
|
270 template <class _CharT, class _Traits> |
|
271 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(double __x) |
|
272 { return _STLP_PRIV __put_num(*this, __x); } |
|
273 |
|
274 #ifndef _STLP_NO_LONG_DOUBLE |
|
275 template <class _CharT, class _Traits> |
|
276 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long double __x) |
|
277 { return _STLP_PRIV __put_num(*this, __x); } |
|
278 #endif |
|
279 |
|
280 template <class _CharT, class _Traits> |
|
281 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(const void* __x) |
|
282 { return _STLP_PRIV __put_num(*this, __x); } |
|
283 |
|
284 #ifndef _STLP_NO_BOOL |
|
285 template <class _CharT, class _Traits> |
|
286 basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(bool __x) |
|
287 { return _STLP_PRIV __put_num(*this, __x); } |
|
288 #endif |
|
289 |
|
290 template <class _CharT, class _Traits> |
|
291 void basic_ostream<_CharT, _Traits>::_M_put_char(_CharT __c) { |
|
292 sentry __sentry(*this); |
|
293 if (__sentry) { |
|
294 bool __failed = true; |
|
295 _STLP_TRY { |
|
296 streamsize __npad = this->width() > 0 ? this->width() - 1 : 0; |
|
297 // if (__npad <= 1) |
|
298 if (__npad == 0) |
|
299 __failed = this->_S_eof(this->rdbuf()->sputc(__c)); |
|
300 else if ((this->flags() & ios_base::adjustfield) == ios_base::left) { |
|
301 __failed = this->_S_eof(this->rdbuf()->sputc(__c)); |
|
302 __failed = __failed || |
|
303 this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
304 } |
|
305 else { |
|
306 __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
307 __failed = __failed || this->_S_eof(this->rdbuf()->sputc(__c)); |
|
308 } |
|
309 |
|
310 this->width(0); |
|
311 } |
|
312 _STLP_CATCH_ALL { |
|
313 this->_M_handle_exception(ios_base::badbit); |
|
314 } |
|
315 |
|
316 if (__failed) |
|
317 this->setstate(ios_base::badbit); |
|
318 } |
|
319 } |
|
320 |
|
321 template <class _CharT, class _Traits> |
|
322 void basic_ostream<_CharT, _Traits>::_M_put_nowiden(const _CharT* __s) { |
|
323 sentry __sentry(*this); |
|
324 if (__sentry) { |
|
325 bool __failed = true; |
|
326 streamsize __n = _Traits::length(__s); |
|
327 streamsize __npad = this->width() > __n ? this->width() - __n : 0; |
|
328 |
|
329 _STLP_TRY { |
|
330 if (__npad == 0) |
|
331 __failed = this->rdbuf()->sputn(__s, __n) != __n; |
|
332 else if ((this->flags() & ios_base::adjustfield) == ios_base::left) { |
|
333 __failed = this->rdbuf()->sputn(__s, __n) != __n; |
|
334 __failed = __failed || |
|
335 this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
336 } |
|
337 else { |
|
338 __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
339 __failed = __failed || this->rdbuf()->sputn(__s, __n) != __n; |
|
340 } |
|
341 |
|
342 this->width(0); |
|
343 } |
|
344 _STLP_CATCH_ALL { |
|
345 this->_M_handle_exception(ios_base::badbit); |
|
346 } |
|
347 |
|
348 if (__failed) |
|
349 this->setstate(ios_base::failbit); |
|
350 } |
|
351 } |
|
352 |
|
353 template <class _CharT, class _Traits> |
|
354 void basic_ostream<_CharT, _Traits>::_M_put_widen(const char* __s) { |
|
355 sentry __sentry(*this); |
|
356 if (__sentry) { |
|
357 bool __failed = true; |
|
358 streamsize __n = char_traits<char>::length(__s); |
|
359 streamsize __npad = this->width() > __n ? this->width() - __n : 0; |
|
360 |
|
361 _STLP_TRY { |
|
362 if (__npad == 0) |
|
363 __failed = !this->_M_put_widen_aux(__s, __n); |
|
364 else if ((this->flags() & ios_base::adjustfield) == ios_base::left) { |
|
365 __failed = !this->_M_put_widen_aux(__s, __n); |
|
366 __failed = __failed || |
|
367 this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
368 } |
|
369 else { |
|
370 __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
371 __failed = __failed || !this->_M_put_widen_aux(__s, __n); |
|
372 } |
|
373 |
|
374 this->width(0); |
|
375 } |
|
376 _STLP_CATCH_ALL { |
|
377 this->_M_handle_exception(ios_base::badbit); |
|
378 } |
|
379 |
|
380 if (__failed) |
|
381 this->setstate(ios_base::failbit); |
|
382 } |
|
383 } |
|
384 |
|
385 template <class _CharT, class _Traits> |
|
386 bool basic_ostream<_CharT, _Traits>::_M_put_widen_aux(const char* __s, |
|
387 streamsize __n) { |
|
388 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
389 |
|
390 for ( ; __n > 0 ; --__n) |
|
391 if (this->_S_eof(__buf->sputc(this->widen(*__s++)))) |
|
392 return false; |
|
393 return true; |
|
394 } |
|
395 |
|
396 // Unformatted output of a single character. |
|
397 template <class _CharT, class _Traits> |
|
398 basic_ostream<_CharT, _Traits>& |
|
399 basic_ostream<_CharT, _Traits>::put(char_type __c) { |
|
400 sentry __sentry(*this); |
|
401 bool __failed = true; |
|
402 |
|
403 if (__sentry) { |
|
404 _STLP_TRY { |
|
405 __failed = this->_S_eof(this->rdbuf()->sputc(__c)); |
|
406 } |
|
407 _STLP_CATCH_ALL { |
|
408 this->_M_handle_exception(ios_base::badbit); |
|
409 } |
|
410 } |
|
411 |
|
412 if (__failed) |
|
413 this->setstate(ios_base::badbit); |
|
414 |
|
415 return *this; |
|
416 } |
|
417 |
|
418 // Unformatted output of a single character. |
|
419 template <class _CharT, class _Traits> |
|
420 basic_ostream<_CharT, _Traits>& |
|
421 basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) { |
|
422 sentry __sentry(*this); |
|
423 bool __failed = true; |
|
424 |
|
425 if (__sentry) { |
|
426 _STLP_TRY { |
|
427 __failed = this->rdbuf()->sputn(__s, __n) != __n; |
|
428 } |
|
429 _STLP_CATCH_ALL { |
|
430 this->_M_handle_exception(ios_base::badbit); |
|
431 } |
|
432 } |
|
433 |
|
434 if (__failed) |
|
435 this->setstate(ios_base::badbit); |
|
436 |
|
437 return *this; |
|
438 } |
|
439 |
|
440 _STLP_END_NAMESPACE |
|
441 |
|
442 #endif /* _STLP_OSTREAM_C */ |
|
443 |
|
444 // Local Variables: |
|
445 // mode:C++ |
|
446 // End: |