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.
11 #include <fstream> // std::filebuf
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>
26 // Generate a unique explicit instantion in every translation unit using a tag
27 // type in an anonymous namespace.
29 struct file_access_tag
{};
31 template <typename Tag
, typename BufType
, FILE* BufType::*FileMemberPtr
>
33 friend auto get_file(BufType
& obj
) -> FILE* { return obj
.*FileMemberPtr
; }
37 template class file_access
<file_access_tag
, std::filebuf
,
38 &std::filebuf::_Myfile
>;
39 auto get_file(std::filebuf
&) -> FILE*;
40 #elif defined(_WIN32) && defined(_LIBCPP_VERSION)
41 template class file_access
<file_access_tag
, std::__stdoutbuf
<char>,
42 &std::__stdoutbuf
<char>::__file_
>;
43 auto get_file(std::__stdoutbuf
<char>&) -> FILE*;
46 inline bool write_ostream_unicode(std::ostream
& os
, fmt::string_view data
) {
48 if (auto* buf
= dynamic_cast<std::filebuf
*>(os
.rdbuf()))
49 if (FILE* f
= get_file(*buf
)) return write_console(f
, data
);
50 #elif defined(_WIN32) && defined(__GLIBCXX__)
51 auto* rdbuf
= os
.rdbuf();
53 if (auto* sfbuf
= dynamic_cast<__gnu_cxx::stdio_sync_filebuf
<char>*>(rdbuf
))
54 c_file
= sfbuf
->file();
55 else if (auto* fbuf
= dynamic_cast<__gnu_cxx::stdio_filebuf
<char>*>(rdbuf
))
56 c_file
= fbuf
->file();
59 if (c_file
) return write_console(c_file
, data
);
60 #elif defined(_WIN32) && defined(_LIBCPP_VERSION)
61 if (auto* buf
= dynamic_cast<std::__stdoutbuf
<char>*>(os
.rdbuf()))
62 if (FILE* f
= get_file(*buf
)) return write_console(f
, data
);
64 ignore_unused(os
, data
);
68 inline bool write_ostream_unicode(std::wostream
&,
69 fmt::basic_string_view
<wchar_t>) {
73 // Write the content of buf to os.
74 // It is a separate function rather than a part of vprint to simplify testing.
75 template <typename Char
>
76 void write_buffer(std::basic_ostream
<Char
>& os
, buffer
<Char
>& buf
) {
77 const Char
* buf_data
= buf
.data();
78 using unsigned_streamsize
= std::make_unsigned
<std::streamsize
>::type
;
79 unsigned_streamsize size
= buf
.size();
80 unsigned_streamsize max_size
= to_unsigned(max_value
<std::streamsize
>());
82 unsigned_streamsize n
= size
<= max_size
? size
: max_size
;
83 os
.write(buf_data
, static_cast<std::streamsize
>(n
));
89 template <typename Char
, typename T
>
90 void format_value(buffer
<Char
>& buf
, const T
& value
,
91 locale_ref loc
= locale_ref()) {
92 auto&& format_buf
= formatbuf
<std::basic_streambuf
<Char
>>(buf
);
93 auto&& output
= std::basic_ostream
<Char
>(&format_buf
);
94 #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
95 if (loc
) output
.imbue(loc
.get
<std::locale
>());
98 output
.exceptions(std::ios_base::failbit
| std::ios_base::badbit
);
101 template <typename T
> struct streamed_view
{ const T
& value
; };
103 } // namespace detail
105 // Formats an object of type T that has an overloaded ostream operator<<.
106 template <typename Char
>
107 struct basic_ostream_formatter
: formatter
<basic_string_view
<Char
>, Char
> {
108 void set_debug_format() = delete;
110 template <typename T
, typename OutputIt
>
111 auto format(const T
& value
, basic_format_context
<OutputIt
, Char
>& ctx
) const
113 auto buffer
= basic_memory_buffer
<Char
>();
114 detail::format_value(buffer
, value
, ctx
.locale());
115 return formatter
<basic_string_view
<Char
>, Char
>::format(
116 {buffer
.data(), buffer
.size()}, ctx
);
120 using ostream_formatter
= basic_ostream_formatter
<char>;
122 template <typename T
, typename Char
>
123 struct formatter
<detail::streamed_view
<T
>, Char
>
124 : basic_ostream_formatter
<Char
> {
125 template <typename OutputIt
>
126 auto format(detail::streamed_view
<T
> view
,
127 basic_format_context
<OutputIt
, Char
>& ctx
) const -> OutputIt
{
128 return basic_ostream_formatter
<Char
>::format(view
.value
, ctx
);
134 Returns a view that formats `value` via an ostream ``operator<<``.
138 fmt::print("Current thread id: {}\n",
139 fmt::streamed(std::this_thread::get_id()));
142 template <typename T
>
143 auto streamed(const T
& value
) -> detail::streamed_view
<T
> {
149 inline void vprint_directly(std::ostream
& os
, string_view format_str
,
151 auto buffer
= memory_buffer();
152 detail::vformat_to(buffer
, format_str
, args
);
153 detail::write_buffer(os
, buffer
);
156 } // namespace detail
158 FMT_EXPORT
template <typename Char
>
159 void vprint(std::basic_ostream
<Char
>& os
,
160 basic_string_view
<type_identity_t
<Char
>> format_str
,
161 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
162 auto buffer
= basic_memory_buffer
<Char
>();
163 detail::vformat_to(buffer
, format_str
, args
);
164 if (detail::write_ostream_unicode(os
, {buffer
.data(), buffer
.size()})) return;
165 detail::write_buffer(os
, buffer
);
170 Prints formatted data to the stream *os*.
174 fmt::print(cerr, "Don't {}!", "panic");
177 FMT_EXPORT
template <typename
... T
>
178 void print(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
179 const auto& vargs
= fmt::make_format_args(args
...);
180 if (detail::is_utf8())
181 vprint(os
, fmt
, vargs
);
183 detail::vprint_directly(os
, fmt
, vargs
);
187 template <typename
... Args
>
188 void print(std::wostream
& os
,
189 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
191 vprint(os
, fmt
, fmt::make_format_args
<buffer_context
<wchar_t>>(args
...));
194 FMT_EXPORT
template <typename
... T
>
195 void println(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
196 fmt::print(os
, "{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
200 template <typename
... Args
>
201 void println(std::wostream
& os
,
202 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
204 print(os
, L
"{}\n", fmt::format(fmt
, std::forward
<Args
>(args
)...));
209 #endif // FMT_OSTREAM_H_