diff --git a/AK/COWVector.h b/AK/COWVector.h new file mode 100644 index 0000000000..23bc8da0c9 --- /dev/null +++ b/AK/COWVector.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021-2024, Ali Mohammad Pur + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace AK { + +template +class COWVector { + struct Detail : RefCounted { + Vector m_members; + }; + +public: + COWVector() + : m_detail(make_ref_counted()) + { + } + + COWVector(std::initializer_list entries) + : m_detail(make_ref_counted()) + { + 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 release() && + { + if (m_detail->ref_count() == 1) + return exchange(m_detail->m_members, Vector()); + + 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&& values) + { + copy(); + m_detail->m_members.extend(move(values)); + } + + void extend(Vector const& values) + { + copy(); + m_detail->m_members.extend(values); + } + + void extend(COWVector 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 + void empend(Args&&... args) + { + copy(); + m_detail->m_members.empend(forward(args)...); + } + + void clear() + { + if (m_detail->ref_count() > 1) + m_detail = make_ref_counted(); + 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(); + new_detail->m_members = m_detail->m_members; + m_detail = new_detail; + } + + NonnullRefPtr m_detail; +}; + +} + +#if USING_AK_GLOBALLY +using AK::COWVector; +#endif diff --git a/Userland/Libraries/LibRegex/RegexMatch.h b/Userland/Libraries/LibRegex/RegexMatch.h index 296eb421ff..46f7ef20de 100644 --- a/Userland/Libraries/LibRegex/RegexMatch.h +++ b/Userland/Libraries/LibRegex/RegexMatch.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -25,135 +26,6 @@ namespace regex { -template -class COWVector { - struct Detail : RefCounted { - Vector m_members; - }; - -public: - COWVector() - : m_detail(make_ref_counted()) - { - } - - COWVector(COWVector const&) = default; - COWVector(COWVector&&) = default; - - COWVector& operator=(COWVector const&) = default; - COWVector& operator=(COWVector&&) = default; - - Vector release() && - { - if (m_detail->ref_count() == 1) - return exchange(m_detail->m_members, Vector()); - - 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 - void empend(Args&&... args) - { - copy(); - m_detail->m_members.empend(forward(args)...); - } - - void clear() - { - if (m_detail->ref_count() > 1) - m_detail = make_ref_counted(); - 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(); - new_detail->m_members = m_detail->m_members; - m_detail = new_detail; - } - - NonnullRefPtr m_detail; -}; - class RegexStringView { public: RegexStringView() = default;