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
15 # include <ext/stdio_filebuf.h>
16 # include <ext/stdio_sync_filebuf.h>
26 template <typename Streambuf
> class formatbuf
: public Streambuf
{
28 using char_type
= typename
Streambuf::char_type
;
29 using streamsize
= decltype(std::declval
<Streambuf
>().sputn(nullptr, 0));
30 using int_type
= typename
Streambuf::int_type
;
31 using traits_type
= typename
Streambuf::traits_type
;
33 buffer
<char_type
>& buffer_
;
36 explicit formatbuf(buffer
<char_type
>& buf
) : buffer_(buf
) {}
39 // The put area is always empty. This makes the implementation simpler and has
40 // the advantage that the streambuf and the buffer are always in sync and
41 // sputc never writes into uninitialized memory. A disadvantage is that each
42 // call to sputc always results in a (virtual) call to overflow. There is no
43 // disadvantage here for sputn since this always results in a call to xsputn.
45 auto overflow(int_type ch
) -> int_type override
{
46 if (!traits_type::eq_int_type(ch
, traits_type::eof()))
47 buffer_
.push_back(static_cast<char_type
>(ch
));
51 auto xsputn(const char_type
* s
, streamsize count
) -> streamsize override
{
52 buffer_
.append(s
, s
+ count
);
57 // Generate a unique explicit instantion in every translation unit using a tag
58 // type in an anonymous namespace.
60 struct file_access_tag
{};
62 template <typename Tag
, typename BufType
, FILE* BufType::*FileMemberPtr
>
64 friend auto get_file(BufType
& obj
) -> FILE* { return obj
.*FileMemberPtr
; }
68 template class file_access
<file_access_tag
, std::filebuf
,
69 &std::filebuf::_Myfile
>;
70 auto get_file(std::filebuf
&) -> FILE*;
73 inline auto write_ostream_unicode(std::ostream
& os
, fmt::string_view data
)
77 if (auto* buf
= dynamic_cast<std::filebuf
*>(os
.rdbuf()))
81 #elif defined(_WIN32) && defined(__GLIBCXX__)
82 auto* rdbuf
= os
.rdbuf();
83 if (auto* sfbuf
= dynamic_cast<__gnu_cxx::stdio_sync_filebuf
<char>*>(rdbuf
))
85 else if (auto* fbuf
= dynamic_cast<__gnu_cxx::stdio_filebuf
<char>*>(rdbuf
))
90 ignore_unused(os
, data
, f
);
97 return write_console(fd
, data
);
103 inline auto write_ostream_unicode(std::wostream
&,
104 fmt::basic_string_view
<wchar_t>) -> bool {
108 // Write the content of buf to os.
109 // It is a separate function rather than a part of vprint to simplify testing.
110 template <typename Char
>
111 void write_buffer(std::basic_ostream
<Char
>& os
, buffer
<Char
>& buf
) {
112 const Char
* buf_data
= buf
.data();
113 using unsigned_streamsize
= std::make_unsigned
<std::streamsize
>::type
;
114 unsigned_streamsize size
= buf
.size();
115 unsigned_streamsize max_size
= to_unsigned(max_value
<std::streamsize
>());
117 unsigned_streamsize n
= size
<= max_size
? size
: max_size
;
118 os
.write(buf_data
, static_cast<std::streamsize
>(n
));
124 template <typename Char
, typename T
>
125 void format_value(buffer
<Char
>& buf
, const T
& value
) {
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 output
.imbue(std::locale::classic()); // The default is always unlocalized.
132 output
.exceptions(std::ios_base::failbit
| std::ios_base::badbit
);
135 template <typename T
> struct streamed_view
{
139 } // namespace detail
141 // Formats an object of type T that has an overloaded ostream operator<<.
142 template <typename Char
>
143 struct basic_ostream_formatter
: formatter
<basic_string_view
<Char
>, Char
> {
144 void set_debug_format() = delete;
146 template <typename T
, typename OutputIt
>
147 auto format(const T
& value
, basic_format_context
<OutputIt
, Char
>& ctx
) const
149 auto buffer
= basic_memory_buffer
<Char
>();
150 detail::format_value(buffer
, value
);
151 return formatter
<basic_string_view
<Char
>, Char
>::format(
152 {buffer
.data(), buffer
.size()}, ctx
);
156 using ostream_formatter
= basic_ostream_formatter
<char>;
158 template <typename T
, typename Char
>
159 struct formatter
<detail::streamed_view
<T
>, Char
>
160 : basic_ostream_formatter
<Char
> {
161 template <typename OutputIt
>
162 auto format(detail::streamed_view
<T
> view
,
163 basic_format_context
<OutputIt
, Char
>& ctx
) const -> OutputIt
{
164 return basic_ostream_formatter
<Char
>::format(view
.value
, ctx
);
170 Returns a view that formats `value` via an ostream ``operator<<``.
174 fmt::print("Current thread id: {}\n",
175 fmt::streamed(std::this_thread::get_id()));
178 template <typename T
>
179 constexpr auto streamed(const T
& value
) -> detail::streamed_view
<T
> {
185 inline void vprint_directly(std::ostream
& os
, string_view format_str
,
187 auto buffer
= memory_buffer();
188 detail::vformat_to(buffer
, format_str
, args
);
189 detail::write_buffer(os
, buffer
);
192 } // namespace detail
194 FMT_EXPORT
template <typename Char
>
195 void vprint(std::basic_ostream
<Char
>& os
,
196 basic_string_view
<type_identity_t
<Char
>> format_str
,
197 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
198 auto buffer
= basic_memory_buffer
<Char
>();
199 detail::vformat_to(buffer
, format_str
, args
);
200 if (detail::write_ostream_unicode(os
, {buffer
.data(), buffer
.size()})) return;
201 detail::write_buffer(os
, buffer
);
206 Prints formatted data to the stream *os*.
210 fmt::print(cerr, "Don't {}!", "panic");
213 FMT_EXPORT
template <typename
... T
>
214 void print(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
215 const auto& vargs
= fmt::make_format_args(args
...);
216 if (detail::is_utf8())
217 vprint(os
, fmt
, vargs
);
219 detail::vprint_directly(os
, fmt
, vargs
);
223 template <typename
... Args
>
224 void print(std::wostream
& os
,
225 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
227 vprint(os
, fmt
, fmt::make_format_args
<buffer_context
<wchar_t>>(args
...));
230 FMT_EXPORT
template <typename
... T
>
231 void println(std::ostream
& os
, format_string
<T
...> fmt
, T
&&... args
) {
232 fmt::print(os
, "{}\n", fmt::format(fmt
, std::forward
<T
>(args
)...));
236 template <typename
... Args
>
237 void println(std::wostream
& os
,
238 basic_format_string
<wchar_t, type_identity_t
<Args
>...> fmt
,
240 print(os
, L
"{}\n", fmt::format(fmt
, std::forward
<Args
>(args
)...));
245 #endif // FMT_OSTREAM_H_