1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:57:44 +00:00

LibRegex: Use a copy-on-write vector for fork state

This commit is contained in:
Ali Mohammad Pur 2022-11-03 02:36:25 +03:30 committed by Ali Mohammad Pur
parent 48a4c9c1ad
commit f1851346d3
3 changed files with 140 additions and 8 deletions

View file

@ -12,6 +12,7 @@
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <AK/MemMem.h>
#include <AK/RedBlackTree.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/StringView.h>
@ -23,6 +24,135 @@
namespace regex {
template<typename T>
class COWVector {
struct Detail : RefCounted<Detail> {
Vector<T> m_members;
};
public:
COWVector()
: m_detail(make_ref_counted<Detail>())
{
}
COWVector(COWVector const&) = default;
COWVector(COWVector&&) = default;
COWVector& operator=(COWVector const&) = default;
COWVector& operator=(COWVector&&) = default;
Vector<T> release() &&
{
if (m_detail->ref_count() == 1)
return exchange(m_detail->m_members, Vector<T>());
return m_detail->m_members;
}
void append(T const& value)
{
return append(T { value });
}
void append(T&& value)
{
copy();
m_detail->m_members.append(move(value));
}
void resize(size_t size)
{
copy();
m_detail->m_members.resize(size);
}
void ensure_capacity(size_t capacity)
{
if (m_detail->m_members.capacity() >= capacity)
return;
copy();
m_detail->m_members.ensure_capacity(capacity);
}
template<typename... Args>
void empend(Args&&... args)
{
copy();
m_detail->m_members.empend(forward<Args>(args)...);
}
void clear()
{
if (m_detail->ref_count() > 1)
m_detail = make_ref_counted<Detail>();
else
m_detail->m_members.clear();
}
T& at(size_t index)
{
// We're handing out a mutable reference, so make sure we own the data exclusively.
copy();
return m_detail->m_members.at(index);
}
T const& at(size_t index) const
{
return m_detail->m_members.at(index);
}
T& operator[](size_t index)
{
// We're handing out a mutable reference, so make sure we own the data exclusively.
copy();
return m_detail->m_members[index];
}
T const& operator[](size_t index) const
{
return m_detail->m_members[index];
}
size_t capacity() const
{
return m_detail->m_members.capacity();
}
size_t size() const
{
return m_detail->m_members.size();
}
bool is_empty() const
{
return m_detail->m_members.is_empty();
}
T const& first() const
{
return m_detail->m_members.first();
}
T const& last() const
{
return m_detail->m_members.last();
}
private:
void copy()
{
if (m_detail->ref_count() <= 1)
return;
auto new_detail = make_ref_counted<Detail>();
new_detail->m_members = m_detail->m_members;
m_detail = new_detail;
}
NonnullRefPtr<Detail> m_detail;
};
class RegexStringView {
public:
RegexStringView() = default;
@ -510,9 +640,9 @@ struct MatchState {
size_t fork_at_position { 0 };
size_t forks_since_last_save { 0 };
Optional<size_t> initiating_fork;
Vector<Match> matches;
Vector<Vector<Match>> capture_group_matches;
Vector<u64> repetition_marks;
COWVector<Match> matches;
COWVector<Vector<Match>> capture_group_matches;
COWVector<u64> repetition_marks;
};
}