libstdc++
print.h
Go to the documentation of this file.
1 // Inline implementation details for std::print functions -*- C++ -*-
2 
3 // Copyright The GNU Toolchain Authors.
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/bits/print.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{print}
28  *
29  * This file contains the parts of `<print>` which are currently defined
30  * inline, but should be moved into the library eventually.
31  */
32 
33 #ifndef _GLIBCXX_PRINT_H
34 #define _GLIBCXX_PRINT_H 1
35 
36 #ifdef _GLIBCXX_SYSHDR
37 #pragma GCC system_header
38 #endif
39 
40 #include <bits/requires_hosted.h> // for std::format
41 
42 #include <bits/version.h>
43 
44 #ifdef __glibcxx_print // C++ >= 23
45 
46 #include <format>
47 #include <cstdio> // FILE, EOF, flockfile, etc.
48 #include <cerrno> // EACCES, EIO
49 #include <bits/functexcept.h> // __throw_system_error
50 
51 #ifdef _WIN32
52 # include <system_error> // system_error
53 #endif
54 
55 namespace std _GLIBCXX_VISIBILITY(default)
56 {
57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
58 
59 namespace __format
60 {
61 #if _GLIBCXX_USE_STDIO_LOCKING && _GLIBCXX_USE_GLIBC_STDIO_EXT
62  // These are defined in <stdio_ext.h> but we don't want to include that.
63  extern "C" int __fwritable(FILE*) noexcept;
64  extern "C" int __flbf(FILE*) noexcept;
65  extern "C" size_t __fbufsize(FILE*) noexcept;
66 
67  // A format sink that writes directly to a Glibc FILE.
68  // The file is locked on construction and its buffer is accessed directly.
69  class _File_sink final : _Buf_sink<char>
70  {
71  struct _File
72  {
73  explicit
74  _File(FILE* __f) : _M_file(__f)
75  {
76  ::flockfile(__f);
77  // Ensure stream is in write mode
78  if (!__fwritable(__f))
79  {
80  ::funlockfile(__f);
81  __throw_system_error(EACCES);
82  }
83  // Allocate buffer if needed:
84  if (_M_write_buf().empty())
85  if (::__overflow(__f, EOF) == EOF)
86  {
87  const int __err = errno;
88  ::funlockfile(__f);
89  __throw_system_error(__err);
90  }
91  }
92 
93  ~_File() { ::funlockfile(_M_file); }
94 
95  _File(_File&&) = delete;
96 
97  // A span viewing the unused portion of the stream's output buffer.
98  std::span<char>
99  _M_write_buf() noexcept
100  {
101  return {_M_file->_IO_write_ptr,
102  size_t(_M_file->_IO_buf_end - _M_file->_IO_write_ptr)};
103  }
104 
105  // Flush the output buffer to the file so we can write to it again.
106  void
107  _M_flush()
108  {
109  if (::fflush_unlocked(_M_file))
110  __throw_system_error(errno);
111  }
112 
113  // Update the current position in the output buffer.
114  // __n is the number of characters written to the _M_write_buf() span,
115  // so will not exceed the size of the output buffer.
116  void
117  _M_bump(size_t __n) noexcept
118  { _M_file->_IO_write_ptr += __n; }
119 
120  bool
121  _M_line_buffered() const noexcept
122  { return __flbf(_M_file); } // Or: _M_file->_flags & 0x200
123 
124  bool
125  _M_unbuffered() const noexcept
126  { return __fbufsize(_M_file) == 1; } // Or: _M_file->_flags & 0x2
127 
128  FILE* _M_file;
129  } _M_file;
130 
131  bool _M_add_newline; // True for std::println, false for std::print.
132 
133  // Flush the stream's put area so it can be refilled.
134  void
135  _M_overflow() override
136  {
137  auto __s = this->_M_used();
138  if (__s.data() == this->_M_buf)
139  {
140  // Characters in internal buffer need to be transferred to the FILE.
141  auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(),
142  _M_file._M_file);
143  if (__n != __s.size())
144  __throw_system_error(errno);
145  this->_M_reset(this->_M_buf);
146  }
147  else
148  {
149  // Characters were written directly to the FILE's output buffer.
150  _M_file._M_bump(__s.size());
151  _M_file._M_flush();
152  this->_M_reset(_M_file._M_write_buf());
153  }
154  }
155 
156  public:
157  _File_sink(FILE* __f, bool __add_newline)
158  : _M_file(__f), _M_add_newline(__add_newline)
159  {
160  if (!_M_file._M_unbuffered())
161  // Write directly to the FILE's output buffer.
162  this->_M_reset(_M_file._M_write_buf());
163  }
164 
165  // This calls I/O functions which are cancellation points, so they
166  // could exit with a __forced_unwind exception. The noexcept(false)
167  // allows that to propagate instead of terminating the process.
168  ~_File_sink() noexcept(false)
169  {
170  auto __s = this->_M_used();
171  if (__s.data() == this->_M_buf) // Unbuffered stream
172  {
173  _File_sink::_M_overflow(); // Transfer _M_buf to stream.
174  if (_M_add_newline)
175  ::putc_unlocked('\n', _M_file._M_file);
176  }
177  else
178  {
179  _M_file._M_bump(__s.size());
180  if (_M_add_newline)
181  ::putc_unlocked('\n', _M_file._M_file); // '\n' triggers a flush
182  else if (_M_file._M_line_buffered() && __s.size()
183  && (__s.back() == '\n'
184  || __builtin_memchr(__s.data(), '\n', __s.size())))
185  _M_file._M_flush();
186  }
187  }
188 
189  using _Sink<char>::out;
190  };
191 #elif _GLIBCXX_USE_STDIO_LOCKING
192  // A format sink that buffers output and then copies it to a stdio FILE.
193  // The file is locked on construction and written to using fwrite_unlocked.
194  class _File_sink final : _Buf_sink<char>
195  {
196  struct _File // RAII type to lock/unlock the file.
197  {
198  explicit _File(FILE* __f) : _M_file(__f) { ::flockfile(_M_file); }
199  ~_File() { ::funlockfile(_M_file); }
200  FILE* _M_file;
201  } _M_file;
202 
203  bool _M_add_newline;
204 
205  // Transfer buffer contents to the FILE, so buffer can be refilled.
206  void
207  _M_overflow() override
208  {
209  auto __s = this->_M_used();
210 #if _GLIBCXX_HAVE_FWRITE_UNLOCKED
211  auto __n = ::fwrite_unlocked(__s.data(), 1, __s.size(), _M_file._M_file);
212  if (__n != __s.size())
213  __throw_system_error(errno);
214 #else
215  for (char __c : __s)
216  ::putc_unlocked(__c, _M_file._M_file);
217  if (::ferror(_M_file._M_file))
218  __throw_system_error(errno);
219 #endif
220  this->_M_reset(this->_M_buf);
221  }
222 
223  public:
224  _File_sink(FILE* __f, bool __add_newline) noexcept
225  : _Buf_sink<char>(), _M_file(__f), _M_add_newline(__add_newline)
226  { }
227 
228  ~_File_sink() noexcept(false) // See above for noexcept(false) rationale.
229  {
230  _File_sink::_M_overflow();
231  if (_M_add_newline)
232  ::putc_unlocked('\n', _M_file._M_file);
233  }
234 
235  using _Sink<char>::out;
236  };
237 #else
238  // A wrapper around a format sink that copies the output to a stdio FILE.
239  // This is not actually a _Sink itself, but it creates one to hold the
240  // formatted characters and then copies them to the file when finished.
241  class _File_sink final
242  {
243  FILE* _M_file;
244  _Str_sink<char> _M_sink;
245  bool _M_add_newline;
246 
247  public:
248  _File_sink(FILE* __f, bool __add_newline) noexcept
249  : _M_file(__f), _M_add_newline(__add_newline)
250  { }
251 
252  ~_File_sink() noexcept(false) // See above for noexcept(false) rationale.
253  {
254  string __s = std::move(_M_sink).get();
255  if (_M_add_newline)
256  __s += '\n';
257  auto __n = std::fwrite(__s.data(), 1, __s.size(), _M_file);
258  if (__n < __s.size())
259  __throw_system_error(EIO); // Non-POSIX fwrite doesn't set errno.
260  }
261 
262  auto out() { return _M_sink.out(); }
263  };
264 #endif
265 } // namespace __format
266 
267 #ifdef _GLIBCXX_NO_INLINE_PRINT
268 # define _GLIBCXX_PRINT_INLINE_USED [[__gnu__::__used__]]
269 #else
270 # define _GLIBCXX_PRINT_INLINE_USED
271 #endif
272 
273  _GLIBCXX_PRINT_INLINE_USED
274  inline void
275  vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)
276  {
277  std::vformat_to(__format::_File_sink(__stream, false).out(), __fmt, __args);
278  }
279 
280  _GLIBCXX_PRINT_INLINE_USED
281  inline void
282  vprint_nonunicode_buffered(FILE* __stream, string_view __fmt,
283  format_args __args)
284  {
285  // _GLIBCXX_RESOLVE_LIB_DEFECTS
286  // 4549. vprint_nonunicode_buffered ignores its stream parameter
287  __format::_Str_sink<char> __buf;
288  std::vformat_to(__buf.out(), __fmt, __args);
289  auto __out = __buf.view();
290  if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
291  __throw_system_error(EIO);
292  }
293 
294  _GLIBCXX_PRINT_INLINE_USED
295  inline void
296  vprint_unicode(FILE* __stream, string_view __fmt, format_args __args)
297  {
298 #if !defined(_WIN32) || defined(__CYGWIN__)
299  // For most targets we don't need to do anything special to write
300  // Unicode to a terminal.
301  std::vprint_nonunicode(__stream, __fmt, __args);
302 #else
303  __format::_Str_sink<char> __buf;
304  std::vformat_to(__buf.out(), __fmt, __args);
305  auto __out = __buf._M_span();
306 
307  void* __open_terminal(FILE*);
308  error_code __write_to_terminal(void*, span<char>);
309  // If stream refers to a terminal, write a native Unicode string to it.
310  if (auto __term = __open_terminal(__stream))
311  {
312  error_code __e;
313  if (!std::fflush(__stream))
314  {
315  __e = __write_to_terminal(__term, __out);
316  if (!__e)
317  return;
318  if (__e == std::make_error_code(errc::illegal_byte_sequence))
319  return;
320  }
321  else
322  __e = error_code(errno, generic_category());
323  _GLIBCXX_THROW_OR_ABORT(system_error(__e, "std::vprint_unicode"));
324  }
325 
326  // Otherwise just write the string to the file.
327  if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
328  __throw_system_error(EIO);
329 #endif
330  }
331 
332  _GLIBCXX_PRINT_INLINE_USED
333  inline void
334  vprint_unicode_buffered(FILE* __stream, string_view __fmt, format_args __args)
335  {
336 #if !defined(_WIN32) || defined(__CYGWIN__)
337  // For most targets we don't need to do anything special to write
338  // Unicode to a terminal. Just use the nonunicode function.
339  std::vprint_nonunicode_buffered(__stream, __fmt, __args);
340 #else
341  // For Windows the locking function formats everything first anyway,
342  // so no formatting happens while a lock is taken. Just use that.
343  std::vprint_unicode(__stream, __fmt, __args);
344 #endif
345  }
346 #undef _GLIBCXX_PRINT_INLINE_USED
347 
348 _GLIBCXX_END_NAMESPACE_VERSION
349 } // namespace std
350 #endif // __glibcxx_print
351 #endif // _GLIBCXX_PRINT_H
const error_category & generic_category() noexcept
Error category for errno error codes.
error_code make_error_code(future_errc __errc) noexcept
Overload of make_error_code for future_errc.
Definition: future:97
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:138
ISO C++ entities toplevel namespace is std.
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
Definition: range_access.h:294