diff --git a/AK/FixedArray.h b/AK/FixedArray.h new file mode 100644 index 0000000000..ddcbc6c47a --- /dev/null +++ b/AK/FixedArray.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace AK { + +template +class FixedArray { +public: + FixedArray() { } + explicit FixedArray(size_t size) + : m_size(size) + { + if (m_size != 0) { + m_elements = (T*)kmalloc(sizeof(T) * m_size); + for (size_t i = 0; i < m_size; ++i) + new (&m_elements[i]) T(); + } + } + ~FixedArray() + { + clear(); + } + + FixedArray(FixedArray const& other) + : m_size(other.m_size) + { + if (m_size != 0) { + m_elements = (T*)kmalloc(sizeof(T) * m_size); + for (size_t i = 0; i < m_size; ++i) + new (&m_elements[i]) T(other[i]); + } + } + + FixedArray& operator=(FixedArray const& other) + { + FixedArray array(other); + swap(array); + return *this; + } + + FixedArray(FixedArray&&) = delete; + FixedArray& operator=(FixedArray&&) = delete; + + void clear() + { + if (!m_elements) + return; + for (size_t i = 0; i < m_size; ++i) + m_elements[i].~T(); + kfree_sized(m_elements, sizeof(T) * m_size); + m_elements = nullptr; + m_size = 0; + } + + size_t size() const { return m_size; } + T* data() { return m_elements; } + T const* data() const { return m_elements; } + + T& operator[](size_t index) + { + VERIFY(index < m_size); + return m_elements[index]; + } + + T const& operator[](size_t index) const + { + VERIFY(index < m_size); + return m_elements[index]; + } + + bool contains_slow(T const& value) const + { + for (size_t i = 0; i < m_size; ++i) { + if (m_elements[i] == value) + return true; + } + return false; + } + + void swap(FixedArray& other) + { + ::swap(m_elements, other.m_elements); + ::swap(m_size, other.m_size); + } + + using ConstIterator = SimpleIterator; + using Iterator = SimpleIterator; + + ConstIterator begin() const { return ConstIterator::begin(*this); } + Iterator begin() { return Iterator::begin(*this); } + + ConstIterator end() const { return ConstIterator::end(*this); } + Iterator end() { return Iterator::end(*this); } + +private: + size_t m_size { 0 }; + T* m_elements { nullptr }; +}; + +} + +using AK::FixedArray; diff --git a/AK/Forward.h b/AK/Forward.h index cdd779ed1d..408b517ad7 100644 --- a/AK/Forward.h +++ b/AK/Forward.h @@ -84,6 +84,9 @@ using OrderedHashMap = HashMap; template class Badge; +template +class FixedArray; + template class Function; @@ -132,6 +135,7 @@ using AK::CircularDuplexStream; using AK::CircularQueue; using AK::DoublyLinkedList; using AK::DuplexMemoryStream; +using AK::FixedArray; using AK::FlyString; using AK::Function; using AK::HashMap; diff --git a/Tests/AK/CMakeLists.txt b/Tests/AK/CMakeLists.txt index 346165afd0..8459a55706 100644 --- a/Tests/AK/CMakeLists.txt +++ b/Tests/AK/CMakeLists.txt @@ -21,6 +21,7 @@ set(AK_TEST_SOURCES TestEndian.cpp TestEnumBits.cpp TestFind.cpp + TestFixedArray.cpp TestFormat.cpp TestGenericLexer.cpp TestHashFunctions.cpp diff --git a/Tests/AK/TestFixedArray.cpp b/Tests/AK/TestFixedArray.cpp new file mode 100644 index 0000000000..6b33818c62 --- /dev/null +++ b/Tests/AK/TestFixedArray.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include + +TEST_CASE(construct) +{ + EXPECT(FixedArray().size() == 0); +} + +TEST_CASE(ints) +{ + FixedArray ints(3); + ints[0] = 0; + ints[1] = 1; + ints[2] = 2; + EXPECT_EQ(ints[0], 0); + EXPECT_EQ(ints[1], 1); + EXPECT_EQ(ints[2], 2); + + ints.clear(); + EXPECT_EQ(ints.size(), 0u); +}