1 | // Output streams -*- 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 include/ostream |
26 | * This is a Standard C++ Library header. |
27 | */ |
28 | |
29 | // |
30 | // ISO C++ 14882: 27.6.2 Output streams |
31 | // |
32 | |
33 | #ifndef _GLIBCXX_OSTREAM |
34 | #define _GLIBCXX_OSTREAM 1 |
35 | |
36 | #pragma GCC system_header |
37 | |
38 | #include <bits/requires_hosted.h> // iostreams |
39 | |
40 | #include <ios> |
41 | #include <bits/ostream_insert.h> |
42 | #if __cplusplus > 202002L |
43 | # include <format> |
44 | #endif |
45 | |
46 | # define __glibcxx_want_print |
47 | #include <bits/version.h> // __glibcxx_syncbuf |
48 | |
49 | namespace std _GLIBCXX_VISIBILITY(default) |
50 | { |
51 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
52 | |
53 | /** |
54 | * @brief Template class basic_ostream. |
55 | * @ingroup io |
56 | * |
57 | * @tparam _CharT Type of character stream. |
58 | * @tparam _Traits Traits for character type, defaults to |
59 | * char_traits<_CharT>. |
60 | * |
61 | * This is the base class for all output streams. It provides text |
62 | * formatting of all builtin types, and communicates with any class |
63 | * derived from basic_streambuf to do the actual output. |
64 | */ |
65 | template<typename _CharT, typename _Traits> |
66 | class basic_ostream : virtual public basic_ios<_CharT, _Traits> |
67 | { |
68 | public: |
69 | // Types (inherited from basic_ios): |
70 | typedef _CharT char_type; |
71 | typedef typename _Traits::int_type int_type; |
72 | typedef typename _Traits::pos_type pos_type; |
73 | typedef typename _Traits::off_type off_type; |
74 | typedef _Traits traits_type; |
75 | |
76 | // Non-standard Types: |
77 | typedef basic_streambuf<_CharT, _Traits> __streambuf_type; |
78 | typedef basic_ios<_CharT, _Traits> __ios_type; |
79 | typedef basic_ostream<_CharT, _Traits> __ostream_type; |
80 | typedef num_put<_CharT, ostreambuf_iterator<_CharT, _Traits> > |
81 | __num_put_type; |
82 | typedef ctype<_CharT> __ctype_type; |
83 | |
84 | /** |
85 | * @brief Base constructor. |
86 | * |
87 | * This ctor is almost never called by the user directly, rather from |
88 | * derived classes' initialization lists, which pass a pointer to |
89 | * their own stream buffer. |
90 | */ |
91 | explicit |
92 | basic_ostream(__streambuf_type* __sb) |
93 | { this->init(__sb); } |
94 | |
95 | /** |
96 | * @brief Base destructor. |
97 | * |
98 | * This does very little apart from providing a virtual base dtor. |
99 | */ |
100 | virtual |
101 | ~basic_ostream() { } |
102 | |
103 | /// Safe prefix/suffix operations. |
104 | class sentry; |
105 | friend class sentry; |
106 | |
107 | ///@{ |
108 | /** |
109 | * @brief Interface for manipulators. |
110 | * |
111 | * Manipulators such as @c std::endl and @c std::hex use these |
112 | * functions in constructs like "std::cout << std::endl". For more |
113 | * information, see the iomanip header. |
114 | */ |
115 | __ostream_type& |
116 | operator<<(__ostream_type& (*__pf)(__ostream_type&)) |
117 | { |
118 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
119 | // DR 60. What is a formatted input function? |
120 | // The inserters for manipulators are *not* formatted output functions. |
121 | return __pf(*this); |
122 | } |
123 | |
124 | __ostream_type& |
125 | operator<<(__ios_type& (*__pf)(__ios_type&)) |
126 | { |
127 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
128 | // DR 60. What is a formatted input function? |
129 | // The inserters for manipulators are *not* formatted output functions. |
130 | __pf(*this); |
131 | return *this; |
132 | } |
133 | |
134 | __ostream_type& |
135 | operator<<(ios_base& (*__pf) (ios_base&)) |
136 | { |
137 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
138 | // DR 60. What is a formatted input function? |
139 | // The inserters for manipulators are *not* formatted output functions. |
140 | __pf(*this); |
141 | return *this; |
142 | } |
143 | ///@} |
144 | |
145 | ///@{ |
146 | /** |
147 | * @name Inserters |
148 | * |
149 | * All the @c operator<< functions (aka <em>formatted output |
150 | * functions</em>) have some common behavior. Each starts by |
151 | * constructing a temporary object of type std::basic_ostream::sentry. |
152 | * This can have several effects, concluding with the setting of a |
153 | * status flag; see the sentry documentation for more. |
154 | * |
155 | * If the sentry status is good, the function tries to generate |
156 | * whatever data is appropriate for the type of the argument. |
157 | * |
158 | * If an exception is thrown during insertion, ios_base::badbit |
159 | * will be turned on in the stream's error state without causing an |
160 | * ios_base::failure to be thrown. The original exception will then |
161 | * be rethrown. |
162 | */ |
163 | |
164 | ///@{ |
165 | /** |
166 | * @brief Integer arithmetic inserters |
167 | * @param __n A variable of builtin integral type. |
168 | * @return @c *this if successful |
169 | * |
170 | * These functions use the stream's current locale (specifically, the |
171 | * @c num_get facet) to perform numeric formatting. |
172 | */ |
173 | __ostream_type& |
174 | operator<<(long __n) |
175 | { return _M_insert(__n); } |
176 | |
177 | __ostream_type& |
178 | operator<<(unsigned long __n) |
179 | { return _M_insert(__n); } |
180 | |
181 | __ostream_type& |
182 | operator<<(bool __n) |
183 | { return _M_insert(__n); } |
184 | |
185 | __ostream_type& |
186 | operator<<(short __n); |
187 | |
188 | __ostream_type& |
189 | operator<<(unsigned short __n) |
190 | { |
191 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
192 | // 117. basic_ostream uses nonexistent num_put member functions. |
193 | return _M_insert(static_cast<unsigned long>(__n)); |
194 | } |
195 | |
196 | __ostream_type& |
197 | operator<<(int __n); |
198 | |
199 | __ostream_type& |
200 | operator<<(unsigned int __n) |
201 | { |
202 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
203 | // 117. basic_ostream uses nonexistent num_put member functions. |
204 | return _M_insert(static_cast<unsigned long>(__n)); |
205 | } |
206 | |
207 | #ifdef _GLIBCXX_USE_LONG_LONG |
208 | #pragma GCC diagnostic push |
209 | #pragma GCC diagnostic ignored "-Wlong-long" |
210 | __ostream_type& |
211 | operator<<(long long __n) |
212 | { return _M_insert(__n); } |
213 | |
214 | __ostream_type& |
215 | operator<<(unsigned long long __n) |
216 | { return _M_insert(__n); } |
217 | #pragma GCC diagnostic pop |
218 | #endif |
219 | ///@} |
220 | |
221 | ///@{ |
222 | /** |
223 | * @brief Floating point arithmetic inserters |
224 | * @param __f A variable of builtin floating point type. |
225 | * @return @c *this if successful |
226 | * |
227 | * These functions use the stream's current locale (specifically, the |
228 | * @c num_get facet) to perform numeric formatting. |
229 | */ |
230 | __ostream_type& |
231 | operator<<(double __f) |
232 | { return _M_insert(__f); } |
233 | |
234 | __ostream_type& |
235 | operator<<(float __f) |
236 | { |
237 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
238 | // 117. basic_ostream uses nonexistent num_put member functions. |
239 | return _M_insert(static_cast<double>(__f)); |
240 | } |
241 | |
242 | __ostream_type& |
243 | operator<<(long double __f) |
244 | { return _M_insert(__f); } |
245 | ///@} |
246 | |
247 | #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) |
248 | __attribute__((__always_inline__)) |
249 | __ostream_type& |
250 | operator<<(_Float16 __f) |
251 | { |
252 | return _M_insert(static_cast<double>(__f)); |
253 | } |
254 | #endif |
255 | |
256 | #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) |
257 | __attribute__((__always_inline__)) |
258 | __ostream_type& |
259 | operator<<(_Float32 __f) |
260 | { |
261 | return _M_insert(static_cast<double>(__f)); |
262 | } |
263 | #endif |
264 | |
265 | #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) |
266 | __attribute__((__always_inline__)) |
267 | __ostream_type& |
268 | operator<<(_Float64 __f) |
269 | { |
270 | return _M_insert(static_cast<double>(__f)); |
271 | } |
272 | #endif |
273 | |
274 | #if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) |
275 | __attribute__((__always_inline__)) |
276 | __ostream_type& |
277 | operator<<(_Float128 __f) |
278 | { |
279 | return _M_insert(static_cast<long double>(__f)); |
280 | } |
281 | #endif |
282 | |
283 | #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) |
284 | __attribute__((__always_inline__)) |
285 | __ostream_type& |
286 | operator<<(__gnu_cxx::__bfloat16_t __f) |
287 | { |
288 | return _M_insert(static_cast<double>(__f)); |
289 | } |
290 | #endif |
291 | |
292 | /** |
293 | * @brief Pointer arithmetic inserters |
294 | * @param __p A variable of pointer type. |
295 | * @return @c *this if successful |
296 | * |
297 | * These functions use the stream's current locale (specifically, the |
298 | * @c num_get facet) to perform numeric formatting. |
299 | */ |
300 | __ostream_type& |
301 | operator<<(const void* __p) |
302 | { return _M_insert(__p); } |
303 | |
304 | #if __cplusplus >= 201703L |
305 | __ostream_type& |
306 | operator<<(nullptr_t) |
307 | { return *this << "nullptr" ; } |
308 | #endif |
309 | |
310 | #if __cplusplus > 202002L |
311 | __attribute__((__always_inline__)) |
312 | __ostream_type& |
313 | operator<<(const volatile void* __p) |
314 | { return _M_insert(const_cast<const void*>(__p)); } |
315 | #endif |
316 | |
317 | /** |
318 | * @brief Extracting from another streambuf. |
319 | * @param __sb A pointer to a streambuf |
320 | * |
321 | * This function behaves like one of the basic arithmetic extractors, |
322 | * in that it also constructs a sentry object and has the same error |
323 | * handling behavior. |
324 | * |
325 | * If @p __sb is NULL, the stream will set failbit in its error state. |
326 | * |
327 | * Characters are extracted from @p __sb and inserted into @c *this |
328 | * until one of the following occurs: |
329 | * |
330 | * - the input stream reaches end-of-file, |
331 | * - insertion into the output sequence fails (in this case, the |
332 | * character that would have been inserted is not extracted), or |
333 | * - an exception occurs while getting a character from @p __sb, which |
334 | * sets failbit in the error state |
335 | * |
336 | * If the function inserts no characters, failbit is set. |
337 | */ |
338 | __ostream_type& |
339 | operator<<(__streambuf_type* __sb); |
340 | ///@} |
341 | |
342 | ///@{ |
343 | /** |
344 | * @name Unformatted Output Functions |
345 | * |
346 | * All the unformatted output functions have some common behavior. |
347 | * Each starts by constructing a temporary object of type |
348 | * std::basic_ostream::sentry. This has several effects, concluding |
349 | * with the setting of a status flag; see the sentry documentation |
350 | * for more. |
351 | * |
352 | * If the sentry status is good, the function tries to generate |
353 | * whatever data is appropriate for the type of the argument. |
354 | * |
355 | * If an exception is thrown during insertion, ios_base::badbit |
356 | * will be turned on in the stream's error state. If badbit is on in |
357 | * the stream's exceptions mask, the exception will be rethrown |
358 | * without completing its actions. |
359 | */ |
360 | |
361 | /** |
362 | * @brief Simple insertion. |
363 | * @param __c The character to insert. |
364 | * @return *this |
365 | * |
366 | * Tries to insert @p __c. |
367 | * |
368 | * @note This function is not overloaded on signed char and |
369 | * unsigned char. |
370 | */ |
371 | __ostream_type& |
372 | put(char_type __c); |
373 | |
374 | /** |
375 | * @brief Character string insertion. |
376 | * @param __s The array to insert. |
377 | * @param __n Maximum number of characters to insert. |
378 | * @return *this |
379 | * |
380 | * Characters are copied from @p __s and inserted into the stream until |
381 | * one of the following happens: |
382 | * |
383 | * - @p __n characters are inserted |
384 | * - inserting into the output sequence fails (in this case, badbit |
385 | * will be set in the stream's error state) |
386 | * |
387 | * @note This function is not overloaded on signed char and |
388 | * unsigned char. |
389 | */ |
390 | __ostream_type& |
391 | write(const char_type* __s, streamsize __n); |
392 | ///@} |
393 | |
394 | /** |
395 | * @brief Synchronizing the stream buffer. |
396 | * @return *this |
397 | * |
398 | * If @c rdbuf() is a null pointer, changes nothing. |
399 | * |
400 | * Otherwise, calls @c rdbuf()->pubsync(), and if that returns -1, |
401 | * sets badbit. |
402 | */ |
403 | __ostream_type& |
404 | flush(); |
405 | |
406 | /** |
407 | * @brief Getting the current write position. |
408 | * @return A file position object. |
409 | * |
410 | * If @c fail() is not false, returns @c pos_type(-1) to indicate |
411 | * failure. Otherwise returns @c rdbuf()->pubseekoff(0,cur,out). |
412 | */ |
413 | pos_type |
414 | tellp(); |
415 | |
416 | /** |
417 | * @brief Changing the current write position. |
418 | * @param __pos A file position object. |
419 | * @return *this |
420 | * |
421 | * If @c fail() is not true, calls @c rdbuf()->pubseekpos(pos). If |
422 | * that function fails, sets failbit. |
423 | */ |
424 | __ostream_type& |
425 | seekp(pos_type); |
426 | |
427 | /** |
428 | * @brief Changing the current write position. |
429 | * @param __off A file offset object. |
430 | * @param __dir The direction in which to seek. |
431 | * @return *this |
432 | * |
433 | * If @c fail() is not true, calls @c rdbuf()->pubseekoff(off,dir). |
434 | * If that function fails, sets failbit. |
435 | */ |
436 | __ostream_type& |
437 | seekp(off_type, ios_base::seekdir); |
438 | |
439 | protected: |
440 | basic_ostream() |
441 | { this->init(0); } |
442 | |
443 | #if __cplusplus >= 201103L |
444 | // Non-standard constructor that does not call init() |
445 | basic_ostream(basic_iostream<_CharT, _Traits>&) { } |
446 | |
447 | basic_ostream(const basic_ostream&) = delete; |
448 | |
449 | basic_ostream(basic_ostream&& __rhs) |
450 | : __ios_type() |
451 | { __ios_type::move(__rhs); } |
452 | |
453 | // 27.7.3.3 Assign/swap |
454 | |
455 | basic_ostream& operator=(const basic_ostream&) = delete; |
456 | |
457 | basic_ostream& |
458 | operator=(basic_ostream&& __rhs) |
459 | { |
460 | swap(__rhs); |
461 | return *this; |
462 | } |
463 | |
464 | void |
465 | swap(basic_ostream& __rhs) |
466 | { __ios_type::swap(__rhs); } |
467 | #endif |
468 | |
469 | template<typename _ValueT> |
470 | __ostream_type& |
471 | _M_insert(_ValueT __v); |
472 | |
473 | private: |
474 | #if !_GLIBCXX_INLINE_VERSION |
475 | void |
476 | _M_write(const char_type* __s, streamsize __n) |
477 | { std::__ostream_insert(*this, __s, __n); } |
478 | #endif |
479 | }; |
480 | |
481 | /** |
482 | * @brief Performs setup work for output streams. |
483 | * |
484 | * Objects of this class are created before all of the standard |
485 | * inserters are run. It is responsible for <em>exception-safe prefix and |
486 | * suffix operations</em>. |
487 | */ |
488 | template <typename _CharT, typename _Traits> |
489 | class basic_ostream<_CharT, _Traits>::sentry |
490 | { |
491 | // Data Members. |
492 | bool _M_ok; |
493 | basic_ostream<_CharT, _Traits>& _M_os; |
494 | |
495 | public: |
496 | /** |
497 | * @brief The constructor performs preparatory work. |
498 | * @param __os The output stream to guard. |
499 | * |
500 | * If the stream state is good (@a __os.good() is true), then if the |
501 | * stream is tied to another output stream, @c is.tie()->flush() |
502 | * is called to synchronize the output sequences. |
503 | * |
504 | * If the stream state is still good, then the sentry state becomes |
505 | * true (@a okay). |
506 | */ |
507 | explicit |
508 | sentry(basic_ostream<_CharT, _Traits>& __os); |
509 | |
510 | #pragma GCC diagnostic push |
511 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
512 | /** |
513 | * @brief Possibly flushes the stream. |
514 | * |
515 | * If @c ios_base::unitbuf is set in @c os.flags(), and |
516 | * @c std::uncaught_exception() is true, the sentry destructor calls |
517 | * @c flush() on the output stream. |
518 | */ |
519 | ~sentry() |
520 | { |
521 | // XXX MT |
522 | if (bool(_M_os.flags() & ios_base::unitbuf) && !uncaught_exception()) |
523 | { |
524 | // Can't call flush directly or else will get into recursive lock. |
525 | if (_M_os.rdbuf() && _M_os.rdbuf()->pubsync() == -1) |
526 | _M_os.setstate(ios_base::badbit); |
527 | } |
528 | } |
529 | #pragma GCC diagnostic pop |
530 | |
531 | /** |
532 | * @brief Quick status checking. |
533 | * @return The sentry state. |
534 | * |
535 | * For ease of use, sentries may be converted to booleans. The |
536 | * return value is that of the sentry state (true == okay). |
537 | */ |
538 | #if __cplusplus >= 201103L |
539 | explicit |
540 | #endif |
541 | operator bool() const |
542 | { return _M_ok; } |
543 | }; |
544 | |
545 | ///@{ |
546 | /** |
547 | * @brief Character inserters |
548 | * @param __out An output stream. |
549 | * @param __c A character. |
550 | * @return out |
551 | * |
552 | * Behaves like one of the formatted arithmetic inserters described in |
553 | * std::basic_ostream. After constructing a sentry object with good |
554 | * status, this function inserts a single character and any required |
555 | * padding (as determined by [22.2.2.2.2]). @c __out.width(0) is then |
556 | * called. |
557 | * |
558 | * If @p __c is of type @c char and the character type of the stream is not |
559 | * @c char, the character is widened before insertion. |
560 | */ |
561 | template<typename _CharT, typename _Traits> |
562 | inline basic_ostream<_CharT, _Traits>& |
563 | operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c) |
564 | { |
565 | if (__out.width() != 0) |
566 | return __ostream_insert(__out, &__c, 1); |
567 | __out.put(__c); |
568 | return __out; |
569 | } |
570 | |
571 | template<typename _CharT, typename _Traits> |
572 | inline basic_ostream<_CharT, _Traits>& |
573 | operator<<(basic_ostream<_CharT, _Traits>& __out, char __c) |
574 | { return (__out << __out.widen(__c)); } |
575 | |
576 | // Specialization |
577 | template<typename _Traits> |
578 | inline basic_ostream<char, _Traits>& |
579 | operator<<(basic_ostream<char, _Traits>& __out, char __c) |
580 | { |
581 | if (__out.width() != 0) |
582 | return __ostream_insert(__out, &__c, 1); |
583 | __out.put(__c); |
584 | return __out; |
585 | } |
586 | |
587 | // Signed and unsigned |
588 | template<typename _Traits> |
589 | inline basic_ostream<char, _Traits>& |
590 | operator<<(basic_ostream<char, _Traits>& __out, signed char __c) |
591 | { return (__out << static_cast<char>(__c)); } |
592 | |
593 | template<typename _Traits> |
594 | inline basic_ostream<char, _Traits>& |
595 | operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c) |
596 | { return (__out << static_cast<char>(__c)); } |
597 | |
598 | #if __cplusplus > 201703L |
599 | // The following deleted overloads prevent formatting character values as |
600 | // numeric values. |
601 | |
602 | template<typename _Traits> |
603 | basic_ostream<char, _Traits>& |
604 | operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete; |
605 | |
606 | #ifdef _GLIBCXX_USE_CHAR8_T |
607 | template<typename _Traits> |
608 | basic_ostream<char, _Traits>& |
609 | operator<<(basic_ostream<char, _Traits>&, char8_t) = delete; |
610 | #endif |
611 | |
612 | template<typename _Traits> |
613 | basic_ostream<char, _Traits>& |
614 | operator<<(basic_ostream<char, _Traits>&, char16_t) = delete; |
615 | |
616 | template<typename _Traits> |
617 | basic_ostream<char, _Traits>& |
618 | operator<<(basic_ostream<char, _Traits>&, char32_t) = delete; |
619 | |
620 | #ifdef _GLIBCXX_USE_WCHAR_T |
621 | #ifdef _GLIBCXX_USE_CHAR8_T |
622 | template<typename _Traits> |
623 | basic_ostream<wchar_t, _Traits>& |
624 | operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete; |
625 | #endif // _GLIBCXX_USE_CHAR8_T |
626 | |
627 | template<typename _Traits> |
628 | basic_ostream<wchar_t, _Traits>& |
629 | operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete; |
630 | |
631 | template<typename _Traits> |
632 | basic_ostream<wchar_t, _Traits>& |
633 | operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete; |
634 | #endif // _GLIBCXX_USE_WCHAR_T |
635 | #endif // C++20 |
636 | ///@} |
637 | |
638 | ///@{ |
639 | /** |
640 | * @brief String inserters |
641 | * @param __out An output stream. |
642 | * @param __s A character string. |
643 | * @return out |
644 | * @pre @p __s must be a non-NULL pointer |
645 | * |
646 | * Behaves like one of the formatted arithmetic inserters described in |
647 | * std::basic_ostream. After constructing a sentry object with good |
648 | * status, this function inserts @c traits::length(__s) characters starting |
649 | * at @p __s, widened if necessary, followed by any required padding (as |
650 | * determined by [22.2.2.2.2]). @c __out.width(0) is then called. |
651 | */ |
652 | template<typename _CharT, typename _Traits> |
653 | inline basic_ostream<_CharT, _Traits>& |
654 | operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s) |
655 | { |
656 | if (!__s) |
657 | __out.setstate(ios_base::badbit); |
658 | else |
659 | __ostream_insert(__out, __s, |
660 | static_cast<streamsize>(_Traits::length(__s))); |
661 | return __out; |
662 | } |
663 | |
664 | template<typename _CharT, typename _Traits> |
665 | basic_ostream<_CharT, _Traits> & |
666 | operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s); |
667 | |
668 | // Partial specializations |
669 | template<typename _Traits> |
670 | inline basic_ostream<char, _Traits>& |
671 | operator<<(basic_ostream<char, _Traits>& __out, const char* __s) |
672 | { |
673 | if (!__s) |
674 | __out.setstate(ios_base::badbit); |
675 | else |
676 | __ostream_insert(__out, __s, |
677 | static_cast<streamsize>(_Traits::length(__s))); |
678 | return __out; |
679 | } |
680 | |
681 | // Signed and unsigned |
682 | template<typename _Traits> |
683 | inline basic_ostream<char, _Traits>& |
684 | operator<<(basic_ostream<char, _Traits>& __out, const signed char* __s) |
685 | { return (__out << reinterpret_cast<const char*>(__s)); } |
686 | |
687 | template<typename _Traits> |
688 | inline basic_ostream<char, _Traits> & |
689 | operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s) |
690 | { return (__out << reinterpret_cast<const char*>(__s)); } |
691 | |
692 | #if __cplusplus > 201703L |
693 | // The following deleted overloads prevent formatting strings as |
694 | // pointer values. |
695 | |
696 | template<typename _Traits> |
697 | basic_ostream<char, _Traits>& |
698 | operator<<(basic_ostream<char, _Traits>&, const wchar_t*) = delete; |
699 | |
700 | #ifdef _GLIBCXX_USE_CHAR8_T |
701 | template<typename _Traits> |
702 | basic_ostream<char, _Traits>& |
703 | operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete; |
704 | #endif // _GLIBCXX_USE_CHAR8_T |
705 | |
706 | template<typename _Traits> |
707 | basic_ostream<char, _Traits>& |
708 | operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete; |
709 | |
710 | template<typename _Traits> |
711 | basic_ostream<char, _Traits>& |
712 | operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete; |
713 | |
714 | #ifdef _GLIBCXX_USE_WCHAR_T |
715 | #ifdef _GLIBCXX_USE_CHAR8_T |
716 | template<typename _Traits> |
717 | basic_ostream<wchar_t, _Traits>& |
718 | operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete; |
719 | #endif |
720 | |
721 | template<typename _Traits> |
722 | basic_ostream<wchar_t, _Traits>& |
723 | operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete; |
724 | |
725 | template<typename _Traits> |
726 | basic_ostream<wchar_t, _Traits>& |
727 | operator<<(basic_ostream<wchar_t, _Traits>&, const char32_t*) = delete; |
728 | #endif // _GLIBCXX_USE_WCHAR_T |
729 | #endif // C++20 |
730 | ///@} |
731 | |
732 | // Standard basic_ostream manipulators |
733 | |
734 | /** |
735 | * @brief Write a newline and flush the stream. |
736 | * |
737 | * This manipulator is often mistakenly used when a simple newline is |
738 | * desired, leading to poor buffering performance. See |
739 | * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering |
740 | * for more on this subject. |
741 | */ |
742 | template<typename _CharT, typename _Traits> |
743 | inline basic_ostream<_CharT, _Traits>& |
744 | endl(basic_ostream<_CharT, _Traits>& __os) |
745 | { return flush(__os.put(__os.widen('\n'))); } |
746 | |
747 | /** |
748 | * @brief Write a null character into the output sequence. |
749 | * |
750 | * <em>Null character</em> is @c CharT() by definition. For CharT |
751 | * of @c char, this correctly writes the ASCII @c NUL character |
752 | * string terminator. |
753 | */ |
754 | template<typename _CharT, typename _Traits> |
755 | inline basic_ostream<_CharT, _Traits>& |
756 | ends(basic_ostream<_CharT, _Traits>& __os) |
757 | { return __os.put(_CharT()); } |
758 | |
759 | /** |
760 | * @brief Flushes the output stream. |
761 | * |
762 | * This manipulator simply calls the stream's @c flush() member function. |
763 | */ |
764 | template<typename _CharT, typename _Traits> |
765 | inline basic_ostream<_CharT, _Traits>& |
766 | flush(basic_ostream<_CharT, _Traits>& __os) |
767 | { return __os.flush(); } |
768 | |
769 | #if __cplusplus >= 201103L |
770 | // C++11 27.7.3.9 Rvalue stream insertion [ostream.rvalue] |
771 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
772 | // 1203. More useful rvalue stream insertion |
773 | |
774 | #if __cpp_concepts >= 201907L && __glibcxx_type_trait_variable_templates |
775 | // Use concepts if possible because they're cheaper to evaluate. |
776 | template<typename _Tp> |
777 | concept __derived_from_ios_base = is_class_v<_Tp> |
778 | && (!is_same_v<_Tp, ios_base>) |
779 | && requires (_Tp* __t, ios_base* __b) { __b = __t; }; |
780 | |
781 | template<typename _Os, typename _Tp> |
782 | requires __derived_from_ios_base<_Os> |
783 | && requires (_Os& __os, const _Tp& __t) { __os << __t; } |
784 | using __rvalue_stream_insertion_t = _Os&&; |
785 | #else |
786 | template<typename _Tp> |
787 | using _Require_derived_from_ios_base |
788 | = _Require<is_class<_Tp>, __not_<is_same<_Tp, ios_base>>, |
789 | is_convertible<typename add_pointer<_Tp>::type, ios_base*>>; |
790 | |
791 | template<typename _Os, typename _Tp, |
792 | typename = _Require_derived_from_ios_base<_Os>, |
793 | typename |
794 | = decltype(std::declval<_Os&>() << std::declval<const _Tp&>())> |
795 | using __rvalue_stream_insertion_t = _Os&&; |
796 | #endif |
797 | |
798 | /** |
799 | * @brief Generic inserter for rvalue stream |
800 | * @param __os An input stream. |
801 | * @param __x A reference to the object being inserted. |
802 | * @return __os |
803 | * |
804 | * This is just a forwarding function to allow insertion to |
805 | * rvalue streams since they won't bind to the inserter functions |
806 | * that take an lvalue reference. |
807 | */ |
808 | template<typename _Ostream, typename _Tp> |
809 | inline __rvalue_stream_insertion_t<_Ostream, _Tp> |
810 | operator<<(_Ostream&& __os, const _Tp& __x) |
811 | { |
812 | __os << __x; |
813 | return std::move(__os); |
814 | } |
815 | |
816 | #ifdef __glibcxx_syncbuf // C++ >= 20 && HOSTED && CXX11ABI |
817 | template<typename _CharT, typename _Traits> |
818 | class __syncbuf_base : public basic_streambuf<_CharT, _Traits> |
819 | { |
820 | public: |
821 | static bool* |
822 | _S_get(basic_streambuf<_CharT, _Traits>* __buf [[maybe_unused]]) noexcept |
823 | { |
824 | #if __cpp_rtti |
825 | if (auto __p = dynamic_cast<__syncbuf_base*>(__buf)) |
826 | return &__p->_M_emit_on_sync; |
827 | #endif |
828 | return nullptr; |
829 | } |
830 | |
831 | protected: |
832 | __syncbuf_base(basic_streambuf<_CharT, _Traits>* __w = nullptr) |
833 | : _M_wrapped(__w) |
834 | { } |
835 | |
836 | basic_streambuf<_CharT, _Traits>* _M_wrapped = nullptr; |
837 | bool _M_emit_on_sync = false; |
838 | bool _M_needs_sync = false; |
839 | }; |
840 | |
841 | template<typename _CharT, typename _Traits> |
842 | inline basic_ostream<_CharT, _Traits>& |
843 | emit_on_flush(basic_ostream<_CharT, _Traits>& __os) |
844 | { |
845 | if (bool* __flag = __syncbuf_base<_CharT, _Traits>::_S_get(__os.rdbuf())) |
846 | *__flag = true; |
847 | return __os; |
848 | } |
849 | |
850 | template<typename _CharT, typename _Traits> |
851 | inline basic_ostream<_CharT, _Traits>& |
852 | noemit_on_flush(basic_ostream<_CharT, _Traits>& __os) |
853 | { |
854 | if (bool* __flag = __syncbuf_base<_CharT, _Traits>::_S_get(__os.rdbuf())) |
855 | *__flag = false; |
856 | return __os; |
857 | } |
858 | |
859 | template<typename _CharT, typename _Traits> |
860 | inline basic_ostream<_CharT, _Traits>& |
861 | flush_emit(basic_ostream<_CharT, _Traits>& __os) |
862 | { |
863 | struct _Restore |
864 | { |
865 | ~_Restore() { *_M_flag = _M_prev; } |
866 | |
867 | bool _M_prev = false; |
868 | bool* _M_flag = &_M_prev; |
869 | } __restore; |
870 | |
871 | if (bool* __flag = __syncbuf_base<_CharT, _Traits>::_S_get(__os.rdbuf())) |
872 | { |
873 | __restore._M_prev = *__flag; |
874 | __restore._M_flag = __flag; |
875 | *__flag = true; |
876 | } |
877 | |
878 | __os.flush(); |
879 | return __os; |
880 | } |
881 | #endif // __glibcxx_syncbuf |
882 | |
883 | #if __cpp_lib_print // C++ >= 23 |
884 | |
885 | inline void |
886 | vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args) |
887 | { |
888 | ostream::sentry __cerb(__os); |
889 | if (__cerb) |
890 | { |
891 | __format::_Str_sink<char> __buf; |
892 | std::vformat_to(out: __buf.out(), loc: __os.getloc(), __fmt, __args); |
893 | auto __out = __buf.view(); |
894 | |
895 | __try |
896 | { |
897 | std::__ostream_write(out&: __os, s: __out.data(), n: __out.size()); |
898 | } |
899 | __catch(const __cxxabiv1::__forced_unwind&) |
900 | { |
901 | __os._M_setstate(state: ios_base::badbit); |
902 | __throw_exception_again; |
903 | } |
904 | __catch(...) |
905 | { __os._M_setstate(state: ios_base::badbit); } |
906 | } |
907 | } |
908 | |
909 | inline void |
910 | vprint_unicode(ostream& __os, string_view __fmt, format_args __args) |
911 | { |
912 | #if !defined(_WIN32) || defined(__CYGWIN__) |
913 | // For most targets we don't need to do anything special to write |
914 | // Unicode to a terminal. |
915 | std::vprint_nonunicode(__os, __fmt, __args); |
916 | #else |
917 | ostream::sentry __cerb(__os); |
918 | if (__cerb) |
919 | { |
920 | __format::_Str_sink<char> __buf; |
921 | std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args); |
922 | auto __out = __buf.view(); |
923 | |
924 | void* __open_terminal(streambuf*); |
925 | error_code __write_to_terminal(void*, span<char>); |
926 | // If stream refers to a terminal, write a Unicode string to it. |
927 | if (auto __term = __open_terminal(__os.rdbuf())) |
928 | { |
929 | #if !defined(_WIN32) || defined(__CYGWIN__) |
930 | // For POSIX, __open_terminal(streambuf*) uses fdopen to open a |
931 | // new file, so we would need to close it here. This code is not |
932 | // actually compiled because it's inside an #ifdef _WIN32 group, |
933 | // but just in case that changes in future ... |
934 | struct _Guard |
935 | { |
936 | _Guard(void* __p) : _M_f((FILE*)__p) { } |
937 | ~_Guard() { std::fclose(_M_f); } |
938 | _Guard(_Guard&&) = delete; |
939 | _Guard& operator=(_Guard&&) = delete; |
940 | FILE* _M_f; |
941 | }; |
942 | _Guard __g(__term); |
943 | #endif |
944 | |
945 | ios_base::iostate __err = ios_base::goodbit; |
946 | __try |
947 | { |
948 | if (__os.rdbuf()->pubsync() == -1) |
949 | __err = ios::badbit; |
950 | else if (auto __e = __write_to_terminal(__term, __out)) |
951 | if (__e != std::make_error_code(errc::illegal_byte_sequence)) |
952 | __err = ios::badbit; |
953 | } |
954 | __catch(const __cxxabiv1::__forced_unwind&) |
955 | { |
956 | __os._M_setstate(ios_base::badbit); |
957 | __throw_exception_again; |
958 | } |
959 | __catch(...) |
960 | { __os._M_setstate(ios_base::badbit); } |
961 | |
962 | if (__err) |
963 | __os.setstate(__err); |
964 | return; |
965 | } |
966 | |
967 | // Otherwise just insert the string as vprint_nonunicode does. |
968 | __try |
969 | { |
970 | std::__ostream_write(__os, __out.data(), __out.size()); |
971 | } |
972 | __catch(const __cxxabiv1::__forced_unwind&) |
973 | { |
974 | __os._M_setstate(ios_base::badbit); |
975 | __throw_exception_again; |
976 | } |
977 | __catch(...) |
978 | { __os._M_setstate(ios_base::badbit); } |
979 | } |
980 | #endif // _WIN32 |
981 | } |
982 | |
983 | template<typename... _Args> |
984 | inline void |
985 | print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) |
986 | { |
987 | auto __fmtargs = std::make_format_args(__args...); |
988 | if constexpr (__unicode::__literal_encoding_is_utf8()) |
989 | std::vprint_unicode(__os, fmt: __fmt.get(), args: __fmtargs); |
990 | else |
991 | std::vprint_nonunicode(__os, fmt: __fmt.get(), args: __fmtargs); |
992 | } |
993 | |
994 | template<typename... _Args> |
995 | inline void |
996 | println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) |
997 | { |
998 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
999 | // 4088. println ignores the locale imbued in std::ostream |
1000 | std::print(__os, "{}\n" , std::format(__os.getloc(), __fmt, |
1001 | std::forward<_Args>(__args)...)); |
1002 | } |
1003 | |
1004 | // Defined for C++26, supported as an extension to C++23. |
1005 | inline void println(ostream& __os) |
1006 | { |
1007 | #if defined(_WIN32) && !defined(__CYGWIN__) |
1008 | if constexpr (__unicode::__literal_encoding_is_utf8()) |
1009 | std::vprint_unicode(__os, "\n" , std::make_format_args()); |
1010 | else |
1011 | #endif |
1012 | __os.put(c: '\n'); |
1013 | } |
1014 | |
1015 | #endif // __cpp_lib_print |
1016 | |
1017 | #endif // C++11 |
1018 | |
1019 | _GLIBCXX_END_NAMESPACE_VERSION |
1020 | } // namespace std |
1021 | |
1022 | #include <bits/ostream.tcc> |
1023 | |
1024 | #endif /* _GLIBCXX_OSTREAM */ |
1025 | |