2020-10-25 06:21:36 +08:00
|
|
|
#pragma once
|
2022-10-02 04:29:51 +08:00
|
|
|
#include <blah_common.h>
|
2020-10-25 06:21:36 +08:00
|
|
|
|
|
|
|
namespace Blah
|
|
|
|
{
|
2021-03-23 07:53:27 +08:00
|
|
|
// A lightweight Vector implementation
|
2020-10-25 08:34:20 +08:00
|
|
|
template<class T>
|
|
|
|
class Vector
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
T* m_buffer;
|
2020-10-25 15:54:19 +08:00
|
|
|
int m_count;
|
|
|
|
int m_capacity;
|
2020-10-25 08:34:20 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Vector();
|
|
|
|
Vector(int capacity);
|
2022-02-12 07:20:07 +08:00
|
|
|
Vector(const InitializerList<T>& list);
|
2020-10-25 08:34:20 +08:00
|
|
|
Vector(const Vector& src);
|
|
|
|
Vector(Vector&& src) noexcept;
|
|
|
|
~Vector();
|
|
|
|
|
|
|
|
Vector& operator=(const Vector& src);
|
|
|
|
Vector& operator=(Vector&& src) noexcept;
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
void clear();
|
|
|
|
void dispose();
|
|
|
|
|
|
|
|
int size() const;
|
|
|
|
int capacity() const;
|
|
|
|
|
2020-12-06 05:50:19 +08:00
|
|
|
void reserve(int new_capacity);
|
2020-10-25 15:54:19 +08:00
|
|
|
void resize(int new_count);
|
|
|
|
T* expand(int amount = 1);
|
2020-10-25 08:34:20 +08:00
|
|
|
|
|
|
|
void push_back(const T& item);
|
|
|
|
void push_back(T&& item);
|
|
|
|
template<class ...Args>
|
|
|
|
void emplace_back(Args&&...args);
|
|
|
|
|
|
|
|
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 08:34:20 +08:00
|
|
|
};
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
|
2020-10-25 08:34:20 +08:00
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline Vector<T>::Vector()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
|
|
|
m_buffer = nullptr;
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = m_capacity = 0;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline Vector<T>::Vector(int capacity)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
|
|
|
m_buffer = nullptr;
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = m_capacity = 0;
|
|
|
|
reserve(capacity);
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline Vector<T>::Vector(const Vector& src)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
m_buffer = nullptr;
|
|
|
|
m_count = m_capacity = 0;
|
|
|
|
reserve(src.m_capacity);
|
|
|
|
for (int i = 0; i < src.m_count; i++)
|
2021-01-03 16:32:01 +08:00
|
|
|
new (m_buffer + i) T(src.m_buffer[i]);
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = src.m_count;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline Vector<T>::Vector(Vector&& src) noexcept
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
|
|
|
m_buffer = src.m_buffer;
|
|
|
|
m_capacity = src.m_capacity;
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = src.m_count;
|
2020-10-25 08:34:20 +08:00
|
|
|
src.m_buffer = nullptr;
|
2020-10-25 15:54:19 +08:00
|
|
|
src.m_capacity = 0;
|
|
|
|
src.m_count = 0;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
2021-03-21 14:24:18 +08:00
|
|
|
template<class T>
|
2022-02-12 07:20:07 +08:00
|
|
|
inline Vector<T>::Vector(const InitializerList<T>& list)
|
2021-03-21 14:24:18 +08:00
|
|
|
{
|
|
|
|
m_buffer = nullptr;
|
|
|
|
m_count = m_capacity = 0;
|
2021-05-10 08:23:02 +08:00
|
|
|
reserve((int)list.size());
|
2021-03-21 14:24:18 +08:00
|
|
|
for (auto& it : list)
|
|
|
|
push_back(std::move(it));
|
|
|
|
}
|
|
|
|
|
2020-10-25 08:34:20 +08:00
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline Vector<T>::~Vector()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
dispose();
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline Vector<T>& Vector<T>::operator=(const Vector& src)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
reserve(src.m_capacity);
|
|
|
|
for (int i = 0; i < src.m_count; i++)
|
2021-01-05 10:37:08 +08:00
|
|
|
new (m_buffer + i) T(src.m_buffer[i]);
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = src.m_count;
|
2020-10-25 08:34:20 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline Vector<T>& Vector<T>::operator=(Vector&& src) noexcept
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
|
|
|
dispose();
|
|
|
|
m_buffer = src.m_buffer;
|
|
|
|
m_capacity = src.m_capacity;
|
2020-10-25 15:54:19 +08:00
|
|
|
m_count = src.m_count;
|
2020-10-25 08:34:20 +08:00
|
|
|
src.m_buffer = nullptr;
|
2020-10-25 15:54:19 +08:00
|
|
|
src.m_capacity = 0;
|
|
|
|
src.m_count = 0;
|
2020-10-25 08:34:20 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline void Vector<T>::clear()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
for (int i = 0; i < m_count; i++)
|
|
|
|
m_buffer[i].~T();
|
|
|
|
m_count = 0;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline void Vector<T>::dispose()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
clear();
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
::operator delete (m_buffer, sizeof(T) * m_capacity);
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
m_capacity = 0;
|
|
|
|
m_buffer = nullptr;
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline int Vector<T>::size() const
|
|
|
|
{
|
|
|
|
return m_count;
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline int Vector<T>::capacity() const
|
|
|
|
{
|
|
|
|
return m_capacity;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-12-06 05:50:19 +08:00
|
|
|
inline void Vector<T>::reserve(int cap)
|
2020-10-25 15:54:19 +08:00
|
|
|
{
|
|
|
|
if (cap > m_capacity)
|
|
|
|
{
|
|
|
|
int new_capacity = m_capacity;
|
|
|
|
if (new_capacity <= 0)
|
|
|
|
new_capacity = 8;
|
|
|
|
while (new_capacity < cap)
|
|
|
|
new_capacity *= 2;
|
|
|
|
|
|
|
|
T* new_buffer = (T*)::operator new (sizeof(T) * new_capacity);
|
|
|
|
|
2021-12-18 18:48:06 +08:00
|
|
|
if constexpr (std::is_trivially_copyable<T>())
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2022-10-02 04:29:51 +08:00
|
|
|
u8* src = (u8*)m_buffer;
|
|
|
|
u8* len = src + m_count * sizeof(T);
|
|
|
|
u8* dst = (u8*)new_buffer;
|
|
|
|
while (src < len) *(dst++) = *(src++);
|
2021-12-18 18:48:06 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < m_count; i++)
|
|
|
|
{
|
|
|
|
if (i < new_capacity)
|
|
|
|
new (new_buffer + i) T(std::move(m_buffer[i]));
|
|
|
|
m_buffer[i].~T();
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
2021-12-18 18:48:06 +08:00
|
|
|
::operator delete (m_buffer, sizeof(T) * m_capacity);
|
2020-10-25 15:54:19 +08:00
|
|
|
|
2020-10-25 08:34:20 +08:00
|
|
|
m_buffer = new_buffer;
|
2020-10-25 15:54:19 +08:00
|
|
|
m_capacity = new_capacity;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline void Vector<T>::resize(int new_count)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
if (new_count < m_count)
|
|
|
|
erase(new_count, m_count - new_count);
|
|
|
|
else
|
|
|
|
expand(new_count - m_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline T* Vector<T>::expand(int amount)
|
|
|
|
{
|
|
|
|
if (amount > 0)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
int count = m_count;
|
|
|
|
|
|
|
|
reserve(count + amount);
|
|
|
|
for (int i = 0; i < amount; i++)
|
|
|
|
new (m_buffer + count + i) T();
|
|
|
|
|
|
|
|
m_count += amount;
|
|
|
|
return &m_buffer[count];
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
return m_buffer;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline void Vector<T>::push_back(const T& item)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2021-01-03 16:32:01 +08:00
|
|
|
reserve(m_count + 1);
|
|
|
|
new (m_buffer + m_count) T(item);
|
|
|
|
m_count++;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline void Vector<T>::push_back(T&& item)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2021-01-03 16:32:01 +08:00
|
|
|
reserve(m_count + 1);
|
|
|
|
new (m_buffer + m_count) T(std::move(item));
|
|
|
|
m_count++;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class ...Args>
|
2020-12-06 05:50:19 +08:00
|
|
|
inline void Vector<T>::emplace_back(Args&& ...args)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
reserve(m_count + 1);
|
|
|
|
new (m_buffer + m_count) T(std::forward<Args>(args)...);
|
|
|
|
m_count++;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline T& Vector<T>::operator[](int index)
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
|
|
|
return m_buffer[index];
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline const T& Vector<T>::operator[](int index) const
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
2020-10-25 08:34:20 +08:00
|
|
|
return m_buffer[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline T* Vector<T>::data()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
return m_buffer;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline const T* Vector<T>::data() const
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
return m_buffer;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline T* Vector<T>::begin()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
return m_buffer;
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline const T* Vector<T>::begin() const
|
|
|
|
{
|
|
|
|
return m_buffer;
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline T* Vector<T>::end()
|
|
|
|
{
|
|
|
|
return m_buffer + m_count;
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline const T* Vector<T>::end() const
|
|
|
|
{
|
|
|
|
return m_buffer + m_count;
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2020-10-25 15:54:19 +08:00
|
|
|
inline T& Vector<T>::front()
|
2020-10-25 08:34:20 +08:00
|
|
|
{
|
2020-10-25 15:54:19 +08:00
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return m_buffer[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline const T& Vector<T>::front() const
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return m_buffer[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline T& Vector<T>::back()
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return m_buffer[m_count - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline const T& Vector<T>::back() const
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
return m_buffer[m_count - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline void Vector<T>::erase(int index, int elements)
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(index >= 0 && index + elements <= m_count, "Index out of range");
|
|
|
|
|
|
|
|
if (elements >= 1)
|
|
|
|
{
|
|
|
|
for (int i = index; i < (m_count - elements); i++)
|
|
|
|
m_buffer[i] = std::move(m_buffer[i + elements]);
|
|
|
|
for (int i = m_count - elements; i < m_count; i++)
|
|
|
|
m_buffer[i].~T();
|
|
|
|
m_count -= elements;
|
|
|
|
}
|
2020-10-25 08:34:20 +08:00
|
|
|
}
|
|
|
|
|
2020-10-25 15:54:19 +08:00
|
|
|
template<class T>
|
|
|
|
inline T Vector<T>::pop()
|
|
|
|
{
|
|
|
|
BLAH_ASSERT(m_count > 0, "Index out of range");
|
|
|
|
|
|
|
|
T value = std::move(m_buffer[m_count - 1]);
|
|
|
|
m_buffer[m_count - 1].~T();
|
|
|
|
m_count--;
|
|
|
|
return value;
|
|
|
|
}
|
2022-10-02 04:29:51 +08:00
|
|
|
}
|