Просмотр исходного кода

Port Array (List), Queue and PriorityQueue to NMFPS (see issue #35). Also add Hash from bitsquid.

Daniele Bartolini 12 лет назад
Родитель
Сommit
867cd1d878
49 измененных файлов с 1478 добавлено и 1188 удалено
  1. 9 7
      engine/CMakeLists.txt
  2. 8 8
      engine/ConsoleServer.cpp
  3. 1 1
      engine/ConsoleServer.h
  4. 1 1
      engine/Crown.h
  5. 4 4
      engine/audio/backend/ALSoundWorld.cpp
  6. 1 1
      engine/audio/backend/SLESSoundWorld.cpp
  7. 1 1
      engine/core/Profiler.h
  8. 336 0
      engine/core/containers/Array.h
  9. 106 0
      engine/core/containers/ContainerTypes.h
  10. 23 26
      engine/core/containers/EventStream.h
  11. 366 0
      engine/core/containers/Hash.h
  12. 1 1
      engine/core/containers/IdArray.h
  13. 0 391
      engine/core/containers/List.h
  14. 36 140
      engine/core/containers/PriorityQueue.h
  15. 199 224
      engine/core/containers/Queue.h
  16. 1 1
      engine/core/containers/Vector.h
  17. 5 5
      engine/core/filesystem/NetworkFile.cpp
  18. 4 4
      engine/core/filesystem/NetworkFilesystem.h
  19. 15 15
      engine/core/json/JSON.cpp
  20. 2 2
      engine/core/json/JSON.h
  21. 44 44
      engine/core/json/JSONParser.cpp
  22. 13 13
      engine/core/json/JSONParser.h
  23. 16 16
      engine/core/strings/DynamicString.h
  24. 3 3
      engine/core/strings/Path.h
  25. 7 7
      engine/core/strings/StringStream.h
  26. 2 2
      engine/lua/LuaPhysicsWorld.cpp
  27. 4 4
      engine/lua/LuaRaycast.cpp
  28. 2 2
      engine/physics/PhysicsWorld.cpp
  29. 1 1
      engine/physics/PhysicsWorld.h
  30. 2 2
      engine/physics/Raycast.cpp
  31. 1 1
      engine/physics/Raycast.h
  32. 1 1
      engine/renderers/RenderWorld.h
  33. 5 5
      engine/resource/FontResource.cpp
  34. 35 35
      engine/resource/GuiResource.cpp
  35. 1 1
      engine/resource/GuiResource.h
  36. 4 4
      engine/resource/MaterialResource.cpp
  37. 20 20
      engine/resource/MeshResource.cpp
  38. 50 50
      engine/resource/PackageResource.cpp
  39. 65 65
      engine/resource/PhysicsResource.cpp
  40. 5 4
      engine/resource/ResourceLoader.cpp
  41. 1 2
      engine/resource/ResourceLoader.h
  42. 11 10
      engine/resource/ResourceManager.cpp
  43. 2 2
      engine/resource/ResourceManager.h
  44. 26 25
      engine/resource/SpriteResource.cpp
  45. 1 1
      engine/resource/SpriteResource.h
  46. 28 28
      engine/resource/UnitResource.cpp
  47. 1 1
      engine/tests/containers.cpp
  48. 6 5
      engine/world/SceneGraphManager.cpp
  49. 2 2
      engine/world/SceneGraphManager.h

+ 9 - 7
engine/CMakeLists.txt

@@ -131,15 +131,17 @@ set (CONTAINERS_SRC
 )
 
 set (CONTAINERS_HEADERS
-	core/containers/Queue.h
-	core/containers/PriorityQueue.h
+	core/containers/Array.h
+	core/containers/ContainerTypes.h
+	core/containers/EventStream.h
+	core/containers/Hash.h
+	core/containers/IdArray.h
+	core/containers/IdTable.h
 	core/containers/Map.h
-	core/containers/List.h
-	core/containers/Vector.h
+	core/containers/PriorityQueue.h
+	core/containers/Queue.h
 	core/containers/RBTree.h
-	core/containers/IdTable.h
-	core/containers/IdArray.h
-	core/containers/EventStream.h
+	core/containers/Vector.h
 )
 
 set (MATH_SRC

+ 8 - 8
engine/ConsoleServer.cpp

@@ -136,17 +136,17 @@ void ConsoleServer::update()
 	}
 
 	TempAllocator256 alloc;
-	List<Id> to_remove(alloc);
+	Array<Id> to_remove(alloc);
 
 	// Update all clients
 	for (uint32_t i = 0; i < m_clients.size(); i++)
 	{
 		ReadResult rr = update_client(m_clients[i].socket);
-		if (rr.error != ReadResult::NO_ERROR) to_remove.push_back(m_clients[i].id);
+		if (rr.error != ReadResult::NO_ERROR) array::push_back(to_remove, m_clients[i].id);
 	}
 
 	// Remove clients
-	for (uint32_t i = 0; i < to_remove.size(); i++)
+	for (uint32_t i = 0; i < array::size(to_remove); i++)
 	{
 		m_clients.lookup(to_remove[i]).socket.close();
 		m_clients.destroy(to_remove[i]);
@@ -174,15 +174,15 @@ ReadResult ConsoleServer::update_client(TCPSocket client)
 	if (rr.error != ReadResult::NO_ERROR) return rr;
 
 	// Else read the message
-	List<char> msg_buf(default_allocator());
-	msg_buf.resize(msg_len);
-	ReadResult msg_result = client.read(msg_buf.begin(), msg_len);
-	msg_buf.push_back('\0');
+	Array<char> msg_buf(default_allocator());
+	array::resize(msg_buf, msg_len);
+	ReadResult msg_result = client.read(array::begin(msg_buf), msg_len);
+	array::push_back(msg_buf, '\0');
 
 	if (msg_result.error == ReadResult::REMOTE_CLOSED) return msg_result;
 	if (msg_result.error != ReadResult::NO_ERROR) return msg_result;
 
-	process(client, msg_buf.begin());
+	process(client, array::begin(msg_buf));
 	return msg_result;
 }
 

+ 1 - 1
engine/ConsoleServer.h

@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "OsSocket.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Queue.h"
 #include "IdArray.h"
 #include "Log.h"

+ 1 - 1
engine/Crown.h

@@ -57,7 +57,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 // Core/Containers
 #include "Map.h"
 #include "RBTree.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Vector.h"
 #include "Queue.h"
 #include "PriorityQueue.h"

+ 4 - 4
engine/audio/backend/ALSoundWorld.cpp

@@ -36,7 +36,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Device.h"
 #include "ResourceManager.h"
 #include "SoundResource.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "TempAllocator.h"
 
 namespace crown
@@ -337,7 +337,7 @@ public:
 	virtual void update()
 	{
 		TempAllocator256 alloc;
-		List<SoundInstanceId> to_delete(alloc);
+		Array<SoundInstanceId> to_delete(alloc);
 
 		// Check what sounds finished playing
 		for (uint32_t i = 0; i < m_playing_sounds.size(); i++)
@@ -345,12 +345,12 @@ public:
 			SoundInstance& instance = m_playing_sounds[i];
 			if (instance.finished())
 			{
-				to_delete.push_back(instance.m_id);
+				array::push_back(to_delete, instance.m_id);
 			}
 		}
 
 		// Destroy instances which finished playing
-		for (uint32_t i = 0; i < to_delete.size(); i++)
+		for (uint32_t i = 0; i < array::size(to_delete); i++)
 		{
 			stop(to_delete[i]);
 		}

+ 1 - 1
engine/audio/backend/SLESSoundWorld.cpp

@@ -36,7 +36,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Device.h"
 #include "ResourceManager.h"
 #include "SoundResource.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "TempAllocator.h"
 #include "Queue.h"
 

+ 1 - 1
engine/core/Profiler.h

@@ -72,7 +72,7 @@ namespace profiler
 		double time;
 	};
 
-	static List<char> g_buffer(default_allocator());
+	static Array<char> g_buffer(default_allocator());
 	static Mutex g_buffer_mutex;
 
 	#define THREAD_BUFFER_SIZE 1024

+ 336 - 0
engine/core/containers/Array.h

@@ -0,0 +1,336 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include <cstring>
+#include "Assert.h"
+#include "ContainerTypes.h"
+
+namespace crown
+{
+namespace array
+{
+	/// Returns whether the list is empty
+	template <typename T> bool empty(const Array<T>& a);
+
+	/// Returns the number of items in the list
+	template <typename T> uint32_t size(const Array<T>& a);
+
+	/// Returns the maximum number of items the array can hold
+	template <typename T> uint32_t capacity(const Array<T>& a);
+
+	/// Resizes the list to the given @a size.
+	/// @note
+	/// Old items will be copied to the newly created list.
+	/// If the new capacity is smaller than the previous one, the
+	/// list will be truncated.
+	template <typename T> void resize(Array<T>& a, uint32_t size);
+
+	/// Reserves space in the list for at least @a capacity items.
+	template <typename T> void reserve(uint32_t capacity);
+
+	/// Sets the list capacity
+	template <typename T> void set_capacity(Array<T>& a, uint32_t capacity);
+
+	/// Grows the list to contain at least @a min_capacity items
+	template <typename T> void grow(Array<T>& a, uint32_t min_capacity);
+
+	/// Condenses the array so that the capacity matches the actual number
+	/// of items in the list.
+	template <typename T> void condense(Array<T>& a);
+
+	/// Appends an item to the list and returns its index.
+	template <typename T> uint32_t push_back(Array<T>& a, const T& item);
+
+	/// Removes the last item from the list.
+	template <typename T> void pop_back(Array<T>& a);
+
+	/// Appends @a count @a items to the list and returns the number
+	/// of items in the list after the append operation.
+	template <typename T> uint32_t push(Array<T>& a, const T* items, uint32_t count);
+
+	/// Clears the content of the list.
+	/// @note
+	/// Does not free memory nor call destructors, it only zeroes
+	/// the number of items in the list for efficiency.
+	template <typename T> void clear(Array<T>& a);
+
+	/// Copies the content of the @a other list into this one.
+
+
+	template <typename T> T* begin(Array<T>& a);
+	template <typename T> const T* begin(const Array<T>& a);
+	template <typename T> T* end(Array<T>& a);
+	template <typename T> const T* end(const Array<T>& a);
+
+	template <typename T> T& front(Array<T>& a);
+	template <typename T> const T& front(const Array<T>& a);
+	template <typename T> T& back(Array<T>& a);
+	template <typename T> const T& back(const Array<T>& a);
+} // namespace array
+
+namespace array
+{
+	template <typename T>
+	inline bool empty(const Array<T>& a)
+	{
+		return a.m_size == 0;
+	}
+
+	template <typename T>
+	inline uint32_t size(const Array<T>& a)
+	{
+		return a.m_size;
+	}
+
+	template <typename T>
+	inline uint32_t capacity(const Array<T>& a)
+	{
+		return a.m_capacity;
+	}
+
+	template <typename T>
+	inline void resize(Array<T>& a, uint32_t size)
+	{
+		if (size > a.m_capacity)
+		{
+			set_capacity(a, size);
+		}
+
+		a.m_size = size;
+	}
+
+	template <typename T>
+	inline void reserve(Array<T>& a, uint32_t capacity)
+	{
+		if (capacity > a.m_capacity)
+		{
+			grow(a, capacity);
+		}
+	}
+
+	template <typename T>
+	inline void set_capacity(Array<T>& a, uint32_t capacity)
+	{
+		if (capacity == a.m_capacity)
+		{
+			return;
+		}
+
+		if (capacity < a.m_size)
+		{
+			resize(a, capacity);
+		}
+
+		if (capacity > 0)
+		{
+			T* tmp = a.m_array;
+			a.m_capacity = capacity;
+
+			a.m_array = (T*)a.m_allocator->allocate(capacity * sizeof(T), CE_ALIGNOF(T));
+
+			memcpy(a.m_array, tmp, a.m_size * sizeof(T));
+
+			if (tmp)
+			{
+				a.m_allocator->deallocate(tmp);
+			}
+		}
+	}
+
+	template <typename T>
+	inline void grow(Array<T>& a, uint32_t min_capacity)
+	{
+		uint32_t new_capacity = a.m_capacity * 2 + 1;
+
+		if (new_capacity < min_capacity)
+		{
+			new_capacity = min_capacity;
+		}
+
+		set_capacity(a, new_capacity);
+	}
+
+	template <typename T>
+	inline void condense(Array<T>& a)
+	{
+		resize(a, a.m_size);
+	}
+
+	template <typename T>
+	inline uint32_t push_back(Array<T>& a, const T& item)
+	{
+		if (a.m_capacity == a.m_size)
+		{
+			grow(a, 0);
+		}
+
+		a.m_array[a.m_size] = item;
+
+		return 	a.m_size++;
+	}
+
+	template <typename T>
+	inline void pop_back(Array<T>& a)
+	{
+		CE_ASSERT(a.m_size > 0, "The list is empty");
+
+		a.m_size--;
+	}
+
+	template <typename T>
+	inline uint32_t push(Array<T>& a, const T* items, uint32_t count)
+	{
+		if (a.m_capacity <= a.m_size + count)
+		{
+			grow(a, a.m_size + count);
+		}
+
+		memcpy(&a.m_array[a.m_size], items, sizeof(T) * count);
+		a.m_size += count;
+
+		return a.m_size;
+	}
+
+	template <typename T>
+	inline void clear(Array<T>& a)
+	{
+		a.m_size = 0;
+	}
+
+	template <typename T>
+	inline const T* begin(const Array<T>& a)
+	{
+		return a.m_array;
+	}
+
+	template <typename T>
+	inline T* begin(Array<T>& a)
+	{
+		return a.m_array;
+	}
+
+	template <typename T>
+	inline const T* end(const Array<T>& a)
+	{
+		return a.m_array + a.m_size;
+	}
+
+	template <typename T>
+	inline T* end(Array<T>& a)
+	{
+		return a.m_array + a.m_size;
+	}
+
+	template <typename T>
+	inline T& front(Array<T>& a)
+	{
+		CE_ASSERT(a.m_size > 0, "The list is empty");
+
+		return a.m_array[0];
+	}
+
+	template <typename T>
+	inline const T& front(const Array<T>& a)
+	{
+		CE_ASSERT(a.m_size > 0, "The list is empty");
+
+		return a.m_array[0];
+	}
+
+	template <typename T>
+	inline T& back(Array<T>& a)
+	{
+		CE_ASSERT(a.m_size > 0, "The list is empty");
+
+		return a.m_array[a.m_size - 1];
+	}
+
+	template <typename T>
+	inline const T& back(const Array<T>& a)
+	{
+		CE_ASSERT(a.m_size > 0, "The list is empty");
+
+		return a.m_array[a.m_size - 1];
+	}
+} // namespace array
+
+template <typename T>
+inline Array<T>::Array(Allocator& allocator)
+	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
+{
+}
+
+template <typename T>
+inline Array<T>::Array(Allocator& allocator, uint32_t capacity)
+	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
+{
+	array::resize(*this, capacity);
+}
+
+template <typename T>
+inline Array<T>::Array(const Array<T>& other)
+	: m_allocator(other.m_allocator), m_capacity(0), m_size(0), m_array(NULL)
+{
+	*this = other;
+}
+
+template <typename T>
+inline Array<T>::~Array()
+{
+	if (m_array)
+	{
+		m_allocator->deallocate(m_array);
+	}
+}
+
+template <typename T>
+inline T& Array<T>::operator[](uint32_t index)
+{
+	CE_ASSERT(index < m_size, "Index out of bounds");
+
+	return m_array[index];
+}
+
+template <typename T>
+inline const T& Array<T>::operator[](uint32_t index) const
+{
+	CE_ASSERT(index < m_size, "Index out of bounds");
+
+	return m_array[index];
+}
+
+template <typename T>
+inline Array<T>& Array<T>::operator=(const Array<T>& other)
+{
+	const uint32_t size = other.m_size;
+	array::resize(*this, size);
+	memcpy(m_array, other.m_array, sizeof(T) * size);
+	return *this;
+}
+
+} // namespace crown

+ 106 - 0
engine/core/containers/ContainerTypes.h

@@ -0,0 +1,106 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Types.h"
+#include "Allocator.h"
+
+namespace crown
+{
+
+/// Dynamic array of POD items.
+/// @note
+/// Does not call constructors/destructors so it is not very suitable for non-POD items.
+template <typename T>
+struct Array
+{
+	Array(Allocator& allocator);
+
+	/// Allocates capacity * sizeof(T) bytes.
+	Array(Allocator& allocator, uint32_t capacity);
+	Array(const Array<T>& other);
+	~Array();
+
+	/// Random access by index
+	T& operator[](uint32_t index);
+	const T& operator[](uint32_t index) const;
+
+	Array<T>& operator=(const Array<T>& other);
+
+	Allocator* m_allocator;
+	uint32_t m_capacity;
+	uint32_t m_size;
+	T* m_array;
+};
+
+/// Circular buffer double-ended queue of POD items.
+/// @note
+/// Does not call constructors/destructors so it is not very suitable for non-POD items.
+template <typename T>
+struct Queue
+{
+	Queue(Allocator& allocator);
+
+	/// Random access by index
+	T& operator[](uint32_t index);
+
+	/// Random access by index
+	const T& operator[](uint32_t index) const;
+
+	uint32_t m_read;
+	uint32_t m_size;
+	Array<T> m_queue;
+};
+
+/// Priority queue of POD items.
+template <typename T>
+struct PriorityQueue
+{
+	PriorityQueue(Allocator& a);
+
+	Array<T> m_queue;
+};
+
+/// Hash from an uint64_t to POD items. If you want to use a generic key
+/// item, use a hash function to map that item to an uint64_t.
+template<typename T>
+struct Hash
+{
+	Hash(Allocator &a);
+	
+	struct Entry
+	{
+		uint64_t key;
+		uint32_t next;
+		T value;
+	};
+
+	Array<uint32_t> _hash;
+	Array<Entry> _data;
+};
+
+} // namespace crown

