summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-08-07 20:05:36 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-08-07 20:05:36 +0200
commit5096eaa8455fdacec8e0e23ee5ff76ec06490493 (patch)
treec3e43109c82e95a91a7d7938db6564a3cf4d2390 /AK
parent6bdb81ad87708015be8252b5e431a20b498048ff (diff)
downloadserenity-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.h83
-rw-r--r--AK/Tests/Makefile9
-rw-r--r--AK/Tests/TestFixedArray.cpp55
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)