From 9cc996b1e59fd0219e039c753e436bc12617a348 Mon Sep 17 00:00:00 2001 From: AnotherTest Date: Fri, 21 Aug 2020 03:47:47 +0430 Subject: [PATCH] AK: Add Stream::offset_of(ReadonlyBytes) --- AK/Stream.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/AK/Stream.h b/AK/Stream.h index 75830ca0f7..bb52de4236 100644 --- a/AK/Stream.h +++ b/AK/Stream.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -299,6 +300,53 @@ public: return true; } + Optional offset_of(ReadonlyBytes value) const + { + if (value.size() > remaining()) + return {}; + + // First, find which chunk we're in. + auto chunk_index = (m_read_offset - m_base_offset) / chunk_size; + auto last_written_chunk_index = (m_write_offset - m_base_offset) / chunk_size; + auto first_chunk_index = chunk_index; + auto last_written_chunk_offset = m_write_offset % chunk_size; + auto first_chunk_offset = m_read_offset % chunk_size; + size_t last_chunk_offset = 0; + auto found_value = false; + + for (; chunk_index <= last_written_chunk_index; ++chunk_index) { + auto chunk_bytes = m_chunks[chunk_index].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) { + chunk_bytes = chunk_bytes.slice(first_chunk_offset); + chunk_offset = first_chunk_offset; + } + + // See if 'value' is in this chunk, + auto position = AK::memmem(chunk_bytes.data(), chunk_bytes.size(), value.data(), value.size()); + 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) { + 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(Bytes bytes) override { size_t nread = 0;