+ 23 - 26
engine/core/containers/EventStream.h

@@ -27,42 +27,39 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Assert.h"
-#include "Allocator.h"
-#include "List.h"
+#include "Array.h"
 
 namespace crown
 {
 
-typedef List<char> EventStream;
+typedef Array<char> EventStream;
 
-/// Functions for operating on a List<char> as a stream of events of the form:
+/// Functions for operating on a Array<char> as a stream of events of the form:
 /// [event_header_0][event_data_0][event_header_1][event_data_1] ...
 namespace event_stream
 {
+	struct Header
+	{
+		uint32_t type;
+		uint32_t size;
+	};
 
-struct Header
-{
-	uint32_t type;
-	uint32_t size;
-};
-
-/// Appends the @a event of the given @a type and @a size to the stream @a s. 
-inline void write(EventStream& s, uint32_t type, uint32_t size, const void* event)
-{
-	Header header;
-	header.type = type;
-	header.size = size;
+	/// Appends the @a event of the given @a type and @a size to the stream @a s. 
+	inline void write(EventStream& s, uint32_t type, uint32_t size, const void* event)
+	{
+		Header header;
+		header.type = type;
+		header.size = size;
 
-	s.push((char*) &header, sizeof(Header));
-	s.push((char*) event, (size_t) size);
-}
-
-/// Appends the @a event of the given @a type to the stream @a s
-template <typename T>
-inline void write(EventStream& s, uint32_t type, const T& event)
-{
-	event_stream::write(s, type, sizeof(T), &event);
-}
+		array::push(s, (char*) &header, sizeof(Header));
+		array::push(s, (char*) event, (size_t) size);
+	}
 
+	/// Appends the @a event of the given @a type to the stream @a s
+	template <typename T>
+	inline void write(EventStream& s, uint32_t type, const T& event)
+	{
+		event_stream::write(s, type, sizeof(T), &event);
+	}
 } // namespace event_stream
 } // namespace crown

+ 366 - 0
engine/core/containers/Hash.h

