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.
12 # include <fstream> // std::filebuf
17 # include <ext/stdio_filebuf.h>
18 # include <ext/stdio_sync_filebuf.h>
23 #include "chrono.h" // formatbuf
28 // Generate a unique explicit instantion in every translation unit using a tag
29 // type in an anonymous namespace.
31 struct file_access_tag
{};
33 template <typename Tag
, typename BufType
, FILE* BufType::*FileMemberPtr
>
35 friend auto get_file(BufType
& obj
) -> FILE* { return obj
.*FileMemberPtr
; }
39 template class file_access
<file_access_tag
, std::filebuf
,
40 &std::filebuf::_Myfile
>;
41 auto get_file(std::filebuf
&) -> FILE*;
44 inline auto write_ostream_unicode(std::ostream
& os
, fmt::string_view data
)
47 #if FMT_MSC_VERSION && FMT_USE_RTTI
48 if (auto* buf
= dynamic_cast<std::filebuf
*>(os
.rdbuf()))
52 #elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI
53 auto* rdbuf
= os
.rdbuf();
54 if (auto* sfbuf
= dynamic_cast<__gnu_cxx::stdio_sync_filebuf
<char>*>(rdbuf
))
56 else if (auto* fbuf
= dynamic_cast<__gnu_cxx::stdio_filebuf
<char>*>(rdbuf
))
61 ignore_unused(os
, data
, f
);
68 return write_console(fd
, data
);
74 inline auto write_ostream_unicode(std::wostream
&,
75 fmt::basic_string_view
<wchar_t>) -> bool {
79 // Write the content of buf to os.
80 // It is a separate function rather than a part of vprint to simplify testing.
81 template <typename Char
>
82 void write_buffer(std::basic_ostream
<Char
>& os
, buffer
<Char
>& buf
) {
83 const Char
* buf_data
= buf
.data();
84 using unsigned_streamsize
= std::make_unsigned
<std::streamsize
>::type
;
85 unsigned_streamsize size
= buf
.size();
86 unsigned_streamsize max_size
= to_unsigned(max_value
<std::streamsize
>());
88 unsigned_streamsize n
= size
<= max_size
? size
: max_size
;
89 os
.write(buf_data
, static_cast<std::streamsize
>(n
));
95 template <typename Char
, typename T
>
96 void format_value(buffer
<Char
>& buf
, const T
& value
) {
97 auto&& format_buf
= formatbuf
<std::basic_streambuf
<Char
>>(buf
);
98 auto&& output
= std::basic_ostream
<Char
>(&format_buf
);
99 #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
100 output
.imbue(std::locale::classic()); // The default is always unlocalized.
103 output
.exceptions(std::ios_base::failbit
| std::ios_base::badbit
);
106 template <typename T
> struct streamed_view
{
110 } // namespace detail
112 // Formats an object of type T that has an overloaded ostream operator<<.
113 template <typename Char
>
114 struct basic_ostream_formatter
: formatter
<basic_string_view
<Char
>, Char
> {
115 void set_debug_format() = delete;
117 template <typename T
, typename Context
>
118 auto format(const T
& value
, Context
& ctx
) const -> decltype(ctx
.out()) {
119 auto buffer
= basic_memory_buffer
<Char
>();
120 detail::format_value(buffer
, value
);
121 return formatter
<basic_string_view
<Char
>, Char
>::format(
122 {buffer
.data(), buffer
.size()}, ctx
);
126 using ostream_formatter
= basic_ostream_formatter
<char>;
128 template <typename T
, typename Char
>
129 struct formatter
<detail::streamed_view
<T
>, Char
>
130 : basic_ostream_formatter
<Char
> {
131 template <typename Context
>
132 auto format(detail::streamed_view
<T
> view
, Context
& ctx
) const
133 -> decltype(ctx
.out()) {
134 return basic_ostream_formatter
<Char
>::format(view
.value
, ctx
);
139 * Returns a view that formats `value` via an ostream `operator<<`.
143 * fmt::print("Current thread id: {}\n",
144 * fmt::streamed(std::this_thread::get_id()));
146 template <typename T
>
147 constexpr auto streamed(const T
& value
) -> detail::streamed_view
<T
> {
153 inline void vprint_directly(std::ostream
& os
, string_view format_str
,
155 auto buffer
= memory_buffer();
156 detail::vformat_to(buffer
, format_str
, args
);
157 detail::write_buffer(os
, buffer
);
160 } // namespace detail
162 FMT_EXPORT
template <typename Char
>
163 void vprint(std::basic_ostream
<Char
>& os
,
164 basic_string_view
<type_identity_t
<Char
>> format_str
,
165 typename
detail::vformat_args
<Char
>::type args
) {
166 auto buffer
= basic_memory_buffer
<Char
>();
167 detail::vformat_to(buffer
, format_str
, args
);
168 if (detail::write_ostream_unicode(os
, {buffer
.data(), buffer
.size()})) return;
169 detail::write_buffer(os
, buffer
);
173 * Prints formatted data to the stream `os`.
177 * fmt::print(cerr, "Don't {}!", "panic");
179 FMT_EXPORT
template <typename
... T
>
180 void print(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
181 const auto& vargs
= fmt::make_format_args(args
...);
182 if (detail::use_utf8())
183 vprint(os
, fmt
, vargs
);
185 detail::vprint_directly(os
, fmt
, vargs
);
189 template <typename
... Args
>
190 void print(std::wostream
& os
,
191 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
193 vprint(os
, fmt
, fmt::make_format_args
<buffered_context
<wchar_t>>(args
...));
196 FMT_EXPORT
template <typename
... T
>
197 void println(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
198 fmt::print(os
, "{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
202 template <typename
... Args
>
203 void println(std::wostream
& os
,
204 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
206 print(os
, L
"{}\n", fmt::format(fmt
, std::forward
<Args
>(args
)...));
211 #endif // FMT_OSTREAM_H_