diff options
author | Tim Schumacher <timschumi@gmx.de> | 2022-11-28 18:54:14 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-11-30 08:03:31 +0100 |
commit | 6e29619dcbe6af0344f983fbf62897433baf2d36 (patch) | |
tree | c005a31d8463c2193cb333f9ed45ff77c7573442 | |
parent | 7a065513cde6a906f794d3b5828dfb575ea4d4be (diff) | |
download | serenity-6e29619dcbe6af0344f983fbf62897433baf2d36.zip |
LibCore: Add `Stream::discard()`
-rw-r--r-- | Userland/Libraries/LibCore/Stream.cpp | 30 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/Stream.h | 8 |
2 files changed, 38 insertions, 0 deletions
diff --git a/Userland/Libraries/LibCore/Stream.cpp b/Userland/Libraries/LibCore/Stream.cpp index cf19566079..b70c9f1518 100644 --- a/Userland/Libraries/LibCore/Stream.cpp +++ b/Userland/Libraries/LibCore/Stream.cpp @@ -73,6 +73,22 @@ ErrorOr<ByteBuffer> Stream::read_all_impl(size_t block_size, size_t expected_fil return data; } +ErrorOr<void> Stream::discard(size_t discarded_bytes) +{ + // Note: This was chosen arbitrarily. + // Note: This can't be PAGE_SIZE because it is defined to sysconf() on Lagom. + constexpr size_t continuous_read_size = 4096; + + Array<u8, continuous_read_size> buffer; + + while (discarded_bytes > 0) { + auto slice = TRY(read(buffer.span().slice(0, min(discarded_bytes, continuous_read_size)))); + discarded_bytes -= slice.size(); + } + + return {}; +} + bool Stream::write_or_error(ReadonlyBytes buffer) { VERIFY(buffer.size()); @@ -120,6 +136,12 @@ ErrorOr<off_t> SeekableStream::size() return seek_result.value(); } +ErrorOr<void> SeekableStream::discard(size_t discarded_bytes) +{ + TRY(seek(discarded_bytes, SeekMode::FromCurrentPosition)); + return {}; +} + ErrorOr<NonnullOwnPtr<File>> File::open(StringView filename, OpenMode mode, mode_t permissions) { auto file = TRY(adopt_nonnull_own_or_enomem(new (nothrow) File(mode))); @@ -729,6 +751,14 @@ ErrorOr<Bytes> WrappedAKInputStream::read(Bytes bytes) return bytes.slice(0, bytes_read); } +ErrorOr<void> WrappedAKInputStream::discard(size_t discarded_bytes) +{ + if (!m_stream->discard_or_error(discarded_bytes)) + return Error::from_string_literal("Underlying InputStream indicated an error"); + + return {}; +} + ErrorOr<size_t> WrappedAKInputStream::write(ReadonlyBytes) { VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibCore/Stream.h b/Userland/Libraries/LibCore/Stream.h index 3fc95f1cc4..2a28bcae75 100644 --- a/Userland/Libraries/LibCore/Stream.h +++ b/Userland/Libraries/LibCore/Stream.h @@ -41,6 +41,10 @@ public: /// is returned once EOF is encountered. The block size determines the size /// of newly allocated chunks while reading. virtual ErrorOr<ByteBuffer> read_all(size_t block_size = 4096); + /// Discards the given number of bytes from the stream. + /// Unless specifically overwritten, this just uses read() to read into an + /// internal stack-based buffer. + virtual ErrorOr<void> discard(size_t discarded_bytes); virtual bool is_writable() const { return false; } /// Tries to write the entire contents of the buffer. It is possible for @@ -97,6 +101,9 @@ public: /// Shrinks or extends the stream to the given size. Returns an errno in /// the case of an error. virtual ErrorOr<void> truncate(off_t length) = 0; + /// Seeks until after the given amount of bytes to be discarded instead of + /// reading and discarding everything manually; + virtual ErrorOr<void> discard(size_t discarded_bytes) override; }; /// The Socket class is the base class for all concrete BSD-style socket @@ -973,6 +980,7 @@ class WrappedAKInputStream final : public Stream { public: WrappedAKInputStream(NonnullOwnPtr<InputStream> stream); virtual ErrorOr<Bytes> read(Bytes) override; + virtual ErrorOr<void> discard(size_t discarded_bytes) override; virtual ErrorOr<size_t> write(ReadonlyBytes) override; virtual bool is_eof() const override; virtual bool is_open() const override; |