mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-17 16:28:06 +03:00
AK: Add search-related helpers to CircularBuffer
This factors out a lot of complicated math into somewhat understandable functions. While at it, rename `next_read_span_with_seekback` to `next_seekback_span` to keep the naming consistent and to avoid making function names any longer.
This commit is contained in:
parent
d12036132e
commit
2109f61b0d
Notes:
sideshowbarker
2024-07-17 02:55:44 +09:00
Author: https://github.com/timschumi Commit: https://github.com/SerenityOS/serenity/commit/2109f61b0d Pull-request: https://github.com/SerenityOS/serenity/pull/19332 Reviewed-by: https://github.com/linusg ✅
@ -53,6 +53,11 @@ size_t CircularBuffer::seekback_limit() const
|
|||||||
return m_seekback_limit;
|
return m_seekback_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t SearchableCircularBuffer::search_limit() const
|
||||||
|
{
|
||||||
|
return m_seekback_limit - m_used_space;
|
||||||
|
}
|
||||||
|
|
||||||
bool CircularBuffer::is_wrapping_around() const
|
bool CircularBuffer::is_wrapping_around() const
|
||||||
{
|
{
|
||||||
return capacity() <= m_reading_head + m_used_space;
|
return capacity() <= m_reading_head + m_used_space;
|
||||||
@ -113,7 +118,7 @@ ReadonlyBytes CircularBuffer::next_read_span(size_t offset) const
|
|||||||
return m_buffer.span().slice(reading_head, min(capacity() - reading_head, used_space));
|
return m_buffer.span().slice(reading_head, min(capacity() - reading_head, used_space));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadonlyBytes CircularBuffer::next_read_span_with_seekback(size_t distance) const
|
ReadonlyBytes CircularBuffer::next_seekback_span(size_t distance) const
|
||||||
{
|
{
|
||||||
VERIFY(m_seekback_limit <= capacity());
|
VERIFY(m_seekback_limit <= capacity());
|
||||||
VERIFY(distance <= m_seekback_limit);
|
VERIFY(distance <= m_seekback_limit);
|
||||||
@ -124,6 +129,17 @@ ReadonlyBytes CircularBuffer::next_read_span_with_seekback(size_t distance) cons
|
|||||||
return m_buffer.span().slice(read_offset, min(capacity() - read_offset, distance));
|
return m_buffer.span().slice(read_offset, min(capacity() - read_offset, distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReadonlyBytes SearchableCircularBuffer::next_search_span(size_t distance) const
|
||||||
|
{
|
||||||
|
VERIFY(search_limit() <= capacity());
|
||||||
|
VERIFY(distance <= search_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 - distance) % capacity();
|
||||||
|
|
||||||
|
return m_buffer.span().slice(read_offset, min(capacity() - read_offset, distance));
|
||||||
|
}
|
||||||
|
|
||||||
size_t CircularBuffer::write(ReadonlyBytes bytes)
|
size_t CircularBuffer::write(ReadonlyBytes bytes)
|
||||||
{
|
{
|
||||||
auto remaining = bytes.size();
|
auto remaining = bytes.size();
|
||||||
@ -178,7 +194,7 @@ ErrorOr<Bytes> CircularBuffer::read_with_seekback(Bytes bytes, size_t distance)
|
|||||||
auto remaining = bytes.size();
|
auto remaining = bytes.size();
|
||||||
|
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
auto const next_span = next_read_span_with_seekback(distance);
|
auto const next_span = next_seekback_span(distance);
|
||||||
if (next_span.size() == 0)
|
if (next_span.size() == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -244,7 +260,7 @@ ErrorOr<size_t> CircularBuffer::copy_from_seekback(size_t distance, size_t lengt
|
|||||||
if (empty_space() == 0)
|
if (empty_space() == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto next_span = next_read_span_with_seekback(distance);
|
auto next_span = next_seekback_span(distance);
|
||||||
if (next_span.size() == 0)
|
if (next_span.size() == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -297,15 +313,11 @@ ErrorOr<Vector<SearchableCircularBuffer::Match>> SearchableCircularBuffer::find_
|
|||||||
Vector<Match> matches;
|
Vector<Match> matches;
|
||||||
|
|
||||||
// Use memmem to find the initial matches.
|
// Use memmem to find the initial matches.
|
||||||
// Note: We have the read head as our reference point, but `next_read_span_with_seekback` isn't aware of that and continues to use the write head.
|
|
||||||
// Therefore, we need to make sure to slice off the extraneous bytes from the end of the span and shift the returned distances by the correct amount.
|
|
||||||
size_t haystack_offset_from_start = 0;
|
size_t haystack_offset_from_start = 0;
|
||||||
Vector<ReadonlyBytes, 2> haystack;
|
Vector<ReadonlyBytes, 2> haystack;
|
||||||
haystack.append(next_read_span_with_seekback(m_seekback_limit));
|
haystack.append(next_search_span(search_limit()));
|
||||||
if (haystack[0].size() < m_seekback_limit - used_space())
|
if (haystack[0].size() < search_limit())
|
||||||
haystack.append(next_read_span_with_seekback(m_seekback_limit - haystack[0].size()));
|
haystack.append(next_search_span(search_limit() - haystack[0].size()));
|
||||||
|
|
||||||
haystack.last() = haystack.last().trim(haystack.last().size() - used_space());
|
|
||||||
|
|
||||||
auto needle = next_read_span().trim(minimum_length);
|
auto needle = next_read_span().trim(minimum_length);
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ protected:
|
|||||||
|
|
||||||
[[nodiscard]] Bytes next_write_span();
|
[[nodiscard]] Bytes next_write_span();
|
||||||
[[nodiscard]] ReadonlyBytes next_read_span(size_t offset = 0) const;
|
[[nodiscard]] ReadonlyBytes next_read_span(size_t offset = 0) const;
|
||||||
[[nodiscard]] ReadonlyBytes next_read_span_with_seekback(size_t distance) const;
|
[[nodiscard]] ReadonlyBytes next_seekback_span(size_t distance) const;
|
||||||
|
|
||||||
ByteBuffer m_buffer {};
|
ByteBuffer m_buffer {};
|
||||||
|
|
||||||
@ -65,6 +65,8 @@ public:
|
|||||||
static ErrorOr<SearchableCircularBuffer> create_empty(size_t size);
|
static ErrorOr<SearchableCircularBuffer> create_empty(size_t size);
|
||||||
static ErrorOr<SearchableCircularBuffer> create_initialized(ByteBuffer);
|
static ErrorOr<SearchableCircularBuffer> create_initialized(ByteBuffer);
|
||||||
|
|
||||||
|
[[nodiscard]] size_t search_limit() const;
|
||||||
|
|
||||||
struct Match {
|
struct Match {
|
||||||
size_t distance;
|
size_t distance;
|
||||||
size_t length;
|
size_t length;
|
||||||
@ -76,6 +78,10 @@ public:
|
|||||||
ErrorOr<Vector<Match>> find_copy_in_seekback(Vector<size_t> const& distances, size_t maximum_length, size_t minimum_length = 2) const;
|
ErrorOr<Vector<Match>> find_copy_in_seekback(Vector<size_t> const& distances, size_t maximum_length, size_t minimum_length = 2) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Note: This function has a similar purpose as next_seekback_span, but they differ in their reference point.
|
||||||
|
// Seekback operations start counting their distance at the write head, while search operations start counting their distance at the read head.
|
||||||
|
[[nodiscard]] ReadonlyBytes next_search_span(size_t distance) const;
|
||||||
|
|
||||||
SearchableCircularBuffer(ByteBuffer);
|
SearchableCircularBuffer(ByteBuffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user