@@ -0,0 +1,366 @@
+/*
+Copyright (C) 2012 Bitsquid AB
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include "Array.h"
+#include "ContainerTypes.h"
+
+namespace crown {
+
+	/// The hash function stores its data in a "list-in-an-array" where
+	/// indices are used instead of pointers. 
+	///
+	/// When items are removed, the array-list is repacked to always keep
+	/// it tightly ordered.
+	namespace hash
+	{
+		/// Returns true if the specified key exists in the hash.
+		template<typename T> bool has(const Hash<T> &h, uint64_t key);
+
+		/// Returns the value stored for the specified key, or deffault if the key
+		/// does not exist in the hash.
+		template<typename T> const T &get(const Hash<T> &h, uint64_t key, const T &deffault);
+
+		/// Sets the value for the key.
+		template<typename T> void set(Hash<T> &h, uint64_t key, const T &value);
+
+		/// Removes the key from the hash if it exists.
+		template<typename T> void remove(Hash<T> &h, uint64_t key);
+
+		/// Resizes the hash lookup table to the specified size.
+		/// (The table will grow automatically when 70 % full.)
+		template<typename T> void reserve(Hash<T> &h, uint32_t size);
+
+		/// Remove all elements from the hash.
+		template<typename T> void clear(Hash<T> &h);
+
+		/// Returns a pointer to the first entry in the hash table, can be used to
+		/// efficiently iterate over the elements (in random order).
+		template<typename T> const typename Hash<T>::Entry *begin(const Hash<T> &h);
+		template<typename T> const typename Hash<T>::Entry *end(const Hash<T> &h);
+	}
+
+	namespace multi_hash
+	{
+		/// Finds the first entry with the specified key.
+		template<typename T> const typename Hash<T>::Entry *find_first(const Hash<T> &h, uint64_t key);
+
+		/// Finds the next entry with the same key as e.
+		template<typename T> const typename Hash<T>::Entry *find_next(const Hash<T> &h, const typename Hash<T>::Entry *e);
+
+		/// Returns the number of entries with the key.
+		template<typename T> uint32_t count(const Hash<T> &h, uint64_t key);
+
+		/// Returns all the entries with the specified key.
+		/// Use a TempAllocator for the array to avoid allocating memory.
+		template<typename T> void get(const Hash<T> &h, uint64_t key, Array<T> &items);
+
+		/// Inserts the value as an aditional value for the key.
+		template<typename T> void insert(Hash<T> &h, uint64_t key, const T &value);
+
+		/// Removes the specified entry.
+		template<typename T> void remove(Hash<T> &h, const typename Hash<T>::Entry *e);
+
+		/// Removes all entries with the specified key.
+		template<typename T> void remove_all(Hash<T> &h, uint64_t key);
+	}
+
+	namespace hash_internal
+	{
+		const uint32_t END_OF_LIST = 0xffffffffu;
+		
+		struct FindResult
+		{
+			uint32_t hash_i;
+			uint32_t data_prev;
+			uint32_t data_i;
+		};	
+
+		template<typename T> uint32_t add_entry(Hash<T> &h, uint64_t key)
+		{
+			typename Hash<T>::Entry e;
+			e.key = key;
+			e.next = END_OF_LIST;
+			uint32_t ei = array::size(h._data);
+			array::push_back(h._data, e);
+			return ei;
+		}
+
+		template<typename T> void erase(Hash<T> &h, const FindResult &fr)
+		{
+			if (fr.data_prev == END_OF_LIST)
+				h._hash[fr.hash_i] = h._data[fr.data_i].next;
+			else
+				h._data[fr.data_prev].next = h._data[fr.data_i].next;
+
+			if (fr.data_i == array::size(h._data) - 1) {
+				array::pop_back(h._data);
+				return;
+			}
+
+			h._data[fr.data_i] = h._data[array::size(h._data) - 1];
+			FindResult last = find(h, h._data[fr.data_i].key);
+
+			if (last.data_prev != END_OF_LIST)
+				h._data[last.data_prev].next = fr.data_i;
+			else
+				h._hash[last.hash_i] = fr.data_i;
+		}
+
+		template<typename T> FindResult find(const Hash<T> &h, uint64_t key)
+		{
+			FindResult fr;
+			fr.hash_i = END_OF_LIST;
+			fr.data_prev = END_OF_LIST;
+			fr.data_i = END_OF_LIST;
+
+			if (array::size(h._hash) == 0)
+				return fr;
+
+			fr.hash_i = key % array::size(h._hash);
+			fr.data_i = h._hash[fr.hash_i];
+			while (fr.data_i != END_OF_LIST) {
+				if (h._data[fr.data_i].key == key)
+					return fr;
+				fr.data_prev = fr.data_i;
+				fr.data_i = h._data[fr.data_i].next;
+			}
+			return fr;
+		}
+
+		template<typename T> FindResult find(const Hash<T> &h, const typename Hash<T>::Entry *e)
+		{
+			FindResult fr;
+			fr.hash_i = END_OF_LIST;
+			fr.data_prev = END_OF_LIST;
+			fr.data_i = END_OF_LIST;
+
+			if (array::size(h._hash) == 0)
+				return fr;
+
+			fr.hash_i = e->key % array::size(h._hash);
+			fr.data_i = h._hash[fr.hash_i];
+			while (fr.data_i != END_OF_LIST) {
+				if (&h._data[fr.data_i] == e)
+					return fr;
+				fr.data_prev = fr.data_i;
+				fr.data_i = h._data[fr.data_i].next;
+			}
+			return fr;
+		}
+
+		template<typename T> uint32_t find_or_fail(const Hash<T> &h, uint64_t key)
+		{
+			return find(h, key).data_i;
+		}
+
+		template<typename T> uint32_t find_or_make(Hash<T> &h, uint64_t key)
+		{
+			const FindResult fr = find(h, key);
+			if (fr.data_i != END_OF_LIST)
+				return fr.data_i;
+
+			uint32_t i = add_entry(h, key);
+			if (fr.data_prev == END_OF_LIST)
+				h._hash[fr.hash_i] = i;
+			else
+				h._data[fr.data_prev].next = i;
+			return i;
+		}
+
+		template<typename T> uint32_t make(Hash<T> &h, uint64_t key)
+		{
+			const FindResult fr = find(h, key);
+			const uint32_t i = add_entry(h, key);
+
+			if (fr.data_prev == END_OF_LIST)
+				h._hash[fr.hash_i] = i;
+			else
+				h._data[fr.data_prev].next = i;
+
+			h._data[i].next = fr.data_i;
+			return i;
+		}	
+
+		template<typename T> void find_and_erase(Hash<T> &h, uint64_t key)
+		{
+			const FindResult fr = find(h, key);
+			if (fr.data_i != END_OF_LIST)
+				erase(h, fr);
+		}
+
+		template<typename T> void rehash(Hash<T> &h, uint32_t new_size)
+		{
+			Hash<T> nh(*h._hash._allocator);
+			array::resize(nh._hash, new_size);
+			array::reserve(nh._data, array::size(h._data));
+			for (uint32_t i=0; i<new_size; ++i)
+				nh._hash[i] = END_OF_LIST;
+			for (uint32_t i=0; i<array::size(h._data); ++i) {
+				const typename Hash<T>::Entry &e = h._data[i];
+				multi_hash::insert(nh, e.key, e.value);
+			}
+
+			Hash<T> empty(*h._hash._allocator);
+			h.~Hash<T>();
+			memcpy(&h, &nh, sizeof(Hash<T>));
+			memcpy(&nh, &empty, sizeof(Hash<T>));
+		}
+
+		template<typename T> bool full(const Hash<T> &h)
+		{
+			const float max_load_factor = 0.7f;
+			return array::size(h._data) >= array::size(h._hash) * max_load_factor;
+		}
+
+		template<typename T> void grow(Hash<T> &h)
+		{
+			const uint32_t new_size = array::size(h._data) * 2 + 10;
+			rehash(h, new_size);
+		}
+	}
+
+	namespace hash
+	{
+		template<typename T> bool has(const Hash<T> &h, uint64_t key)
+		{
+			return hash_internal::find_or_fail(h, key) != hash_internal::END_OF_LIST;
+		}
+
+		template<typename T> const T &get(const Hash<T> &h, uint64_t key, const T &deffault)
+		{
+			const uint32_t i = hash_internal::find_or_fail(h, key);
+			return i == hash_internal::END_OF_LIST ? deffault : h._data[i].value;
+		}
+
+		template<typename T> void set(Hash<T> &h, uint64_t key, const T &value)
+		{
+			if (array::size(h._hash) == 0)
+				hash_internal::grow(h);
+
+			const uint32_t i = hash_internal::find_or_make(h, key);
+			h._data[i].value = value;
+			if (hash_internal::full(h))
+				hash_internal::grow(h);
+		}
+
+		template<typename T> void remove(Hash<T> &h, uint64_t key)
+		{
+			hash_internal::find_and_erase(h, key);
+		}
+
+		template<typename T> void reserve(Hash<T> &h, uint32_t size)
+		{
+			hash_internal::rehash(h, size);
+		}
+
+		template<typename T> void clear(Hash<T> &h)
+		{
+			array::clear(h._data);
+			array::clear(h._hash);
+		}
+
+		template<typename T> const typename Hash<T>::Entry *begin(const Hash<T> &h)
+		{
+			return array::begin(h._data);
+		}
+
+		template<typename T> const typename Hash<T>::Entry *end(const Hash<T> &h)
+		{
+			return array::end(h._data);
+		}
+	}
+
+	namespace multi_hash
+	{
+		template<typename T> const typename Hash<T>::Entry *find_first(const Hash<T> &h, uint64_t key)
+		{
+			const uint32_t i = hash_internal::find_or_fail(h, key);
+			return i == hash_internal::END_OF_LIST ? 0 : &h._data[i];
+		}
+
+		template<typename T> const typename Hash<T>::Entry *find_next(const Hash<T> &h, const typename Hash<T>::Entry *e)
+		{
+			uint32_t i = e->next;
+			while (i != hash_internal::END_OF_LIST) {
+				if (h._data[i].key == e->key)
+					return &h._data[i];
+				i = h._data[i].next;
+			}
+			return 0;
+		}
+
+		template<typename T> uint32_t count(const Hash<T> &h, uint64_t key)
+		{
+			uint32_t i = 0;
+			const typename Hash<T>::Entry *e = find_first(h, key);
+			while (e) {
+				++i;
+				e = find_next(h, e);
+			}
+			return i;
+		}
+
+		template<typename T> void get(const Hash<T> &h, uint64_t key, Array<T> &items)
+		{
+			const typename Hash<T>::Entry *e = find_first(h, key);
+			while (e) {
+				array::push_back(items, e->value);
+				e = find_next(h, e);
+			}
+		}
+
+		template<typename T> void insert(Hash<T> &h, uint64_t key, const T &value)
+		{
+			if (array::size(h._hash) == 0)
+				hash_internal::grow(h);
+
+			const uint32_t i = hash_internal::make(h, key);
+			h._data[i].value = value;
+			if (hash_internal::full(h))
+				hash_internal::grow(h);
+		}
+
+		template<typename T> void remove(Hash<T> &h, const typename Hash<T>::Entry *e)
+		{
+			const hash_internal::FindResult fr = hash_internal::find(h, e);
+			if (fr.data_i != hash_internal::END_OF_LIST)
+				hash_internal::erase(h, fr);
+		}
+
+		template<typename T> void remove_all(Hash<T> &h, uint64_t key)
+		{
+			while (hash::has(h, key))
+				hash::remove(h, key);
+		}
+	}
+
+
+	template <typename T> Hash<T>::Hash(Allocator &a) :
+		_hash(a), _data(a)
+	{
+	}
+} // namespace crown

+ 1 - 1
engine/core/containers/IdArray.h

@@ -28,7 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "Assert.h"
 #include "Types.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Log.h"
 
 namespace crown

+ 0 - 391
engine/core/containers/List.h

@@ -1,391 +0,0 @@
-/*
-Copyright (c) 2013 Daniele Bartolini, Michele Rossi
-Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#pragma once
-
-#include "Allocator.h"
-#include "Types.h"
-#include "Assert.h"
-#include <cstring>
-
-namespace crown
-{
-
-/// Dynamic array of POD items.
-/// @note
-/// Does not call constructors/destructors so it is not very suitable for non-POD items.
-template <typename T>
-class List
-{
-public:
-
-	/// Does not allocate memory.
-						List(Allocator& allocator);
-
-	/// Allocates capacity * sizeof(T) bytes.
-						List(Allocator& allocator, uint32_t capacity);
-						List(const List<T>& other);
-						~List();
-
-	/// Random access by index
-	T&					operator[](uint32_t index);
-
-	/// Random access by index
-	const T&			operator[](uint32_t index) const;
-
-	/// Returns whether the list is empty
-	bool				empty() const;
-
-	/// Returns the number of items in the list
-	uint32_t			size() const;
-
-	/// Returns the maximum number of items the array can hold
-	uint32_t			capacity() const;
-
-	/// Resizes the list to the given @a size.
-	/// @note
-	/// Old items will be copied to the newly created list.
-	/// If the new capacity is smaller than the previous one, the
-	/// list will be truncated.
-	void				resize(uint32_t size);
-
-	/// Reserves space in the list for at least @a capacity items.
-	void				reserve(uint32_t capacity);
-
-	/// Sets the list capacity
-	void				set_capacity(uint32_t capacity);
-
-	/// Grows the list to contain at least @a min_capacity items
-	void				grow(uint32_t min_capacity);
-
-	/// Condenses the array so that the capacity matches the actual number
-	/// of items in the list.
-	void				condense();
-
-	/// Appends an item to the list and returns its index.
-	uint32_t			push_back(const T& item);
-
-	/// Removes the last item from the list.
-	void				pop_back();
-
-	/// Appends @a count @a items to the list and returns the number
-	/// of items in the list after the append operation.
-	uint32_t			push(const T* items, uint32_t count);
-
-	/// Clears the content of the list.
-	/// @note
-	/// Does not free memory nor call destructors, it only zeroes
-	/// the number of items in the list for efficiency.
-	void				clear();
-
-	/// Copies the content of the @a other list into this one.
-	const List<T>&		operator=(const List<T>& other);
-
-	T*					begin();
-	const T*			begin() const;
-	T*					end();
-	const T*			end() const;
-
-	T&					front();
-	const T&			front() const;
-	T&					back();
-	const T&			back() const;
-
-private:
-
-	Allocator*			m_allocator;
-	uint32_t			m_capacity;
-	uint32_t			m_size;
-	T*					m_array;
-};
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline List<T>::List(Allocator& allocator)
-	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
-{
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline List<T>::List(Allocator& allocator, uint32_t capacity)
-	: m_allocator(&allocator), m_capacity(0), m_size(0), m_array(NULL)
-{
-	resize(capacity);
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline List<T>::List(const List<T>& other)
-	: m_allocator(other.m_allocator), m_capacity(0), m_size(0), m_array(NULL)
-{
-	*this = other;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline List<T>::~List()
-{
-	if (m_array)
-	{
-		m_allocator->deallocate(m_array);
-	}
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T& List<T>::operator[](uint32_t index)
-{
-	CE_ASSERT(index < m_size, "Index out of bounds");
-
-	return m_array[index];
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T& List<T>::operator[](uint32_t index) const
-{
-	CE_ASSERT(index < m_size, "Index out of bounds");
-
-	return m_array[index];
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline bool List<T>::empty() const
-{
-	return m_size == 0;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline uint32_t List<T>::size() const
-{
-	return m_size;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline uint32_t List<T>::capacity() const
-{
-	return m_capacity;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::resize(uint32_t size)
-{
-	if (size > m_capacity)
-	{
-		set_capacity(size);
-	}
-
-	m_size = size;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::reserve(uint32_t capacity)
-{
-	if (capacity > m_capacity)
-	{
-		grow(capacity);
-	}
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::set_capacity(uint32_t capacity)
-{
-	if (capacity == m_capacity)
-	{
-		return;
-	}
-
-	if (capacity < m_size)
-	{
-		resize(capacity);
-	}
-
-	if (capacity > 0)
-	{
-		T* tmp = m_array;
-		m_capacity = capacity;
-
-		m_array = (T*)m_allocator->allocate(capacity * sizeof(T), CE_ALIGNOF(T));
-
-		memcpy(m_array, tmp, m_size * sizeof(T));
-
-		if (tmp)
-		{
-			m_allocator->deallocate(tmp);
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::grow(uint32_t min_capacity)
-{
-	uint32_t new_capacity = m_capacity * 2 + 1;
-
-	if (new_capacity < min_capacity)
-	{
-		new_capacity = min_capacity;
-	}
-
-	set_capacity(new_capacity);
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::condense()
-{
-	resize(m_size);
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline uint32_t List<T>::push_back(const T& item)
-{
-	if (m_capacity == m_size)
-	{
-		grow(0);
-	}
-
-	m_array[m_size] = item;
-
-	return 	m_size++;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::pop_back()
-{
-	CE_ASSERT(m_size > 0, "The list is empty");
-
-	m_size--;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline uint32_t List<T>::push(const T* items, uint32_t count)
-{
-	if (m_capacity <= m_size + count)
-	{
-		grow(m_size + count);
-	}
-
-	memcpy(&m_array[m_size], items, sizeof(T) * count);
-	m_size += count;
-
-	return m_size;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void List<T>::clear()
-{
-	m_size = 0;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const List<T>& List<T>::operator=(const List<T>& other)
-{
-	const uint32_t size = other.m_size;
-	resize(size);
-	memcpy(m_array, other.m_array, sizeof(T) * size);
-
-	return *this;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T* List<T>::begin() const
-{
-	return m_array;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T* List<T>::begin()
-{
-	return m_array;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T* List<T>::end() const
-{
-	return m_array + m_size;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T* List<T>::end()
-{
-	return m_array + m_size;
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T& List<T>::front()
-{
-	CE_ASSERT(m_size > 0, "The list is empty");
-
-	return m_array[0];
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T& List<T>::front() const
-{
-	CE_ASSERT(m_size > 0, "The list is empty");
-
-	return m_array[0];
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T& List<T>::back()
-{
-	CE_ASSERT(m_size > 0, "The list is empty");
-
-	return m_array[m_size - 1];
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T& List<T>::back() const
-{
-	CE_ASSERT(m_size > 0, "The list is empty");
-
-	return m_array[m_size - 1];
-}
-
-} // namespace crown
-

+ 36 - 140
engine/core/containers/PriorityQueue.h

@@ -27,156 +27,52 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <algorithm>
-#include "List.h"
+#include "ContainerTypes.h"
 
 namespace crown
 {
-
-template <typename T>
-class PriorityQueue
+namespace priority_queue
 {
-public:
-
-	/// Does not allocate memory.
-					PriorityQueue(Allocator& a);
-					~PriorityQueue();
-
-	/// Returns whether the queue is empty.
-	bool			empty() const;
-
-	/// Returns the number of items in the queue.
-	uint32_t		size() const;
-
 	/// Returns the first item in the queue.
-	const T&		top() const;
+	template <typename T> const T& top(const PriorityQueue<T>& q);
 
 	/// Inserts @a item into the queue.
-	void			push(const T& item);
+	template <typename T> void push(PriorityQueue<T>& q, const T& item);
 
 	/// Removes the first item from the queue.
-	void			pop();
-
-	T*				begin();
-	const T*		begin() const;
-	T*				end();
-	const T*		end() const;
-
-	T&				front();
-	const T&		front() const;
-	T&				back();
-	const T&		back() const;
-
-private:
-
-	List<T>			m_queue;
-};
-
-//-----------------------------------------------------------------------------
-template <typename T>
-PriorityQueue<T>::PriorityQueue(Allocator& a) :
-	m_queue(a)
-{
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-PriorityQueue<T>::~PriorityQueue()
-{
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-bool PriorityQueue<T>::empty() const
-{
-	return m_queue.empty();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-uint32_t PriorityQueue<T>::size() const
-{
-	return m_queue.size();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-const T& PriorityQueue<T>::top() const
-{
-	return m_queue.front();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-void PriorityQueue<T>::push(const T& item)
-{
-	m_queue.push_back(item);
-
-	std::push_heap(begin(), end());
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-void PriorityQueue<T>::pop()
-{
-	std::pop_heap(begin(), end());
-
-	m_queue.pop_back();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-const T* PriorityQueue<T>::begin() const
-{
-	return m_queue.begin();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-T* PriorityQueue<T>::begin()
-{
-	return m_queue.begin();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-const T* PriorityQueue<T>::end() const
-{
-	return m_queue.end();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-T* PriorityQueue<T>::end()
-{
-	return m_queue.end();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-const T& PriorityQueue<T>::front() const
-{
-	return m_queue.front();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-T& PriorityQueue<T>::front()
-{
-	return m_queue.front();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-const T& PriorityQueue<T>::back() const
-{
-	return m_queue.back();
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-T& PriorityQueue<T>::back()
+	template <typename T> void pop(PriorityQueue<T>& q);
+} // namespace priority_queue
+
+namespace priority_queue
+{
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	const T& top(const PriorityQueue<T>& q)
+	{
+		return q.m_queue.front();
+	}
+
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	void push(PriorityQueue<T>& q, const T& item)
+	{
+		array::push_back(q.m_queue, item);
+		std::push_heap(array::begin(q.m_queue), array::end(q.m_queue));
+	}
+
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	void pop(PriorityQueue<T>& q)
+	{
+		std::pop_heap(array::begin(q.m_queue), array::end(q.m_queue));
+		array::pop_back(q.m_queue);
+	}
+} // namespace priority_queue
+
+template <typename T>
+PriorityQueue<T>::PriorityQueue(Allocator& a)
+	: m_queue(a)
 {
-	return m_queue.back();
 }
 
 } // namespace crown

+ 199 - 224
engine/core/containers/Queue.h

@@ -26,337 +26,312 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "Types.h"
-#include "List.h"
-#include "Allocator.h"
+#include "ContainerTypes.h"
+#include "Array.h"
 #include "Assert.h"
 #include <cstring>
 
 namespace crown
 {
-
-/// Circular buffer double-ended queue of POD items.
-/// @note
-/// Does not call constructors/destructors so it is not very suitable for non-POD items.
-template <typename T>
-class Queue
+namespace queue
 {
-public:
-
-					Queue(Allocator& allocator);
-					~Queue();
-
-	/// Random access by index
-	T&				operator[](uint32_t index);
-
-	/// Random access by index
-	const T&		operator[](uint32_t index) const;
-
 	/// Returns whether the queue is empty.
-	bool			empty() const;
+	template<typename T> bool empty(const Queue<T>& q);
 
 	/// Returns the number of items in the queue
-	uint32_t		size() const;
+	template<typename T> uint32_t size(const Queue<T>& q);
 
 	/// Returns the number of items the queue can hold before
 	/// a resize must occur.
-	uint32_t		space() const;
+	template<typename T> uint32_t space(const Queue<T>& q);
 
 	/// Increase or decrease the capacity of the queue.
 	/// @note
 	/// Old items will be copied to the newly created queue.
 	/// If the new @a capacity is smaller than the previous one, the
 	/// queue will be truncated.
-	void			increase_capacity(uint32_t capacity);
+	template<typename T> void increase_capacity(Queue<T>& q, uint32_t capacity);
 
 	/// Grows the queue to contain at least @a min_capacity items.
 	/// If @a min_capacity is set to 0, the queue automatically
 	/// determines the new capacity based on its size at the 
 	/// time of call.
-	void			grow(uint32_t min_capacity);
+	template<typename T> void grow(Queue<T>& q, uint32_t min_capacity);
 
 	/// Appends an @a item to the back of the queue
-	void			push_back(const T& item);
+	template<typename T> void push_back(Queue<T>& q, const T& item);
 
 	/// Removes the last item from the queue
-	void			pop_back();
+	template<typename T> void pop_back(Queue<T>& q);
 
 	/// Appends an @a item to the front of the queue
-	void			push_front(const T& item);
+	template<typename T> void push_front(Queue<T>& q, const T& item);
 
 	/// Removes the first item from the queue
-	void			pop_front();
+	template<typename T> void pop_front(Queue<T>& q);
 
 	/// Appends @a n @a items to the back of the queue
-	void			push(const T *items, uint32_t n);
+	template<typename T> void push(Queue<T>& q, const T *items, uint32_t n);
 
 	/// Removes @a n items from the front of the queue
-	void			pop(uint32_t n);
+	template<typename T> void pop(Queue<T>& q, uint32_t n);
 
 	/// Clears the content of the queue.
 	/// @note
 	/// Does not free memory nor call destructors, it only zeroes
 	/// the number of items in the queue for efficiency.
-	void 			clear();
-
-	T*				begin();
-	const T*		begin() const;
-	T*				end();
-	const T*		end() const;
-
-	T&				front();
-	const T&		front() const;
-	T&				back();
-	const T&		back() const;
-
-private:
+	template<typename T> void clear(Queue<T>& q);
 
-	uint32_t		m_read;
-	uint32_t		m_size;
-	List<T>			m_queue;
-};
+	template<typename T> T* begin(Queue<T>& q);
+	template<typename T> const T* begin(const Queue<T>& q);
+	template<typename T> T* end(Queue<T>& q);
+	template<typename T> const T* end(const Queue<T>& q);
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline Queue<T>::Queue(Allocator& allocator) :
-	m_read(0),
-	m_size(0),
-	m_queue(allocator)
-{
-}
+	template<typename T> T& front(Queue<T>& q);
+	template<typename T> const T& front(const Queue<T>& q);
+	template<typename T> T& back(Queue<T>& q);
+	template<typename T> const T& back(const Queue<T>& q);
+} // namespace queue
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline Queue<T>::~Queue()
+namespace queue
 {
-}
-
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T& Queue<T>::operator[](uint32_t index)
-{
-	return m_queue[(m_read + index) % m_queue.size()];
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline bool empty(const Queue<T>& q)
+	{
+		return q.m_size == 0;
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T& Queue<T>::operator[](uint32_t index) const
-{
-	return m_queue[(m_read + index) % m_queue.size()];
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline uint32_t size(const Queue<T>& q)
+	{
+		return q.m_size;
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline bool Queue<T>::empty() const
-{
-	return m_size == 0;
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline uint32_t space(const Queue<T>& q)
+	{
+		return array::size(q.m_queue) - q.m_size;
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline uint32_t Queue<T>::size() const
-{
-	return m_size;
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void increase_capacity(Queue<T>& q, uint32_t capacity)
+	{
+		uint32_t old_size = array::size(q.m_queue);
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline uint32_t Queue<T>::space() const
-{
-	return m_queue.size() - m_size;
-}
+		array::resize(q.m_queue, capacity);
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::increase_capacity(uint32_t capacity)
-{
-	uint32_t old_size = m_queue.size();
+		if (q.m_read + q.m_size > old_size)
+		{
+			memmove(array::begin(q.m_queue) + capacity - (old_size - q.m_read), array::begin(q.m_queue) + q.m_read, (old_size - q.m_read) * sizeof(T));
 
-	m_queue.resize(capacity);
+			q.m_read += (capacity - old_size);
+		}
+	}
 
-	if (m_read + m_size > old_size)
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void grow(Queue<T>& q, uint32_t min_capacity)
 	{
-		memmove(m_queue.begin() + capacity - (old_size - m_read), m_queue.begin() + m_read, (old_size - m_read) * sizeof(T));
+		uint32_t new_capacity = array::size(q.m_queue) * 2 + 1;
 
-		m_read += (capacity - old_size);
-	}
-}
+		if (new_capacity < min_capacity)
+		{
+			new_capacity = min_capacity;
+		}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::grow(uint32_t min_capacity)
-{
-	uint32_t new_capacity = m_queue.size() * 2 + 1;
+		increase_capacity(q, new_capacity);
+	}
 
-	if (new_capacity < min_capacity)
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void push_back(Queue<T>& q, const T& item)
 	{
-		new_capacity = min_capacity;
-	}
+		if (space(q) == 0)
+		{
+			grow(q, 0);
+		}
 
-	increase_capacity(new_capacity);
-}
+		q[q.m_size] = item;
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::push_back(const T& item)
-{
-	if (space() == 0)
+		q.m_size++;
+	}
+
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void pop_back(Queue<T>& q)
 	{
-		grow(0);
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
+
+		q.m_size--;
 	}
 
-	(*this)[m_size] = item;
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void push_front(Queue<T>& q, const T& item)
+	{
+		if (space(q) == 0)
+		{
+			grow(q, 0);
+		}
 
-	m_size++;
-}
+		q.m_read = (q.m_read - 1 + array::size(q.m_queue)) % array::size(q.m_queue);
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::pop_back()
-{
-	CE_ASSERT(m_size > 0, "The queue is empty");
+		q[0] = item;
 
-	m_size--;
-}
+		q.m_size++;
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::push_front(const T& item)
-{
-	if (space() == 0)
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void pop_front(Queue<T>& q)
 	{
-		grow(0);
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
+
+		q.m_read = (q.m_read + 1) % array::size(q.m_queue);
+		q.m_size--;
 	}
 
-	m_read = (m_read - 1 + m_queue.size()) % m_queue.size();
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void push(Queue<T>& q, const T *items, uint32_t n)
+	{
+		if (q.space() < n)
+		{
+			q.grow(q.size() + n);		
+		}
 
-	(*this)[0] = item;
+		const uint32_t size = array::size(q.m_queue);
+		const uint32_t insert = (q.m_read + q.m_size) % size;
 
-	m_size++;
-}
+		uint32_t to_insert = n;
+		if (insert + to_insert > size)
+		{
+			to_insert = size - insert;
+		}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::pop_front()
-{
-	CE_ASSERT(m_size > 0, "The queue is empty");
+		memcpy(array::begin(q.m_queue) + insert, items, to_insert * sizeof(T));
 
-	m_read = (m_read + 1) % m_queue.size();
-	m_size--;
-}
+		q.m_size += to_insert;
+		items += to_insert;
+		n -= to_insert;
+		memcpy(array::begin(q.m_queue), items, n * sizeof(T));
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::push(const T *items, uint32_t n)
-{
-	if (space() < n)
+		q.m_size += n;
+	}
+
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void pop(Queue<T>& q, uint32_t n)
 	{
-		grow(size() + n);		
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
+
+		q.m_read = (q.m_read + n) % array::size(q.m_queue);
+		q.m_size -= n;
 	}
 
-	const uint32_t size = m_queue.size();
-	const uint32_t insert = (m_read + m_size) % size;
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline void clear(Queue<T>& q)
+	{
+		q.m_read = 0;
+		q.m_size = 0;
+	}
 
-	uint32_t to_insert = n;
-	if (insert + to_insert > size)
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline T* begin(Queue<T>& q)
 	{
-		to_insert = size - insert;
+		return array::begin(q.m_queue) + q.m_read;
 	}
 
-	memcpy(m_queue.begin() + insert, items, to_insert * sizeof(T));
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline const T* begin(const Queue<T>& q)
+	{
+		return array::begin(q.m_queue) + q.m_read;
+	}
 
-	m_size += to_insert;
-	items += to_insert;
-	n -= to_insert;
-	memcpy(m_queue.begin(), items, n * sizeof(T));
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline T* end(Queue<T>& q)
+	{
+		uint32_t end = q.m_read + q.m_size;
 
-	m_size += n;
-}
+		return end >= array::size(q.m_queue) ? array::end(q.m_queue) : array::begin(q.m_queue) + end;
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::pop(uint32_t n)
-{
-	CE_ASSERT(m_size > 0, "The queue is empty");
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline const T* end(const Queue<T>& q)
+	{
+		uint32_t end = q.m_read + q.m_size;
 
-	m_read = (m_read + n) % m_queue.size();
-	m_size -= n;
-}
+		return end >= array::size(q.m_queue) ? array::end(q.m_queue) : array::begin(q.m_queue) + end;
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline void Queue<T>::clear()
-{
-	m_read = 0;
-	m_size = 0;
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline T& front(Queue<T>& q)
+	{
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T* Queue<T>::begin()
-{
-	return m_queue.begin() + m_read;
-}
+		return q.m_queue[q.m_read];
+	}
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T* Queue<T>::begin() const
-{
-	return m_queue.begin() + m_read;
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline const T& front(const Queue<T>& q)
+	{
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T* Queue<T>::end()
-{
-	uint32_t end = m_read + m_size;
+		return q.m_queue[q.m_read];
+	}
 
-	return end >= m_queue.size() ? m_queue.end() : m_queue.begin() + end;
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline T& back(Queue<T>& q)
+	{
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline const T* Queue<T>::end() const
-{
-	uint32_t end = m_read + m_size;
+		return q[q.m_size - 1];
+	}
 
-	return end >= m_queue.size() ? m_queue.end() : m_queue.begin() + end;
-}
+	//-----------------------------------------------------------------------------
+	template <typename T>
+	inline const T& back(const Queue<T>& q)
+	{
+		CE_ASSERT(q.m_size > 0, "The queue is empty");
 
-//-----------------------------------------------------------------------------
-template <typename T>
-inline T& Queue<T>::front()
-{
-	CE_ASSERT(m_size > 0, "The queue is empty");
+		return q[q.m_size - 1];
+	}
 
-	return m_queue[m_read];
-}
+} // namespace queue
 
 //-----------------------------------------------------------------------------
 template <typename T>
-inline const T& Queue<T>::front() const
+inline Queue<T>::Queue(Allocator& allocator)
+	: m_read(0)
+	, m_size(0)
+	, m_queue(allocator)
 {
-	CE_ASSERT(m_size > 0, "The queue is empty");
-
-	return m_queue[m_read];
 }
 
 //-----------------------------------------------------------------------------
 template <typename T>
-inline T& Queue<T>::back()
+inline T& Queue<T>::operator[](uint32_t index)
 {
-	CE_ASSERT(m_size > 0, "The queue is empty");
-
-	return (*this)[m_size - 1];
+	return m_queue[(m_read + index) % array::size(m_queue)];
 }
 
 //-----------------------------------------------------------------------------
 template <typename T>
-inline const T& Queue<T>::back() const
+inline const T& Queue<T>::operator[](uint32_t index) const
 {
-	CE_ASSERT(m_size > 0, "The queue is empty");
-
-	return (*this)[m_size - 1];
+	return m_queue[(m_read + index) % array::size(m_queue)];
 }
 
 } // namespace crown

+ 1 - 1
engine/core/containers/Vector.h

@@ -36,7 +36,7 @@ namespace crown
 /// Dynamic array of objects.
 /// @note
 /// Calls constructors and destructors, not suitable for performance-critical stuff.
-/// If your data is POD, use List<T> instead.
+/// If your data is POD, use Array<T> instead.
 template <typename T>
 class Vector
 {

+ 5 - 5
engine/core/filesystem/NetworkFile.cpp

@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "JSONParser.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Log.h"
 #include "MathUtils.h"
 #include "NetworkFile.h"
@@ -89,11 +89,11 @@ void NetworkFile::read(void* buffer, size_t size)
 	network_filesystem::send(m_socket, command.c_str());
 
 	// Wait for response
-	List<char> response(default_allocator());
+	Array<char> response(default_allocator());
 	network_filesystem::read_response(m_socket, response);
 
 	// Parse the response
-	JSONParser json(response.begin());
+	JSONParser json(array::begin(response));
 	JSONElement root = json.root();
 
 	DynamicString data_base64;
@@ -154,10 +154,10 @@ size_t NetworkFile::size()
 	network_filesystem::send(m_socket, command.c_str());
 
 	// Wait for response
-	List<char> response(default_allocator());
+	Array<char> response(default_allocator());
 	network_filesystem::read_response(m_socket, response);
 
-	JSONParser parser(response.begin());
+	JSONParser parser(array::begin(response));
 	JSONElement root = parser.root();
 
 	return (size_t) root.key("size").to_int();

+ 4 - 4
engine/core/filesystem/NetworkFilesystem.h

@@ -35,17 +35,17 @@ namespace crown
 {
 namespace network_filesystem
 {
-	inline void read_response(TCPSocket socket, List<char>& response)
+	inline void read_response(TCPSocket socket, Array<char>& response)
 	{
 		// Read message length
 		uint32_t msg_len = 0;
 		socket.read(&msg_len, 4);
 
-		response.resize(msg_len);
-		socket.read(response.begin(), msg_len);
+		array::resize(response, msg_len);
+		socket.read(array::begin(response), msg_len);
 
 		// Ensure NUL-terminated
-		response.push_back('\0');
+		array::push_back(response, '\0');
 	}
 
 	inline void send(TCPSocket socket, const char* msg)

+ 15 - 15
engine/core/json/JSON.cpp

@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 */
 
 #include "JSON.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "StringUtils.h"
 #include "DynamicString.h"
 
