2020-10-25 06:21:36 +08:00
|
|
|
#pragma once
|
2021-03-21 08:33:04 +08:00
|
|
|
#include <blah/core/common.h>
|
2020-10-25 06:21:36 +08:00
|
|
|
#include <new>
|
2021-01-03 10:27:58 +08:00
|
|
|
#include <initializer_list>
|
2020-10-25 06:21:36 +08:00
|
|
|
|
|
|
|
namespace Blah
|
|
|
|
{
|
|
|
|
// A mix between an std::vector and an std::array
|
|
|
|
// The goal is to have an std::vector implementation that lives
|
|
|
|
// on the stack instead of the heap
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
2020-10-25 06:21:36 +08:00
|
|
|
class StackVector
|
|
|
|
{
|
|
|
|
private:
|
2020-11-23 17:32:06 +08:00
|
|
|
char m_buffer[sizeof(T) * Capacity];
|
2020-10-25 15:54:19 +08:00
|
|
|
int m_count;
|
2020-10-25 06:21:36 +08:00
|
|
|
|
|
|
|
public:
|
2020-12-29 10:31:06 +08:00
|
|
|
static inline constexpr size_t MaxCapacity = Capacity;
|
2020-10-25 06:21:36 +08:00
|
|
|
|
|
|
|
StackVector();
|
2020-12-29 10:31:06 +08:00
|
|
|
StackVector(const std::initializer_list<T>& init);
|
2020-10-25 06:21:36 +08:00
|
|
|
StackVector(const StackVector& src);
|
|
|
|
StackVector(StackVector&& src) noexcept;
|
|
|
|
~StackVector();
|
|
|
|
|
|
|
|
StackVector& operator=(const StackVector& src);
|
|
|
|
StackVector& operator=(StackVector&& src) noexcept;
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
void clear();
|
|
|
|
|
|
|
|
int size() const;
|
|
|
|
constexpr int capacity() { return Capacity; }
|
|
|
|
|
|
|
|
T* expand(int amount = 1);
|
2020-10-25 06:21:36 +08:00
|
|
|
void push_back(const T& item);
|
|
|
|
void push_back(T&& item);
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class ...Args>
|
|
|
|
void emplace_back(Args&&...args);
|
2020-10-25 06:21:36 +08:00
|
|
|
|
|
|
|
T& operator[](int index);
|
|
|
|
const T& operator[](int index) const;
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
T* data();
|
|
|
|
const T* data() const;
|
|
|
|
T* begin();
|
|
|
|
const T* begin() const;
|
|
|
|
T* end();
|
|
|
|
const T* end() const;
|
|
|
|
T& front();
|
|
|
|
const T& front() const;
|
|
|
|
T& back();
|
|
|
|
const T& back() const;
|
|
|
|
|
|
|
|
void erase(int index, int elements = 1);
|
|
|
|
T pop();
|
2020-10-25 06:21:36 +08:00
|
|
|
};
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>::StackVector()
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = 0;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-12-29 10:31:06 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>::StackVector(const std::initializer_list<T>& init)
|
|
|
|
{
|
|
|
|
m_count = 0;
|
|
|
|
for (auto& it : init)
|
|
|
|
push_back(it);
|
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>::StackVector(const StackVector& src)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
for (int i = 0; i < src.m_count; i++)
|
|
|
|
new (data() + i) T(src.data()[i]);
|
|
|
|
m_count = src.m_count;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>::StackVector(StackVector&& src) noexcept
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
for (int i = 0; i < src.m_count; i++)
|
|
|
|
new (data() + i) T(std::move(src.data()[i]));
|
|
|
|
m_count = src.m_count;
|
|
|
|
}
|
2020-10-25 06:21:36 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>::~StackVector()
|
|
|
|
{
|
|
|
|
clear();
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>& StackVector<T, Capacity>::operator=(const StackVector& src)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
for (int i = 0; i < src.m_count; i++)
|
2021-04-25 13:47:44 +08:00
|
|
|
new (data() + i) T(std::move(src.data()[i]));
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = src.m_count;
|
2020-10-25 06:21:36 +08:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline StackVector<T, Capacity>& StackVector<T, Capacity>::operator=(StackVector&& src) noexcept
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
for (int i = 0; i < src.m_count; i++)
|
2021-04-25 13:47:44 +08:00
|
|
|
new (data() + i) T(std::move(src.data()[i]));
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = src.m_count;
|
2020-10-25 06:21:36 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline void StackVector<T, Capacity>::clear()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_count; i++)
|
|
|
|
data()[i].~T();
|
|
|
|
m_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline int StackVector<T, Capacity>::size() const
|
|
|
|
{
|
|
|
|
return m_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T* StackVector<T, Capacity>::expand(int amount)
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count + amount <= Capacity, "Exceeded StackVector Capacity");
|
|
|
|
|
|
|
|
if (amount > 0)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
int count = m_count;
|
|
|
|
|
|
|
|
for (int i = 0; i < amount; i++)
|
2020-11-30 03:18:22 +08:00
|
|
|
new (data() + count + i) T();
|
2020-10-25 15:54:19 +08:00
|
|
|
|
|
|
|
m_count += amount;
|
|
|
|
return &data()[count];
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2021-01-11 16:25:34 +08:00
|
|
|
return (T*)m_buffer;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline void StackVector<T, Capacity>::push_back(const T& item)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity");
|
|
|
|
new (data() + m_count) T(item);
|
|
|
|
m_count++;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline void StackVector<T, Capacity>::push_back(T&& item)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity");
|
|
|
|
new (data() + m_count) T(std::move(item));
|
|
|
|
m_count++;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
template<class ...Args>
|
|
|
|
inline void StackVector<T, Capacity>::emplace_back(Args && ...args)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity");
|
|
|
|
new (data() + m_count) T(std::forward<Args>(args)...);
|
|
|
|
m_count++;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T& StackVector<T, Capacity>::operator[](int index)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
|
|
|
return data()[index];
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline const T& StackVector<T, Capacity>::operator[](int index) const
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
|
|
|
return data()[index];
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T* StackVector<T, Capacity>::data()
|
|
|
|
{
|
|
|
|
return (T*)m_buffer;
|
|
|
|
}
|
2020-10-25 06:21:36 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline const T* StackVector<T, Capacity>::data() const
|
|
|
|
{
|
|
|
|
return (T*)m_buffer;
|
|
|
|
}
|
2020-10-25 06:21:36 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T* StackVector<T, Capacity>::begin()
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
return (T*)m_buffer;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline const T* StackVector<T, Capacity>::begin() const
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
return (T*)m_buffer;
|
|
|
|
}
|
2020-10-25 06:21:36 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T* StackVector<T, Capacity>::end()
|
|
|
|
{
|
|
|
|
return ((T*)m_buffer) + m_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline const T* StackVector<T, Capacity>::end() const
|
|
|
|
{
|
|
|
|
return ((T*)m_buffer) + m_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T& StackVector<T, Capacity>::front()
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return data()[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline const T& StackVector<T, Capacity>::front() const
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return data()[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T& StackVector<T, Capacity>::back()
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return data()[m_count - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline const T& StackVector<T, Capacity>::back() const
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return data()[m_count - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline void StackVector<T, Capacity>::erase(int index, int elements)
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(index >= 0 && index + elements <= m_count, "Index out of range");
|
|
|
|
|
|
|
|
if (elements >= 1)
|
2020-10-25 06:21:36 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
for (int i = index; i < (m_count - elements); i++)
|
|
|
|
data()[i] = std::move(data()[i + elements]);
|
|
|
|
for (int i = m_count - elements; i < m_count; i++)
|
|
|
|
data()[i].~T();
|
|
|
|
m_count -= elements;
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T, size_t Capacity>
|
|
|
|
inline T StackVector<T, Capacity>::pop()
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
|
|
|
|
T value = std::move(data()[m_count - 1]);
|
|
|
|
data()[m_count - 1].~T();
|
|
|
|
m_count--;
|
|
|
|
return value;
|
|
|
|
}
|
2020-10-25 06:21:36 +08:00
|
|
|
}
|