3#include "../Memory/Allocator.h"
7#include <initializer_list>
19 capacityPtr(
static_cast<uint8_t*
>(firstPtr) + capacity),
23 void growPod(
const void* firstElement,
const size_t minSizeBytes);
25 size_t sizeInBytes()
const
27 return static_cast<size_t>(
static_cast<uint8_t*
>(lastPtr) -
static_cast<uint8_t*
>(firstPtr));
30 size_t capacityInBytes()
const
32 return static_cast<size_t>(
static_cast<uint8_t*
>(capacityPtr) -
static_cast<uint8_t*
>(firstPtr));
45 bool empty()
const {
return lastPtr == firstPtr; }
46 size_t size()
const {
return end() - begin(); }
47 size_t capacity()
const {
return static_cast<T *
>(capacityPtr) - begin(); }
49 T * data() {
return static_cast<T *
>(firstPtr); }
50 const T * data()
const {
return static_cast<const T *
>(firstPtr); }
52 T * begin() {
return static_cast<T *
>(firstPtr); }
53 T * end() {
return static_cast<T *
>(lastPtr); }
55 const T * begin()
const {
return static_cast<const T *
>(firstPtr); }
56 const T * end()
const {
return static_cast<const T *
>(lastPtr); }
57 const T * cbegin()
const {
return static_cast<const T *
>(firstPtr); }
58 const T * cend()
const {
return static_cast<const T *
>(lastPtr); }
60 T & operator[](
const size_t index)
62 assert(index < size() &&
"Index out of bounds");
63 return begin()[index];
66 const T & operator[](
const size_t index)
const
68 assert(index < size() &&
"Index out of bounds");
69 return begin()[index];
78 const T & back()
const
90 const T & front()
const
100 bool isSmall()
const {
return firstPtr == &firstElement; }
102 void setSize(
size_t newSize)
104 assert(begin() + newSize <= capacityPtr &&
"Size exceeds capacity.");
105 lastPtr = begin() + newSize;
110 firstPtr = lastPtr = capacityPtr = &firstElement;
113 alignas(T) uint8_t firstElement[
sizeof(T)];
116 template<
typename T,
bool isPod>
120 void push_back(
const T & t)
122 if (this->size() == this->capacity()) {
126 new (this->end()) T(t);
127 this->setSize(this->size() + 1);
130 void push_back(T && t)
132 if (this->size() == this->capacity()) {
136 new (this->end()) T(std::move(t));
137 this->setSize(this->size() + 1);
140 template<
typename... Args>
141 void emplace_back(Args &&... args)
143 if (this->size() == this->capacity()) {
147 new (this->end()) T(std::forward<Args>(args)...);
148 this->setSize(this->size() + 1);
153 this->setSize(this->size() - 1);
158 void erase(
const T* pos)
160 const size_t index = pos - this->begin();
161 assert(index < this->size() &&
"Index out of bounds");
162 (this->begin() + index)->~T();
163 this->move(this->begin()+index+1, this->end(), this->begin() + index);
164 this->setSize(this->size() - 1);
171 void grow(
size_t minSize = 0)
173 size_t newCapacity = this->capacity() * 2;
174 if (minSize > newCapacity) newCapacity = minSize;
176 const size_t currentSize = this->size();
178 auto newBuffer =
static_cast<T *
>(this->allocator->
allocate(newCapacity *
sizeof(T)));
180 moveNew(this->begin(), this->end(), newBuffer);
182 destroy(this->begin(), this->end());
184 this->firstPtr = newBuffer;
185 this->lastPtr = newBuffer + currentSize;
186 this->capacityPtr = newBuffer + newCapacity;
189 void initialize(T* first,
const T* last)
191 while (first != last) {
196 void destroy(T* first,
const T* last)
198 while (first != last) {
203 template<
typename T1,
typename T2>
204 void moveNew(T1 first, T1 last, T2 dest)
206 while (first != last) {
207 new (dest++) T(std::move(*first++));
211 template<
typename T1,
typename T2>
212 void move(T1 first, T1 last, T2 dest)
214 while (first != last) {
215 (*dest++) = std::move(*first++);
219 template<
typename T1,
typename T2>
220 void copy(T1 first, T1 last, T2 dest)
222 while (first != last) {
223 (*dest++) = *first++;
227 template<
typename T1,
typename T2>
228 void copyNew(T1 first, T1 last, T2 dest)
230 while (first != last) {
231 new (dest++) T(*first++);
240 void push_back(
const T & t)
242 if (this->size() == this->capacity()) {
246 new (this->end()) T(t);
247 this->setSize(this->size() + 1);
252 this->setSize(this->size() - 1);
256 void erase(
const T* pos)
258 const size_t index = pos - this->begin();
259 assert(index < this->size() &&
"Index out of bounds");
260 this->move(this->begin() + index + 1, this->end(), this->begin() + index);
261 this->setSize(this->size() - 1);
269 void grow(
size_t minSize = 0)
271 this->growPod(&this->firstElement, minSize *
sizeof(T));
274 void initialize(T *, T *) {}
275 void destroy(T *, T *) {}
277 template<
typename T1,
typename T2>
278 void move(T1 first, T1 last, T2 dest)
280 copy(first, last, dest);
283 template<
typename T1,
typename T2>
284 void copy(T1 first, T1 last, T2 dest)
286 copyNew(first, last, dest);
289 template<
typename T1,
typename T2>
290 void copyNew(T1 first, T1 last, T2 dest)
292 std::memcpy(dest, first, (last - first) *
sizeof(T));
302 this->destroy(this->begin(), this->end());
304 if (!this->isSmall()) {
311 if (
this == &other)
return *
this;
315 if (this->capacity() < other.capacity()) {
316 this->grow(other.size());
319 this->copyNew(other.begin(), other.end(), this->begin());
321 this->setSize(other.size());
328 if (
this == &other)
return *
this;
330 this->destroy(this->begin(), this->end());
332 if (!other.isSmall()) {
333 if (!this->isSmall()) {
337 this->firstPtr = other.firstPtr;
338 this->lastPtr = other.lastPtr;
339 this->capacityPtr = other.capacityPtr;
340 this->allocator = other.allocator;
347 if (this->capacity() < other.capacity()) {
348 this->grow(other.size());
351 this->move(other.begin(), other.end(), this->begin());
353 this->setSize(other.size());
358 void resize(
size_t newSize)
360 if (newSize > this->capacity()) {
364 this->setSize(newSize);
367 void reserve(
size_t newCapacity)
369 if (newCapacity >= this->capacity()) {
370 this->grow(newCapacity);
376 this->destroy(this->begin(), this->end());
381 template<
typename T1>
382 void assign(T1 first, T1 last)
385 const size_t newSize = last - first;
387 if (newSize > this->capacity()) {
391 this->copyNew(first, last, this->data());
392 this->setSize(newSize);
395 void assign(std::initializer_list<T> il)
397 assign(il.begin(), il.end());
400 template<
typename T1>
401 void append(T1 first, T1 last)
403 const size_t newSize = last - first + this->size();
405 if (newSize > this->capacity()) {
409 this->copyNew(first, last, this->end());
410 this->setSize(newSize);
413 void append(std::initializer_list<T> il)
415 append(il.begin(), il.end());
425 this->allocator->
deallocate(this->firstPtr, this->capacityInBytes());
429 template<
typename T,
size_t Size>
432 template<
typename Ts,
size_t Sizes>
435 alignas(Ts) uint8_t inlineStorage[
sizeof(Ts) * Sizes];
443 using value_type = T;
444 using difference_type = ptrdiff_t;
445 using pointer =
const T*;
446 using reference =
const T&;
450 SmallVector(
Memory::Allocator * allocator) : SmallVectorImpl<T>(Size, allocator) {};
452 SmallVector(SmallVector && other) noexcept : SmallVectorImpl<T>(Size)
454 SmallVectorImpl<T>::operator=(std::move(other));
457 SmallVector(SmallVectorImpl<T> && other) noexcept : SmallVectorImpl<T>(Size)
459 SmallVectorImpl<T>::operator=(std::move(other));
462 SmallVector(
const SmallVector & other) : SmallVectorImpl<T>(Size)
464 SmallVectorImpl<T>::operator=(other);
467 SmallVector(
const SmallVectorImpl<T> & other) : SmallVectorImpl<T>(Size)
469 SmallVectorImpl<T>::operator=(other);
472 SmallVector(std::initializer_list<T> il) : SmallVectorImpl<T>(Size)
477 SmallVector & operator=(
const SmallVector & other)
479 SmallVectorImpl<T>::operator=(other);
483 SmallVector & operator=(SmallVector && other)
noexcept
485 SmallVectorImpl<T>::operator=(std::move(other));
489 SmallVector & operator=(SmallVectorImpl<T> && other)
noexcept
491 SmallVectorImpl<T>::operator=(std::move(other));
496 SmallVectorStorage<T, Size> inlineStorage;
Base allocator implementation.
virtual void deallocate(void *ptr, size_t size, MemBlockType type=MemBlockType::Block)
Deallocate the memory block at the given pointer, with the given size.
virtual void * allocate(size_t size, size_t alignment=0, MemBlockType type=MemBlockType::Block)
Allocate raw memory.
static Allocator * overflowAllocator()
Contains all Cogs related functionality.