@@ -280,49 +280,49 @@ double parse_number(const char* s)
 
 	const char* ch = s;
 
- 	List<char> str(default_allocator());
+ 	Array<char> str(default_allocator());
 
 	if ((*ch) == '-')
 	{
-		str.push_back('-');
+		array::push_back(str, '-');
 		ch = next(ch, '-');
 	}
 	while ((*ch) >= '0' && (*ch) <= '9')
 	{
-		str.push_back((*ch));
+		array::push_back(str, (*ch));
 		ch = next(ch);
 	}
 
 	if ((*ch) == '.')
 	{
-		str.push_back('.');
+		array::push_back(str, '.');
 		while ((*(ch = next(ch))) && (*ch) >= '0' && (*ch) <= '9')
 		{
-			str.push_back(*ch);
+			array::push_back(str, *ch);
 		}
 	}
 
 	if ((*ch) == 'e' || (*ch) == 'E')
 	{
-		str.push_back(*ch);
+		array::push_back(str, *ch);
 		ch = next(ch);
 
 		if ((*ch) == '-' || (*ch) == '+')
 		{
-			str.push_back(*ch);
+			array::push_back(str, *ch);
 			ch = next(ch);
 		}
 		while ((*ch) >= '0' && (*ch) <= '9')
 		{
-			str.push_back(*ch);
+			array::push_back(str, *ch);
 			ch = next(ch);
 		}
 	}
 
 	// Ensure null terminated
-	str.push_back('\0');
+	array::push_back(str, '\0');
 
-	return string::parse_double(str.begin());
+	return string::parse_double(array::begin(str));
 }
 
 //-----------------------------------------------------------------------------
@@ -376,7 +376,7 @@ float parse_float(const char* s)
 }
 
 //-----------------------------------------------------------------------------
-void parse_array(const char* s, List<const char*>& array)
+void parse_array(const char* s, Array<const char*>& array)
 {
 	CE_ASSERT_NOT_NULL(s);
 
@@ -400,7 +400,7 @@ void parse_array(const char* s, List<const char*>& array)
 
 		while (*ch)
 		{
-			array.push_back(ch);
+			array::push_back(array, ch);
 
 			ch = skip_array(ch);
 			ch = skip_object(ch);
@@ -430,7 +430,7 @@ void parse_array(const char* s, List<const char*>& array)
 }
 
 //-----------------------------------------------------------------------------
-void parse_object(const char* s, List<JSONPair>& object)
+void parse_object(const char* s, Array<JSONPair>& object)
 {
 	CE_ASSERT_NOT_NULL(s);
 
@@ -467,7 +467,7 @@ void parse_object(const char* s, List<JSONPair>& object)
 			ch = skip_whites(ch);
 
 			pair.val = ch;
-			object.push_back(pair);
+			array::push_back(object, pair);
 
 			// Skip any value
 			ch = skip_array(ch);

+ 2 - 2
engine/core/json/JSON.h

@@ -81,11 +81,11 @@ float parse_float(const char* s);
 
 /// Parses the @a s JSON array and puts it into @a array as pointers to
 /// the corresponding items into the original @a s string.
-void parse_array(const char* s, List<const char*>& array);
+void parse_array(const char* s, Array<const char*>& array);
 
 /// Parses the @a s JSON object and puts it into @a object as pointers to
 /// the corresponding key/value pairs into the original @a s string.
-void parse_object(const char* s, List<JSONPair>& object);
+void parse_object(const char* s, Array<JSONPair>& object);
 
 } // namespace json
 } // namespace crown

+ 44 - 44
engine/core/json/JSONParser.cpp

@@ -65,11 +65,11 @@ JSONElement& JSONElement::operator=(const JSONElement& other)
 //--------------------------------------------------------------------------
 JSONElement JSONElement::operator[](uint32_t i)
 {
-	List<const char*> array(default_allocator());
+	Array<const char*> array(default_allocator());
 
 	json::parse_array(m_at, array);
 
-	CE_ASSERT(i < array.size(), "Index out of bounds");
+	CE_ASSERT(i < array::size(array), "Index out of bounds");
 
 	return JSONElement(array[i]);
 }
