mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 05:25:32 +03:00
AK: Add CircularBuffer::read_with_seekback
This commit is contained in:
parent
afc0e461e1
commit
d717a08003
Notes:
sideshowbarker
2024-07-17 05:19:06 +09:00
Author: https://github.com/timschumi Commit: https://github.com/SerenityOS/serenity/commit/d717a08003 Pull-request: https://github.com/SerenityOS/serenity/pull/16917 Reviewed-by: https://github.com/ADKaster ✅
@ -71,6 +71,7 @@ void CircularBuffer::clear()
|
||||
{
|
||||
m_reading_head = 0;
|
||||
m_used_space = 0;
|
||||
m_seekback_limit = 0;
|
||||
}
|
||||
|
||||
Bytes CircularBuffer::next_write_span()
|
||||
@ -85,6 +86,17 @@ ReadonlyBytes CircularBuffer::next_read_span() const
|
||||
return m_buffer.span().slice(m_reading_head, min(capacity() - m_reading_head, m_used_space));
|
||||
}
|
||||
|
||||
ReadonlyBytes CircularBuffer::next_read_span_with_seekback(size_t distance) const
|
||||
{
|
||||
VERIFY(m_seekback_limit <= capacity());
|
||||
VERIFY(distance <= m_seekback_limit);
|
||||
|
||||
// Note: We are adding the capacity once here to ensure that we can wrap around the negative space by using modulo.
|
||||
auto read_offset = (capacity() + m_reading_head + m_used_space - distance) % capacity();
|
||||
|
||||
return m_buffer.span().slice(read_offset, min(capacity() - read_offset, m_seekback_limit));
|
||||
}
|
||||
|
||||
size_t CircularBuffer::write(ReadonlyBytes bytes)
|
||||
{
|
||||
auto remaining = bytes.size();
|
||||
@ -98,6 +110,10 @@ size_t CircularBuffer::write(ReadonlyBytes bytes)
|
||||
|
||||
m_used_space += written_bytes;
|
||||
|
||||
m_seekback_limit += written_bytes;
|
||||
if (m_seekback_limit > capacity())
|
||||
m_seekback_limit = capacity();
|
||||
|
||||
remaining -= written_bytes;
|
||||
}
|
||||
|
||||
@ -127,6 +143,27 @@ Bytes CircularBuffer::read(Bytes bytes)
|
||||
return bytes.trim(bytes.size() - remaining);
|
||||
}
|
||||
|
||||
ErrorOr<Bytes> CircularBuffer::read_with_seekback(Bytes bytes, size_t distance)
|
||||
{
|
||||
if (distance > m_seekback_limit)
|
||||
return Error::from_string_literal("Tried a seekback read beyond the seekback limit");
|
||||
|
||||
auto remaining = bytes.size();
|
||||
|
||||
while (remaining > 0) {
|
||||
auto const next_span = next_read_span_with_seekback(distance);
|
||||
if (next_span.size() == 0)
|
||||
break;
|
||||
|
||||
auto written_bytes = next_span.copy_trimmed_to(bytes.slice(bytes.size() - remaining));
|
||||
|
||||
distance -= written_bytes;
|
||||
remaining -= written_bytes;
|
||||
}
|
||||
|
||||
return bytes.trim(bytes.size() - remaining);
|
||||
}
|
||||
|
||||
ErrorOr<void> CircularBuffer::discard(size_t discarding_size)
|
||||
{
|
||||
if (m_used_space < discarding_size)
|
||||
|
@ -42,6 +42,10 @@ public:
|
||||
Bytes read(Bytes bytes);
|
||||
ErrorOr<void> discard(size_t discarded_bytes);
|
||||
|
||||
/// Compared to `read()`, this starts reading from an offset that is `distance` bytes
|
||||
/// before the current write pointer and allows for reading already-read data.
|
||||
ErrorOr<Bytes> read_with_seekback(Bytes bytes, size_t distance);
|
||||
|
||||
[[nodiscard]] size_t empty_space() const;
|
||||
[[nodiscard]] size_t used_space() const;
|
||||
[[nodiscard]] size_t capacity() const;
|
||||
@ -57,11 +61,13 @@ private:
|
||||
|
||||
[[nodiscard]] Bytes next_write_span();
|
||||
[[nodiscard]] ReadonlyBytes next_read_span() const;
|
||||
[[nodiscard]] ReadonlyBytes next_read_span_with_seekback(size_t distance) const;
|
||||
|
||||
ByteBuffer m_buffer {};
|
||||
|
||||
size_t m_reading_head {};
|
||||
size_t m_used_space {};
|
||||
size_t m_seekback_limit {};
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user