xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ostream/print.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===---------------------------------------------------------------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===---------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric 
9*0fca6ea1SDimitry Andric #ifndef _LIBCPP___OSTREAM_PRINT_H
10*0fca6ea1SDimitry Andric #define _LIBCPP___OSTREAM_PRINT_H
11*0fca6ea1SDimitry Andric 
12*0fca6ea1SDimitry Andric #include <__config>
13*0fca6ea1SDimitry Andric #include <__fwd/ostream.h>
14*0fca6ea1SDimitry Andric #include <__iterator/ostreambuf_iterator.h>
15*0fca6ea1SDimitry Andric #include <__ostream/basic_ostream.h>
16*0fca6ea1SDimitry Andric #include <format>
17*0fca6ea1SDimitry Andric #include <ios>
18*0fca6ea1SDimitry Andric #include <locale>
19*0fca6ea1SDimitry Andric #include <print>
20*0fca6ea1SDimitry Andric 
21*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22*0fca6ea1SDimitry Andric #  pragma GCC system_header
23*0fca6ea1SDimitry Andric #endif
24*0fca6ea1SDimitry Andric 
25*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
26*0fca6ea1SDimitry Andric 
27*0fca6ea1SDimitry Andric #if _LIBCPP_STD_VER >= 23
28*0fca6ea1SDimitry Andric 
29*0fca6ea1SDimitry Andric template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
30*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void
31*0fca6ea1SDimitry Andric __vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) {
32*0fca6ea1SDimitry Andric   // [ostream.formatted.print]/3
33*0fca6ea1SDimitry Andric   // Effects: Behaves as a formatted output function
34*0fca6ea1SDimitry Andric   // ([ostream.formatted.reqmts]) of os, except that:
35*0fca6ea1SDimitry Andric   // - failure to generate output is reported as specified below, and
36*0fca6ea1SDimitry Andric   // - any exception thrown by the call to vformat is propagated without regard
37*0fca6ea1SDimitry Andric   //   to the value of os.exceptions() and without turning on ios_base::badbit
38*0fca6ea1SDimitry Andric   //   in the error state of os.
39*0fca6ea1SDimitry Andric   // After constructing a sentry object, the function initializes an automatic
40*0fca6ea1SDimitry Andric   // variable via
41*0fca6ea1SDimitry Andric   //   string out = vformat(os.getloc(), fmt, args);
42*0fca6ea1SDimitry Andric 
43*0fca6ea1SDimitry Andric   ostream::sentry __s(__os);
44*0fca6ea1SDimitry Andric   if (__s) {
45*0fca6ea1SDimitry Andric     string __o = std::vformat(__os.getloc(), __fmt, __args);
46*0fca6ea1SDimitry Andric     if (__write_nl)
47*0fca6ea1SDimitry Andric       __o += '\n';
48*0fca6ea1SDimitry Andric 
49*0fca6ea1SDimitry Andric     const char* __str = __o.data();
50*0fca6ea1SDimitry Andric     size_t __len      = __o.size();
51*0fca6ea1SDimitry Andric 
52*0fca6ea1SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
53*0fca6ea1SDimitry Andric     try {
54*0fca6ea1SDimitry Andric #  endif // _LIBCPP_HAS_NO_EXCEPTIONS
55*0fca6ea1SDimitry Andric       typedef ostreambuf_iterator<char> _Ip;
56*0fca6ea1SDimitry Andric       if (std::__pad_and_output(
57*0fca6ea1SDimitry Andric               _Ip(__os),
58*0fca6ea1SDimitry Andric               __str,
59*0fca6ea1SDimitry Andric               (__os.flags() & ios_base::adjustfield) == ios_base::left ? __str + __len : __str,
60*0fca6ea1SDimitry Andric               __str + __len,
61*0fca6ea1SDimitry Andric               __os,
62*0fca6ea1SDimitry Andric               __os.fill())
63*0fca6ea1SDimitry Andric               .failed())
64*0fca6ea1SDimitry Andric         __os.setstate(ios_base::badbit | ios_base::failbit);
65*0fca6ea1SDimitry Andric 
66*0fca6ea1SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
67*0fca6ea1SDimitry Andric     } catch (...) {
68*0fca6ea1SDimitry Andric       __os.__set_badbit_and_consider_rethrow();
69*0fca6ea1SDimitry Andric     }
70*0fca6ea1SDimitry Andric #  endif // _LIBCPP_HAS_NO_EXCEPTIONS
71*0fca6ea1SDimitry Andric   }
72*0fca6ea1SDimitry Andric }
73*0fca6ea1SDimitry Andric 
74*0fca6ea1SDimitry Andric template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
75*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(ostream& __os, string_view __fmt, format_args __args) {
76*0fca6ea1SDimitry Andric   std::__vprint_nonunicode(__os, __fmt, __args, false);
77*0fca6ea1SDimitry Andric }
78*0fca6ea1SDimitry Andric 
79*0fca6ea1SDimitry Andric // Returns the FILE* associated with the __os.
80*0fca6ea1SDimitry Andric // Returns a nullptr when no FILE* is associated with __os.
81*0fca6ea1SDimitry Andric // This function is in the dylib since the type of the buffer associated
82*0fca6ea1SDimitry Andric // with std::cout, std::cerr, and std::clog is only known in the dylib.
83*0fca6ea1SDimitry Andric //
84*0fca6ea1SDimitry Andric // This function implements part of the implementation-defined behavior
85*0fca6ea1SDimitry Andric // of [ostream.formatted.print]/3
86*0fca6ea1SDimitry Andric //   If the function is vprint_unicode and os is a stream that refers to
87*0fca6ea1SDimitry Andric //   a terminal capable of displaying Unicode which is determined in an
88*0fca6ea1SDimitry Andric //   implementation-defined manner, writes out to the terminal using the
89*0fca6ea1SDimitry Andric //   native Unicode API;
90*0fca6ea1SDimitry Andric // Whether the returned FILE* is "a terminal capable of displaying Unicode"
91*0fca6ea1SDimitry Andric // is determined in the same way as the print(FILE*, ...) overloads.
92*0fca6ea1SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI FILE* __get_ostream_file(ostream& __os);
93*0fca6ea1SDimitry Andric 
94*0fca6ea1SDimitry Andric #  ifndef _LIBCPP_HAS_NO_UNICODE
95*0fca6ea1SDimitry Andric template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
96*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI void __vprint_unicode(ostream& __os, string_view __fmt, format_args __args, bool __write_nl) {
97*0fca6ea1SDimitry Andric #    if _LIBCPP_AVAILABILITY_HAS_PRINT == 0
98*0fca6ea1SDimitry Andric   return std::__vprint_nonunicode(__os, __fmt, __args, __write_nl);
99*0fca6ea1SDimitry Andric #    else
100*0fca6ea1SDimitry Andric   FILE* __file = std::__get_ostream_file(__os);
101*0fca6ea1SDimitry Andric   if (!__file || !__print::__is_terminal(__file))
102*0fca6ea1SDimitry Andric     return std::__vprint_nonunicode(__os, __fmt, __args, __write_nl);
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric   // [ostream.formatted.print]/3
105*0fca6ea1SDimitry Andric   //    If the function is vprint_unicode and os is a stream that refers to a
106*0fca6ea1SDimitry Andric   //    terminal capable of displaying Unicode which is determined in an
107*0fca6ea1SDimitry Andric   //    implementation-defined manner, writes out to the terminal using the
108*0fca6ea1SDimitry Andric   //    native Unicode API; if out contains invalid code units, the behavior is
109*0fca6ea1SDimitry Andric   //    undefined and implementations are encouraged to diagnose it. If the
110*0fca6ea1SDimitry Andric   //    native Unicode API is used, the function flushes os before writing out.
111*0fca6ea1SDimitry Andric   //
112*0fca6ea1SDimitry Andric   // This is the path for the native API, start with flushing.
113*0fca6ea1SDimitry Andric   __os.flush();
114*0fca6ea1SDimitry Andric 
115*0fca6ea1SDimitry Andric #      ifndef _LIBCPP_HAS_NO_EXCEPTIONS
116*0fca6ea1SDimitry Andric   try {
117*0fca6ea1SDimitry Andric #      endif // _LIBCPP_HAS_NO_EXCEPTIONS
118*0fca6ea1SDimitry Andric     ostream::sentry __s(__os);
119*0fca6ea1SDimitry Andric     if (__s) {
120*0fca6ea1SDimitry Andric #      ifndef _LIBCPP_WIN32API
121*0fca6ea1SDimitry Andric       __print::__vprint_unicode_posix(__file, __fmt, __args, __write_nl, true);
122*0fca6ea1SDimitry Andric #      elif !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
123*0fca6ea1SDimitry Andric     __print::__vprint_unicode_windows(__file, __fmt, __args, __write_nl, true);
124*0fca6ea1SDimitry Andric #      else
125*0fca6ea1SDimitry Andric #        error "Windows builds with wchar_t disabled are not supported."
126*0fca6ea1SDimitry Andric #      endif
127*0fca6ea1SDimitry Andric     }
128*0fca6ea1SDimitry Andric 
129*0fca6ea1SDimitry Andric #      ifndef _LIBCPP_HAS_NO_EXCEPTIONS
130*0fca6ea1SDimitry Andric   } catch (...) {
131*0fca6ea1SDimitry Andric     __os.__set_badbit_and_consider_rethrow();
132*0fca6ea1SDimitry Andric   }
133*0fca6ea1SDimitry Andric #      endif // _LIBCPP_HAS_NO_EXCEPTIONS
134*0fca6ea1SDimitry Andric #    endif   // _LIBCPP_AVAILABILITY_HAS_PRINT
135*0fca6ea1SDimitry Andric }
136*0fca6ea1SDimitry Andric 
137*0fca6ea1SDimitry Andric template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
138*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(ostream& __os, string_view __fmt, format_args __args) {
139*0fca6ea1SDimitry Andric   std::__vprint_unicode(__os, __fmt, __args, false);
140*0fca6ea1SDimitry Andric }
141*0fca6ea1SDimitry Andric #  endif // _LIBCPP_HAS_NO_UNICODE
142*0fca6ea1SDimitry Andric 
143*0fca6ea1SDimitry Andric template <class... _Args>
144*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI void print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) {
145*0fca6ea1SDimitry Andric #  ifndef _LIBCPP_HAS_NO_UNICODE
146*0fca6ea1SDimitry Andric   if constexpr (__print::__use_unicode_execution_charset)
147*0fca6ea1SDimitry Andric     std::__vprint_unicode(__os, __fmt.get(), std::make_format_args(__args...), false);
148*0fca6ea1SDimitry Andric   else
149*0fca6ea1SDimitry Andric     std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), false);
150*0fca6ea1SDimitry Andric #  else  // _LIBCPP_HAS_NO_UNICODE
151*0fca6ea1SDimitry Andric   std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), false);
152*0fca6ea1SDimitry Andric #  endif // _LIBCPP_HAS_NO_UNICODE
153*0fca6ea1SDimitry Andric }
154*0fca6ea1SDimitry Andric 
155*0fca6ea1SDimitry Andric template <class... _Args>
156*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI void println(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args) {
157*0fca6ea1SDimitry Andric #  ifndef _LIBCPP_HAS_NO_UNICODE
158*0fca6ea1SDimitry Andric   // Note the wording in the Standard is inefficient. The output of
159*0fca6ea1SDimitry Andric   // std::format is a std::string which is then copied. This solution
160*0fca6ea1SDimitry Andric   // just appends a newline at the end of the output.
161*0fca6ea1SDimitry Andric   if constexpr (__print::__use_unicode_execution_charset)
162*0fca6ea1SDimitry Andric     std::__vprint_unicode(__os, __fmt.get(), std::make_format_args(__args...), true);
163*0fca6ea1SDimitry Andric   else
164*0fca6ea1SDimitry Andric     std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), true);
165*0fca6ea1SDimitry Andric #  else  // _LIBCPP_HAS_NO_UNICODE
166*0fca6ea1SDimitry Andric   std::__vprint_nonunicode(__os, __fmt.get(), std::make_format_args(__args...), true);
167*0fca6ea1SDimitry Andric #  endif // _LIBCPP_HAS_NO_UNICODE
168*0fca6ea1SDimitry Andric }
169*0fca6ea1SDimitry Andric 
170*0fca6ea1SDimitry Andric template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563).
171*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void println(ostream& __os) {
172*0fca6ea1SDimitry Andric   std::print(__os, "\n");
173*0fca6ea1SDimitry Andric }
174*0fca6ea1SDimitry Andric 
175*0fca6ea1SDimitry Andric #endif // _LIBCPP_STD_VER >= 23
176*0fca6ea1SDimitry Andric 
177*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric #endif // _LIBCPP___OSTREAM_PRINT_H
180