@@ -85,11 +85,11 @@ JSONElement JSONElement::index_or_nil(uint32_t i)
 {
 	if (m_at != NULL)
 	{
-		List<const char*> array(default_allocator());
+		Array<const char*> array(default_allocator());
 
 		json::parse_array(m_at, array);
 
-		if (i >= array.size())
+		if (i >= array::size(array))
 		{
 			return JSONElement();
 		}
@@ -103,14 +103,14 @@ JSONElement JSONElement::index_or_nil(uint32_t i)
 //--------------------------------------------------------------------------
 JSONElement JSONElement::key(const char* k)
 {
-	List<JSONPair> object(default_allocator());
+	Array<JSONPair> object(default_allocator());
 
 	json::parse_object(m_at, object);
 
 	bool found = false;
 
 	const char* tmp_at = m_at;
-	for (uint32_t i = 0; i < object.size(); i++)
+	for (uint32_t i = 0; i < array::size(object); i++)
 	{
 		DynamicString key;
 		json::parse_string(object[i].key, key);
@@ -132,14 +132,14 @@ JSONElement JSONElement::key_or_nil(const char* k)
 {
 	if (m_at != NULL)
 	{
-		List<JSONPair> object(default_allocator());
+		Array<JSONPair> object(default_allocator());
 
 		json::parse_object(m_at, object);
 
 		bool found = false;
 
 		const char* tmp_at = m_at;
-		for (uint32_t i = 0; i < object.size(); i++)
+		for (uint32_t i = 0; i < array::size(object); i++)
 		{
 			DynamicString key;
 			json::parse_string(object[i].key, key);
@@ -165,10 +165,10 @@ JSONElement JSONElement::key_or_nil(const char* k)
 //--------------------------------------------------------------------------
 bool JSONElement::has_key(const char* k) const
 {
-	List<JSONPair> object(default_allocator());
+	Array<JSONPair> object(default_allocator());
 	json::parse_object(m_at, object);
 
-	for (uint32_t i = 0; i < object.size(); i++)
+	for (uint32_t i = 0; i < array::size(object); i++)
 	{
 		DynamicString key;
 		json::parse_string(object[i].key, key);
@@ -185,12 +185,12 @@ bool JSONElement::has_key(const char* k) const
 //--------------------------------------------------------------------------
 bool JSONElement::is_key_unique(const char* k) const
 {
-	List<JSONPair> object(default_allocator());
+	Array<JSONPair> object(default_allocator());
 	json::parse_object(m_at, object);
 
 	bool found = false;
 
-	for (uint32_t i = 0; i < object.size(); i++)
+	for (uint32_t i = 0; i < array::size(object); i++)
 	{
 		DynamicString key;
 		json::parse_string(object[i].key, key);
@@ -246,91 +246,91 @@ StringId32 JSONElement::to_string_id() const
 }
 
 //--------------------------------------------------------------------------
-void JSONElement::to_array(List<bool>& array) const
+void JSONElement::to_array(Array<bool>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
-		array.push_back(json::parse_bool(temp[i]));
+		array::push_back(array, json::parse_bool(temp[i]));
 	}
 }
 
 //--------------------------------------------------------------------------
-void JSONElement::to_array(List<int16_t>& array) const
+void JSONElement::to_array(Array<int16_t>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
-		array.push_back((int16_t)json::parse_int(temp[i]));
+		array::push_back(array, (int16_t)json::parse_int(temp[i]));
 	}
 }
 
 //--------------------------------------------------------------------------
-void JSONElement::to_array(List<uint16_t>& array) const
+void JSONElement::to_array(Array<uint16_t>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
-		array.push_back((uint16_t)json::parse_int(temp[i]));
+		array::push_back(array, (uint16_t)json::parse_int(temp[i]));
 	}
 }
 
 //--------------------------------------------------------------------------
-void JSONElement::to_array(List<int32_t>& array) const
+void JSONElement::to_array(Array<int32_t>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
-		array.push_back((int32_t)json::parse_int(temp[i]));
+		array::push_back(array, (int32_t)json::parse_int(temp[i]));
 	}
 }
 
 //--------------------------------------------------------------------------
-void JSONElement::to_array(List<uint32_t>& array) const
+void JSONElement::to_array(Array<uint32_t>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
-		array.push_back((uint32_t)json::parse_int(temp[i]));
+		array::push_back(array, (uint32_t)json::parse_int(temp[i]));
 	}
 }
 
 //--------------------------------------------------------------------------
-void JSONElement::to_array(List<float>& array) const
+void JSONElement::to_array(Array<float>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
-		array.push_back(json::parse_float(temp[i]));
+		array::push_back(array, json::parse_float(temp[i]));
 	}
 }
 
 //--------------------------------------------------------------------------
 void JSONElement::to_array(Vector<DynamicString>& array) const
 {
-	List<const char*> temp(default_allocator());
+	Array<const char*> temp(default_allocator());
 
 	json::parse_array(m_at, temp);
 
-	for (uint32_t i = 0; i < temp.size(); i++)
+	for (uint32_t i = 0; i < array::size(temp); i++)
 	{
 		DynamicString str;
 		json::parse_string(temp[i], str);
@@ -341,10 +341,10 @@ void JSONElement::to_array(Vector<DynamicString>& array) const
 //--------------------------------------------------------------------------
 void JSONElement::to_keys(Vector<DynamicString>& keys) const
 {
-	List<JSONPair> object(default_allocator());
+	Array<JSONPair> object(default_allocator());
 	json::parse_object(m_at, object);
 
-	for (uint32_t i = 0; i < object.size(); i++)
+	for (uint32_t i = 0; i < array::size(object); i++)
 	{
 		DynamicString key;
 		json::parse_string(object[i].key, key);
@@ -434,17 +434,17 @@ uint32_t JSONElement::size() const
 		}
 		case JSONType::OBJECT:
 		{
-			List<JSONPair> object(default_allocator());
+			Array<JSONPair> object(default_allocator());
 			json::parse_object(m_at, object);
 
-			return object.size();
+			return array::size(object);
 		}
 		case JSONType::ARRAY:
 		{
-			List<const char*> array(default_allocator());
+			Array<const char*> array(default_allocator());
 			json::parse_array(m_at, array);
 
-			return array.size();
+			return array::size(array);
 		}
 		case JSONType::STRING:
 		{

+ 13 - 13
engine/core/json/JSONParser.h

@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Vector.h"
 
 namespace crown
@@ -127,24 +127,24 @@ public:
 	/// array elements by JSONElement::operator[] and it is the very preferred way
 	/// for retrieving array elemets. However, you have to be sure that the array
 	/// contains only items of the given @array type.
-	void				to_array(List<bool>& array) const;
+	void				to_array(Array<bool>& array) const;
 
-	/// @copydoc JSONElement::to_array(List<bool>&)
-	void				to_array(List<int16_t>& array) const;
+	/// @copydoc JSONElement::to_array(Array<bool>&)
+	void				to_array(Array<int16_t>& array) const;
 
-	/// @copydoc JSONElement::to_array(List<bool>&)
-	void				to_array(List<uint16_t>& array) const;
+	/// @copydoc JSONElement::to_array(Array<bool>&)
+	void				to_array(Array<uint16_t>& array) const;
 
-	/// @copydoc JSONElement::to_array(List<bool>&)
-	void				to_array(List<int32_t>& array) const;
+	/// @copydoc JSONElement::to_array(Array<bool>&)
+	void				to_array(Array<int32_t>& array) const;
 
-	/// @copydoc JSONElement::to_array(List<bool>&)
-	void				to_array(List<uint32_t>& array) const;
+	/// @copydoc JSONElement::to_array(Array<bool>&)
+	void				to_array(Array<uint32_t>& array) const;
 
-	/// @copydoc JSONElement::to_array(List<bool>&)
-	void				to_array(List<float>& array) const;
+	/// @copydoc JSONElement::to_array(Array<bool>&)
+	void				to_array(Array<float>& array) const;
 
-	/// @copydoc JSONElement::to_array(List<bool>&)
+	/// @copydoc JSONElement::to_array(Array<bool>&)
 	void				to_array(Vector<DynamicString>& array) const;
 
 	/// Returns all the keys of the element.

+ 16 - 16
engine/core/strings/DynamicString.h

@@ -32,7 +32,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Assert.h"
 #include "Allocator.h"
 #include "StringUtils.h"
-#include "List.h"
+#include "Array.h"
 #include "Hash.h"
 
 namespace crown
@@ -86,7 +86,7 @@ public:
 
 private:
 
-	List<char>			m_string;
+	Array<char>			m_string;
 };
 
 //-----------------------------------------------------------------------------
@@ -101,7 +101,7 @@ inline DynamicString::DynamicString(const char* s, Allocator& allocator)
 {
 	if (s != NULL)
 	{
-		m_string.push(s, string::strlen(s));
+		array::push(m_string, s, string::strlen(s));
 	}
 }
 
@@ -123,7 +123,7 @@ inline DynamicString& DynamicString::operator+=(const char* s)
 {
 	CE_ASSERT_NOT_NULL(s);
 
-	m_string.push(s, string::strlen(s));
+	array::push(m_string, s, string::strlen(s));
 
 	return *this;
 }
@@ -131,7 +131,7 @@ inline DynamicString& DynamicString::operator+=(const char* s)
 //-----------------------------------------------------------------------------
 inline DynamicString& DynamicString::operator+=(const char c)
 {
-	m_string.push_back(c);
+	array::push_back(m_string, c);
 
 	return *this;
 }
@@ -149,8 +149,8 @@ inline DynamicString& DynamicString::operator=(const char* s)
 {
 	CE_ASSERT_NOT_NULL(s);
 
-	m_string.clear();
-	m_string.push(s, string::strlen(s));
+	array::clear(m_string);
+	array::push(m_string, s, string::strlen(s));
 
 	return *this;
 }
@@ -158,8 +158,8 @@ inline DynamicString& DynamicString::operator=(const char* s)
 //-----------------------------------------------------------------------------
 inline DynamicString& DynamicString::operator=(const char c)
 {
-	m_string.clear();
-	m_string.push_back(c);
+	array::clear(m_string);
+	array::push_back(m_string, c);
 
 	return *this;
 }
@@ -193,8 +193,8 @@ inline void DynamicString::strip_leading(const char* s)
 	const size_t my_len = string::strlen(c_str());
 	const size_t s_len = string::strlen(s);
 
-	memmove(m_string.begin(), m_string.begin() + s_len, (my_len - s_len));
-	m_string.resize(my_len - s_len);
+	memmove(array::begin(m_string), array::begin(m_string) + s_len, (my_len - s_len));
+	array::resize(m_string, my_len - s_len);
 }
 
 //-----------------------------------------------------------------------------
@@ -206,7 +206,7 @@ inline void DynamicString::strip_trailing(const char* s)
 	const size_t my_len = string::strlen(c_str());
 	const size_t s_len = string::strlen(s);
 
-	m_string.resize(my_len - s_len);
+	array::resize(m_string, my_len - s_len);
 }
 
 //-----------------------------------------------------------------------------
@@ -227,7 +227,7 @@ inline bool DynamicString::ends_with(const char* s)
 
 	if (my_len >= s_len)
 	{
-		return string::strncmp(m_string.begin() + (my_len - s_len), s, s_len) == 0;
+		return string::strncmp(array::begin(m_string) + (my_len - s_len), s, s_len) == 0;
 	}
 
 	return false;
@@ -242,10 +242,10 @@ inline StringId32 DynamicString::to_string_id()
 //-----------------------------------------------------------------------------
 inline const char* DynamicString::c_str()
 {
-	m_string.push_back('\0');
-	m_string.pop_back();
+	array::push_back(m_string, '\0');
+	array::pop_back(m_string);
 
-	return m_string.begin();
+	return array::begin(m_string);
 }
 
 } // namespace crown

+ 3 - 3
engine/core/strings/Path.h

@@ -43,7 +43,7 @@ void basename(const char* path, char* str, size_t len);
 void extension(const char* path, char* str, size_t len);
 void filename_without_extension(const char* path, char* str, size_t len);
 
-//bool segments(const char* path, List<Str>& ret);
+//bool segments(const char* path, Array<Str>& ret);
 inline void strip_trailing_separator(const char* path, char* ret, size_t len);
 
 /// Returns whether the segment is valid.
@@ -114,7 +114,7 @@ inline bool is_valid_path(const char* path)
 //		return true;
 //	}
 
-//	List<Str> segmentList;
+//	Array<Str> segmentList;
 //	if (!get_segments(Str(path), segmentList))
 //	{
 //		return false;
@@ -260,7 +260,7 @@ inline void filename_without_extension(const char* path, char* str, size_t len)
 }
 
 /// Returns the segments contained in path.
-//bool segments(const char* path, List<Str>& ret)
+//bool segments(const char* path, Array<Str>& ret)
 //{
 //	path.Split(os::PATH_SEPARATOR, ret);
 

+ 7 - 7
engine/core/strings/StringStream.h

@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include <stdio.h>
-#include "List.h"
+#include "ContainerTypes.h"
 #include "StringUtils.h"
 #include "OS.h"
 
@@ -62,7 +62,7 @@ private:
 
 private:
 
-	List<char>			m_string;
+	Array<char>			m_string;
 };
 
 //-----------------------------------------------------------------------------
@@ -74,7 +74,7 @@ inline StringStream::StringStream(Allocator& allocator)
 //-----------------------------------------------------------------------------
 inline void StringStream::clear()
 {
-	m_string.clear();
+	array::clear(m_string);
 }
 
 //-----------------------------------------------------------------------------
@@ -128,7 +128,7 @@ inline StringStream& StringStream::operator<<(double val)
 //-----------------------------------------------------------------------------
 inline StringStream& StringStream::operator<<(const char* s)
 {
-	m_string.push(s, string::strlen(s));
+	array::push(m_string, s, string::strlen(s));
 
 	return *this;
 }
@@ -136,10 +136,10 @@ inline StringStream& StringStream::operator<<(const char* s)
 //-----------------------------------------------------------------------------
 inline const char* StringStream::c_str()
 {
-	m_string.push_back('\0');
-	m_string.pop_back();
+	array::push_back(m_string, '\0');
+	array::pop_back(m_string);
 
-	return m_string.begin();
+	return array::begin(m_string);
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 2
engine/lua/LuaPhysicsWorld.cpp

@@ -84,12 +84,12 @@ CE_EXPORT int physics_world_overlap_test(lua_State* L)
 	Quaternion rot = stack.get_quaternion(6);
 	Vector3 size = stack.get_vector3(7);
 
-	List<Actor*> actors(default_allocator());
+	Array<Actor*> actors(default_allocator());
 
 	world->overlap_test(callback, filter, shape_type, pos, rot, size, actors);
 
 	stack.push_table();
-	for (uint32_t i = 0; i < actors.size(); i++)
+	for (uint32_t i = 0; i < array::size(actors); i++)
 	{
 		stack.push_key_begin(i+1);
 		stack.push_actor(actors[i]);

+ 4 - 4
engine/lua/LuaRaycast.cpp

@@ -42,7 +42,7 @@ CE_EXPORT int raycast_cast(lua_State* L)
 	Vector3 dir = stack.get_vector3(3);
 	float length = stack.get_float(4);
 	
-	List<RaycastHit> hits(default_allocator());
+	Array<RaycastHit> hits(default_allocator());
 
 	raycast->cast(from, dir, length, hits);
 
@@ -50,13 +50,13 @@ CE_EXPORT int raycast_cast(lua_State* L)
 	{
 		case CollisionMode::CLOSEST:
 		{
-			bool hit = hits.size() > 0 ? true : false;
+			bool hit = array::size(hits) > 0 ? true : false;
 			stack.push_bool(hit);
 			break;
 		}
 		case CollisionMode::ANY:
 		{
-			bool hit = hits.size() > 0 ? true : false;
+			bool hit = array::size(hits) > 0 ? true : false;
 			stack.push_bool(hit);
 			if (hit)
 			{
@@ -71,7 +71,7 @@ CE_EXPORT int raycast_cast(lua_State* L)
 		case CollisionMode::ALL:
 		{
 			stack.push_table();
-			for (uint32_t i = 0; i < hits.size(); i++)
+			for (uint32_t i = 0; i < array::size(hits); i++)
 			{
 				stack.push_key_begin(i+1);
 				

+ 2 - 2
engine/physics/PhysicsWorld.cpp

@@ -387,7 +387,7 @@ void PhysicsWorld::clear_kinematic(ActorId id)
 
 //-----------------------------------------------------------------------------
 void PhysicsWorld::overlap_test(const char* callback, CollisionType::Enum filter, ShapeType::Enum type,
-								const Vector3& pos, const Quaternion& rot, const Vector3& size, List<Actor*>& actors)
+								const Vector3& pos, const Quaternion& rot, const Vector3& size, Array<Actor*>& actors)
 {
 	PxTransform transform(PxVec3(pos.x, pos.y, pos.z), PxQuat(rot.v.x, rot.v.y, rot.v.z, rot.w));
 
@@ -418,7 +418,7 @@ void PhysicsWorld::overlap_test(const char* callback, CollisionType::Enum filter
 	{
 		PxOverlapHit oh = m_buffer.getAnyHit(i);
 
-		actors.push_back((Actor*)(oh.actor->userData));
+		array::push_back(actors, (Actor*)(oh.actor->userData));
 	}
 }
 

+ 1 - 1
engine/physics/PhysicsWorld.h

@@ -108,7 +108,7 @@ public:
 
 	/// Finds all actors in the physics world that are in a particular shape (supported: spheres, capsules and boxes)
 	void						overlap_test(const char* callback, CollisionType::Enum filter, ShapeType::Enum type,
-											const Vector3& pos, const Quaternion& rot, const Vector3& size, List<Actor*>& actors);
+											const Vector3& pos, const Quaternion& rot, const Vector3& size, Array<Actor*>& actors);
 
 	void						update(float dt);
 

+ 2 - 2
engine/physics/Raycast.cpp

@@ -59,7 +59,7 @@ Raycast::Raycast(PxScene* scene, EventStream& events, const char* callback, Coll
 }
 
 //-------------------------------------------------------------------------
-void Raycast::cast(const Vector3& from, const Vector3& dir, const float length, List<RaycastHit>& hits)
+void Raycast::cast(const Vector3& from, const Vector3& dir, const float length, Array<RaycastHit>& hits)
 {
 	m_scene->raycast(PxVec3(from.x, from.y, from.z), PxVec3(dir.x, dir.y, dir.z), length, m_buffer, PxHitFlags(PxHitFlag::eDEFAULT), m_fd);
 
@@ -78,7 +78,7 @@ void Raycast::cast(const Vector3& from, const Vector3& dir, const float length,
 		hit.normal.z = rh.normal.z;
 		hit.actor = (Actor*)(rh.actor->userData);
 
-		hits.push_back(hit);
+		array::push_back(hits, hit);
 	}
 }
 

+ 1 - 1
engine/physics/Raycast.h

@@ -68,7 +68,7 @@ struct Raycast
 	/// If there was a hit, the callback will also be called with the position of the hit, the distance from the origin, the normal of the surface that 
 	/// was hit and the actor that was hit.
 	/// @a CollisionMode::ALL: as @a CollisionMode::CLOSEST, with more tuples
-	void					cast(const Vector3& from, const Vector3& dir, const float length, List<RaycastHit>& hits);
+	void					cast(const Vector3& from, const Vector3& dir, const float length, Array<RaycastHit>& hits);
 
 	CollisionMode::Enum 	mode() const;
 

+ 1 - 1
engine/renderers/RenderWorld.h

@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "IdArray.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "PoolAllocator.h"
 #include "Resource.h"
 #include "Matrix4x4.h"

+ 5 - 5
engine/resource/FontResource.cpp

@@ -69,7 +69,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	// Out buffer
 	FontHeader h;
-	List<FontGlyphData> m_glyphs(default_allocator());
+	Array<FontGlyphData> m_glyphs(default_allocator());
 
 	JSONParser json(buf);
 	JSONElement root = json.root();
@@ -90,22 +90,22 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	{
 		FontGlyphData data;
 		parse_glyph(glyphs[i], data);
-		m_glyphs.push_back(data);
+		array::push_back(m_glyphs, data);
 	}
 
 	fs.close(file);
 	default_allocator().deallocate(buf);
 
 	h.material.id = hash::murmur2_64(material_name.c_str(), string::strlen(material_name.c_str()), 0);
-	h.num_glyphs = m_glyphs.size();
+	h.num_glyphs = array::size(m_glyphs);
 	h.texture_size = size.to_int();
 	h.font_size = font_size.to_int();
 
 	out_file->write((char*) &h, sizeof(FontHeader));
 
-	if (m_glyphs.size() > 0)
+	if (array::size(m_glyphs) > 0)
 	{
-		out_file->write((char*) m_glyphs.begin(), sizeof(FontGlyphData) * h.num_glyphs);
+		out_file->write((char*) array::begin(m_glyphs), sizeof(FontGlyphData) * h.num_glyphs);
 	}
 }
 

+ 35 - 35
engine/resource/GuiResource.cpp

@@ -44,7 +44,7 @@ namespace gui_resource
 {
 
 //-----------------------------------------------------------------------------
-void parse_rect(JSONElement rect, List<float>& positions, List<float>& sizes, List<float>& colors)
+void parse_rect(JSONElement rect, Array<float>& positions, Array<float>& sizes, Array<float>& colors)
 {
 	JSONElement position 	= rect.key("position");
 	JSONElement size 		= rect.key("size");
@@ -56,7 +56,7 @@ void parse_rect(JSONElement rect, List<float>& positions, List<float>& sizes, Li
 }
 
 //-----------------------------------------------------------------------------
-void parse_triangle(JSONElement triangle, List<float>& points, List<float>& colors)
+void parse_triangle(JSONElement triangle, Array<float>& points, Array<float>& colors)
 {
 	JSONElement point	= triangle.key("points");
 	JSONElement color 	= triangle.key("color");
@@ -66,7 +66,7 @@ void parse_triangle(JSONElement triangle, List<float>& points, List<float>& colo
 }
 
 //-----------------------------------------------------------------------------
-void parse_image(JSONElement image, StringId64& material, List<float>& positions, List<float>& sizes)
+void parse_image(JSONElement image, StringId64& material, Array<float>& positions, Array<float>& sizes)
 {
 	JSONElement mat			= image.key("material");
 	JSONElement position 	= image.key("position");
@@ -90,22 +90,22 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	// Out buffer
 	GuiHeader h;
-	List<GuiRectData> 		m_gui_rects(default_allocator());
-	List<GuiTriangleData> 	m_gui_triangles(default_allocator());
-	List<GuiImageData> 		m_gui_images(default_allocator());
+	Array<GuiRectData> 		m_gui_rects(default_allocator());
+	Array<GuiTriangleData> 	m_gui_triangles(default_allocator());
+	Array<GuiImageData> 		m_gui_images(default_allocator());
 
 	JSONParser json(buf);
 	JSONElement root = json.root();
 
-	List<float>	m_gui_position(default_allocator());
+	Array<float>	m_gui_position(default_allocator());
 	root.key("position").to_array(m_gui_position);
 
 	// Parse & compile all rects
 	if (root.has_key("rects"))
 	{
-		List<float> 		m_rect_positions(default_allocator());
-		List<float> 		m_rect_sizes(default_allocator());
-		List<float> 		m_rect_colors(default_allocator());
+		Array<float> 		m_rect_positions(default_allocator());
+		Array<float> 		m_rect_sizes(default_allocator());
+		Array<float> 		m_rect_colors(default_allocator());
 
 		JSONElement rects = root.key("rects");
 		uint32_t num_rects = rects.size();
@@ -124,19 +124,19 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 			rect.color[2] = m_rect_colors[2];
 			rect.color[3] = m_rect_colors[3];
 
-			m_gui_rects.push_back(rect);
+			array::push_back(m_gui_rects, rect);
 
-			m_rect_positions.clear();
-			m_rect_sizes.clear();
-			m_rect_colors.clear();
+			array::clear(m_rect_positions);
+			array::clear(m_rect_sizes);
+			array::clear(m_rect_colors);
 		}
 	}
 
 	// Parse & compile all triangles
 	if (root.has_key("triangles"))
 	{
-		List<float> m_triangle_points(default_allocator());
-		List<float> m_triangle_colors(default_allocator());
+		Array<float> m_triangle_points(default_allocator());
+		Array<float> m_triangle_colors(default_allocator());
 
 		JSONElement triangles = root.key("triangles");
 		uint32_t num_triangles = triangles.size();
@@ -157,10 +157,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 			triangle.color[2] = m_triangle_colors[2];
 			triangle.color[3] = m_triangle_colors[3];
 
-			m_gui_triangles.push_back(triangle);
+			array::push_back(m_gui_triangles, triangle);
 
-			m_triangle_points.clear();
-			m_triangle_colors.clear();
+			array::clear(m_triangle_points);
+			array::clear(m_triangle_colors);
 		}
 	}
 
@@ -168,8 +168,8 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	if (root.has_key("images"))
 	{
 		StringId64			m_image_material = 0;
-		List<float> 		m_image_positions(default_allocator());
-		List<float> 		m_image_sizes(default_allocator());
+		Array<float> 		m_image_positions(default_allocator());
+		Array<float> 		m_image_sizes(default_allocator());
 
 		JSONElement images = root.key("images");
 		uint32_t num_images = images.size();
@@ -185,10 +185,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 			image.size[0] 		= m_image_sizes[0];
 			image.size[1] 		= m_image_sizes[1];
 
-			m_gui_images.push_back(image);
+			array::push_back(m_gui_images, image);
 
-			m_image_positions.clear();
-			m_image_sizes.clear();
+			array::clear(m_image_positions);
+			array::clear(m_image_sizes);
 		}
 	}
 
@@ -198,26 +198,26 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	// Fill resource header
 	h.position[0] = m_gui_position[0];
 	h.position[1] = m_gui_position[1];
-	h.num_rects = m_gui_rects.size();
-	h.num_triangles = m_gui_triangles.size();
-	h.num_images = m_gui_images.size();
+	h.num_rects = array::size(m_gui_rects);
+	h.num_triangles = array::size(m_gui_triangles);
+	h.num_images = array::size(m_gui_images);
 	h.rects_offset 	= sizeof(GuiHeader);
-	h.triangles_offset = h.rects_offset + sizeof(GuiRectData) * m_gui_rects.size();
-	h.images_offset = h.triangles_offset + sizeof(GuiTriangleData) * m_gui_triangles.size();
+	h.triangles_offset = h.rects_offset + sizeof(GuiRectData) * array::size(m_gui_rects);
+	h.images_offset = h.triangles_offset + sizeof(GuiTriangleData) * array::size(m_gui_triangles);
 
 	// Write compiled resource
 	out_file->write((char*) &h, sizeof(GuiHeader));
-	if (m_gui_rects.size() > 0)
+	if (array::size(m_gui_rects) > 0)
 	{
-		out_file->write((char*) m_gui_rects.begin(), sizeof(GuiRectData) * h.num_rects);
+		out_file->write((char*) array::begin(m_gui_rects), sizeof(GuiRectData) * h.num_rects);
 	}
-	if (m_gui_triangles.size() > 0)
+	if (array::size(m_gui_triangles) > 0)
 	{
-		out_file->write((char*) m_gui_triangles.begin(), sizeof(GuiTriangleData) * h.num_triangles);
+		out_file->write((char*) array::begin(m_gui_triangles), sizeof(GuiTriangleData) * h.num_triangles);
 	}
-	if (m_gui_images.size() > 0)
+	if (array::size(m_gui_images) > 0)
 	{
-		out_file->write((char*) m_gui_images.begin(), sizeof(GuiImageData) * h.num_images);
+		out_file->write((char*) array::begin(m_gui_images), sizeof(GuiImageData) * h.num_images);
 	}
 }
 

+ 1 - 1
engine/resource/GuiResource.h

@@ -35,7 +35,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "File.h"
 #include "OS.h"
 #include "StringUtils.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Bundle.h"
 #include "Device.h"
 #include "Renderer.h"

+ 4 - 4
engine/resource/MaterialResource.cpp

@@ -47,7 +47,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	JSONElement root = json.root();
 
 	// Read texture layers
-	List<ResourceId> texture_layers(default_allocator());
+	Array<ResourceId> texture_layers(default_allocator());
 
 	JSONElement tl = root.key("texture_layers");
 	for (uint32_t i = 0; i < tl.size(); i++)
@@ -55,7 +55,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		DynamicString tex;
 		tl[i].to_string(tex); tex += ".texture";
 		ResourceId tex_id; tex_id.id = hash::murmur2_64(tex.c_str(), tex.length(), 0);
-		texture_layers.push_back(tex_id);
+		array::push_back(texture_layers, tex_id);
 	}
 
 	fs.close(file);
@@ -63,7 +63,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	// Write resource
 	MaterialHeader mh;
-	mh.num_texture_layers = texture_layers.size();
+	mh.num_texture_layers = array::size(texture_layers);
 
 	uint32_t offt = sizeof(MaterialHeader);
 	mh.texture_layers_offset = offt;
@@ -72,7 +72,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	if (mh.num_texture_layers)
 	{
-		out_file->write((char*) texture_layers.begin(), sizeof(ResourceId) * texture_layers.size());
+		out_file->write((char*) array::begin(texture_layers), sizeof(ResourceId) * array::size(texture_layers));
 	}
 }
 

+ 20 - 20
engine/resource/MeshResource.cpp

@@ -55,8 +55,8 @@ MeshHeader			m_mesh_header;
 bool				m_has_normal;
 bool				m_has_texcoord;
 
-List<MeshVertex>	m_vertices(default_allocator());
-List<uint16_t>		m_indices(default_allocator());
+Array<MeshVertex>	m_vertices(default_allocator());
+Array<uint16_t>		m_indices(default_allocator());
 
 //-----------------------------------------------------------------------------
 void compile(Filesystem& fs, const char* resource_path, File* out_file)
@@ -81,18 +81,18 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		Log::e("Bad mesh: array 'position' not found.");
 		return;
 	}
-	List<float> position_array(default_allocator());
+	Array<float> position_array(default_allocator());
 	position.to_array(position_array);
 
 
-	List<float> normal_array(default_allocator());
+	Array<float> normal_array(default_allocator());
 	if (!normal.is_nil())
 	{
 		m_has_normal = true;
 		normal.to_array(normal_array);
 	}
 
-	List<float> texcoord_array(default_allocator());
+	Array<float> texcoord_array(default_allocator());
 	if (!texcoord.is_nil())
 	{
 		m_has_texcoord = true;
@@ -107,9 +107,9 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		return;
 	}
 
-	List<uint16_t> position_index(default_allocator());
-	List<uint16_t> normal_index(default_allocator());
-	List<uint16_t> texcoord_index(default_allocator());
+	Array<uint16_t> position_index(default_allocator());
+	Array<uint16_t> normal_index(default_allocator());
+	Array<uint16_t> texcoord_index(default_allocator());
 
 	index[0].to_array(position_index);
 
@@ -125,7 +125,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	// Generate vb/ib
 	uint32_t idx = 0;
-	for (uint32_t i = 0; i < position_index.size(); i++)
+	for (uint32_t i = 0; i < array::size(position_index); i++)
 	{
 		MeshVertex v;
 
@@ -147,7 +147,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 		uint32_t f_idx = 0;
 		bool found = false;
-		for (; f_idx < m_vertices.size(); f_idx++)
+		for (; f_idx < array::size(m_vertices); f_idx++)
 		{
 			if (m_vertices[f_idx] == v)
 			{
@@ -158,12 +158,12 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 		if (found)
 		{
-			m_indices.push_back(f_idx);
+			array::push_back(m_indices, (uint16_t) f_idx);
 		}
 		else
 		{
-			m_vertices.push_back(v);
-			m_indices.push_back(idx);
+			array::push_back(m_vertices, v);
+			array::push_back(m_indices, (uint16_t) idx);
 			idx++;
 		}
 	}
@@ -177,12 +177,12 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	fs.close(file);
 
 	MeshData data;
-	data.vertices.num_vertices = m_vertices.size();
+	data.vertices.num_vertices = array::size(m_vertices);
 	data.vertices.format = VertexFormat::P3_N3_T2;
 	data.vertices.offset = sizeof(MeshHeader) + sizeof(MeshData);
 
-	data.indices.num_indices = m_indices.size();
-	data.indices.offset = sizeof(MeshHeader) + sizeof(MeshData) + m_vertices.size() * sizeof(MeshVertex);
+	data.indices.num_indices = array::size(m_indices);
+	data.indices.offset = sizeof(MeshHeader) + sizeof(MeshData) + array::size(m_vertices) * sizeof(MeshVertex);
 
 	// Write header
 	out_file->write((char*)&m_mesh_header, sizeof(MeshHeader));
@@ -191,14 +191,14 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	out_file->write((char*)&data, sizeof(MeshData));
 
 	// Write vertices
-	out_file->write((char*) m_vertices.begin(), m_vertices.size() * sizeof(MeshVertex));
+	out_file->write((char*) array::begin(m_vertices), array::size(m_vertices) * sizeof(MeshVertex));
 
 	// Write indices
-	out_file->write((char*) m_indices.begin(), m_indices.size() * sizeof(uint16_t));
+	out_file->write((char*) array::begin(m_indices), array::size(m_indices) * sizeof(uint16_t));
 
 	// Cleanup
-	m_vertices.clear();
-	m_indices.clear();
+	array::clear(m_vertices);
+	array::clear(m_indices);
 }
 
 } // namespace mesh_resource

+ 50 - 50
engine/resource/PackageResource.cpp

@@ -50,16 +50,16 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	JSONParser json(file_buf);
 	JSONElement root = json.root();
 
-	List<ResourceId> m_texture(default_allocator());
-	List<ResourceId> m_script(default_allocator());
-	List<ResourceId> m_sound(default_allocator());
-	List<ResourceId> m_mesh(default_allocator());
-	List<ResourceId> m_unit(default_allocator());
-	List<ResourceId> m_sprite(default_allocator());
-	List<ResourceId> m_physics(default_allocator());
-	List<ResourceId> m_materials(default_allocator());
-	List<ResourceId> m_guis(default_allocator());
-	List<ResourceId> m_fonts(default_allocator());
+	Array<ResourceId> m_texture(default_allocator());
+	Array<ResourceId> m_script(default_allocator());
+	Array<ResourceId> m_sound(default_allocator());
+	Array<ResourceId> m_mesh(default_allocator());
+	Array<ResourceId> m_unit(default_allocator());
+	Array<ResourceId> m_sprite(default_allocator());
+	Array<ResourceId> m_physics(default_allocator());
+	Array<ResourceId> m_materials(default_allocator());
+	Array<ResourceId> m_guis(default_allocator());
+	Array<ResourceId> m_fonts(default_allocator());
 
 	// Check for resource types
 	if (root.has_key("texture"))
@@ -80,7 +80,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(texture_name.c_str(), texture_name.length(), 0);
-			m_texture.push_back(id);
+			array::push_back(m_texture, id);
 		}
 	}
 
@@ -104,7 +104,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(lua_name.c_str(), lua_name.length(), 0);
-			m_script.push_back(id);
+			array::push_back(m_script, id);
 		}
 	}
 
