diff --git a/include/fmt/os.h b/include/fmt/os.h index c86c2153..e79de6e8 100644 --- a/include/fmt/os.h +++ b/include/fmt/os.h @@ -343,8 +343,8 @@ class file { // Returns the memory page size. long getpagesize(); -// A buffered file with a direct buffer access and no synchronization. -class direct_buffered_file : private detail::buffer { +// A fast output stream without synchronization. +class ostream : private detail::buffer { private: file file_; char buffer_[BUFSIZ]; @@ -357,11 +357,18 @@ class direct_buffered_file : private detail::buffer { void grow(size_t) final; - public: - direct_buffered_file(cstring_view path, int oflag) + ostream(cstring_view path, int oflag) : buffer(buffer_, 0, BUFSIZ), file_(path, oflag) {} - ~direct_buffered_file() { flush(); } + public: + ostream(ostream&& other) + : buffer(buffer_, 0, BUFSIZ), file_(std::move(other.file_)) { + append(other.begin(), other.end()); + other.clear(); + } + ~ostream() { flush(); } + + friend ostream output_file(cstring_view path, int oflag); void close() { flush(); @@ -369,13 +376,14 @@ class direct_buffered_file : private detail::buffer { } template - friend void print(direct_buffered_file& f, const S& format_str, - const Args&... args); + void print(const S& format_str, const Args&... args) { + format_to(detail::buffer_appender(*this), format_str, args...); + } }; -template -void print(direct_buffered_file& f, const S& format_str, const Args&... args) { - format_to(detail::buffer_appender(f), format_str, args...); +inline ostream output_file(cstring_view path, + int oflag = file::WRONLY | file::CREATE) { + return {path, oflag}; } #endif // FMT_USE_FCNTL diff --git a/src/os.cc b/src/os.cc index 74685549..5931702c 100644 --- a/src/os.cc +++ b/src/os.cc @@ -314,7 +314,7 @@ long getpagesize() { # endif } -void direct_buffered_file::grow(size_t) { +void ostream::grow(size_t) { if (this->size() == BUFSIZ) flush(); } #endif // FMT_USE_FCNTL diff --git a/test/os-test.cc b/test/os-test.cc index b1917f7e..4cf76f2a 100644 --- a/test/os-test.cc +++ b/test/os-test.cc @@ -287,21 +287,19 @@ TEST(BufferedFileTest, Fileno) { EXPECT_READ(copy, FILE_CONTENT); } -TEST(DirectBufferedFileTest, Print) { - fmt::direct_buffered_file out("test-file", - fmt::file::WRONLY | fmt::file::CREATE); - fmt::print(out, "The answer is {}.\n", 42); +TEST(OStreamTest, Print) { + fmt::ostream out = fmt::output_file("test-file"); + out.print("The answer is {}.\n", 42); out.close(); file in("test-file", file::RDONLY); EXPECT_READ(in, "The answer is 42.\n"); } -TEST(DirectBufferedFileTest, BufferBoundary) { +TEST(OStreamTest, BufferBoundary) { auto str = std::string(4096, 'x'); - fmt::direct_buffered_file out("test-file", - fmt::file::WRONLY | fmt::file::CREATE); - fmt::print(out, "{}", str); - fmt::print(out, "{}", str); + fmt::ostream out = fmt::output_file("test-file"); + out.print("{}", str); + out.print("{}", str); out.close(); file in("test-file", file::RDONLY); EXPECT_READ(in, str + str);