mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:48:14 +00:00
AK+LibRegex: Move COWVector to AK
This is about to gain a new user, so move it to AK.
This commit is contained in:
parent
bbb96d65b1
commit
cefe177a56
2 changed files with 180 additions and 129 deletions
179
AK/COWVector.h
Normal file
179
AK/COWVector.h
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2024, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/NonnullRefPtr.h>
|
||||||
|
#include <AK/RefCounted.h>
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
|
||||||
|
namespace AK {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class COWVector {
|
||||||
|
struct Detail : RefCounted<Detail> {
|
||||||
|
Vector<T> m_members;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
COWVector()
|
||||||
|
: m_detail(make_ref_counted<Detail>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
COWVector(std::initializer_list<T> entries)
|
||||||
|
: m_detail(make_ref_counted<Detail>())
|
||||||
|
{
|
||||||
|
for (auto& entry : entries)
|
||||||
|
m_detail->m_members.append(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 extend(Vector<T>&& values)
|
||||||
|
{
|
||||||
|
copy();
|
||||||
|
m_detail->m_members.extend(move(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
void extend(Vector<T> const& values)
|
||||||
|
{
|
||||||
|
copy();
|
||||||
|
m_detail->m_members.extend(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
void extend(COWVector<T> const& values)
|
||||||
|
{
|
||||||
|
copy();
|
||||||
|
m_detail->m_members.extend(values.m_detail->m_members);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepend(T value)
|
||||||
|
{
|
||||||
|
copy();
|
||||||
|
m_detail->m_members.prepend(move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USING_AK_GLOBALLY
|
||||||
|
using AK::COWVector;
|
||||||
|
#endif
|
|
@ -11,6 +11,7 @@
|
||||||
#include <AK/Error.h>
|
#include <AK/Error.h>
|
||||||
|
|
||||||
#include <AK/ByteString.h>
|
#include <AK/ByteString.h>
|
||||||
|
#include <AK/COWVector.h>
|
||||||
#include <AK/DeprecatedFlyString.h>
|
#include <AK/DeprecatedFlyString.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/MemMem.h>
|
#include <AK/MemMem.h>
|
||||||
|
@ -25,135 +26,6 @@
|
||||||
|
|
||||||
namespace regex {
|
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 {
|
class RegexStringView {
|
||||||
public:
|
public:
|
||||||
RegexStringView() = default;
|
RegexStringView() = default;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue