1 // Formatting library for C++ - std::ostream support
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
13 #if defined(_WIN32) && defined(__GLIBCXX__)
14 # include <ext/stdio_filebuf.h>
15 # include <ext/stdio_sync_filebuf.h>
16 #elif defined(_WIN32) && defined(_LIBCPP_VERSION)
17 # include <__std_stream>
24 template <typename OutputIt
, typename Char
> class basic_printf_context
;
28 // Checks if T has a user-defined operator<<.
29 template <typename T
, typename Char
, typename Enable
= void>
34 -> bool_constant
<sizeof(std::declval
<std::basic_ostream
<Char
>&>()
35 << std::declval
<U
>()) != 0>;
37 template <typename
> static auto test(...) -> std::false_type
;
39 using result
= decltype(test
<T
>(0));
42 is_streamable() = default;
44 static const bool value
= result::value
;
47 // Formatting of built-in types and arrays is intentionally disabled because
48 // it's handled by standard (non-ostream) formatters.
49 template <typename T
, typename Char
>
53 std::is_arithmetic
<T
>::value
|| std::is_array
<T
>::value
||
54 std::is_pointer
<T
>::value
|| std::is_same
<T
, char8_type
>::value
||
55 std::is_convertible
<T
, fmt::basic_string_view
<Char
>>::value
||
56 std::is_same
<T
, std_string_view
<Char
>>::value
||
57 (std::is_convertible
<T
, int>::value
&& !std::is_enum
<T
>::value
)>>
60 // Generate a unique explicit instantion in every translation unit using a tag
61 // type in an anonymous namespace.
63 struct file_access_tag
{};
65 template <class Tag
, class BufType
, FILE* BufType::*FileMemberPtr
>
67 friend auto get_file(BufType
& obj
) -> FILE* { return obj
.*FileMemberPtr
; }
71 template class file_access
<file_access_tag
, std::filebuf
,
72 &std::filebuf::_Myfile
>;
73 auto get_file(std::filebuf
&) -> FILE*;
74 #elif defined(_WIN32) && defined(_LIBCPP_VERSION)
75 template class file_access
<file_access_tag
, std::__stdoutbuf
<char>,
76 &std::__stdoutbuf
<char>::__file_
>;
77 auto get_file(std::__stdoutbuf
<char>&) -> FILE*;
80 inline bool write_ostream_unicode(std::ostream
& os
, fmt::string_view data
) {
82 if (auto* buf
= dynamic_cast<std::filebuf
*>(os
.rdbuf()))
83 if (FILE* f
= get_file(*buf
)) return write_console(f
, data
);
84 #elif defined(_WIN32) && defined(__GLIBCXX__)
85 auto* rdbuf
= os
.rdbuf();
87 if (auto* fbuf
= dynamic_cast<__gnu_cxx::stdio_sync_filebuf
<char>*>(rdbuf
))
88 c_file
= fbuf
->file();
89 else if (auto* fbuf
= dynamic_cast<__gnu_cxx::stdio_filebuf
<char>*>(rdbuf
))
90 c_file
= fbuf
->file();
93 if (c_file
) return write_console(c_file
, data
);
94 #elif defined(_WIN32) && defined(_LIBCPP_VERSION)
95 if (auto* buf
= dynamic_cast<std::__stdoutbuf
<char>*>(os
.rdbuf()))
96 if (FILE* f
= get_file(*buf
)) return write_console(f
, data
);
98 ignore_unused(os
, data
);
102 inline bool write_ostream_unicode(std::wostream
&,
103 fmt::basic_string_view
<wchar_t>) {
107 // Write the content of buf to os.
108 // It is a separate function rather than a part of vprint to simplify testing.
109 template <typename Char
>
110 void write_buffer(std::basic_ostream
<Char
>& os
, buffer
<Char
>& buf
) {
111 const Char
* buf_data
= buf
.data();
112 using unsigned_streamsize
= std::make_unsigned
<std::streamsize
>::type
;
113 unsigned_streamsize size
= buf
.size();
114 unsigned_streamsize max_size
= to_unsigned(max_value
<std::streamsize
>());
116 unsigned_streamsize n
= size
<= max_size
? size
: max_size
;
117 os
.write(buf_data
, static_cast<std::streamsize
>(n
));
123 template <typename Char
, typename T
>
124 void format_value(buffer
<Char
>& buf
, const T
& value
,
125 locale_ref loc
= locale_ref()) {
126 auto&& format_buf
= formatbuf
<std::basic_streambuf
<Char
>>(buf
);
127 auto&& output
= std::basic_ostream
<Char
>(&format_buf
);
128 #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
129 if (loc
) output
.imbue(loc
.get
<std::locale
>());
132 output
.exceptions(std::ios_base::failbit
| std::ios_base::badbit
);
135 template <typename T
> struct streamed_view
{ const T
& value
; };
137 } // namespace detail
139 // Formats an object of type T that has an overloaded ostream operator<<.
140 template <typename Char
>
141 struct basic_ostream_formatter
: formatter
<basic_string_view
<Char
>, Char
> {
142 void set_debug_format() = delete;
144 template <typename T
, typename OutputIt
>
145 auto format(const T
& value
, basic_format_context
<OutputIt
, Char
>& ctx
) const
147 auto buffer
= basic_memory_buffer
<Char
>();
148 format_value(buffer
, value
, ctx
.locale());
149 return formatter
<basic_string_view
<Char
>, Char
>::format(
150 {buffer
.data(), buffer
.size()}, ctx
);
154 using ostream_formatter
= basic_ostream_formatter
<char>;
156 template <typename T
, typename Char
>
157 struct formatter
<detail::streamed_view
<T
>, Char
>
158 : basic_ostream_formatter
<Char
> {
159 template <typename OutputIt
>
160 auto format(detail::streamed_view
<T
> view
,
161 basic_format_context
<OutputIt
, Char
>& ctx
) const -> OutputIt
{
162 return basic_ostream_formatter
<Char
>::format(view
.value
, ctx
);
168 Returns a view that formats `value` via an ostream ``operator<<``.
172 fmt::print("Current thread id: {}\n",
173 fmt::streamed(std::this_thread::get_id()));
176 template <typename T
>
177 auto streamed(const T
& value
) -> detail::streamed_view
<T
> {
183 // Formats an object of type T that has an overloaded ostream operator<<.
184 template <typename T
, typename Char
>
185 struct fallback_formatter
<T
, Char
, enable_if_t
<is_streamable
<T
, Char
>::value
>>
186 : basic_ostream_formatter
<Char
> {
187 using basic_ostream_formatter
<Char
>::format
;
190 inline void vprint_directly(std::ostream
& os
, string_view format_str
,
192 auto buffer
= memory_buffer();
193 detail::vformat_to(buffer
, format_str
, args
);
194 detail::write_buffer(os
, buffer
);
197 } // namespace detail
199 FMT_MODULE_EXPORT
template <typename Char
>
200 void vprint(std::basic_ostream
<Char
>& os
,
201 basic_string_view
<type_identity_t
<Char
>> format_str
,
202 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
203 auto buffer
= basic_memory_buffer
<Char
>();
204 detail::vformat_to(buffer
, format_str
, args
);
205 if (detail::write_ostream_unicode(os
, {buffer
.data(), buffer
.size()})) return;
206 detail::write_buffer(os
, buffer
);
211 Prints formatted data to the stream *os*.
215 fmt::print(cerr, "Don't {}!", "panic");
218 FMT_MODULE_EXPORT
template <typename
... T
>
219 void print(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
220 const auto& vargs
= fmt::make_format_args(args
...);
221 if (detail::is_utf8())
222 vprint(os
, fmt
, vargs
);
224 detail::vprint_directly(os
, fmt
, vargs
);
228 template <typename
... Args
>
229 void print(std::wostream
& os
,
230 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
232 vprint(os
, fmt
, fmt::make_format_args
<buffer_context
<wchar_t>>(args
...));
237 #endif // FMT_OSTREAM_H_