From effd732123fd47ae8547d6d4834bf77227131061 Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Thu, 20 May 2021 23:17:18 +0300 Subject: [PATCH] add `fmt::print()` overload to support compiled format --- include/fmt/compile.h | 14 ++++++++++++++ include/fmt/format-inl.h | 12 +++++++++--- include/fmt/format.h | 4 ++++ test/compile-test.cc | 8 ++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 718815357ea3..7b0ef8951b15 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -606,6 +606,20 @@ size_t formatted_size(const S& format_str, const Args&... args) { return format_to(detail::counting_iterator(), format_str, args...).count(); } +template ::value)> +void print(std::FILE* f, const S& format_str, const Args&... args) { + memory_buffer buffer; + format_to(std::back_inserter(buffer), format_str, args...); + detail::print_buffer(f, buffer); +} + +template ::value)> +void print(const S& format_str, const Args&... args) { + print(stdout, format_str, args...); +} + #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS inline namespace literals { template diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 93b7a90727eb..d26257aaeea3 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -2594,9 +2594,8 @@ extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // } // namespace detail #endif -FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { - memory_buffer buffer; - detail::vformat_to(buffer, format_str, args); +namespace detail { +FMT_FUNC void print_buffer(std::FILE* f, const memory_buffer& buffer) { #ifdef _WIN32 auto fd = _fileno(f); if (_isatty(fd)) { @@ -2613,6 +2612,13 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { #endif detail::fwrite_fully(buffer.data(), 1, buffer.size(), f); } +} // namespace detail + +FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, args); + detail::print_buffer(f, buffer); +} #ifdef _WIN32 // Print assuming legacy (non-Unicode) encoding. diff --git a/include/fmt/format.h b/include/fmt/format.h index 0478ba0c9186..0616a598b4d4 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -783,6 +783,10 @@ template struct is_contiguous> : std::true_type { }; +namespace detail { +FMT_API void print_buffer(std::FILE*, const memory_buffer&); +} + /** A formatting error such as invalid format string. */ FMT_CLASS_API class FMT_API format_error : public std::runtime_error { diff --git a/test/compile-test.cc b/test/compile-test.cc index 71eddc920e4f..58fd057d7b51 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -11,6 +11,7 @@ #include "fmt/chrono.h" #include "gmock/gmock.h" +#include "gtest-extra.h" TEST(iterator_test, counting_iterator) { auto it = fmt::detail::counting_iterator(); @@ -241,6 +242,13 @@ FMT_END_NAMESPACE TEST(compile_test, to_string_and_formatter) { fmt::format(FMT_COMPILE("{}"), to_stringable()); } + +TEST(compile_test, print) { + EXPECT_WRITE(stdout, fmt::print(FMT_COMPILE("Don't {}!"), "panic"), + "Don't panic!"); + EXPECT_WRITE(stderr, fmt::print(stderr, FMT_COMPILE("Don't {}!"), "panic"), + "Don't panic!"); +} #endif #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS