Improve support for non-POSIX platforms

This commit is contained in:
Victor Zverovich
2024-07-08 11:18:44 -07:00
parent a43391199f
commit 486838f26f

View File

@ -1449,6 +1449,13 @@ inline void funlockfile(FILE* f) { _unlock_file(f); }
inline int getc_unlocked(FILE* f) { return _fgetc_nolock(f); } inline int getc_unlocked(FILE* f) { return _fgetc_nolock(f); }
#endif #endif
template <typename F = FILE, typename Enable = void>
struct has_flockfile : std::false_type {};
template <typename F>
struct has_flockfile<F, void_t<decltype(flockfile(static_cast<F*>(nullptr)))>>
: std::true_type {};
// A FILE wrapper. F is FILE defined as a template parameter to make system API // A FILE wrapper. F is FILE defined as a template parameter to make system API
// detection work. // detection work.
template <typename F> class file_base { template <typename F> class file_base {
@ -1619,7 +1626,15 @@ inline auto get_file(FILE* f, ...) -> fallback_file<FILE> { return f; }
using file_ref = decltype(get_file(static_cast<FILE*>(nullptr), 0)); using file_ref = decltype(get_file(static_cast<FILE*>(nullptr), 0));
template <typename F = FILE, typename Enable = void>
class file_print_buffer : public buffer<char> { class file_print_buffer : public buffer<char> {
public:
explicit file_print_buffer(F*) : buffer(nullptr, size_t()) {}
};
template <typename F>
class file_print_buffer<F, enable_if_t<has_flockfile<F>::value>>
: public buffer<char> {
private: private:
file_ref file_; file_ref file_;
@ -1634,7 +1649,7 @@ class file_print_buffer : public buffer<char> {
} }
public: 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); flockfile(f);
file_.init_buffer(); file_.init_buffer();
auto buf = file_.get_write_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) { 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); if (!detail::file_ref(f).is_buffered() || !detail::has_flockfile<>())
auto&& buffer = detail::file_print_buffer(f); return vprint_buffered(f, fmt, args);
auto&& buffer = detail::file_print_buffer<>(f);
return detail::vformat_to(buffer, fmt, args); return detail::vformat_to(buffer, fmt, args);
} }