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