190 lines
3.3 KiB
C++
190 lines
3.3 KiB
C++
#pragma once
|
|
#include <luna/Alloc.h>
|
|
#include <luna/CString.h>
|
|
#include <luna/Result.h>
|
|
#include <luna/Types.h>
|
|
|
|
template <typename T> class Vector
|
|
{
|
|
public:
|
|
typedef T* Iterator;
|
|
typedef const T* ConstIterator;
|
|
|
|
Vector()
|
|
{
|
|
}
|
|
|
|
Vector(const Vector<T>& other)
|
|
{
|
|
reserve(other.capacity());
|
|
memcpy(m_data, other.data(), other.size());
|
|
m_size = other.size();
|
|
}
|
|
|
|
Vector(Vector<T>&& other)
|
|
{
|
|
m_data = other.data();
|
|
m_capacity = other.capacity();
|
|
m_size = other.size();
|
|
|
|
other.m_capacity = other.m_size = 0;
|
|
other.m_data = nullptr;
|
|
}
|
|
|
|
Vector<T>& operator=(const Vector<T>& other)
|
|
{
|
|
if (&other == this) return *this;
|
|
|
|
if (m_data) free_impl(m_data);
|
|
|
|
m_data = nullptr;
|
|
m_capacity = m_size = 0;
|
|
|
|
reserve(other.capacity());
|
|
memcpy(m_data, other.data(), other.size());
|
|
m_size = other.size();
|
|
|
|
return *this;
|
|
}
|
|
|
|
Vector<T>& operator=(Vector<T>&& other)
|
|
{
|
|
if (&other == this) return *this;
|
|
|
|
if (m_data) free_impl(m_data);
|
|
|
|
m_data = other.data();
|
|
m_capacity = other.capacity();
|
|
m_size = other.size();
|
|
|
|
other.m_capacity = other.m_size = 0;
|
|
other.m_data = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
~Vector()
|
|
{
|
|
if (m_data) free_impl(m_data);
|
|
}
|
|
|
|
Result<void> try_reserve(usize capacity)
|
|
{
|
|
return resize(capacity);
|
|
}
|
|
|
|
void reserve(usize capacity)
|
|
{
|
|
resize(capacity).release_value();
|
|
}
|
|
|
|
Result<void> try_append(T&& item)
|
|
{
|
|
if (m_capacity == m_size) TRY(resize(m_capacity + 8));
|
|
|
|
new (&m_data[m_size]) T(move(item));
|
|
|
|
m_size++;
|
|
|
|
return {};
|
|
}
|
|
|
|
Result<void> try_append(const T& item)
|
|
{
|
|
return try_append(T(item));
|
|
}
|
|
|
|
Option<T> try_pop()
|
|
{
|
|
if (m_size == 0) return {};
|
|
|
|
m_size--;
|
|
|
|
return move(m_data[m_size]);
|
|
}
|
|
|
|
const T& operator[](usize index) const
|
|
{
|
|
check(index < m_size);
|
|
return m_data[m_size];
|
|
}
|
|
|
|
T& operator[](usize index)
|
|
{
|
|
check(index < m_size);
|
|
return m_data[m_size];
|
|
}
|
|
|
|
Iterator begin()
|
|
{
|
|
return m_data;
|
|
}
|
|
|
|
ConstIterator begin() const
|
|
{
|
|
return m_data;
|
|
}
|
|
|
|
Iterator end()
|
|
{
|
|
return m_data + m_size;
|
|
}
|
|
|
|
ConstIterator end() const
|
|
{
|
|
return m_data + m_size;
|
|
}
|
|
|
|
const T* data() const
|
|
{
|
|
return m_data;
|
|
}
|
|
|
|
T* data()
|
|
{
|
|
return m_data;
|
|
}
|
|
|
|
usize capacity() const
|
|
{
|
|
return m_capacity;
|
|
}
|
|
|
|
usize byte_capacity() const
|
|
{
|
|
return m_capacity * sizeof(T);
|
|
}
|
|
|
|
usize size() const
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
m_size = m_capacity = 0;
|
|
free_impl(m_data);
|
|
m_data = nullptr;
|
|
}
|
|
|
|
private:
|
|
T* m_data { nullptr };
|
|
usize m_capacity { 0 };
|
|
usize m_size { 0 };
|
|
|
|
Result<void> resize(usize new_capacity)
|
|
{
|
|
const usize new_byte_capacity = new_capacity * sizeof(T);
|
|
|
|
void* const ptr = TRY(realloc_impl(m_data, new_byte_capacity));
|
|
|
|
if (new_capacity < m_capacity) memcpy(ptr, m_data, new_byte_capacity);
|
|
else
|
|
memcpy(ptr, m_data, byte_capacity());
|
|
|
|
m_capacity = new_capacity;
|
|
m_data = (T*)ptr;
|
|
return {};
|
|
}
|
|
};
|