|
1 /* |
|
2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. |
|
3 * |
|
4 * Copyright (c) 1999 |
|
5 * Silicon Graphics Computer Systems, Inc. |
|
6 * |
|
7 * Copyright (c) 1999 |
|
8 * Boris Fomitchev |
|
9 * |
|
10 * This material is provided "as is", with absolutely no warranty expressed |
|
11 * or implied. Any use is at your own risk. |
|
12 * |
|
13 * Permission to use or copy this software for any purpose is hereby granted |
|
14 * without fee, provided the above notices are retained on all copies. |
|
15 * Permission to modify the code and to distribute modified code is granted, |
|
16 * provided the above notices are retained, and a notice that the code was |
|
17 * modified is included with the above copyright notice. |
|
18 * |
|
19 */ |
|
20 #ifndef _STLP_OSTREAM_C |
|
21 #define _STLP_OSTREAM_C |
|
22 |
|
23 |
|
24 #ifndef _STLP_INTERNAL_OSTREAM_H |
|
25 # include <stl/_ostream.h> |
|
26 #endif |
|
27 |
|
28 #if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) |
|
29 |
|
30 #if !defined (_STLP_INTERNAL_NUM_PUT_H) |
|
31 # include <stl/_num_put.h> // For basic_streambuf and iterators |
|
32 #endif |
|
33 |
|
34 _STLP_BEGIN_NAMESPACE |
|
35 |
|
36 // Helper functions for istream<>::sentry constructor. |
|
37 template <class _CharT, class _Traits> |
|
38 bool |
|
39 _M_init(basic_ostream<_CharT, _Traits>& __str) { |
|
40 if (__str.good()) { |
|
41 // boris : check if this is needed ! |
|
42 if (!__str.rdbuf()) |
|
43 __str.setstate(ios_base::badbit); |
|
44 if (__str.tie()) |
|
45 __str.tie()->flush(); |
|
46 return __str.good(); |
|
47 } else |
|
48 return false; |
|
49 } |
|
50 |
|
51 //---------------------------------------------------------------------- |
|
52 // Definitions of non-inline member functions. |
|
53 |
|
54 // Constructor, destructor |
|
55 |
|
56 template <class _CharT, class _Traits> |
|
57 _STLP_EXP_DECLSPEC basic_ostream<_CharT, _Traits> |
|
58 ::basic_ostream(basic_streambuf<_CharT, _Traits>* __buf) |
|
59 : basic_ios<_CharT, _Traits>() |
|
60 { |
|
61 this->init(__buf); |
|
62 } |
|
63 |
|
64 template <class _CharT, class _Traits> |
|
65 _STLP_EXP_DECLSPEC basic_ostream<_CharT, _Traits>::~basic_ostream() |
|
66 {} |
|
67 |
|
68 // Output directly from a streambuf. |
|
69 template <class _CharT, class _Traits> |
|
70 _STLP_EXP_DECLSPEC basic_ostream<_CharT, _Traits>& |
|
71 basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<_CharT, _Traits>* __from) |
|
72 { |
|
73 sentry __sentry(*this); |
|
74 if (__sentry) { |
|
75 if (__from) { |
|
76 bool __any_inserted = __from->gptr() != __from->egptr() |
|
77 ? this->_M_copy_buffered(__from, this->rdbuf()) |
|
78 : this->_M_copy_unbuffered(__from, this->rdbuf()); |
|
79 if (!__any_inserted) |
|
80 this->setstate(ios_base::failbit); |
|
81 } |
|
82 else |
|
83 this->setstate(ios_base::badbit); |
|
84 } |
|
85 |
|
86 return *this; |
|
87 } |
|
88 |
|
89 // Helper functions for the streambuf version of operator<<. The |
|
90 // exception-handling code is complicated because exceptions thrown |
|
91 // while extracting characters are treated differently than exceptions |
|
92 // thrown while inserting characters. |
|
93 |
|
94 template <class _CharT, class _Traits> |
|
95 bool basic_ostream<_CharT, _Traits> |
|
96 ::_M_copy_buffered(basic_streambuf<_CharT, _Traits>* __from, |
|
97 basic_streambuf<_CharT, _Traits>* __to) |
|
98 { |
|
99 bool __any_inserted = false; |
|
100 |
|
101 while (__from->egptr() != __from->gptr()) { |
|
102 const ptrdiff_t __avail = __from->egptr() - __from->gptr(); |
|
103 |
|
104 streamsize __nwritten; |
|
105 _STLP_TRY { |
|
106 __nwritten = __to->sputn(__from->gptr(), __avail); |
|
107 __from->gbump((int)__nwritten); |
|
108 } |
|
109 _STLP_CATCH_ALL { |
|
110 this->_M_handle_exception(ios_base::badbit); |
|
111 return __any_inserted; |
|
112 } |
|
113 |
|
114 if (__nwritten == __avail) { |
|
115 _STLP_TRY { |
|
116 if (this->_S_eof(__from->sgetc())) |
|
117 return true; |
|
118 else |
|
119 __any_inserted = true; |
|
120 } |
|
121 _STLP_CATCH_ALL { |
|
122 this->_M_handle_exception(ios_base::failbit); |
|
123 return false; |
|
124 } |
|
125 } |
|
126 |
|
127 else if (__nwritten != 0) |
|
128 return true; |
|
129 |
|
130 else |
|
131 return __any_inserted; |
|
132 } |
|
133 |
|
134 // No characters are in the buffer, but we aren't at EOF. Switch to |
|
135 // unbuffered mode. |
|
136 return __any_inserted || this->_M_copy_unbuffered(__from, __to); |
|
137 } |
|
138 |
|
139 template <class _CharT, class _Traits> |
|
140 bool basic_ostream<_CharT, _Traits> |
|
141 ::_M_copy_unbuffered(basic_streambuf<_CharT, _Traits>* __from, |
|
142 basic_streambuf<_CharT, _Traits>* __to) |
|
143 { |
|
144 bool __any_inserted = false; |
|
145 |
|
146 #ifdef __SYMBIAN32__ |
|
147 int_type __c; |
|
148 _STLP_TRY { |
|
149 __c = __from->sgetc();; |
|
150 } |
|
151 _STLP_CATCH_ALL { |
|
152 this->_M_handle_exception(ios_base::failbit); |
|
153 return __any_inserted; |
|
154 } |
|
155 for(;;){ |
|
156 |
|
157 if (this->_S_eof(__c)) |
|
158 return __any_inserted; |
|
159 |
|
160 else { |
|
161 int_type __tmp; |
|
162 _STLP_TRY { |
|
163 __tmp = __to->sputc(__c); |
|
164 } |
|
165 _STLP_CATCH_ALL { |
|
166 this->_M_handle_exception(ios_base::badbit); |
|
167 return __any_inserted; |
|
168 } |
|
169 |
|
170 if (this->_S_eof(__tmp)) { |
|
171 break; |
|
172 } |
|
173 else |
|
174 __any_inserted = true; |
|
175 } |
|
176 _STLP_TRY { |
|
177 __c = __from->snextc(); |
|
178 } |
|
179 _STLP_CATCH_ALL { |
|
180 this->_M_handle_exception(ios_base::failbit); |
|
181 return __any_inserted; |
|
182 } |
|
183 } |
|
184 #else |
|
185 while (true) { |
|
186 int_type __c; |
|
187 _STLP_TRY { |
|
188 __c = __from->sbumpc(); |
|
189 } |
|
190 _STLP_CATCH_ALL { |
|
191 this->_M_handle_exception(ios_base::failbit); |
|
192 return __any_inserted; |
|
193 } |
|
194 |
|
195 if (this->_S_eof(__c)) |
|
196 return __any_inserted; |
|
197 |
|
198 else { |
|
199 int_type __tmp; |
|
200 _STLP_TRY { |
|
201 __tmp = __to->sputc(__c); |
|
202 } |
|
203 _STLP_CATCH_ALL { |
|
204 this->_M_handle_exception(ios_base::badbit); |
|
205 return __any_inserted; |
|
206 } |
|
207 |
|
208 if (this->_S_eof(__tmp)) { |
|
209 _STLP_TRY { |
|
210 /* __tmp = */ __from->sputbackc(__c); |
|
211 } |
|
212 _STLP_CATCH_ALL { |
|
213 this->_M_handle_exception(ios_base::badbit); |
|
214 return __any_inserted; |
|
215 } |
|
216 } |
|
217 else |
|
218 __any_inserted = true; |
|
219 } |
|
220 } |
|
221 #endif |
|
222 return __any_inserted; |
|
223 } |
|
224 |
|
225 // Helper function for numeric output. |
|
226 |
|
227 template <class _CharT, class _Traits, class _Number> |
|
228 basic_ostream<_CharT, _Traits>& |
|
229 _M_put_num(basic_ostream<_CharT, _Traits>& __os, _Number __x) |
|
230 { |
|
231 typedef typename basic_ostream<_CharT, _Traits>::sentry _Sentry; |
|
232 _Sentry __sentry(__os); |
|
233 bool __failed = true; |
|
234 |
|
235 if (__sentry) { |
|
236 _STLP_TRY { |
|
237 typedef num_put<_CharT, ostreambuf_iterator<_CharT, _Traits> > _NumPut; |
|
238 __failed = (use_facet<_NumPut>(__os.getloc())).put( |
|
239 ostreambuf_iterator<_CharT, _Traits>(__os.rdbuf()), |
|
240 __os, __os.fill(), |
|
241 __x).failed(); |
|
242 } |
|
243 _STLP_CATCH_ALL { |
|
244 __os._M_handle_exception(ios_base::badbit); |
|
245 } |
|
246 } |
|
247 if (__failed) |
|
248 __os.setstate(ios_base::badbit); |
|
249 return __os; |
|
250 } |
|
251 |
|
252 # if defined (_STLP_USE_TEMPLATE_EXPORT) && defined (__BUILDING_STLPORT) |
|
253 _STLP_EXPORT_TEMPLATE _STLP_EXP_DECLSPEC basic_ostream<char, char_traits<char> >& _STLP_CALL |
|
254 _M_put_num(basic_ostream<char, char_traits<char> >&, unsigned long); |
|
255 _STLP_EXPORT_TEMPLATE _STLP_EXP_DECLSPEC basic_ostream<char, char_traits<char> >& _STLP_CALL |
|
256 _M_put_num(basic_ostream<char, char_traits<char> >&, long); |
|
257 # if defined (_STLP_LONG_LONG) |
|
258 _STLP_EXPORT_TEMPLATE _STLP_EXP_DECLSPEC basic_ostream<char, char_traits<char> >& _STLP_CALL |
|
259 _M_put_num(basic_ostream<char, char_traits<char> >&, unsigned _STLP_LONG_LONG); |
|
260 _STLP_EXPORT_TEMPLATE _STLP_EXP_DECLSPEC basic_ostream<char, char_traits<char> >& _STLP_CALL |
|
261 _M_put_num(basic_ostream<char, char_traits<char> >&, _STLP_LONG_LONG ); |
|
262 # endif |
|
263 # endif |
|
264 |
|
265 template <class _CharT, class _Traits> |
|
266 void basic_ostream<_CharT, _Traits>::_M_put_char(_CharT __c) |
|
267 { |
|
268 sentry __sentry(*this); |
|
269 if (__sentry) { |
|
270 bool __failed = true; |
|
271 _STLP_TRY { |
|
272 streamsize __npad = this->width() > 0 ? this->width() - 1 : 0; |
|
273 // if (__npad <= 1) |
|
274 if (__npad == 0) |
|
275 __failed = this->_S_eof(this->rdbuf()->sputc(__c)); |
|
276 else if ((this->flags() & ios_base::adjustfield) == ios_base::left) { |
|
277 __failed = this->_S_eof(this->rdbuf()->sputc(__c)); |
|
278 __failed = __failed || |
|
279 this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
280 } |
|
281 else { |
|
282 __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
283 __failed = __failed || this->_S_eof(this->rdbuf()->sputc(__c)); |
|
284 } |
|
285 |
|
286 this->width(0); |
|
287 } |
|
288 _STLP_CATCH_ALL { |
|
289 this->_M_handle_exception(ios_base::badbit); |
|
290 } |
|
291 |
|
292 if (__failed) |
|
293 this->setstate(ios_base::badbit); |
|
294 } |
|
295 } |
|
296 |
|
297 template <class _CharT, class _Traits> |
|
298 void basic_ostream<_CharT, _Traits>::_M_put_nowiden(const _CharT* __s) |
|
299 { |
|
300 sentry __sentry(*this); |
|
301 if (__sentry) { |
|
302 bool __failed = true; |
|
303 streamsize __n = _Traits::length(__s); |
|
304 streamsize __npad = this->width() > __n ? this->width() - __n : 0; |
|
305 |
|
306 _STLP_TRY { |
|
307 if (__npad == 0) |
|
308 __failed = this->rdbuf()->sputn(__s, __n) != __n; |
|
309 else if ((this->flags() & ios_base::adjustfield) == ios_base::left) { |
|
310 __failed = this->rdbuf()->sputn(__s, __n) != __n; |
|
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->rdbuf()->sputn(__s, __n) != __n; |
|
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::failbit); |
|
327 } |
|
328 } |
|
329 |
|
330 template <class _CharT, class _Traits> |
|
331 void basic_ostream<_CharT, _Traits>::_M_put_widen(const char* __s) |
|
332 { |
|
333 sentry __sentry(*this); |
|
334 if (__sentry) { |
|
335 bool __failed = true; |
|
336 streamsize __n = char_traits<char>::length(__s); |
|
337 streamsize __npad = this->width() > __n ? this->width() - __n : 0; |
|
338 |
|
339 _STLP_TRY { |
|
340 if (__npad == 0) |
|
341 __failed = !this->_M_put_widen_aux(__s, __n); |
|
342 else if ((this->flags() & ios_base::adjustfield) == ios_base::left) { |
|
343 __failed = !this->_M_put_widen_aux(__s, __n); |
|
344 __failed = __failed || |
|
345 this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
346 } |
|
347 else { |
|
348 __failed = this->rdbuf()->_M_sputnc(this->fill(), __npad) != __npad; |
|
349 __failed = __failed || !this->_M_put_widen_aux(__s, __n); |
|
350 } |
|
351 |
|
352 this->width(0); |
|
353 } |
|
354 _STLP_CATCH_ALL { |
|
355 this->_M_handle_exception(ios_base::badbit); |
|
356 } |
|
357 |
|
358 if (__failed) |
|
359 this->setstate(ios_base::failbit); |
|
360 } |
|
361 } |
|
362 |
|
363 template <class _CharT, class _Traits> |
|
364 bool basic_ostream<_CharT, _Traits>::_M_put_widen_aux(const char* __s, |
|
365 streamsize __n) |
|
366 { |
|
367 basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); |
|
368 |
|
369 for ( ; __n > 0 ; --__n) |
|
370 if (this->_S_eof(__buf->sputc(this->widen(*__s++)))) |
|
371 return false; |
|
372 return true; |
|
373 } |
|
374 |
|
375 // Unformatted output of a single character. |
|
376 template <class _CharT, class _Traits> |
|
377 _STLP_EXP_DECLSPEC basic_ostream<_CharT, _Traits>& |
|
378 basic_ostream<_CharT, _Traits>::put(char_type __c) |
|
379 { |
|
380 sentry __sentry(*this); |
|
381 bool __failed = true; |
|
382 |
|
383 if (__sentry) { |
|
384 _STLP_TRY { |
|
385 __failed = this->_S_eof(this->rdbuf()->sputc(__c)); |
|
386 } |
|
387 _STLP_CATCH_ALL { |
|
388 this->_M_handle_exception(ios_base::badbit); |
|
389 } |
|
390 } |
|
391 |
|
392 if (__failed) |
|
393 this->setstate(ios_base::badbit); |
|
394 |
|
395 return *this; |
|
396 } |
|
397 |
|
398 // Unformatted output of a single character. |
|
399 template <class _CharT, class _Traits> |
|
400 _STLP_EXP_DECLSPEC basic_ostream<_CharT, _Traits>& |
|
401 basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) |
|
402 { |
|
403 sentry __sentry(*this); |
|
404 bool __failed = true; |
|
405 |
|
406 if (__sentry) { |
|
407 _STLP_TRY { |
|
408 __failed = this->rdbuf()->sputn(__s, __n) != __n; |
|
409 } |
|
410 _STLP_CATCH_ALL { |
|
411 this->_M_handle_exception(ios_base::badbit); |
|
412 } |
|
413 } |
|
414 |
|
415 if (__failed) |
|
416 this->setstate(ios_base::badbit); |
|
417 |
|
418 return *this; |
|
419 } |
|
420 |
|
421 _STLP_END_NAMESPACE |
|
422 |
|
423 #endif /* defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) */ |
|
424 |
|
425 #endif /* _STLP_OSTREAM_C */ |