@@ -127,7 +127,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(sound_name.c_str(), string::strlen(sound_name.c_str()), 0);
-			m_sound.push_back(id);
+			array::push_back(m_sound, id);
 		}
 	}
 
@@ -150,7 +150,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(mesh_name.c_str(), mesh_name.length(), 0);
-			m_mesh.push_back(id);
+			array::push_back(m_mesh, id);
 		}
 	}
 
@@ -172,7 +172,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(unit_name.c_str(), unit_name.length(), 0);
-			m_unit.push_back(id);
+			array::push_back(m_unit, id);
 		}
 	}
 
@@ -195,7 +195,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(sprite_name.c_str(), sprite_name.length(), 0);
-			m_sprite.push_back(id);
+			array::push_back(m_sprite, id);
 		}
 	}
 
@@ -218,7 +218,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(physics_name.c_str(), physics_name.length(), 0);
-			m_physics.push_back(id);
+			array::push_back(m_physics, id);
 		}	
 	}
 
@@ -241,7 +241,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(materials_name.c_str(), materials_name.length(), 0);
-			m_materials.push_back(id);
+			array::push_back(m_materials, id);
 		}
 	}
 
@@ -264,7 +264,7 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(guis_name.c_str(), guis_name.length(), 0);
-			m_guis.push_back(id);
+			array::push_back(m_guis, id);
 		}
 	}
 
@@ -287,21 +287,21 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 			ResourceId id;
 			id.id = hash::murmur2_64(font_name.c_str(), font_name.length(), 0);
-			m_fonts.push_back(id);
+			array::push_back(m_fonts, id);
 		}
 	}
 
 	PackageHeader header;
-	header.num_textures = m_texture.size();
-	header.num_scripts = m_script.size();
-	header.num_sounds = m_sound.size();
-	header.num_meshes = m_mesh.size();
-	header.num_units = m_unit.size();
-	header.num_sprites = m_sprite.size();
-	header.num_physics = m_physics.size();
-	header.num_materials = m_materials.size();
-	header.num_guis = m_guis.size();
-	header.num_fonts = m_fonts.size();
+	header.num_textures = array::size(m_texture);
+	header.num_scripts = array::size(m_script);
+	header.num_sounds = array::size(m_sound);
+	header.num_meshes = array::size(m_mesh);
+	header.num_units = array::size(m_unit);
+	header.num_sprites = array::size(m_sprite);
+	header.num_physics = array::size(m_physics);
+	header.num_materials = array::size(m_materials);
+	header.num_guis = array::size(m_guis);
+	header.num_fonts = array::size(m_fonts);
 
 	header.textures_offset = sizeof(PackageHeader);
 	header.scripts_offset  = header.textures_offset + sizeof(ResourceId) * header.num_textures;
@@ -316,45 +316,45 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	out_file->write((char*) &header, sizeof(PackageHeader));
 
-	if (m_texture.size() > 0)
+	if (array::size(m_texture) > 0)
 	{
-		out_file->write((char*) m_texture.begin(), sizeof(ResourceId) * header.num_textures);		
+		out_file->write((char*) array::begin(m_texture), sizeof(ResourceId) * header.num_textures);		
 	}
-	if (m_script.size() > 0)
+	if (array::size(m_script) > 0)
 	{
-		out_file->write((char*) m_script.begin(), sizeof(ResourceId) * header.num_scripts);
+		out_file->write((char*) array::begin(m_script), sizeof(ResourceId) * header.num_scripts);
 	}
-	if (m_sound.size() > 0)
+	if (array::size(m_sound) > 0)
 	{
-		out_file->write((char*) m_sound.begin(), sizeof(ResourceId) * header.num_sounds);
+		out_file->write((char*) array::begin(m_sound), sizeof(ResourceId) * header.num_sounds);
 	}
-	if (m_mesh.size() > 0)
+	if (array::size(m_mesh) > 0)
 	{
-		out_file->write((char*) m_mesh.begin(), sizeof(ResourceId) * header.num_meshes);
+		out_file->write((char*) array::begin(m_mesh), sizeof(ResourceId) * header.num_meshes);
 	}
-	if (m_unit.size() > 0)
+	if (array::size(m_unit) > 0)
 	{
-		out_file->write((char*) m_unit.begin(), sizeof(ResourceId) * header.num_units);	
+		out_file->write((char*) array::begin(m_unit), sizeof(ResourceId) * header.num_units);	
 	}
-	if (m_sprite.size() > 0)
+	if (array::size(m_sprite) > 0)
 	{
-		out_file->write((char*) m_sprite.begin(), sizeof(ResourceId) * header.num_sprites);
+		out_file->write((char*) array::begin(m_sprite), sizeof(ResourceId) * header.num_sprites);
 	}
-	if (m_physics.size() > 0)
+	if (array::size(m_physics) > 0)
 	{
-		out_file->write((char*) m_physics.begin(), sizeof(ResourceId) * header.num_physics);
+		out_file->write((char*) array::begin(m_physics), sizeof(ResourceId) * header.num_physics);
 	}
-	if (m_materials.size() > 0)
+	if (array::size(m_materials) > 0)
 	{
-		out_file->write((char*) m_materials.begin(), sizeof(ResourceId) * header.num_materials);
+		out_file->write((char*) array::begin(m_materials), sizeof(ResourceId) * header.num_materials);
 	}
-	if (m_guis.size() > 0)
+	if (array::size(m_guis) > 0)
 	{
-		out_file->write((char*) m_guis.begin(), sizeof(ResourceId) * header.num_guis);
+		out_file->write((char*) array::begin(m_guis), sizeof(ResourceId) * header.num_guis);
 	}
-	if (m_fonts.size() > 0)
+	if (array::size(m_fonts) > 0)
 	{
-		out_file->write((char*) m_fonts.begin(), sizeof(ResourceId) * header.num_fonts);
+		out_file->write((char*) array::begin(m_fonts), sizeof(ResourceId) * header.num_fonts);
 	}
 }
 

+ 65 - 65
engine/resource/PhysicsResource.cpp

@@ -85,7 +85,7 @@ void parse_controller(JSONElement e, PhysicsController& controller)
 }
 
 //-----------------------------------------------------------------------------
-void parse_shapes(JSONElement e, List<PhysicsShape>& shapes)
+void parse_shapes(JSONElement e, Array<PhysicsShape>& shapes)
 {
 	Vector<DynamicString> keys(default_allocator());
 	e.to_keys(keys);
@@ -164,12 +164,12 @@ void parse_shapes(JSONElement e, List<PhysicsShape>& shapes)
 			}
 		}
 
-		shapes.push_back(ps);
+		array::push_back(shapes, ps);
 	}
 }
 
 //-----------------------------------------------------------------------------
