mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:48:11 +00:00
AK: Implement DuplexMemoryStream::offset_of() in terms of memmem()
This fixes the FIXME about missing matches that go across chunk boundaries.
This commit is contained in:
parent
036b39cdfd
commit
602d2ff856
1 changed files with 17 additions and 43 deletions
|
@ -222,55 +222,29 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Does not read across chunk boundaries
|
|
||||||
// Perhaps implement AK::memmem() for iterators?
|
|
||||||
Optional<size_t> offset_of(ReadonlyBytes value) const
|
Optional<size_t> offset_of(ReadonlyBytes value) const
|
||||||
{
|
{
|
||||||
if (value.size() > size())
|
// We can't directly pass m_chunks to memmem since we have a limited read/write range we want to search in.
|
||||||
return {};
|
Vector<ReadonlyBytes> spans;
|
||||||
|
auto chunk_index = (m_read_offset - m_base_offset) / chunk_size;
|
||||||
// First, find which chunk we're in.
|
auto chunk_read_offset = (m_read_offset - m_base_offset) % chunk_size;
|
||||||
auto chunk_index = min((m_read_offset - m_base_offset) / chunk_size, m_chunks.size() - 1);
|
auto bytes_to_search = m_write_offset - m_read_offset;
|
||||||
auto last_written_chunk_index = (m_write_offset - m_base_offset) / chunk_size;
|
for (; bytes_to_search > 0;) {
|
||||||
auto first_chunk_index = chunk_index;
|
ReadonlyBytes span = m_chunks[chunk_index];
|
||||||
auto last_written_chunk_offset = m_write_offset % chunk_size;
|
if (chunk_read_offset) {
|
||||||
auto first_chunk_offset = m_read_offset % chunk_size;
|
span = span.slice(chunk_read_offset);
|
||||||
size_t last_chunk_offset = 0;
|
chunk_read_offset = 0;
|
||||||
auto found_value = false;
|
|
||||||
auto chunk_index_max_bound = last_written_chunk_offset > 0 ? last_written_chunk_index + 1 : last_written_chunk_index;
|
|
||||||
|
|
||||||
for (; chunk_index < chunk_index_max_bound; ++chunk_index) {
|
|
||||||
auto& chunk = m_chunks[chunk_index];
|
|
||||||
auto chunk_bytes = chunk.bytes();
|
|
||||||
size_t chunk_offset = 0;
|
|
||||||
if (chunk_index == last_written_chunk_index) {
|
|
||||||
chunk_bytes = chunk_bytes.slice(0, last_written_chunk_offset);
|
|
||||||
}
|
}
|
||||||
if (chunk_index == first_chunk_index) {
|
if (bytes_to_search < span.size()) {
|
||||||
chunk_bytes = chunk_bytes.slice(first_chunk_offset);
|
spans.append(span.slice(0, bytes_to_search));
|
||||||
chunk_offset = first_chunk_offset;
|
break;
|
||||||
}
|
}
|
||||||
|
bytes_to_search -= span.size();
|
||||||
// See if 'value' is in this chunk,
|
spans.append(move(span));
|
||||||
auto position = AK::memmem(chunk_bytes.data(), chunk_bytes.size(), value.data(), value.size());
|
++chunk_index;
|
||||||
if (!position)
|
|
||||||
continue; // Not in this chunk either :(
|
|
||||||
|
|
||||||
// We found it!
|
|
||||||
found_value = true;
|
|
||||||
last_chunk_offset = (const u8*)position - chunk_bytes.data() + chunk_offset;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found_value) {
|
return memmem(spans.begin(), spans.end(), value);
|
||||||
if (first_chunk_index == chunk_index)
|
|
||||||
return last_chunk_offset - first_chunk_offset;
|
|
||||||
|
|
||||||
return (chunk_index - first_chunk_index) * chunk_size + last_chunk_offset - first_chunk_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No dice.
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t read_without_consuming(Bytes bytes) const
|
size_t read_without_consuming(Bytes bytes) const
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue