libstdc++
ostream
Go to the documentation of this file.
1 // Output streams -*- C++ -*-
2 
3 // Copyright (C) 1997-2025 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 #ifdef _GLIBCXX_SYSHDR
37 #pragma GCC system_header
38 #endif
39 
40 #include <bits/requires_hosted.h> // iostreams
41 
42 #include <bits/ostream.h>
43 #if __cplusplus > 202002L
44 # include <format>
45 #endif
46 
47 # define __glibcxx_want_print
48 #include <bits/version.h> // __glibcxx_syncbuf
49 
50 namespace std _GLIBCXX_VISIBILITY(default)
51 {
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
53 
54  // Standard basic_ostream manipulators
55 
56  /**
57  * @brief Write a newline and flush the stream.
58  *
59  * This manipulator is often mistakenly used when a simple newline is
60  * desired, leading to poor buffering performance. See
61  * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering
62  * for more on this subject.
63  */
64  template<typename _CharT, typename _Traits>
65  inline basic_ostream<_CharT, _Traits>&
66  endl(basic_ostream<_CharT, _Traits>& __os)
67  { return flush(__os.put(__os.widen('\n'))); }
68 
69  /**
70  * @brief Write a null character into the output sequence.
71  *
72  * <em>Null character</em> is @c CharT() by definition. For CharT
73  * of @c char, this correctly writes the ASCII @c NUL character
74  * string terminator.
75  */
76  template<typename _CharT, typename _Traits>
77  inline basic_ostream<_CharT, _Traits>&
78  ends(basic_ostream<_CharT, _Traits>& __os)
79  { return __os.put(_CharT()); }
80 
81  /**
82  * @brief Flushes the output stream.
83  *
84  * This manipulator simply calls the stream's @c flush() member function.
85  */
86  template<typename _CharT, typename _Traits>
87  inline basic_ostream<_CharT, _Traits>&
88  flush(basic_ostream<_CharT, _Traits>& __os)
89  { return __os.flush(); }
90 
91 #ifdef __glibcxx_syncbuf // C++ >= 20 && HOSTED && CXX11ABI
92  template<typename _CharT, typename _Traits>
93  class __syncbuf_base : public basic_streambuf<_CharT, _Traits>
94  {
95  public:
96  static bool*
97  _S_get(basic_streambuf<_CharT, _Traits>* __buf [[maybe_unused]]) noexcept
98  {
99 #if __cpp_rtti
100  if (auto __p = dynamic_cast<__syncbuf_base*>(__buf))
101  return &__p->_M_emit_on_sync;
102 #endif
103  return nullptr;
104  }
105 
106  protected:
107  __syncbuf_base(basic_streambuf<_CharT, _Traits>* __w = nullptr)
108  : _M_wrapped(__w)
109  { }
110 
111  basic_streambuf<_CharT, _Traits>* _M_wrapped = nullptr;
112  bool _M_emit_on_sync = false;
113  bool _M_needs_sync = false;
114  };
115 
116  template<typename _CharT, typename _Traits>
117  inline basic_ostream<_CharT, _Traits>&
118  emit_on_flush(basic_ostream<_CharT, _Traits>& __os)
119  {
120  if (bool* __flag = __syncbuf_base<_CharT, _Traits>::_S_get(__os.rdbuf()))
121  *__flag = true;
122  return __os;
123  }
124 
125  template<typename _CharT, typename _Traits>
126  inline basic_ostream<_CharT, _Traits>&
127  noemit_on_flush(basic_ostream<_CharT, _Traits>& __os)
128  {
129  if (bool* __flag = __syncbuf_base<_CharT, _Traits>::_S_get(__os.rdbuf()))
130  *__flag = false;
131  return __os;
132  }
133 
134  template<typename _CharT, typename _Traits>
135  inline basic_ostream<_CharT, _Traits>&
136  flush_emit(basic_ostream<_CharT, _Traits>& __os)
137  {
138  struct _Restore
139  {
140  ~_Restore() { *_M_flag = _M_prev; }
141 
142  bool _M_prev = false;
143  bool* _M_flag = &_M_prev;
144  } __restore;
145 
146  if (bool* __flag = __syncbuf_base<_CharT, _Traits>::_S_get(__os.rdbuf()))
147  {
148  __restore._M_prev = *__flag;
149  __restore._M_flag = __flag;
150  *__flag = true;
151  }
152 
153  __os.flush();
154  return __os;
155  }
156 #endif // __glibcxx_syncbuf
157 
158 #if __cpp_lib_print // C++ >= 23
159  inline void
160  vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args)
161  {
162  ostream::sentry __cerb(__os);
163  if (__cerb)
164  {
165  __format::_Str_sink<char> __buf;
166  std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
167  auto __out = __buf.view();
168 
169  __try
170  {
171  std::__ostream_write(__os, __out.data(), __out.size());
172  }
173  __catch(const __cxxabiv1::__forced_unwind&)
174  {
175  __os._M_setstate(ios_base::badbit);
176  __throw_exception_again;
177  }
178  __catch(...)
179  { __os._M_setstate(ios_base::badbit); }
180  }
181  }
182 
183  inline void
184  vprint_unicode(ostream& __os, string_view __fmt, format_args __args)
185  {
186 #if !defined(_WIN32) || defined(__CYGWIN__)
187  // For most targets we don't need to do anything special to write
188  // Unicode to a terminal.
189  std::vprint_nonunicode(__os, __fmt, __args);
190 #else
191  ostream::sentry __cerb(__os);
192  if (__cerb)
193  {
194  __format::_Str_sink<char> __buf;
195  std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
196  auto __out = __buf.view();
197 
198  void* __open_terminal(streambuf*);
199  error_code __write_to_terminal(void*, span<char>);
200  // If stream refers to a terminal, write a Unicode string to it.
201  if (auto __term = __open_terminal(__os.rdbuf()))
202  {
203 #if !defined(_WIN32) || defined(__CYGWIN__)
204  // For POSIX, __open_terminal(streambuf*) uses fdopen to open a
205  // new file, so we would need to close it here. This code is not
206  // actually compiled because it's inside an #ifdef _WIN32 group,
207  // but just in case that changes in future ...
208  struct _Guard
209  {
210  _Guard(void* __p) : _M_f((FILE*)__p) { }
211  ~_Guard() { std::fclose(_M_f); }
212  _Guard(_Guard&&) = delete;
213  _Guard& operator=(_Guard&&) = delete;
214  FILE* _M_f;
215  };
216  _Guard __g(__term);
217 #endif
218 
219  ios_base::iostate __err = ios_base::goodbit;
220  __try
221  {
222  if (__os.rdbuf()->pubsync() == -1)
223  __err = ios::badbit;
224  else if (auto __e = __write_to_terminal(__term, __out))
225  if (__e != std::make_error_code(errc::illegal_byte_sequence))
226  __err = ios::badbit;
227  }
228  __catch(const __cxxabiv1::__forced_unwind&)
229  {
230  __os._M_setstate(ios_base::badbit);
231  __throw_exception_again;
232  }
233  __catch(...)
234  { __os._M_setstate(ios_base::badbit); }
235 
236  if (__err)
237  __os.setstate(__err);
238  return;
239  }
240 
241  // Otherwise just insert the string as vprint_nonunicode does.
242  __try
243  {
244  std::__ostream_write(__os, __out.data(), __out.size());
245  }
246  __catch(const __cxxabiv1::__forced_unwind&)
247  {
248  __os._M_setstate(ios_base::badbit);
249  __throw_exception_again;
250  }
251  __catch(...)
252  { __os._M_setstate(ios_base::badbit); }
253  }
254 #endif // _WIN32
255  }
256 
257  template<typename... _Args>
258  inline void
259  print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args)
260  {
261  auto __fmtargs = std::make_format_args(__args...);
262  if constexpr (__unicode::__literal_encoding_is_utf8())
263  std::vprint_unicode(__os, __fmt.get(), __fmtargs);
264  else
265  std::vprint_nonunicode(__os, __fmt.get(), __fmtargs);
266  }
267 
268  template<typename... _Args>
269  inline void
270  println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args)
271  {
272  // _GLIBCXX_RESOLVE_LIB_DEFECTS
273  // 4088. println ignores the locale imbued in std::ostream
274  std::print(__os, "{}\n", std::format(__os.getloc(), __fmt,
275  std::forward<_Args>(__args)...));
276  }
277 
278  // Defined for C++26, supported as an extension to C++23.
279  inline void println(ostream& __os)
280  {
281 #if defined(_WIN32) && !defined(__CYGWIN__)
282  if constexpr (__unicode::__literal_encoding_is_utf8())
283  std::vprint_unicode(__os, "\n", std::make_format_args());
284  else
285 #endif
286  __os.put('\n');
287  }
288 
289 #endif // __cpp_lib_print
290 
291 _GLIBCXX_END_NAMESPACE_VERSION
292 } // namespace std
293 
294 #include <bits/ostream.tcc>
295 
296 #endif /* _GLIBCXX_OSTREAM */