diff --git a/include/fmt/os.h b/include/fmt/os.h index 974c5c20..cfc9157c 100644 --- a/include/fmt/os.h +++ b/include/fmt/os.h @@ -358,16 +358,23 @@ struct ostream_params { # endif }; -class file_buffer final : public buffer { +} // namespace detail + +FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size(); + +/// A fast buffered output stream for writing from a single thread. Writing from +/// multiple threads without external synchronization may result in a data race. +class FMT_API ostream : private detail::buffer { private: file file_; - FMT_API static void grow(buffer& buf, size_t); + ostream(cstring_view path, const detail::ostream_params& params); + + static void grow(buffer& buf, size_t); public: - FMT_API file_buffer(cstring_view path, const ostream_params& params); - FMT_API file_buffer(file_buffer&& other) noexcept; - FMT_API ~file_buffer(); + ostream(ostream&& other) noexcept; + ~ostream(); void flush() { if (size() == 0) return; @@ -375,42 +382,18 @@ class file_buffer final : public buffer { clear(); } + template + friend auto output_file(cstring_view path, T... params) -> ostream; + void close() { flush(); file_.close(); } -}; - -} // namespace detail - -FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size(); - -/// A fast output stream for writing from a single thread. Writing from -/// multiple threads without external synchronization may result in a data race. -class FMT_API ostream { - private: - FMT_MSC_WARNING(suppress : 4251) - detail::file_buffer buffer_; - - ostream(cstring_view path, const detail::ostream_params& params) - : buffer_(path, params) {} - - public: - ostream(ostream&& other) : buffer_(std::move(other.buffer_)) {} - - ~ostream(); - - void flush() { buffer_.flush(); } - - template - friend auto output_file(cstring_view path, T... params) -> ostream; - - void close() { buffer_.close(); } /// Formats `args` according to specifications in `fmt` and writes the /// output to the file. template void print(format_string fmt, T&&... args) { - vformat_to(appender(buffer_), fmt, fmt::make_format_args(args...)); + vformat_to(appender(*this), fmt, fmt::make_format_args(args...)); } }; diff --git a/src/os.cc b/src/os.cc index 27366499..102000be 100644 --- a/src/os.cc +++ b/src/os.cc @@ -374,30 +374,25 @@ long getpagesize() { } # endif -namespace detail { - -void file_buffer::grow(buffer& buf, size_t) { - if (buf.size() == buf.capacity()) static_cast(buf).flush(); +void ostream::grow(buffer& buf, size_t) { + if (buf.size() == buf.capacity()) static_cast(buf).flush(); } -file_buffer::file_buffer(cstring_view path, const ostream_params& params) +ostream::ostream(cstring_view path, const detail::ostream_params& params) : buffer(grow), file_(path, params.oflag) { set(new char[params.buffer_size], params.buffer_size); } -file_buffer::file_buffer(file_buffer&& other) noexcept +ostream::ostream(ostream&& other) noexcept : buffer(grow, other.data(), other.size(), other.capacity()), file_(std::move(other.file_)) { other.clear(); other.set(nullptr, 0); } -file_buffer::~file_buffer() { +ostream::~ostream() { flush(); delete[] data(); } -} // namespace detail - -ostream::~ostream() = default; #endif // FMT_USE_FCNTL FMT_END_NAMESPACE