libstdc++
ostream_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/ostream_print.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{ostream}
28  *
29  * This file contains the parts of `<ostream>` which are currently defined
30  * inline, but should be moved into the library eventually.
31  */
32 
33 #ifndef _GLIBCXX_OSTREAM_PRINT_H
34 #define _GLIBCXX_OSTREAM_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 #include <format>
46 
47 namespace std _GLIBCXX_VISIBILITY(default)
48 {
49 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 
51 #ifdef _GLIBCXX_NO_INLINE_PRINT
52 # define _GLIBCXX_PRINT_INLINE_USED [[__gnu__::__used__]]
53 #else
54 # define _GLIBCXX_PRINT_INLINE_USED
55 #endif
56 
57  _GLIBCXX_PRINT_INLINE_USED
58  inline void
59  vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args)
60  {
61  ostream::sentry __cerb(__os);
62  if (__cerb)
63  {
64  __format::_Str_sink<char> __buf;
65  std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
66  auto __out = __buf.view();
67 
68  __try
69  {
70  std::__ostream_write(__os, __out.data(), __out.size());
71  }
72  __catch(const __cxxabiv1::__forced_unwind&)
73  {
74  __os._M_setstate(ios_base::badbit);
75  __throw_exception_again;
76  }
77  __catch(...)
78  { __os._M_setstate(ios_base::badbit); }
79  }
80  }
81 
82  _GLIBCXX_PRINT_INLINE_USED
83  inline void
84  vprint_unicode(ostream& __os, string_view __fmt, format_args __args)
85  {
86 #if !defined(_WIN32) || defined(__CYGWIN__)
87  // For most targets we don't need to do anything special to write
88  // Unicode to a terminal.
89  std::vprint_nonunicode(__os, __fmt, __args);
90 #else
91  ostream::sentry __cerb(__os);
92  if (__cerb)
93  {
94  __format::_Str_sink<char> __buf;
95  std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
96  auto __out = __buf._M_span();
97 
98  void* __open_terminal(streambuf*);
99  error_code __write_to_terminal(void*, span<char>);
100  // If stream refers to a terminal, write a Unicode string to it.
101  if (auto __term = __open_terminal(__os.rdbuf()))
102  {
103 #if !defined(_WIN32) || defined(__CYGWIN__)
104  // For POSIX, __open_terminal(streambuf*) uses fdopen to open a
105  // new file, so we would need to close it here. This code is not
106  // actually compiled because it's inside an #ifdef _WIN32 group,
107  // but just in case that changes in future ...
108  struct _Guard
109  {
110  _Guard(void* __p) : _M_f((FILE*)__p) { }
111  ~_Guard() { std::fclose(_M_f); }
112  _Guard(_Guard&&) = delete;
113  _Guard& operator=(_Guard&&) = delete;
114  FILE* _M_f;
115  };
116  _Guard __g(__term);
117 #endif
118 
120  __try
121  {
122  if (__os.rdbuf()->pubsync() == -1)
123  __err = ios::badbit;
124  else if (auto __e = __write_to_terminal(__term, __out))
125  if (__e != std::make_error_code(errc::illegal_byte_sequence))
126  __err = ios::badbit;
127  }
128  __catch(const __cxxabiv1::__forced_unwind&)
129  {
130  __os._M_setstate(ios_base::badbit);
131  __throw_exception_again;
132  }
133  __catch(...)
134  { __os._M_setstate(ios_base::badbit); }
135 
136  if (__err)
137  __os.setstate(__err);
138  return;
139  }
140 
141  // Otherwise just insert the string as vprint_nonunicode does.
142  __try
143  {
144  std::__ostream_write(__os, __out.data(), __out.size());
145  }
146  __catch(const __cxxabiv1::__forced_unwind&)
147  {
148  __os._M_setstate(ios_base::badbit);
149  __throw_exception_again;
150  }
151  __catch(...)
152  { __os._M_setstate(ios_base::badbit); }
153  }
154 #endif // _WIN32
155  }
156 #undef _GLIBCXX_PRINT_INLINE_USED
157 
158 _GLIBCXX_END_NAMESPACE_VERSION
159 } // namespace std
160 #endif // __glibcxx_print
161 #endif // _GLIBCXX_OSTREAM_PRINT_H
error_code make_error_code(future_errc __errc) noexcept
Overload of make_error_code for future_errc.
Definition: future:97
basic_streambuf< char > streambuf
Base class for char buffers.
Definition: iosfwd:139
basic_ostream< char > ostream
Base class for char output streams.
Definition: iosfwd:145
ISO C++ entities toplevel namespace is std.
Thrown as part of forced unwinding.
Definition: cxxabi_forced.h:51
_Ios_Iostate iostate
This is a bitmask type.
Definition: ios_base.h:453
static const iostate goodbit
Indicates all is well.
Definition: ios_base.h:468
static const iostate badbit
Indicates a loss of integrity in an input or output sequence (such as an irrecoverable read error fro...
Definition: ios_base.h:457