Daniele Bartolini 11 lat temu
rodzic
commit
210aa575d7

+ 4 - 1
engine/core/containers/container_types.h

@@ -61,7 +61,10 @@ struct Vector
 
 	const Vector<T>& operator=(const Vector<T>& other);
 
-	Array<T> _array;
+	Allocator* _allocator;
+	uint32_t _capacity;
+	uint32_t _size;
+	T* _array;
 };
 
 /// Circular buffer double-ended queue of POD items.

+ 107 - 69
engine/core/containers/vector.h

@@ -5,9 +5,10 @@
 
 #pragma once
 
-#include "types.h"
+#include "container_types.h"
+#include "allocator.h"
 #include "assert.h"
-#include "array.h"
+#include "macros.h"
 
 namespace crown
 {
@@ -75,186 +76,216 @@ namespace vector
 namespace vector
 {
 	template <typename T>
-	bool empty(const Vector<T>& v)
+	inline bool empty(const Vector<T>& v)
 	{
-		return array::empty(v._array);
+		return v._size == 0;
 	}
 
 	template <typename T>
-	uint32_t size(const Vector<T>& v)
+	inline uint32_t size(const Vector<T>& v)
 	{
-		return array::size(v._array);
+		return v._size;
 	}
 
 	template <typename T>
-	uint32_t capacity(const Vector<T>& v)
+	inline uint32_t capacity(const Vector<T>& v)
 	{
-		return array::capacity(v._array);
+		return v._capacity;
 	}
 
 	template <typename T>
-	void resize(Vector<T>& v, uint32_t size)
+	inline void resize(Vector<T>& v, uint32_t size)
 	{
-		array::resize(v._array, size);
+		if (size > v._capacity)
+			set_capacity(v, size);
+
+		v._size = size;
 	}
 
 	template <typename T>
-	void reserve(Vector<T>& v, uint32_t capacity)
+	inline void reserve(Vector<T>& v, uint32_t capacity)
 	{
-		array::reserve(v._array, capacity);
+		if (capacity > v._capacity)
+			grow(v, capacity);
 	}
 
 	template <typename T>
-	void set_capacity(Vector<T>& v, uint32_t capacity)
+	inline void set_capacity(Vector<T>& v, uint32_t capacity)
 	{
-		if (capacity == v._array._capacity)
+		if (capacity == v._capacity)
 			return;
 
-		if (capacity < v._array._size)
+		if (capacity < v._size)
 			resize(v, capacity);
 
 		if (capacity > 0)
 		{
-			Array<T> arr = v._array;
-
-			T* tmp = arr._array;
-			arr._capacity = capacity;
-
-			arr._array = (T*)arr._allocator->allocate(capacity * sizeof(T));
+			T* tmp = v._array;
+			v._capacity = capacity;
+			v._array = (T*)v._allocator->allocate(capacity * sizeof(T), CE_ALIGNOF(T));
 
-			for (uint32_t i = 0; i < arr._size; i++)
+			for (uint32_t i = 0; i < v._size; i++)
 			{
-				new (arr._array + i) T(tmp[i]);
+				new (v._array + i) T(tmp[i]);
 			}
 
 			if (tmp)
 			{
-				for (uint32_t i = 0; i < arr._size; i++)
+				for (uint32_t i = 0; i < v._size; i++)
 				{
 					tmp[i].~T();
 				}
-				arr._allocator->deallocate(tmp);
+				v._allocator->deallocate(tmp);
 			}
 		}
 	}
 
 	template <typename T>
-	void grow(Vector<T>& v, uint32_t min_capacity)
+	inline void grow(Vector<T>& v, uint32_t min_capacity)
 	{
-		return array::grow(v._array, min_capacity);
+		uint32_t new_capacity = v._capacity * 2 + 1;
+
+		if (new_capacity < min_capacity)
+			new_capacity = min_capacity;
+
+		set_capacity(v, new_capacity);
 	}
 
 	template <typename T>
-	void condense(Vector<T>& v)
+	inline void condense(Vector<T>& v)
 	{
-		return array::condense(v._array);
+		resize(v, v._size);
 	}
 
 	template <typename T>
-	uint32_t push_back(Vector<T>& v, const T& item)
+	inline uint32_t push_back(Vector<T>& v, const T& item)
 	{
-		if (v._array._capacity == v._array._size)
+		if (v._capacity == v._size)
 			grow(v, 0);
 
-		new (v._array._array + v._array._size) T(item);
+		new (v._array + v._size) T(item);
 
-		return v._array._size++;
+		return v._size++;
 	}
 
 	template <typename T>
-	void pop_back(Vector<T>& v)
+	inline void pop_back(Vector<T>& v)
 	{
-		CE_ASSERT(vector::size(v) > 0, "The vector is empty");
+		CE_ASSERT(v._size > 0, "The vector is empty");
 
-		v._array._array[v._array._size - 1].~T();
-		v._array._size--;
+		v._array[v._size - 1].~T();
+		--v._size;
 	}
 
 	template <typename T>
-	uint32_t push(Vector<T>& v, const T* items, uint32_t count)
+	inline uint32_t push(Vector<T>& v, const T* items, uint32_t count)
 	{
-		if (v._array._capacity <= v._array._size + count)
-			grow(v, v._array._size + count);
+		if (v._capacity <= v._size + count)
+			grow(v, v._size + count);
 
-		T* arr = &v._array._array[v._array._size];
+		T* arr = &v._array[v._size];
 		for (uint32_t i = 0; i < count; i++)
 		{
 			arr[i] = items[i];
 		}
 
-		v._array._size += count;
-		return v._array._size;
+		v._size += count;
+		return v._size;
 	}
 
 	template <typename T>
-	void clear(Vector<T>& v)
+	inline void clear(Vector<T>& v)
 	{
-		for (uint32_t i = 0; i < v._array._size; i++)
+		for (uint32_t i = 0; i < v._size; i++)
 		{
-			v._array._array[i].~T();
+			v._array[i].~T();
 		}
 
-		v._array._size = 0;
+		v._size = 0;
 	}
 
 	template <typename T>
-	T* begin(Vector<T>& v)
+	inline T* begin(Vector<T>& v)
 	{
-		return array::begin(v._array);
+		return v._array;
 	}
+
 	template <typename T>
-	const T* begin(const Vector<T>& v)
+	inline const T* begin(const Vector<T>& v)
 	{
-		return array::begin(v._array);
+		return v._array;
 	}
+
 	template <typename T>
-	T* end(Vector<T>& v)
+	inline T* end(Vector<T>& v)
 	{
-		return array::end(v._array);
+		return v._array + v._size;
 	}
+
 	template <typename T>
-	const T* end(const Vector<T>& v)
+	inline const T* end(const Vector<T>& v)
 	{
-		return array::end(v._array);
+		return v._array + v._size;
 	}
 
 	template <typename T>
-	T& front(Vector<T>& v)
+	inline T& front(Vector<T>& v)
 	{
-		return array::front(v._array);
+		CE_ASSERT(v._size > 0, "The vector is empty");
+
+		return v._array[0];
 	}
+
 	template <typename T>
-	const T& front(const Vector<T>& v)
+	inline const T& front(const Vector<T>& v)
 	{
-		return array::front(v._array);
+		CE_ASSERT(v._size > 0, "The vector is empty");
+
+		return v._array[0];
 	}
+
 	template <typename T>
-	T& back(Vector<T>& v)
+	inline T& back(Vector<T>& v)
 	{
-		return array::back(v._array);
+		CE_ASSERT(v._size > 0, "The vector is empty");
+
+		return v._array[v._size - 1];
 	}
+
 	template <typename T>
-	const T& back(const Vector<T>& v)
+	inline const T& back(const Vector<T>& v)
 	{
-		return array::back(v._array);
+		CE_ASSERT(v._size > 0, "The vector is empty");
+
+		return v._array[v._size - 1];
 	}
 } // namespace vector
 
 template <typename T>
-inline Vector<T>::Vector(Allocator& allocator)
-	: _array(allocator)
+inline Vector<T>::Vector(Allocator& a)
+	: _allocator(&a)
+	, _capacity(0)
+	, _size(0)
+	, _array(NULL)
 {
 }
 
 template <typename T>
-inline Vector<T>::Vector(Allocator& allocator, uint32_t capacity)
-	: _array(allocator)
+inline Vector<T>::Vector(Allocator& a, uint32_t capacity)
+	: _allocator(&a)
+	, _capacity(0)
+	, _size(0)
+	, _array(NULL)
 {
+	vector::resize(*this, capacity);
 }
 
 template <typename T>
 inline Vector<T>::Vector(const Vector<T>& other)
-	: _array(other._array)
+	: _allocator(other._allocator)
+	, _capacity(0)
+	, _size(0)
+	, _array(NULL)
 {
 	*this = other;
 }
@@ -262,21 +293,28 @@ inline Vector<T>::Vector(const Vector<T>& other)
 template <typename T>
 inline Vector<T>::~Vector()
 {
-	for (uint32_t i = 0; i < array::size(_array); i++)
+	for (uint32_t i = 0; i < _size; i++)
 	{
 		_array[i].~T();
 	}
+
+	if (_array)
+		_allocator->deallocate(_array);
 }
 
 template <typename T>
 inline T& Vector<T>::operator[](uint32_t index)
 {
+	CE_ASSERT(index < _size, "Index out of bounds");
+
 	return _array[index];
 }
 
 template <typename T>
 inline const T& Vector<T>::operator[](uint32_t index) const
 {
+	CE_ASSERT(index < _size, "Index out of bounds");
+
 	return _array[index];
 }