SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
List.hpp
Go to the documentation of this file.
1#ifndef _LIST_H_
2#define _LIST_H_
3
5#include <algorithm> // For std::swap
6#include <functional>
7
8namespace Sleak {
9/**
10 * @class List
11 * @brief Implements a dynamic array-like list for storing and managing a
12 * collection of elements.
13 *
14 * The List class provides a flexible and efficient way to store and access
15 * elements in a linear order. It is suitable for scenarios where you need to
16 * dynamically resize the collection or access elements by index.
17 * @ingroup utility
18 */
19template <typename T>
20class List {
21 private:
22 T* data = nullptr;
23 size_t size = 0;
24 size_t capacity = 0;
25
26 /// Recursive quicksort driving sort().
27 void quickSort(int low, int high,
28 std::function<bool(const T&, const T&)> compare) {
29 if (low < high) {
30 int pivotIndex = partition(low, high, compare);
31 quickSort(low, pivotIndex - 1, compare);
32 quickSort(pivotIndex + 1, high, compare);
33 }
34 }
35
36 /// Lomuto partition step for quickSort; returns the pivot's final index.
37 int partition(int low, int high,
38 std::function<bool(const T&, const T&)> compare) {
39 T pivot = data[high];
40 int i = low - 1;
41
42 for (int j = low; j < high; j++) {
43 if (compare(data[j], pivot)) {
44 i++;
45 std::swap(data[i], data[j]);
46 }
47 }
48
49 std::swap(data[i + 1], data[high]);
50 return i + 1;
51 }
52
53 public:
54 List() noexcept = default;
55
56 /// Adopts an existing buffer directly; List takes ownership.
57 List(T* Data, size_t Size) : data(Data), size(Size), capacity(Size) {}
58
59 // Copy constructor
60 List(const List& other) : size(other.size), capacity(other.capacity) {
61 data = new T[capacity];
62 for (size_t i = 0; i < size; ++i) {
63 data[i] = other.data[i];
64 }
65 }
66
67 // Move constructor
68 List(List&& other) noexcept
69 : data(other.data), size(other.size), capacity(other.capacity) {
70 other.data = nullptr;
71 other.size = 0;
72 other.capacity = 0;
73 }
74
75 // Copy assignment
76 List& operator=(const List& other) {
77 if (this != &other) {
78 delete[] data;
79 size = other.size;
80 capacity = other.capacity;
81 data = new T[capacity];
82 for (size_t i = 0; i < size; ++i) {
83 data[i] = other.data[i];
84 }
85 }
86 return *this;
87 }
88
89 // Move assignment
90 List& operator=(List&& other) noexcept {
91 if (this != &other) {
92 delete[] data;
93 data = other.data;
94 size = other.size;
95 capacity = other.capacity;
96 other.data = nullptr;
97 other.size = 0;
98 other.capacity = 0;
99 }
100 return *this;
101 }
102
103 List(std::initializer_list<T> initList) {
104 for (const T& value : initList) {
105 add(value);
106 }
107 }
108
109 /// Frees the backing array.
110 ~List() { delete[] data; }
111
112 // Element addition
113 void add(const T& value) {
114 if (size == capacity) resize();
115 data[size++] = value;
116 }
117
118 void add(T&& value) {
119 if (size == capacity) resize();
120 data[size++] = std::move(value);
121 }
122
123 void add(std::initializer_list<T> AddList) {
124 for (auto&& item : AddList) {
125 add(std::move(item));
126 }
127 }
128
129 // Element access
130 T& operator[](size_t index) {
131 if (index >= size) throw Sleak::IndexOutOfBoundsException();
132 return data[index];
133 }
134
135 const T& operator[](size_t index) const {
136 if (index >= size) throw Sleak::IndexOutOfBoundsException();
137 return data[index];
138 }
139
140 T& at(size_t index) {
141 if (index >= size) throw Sleak::IndexOutOfBoundsException();
142 return data[index];
143 }
144
145 const T& at(size_t index) const {
146 if (index >= size) throw Sleak::IndexOutOfBoundsException();
147 return data[index];
148 }
149
150 // Capacity
151 size_t GetSize() const { return size; }
152 size_t GetByteSize() const { return size * sizeof(T); }
153 size_t GetCapacity() const { return capacity; }
154 bool empty() const { return size == 0; }
155
156 // Data access
157 T* GetData() { return data; }
158 const T* GetData() const { return data; }
159 void* GetRawData() { return static_cast<void*>(data); }
160 const void* GetRawData() const { return static_cast<const void*>(data); }
161
162 // Iterators
163 T* begin() { return data; }
164 const T* begin() const { return data; }
165 T* end() { return data + size; }
166 const T* end() const { return data + size; }
167
168 // Modifiers
169 void clear() {
170 // Reset each live slot to a default-constructed T so that any
171 // resources the elements own (e.g. RefPtr refcounts) are released.
172 // Setting size=0 alone leaks everything until the backing array
173 // is reallocated or destroyed.
174 for (size_t i = 0; i < size; ++i) {
175 data[i] = T();
176 }
177 size = 0;
178 }
179
180 void release() {
181 delete[] data;
182 data = nullptr;
183 size = 0;
184 capacity = 0;
185 }
186
187 void resize() {
188 size_t newCapacity = (capacity == 0) ? 1 : capacity * 2;
189 resize(newCapacity);
190 }
191
192 void resize(size_t newCapacity) {
193 if (newCapacity <= capacity) return;
194
195 T* newData = new T[newCapacity];
196 for (size_t i = 0; i < size; ++i) {
197 newData[i] = std::move(data[i]);
198 }
199 delete[] data;
200 data = newData;
201 capacity = newCapacity;
202 }
203
204 void insert(size_t index, const T& value) {
205 if (index > size) throw Sleak::IndexOutOfBoundsException();
206 if (size == capacity) resize();
207
208 for (size_t i = size; i > index; --i) {
209 data[i] = data[i - 1];
210 }
211 data[index] = value;
212 ++size;
213 }
214
215 void erase(size_t index) {
216 if (index >= size) throw Sleak::IndexOutOfBoundsException();
217
218 for (size_t i = index; i < size - 1; ++i) {
219 data[i] = std::move(data[i + 1]);
220 }
221 // Release the now-unused tail slot; otherwise it keeps owning
222 // the last element (RefPtrs pin their pointees forever).
223 data[size - 1] = T();
224 --size;
225 }
226
227 // Operations
228 void sort(std::function<bool(const T&, const T&)> compare) {
229 quickSort(0, size - 1, compare);
230 }
231
232 void reverse() {
233 for (size_t i = 0; i < size / 2; ++i) {
234 std::swap(data[i], data[size - 1 - i]);
235 }
236 }
237
238 void swap(List& other) noexcept {
239 std::swap(data, other.data);
240 std::swap(size, other.size);
241 std::swap(capacity, other.capacity);
242 }
243
244 // Search
245 T* find(std::function<bool(const T&)> predicate) {
246 for (size_t i = 0; i < size; ++i) {
247 if (predicate(data[i])) return &data[i];
248 }
249 return nullptr;
250 }
251
252 const T* find(std::function<bool(const T&)> predicate) const {
253 for (size_t i = 0; i < size; ++i) {
254 if (predicate(data[i])) return &data[i];
255 }
256 return nullptr;
257 }
258
259 int32_t indexOf(const T& value) {
260 for(int i = 0; i < size; i++)
261 if(data[i] == value)
262 return i;
263
264 return -1;
265 }
266};
267} // namespace Sleak
268
269#endif // _LIST_H_
void * GetRawData()
Definition List.hpp:159
T * end()
Definition List.hpp:165
void clear()
Definition List.hpp:169
void reverse()
Definition List.hpp:232
const void * GetRawData() const
Definition List.hpp:160
T * GetData()
Definition List.hpp:157
const T * GetData() const
Definition List.hpp:158
const T * end() const
Definition List.hpp:166
void add(std::initializer_list< T > AddList)
Definition List.hpp:123
const T * begin() const
Definition List.hpp:164
T * find(std::function< bool(const T &)> predicate)
Definition List.hpp:245
void add(const T &value)
Definition List.hpp:113
T * begin()
Definition List.hpp:163
size_t GetByteSize() const
Definition List.hpp:152
List(const List &other)
Definition List.hpp:60
~List()
Frees the backing array.
Definition List.hpp:110
bool empty() const
Definition List.hpp:154
const T & at(size_t index) const
Definition List.hpp:145
void release()
Definition List.hpp:180
size_t GetSize() const
Definition List.hpp:151
void resize(size_t newCapacity)
Definition List.hpp:192
T & operator[](size_t index)
Definition List.hpp:130
List(List &&other) noexcept
Definition List.hpp:68
void resize()
Definition List.hpp:187
List() noexcept=default
List & operator=(List &&other) noexcept
Definition List.hpp:90
void erase(size_t index)
Definition List.hpp:215
void sort(std::function< bool(const T &, const T &)> compare)
Definition List.hpp:228
List & operator=(const List &other)
Definition List.hpp:76
const T * find(std::function< bool(const T &)> predicate) const
Definition List.hpp:252
T & at(size_t index)
Definition List.hpp:140
void swap(List &other) noexcept
Definition List.hpp:238
const T & operator[](size_t index) const
Definition List.hpp:135
void insert(size_t index, const T &value)
Definition List.hpp:204
void add(T &&value)
Definition List.hpp:118
List(std::initializer_list< T > initList)
Definition List.hpp:103
size_t GetCapacity() const
Definition List.hpp:153
int32_t indexOf(const T &value)
Definition List.hpp:259
Root namespace for everything the engine exposes.
Definition Camera.hpp:10