1// ostream classes -*- C++ -*-
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4// 2006, 2007
5// Free Software Foundation, Inc.
6//
7// This file is part of the GNU ISO C++ Library.  This library is free
8// software; you can redistribute it and/or modify it under the
9// terms of the GNU General Public License as published by the
10// Free Software Foundation; either version 2, or (at your option)
11// any later version.
12
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16// GNU General Public License for more details.
17
18// You should have received a copy of the GNU General Public License along
19// with this library; see the file COPYING.  If not, write to the Free
20// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21// USA.
22
23// As a special exception, you may use this file as part of a free software
24// library without restriction.  Specifically, if other files instantiate
25// templates or use macros or inline functions from this file, or you compile
26// this file and link it with other files to produce an executable, this
27// file does not by itself cause the resulting executable to be covered by
28// the GNU General Public License.  This exception does not however
29// invalidate any other reasons why the executable file might be covered by
30// the GNU General Public License.
31
32/** @file ostream.tcc
33 *  This is an internal header file, included by other library headers.
34 *  You should not attempt to use it directly.
35 */
36
37//
38// ISO C++ 14882: 27.6.2  Output streams
39//
40
41#ifndef _OSTREAM_TCC
42#define _OSTREAM_TCC 1
43
44#pragma GCC system_header
45
46#include <locale>
47
48_GLIBCXX_BEGIN_NAMESPACE(std)
49
50  template<typename _CharT, typename _Traits>
51    basic_ostream<_CharT, _Traits>::sentry::
52    sentry(basic_ostream<_CharT, _Traits>& __os)
53    : _M_ok(false), _M_os(__os)
54    {
55      // XXX MT
56      if (__os.tie() && __os.good())
57	__os.tie()->flush();
58
59      if (__os.good())
60	_M_ok = true;
61      else
62	__os.setstate(ios_base::failbit);
63    }
64
65  template<typename _CharT, typename _Traits>
66    template<typename _ValueT>
67      basic_ostream<_CharT, _Traits>&
68      basic_ostream<_CharT, _Traits>::
69      _M_insert(_ValueT __v)
70      {
71	sentry __cerb(*this);
72	if (__cerb)
73	  {
74	    ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
75	    try
76	      {
77		const __num_put_type& __np = __check_facet(this->_M_num_put);
78		if (__np.put(*this, *this, this->fill(), __v).failed())
79		  __err |= ios_base::badbit;
80	      }
81	    catch(...)
82	      { this->_M_setstate(ios_base::badbit); }
83	    if (__err)
84	      this->setstate(__err);
85	  }
86	return *this;
87      }
88
89  template<typename _CharT, typename _Traits>
90    basic_ostream<_CharT, _Traits>&
91    basic_ostream<_CharT, _Traits>::
92    operator<<(short __n)
93    {
94      // _GLIBCXX_RESOLVE_LIB_DEFECTS
95      // 117. basic_ostream uses nonexistent num_put member functions.
96      const ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
97      if (__fmt == ios_base::oct || __fmt == ios_base::hex)
98	return _M_insert(static_cast<long>(static_cast<unsigned short>(__n)));
99      else
100	return _M_insert(static_cast<long>(__n));
101    }
102
103  template<typename _CharT, typename _Traits>
104    basic_ostream<_CharT, _Traits>&
105    basic_ostream<_CharT, _Traits>::
106    operator<<(int __n)
107    {
108      // _GLIBCXX_RESOLVE_LIB_DEFECTS
109      // 117. basic_ostream uses nonexistent num_put member functions.
110      const ios_base::fmtflags __fmt = this->flags() & ios_base::basefield;
111      if (__fmt == ios_base::oct || __fmt == ios_base::hex)
112	return _M_insert(static_cast<long>(static_cast<unsigned int>(__n)));
113      else
114	return _M_insert(static_cast<long>(__n));
115    }
116  
117  template<typename _CharT, typename _Traits>
118    basic_ostream<_CharT, _Traits>&
119    basic_ostream<_CharT, _Traits>::
120    operator<<(__streambuf_type* __sbin)
121    {
122      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
123      sentry __cerb(*this);
124      if (__cerb && __sbin)
125	{
126	  try
127	    {
128	      if (!__copy_streambufs(__sbin, this->rdbuf()))
129		__err |= ios_base::failbit;
130	    }
131	  catch(...)
132	    { this->_M_setstate(ios_base::failbit); }
133	}
134      else if (!__sbin)
135	__err |= ios_base::badbit;
136      if (__err)
137	this->setstate(__err);
138      return *this;
139    }
140
141  template<typename _CharT, typename _Traits>
142    basic_ostream<_CharT, _Traits>&
143    basic_ostream<_CharT, _Traits>::
144    put(char_type __c)
145    {
146      // _GLIBCXX_RESOLVE_LIB_DEFECTS
147      // DR 60. What is a formatted input function?
148      // basic_ostream::put(char_type) is an unformatted output function.
149      // DR 63. Exception-handling policy for unformatted output.
150      // Unformatted output functions should catch exceptions thrown
151      // from streambuf members.
152      sentry __cerb(*this);
153      if (__cerb)
154	{
155	  ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
156	  try
157	    {
158	      const int_type __put = this->rdbuf()->sputc(__c);
159	      if (traits_type::eq_int_type(__put, traits_type::eof()))
160		__err |= ios_base::badbit;
161	    }
162	  catch (...)
163	    { this->_M_setstate(ios_base::badbit); }
164	  if (__err)
165	    this->setstate(__err);
166	}
167      return *this;
168    }
169
170  template<typename _CharT, typename _Traits>
171    basic_ostream<_CharT, _Traits>&
172    basic_ostream<_CharT, _Traits>::
173    write(const _CharT* __s, streamsize __n)
174    {
175      // _GLIBCXX_RESOLVE_LIB_DEFECTS
176      // DR 60. What is a formatted input function?
177      // basic_ostream::write(const char_type*, streamsize) is an
178      // unformatted output function.
179      // DR 63. Exception-handling policy for unformatted output.
180      // Unformatted output functions should catch exceptions thrown
181      // from streambuf members.
182      sentry __cerb(*this);
183      if (__cerb)
184	{
185	  try
186	    { _M_write(__s, __n); }
187	  catch (...)
188	    { this->_M_setstate(ios_base::badbit); }
189	}
190      return *this;
191    }
192
193  template<typename _CharT, typename _Traits>
194    basic_ostream<_CharT, _Traits>&
195    basic_ostream<_CharT, _Traits>::
196    flush()
197    {
198      // _GLIBCXX_RESOLVE_LIB_DEFECTS
199      // DR 60. What is a formatted input function?
200      // basic_ostream::flush() is *not* an unformatted output function.
201      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
202      try
203	{
204	  if (this->rdbuf() && this->rdbuf()->pubsync() == -1)
205	    __err |= ios_base::badbit;
206	}
207      catch(...)
208	{ this->_M_setstate(ios_base::badbit); }
209      if (__err)
210	this->setstate(__err);
211      return *this;
212    }
213
214  template<typename _CharT, typename _Traits>
215    typename basic_ostream<_CharT, _Traits>::pos_type
216    basic_ostream<_CharT, _Traits>::
217    tellp()
218    {
219      pos_type __ret = pos_type(-1);
220      try
221	{
222	  if (!this->fail())
223	    __ret = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out);
224	}
225      catch(...)
226	{ this->_M_setstate(ios_base::badbit); }
227      return __ret;
228    }
229
230  template<typename _CharT, typename _Traits>
231    basic_ostream<_CharT, _Traits>&
232    basic_ostream<_CharT, _Traits>::
233    seekp(pos_type __pos)
234    {
235      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
236      try
237	{
238	  if (!this->fail())
239	    {
240	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
241	      // 136.  seekp, seekg setting wrong streams?
242	      const pos_type __p = this->rdbuf()->pubseekpos(__pos,
243							     ios_base::out);
244
245	      // 129. Need error indication from seekp() and seekg()
246	      if (__p == pos_type(off_type(-1)))
247		__err |= ios_base::failbit;
248	    }
249	}
250      catch(...)
251	{ this->_M_setstate(ios_base::badbit); }
252      if (__err)
253	this->setstate(__err);
254      return *this;
255    }
256
257  template<typename _CharT, typename _Traits>
258    basic_ostream<_CharT, _Traits>&
259    basic_ostream<_CharT, _Traits>::
260    seekp(off_type __off, ios_base::seekdir __dir)
261    {
262      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
263      try
264	{
265	  if (!this->fail())
266	    {
267	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
268	      // 136.  seekp, seekg setting wrong streams?
269	      const pos_type __p = this->rdbuf()->pubseekoff(__off, __dir,
270							     ios_base::out);
271
272	      // 129. Need error indication from seekp() and seekg()
273	      if (__p == pos_type(off_type(-1)))
274		__err |= ios_base::failbit;
275	    }
276	}
277      catch(...)
278	{ this->_M_setstate(ios_base::badbit); }
279      if (__err)
280	this->setstate(__err);
281      return *this;
282    }
283
284  template<typename _CharT, typename _Traits>
285    basic_ostream<_CharT, _Traits>&
286    operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
287    {
288      if (!__s)
289	__out.setstate(ios_base::badbit);
290      else
291	{
292	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
293	  // 167.  Improper use of traits_type::length()
294	  const size_t __clen = char_traits<char>::length(__s);      
295	  _CharT* __ws = 0;
296	  try
297	    { 
298	      __ws = new _CharT[__clen];
299	      for (size_t  __i = 0; __i < __clen; ++__i)
300		__ws[__i] = __out.widen(__s[__i]);
301	    }
302	  catch(...)
303	    {
304	      delete [] __ws;
305	      __out._M_setstate(ios_base::badbit);
306	      return __out;
307	    }
308
309	  try
310	    {
311	      __ostream_insert(__out, __ws, __clen);
312	      delete [] __ws;
313	    }
314	  catch(...)
315	    {
316	      delete [] __ws;
317	      __throw_exception_again;
318	    }
319	}
320      return __out;
321    }
322
323  // Inhibit implicit instantiations for required instantiations,
324  // which are defined via explicit instantiations elsewhere.
325  // NB:  This syntax is a GNU extension.
326#if _GLIBCXX_EXTERN_TEMPLATE
327  extern template class basic_ostream<char>;
328  extern template ostream& endl(ostream&);
329  extern template ostream& ends(ostream&);
330  extern template ostream& flush(ostream&);
331  extern template ostream& operator<<(ostream&, char);
332  extern template ostream& operator<<(ostream&, unsigned char);
333  extern template ostream& operator<<(ostream&, signed char);
334  extern template ostream& operator<<(ostream&, const char*);
335  extern template ostream& operator<<(ostream&, const unsigned char*);
336  extern template ostream& operator<<(ostream&, const signed char*);
337
338  extern template ostream& ostream::_M_insert(long);
339  extern template ostream& ostream::_M_insert(unsigned long);
340  extern template ostream& ostream::_M_insert(bool);
341#ifdef _GLIBCXX_USE_LONG_LONG
342  extern template ostream& ostream::_M_insert(long long);
343  extern template ostream& ostream::_M_insert(unsigned long long);
344#endif
345  extern template ostream& ostream::_M_insert(double);
346  extern template ostream& ostream::_M_insert(long double);
347  extern template ostream& ostream::_M_insert(const void*);
348
349#ifdef _GLIBCXX_USE_WCHAR_T
350  extern template class basic_ostream<wchar_t>;
351  extern template wostream& endl(wostream&);
352  extern template wostream& ends(wostream&);
353  extern template wostream& flush(wostream&);
354  extern template wostream& operator<<(wostream&, wchar_t);
355  extern template wostream& operator<<(wostream&, char);
356  extern template wostream& operator<<(wostream&, const wchar_t*);
357  extern template wostream& operator<<(wostream&, const char*);
358
359  extern template wostream& wostream::_M_insert(long);
360  extern template wostream& wostream::_M_insert(unsigned long);
361  extern template wostream& wostream::_M_insert(bool);
362#ifdef _GLIBCXX_USE_LONG_LONG
363  extern template wostream& wostream::_M_insert(long long);
364  extern template wostream& wostream::_M_insert(unsigned long long);
365#endif
366  extern template wostream& wostream::_M_insert(double);
367  extern template wostream& wostream::_M_insert(long double);
368  extern template wostream& wostream::_M_insert(const void*);
369#endif
370#endif
371
372_GLIBCXX_END_NAMESPACE
373
374#endif
375