-void parse_actors(JSONElement e, List<PhysicsActor>& actors, List<PhysicsShape>& actor_shapes, List<uint32_t>& shape_indices)
+void parse_actors(JSONElement e, Array<PhysicsActor>& actors, Array<PhysicsShape>& actor_shapes, Array<uint32_t>& shape_indices)
 {
 	Vector<DynamicString> keys(default_allocator());
 	e.to_keys(keys);
@@ -187,15 +187,15 @@ void parse_actors(JSONElement e, List<PhysicsActor>& actors, List<PhysicsShape>&
 		pa.actor_class = clasz.to_string_id();
 		pa.num_shapes = shapes.size();
 
-		actors.push_back(pa);
-		shape_indices.push_back(shape_indices.size());
+		array::push_back(actors, pa);
+		array::push_back(shape_indices, array::size(shape_indices));
 
 		parse_shapes(shapes, actor_shapes);
 	}
 }
 
 //-----------------------------------------------------------------------------
-void parse_joints(JSONElement e, List<PhysicsJoint>& joints)
+void parse_joints(JSONElement e, Array<PhysicsJoint>& joints)
 {
 	Vector<DynamicString> keys(default_allocator());
 	e.to_keys(keys);
@@ -278,7 +278,7 @@ void parse_joints(JSONElement e, List<PhysicsJoint>& joints)
 			}
 		}
 
-		joints.push_back(pj);
+		array::push_back(joints, pj);
 	}
 }
 
@@ -307,10 +307,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		m_has_controller = true;
 	}
 
-	List<PhysicsActor> m_actors(default_allocator());
-	List<uint32_t> m_shapes_indices(default_allocator());
-	List<PhysicsShape> m_shapes(default_allocator());
-	List<PhysicsJoint> m_joints(default_allocator());
+	Array<PhysicsActor> m_actors(default_allocator());
+	Array<uint32_t> m_shapes_indices(default_allocator());
+	Array<PhysicsShape> m_shapes(default_allocator());
+	Array<PhysicsJoint> m_joints(default_allocator());
 
 	if (root.has_key("actors")) parse_actors(root.key("actors"), m_actors, m_shapes, m_shapes_indices);
 	if (root.has_key("joints")) parse_joints(root.key("joints"), m_joints);
@@ -321,10 +321,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	PhysicsHeader h;
 	h.version = 1;
 	h.num_controllers = m_has_controller ? 1 : 0;
-	h.num_actors = m_actors.size();
-	h.num_shapes_indices = m_shapes_indices.size();
-	h.num_shapes = m_shapes.size();
-	h.num_joints = m_joints.size();
+	h.num_actors = array::size(m_actors);
+	h.num_shapes_indices = array::size(m_shapes_indices);
+	h.num_shapes = array::size(m_shapes);
+	h.num_joints = array::size(m_joints);
 
 	uint32_t offt = sizeof(PhysicsHeader);
 	h.controller_offset = offt; offt += sizeof(PhysicsController) * h.num_controllers;
@@ -340,24 +340,24 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		out_file->write((char*) &m_controller, sizeof(PhysicsController));
 	}
 
-	if (m_actors.size())
+	if (array::size(m_actors))
 	{
-		out_file->write((char*) m_actors.begin(), sizeof(PhysicsActor) * m_actors.size());
+		out_file->write((char*) array::begin(m_actors), sizeof(PhysicsActor) * array::size(m_actors));
 	}
 
-	if (m_shapes_indices.size())
+	if (array::size(m_shapes_indices))
 	{
-		out_file->write((char*) m_shapes_indices.begin(), sizeof(uint32_t) * m_shapes_indices.size());
+		out_file->write((char*) array::begin(m_shapes_indices), sizeof(uint32_t) * array::size(m_shapes_indices));
 	}
 
-	if (m_shapes.size())
+	if (array::size(m_shapes))
 	{
-		out_file->write((char*) m_shapes.begin(), sizeof(PhysicsShape) * m_shapes.size());
+		out_file->write((char*) array::begin(m_shapes), sizeof(PhysicsShape) * array::size(m_shapes));
 	}
 
-	if (m_joints.size())
+	if (array::size(m_joints))
 	{
-		out_file->write((char*) m_joints.begin(), sizeof(PhysicsJoint) * m_joints.size());
+		out_file->write((char*) array::begin(m_joints), sizeof(PhysicsJoint) * array::size(m_joints));
 	}
 }
 } // namespace physics_resource
@@ -381,14 +381,14 @@ namespace physics_config_resource
 		uint32_t mask;
 	};
 
-	uint32_t collides_with_to_mask(Vector<DynamicString>& collides_with, List<NameToMask>& name_to_mask)
+	uint32_t collides_with_to_mask(Vector<DynamicString>& collides_with, Array<NameToMask>& name_to_mask)
 	{
 		uint32_t mask = 0;
 
 		for (uint32_t i = 0; i < collides_with.size(); i++)
 		{
 			StringId32 cur_name = collides_with[i].to_string_id();
-			for (uint32_t j = 0; j < name_to_mask.size(); j++)
+			for (uint32_t j = 0; j < array::size(name_to_mask); j++)
 			{
 				if (cur_name == name_to_mask[j].name) mask |= name_to_mask[j].mask;
 			}
@@ -397,10 +397,10 @@ namespace physics_config_resource
 		return mask;
 	}
 
-	uint32_t collision_filter_to_mask(const char* filter, List<NameToMask> name_to_mask)
+	uint32_t collision_filter_to_mask(const char* filter, Array<NameToMask> name_to_mask)
 	{
 		StringId32 filter_hash = hash::murmur2_32(filter, string::strlen(filter));
-		for (uint32_t i = 0; i < name_to_mask.size(); i++)
+		for (uint32_t i = 0; i < array::size(name_to_mask); i++)
 		{
 			if (name_to_mask[i].name == filter_hash) return name_to_mask[i].mask;
 		}
@@ -409,7 +409,7 @@ namespace physics_config_resource
 		return 0;
 	}
 
-	void parse_materials(JSONElement e, List<ObjectName>& names, List<PhysicsMaterial>& objects)
+	void parse_materials(JSONElement e, Array<ObjectName>& names, Array<PhysicsMaterial>& objects)
 	{
 		Vector<DynamicString> keys(default_allocator());
 		e.to_keys(keys);
@@ -432,12 +432,12 @@ namespace physics_config_resource
 			mat.dynamic_friction = dynamic_friction.to_float();
 			mat.restitution = restitution.to_float();
 
-			names.push_back(mat_name);
-			objects.push_back(mat);
+			array::push_back(names, mat_name);
+			array::push_back(objects, mat);
 		}
 	}
 
-	void parse_shapes(JSONElement e, List<NameToMask>& name_to_mask, List<ObjectName>& names, List<PhysicsShape2>& objects)
+	void parse_shapes(JSONElement e, Array<NameToMask>& name_to_mask, Array<ObjectName>& names, Array<PhysicsShape2>& objects)
 	{
 		Vector<DynamicString> keys(default_allocator());
 		e.to_keys(keys);
@@ -459,12 +459,12 @@ namespace physics_config_resource
 			DynamicString cfilter; collision_filter.to_string(cfilter);
 			ps2.collision_filter = collision_filter_to_mask(cfilter.c_str(), name_to_mask);
 
-			names.push_back(shape_name);
-			objects.push_back(ps2);
+			array::push_back(names, shape_name);
+			array::push_back(objects, ps2);
 		}
 	}
 
-	void parse_actors(JSONElement e, List<ObjectName>& names, List<PhysicsActor2>& objects)
+	void parse_actors(JSONElement e, Array<ObjectName>& names, Array<PhysicsActor2>& objects)
 	{
 		Vector<DynamicString> keys(default_allocator());
 		e.to_keys(keys);
@@ -502,12 +502,12 @@ namespace physics_config_resource
 				pa2.flags |= disable_gravity.to_bool() ? PhysicsActor2::DISABLE_GRAVITY : 0;
 			}
 
-			names.push_back(actor_name);
-			objects.push_back(pa2);
+			array::push_back(names, actor_name);
+			array::push_back(objects, pa2);
 		}
 	}
 
-	void parse_collision_filters(JSONElement e, List<ObjectName>& names, List<PhysicsCollisionFilter>& objects, List<NameToMask>& name_to_mask)
+	void parse_collision_filters(JSONElement e, Array<ObjectName>& names, Array<PhysicsCollisionFilter>& objects, Array<NameToMask>& name_to_mask)
 	{
 		Vector<DynamicString> keys(default_allocator());
 		e.to_keys(keys);
@@ -518,7 +518,7 @@ namespace physics_config_resource
 			NameToMask ntm;
 			ntm.name = keys[i].to_string_id();
 			ntm.mask = 1 << i;
-			name_to_mask.push_back(ntm);
+			array::push_back(name_to_mask, ntm);
 		}
 
 		for (uint32_t i = 0; i < keys.size(); i++)
@@ -540,8 +540,8 @@ namespace physics_config_resource
 
 			printf("FILTER: %s, mask = %X\n", keys[i].c_str(), pcf.mask);
 
-			names.push_back(filter_name);
-			objects.push_back(pcf);
+			array::push_back(names, filter_name);
+			array::push_back(objects, pcf);
 		}		
 	}
 
@@ -554,15 +554,15 @@ namespace physics_config_resource
 		JSONParser json(buf);
 		JSONElement root = json.root();
 
-		List<ObjectName> material_names(default_allocator());
-		List<PhysicsMaterial> material_objects(default_allocator());
-		List<ObjectName> shape_names(default_allocator());
-		List<PhysicsShape2> shape_objects(default_allocator());
-		List<ObjectName> actor_names(default_allocator());
-		List<PhysicsActor2> actor_objects(default_allocator());
-		List<ObjectName> filter_names(default_allocator());
-		List<PhysicsCollisionFilter> filter_objects(default_allocator());
-		List<NameToMask> name_to_mask(default_allocator());
+		Array<ObjectName> material_names(default_allocator());
+		Array<PhysicsMaterial> material_objects(default_allocator());
+		Array<ObjectName> shape_names(default_allocator());
+		Array<PhysicsShape2> shape_objects(default_allocator());
+		Array<ObjectName> actor_names(default_allocator());
+		Array<PhysicsActor2> actor_objects(default_allocator());
+		Array<ObjectName> filter_names(default_allocator());
+		Array<PhysicsCollisionFilter> filter_objects(default_allocator());
+		Array<NameToMask> name_to_mask(default_allocator());
 
 		// Parse materials
 		if (root.has_key("collision_filters")) parse_collision_filters(root.key("collision_filters"), filter_names, filter_objects, name_to_mask);
@@ -574,17 +574,17 @@ namespace physics_config_resource
 		fs.close(file);
 
 		// Sort objects by name
-		std::sort(material_names.begin(), material_names.end(), ObjectName());
-		std::sort(shape_names.begin(), shape_names.end(), ObjectName());
-		std::sort(actor_names.begin(), actor_names.end(), ObjectName());
-		std::sort(filter_names.begin(), filter_names.end(), ObjectName());
+		std::sort(array::begin(material_names), array::end(material_names), ObjectName());
+		std::sort(array::begin(shape_names), array::end(shape_names), ObjectName());
+		std::sort(array::begin(actor_names), array::end(actor_names), ObjectName());
+		std::sort(array::begin(filter_names), array::end(filter_names), ObjectName());
 
 		// Setup struct for writing
 		PhysicsConfigHeader header;
-		header.num_materials = material_names.size();
-		header.num_shapes = shape_names.size();
-		header.num_actors = actor_names.size();
-		header.num_filters = filter_names.size();
+		header.num_materials = array::size(material_names);
+		header.num_shapes = array::size(shape_names);
+		header.num_actors = array::size(actor_names);
+		header.num_filters = array::size(filter_names);
 
 		uint32_t offt = sizeof(PhysicsConfigHeader);
 		header.materials_offset = offt;
