diff --git a/include/fmt/color.h b/include/fmt/color.h index 1e785f73..ae63b940 100644 --- a/include/fmt/color.h +++ b/include/fmt/color.h @@ -330,7 +330,7 @@ FMT_CONSTEXPR inline auto operator|(emphasis lhs, emphasis rhs) noexcept namespace detail { template struct ansi_color_escape { - FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color, + FMT_CONSTEXPR ansi_color_escape(color_type text_color, const char* esc) noexcept { // If we have a terminal color, we need to output another escape code // sequence. @@ -412,13 +412,13 @@ template struct ansi_color_escape { }; template -FMT_CONSTEXPR auto make_foreground_color(detail::color_type foreground) noexcept +FMT_CONSTEXPR auto make_foreground_color(color_type foreground) noexcept -> ansi_color_escape { return ansi_color_escape(foreground, "\x1b[38;2;"); } template -FMT_CONSTEXPR auto make_background_color(detail::color_type background) noexcept +FMT_CONSTEXPR auto make_background_color(color_type background) noexcept -> ansi_color_escape { return ansi_color_escape(background, "\x1b[48;2;"); } @@ -434,7 +434,7 @@ template inline void reset_color(buffer& buffer) { buffer.append(reset_color.begin(), reset_color.end()); } -template struct styled_arg : detail::view { +template struct styled_arg : view { const T& value; text_style style; styled_arg(const T& v, text_style s) : value(v), style(s) {} @@ -447,21 +447,21 @@ void vformat_to(buffer& buf, const text_style& ts, bool has_style = false; if (ts.has_emphasis()) { has_style = true; - auto emphasis = detail::make_emphasis(ts.get_emphasis()); + auto emphasis = make_emphasis(ts.get_emphasis()); buf.append(emphasis.begin(), emphasis.end()); } if (ts.has_foreground()) { has_style = true; - auto foreground = detail::make_foreground_color(ts.get_foreground()); + auto foreground = make_foreground_color(ts.get_foreground()); buf.append(foreground.begin(), foreground.end()); } if (ts.has_background()) { has_style = true; - auto background = detail::make_background_color(ts.get_background()); + auto background = make_background_color(ts.get_background()); buf.append(background.begin(), background.end()); } - detail::vformat_to(buf, fmt, args); - if (has_style) detail::reset_color(buf); + vformat_to(buf, fmt, args); + if (has_style) reset_color(buf); } } // namespace detail diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index d1ec65ab..8ae1d5a7 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -41,47 +41,12 @@ template class file_access FILE*; #endif -inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data) - -> bool { - FILE* f = nullptr; -#if FMT_MSC_VERSION && FMT_USE_RTTI - if (auto* buf = dynamic_cast(os.rdbuf())) - f = get_file(*buf); - else - return false; -#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI - auto* rdbuf = os.rdbuf(); - if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) - f = sfbuf->file(); - else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(rdbuf)) - f = fbuf->file(); - else - return false; -#else - ignore_unused(os, data, f); -#endif -#ifdef _WIN32 - if (f) { - int fd = _fileno(f); - if (_isatty(fd)) { - os.flush(); - return write_console(fd, data); - } - } -#endif - return false; -} -inline auto write_ostream_unicode(std::wostream&, - fmt::basic_string_view) -> bool { - return false; -} - // Write the content of buf to os. // It is a separate function rather than a part of vprint to simplify testing. template void write_buffer(std::basic_ostream& os, buffer& buf) { const Char* buf_data = buf.data(); - using unsigned_streamsize = std::make_unsigned::type; + using unsigned_streamsize =make_unsigned_t; unsigned_streamsize size = buf.size(); unsigned_streamsize max_size = to_unsigned(max_value()); do { @@ -96,9 +61,7 @@ template void format_value(buffer& buf, const T& value) { auto&& format_buf = formatbuf>(buf); auto&& output = std::basic_ostream(&format_buf); -#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) output.imbue(std::locale::classic()); // The default is always unlocalized. -#endif output << value; output.exceptions(std::ios_base::failbit | std::ios_base::badbit); } @@ -106,7 +69,6 @@ void format_value(buffer& buf, const T& value) { template struct streamed_view { const T& value; }; - } // namespace detail // Formats an object of type T that has an overloaded ostream operator<<. @@ -148,14 +110,31 @@ constexpr auto streamed(const T& value) -> detail::streamed_view { return {value}; } -FMT_EXPORT template -void vprint(std::basic_ostream& os, - basic_string_view> fmt, - typename detail::vformat_args::type args) { - auto buffer = basic_memory_buffer(); +inline void vprint(std::ostream& os, string_view fmt, format_args args) { + auto buffer = memory_buffer(); detail::vformat_to(buffer, fmt, args); - if (!detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) - detail::write_buffer(os, buffer); + FILE* f = nullptr; +#if FMT_MSC_VERSION && FMT_USE_RTTI + if (auto* buf = dynamic_cast(os.rdbuf())) + f = detail::get_file(*buf); +#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI + auto* rdbuf = os.rdbuf(); + if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) + f = sfbuf->file(); + else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(rdbuf)) + f = fbuf->file(); +#endif +#ifdef _WIN32 + if (f) { + int fd = _fileno(f); + if (_isatty(fd)) { + os.flush(); + if (detail::write_console(fd, {buffer.data(), buffer.size()})) return; + } + } +#endif + detail::ignore_unused(f); + detail::write_buffer(os, buffer); } /** @@ -174,25 +153,11 @@ void print(std::ostream& os, format_string fmt, T&&... args) { detail::write_buffer(os, buffer); } -FMT_EXPORT -template -void print(std::wostream& os, typename fstring::t fmt, - T&&... args) { - vprint(os, fmt, fmt::make_format_args>(args...)); -} - FMT_EXPORT template void println(std::ostream& os, format_string fmt, T&&... args) { fmt::print(os, "{}\n", fmt::format(fmt, std::forward(args)...)); } -FMT_EXPORT -template -void println(std::wostream& os, typename fstring::t fmt, - T&&... args) { - print(os, L"{}\n", fmt::format(fmt, std::forward(args)...)); -} - FMT_END_NAMESPACE #endif // FMT_OSTREAM_H_ diff --git a/include/fmt/xchar.h b/include/fmt/xchar.h index 1ffaf11b..f2b27292 100644 --- a/include/fmt/xchar.h +++ b/include/fmt/xchar.h @@ -10,6 +10,7 @@ #include "color.h" #include "format.h" +#include "ostream.h" #include "ranges.h" #ifndef FMT_MODULE @@ -310,6 +311,24 @@ FMT_DEPRECATED void print(const text_style& ts, wformat_string fmt, return print(stdout, ts, fmt, args...); } +inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) { + auto buffer = basic_memory_buffer(); + detail::vformat_to(buffer, fmt, args); + detail::write_buffer(os, buffer); +} + +template +void print(std::wostream& os, typename fstring::t fmt, + T&&... args) { + vprint(os, fmt, fmt::make_format_args>(args...)); +} + +template +void println(std::wostream& os, typename fstring::t fmt, + T&&... args) { + print(os, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + /// Converts `value` to `std::wstring` using the default format for type `T`. template inline auto to_wstring(const T& value) -> std::wstring { return format(FMT_STRING(L"{}"), value);