summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Schumacher <timschumi@gmx.de>2022-11-28 18:54:14 +0100
committerAndreas Kling <kling@serenityos.org>2022-11-30 08:03:31 +0100
commit6e29619dcbe6af0344f983fbf62897433baf2d36 (patch)
treec005a31d8463c2193cb333f9ed45ff77c7573442
parent7a065513cde6a906f794d3b5828dfb575ea4d4be (diff)
downloadserenity-6e29619dcbe6af0344f983fbf62897433baf2d36.zip
LibCore: Add `Stream::discard()`
-rw-r--r--Userland/Libraries/LibCore/Stream.cpp30
-rw-r--r--Userland/Libraries/LibCore/Stream.h8
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;