@@ -609,13 +609,13 @@ namespace physics_config_resource
 		if (header.num_materials)
 		{
 			// Write material names
-			for (uint32_t i = 0; i < material_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(material_names); i++)
 			{
 				out_file->write((char*) &material_names[i].name, sizeof(StringId32));
 			}
 
 			// Write material objects
-			for (uint32_t i = 0; i < material_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(material_names); i++)
 			{
 				out_file->write((char*) &material_objects[material_names[i].index], sizeof(PhysicsMaterial));
 			}
@@ -624,13 +624,13 @@ namespace physics_config_resource
 		if (header.num_shapes)
 		{
 			// Write shape names
-			for (uint32_t i = 0; i < shape_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(shape_names); i++)
 			{
 				out_file->write((char*) &shape_names[i].name, sizeof(StringId32));
 			}
 
 			// Write material objects
-			for (uint32_t i = 0; i < shape_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(shape_names); i++)
 			{
 				out_file->write((char*) &shape_objects[shape_names[i].index], sizeof(PhysicsShape2));
 			}
@@ -639,13 +639,13 @@ namespace physics_config_resource
 		if (header.num_actors)
 		{
 			// Write shape names
-			for (uint32_t i = 0; i < actor_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(actor_names); i++)
 			{
 				out_file->write((char*) &actor_names[i].name, sizeof(StringId32));
 			}
 
 			// Write material objects
-			for (uint32_t i = 0; i < actor_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(actor_names); i++)
 			{
 				out_file->write((char*) &actor_objects[actor_names[i].index], sizeof(PhysicsActor2));
 			}
@@ -654,13 +654,13 @@ namespace physics_config_resource
 		if (header.num_filters)
 		{
 			// Write shape names
-			for (uint32_t i = 0; i < filter_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(filter_names); i++)
 			{
 				out_file->write((char*) &filter_names[i].name, sizeof(StringId32));
 			}
 
 			// Write material objects
-			for (uint32_t i = 0; i < filter_names.size(); i++)
+			for (uint32_t i = 0; i < array::size(filter_names); i++)
 			{
 				out_file->write((char*) &filter_objects[filter_names[i].index], sizeof(PhysicsCollisionFilter));
 			}

+ 5 - 4
engine/resource/ResourceLoader.cpp

@@ -27,6 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "ResourceLoader.h"
 #include "ResourceRegistry.h"
 #include "Log.h"
+#include "Queue.h"
 
 namespace crown
 {
@@ -59,7 +60,7 @@ LoadResourceId ResourceLoader::load_resource(uint32_t type, ResourceId resource)
 	lr.type = type;
 	lr.resource = resource;
 
-	m_requests.push_back(lr);
+	queue::push_back(m_requests, lr);
 
 	m_results[lr_id % MAX_LOAD_REQUESTS].status = LRS_QUEUED;
 
@@ -98,15 +99,15 @@ int32_t ResourceLoader::run()
 	while (m_should_run)
 	{
 		m_requests_mutex.lock();
-		while (m_requests.empty() && m_should_run)
+		while (queue::empty(m_requests) && m_should_run)
 		{
 			m_full.wait(m_requests_mutex);
 		}
 
 		if (m_should_run)
 		{
-			LoadResource request = m_requests.front();
-			m_requests.pop_front();
+			LoadResource request = queue::front(m_requests);
+			queue::pop_front(m_requests);
 
 			m_requests_mutex.unlock();
 

+ 1 - 2
engine/resource/ResourceLoader.h

@@ -29,8 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "Resource.h"
 #include "OsThread.h"
-#include "Queue.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Mutex.h"
 #include "Cond.h"
 #include "OS.h"

+ 11 - 10
engine/resource/ResourceManager.cpp

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Hash.h"
 #include "TempAllocator.h"
 #include "DynamicString.h"
+#include "Queue.h"
 
 namespace crown
 {
@@ -75,9 +76,9 @@ void ResourceManager::unload(ResourceId name, bool force)
 		resource_on_unload(entry->type, m_resource_heap, entry->resource);
 
 		// Swap with last
-		ResourceEntry temp = m_resources[m_resources.size() - 1];
+		ResourceEntry temp = m_resources[array::size(m_resources) - 1];
 		(*entry) = temp;
-		m_resources.pop_back();
+		array::pop_back(m_resources);
 	}
 }
 
@@ -128,7 +129,7 @@ uint32_t ResourceManager::references(ResourceId name) const
 //-----------------------------------------------------------------------------
 void ResourceManager::flush()
 {
-	while (!m_pendings.empty())
+	while (!queue::empty(m_pendings))
 	{
 		poll_resource_loader();
 	}
@@ -158,21 +159,21 @@ ResourceId ResourceManager::resource_id(const char* type, const char* name) cons
 //-----------------------------------------------------------------------------
 ResourceEntry* ResourceManager::find(ResourceId id) const
 {
-	const ResourceEntry* entry = std::find(m_resources.begin(), m_resources.end(), id);
+	const ResourceEntry* entry = std::find(array::begin(m_resources), array::end(m_resources), id);
 
-	return entry != m_resources.end() ? const_cast<ResourceEntry*>(entry) : NULL;
+	return entry != array::end(m_resources) ? const_cast<ResourceEntry*>(entry) : NULL;
 }
 
 //-----------------------------------------------------------------------------
 void ResourceManager::poll_resource_loader()
 {
-	if (!m_pendings.empty())
+	if (!queue::empty(m_pendings))
 	{
-		PendingRequest request = m_pendings.front();
+		PendingRequest request = queue::front(m_pendings);
 
 		if (m_loader.load_resource_status(request.id) == LRS_LOADED)
 		{
-			m_pendings.pop_front();
+			queue::pop_front(m_pendings);
 
 			void* data = m_loader.load_resource_data(request.id);
 			online(request.resource, data);
@@ -196,14 +197,14 @@ ResourceId ResourceManager::load(uint32_t type, ResourceId name)
 		entry.references = 1;
 		entry.resource = NULL;
 
-		m_resources.push_back(entry);
+		array::push_back(m_resources, entry);
 
 		// Issue request to resource loader
 		PendingRequest pr;
 		pr.resource = name;
 		pr.id = m_loader.load_resource(type, name);
 
-		m_pendings.push_back(pr);
+		queue::push_back(m_pendings, pr);
 
 		return name;
 	}

+ 2 - 2
engine/resource/ResourceManager.h

@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Resource.h"
 #include "ProxyAllocator.h"
 #include "ResourceLoader.h"
@@ -126,7 +126,7 @@ private:
 	uint32_t				m_seed;
 
 	Queue<PendingRequest>	m_pendings;
-	List<ResourceEntry>		m_resources;
+	Array<ResourceEntry>		m_resources;
 
 private:
 

+ 26 - 25
engine/resource/SpriteResource.cpp

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "JSONParser.h"
 #include "SpriteResource.h"
 #include "StringUtils.h"
+#include "Array.h"
 
 namespace crown
 {
@@ -50,7 +51,7 @@ struct FrameData
 };
 
 //-----------------------------------------------------------------------------
-void parse_frame(JSONElement frame, List<StringId32>& names, List<FrameData>& regions)
+void parse_frame(JSONElement frame, Array<StringId32>& names, Array<FrameData>& regions)
 {
 	JSONElement name = frame.key("name");
 	JSONElement region = frame.key("region");
@@ -71,8 +72,8 @@ void parse_frame(JSONElement frame, List<StringId32>& names, List<FrameData>& re
 	fd.scale_x = scale[0].to_float();
 	fd.scale_y = scale[1].to_float();
 
-	names.push_back(name_hash);
-	regions.push_back(fd);
+	array::push_back(names, name_hash);
+	array::push_back(regions, fd);
 }
 
 //-----------------------------------------------------------------------------
@@ -87,10 +88,10 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	float width;
 	float height;
-	List<StringId32>		m_names(default_allocator());
-	List<FrameData> 		m_regions(default_allocator());
-	List<float>				m_vertices(default_allocator());
-	List<uint16_t>			m_indices(default_allocator());
+	Array<StringId32>		m_names(default_allocator());
+	Array<FrameData> 		m_regions(default_allocator());
+	Array<float>			m_vertices(default_allocator());
+	Array<uint16_t>			m_indices(default_allocator());
 
 	// Read width/height
 	width = root.key("width").to_float();
@@ -126,20 +127,20 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 		const float x1 = fd.scale_x * ( w * 0.5) + fd.offset_x;
 		const float y1 = fd.scale_y * ( h * 0.5) + fd.offset_y;
 
-		m_vertices.push_back(x0); m_vertices.push_back(y0); // position
-		m_vertices.push_back(u0); m_vertices.push_back(v0); // uv
+		array::push_back(m_vertices, x0); array::push_back(m_vertices, y0); // position
+		array::push_back(m_vertices, u0); array::push_back(m_vertices, v0); // uv
 
-		m_vertices.push_back(x1); m_vertices.push_back(y0); // position
-		m_vertices.push_back(u1); m_vertices.push_back(v0); // uv
+		array::push_back(m_vertices, x1); array::push_back(m_vertices, y0); // position
+		array::push_back(m_vertices, u1); array::push_back(m_vertices, v0); // uv
 
-		m_vertices.push_back(x1); m_vertices.push_back(y1); // position
-		m_vertices.push_back(u1); m_vertices.push_back(v1); // uv
+		array::push_back(m_vertices, x1); array::push_back(m_vertices, y1); // position
+		array::push_back(m_vertices, u1); array::push_back(m_vertices, v1); // uv
 
-		m_vertices.push_back(x0); m_vertices.push_back(y1); // position
-		m_vertices.push_back(u0); m_vertices.push_back(v1); // uv
+		array::push_back(m_vertices, x0); array::push_back(m_vertices, y1); // position
+		array::push_back(m_vertices, u0); array::push_back(m_vertices, v1); // uv
 
-		m_indices.push_back(num_idx); m_indices.push_back(num_idx + 1); m_indices.push_back(num_idx + 2);
-		m_indices.push_back(num_idx); m_indices.push_back(num_idx + 2); m_indices.push_back(num_idx + 3);
+		array::push_back(m_indices, uint16_t(num_idx)); array::push_back(m_indices, uint16_t(num_idx + 1)); array::push_back(m_indices, uint16_t(num_idx + 2));
+		array::push_back(m_indices, uint16_t(num_idx)); array::push_back(m_indices, uint16_t(num_idx + 2)); array::push_back(m_indices, uint16_t(num_idx + 3));
 		num_idx += 4;
 	}
 
@@ -147,19 +148,19 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	default_allocator().deallocate(buf);
 
 	SpriteHeader h;
-	h.num_frames = m_names.size();
-	h.num_vertices = m_vertices.size() / 4; // 4 components per vertex
-	h.num_indices = m_indices.size();
+	h.num_frames = array::size(m_names);
+	h.num_vertices = array::size(m_vertices) / 4; // 4 components per vertex
+	h.num_indices = array::size(m_indices);
 
 	uint32_t offt = sizeof(SpriteHeader);
 	/*h.frame_names_offset    = offt*/; offt += sizeof(StringId32) * h.num_frames;
-	h.vertices_offset = offt; offt += sizeof(float) * m_vertices.size();
-	h.indices_offset = offt; offt += sizeof(uint16_t) * m_indices.size();
+	h.vertices_offset = offt; offt += sizeof(float) * array::size(m_vertices);
+	h.indices_offset = offt; offt += sizeof(uint16_t) * array::size(m_indices);
 
 	out_file->write((char*) &h, sizeof(SpriteHeader));
-	out_file->write((char*) m_names.begin(), sizeof(StringId32) * m_names.size());
-	out_file->write((char*) m_vertices.begin(), sizeof(float) * m_vertices.size());
-	out_file->write((char*) m_indices.begin(), sizeof(uint16_t) * m_indices.size());
+	out_file->write((char*) array::begin(m_names), sizeof(StringId32) * array::size(m_names));
+	out_file->write((char*) array::begin(m_vertices), sizeof(float) * array::size(m_vertices));
+	out_file->write((char*) array::begin(m_indices), sizeof(uint16_t) * array::size(m_indices));
 }
 
 } // namespace sprite_resource

+ 1 - 1
engine/resource/SpriteResource.h

@@ -34,7 +34,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "File.h"
 #include "OS.h"
 #include "StringUtils.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Bundle.h"
 #include "Device.h"
 #include "ResourceManager.h"

+ 28 - 28
engine/resource/UnitResource.cpp

@@ -29,7 +29,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Filesystem.h"
 #include "Hash.h"
 #include "JSONParser.h"
-#include "List.h"
+#include "ContainerTypes.h"
 #include "Log.h"
 #include "Matrix4x4.h"
 #include "PhysicsTypes.h"
@@ -68,12 +68,12 @@ struct GraphNodeDepth
 };
 
 //-----------------------------------------------------------------------------
-uint32_t compute_link_depth(const GraphNode& node, const List<GraphNode>& nodes)
+uint32_t compute_link_depth(const GraphNode& node, const Array<GraphNode>& nodes)
 {
 	if (node.parent == NO_PARENT) return 0;
 	else
 	{
-		for (uint32_t i = 0; i < nodes.size(); i++)
+		for (uint32_t i = 0; i < array::size(nodes); i++)
 		{
 			if (nodes[i].name == node.parent)
 			{
@@ -86,9 +86,9 @@ uint32_t compute_link_depth(const GraphNode& node, const List<GraphNode>& nodes)
 }
 
 //-----------------------------------------------------------------------------
-uint32_t find_node_index(StringId32 name, const List<GraphNodeDepth>& node_depths)
+uint32_t find_node_index(StringId32 name, const Array<GraphNodeDepth>& node_depths)
 {
-	for (uint32_t i = 0; i < node_depths.size(); i++)
+	for (uint32_t i = 0; i < array::size(node_depths); i++)
 	{
 		if (node_depths[i].name == name)
 		{
@@ -101,12 +101,12 @@ uint32_t find_node_index(StringId32 name, const List<GraphNodeDepth>& node_depth
 }
 
 //-----------------------------------------------------------------------------
-int32_t find_node_parent_index(uint32_t node, const List<GraphNode>& nodes, const List<GraphNodeDepth>& node_depths)
+int32_t find_node_parent_index(uint32_t node, const Array<GraphNode>& nodes, const Array<GraphNodeDepth>& node_depths)
 {
 	StringId32 parent_name = nodes[node_depths[node].index].parent;
 
 	if (parent_name == NO_PARENT) return -1;
-	for (uint32_t i = 0; i < node_depths.size(); i++)
+	for (uint32_t i = 0; i < array::size(node_depths); i++)
 	{
 		if (parent_name == node_depths[i].name)
 		{
@@ -119,7 +119,7 @@ int32_t find_node_parent_index(uint32_t node, const List<GraphNode>& nodes, cons
 }
 
 //-----------------------------------------------------------------------------
-void parse_nodes(JSONElement e, List<GraphNode>& nodes, List<GraphNodeDepth>& node_depths)
+void parse_nodes(JSONElement e, Array<GraphNode>& nodes, Array<GraphNodeDepth>& node_depths)
 {
 	Vector<DynamicString> keys(default_allocator());
 	e.to_keys(keys);
@@ -147,16 +147,16 @@ void parse_nodes(JSONElement e, List<GraphNode>& nodes, List<GraphNodeDepth>& no
 
 		GraphNodeDepth gnd;
 		gnd.name = gn.name;
-		gnd.index = nodes.size();
+		gnd.index = array::size(nodes);
 		gnd.depth = 0;
 
-		nodes.push_back(gn);
-		node_depths.push_back(gnd);
+		array::push_back(nodes, gn);
+		array::push_back(node_depths, gnd);
 	}
 }
 
 //-----------------------------------------------------------------------------
-void parse_cameras(JSONElement e, List<UnitCamera>& cameras, const List<GraphNodeDepth>& node_depths)
+void parse_cameras(JSONElement e, Array<UnitCamera>& cameras, const Array<GraphNodeDepth>& node_depths)
 {
 	Vector<DynamicString> keys(default_allocator());
 	e.to_keys(keys);
@@ -175,12 +175,12 @@ void parse_cameras(JSONElement e, List<UnitCamera>& cameras, const List<GraphNod
 		cn.name = hash::murmur2_32(camera_name, string::strlen(camera_name));
 		cn.node = find_node_index(node_name_hash, node_depths);
 
-		cameras.push_back(cn);
+		array::push_back(cameras, cn);
 	}
 }
 
 //-----------------------------------------------------------------------------
-void parse_renderables(JSONElement e, List<UnitRenderable>& renderables, const List<GraphNodeDepth>& node_depths)
+void parse_renderables(JSONElement e, Array<UnitRenderable>& renderables, const Array<GraphNodeDepth>& node_depths)
 {
 	Vector<DynamicString> keys(default_allocator());
 	e.to_keys(keys);
@@ -220,7 +220,7 @@ void parse_renderables(JSONElement e, List<UnitRenderable>& renderables, const L
 		}
 		rn.resource.id = hash::murmur2_64(res_name.c_str(), res_name.length(), 0);
 
-		renderables.push_back(rn);
+		array::push_back(renderables, rn);
 	}
 }
 
@@ -238,20 +238,20 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 
 	ResourceId				m_physics_resource;
 	ResourceId				m_material_resource;
-	List<GraphNode>			m_nodes(default_allocator());
-	List<GraphNodeDepth>	m_node_depths(default_allocator());
-	List<UnitCamera>		m_cameras(default_allocator());
-	List<UnitRenderable>	m_renderables(default_allocator());
+	Array<GraphNode>			m_nodes(default_allocator());
+	Array<GraphNodeDepth>	m_node_depths(default_allocator());
+	Array<UnitCamera>		m_cameras(default_allocator());
+	Array<UnitRenderable>	m_renderables(default_allocator());
 
 	// Check for nodes
 	if (root.has_key("nodes")) parse_nodes(root.key("nodes"), m_nodes, m_node_depths);
 
-	for (uint32_t i = 0; i < m_nodes.size(); i++)
+	for (uint32_t i = 0; i < array::size(m_nodes); i++)
 	{
 		m_node_depths[i].depth = compute_link_depth(m_nodes[i], m_nodes);
 	}
 
-	std::sort(m_node_depths.begin(), m_node_depths.end(), GraphNodeDepth());
+	std::sort(array::begin(m_node_depths), array::end(m_node_depths), GraphNodeDepth());
 
 	if (root.has_key("renderables")) parse_renderables(root.key("renderables"), m_renderables, m_node_depths);
 	if (root.has_key("cameras")) parse_cameras(root.key("cameras"), m_cameras, m_node_depths);
@@ -286,9 +286,9 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	UnitHeader h;
 	h.physics_resource = m_physics_resource;
 	h.material_resource = m_material_resource;
-	h.num_renderables = m_renderables.size();
-	h.num_cameras = m_cameras.size();
-	h.num_scene_graph_nodes = m_nodes.size();
+	h.num_renderables = array::size(m_renderables);
+	h.num_cameras = array::size(m_cameras);
+	h.num_scene_graph_nodes = array::size(m_nodes);
 
 	uint32_t offt = sizeof(UnitHeader);
 	h.renderables_offset         = offt; offt += sizeof(UnitRenderable) * h.num_renderables;
@@ -299,12 +299,12 @@ void compile(Filesystem& fs, const char* resource_path, File* out_file)
 	out_file->write((char*) &h, sizeof(UnitHeader));
 
 	// Write renderables
-	if (m_renderables.size())
-		out_file->write((char*) m_renderables.begin(), sizeof(UnitRenderable) * h.num_renderables);
+	if (array::size(m_renderables))
+		out_file->write((char*) array::begin(m_renderables), sizeof(UnitRenderable) * h.num_renderables);
 
 	// Write cameras
-	if (m_cameras.size())
-		out_file->write((char*) m_cameras.begin(), sizeof(UnitCamera) * h.num_cameras);
+	if (array::size(m_cameras))
+		out_file->write((char*) array::begin(m_cameras), sizeof(UnitCamera) * h.num_cameras);
 
 	// Write node poses
 	for (uint32_t i = 0; i < h.num_scene_graph_nodes; i++)

+ 1 - 1
engine/tests/containers.cpp

@@ -8,7 +8,7 @@ int main()
 {
 	HeapAllocator allocator;
 
-	List<int> int_list(allocator);
+	Array<int> int_list(allocator);
 
 	CE_ASSERT(int_list.size() == 0, "Size differs from expected value");
 

+ 6 - 5
engine/world/SceneGraphManager.cpp

@@ -26,6 +26,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #include "SceneGraphManager.h"
 #include "SceneGraph.h"
+#include "Array.h"
 
 namespace crown
 {
@@ -44,9 +45,9 @@ SceneGraphManager::~SceneGraphManager()
 //-----------------------------------------------------------------------------
 SceneGraph* SceneGraphManager::create_scene_graph()
 {
-	uint32_t index = m_graphs.size();
+	uint32_t index = array::size(m_graphs);
 	SceneGraph* sg = CE_NEW(default_allocator(), SceneGraph)(default_allocator(), index);
-	m_graphs.push_back(sg);
+	array::push_back(m_graphs, sg);
 	return sg;
 }
 
@@ -55,9 +56,9 @@ void SceneGraphManager::destroy_scene_graph(SceneGraph* sg)
 {
 	CE_ASSERT_NOT_NULL(sg);
 
-	m_graphs[sg->m_index] = m_graphs[m_graphs.size() - 1];
+	m_graphs[sg->m_index] = m_graphs[array::size(m_graphs) - 1];
 	m_graphs[sg->m_index]->m_index = sg->m_index;
-	m_graphs.pop_back();
+	array::pop_back(m_graphs);
 
 	CE_DELETE(default_allocator(), sg);
 }
@@ -65,7 +66,7 @@ void SceneGraphManager::destroy_scene_graph(SceneGraph* sg)
 //-----------------------------------------------------------------------------
 void SceneGraphManager::update()
 {
-	for (uint32_t i = 0; i < m_graphs.size(); i++)
+	for (uint32_t i = 0; i < array::size(m_graphs); i++)
 	{
 		m_graphs[i]->update();
 	}

+ 2 - 2
engine/world/SceneGraphManager.h

@@ -26,7 +26,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 
 #pragma once
 
-#include "List.h"
+#include "ContainerTypes.h"
 
 namespace crown
 {
@@ -52,7 +52,7 @@ public:
 
 private:
 
-	List<SceneGraph*>	m_graphs;
+	Array<SceneGraph*>	m_graphs;
 };
 
 } // namespace crown