diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 8d07cc67..c1653bb4 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -1449,6 +1449,13 @@ inline void funlockfile(FILE* f) { _unlock_file(f); } inline int getc_unlocked(FILE* f) { return _fgetc_nolock(f); } #endif +template +struct has_flockfile : std::false_type {}; + +template +struct has_flockfile(nullptr)))>> + : std::true_type {}; + // A FILE wrapper. F is FILE defined as a template parameter to make system API // detection work. template class file_base { @@ -1619,7 +1626,15 @@ inline auto get_file(FILE* f, ...) -> fallback_file { return f; } using file_ref = decltype(get_file(static_cast(nullptr), 0)); +template class file_print_buffer : public buffer { + public: + explicit file_print_buffer(F*) : buffer(nullptr, size_t()) {} +}; + +template +class file_print_buffer::value>> + : public buffer { private: file_ref file_; @@ -1634,7 +1649,7 @@ class file_print_buffer : public buffer { } public: - explicit file_print_buffer(FILE* f) : buffer(grow, size_t()), file_(f) { + explicit file_print_buffer(F* f) : buffer(grow, size_t()), file_(f) { flockfile(f); file_.init_buffer(); auto buf = file_.get_write_buffer(); @@ -1692,8 +1707,9 @@ FMT_FUNC void vprint_buffered(std::FILE* f, string_view fmt, format_args args) { } FMT_FUNC void vprint(std::FILE* f, string_view fmt, format_args args) { - if (!detail::file_ref(f).is_buffered()) return vprint_buffered(f, fmt, args); - auto&& buffer = detail::file_print_buffer(f); + if (!detail::file_ref(f).is_buffered() || !detail::has_flockfile<>()) + return vprint_buffered(f, fmt, args); + auto&& buffer = detail::file_print_buffer<>(f); return detail::vformat_to(buffer, fmt, args); }