diff --git a/AK/BufferedStream.h b/AK/BufferedStream.h index f0342e31eea..1a51db0000e 100644 --- a/AK/BufferedStream.h +++ b/AK/BufferedStream.h @@ -322,9 +322,84 @@ private: BufferedHelper m_helper; }; +template +class OutputBufferedStream final : public Stream { +public: + static ErrorOr>> create(NonnullOwnPtr stream, size_t buffer_size = 16 * KiB) + { + if (buffer_size == 0) + return Error::from_errno(EINVAL); + if (!stream->is_open()) + return Error::from_errno(ENOTCONN); + + auto buffer = TRY(CircularBuffer::create_empty(buffer_size)); + + return adopt_nonnull_own_or_enomem(new OutputBufferedStream(move(stream), move(buffer))); + } + + OutputBufferedStream(OutputBufferedStream&& other) = default; + OutputBufferedStream& operator=(OutputBufferedStream&& other) = default; + + virtual ErrorOr read_some(Bytes buffer) override + { + TRY(flush_buffer()); + return m_stream->read_some(buffer); + } + + virtual ErrorOr write_some(ReadonlyBytes buffer) override + { + if (!m_stream->is_open()) + return Error::from_errno(ENOTCONN); + + auto const written = m_buffer.write(buffer); + + if (m_buffer.empty_space() == 0) + TRY(m_buffer.flush_to_stream(*m_stream)); + + return written; + } + + virtual bool is_eof() const override + { + MUST(flush_buffer()); + return m_stream->is_eof(); + } + + virtual bool is_open() const override { return m_stream->is_open(); } + + virtual void close() override + { + MUST(flush_buffer()); + m_stream->close(); + } + + ErrorOr flush_buffer() const + { + while (m_buffer.used_space() > 0) + TRY(m_buffer.flush_to_stream(*m_stream)); + return {}; + } + + virtual ~OutputBufferedStream() override + { + MUST(flush_buffer()); + } + +private: + OutputBufferedStream(NonnullOwnPtr stream, CircularBuffer buffer) + : m_stream(move(stream)) + , m_buffer(move(buffer)) + { + } + + mutable NonnullOwnPtr m_stream; + mutable CircularBuffer m_buffer; +}; + } #if USING_AK_GLOBALLY using AK::BufferedHelper; using AK::InputBufferedSeekable; +using AK::OutputBufferedStream; #endif diff --git a/Userland/Libraries/LibCore/File.h b/Userland/Libraries/LibCore/File.h index 7a6728b9afe..303730b1036 100644 --- a/Userland/Libraries/LibCore/File.h +++ b/Userland/Libraries/LibCore/File.h @@ -106,5 +106,6 @@ private: AK_ENUM_BITWISE_OPERATORS(File::OpenMode) using InputBufferedFile = InputBufferedSeekable; +using OutputBufferedFile = OutputBufferedStream; }