1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:17:35 +00:00

AK: Add Disjoint(Chunks Spans)::find(index)

For when the may or may not be out of bounds.
This commit is contained in:
Ali Mohammad Pur 2021-12-21 18:05:21 +03:30 committed by Andreas Kling
parent c417374dd6
commit 2df54a7b56

View file

@ -99,10 +99,21 @@ public:
T const& operator[](size_t index) const { return at(index); } T const& operator[](size_t index) const { return at(index); }
T const& at(size_t index) const { return const_cast<DisjointSpans&>(*this).at(index); } T const& at(size_t index) const { return const_cast<DisjointSpans&>(*this).at(index); }
T& at(size_t index) T& at(size_t index)
{
auto value = find(index);
VERIFY(value != nullptr);
return *value;
}
T* find(size_t index)
{ {
auto span_and_offset = span_around(index); auto span_and_offset = span_around(index);
VERIFY(span_and_offset.offset < span_and_offset.span.size()); if (span_and_offset.offset >= span_and_offset.span.size())
return span_and_offset.span.at(span_and_offset.offset); return nullptr;
return &span_and_offset.span.at(span_and_offset.offset);
}
T const* find(size_t index) const
{
return const_cast<DisjointSpans*>(this)->find(index);
} }
size_t size() const size_t size() const
@ -194,7 +205,12 @@ public:
if (m_chunks.size() == 1) if (m_chunks.size() == 1)
return m_chunks.first().insert(index, value); return m_chunks.first().insert(index, value);
auto chunk_and_offset = chunk_around(index); auto chunk_and_offset = chunk_around(index);
chunk_and_offset.chunk.insert(chunk_and_offset.offset, move(value)); if (!chunk_and_offset.chunk) {
m_chunks.empend();
chunk_and_offset.chunk = &m_chunks.last();
}
chunk_and_offset.chunk->insert(chunk_and_offset.offset, move(value));
} }
void clear() { m_chunks.clear(); } void clear() { m_chunks.clear(); }
@ -204,11 +220,27 @@ public:
T const& at(size_t index) const { return const_cast<DisjointChunks&>(*this).at(index); } T const& at(size_t index) const { return const_cast<DisjointChunks&>(*this).at(index); }
T& at(size_t index) T& at(size_t index)
{ {
if (m_chunks.size() == 1) auto value = find(index);
return m_chunks.first().at(index); VERIFY(value != nullptr);
return *value;
}
T* find(size_t index)
{
if (m_chunks.size() == 1) {
if (m_chunks.first().size() > index)
return &m_chunks.first().at(index);
return nullptr;
}
auto chunk_and_offset = chunk_around(index); auto chunk_and_offset = chunk_around(index);
VERIFY(chunk_and_offset.offset < chunk_and_offset.chunk.size()); if (!chunk_and_offset.chunk || chunk_and_offset.offset >= chunk_and_offset.chunk->size())
return chunk_and_offset.chunk.at(chunk_and_offset.offset); return nullptr;
return &chunk_and_offset.chunk->at(chunk_and_offset.offset);
}
T const* find(size_t index) const
{
return const_cast<DisjointChunks*>(this)->find(index);
} }
size_t size() const size_t size() const
@ -319,11 +351,14 @@ public:
private: private:
struct ChunkAndOffset { struct ChunkAndOffset {
ChunkType& chunk; ChunkType* chunk;
size_t offset; size_t offset;
}; };
ChunkAndOffset chunk_around(size_t index) ChunkAndOffset chunk_around(size_t index)
{ {
if (m_chunks.is_empty())
return { nullptr, index };
size_t offset = 0; size_t offset = 0;
for (auto& chunk : m_chunks) { for (auto& chunk : m_chunks) {
if (chunk.is_empty()) if (chunk.is_empty())
@ -334,10 +369,10 @@ private:
continue; continue;
} }
return { chunk, index - offset }; return { &chunk, index - offset };
} }
return { m_chunks.last(), index - (offset - m_chunks.last().size()) }; return { &m_chunks.last(), index - (offset - m_chunks.last().size()) };
} }
Vector<ChunkType> m_chunks; Vector<ChunkType> m_chunks;