diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-08-07 20:05:36 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-08-07 20:05:36 +0200 |
commit | 5096eaa8455fdacec8e0e23ee5ff76ec06490493 (patch) | |
tree | c3e43109c82e95a91a7d7938db6564a3cf4d2390 /AK | |
parent | 6bdb81ad87708015be8252b5e431a20b498048ff (diff) | |
download | serenity-5096eaa8455fdacec8e0e23ee5ff76ec06490493.zip |
AK: Add a FixedArray<T> container
This is a simple array wrapper that knows its size. It has begin/end
so you can use range-for. It also has a resize() that reallocates.
Diffstat (limited to 'AK')
-rw-r--r-- | AK/FixedArray.h | 83 | ||||
-rw-r--r-- | AK/Tests/Makefile | 9 | ||||
-rw-r--r-- | AK/Tests/TestFixedArray.cpp | 55 |
3 files changed, 144 insertions, 3 deletions
diff --git a/AK/FixedArray.h b/AK/FixedArray.h new file mode 100644 index 0000000000..cfe3eb3fae --- /dev/null +++ b/AK/FixedArray.h @@ -0,0 +1,83 @@ +#pragma once + +#include <AK/Vector.h> + +namespace AK { + +template<typename T> +class FixedArray { +public: + FixedArray() {} + explicit FixedArray(size_t size) + : m_size(size) + { + 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(const FixedArray& other) + : m_size(other.m_size) + { + 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=(const FixedArray&) = delete; + 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(m_elements); + m_elements = nullptr; + m_size = 0; + } + + size_t size() const { return m_size; } + + T& operator[](size_t index) { return m_elements[index]; } + const T& operator[](size_t index) const { return m_elements[index]; } + + void resize(size_t new_size) + { + if (new_size == m_size) + return; + auto* new_elements = (T*)kmalloc(new_size * sizeof(T)); + for (size_t i = 0; i < min(new_size, m_size); ++i) + new (&new_elements[i]) T(move(m_elements[i])); + for (size_t i = min(new_size, m_size); i < new_size; ++i) + new (&new_elements[i]) T(); + for (size_t i = 0; i < m_size; ++i) + m_elements[i].~T(); + if (m_elements) + kfree(m_elements); + m_elements = new_elements; + m_size = new_size; + } + + using Iterator = VectorIterator<FixedArray, T>; + Iterator begin() { return Iterator(*this, 0); } + Iterator end() { return Iterator(*this, size()); } + + using ConstIterator = VectorIterator<const FixedArray, const T>; + ConstIterator begin() const { return ConstIterator(*this, 0); } + ConstIterator end() const { return ConstIterator(*this, size()); } + +private: + size_t m_size { 0 }; + T* m_elements { nullptr }; +}; + +} + +using AK::FixedArray; diff --git a/AK/Tests/Makefile b/AK/Tests/Makefile index 30e940dc3a..7621cf97bb 100644 --- a/AK/Tests/Makefile +++ b/AK/Tests/Makefile @@ -1,4 +1,4 @@ -PROGRAMS = TestString TestQueue TestVector TestHashMap TestJSON TestWeakPtr TestNonnullRefPtr TestRefPtr +PROGRAMS = TestString TestQueue TestVector TestHashMap TestJSON TestWeakPtr TestNonnullRefPtr TestRefPtr TestFixedArray CXXFLAGS = -std=c++17 -Wall -Wextra -ggdb3 -O2 -I../ -I../../ @@ -32,10 +32,13 @@ TestQueue: TestQueue.o $(SHARED_TEST_OBJS) TestVector: TestVector.o $(SHARED_TEST_OBJS) $(PRE_CXX) $(CXX) $(CXXFLAGS) -o $@ TestVector.o $(SHARED_TEST_OBJS) -# + +TestFixedArray: TestFixedArray.o $(SHARED_TEST_OBJS) + $(PRE_CXX) $(CXX) $(CXXFLAGS) -o $@ TestFixedArray.o $(SHARED_TEST_OBJS) + TestHashMap: TestHashMap.o $(SHARED_TEST_OBJS) $(PRE_CXX) $(CXX) $(CXXFLAGS) -o $@ TestHashMap.o $(SHARED_TEST_OBJS) -# + TestJSON: TestJSON.o $(SHARED_TEST_OBJS) $(PRE_CXX) $(CXX) $(CXXFLAGS) -o $@ TestJSON.o $(SHARED_TEST_OBJS) diff --git a/AK/Tests/TestFixedArray.cpp b/AK/Tests/TestFixedArray.cpp new file mode 100644 index 0000000000..92fe01b24c --- /dev/null +++ b/AK/Tests/TestFixedArray.cpp @@ -0,0 +1,55 @@ +#include <AK/TestSuite.h> + +#include <AK/AKString.h> +#include <AK/FixedArray.h> + +TEST_CASE(construct) +{ + EXPECT(FixedArray<int>().size() == 0); +} + +TEST_CASE(ints) +{ + FixedArray<int> 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); +} + +TEST_CASE(resize) +{ + FixedArray<String> strings(2); + strings[0] = "ABC"; + strings[1] = "DEF"; + + EXPECT_EQ(strings.size(), 2u); + EXPECT_EQ(strings[0], "ABC"); + EXPECT_EQ(strings[1], "DEF"); + + strings.resize(4); + + EXPECT_EQ(strings.size(), 4u); + EXPECT_EQ(strings[0], "ABC"); + EXPECT_EQ(strings[1], "DEF"); + + EXPECT_EQ(strings[2].is_null(), true); + EXPECT_EQ(strings[3].is_null(), true); + + strings[2] = "GHI"; + strings[3] = "JKL"; + + EXPECT_EQ(strings[2], "GHI"); + EXPECT_EQ(strings[3], "JKL"); + + strings.resize(1); + EXPECT_EQ(strings.size(), 1u); + EXPECT_EQ(strings[0], "ABC"); +} + +TEST_MAIN(FixedArray) |