OSDN Git Service

2001-03-22 Greg Bumgardner <bumgard@roguewave.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / ostream.tcc
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING.  If not, write to the Free
16 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 // USA.
18
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction.  Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License.  This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27
28 //
29 // ISO C++ 14882: 27.6.2  Output streams
30 //
31
32 #include <bits/std_locale.h>
33
34 namespace std {
35
36   template<typename _CharT, typename _Traits>
37     basic_ostream<_CharT, _Traits>::sentry::
38     sentry(basic_ostream<_CharT,_Traits>& __os)
39     : _M_ok(__os.good()), _M_os(__os)
40     {
41       // XXX MT 
42       if (_M_ok && __os.tie())
43         __os.tie()->flush();  
44     }
45   
46   template<typename _CharT, typename _Traits>
47     basic_ostream<_CharT, _Traits>& 
48     basic_ostream<_CharT, _Traits>::
49     operator<<(__ostream_type& (*__pf)(__ostream_type&))
50     {
51       sentry __cerb(*this);
52       if (__cerb)
53         { 
54           try {
55               __pf(*this);
56           }
57           catch(exception& __fail){
58             // 27.6.2.5.1 Common requirements.
59             // Turn this on without causing an ios::failure to be thrown.
60             this->setstate(ios_base::badbit);
61             if ((this->exceptions() & ios_base::badbit) != 0)
62               __throw_exception_again;
63           }
64         }
65       return *this;
66     }
67   
68   template<typename _CharT, typename _Traits>
69     basic_ostream<_CharT, _Traits>& 
70     basic_ostream<_CharT, _Traits>::
71     operator<<(__ios_type& (*__pf)(__ios_type&))
72     {
73       sentry __cerb(*this);
74       if (__cerb)
75         { 
76           try {
77               __pf(*this);
78           }
79           catch(exception& __fail){
80             // 27.6.2.5.1 Common requirements.
81             // Turn this on without causing an ios::failure to be thrown.
82             this->setstate(ios_base::badbit);
83             if ((this->exceptions() & ios_base::badbit) != 0)
84               __throw_exception_again;
85           }
86         }
87       return *this;
88     }
89
90   template<typename _CharT, typename _Traits>
91     basic_ostream<_CharT, _Traits>& 
92     basic_ostream<_CharT, _Traits>::
93     operator<<(ios_base& (*__pf)(ios_base&))
94     {
95       sentry __cerb(*this);
96       if (__cerb)
97         { 
98           try {
99               __pf(*this);
100           }
101           catch(exception& __fail){
102             // 27.6.2.5.1 Common requirements.
103             // Turn this on without causing an ios::failure to be thrown.
104             this->setstate(ios_base::badbit);
105             if ((this->exceptions() & ios_base::badbit) != 0)
106               __throw_exception_again;
107           }
108         }
109       return *this;
110     }
111
112   template<typename _CharT, typename _Traits>
113     basic_ostream<_CharT, _Traits>& 
114     basic_ostream<_CharT, _Traits>::operator<<(bool __n)
115     {
116       sentry __cerb(*this);
117       if (__cerb) 
118         {
119           try {
120             if (_M_fnumput->put(*this, *this, this->fill(), __n).failed())
121               this->setstate(ios_base::badbit);
122           }
123           catch(exception& __fail){
124             // 27.6.1.2.1 Common requirements.
125             // Turn this on without causing an ios::failure to be thrown.
126             this->setstate(ios_base::badbit);
127             if ((this->exceptions() & ios_base::badbit) != 0)
128               __throw_exception_again;
129           }
130         }
131       return *this;
132     }
133
134   template<typename _CharT, typename _Traits>
135     basic_ostream<_CharT, _Traits>& 
136     basic_ostream<_CharT, _Traits>::operator<<(long __n)
137     {
138       sentry __cerb(*this);
139       if (__cerb) 
140         {
141           try {
142             bool __f;
143             ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
144             if (__fmt & ios_base::oct || __fmt & ios_base::hex)
145               __f = _M_fnumput->put(*this, *this, this->fill(), 
146                                     static_cast<unsigned long>(__n)).failed();
147             else
148               __f = _M_fnumput->put(*this, *this, this->fill(), __n).failed();
149
150             if (__f)  
151               this->setstate(ios_base::badbit);
152           }
153           catch(exception& __fail){
154             // 27.6.1.2.1 Common requirements.
155             // Turn this on without causing an ios::failure to be thrown.
156             this->setstate(ios_base::badbit);
157             if ((this->exceptions() & ios_base::badbit) != 0)
158               __throw_exception_again;
159           }
160         }
161       return *this;
162     }
163
164   template<typename _CharT, typename _Traits>
165     basic_ostream<_CharT, _Traits>& 
166     basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n)
167     {
168       sentry __cerb(*this);
169       if (__cerb) 
170         {
171           try {
172             if (_M_fnumput->put(*this, *this, this->fill(), __n).failed())
173               this->setstate(ios_base::badbit);
174           }
175           catch(exception& __fail){
176             // 27.6.1.2.1 Common requirements.
177             // Turn this on without causing an ios::failure to be thrown.
178             this->setstate(ios_base::badbit);
179             if ((this->exceptions() & ios_base::badbit) != 0)
180               __throw_exception_again;
181           }
182         }
183       return *this;
184     }
185
186 #ifdef _GLIBCPP_USE_LONG_LONG
187   template<typename _CharT, typename _Traits>
188     basic_ostream<_CharT, _Traits>& 
189     basic_ostream<_CharT, _Traits>::operator<<(long long __n)
190     {
191       sentry __cerb(*this);
192       if (__cerb) 
193         {
194           try {
195             bool __f;
196             ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
197             if (__fmt & ios_base::oct || __fmt & ios_base::hex)
198               __f = _M_fnumput->put(*this, *this, this->fill(), 
199                                static_cast<unsigned long long>(__n)).failed();
200             else
201               __f = _M_fnumput->put(*this, *this, this->fill(), __n).failed();
202
203           }
204           catch(exception& __fail){
205             // 27.6.1.2.1 Common requirements.
206             // Turn this on without causing an ios::failure to be thrown.
207             this->setstate(ios_base::badbit);
208             if ((this->exceptions() & ios_base::badbit) != 0)
209               __throw_exception_again;
210           }
211         }
212       return *this;
213     }
214
215   template<typename _CharT, typename _Traits>
216     basic_ostream<_CharT, _Traits>& 
217     basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n)
218     {
219       sentry __cerb(*this);
220       if (__cerb) 
221         {
222           try {
223             if (_M_fnumput->put(*this, *this, this->fill(), __n).failed())
224               this->setstate(ios_base::badbit);
225           }
226           catch(exception& __fail){
227             // 27.6.1.2.1 Common requirements.
228             // Turn this on without causing an ios::failure to be thrown.
229             this->setstate(ios_base::badbit);
230             if ((this->exceptions() & ios_base::badbit) != 0)
231               __throw_exception_again;
232           }
233         }
234       return *this;
235     }
236 #endif
237
238   template<typename _CharT, typename _Traits>
239     basic_ostream<_CharT, _Traits>& 
240     basic_ostream<_CharT, _Traits>::operator<<(double __n)
241     {
242       sentry __cerb(*this);
243       if (__cerb) 
244         {
245           try {
246             if (_M_fnumput->put(*this, *this, this->fill(), __n).failed())
247               this->setstate(ios_base::badbit);
248           }
249           catch(exception& __fail){
250             // 27.6.1.2.1 Common requirements.
251             // Turn this on without causing an ios::failure to be thrown.
252             this->setstate(ios_base::badbit);
253             if ((this->exceptions() & ios_base::badbit) != 0)
254               __throw_exception_again;
255           }
256         }
257       return *this;
258     }
259
260   template<typename _CharT, typename _Traits>
261     basic_ostream<_CharT, _Traits>& 
262     basic_ostream<_CharT, _Traits>::operator<<(long double __n)
263     {
264       sentry __cerb(*this);
265       if (__cerb) 
266         {
267           try {
268             if (_M_fnumput->put(*this, *this, this->fill(), __n).failed())
269               this->setstate(ios_base::badbit);
270           }
271           catch(exception& __fail){
272             // 27.6.1.2.1 Common requirements.
273             // Turn this on without causing an ios::failure to be thrown.
274             this->setstate(ios_base::badbit);
275             if ((this->exceptions() & ios_base::badbit) != 0)
276               __throw_exception_again;
277           }
278         }
279       return *this;
280     }
281
282   template<typename _CharT, typename _Traits>
283     basic_ostream<_CharT, _Traits>& 
284     basic_ostream<_CharT, _Traits>::operator<<(const void* __n)
285     {
286       sentry __cerb(*this);
287       if (__cerb) 
288         {
289           try {
290             if (_M_fnumput->put(*this, *this, this->fill(), __n).failed())
291               this->setstate(ios_base::badbit);
292           }
293           catch(exception& __fail){
294             // 27.6.1.2.1 Common requirements.
295             // Turn this on without causing an ios::failure to be thrown.
296             this->setstate(ios_base::badbit);
297             if ((this->exceptions() & ios_base::badbit) != 0)
298               __throw_exception_again;
299           }
300         }
301       return *this;
302     }
303
304   template<typename _CharT, typename _Traits>
305     basic_ostream<_CharT, _Traits>& 
306     basic_ostream<_CharT, _Traits>::operator<<(__streambuf_type* __sbin)
307     {
308       streamsize __xtrct = 0;
309       __streambuf_type* __sbout = this->rdbuf();
310       sentry __cerb(*this);
311       if (__sbin && __cerb)
312         __xtrct = __copy_streambufs(*this, __sbin, __sbout);
313       if (!__sbin || !__xtrct)
314         this->setstate(ios_base::failbit);
315       return *this;
316     }
317
318   template<typename _CharT, typename _Traits>
319     basic_ostream<_CharT, _Traits>&
320     basic_ostream<_CharT, _Traits>::put(char_type __c)
321     { 
322       sentry __cerb(*this);
323       if (__cerb) 
324         {
325           int_type __put = rdbuf()->sputc(__c); 
326           if (__put != traits_type::to_int_type(__c))
327             this->setstate(ios_base::badbit);
328         }
329       return *this;
330     }
331
332   template<typename _CharT, typename _Traits>
333     basic_ostream<_CharT, _Traits>&
334     basic_ostream<_CharT, _Traits>::write(const _CharT* __s, streamsize __n)
335     {
336       sentry __cerb(*this);
337       if (__cerb)
338         {
339           streamsize __put = this->rdbuf()->sputn(__s, __n);
340           if ( __put != __n)
341             this->setstate(ios_base::badbit);
342         }
343       return *this;
344     }
345
346   template<typename _CharT, typename _Traits>
347     basic_ostream<_CharT, _Traits>&
348     basic_ostream<_CharT, _Traits>::flush()
349     {
350       sentry __cerb(*this);
351       if (__cerb) 
352         {
353           if (this->rdbuf() && this->rdbuf()->pubsync() == -1)
354             this->setstate(ios_base::badbit);
355         }
356       return *this;
357     }
358   
359   template<typename _CharT, typename _Traits>
360     typename basic_ostream<_CharT, _Traits>::pos_type
361     basic_ostream<_CharT, _Traits>::tellp()
362     {
363       pos_type __ret = pos_type(-1);
364       bool __testok = this->fail() != true;
365       
366       if (__testok)
367         __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out);
368       return __ret;
369     }
370
371
372   template<typename _CharT, typename _Traits>
373     basic_ostream<_CharT, _Traits>&
374     basic_ostream<_CharT, _Traits>::seekp(pos_type __pos)
375     {
376       bool __testok = this->fail() != true;
377       
378       if (__testok)
379 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
380 // 136.  seekp, seekg setting wrong streams?
381         this->rdbuf()->pubseekpos(__pos, ios_base::out);
382 #endif
383       return *this;
384     }
385
386   template<typename _CharT, typename _Traits>
387     basic_ostream<_CharT, _Traits>&
388     basic_ostream<_CharT, _Traits>::
389     seekp(off_type __off, ios_base::seekdir __d)
390     {
391       bool __testok = this->fail() != true;
392       
393       if (__testok)
394 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
395 // 136.  seekp, seekg setting wrong streams?
396         rdbuf()->pubseekoff(__off, __d, ios_base::out);
397 #endif
398       return *this;
399     }
400
401   // 27.6.2.5.4 Character inserters
402
403   // Construct correctly padded string, as per 22.2.2.2.2
404   // Similar in theory to __pad_numeric, from num_put, but it doesn't
405   // use _S_fill: perhaps it should.
406   // Assumes 
407   // __newlen > __oldlen
408   // __news is allocated for __newlen size
409   template<typename _CharT, typename _Traits>
410     void
411     __pad_char(basic_ios<_CharT, _Traits>& __ios, 
412                _CharT* __news, const _CharT* __olds,
413                const streamsize __newlen, const streamsize __oldlen)
414     {
415       typedef _CharT    char_type;
416       typedef _Traits   traits_type;
417       typedef typename traits_type::int_type int_type;
418       
419       int_type __plen = static_cast<size_t>(__newlen - __oldlen); 
420       char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
421       traits_type::assign(__pads, __plen, __ios.fill()); 
422
423       char_type* __beg;
424       char_type* __end;
425       size_t __mod = 0;
426       size_t __beglen; //either __plen or __oldlen
427       ios_base::fmtflags __fmt = __ios.flags() & ios_base::adjustfield;
428
429       if (__fmt == ios_base::left)
430         {
431           // Padding last.
432           __beg = const_cast<char_type*>(__olds);
433           __beglen = __oldlen;
434           __end = __pads;
435         }
436       else if (__fmt == ios_base::internal)
437         {
438           // Pad after the sign, if there is one.
439           // Pad after 0[xX], if there is one.
440           // Who came up with these rules, anyway? Jeeze.
441           typedef _Format_cache<_CharT> __cache_type;
442           __cache_type const* __fmt = __cache_type::_S_get(__ios);
443           const char_type* __minus = traits_type::find(__olds, __oldlen, 
444                                                        __fmt->_S_minus);
445           const char_type* __plus = traits_type::find(__olds, __oldlen, 
446                                                       __fmt->_S_plus);
447           bool __testsign = __minus || __plus;
448           bool __testhex = __olds[0] == '0' 
449                            && (__olds[1] == 'x' || __olds[1] == 'X');
450
451           if (__testhex)
452             {
453               __news[0] = __olds[0]; 
454               __news[1] = __olds[1];
455               __mod += 2;
456               __beg = const_cast<char_type*>(__olds + __mod);
457               __beglen = __oldlen - __mod;
458               __end = __pads;
459             }
460           else if (__testsign)
461             {
462               __mod += __plen;
463               const char_type* __sign = __minus ? __minus + 1: __plus + 1;
464               __beg = const_cast<char_type*>(__olds);
465               __beglen = __sign - __olds;
466               __end = const_cast<char_type*>(__sign + __plen);
467               traits_type::copy(__news + __beglen, __pads, __plen);
468             }
469           else
470             {
471               // Padding first.
472               __beg = __pads;
473               __beglen = __plen;
474               __end = const_cast<char_type*>(__olds);
475             }
476         }
477       else
478         {
479           // Padding first.
480           __beg = __pads;
481           __beglen = __plen;
482           __end = const_cast<char_type*>(__olds);
483         }
484
485       traits_type::copy(__news, __beg, __beglen);
486       traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
487     }
488
489   template<typename _CharT, typename _Traits>
490     basic_ostream<_CharT, _Traits>&
491     operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c)
492     {
493       typedef basic_ostream<_CharT, _Traits> __ostream_type;
494       typename __ostream_type::sentry __cerb(__out);
495       if (__cerb)
496         {
497           try {
498             streamsize __w = __out.width();
499             _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
500             __pads[0] = __c;
501             streamsize __len = 1;
502             if (__w > __len)
503               {
504                 __pad_char(__out, __pads, &__c, __w, __len);
505                 __len = __w;
506               }
507             __out.write(__pads, __len);
508             __out.width(0);
509           }
510           catch(exception& __fail){
511             // 27.6.1.2.1 Common requirements.
512             // Turn this on without causing an ios::failure to be thrown.
513             __out.setstate(ios_base::badbit);
514             if ((__out.exceptions() & ios_base::badbit) != 0)
515               __throw_exception_again;
516           }
517         }
518       return __out;
519     }
520
521   // Specialization
522   template <class _Traits> 
523     basic_ostream<char, _Traits>&
524     operator<<(basic_ostream<char, _Traits>& __out, char __c)
525     {
526       typedef basic_ostream<char, _Traits> __ostream_type;
527       typename __ostream_type::sentry __cerb(__out);
528       if (__cerb)
529         {
530           try {
531             streamsize __w = __out.width();
532             char* __pads = static_cast<char*>(__builtin_alloca(__w + 1));
533             __pads[0] = __c;
534             streamsize __len = 1;
535             if (__w > __len)
536               {
537                 __pad_char(__out, __pads, &__c, __w, __len);
538                 __len = __w;
539               }
540             __out.write(__pads, __len);
541             __out.width(0);
542           }
543           catch(exception& __fail){
544             // 27.6.1.2.1 Common requirements.
545             // Turn this on without causing an ios::failure to be thrown.
546             __out.setstate(ios_base::badbit);
547             if ((__out.exceptions() & ios_base::badbit) != 0)
548               __throw_exception_again;
549           }
550         }
551       return __out;
552      }
553
554   template<typename _CharT, typename _Traits>
555     basic_ostream<_CharT, _Traits>&
556     operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
557     {
558       typedef basic_ostream<_CharT, _Traits> __ostream_type;
559       typename __ostream_type::sentry __cerb(__out);
560       if (__cerb)
561         {
562           try {
563             streamsize __w = __out.width();
564             _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
565             streamsize __len = static_cast<streamsize>(_Traits::length(__s));
566             if (__w > __len)
567               {
568                 __pad_char(__out, __pads, __s, __w, __len);
569                 __s = __pads;
570                 __len = __w;
571               }
572             __out.write(__s, __len);
573             __out.width(0);
574           }
575           catch(exception& __fail){
576             // 27.6.1.2.1 Common requirements.
577             // Turn this on without causing an ios::failure to be thrown.
578             __out.setstate(ios_base::badbit);
579             if ((__out.exceptions() & ios_base::badbit) != 0)
580               __throw_exception_again;
581           }
582         }
583       return __out;
584     }
585
586   template<typename _CharT, typename _Traits>
587     basic_ostream<_CharT, _Traits>&
588     operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
589     {
590       typedef basic_ostream<_CharT, _Traits> __ostream_type;
591 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
592 // 167.  Improper use of traits_type::length()
593       typedef char_traits<char>              __ctraits_type;
594 #endif
595       typename __ostream_type::sentry __cerb(__out);
596       if (__cerb)
597         {
598           size_t __clen = __ctraits_type::length(__s);
599           _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__clen + 1)));
600           for (size_t  __i = 0; __i <= __clen; ++__i)
601             __ws[__i] = __out.widen(__s[__i]);
602           _CharT* __str = __ws;
603           
604           try {
605             streamsize __len = static_cast<streamsize>(__clen);
606             streamsize __w = __out.width();
607             _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
608
609             if (__w > __len)
610               {
611                 __pad_char(__out, __pads, __ws, __w, __len);
612                 __str = __pads;
613                 __len = __w;
614               }
615             __out.write(__str, __len);
616             __out.width(0);
617           }
618           catch(exception& __fail){
619             // 27.6.1.2.1 Common requirements.
620             // Turn this on without causing an ios::failure to be thrown.
621             __out.setstate(ios_base::badbit);
622             if ((__out.exceptions() & ios_base::badbit) != 0)
623               __throw_exception_again;
624           }
625         }
626       return __out;
627     }
628
629   // Partial specializationss
630   template<class _Traits>
631     basic_ostream<char, _Traits>&
632     operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
633     {
634       typedef basic_ostream<char, _Traits> __ostream_type;
635       typename __ostream_type::sentry __cerb(__out);
636       if (__cerb)
637         {
638           try {
639             streamsize __w = __out.width();
640             char* __pads = static_cast<char*>(__builtin_alloca(__w));
641             streamsize __len = static_cast<streamsize>(_Traits::length(__s));
642             if (__w > __len)
643               {
644                 __pad_char(__out, __pads, __s, __w, __len);
645                 __s = __pads;
646                 __len = __w;
647               }
648             __out.write(__s, __len);
649             __out.width(0);
650           }
651           catch(exception& __fail){
652             // 27.6.1.2.1 Common requirements.
653             // Turn this on without causing an ios::failure to be thrown.
654             __out.setstate(ios_base::badbit);
655             if ((__out.exceptions() & ios_base::badbit) != 0)
656               __throw_exception_again;
657           }
658         }
659       return __out;
660     }
661
662   // 21.3.7.8 basic_string::operator<<
663   template<typename _CharT, typename _Traits, typename _Alloc>
664     basic_ostream<_CharT, _Traits>&
665     operator<<(basic_ostream<_CharT, _Traits>& __out,
666                const basic_string<_CharT, _Traits, _Alloc>& __s)
667     { return (__out << __s.c_str()); }
668
669 } // namespace std
670  
671 // Local Variables:
672 // mode:C++
673 // End:
674