From 5096eaa8455fdacec8e0e23ee5ff76ec06490493 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 7 Aug 2019 20:05:36 +0200 Subject: [PATCH] AK: Add a FixedArray 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. --- AK/FixedArray.h | 83 +++++++++++++++++++++++++++++++++++++ AK/Tests/Makefile | 9 ++-- AK/Tests/TestFixedArray.cpp | 55 ++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 AK/FixedArray.h create mode 100644 AK/Tests/TestFixedArray.cpp diff --git a/AK/FixedArray.h b/AK/FixedArray.h new file mode 100644 index 00000000000..cfe3eb3fae9 --- /dev/null +++ b/AK/FixedArray.h @@ -0,0 +1,83 @@ +#pragma once + +#include + +namespace AK { + +template +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; + Iterator begin() { return Iterator(*this, 0); } + Iterator end() { return Iterator(*this, size()); } + + using ConstIterator = VectorIterator; + 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 30e940dc3ad..7621cf97bb9 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 00000000000..92fe01b24c3 --- /dev/null +++ b/AK/Tests/TestFixedArray.cpp @@ -0,0 +1,55 @@ +#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); +} + +TEST_CASE(resize) +{ + FixedArray 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)