Преглед изворни кода

Add allocator awareness support

Daniele Bartolini пре 10 година
родитељ
комит
2aff4e140f

+ 25 - 3
src/core/containers/container_types.h

@@ -8,6 +8,7 @@
 #include "types.h"
 #include "types.h"
 #include "memory_types.h"
 #include "memory_types.h"
 #include "functional.h"
 #include "functional.h"
+#include "pair.h"
 
 
 namespace crown
 namespace crown
 {
 {
@@ -39,6 +40,8 @@ struct Array
 	uint32_t _capacity;
 	uint32_t _capacity;
 	uint32_t _size;
 	uint32_t _size;
 	T* _data;
 	T* _data;
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 /// Dynamic array of objects.
 /// Dynamic array of objects.
@@ -65,6 +68,8 @@ struct Vector
 	uint32_t _capacity;
 	uint32_t _capacity;
 	uint32_t _size;
 	uint32_t _size;
 	T* _data;
 	T* _data;
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 /// Circular buffer double-ended queue of POD items.
 /// Circular buffer double-ended queue of POD items.
@@ -84,6 +89,8 @@ struct Queue
 	uint32_t _read;
 	uint32_t _read;
 	uint32_t _size;
 	uint32_t _size;
 	Array<T> _queue;
 	Array<T> _queue;
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 /// Priority queue of POD items.
 /// Priority queue of POD items.
@@ -95,6 +102,8 @@ struct PriorityQueue
 	PriorityQueue(Allocator& a);
 	PriorityQueue(Allocator& a);
 
 
 	Array<T> _queue;
 	Array<T> _queue;
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 /// Hash from an uint64_t to POD items. If you want to use a generic key
 /// Hash from an uint64_t to POD items. If you want to use a generic key
@@ -115,6 +124,8 @@ struct Hash
 
 
 	Array<uint32_t> _hash;
 	Array<uint32_t> _hash;
 	Array<Entry> _data;
 	Array<Entry> _data;
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 /// Map from key to value. Uses a Vector internally, so, definitely
 /// Map from key to value. Uses a Vector internally, so, definitely
@@ -130,20 +141,29 @@ struct Map
 
 
 	struct Node
 	struct Node
 	{
 	{
-		TKey key;
-		TValue value;
+		Node(Allocator& a)
+			: pair(a)
+		{
+		}
+
+		PAIR(TKey, TValue) pair;
 		uint32_t left;
 		uint32_t left;
 		uint32_t right;
 		uint32_t right;
 		uint32_t parent;
 		uint32_t parent;
 		uint32_t color;
 		uint32_t color;
+
+		ALLOCATOR_AWARE;
 	};
 	};
 
 
 	uint32_t _root;
 	uint32_t _root;
+	uint32_t _sentinel;
 	Vector<Node> _data;
 	Vector<Node> _data;
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 /// Sorted map from key to POD items.
 /// Sorted map from key to POD items.
-/// Items are not automatically sorted, you need to call sort_map::sort().
+/// Items are not automatically sorted, you have to call sort_map::sort().
 /// @ingroup Containers.
 /// @ingroup Containers.
 template <typename TKey, typename TValue, class Compare = less<TKey> >
 template <typename TKey, typename TValue, class Compare = less<TKey> >
 struct SortMap
 struct SortMap
@@ -160,6 +180,8 @@ struct SortMap
 #if CROWN_DEBUG
 #if CROWN_DEBUG
 	bool _is_sorted;
 	bool _is_sorted;
 #endif
 #endif
+
+	ALLOCATOR_AWARE;
 };
 };
 
 
 } // namespace crown
 } // namespace crown

+ 150 - 95
src/core/containers/map.h

@@ -8,7 +8,7 @@
 #include "container_types.h"
 #include "container_types.h"
 #include "vector.h"
 #include "vector.h"
 
 
-#define RBTREE_VERIFY
+// #define RBTREE_VERIFY
 
 
 namespace crown
 namespace crown
 {
 {
@@ -46,9 +46,9 @@ namespace map
 
 
 namespace map_internal
 namespace map_internal
 {
 {
-	const uint32_t BLACK = 0xb1b1b1b1u;
-	const uint32_t RED = 0xededededu;
-	const uint32_t NIL = 0xffffffff;
+	const uint32_t BLACK = 0xB1B1B1B1u;
+	const uint32_t RED = 0xEDEDEDEDu;
+	const uint32_t NIL = 0xFFFFFFFFu;
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline uint32_t root(const Map<TKey, TValue>& m)
 	inline uint32_t root(const Map<TKey, TValue>& m)
@@ -80,30 +80,29 @@ namespace map_internal
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline uint32_t color(const Map<TKey, TValue>& m, uint32_t n)
 	inline uint32_t color(const Map<TKey, TValue>& m, uint32_t n)
 	{
 	{
-		if (n == NIL) return BLACK;
 		CE_ASSERT(n < vector::size(m._data), "Index out of bounds (size = %d, n = %d)", vector::size(m._data), n);
 		CE_ASSERT(n < vector::size(m._data), "Index out of bounds (size = %d, n = %d)", vector::size(m._data), n);
 		return m._data[n].color;
 		return m._data[n].color;
 	}
 	}
 
 
-#ifdef RBTREE_VERIFY
+	#ifdef RBTREE_VERIFY
 	template<typename TKey, typename TValue>
 	template<typename TKey, typename TValue>
 	inline int32_t dbg_verify(Map<TKey, TValue>& m, uint32_t n)
 	inline int32_t dbg_verify(Map<TKey, TValue>& m, uint32_t n)
 	{
 	{
-		if (n == NIL)
+		if (n == m._sentinel)
 		{
 		{
 			return 0;
 			return 0;
 		}
 		}
 
 
-		if (left(m, n) != NIL)
+		if (left(m, n) != m._sentinel)
 		{
 		{
 			CE_ASSERT(parent(m, left(m, n)) == n, "Bad RBTree");
 			CE_ASSERT(parent(m, left(m, n)) == n, "Bad RBTree");
-			CE_ASSERT(m._data[left(m, n)].key < m._data[n].key, "Bad RBTree");
+			CE_ASSERT(m._data[left(m, n)].pair.first < m._data[n].pair.first, "Bad RBTree");
 		}
 		}
 
 
-		if (right(m, n) != NIL)
+		if (right(m, n) != m._sentinel)
 		{
 		{
 			CE_ASSERT(parent(m, right(m, n)) == n, "Bad RBTree");
 			CE_ASSERT(parent(m, right(m, n)) == n, "Bad RBTree");
-			CE_ASSERT(m._data[n].key < m._data[right(m, n)].key, "Bad RBTree");
+			CE_ASSERT(m._data[n].pair.first < m._data[right(m, n)].pair.first, "Bad RBTree");
 		}
 		}
 
 
 		int32_t bhL = dbg_verify(m, left(m, n));
 		int32_t bhL = dbg_verify(m, left(m, n));
@@ -135,16 +134,20 @@ namespace map_internal
 		printf("\n");
 		printf("\n");
 		return 0;
 		return 0;
 	}
 	}
-#endif // RBTREE_VERIFY
+	#endif
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline uint32_t min(const Map<TKey, TValue>& m, uint32_t x)
 	inline uint32_t min(const Map<TKey, TValue>& m, uint32_t x)
 	{
 	{
-		if (x == NIL)
+		if (x == m._sentinel)
+		{
 			return x;
 			return x;
+		}
 
 
-		while (left(m, x) != NIL)
+		while (left(m, x) != m._sentinel)
+		{
 			x = left(m, x);
 			x = left(m, x);
+		}
 
 
 		return x;
 		return x;
 	}
 	}
@@ -152,11 +155,15 @@ namespace map_internal
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline uint32_t max(const Map<TKey, TValue>& m, uint32_t x)
 	inline uint32_t max(const Map<TKey, TValue>& m, uint32_t x)
 	{
 	{
-		if (x == NIL)
+		if (x == m._sentinel)
+		{
 			return x;
 			return x;
+		}
 
 
-		while (right(m, x) != NIL)
+		while (right(m, x) != m._sentinel)
+		{
 			x = right(m, x);
 			x = right(m, x);
+		}
 
 
 		return x;
 		return x;
 	}
 	}
@@ -164,8 +171,10 @@ namespace map_internal
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline uint32_t successor(const Map<TKey, TValue>& m, uint32_t x)
 	inline uint32_t successor(const Map<TKey, TValue>& m, uint32_t x)
 	{
 	{
-		if (right(m, x) != NIL)
+		if (right(m, x) != m._sentinel)
+		{
 			return min(m, right(m, x));
 			return min(m, right(m, x));
+		}
 
 
 		uint32_t y = parent(m, x);
 		uint32_t y = parent(m, x);
 
 
@@ -181,8 +190,10 @@ namespace map_internal
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline uint32_t predecessor(const Map<TKey, TValue>& m, uint32_t x)
 	inline uint32_t predecessor(const Map<TKey, TValue>& m, uint32_t x)
 	{
 	{
-		if (left(m, x) != NIL)
+		if (left(m, x) != m._sentinel)
+		{
 			return max(m, left(m, x));
 			return max(m, left(m, x));
+		}
 
 
 		uint32_t y = parent(m, x);
 		uint32_t y = parent(m, x);
 
 
@@ -203,7 +214,7 @@ namespace map_internal
 		uint32_t y = right(m, x);
 		uint32_t y = right(m, x);
 		m._data[x].right = left(m, y);
 		m._data[x].right = left(m, y);
 
 
-		if (left(m, y) != NIL)
+		if (left(m, y) != m._sentinel)
 		{
 		{
 			m._data[left(m, y)].parent = x;
 			m._data[left(m, y)].parent = x;
 		}
 		}
@@ -238,7 +249,7 @@ namespace map_internal
 		uint32_t y = left(m, x);
 		uint32_t y = left(m, x);
 		m._data[x].left = right(m, y);
 		m._data[x].left = right(m, y);
 
 
-		if (right(m, y) != NIL)
+		if (right(m, y) != m._sentinel)
 		{
 		{
 			m._data[right(m, y)].parent = x;
 			m._data[right(m, y)].parent = x;
 		}
 		}
@@ -305,9 +316,10 @@ namespace map_internal
 			}
 			}
 		}
 		}
 
 
-#ifdef RBTREE_VERIFY
-		dbg_verify(m, m._root);
-#endif
+		#ifdef RBTREE_VERIFY
+			dbg_verify(m, m._root);
+		#endif
+
 		vector::pop_back(m._data);
 		vector::pop_back(m._data);
 	}
 	}
 
 
@@ -383,24 +395,30 @@ namespace map_internal
 	{
 	{
 		uint32_t x = m._root;
 		uint32_t x = m._root;
 
 
-		while (x != NIL)
+		while (x != m._sentinel)
 		{
 		{
-			if (m._data[x].key < key)
+			if (m._data[x].pair.first < key)
 			{
 			{
-				if (right(m, x) == NIL)
+				if (right(m, x) == m._sentinel)
+				{
 					return x;
 					return x;
+				}
 
 
 				x = right(m, x);
 				x = right(m, x);
 			}
 			}
-			else if (key < m._data[x].key)
+			else if (key < m._data[x].pair.first)
 			{
 			{
-				if (left(m, x) == NIL)
+				if (left(m, x) == m._sentinel)
+				{
 					return x;
 					return x;
+				}
 
 
 				x = left(m, x);
 				x = left(m, x);
 			}
 			}
 			else
 			else
+			{
 				break;
 				break;
+			}
 		}
 		}
 
 
 		return x;
 		return x;
@@ -411,7 +429,7 @@ namespace map_internal
 	{
 	{
 		uint32_t p = inner_find(m, key);
 		uint32_t p = inner_find(m, key);
 
 
-		if (p != NIL && m._data[p].key == key)
+		if (p != m._sentinel && m._data[p].pair.first == key)
 			return p;
 			return p;
 
 
 		return NIL;
 		return NIL;
@@ -422,34 +440,45 @@ namespace map_internal
 	{
 	{
 		uint32_t p = inner_find(m, key);
 		uint32_t p = inner_find(m, key);
 
 
-		if (p != NIL && m._data[p].key == key)
+		if (p != m._sentinel && m._data[p].pair.first == key)
+		{
+			printf("Found\n");
 			return p;
 			return p;
+		}
+
+		printf("Not found, adding...\n");
 
 
 		typename Map<TKey, TValue>::Node n;
 		typename Map<TKey, TValue>::Node n;
 		n.key = key;
 		n.key = key;
 		n.value = TValue();
 		n.value = TValue();
 		n.color = RED;
 		n.color = RED;
-		n.left = NIL;
-		n.right = NIL;
+		n.left = m._sentinel;
+		n.right = m._sentinel;
 		n.parent = NIL;
 		n.parent = NIL;
 
 
-		if (p == NIL)
+		if (p == m._sentinel)
+		{
 			m._root = n;
 			m._root = n;
+		}
 		else
 		else
 		{
 		{
-			if (key < m._data[p].key)
+			if (key < m._data[p].pair.first)
+			{
 				m._data[p].left = n;
 				m._data[p].left = n;
+			}
 			else
 			else
+			{
 				m._data[p].right = n;
 				m._data[p].right = n;
+			}
 
 
 			m._data[n].parent = p;
 			m._data[n].parent = p;
 		}
 		}
 
 
 		add_fixup(m, n);
 		add_fixup(m, n);
 		m._data[m._root].color = BLACK;
 		m._data[m._root].color = BLACK;
-#ifdef RBTREE_VERIFY
-		dbg_verify(m, m._root);
-#endif
+		#ifdef RBTREE_VERIFY
+			dbg_verify(m, m._root);
+		#endif
 		return n;
 		return n;
 	}
 	}
 } // namespace map_internal
 } // namespace map_internal
@@ -459,7 +488,8 @@ namespace map
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	uint32_t size(const Map<TKey, TValue>& m)
 	uint32_t size(const Map<TKey, TValue>& m)
 	{
 	{
-		return vector::size(m._data);
+		CE_ASSERT(vector::size(m._data) > 0, "Bad Map"); // There should be at least sentinel
+		return vector::size(m._data) - 1;
 	}
 	}
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
@@ -473,8 +503,10 @@ namespace map
 	{
 	{
 		uint32_t p = map_internal::inner_find(m, key);
 		uint32_t p = map_internal::inner_find(m, key);
 
 
-		if (p != map_internal::NIL && m._data[p].key == key)
-			return m._data[p].value;
+		if (p != m._sentinel && m._data[p].pair.first == key)
+		{
+			return m._data[p].pair.second;
+		}
 
 
 		return deffault;
 		return deffault;
 	}
 	}
@@ -482,34 +514,32 @@ namespace map
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	inline void set(Map<TKey, TValue>& m, const TKey& key, const TValue& value)
 	inline void set(Map<TKey, TValue>& m, const TKey& key, const TValue& value)
 	{
 	{
-		using namespace map_internal;
-
-		typename Map<TKey, TValue>::Node node;
-		node.key = key;
-		node.value = value;
-		node.color = RED;
-		node.left = NIL;
-		node.right = NIL;
-		node.parent = NIL;
+		typename Map<TKey, TValue>::Node node(*m._data._allocator);
+		node.pair.first = key;
+		node.pair.second = value;
+		node.color = map_internal::RED;
+		node.left = m._sentinel;
+		node.right = m._sentinel;
+		node.parent = map_internal::NIL;
 		uint32_t n = vector::push_back(m._data, node);
 		uint32_t n = vector::push_back(m._data, node);
 		uint32_t x = m._root;
 		uint32_t x = m._root;
-		uint32_t y = NIL;
+		uint32_t y = map_internal::NIL;
 
 
-		if (x == NIL)
+		if (x == m._sentinel)
 			m._root = n;
 			m._root = n;
 		else
 		else
 		{
 		{
-			while (x != NIL)
+			while (x != m._sentinel)
 			{
 			{
 				y = x;
 				y = x;
 
 
-				if (key < m._data[x].key)
+				if (key < m._data[x].pair.first)
 					x = m._data[x].left;
 					x = m._data[x].left;
 				else
 				else
 					x = m._data[x].right;
 					x = m._data[x].right;
 			}
 			}
 
 
-			if (key < m._data[y].key)
+			if (key < m._data[y].pair.first)
 				m._data[y].left = n;
 				m._data[y].left = n;
 			else
 			else
 				m._data[y].right = n;
 				m._data[y].right = n;
@@ -517,11 +547,11 @@ namespace map
 			m._data[n].parent = y;
 			m._data[n].parent = y;
 		}
 		}
 
 
-		insert_fixup(m, n);
-		m._data[m._root].color = BLACK;
-#ifdef RBTREE_VERIFY
-		dbg_verify(m, m._root);
-#endif
+		map_internal::insert_fixup(m, n);
+		m._data[m._root].color = map_internal::BLACK;
+		#ifdef RBTREE_VERIFY
+			map_internal::dbg_verify(m, m._root);
+		#endif
 	}
 	}
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
@@ -531,77 +561,93 @@ namespace map
 
 
 		uint32_t n = inner_find(m, key);
 		uint32_t n = inner_find(m, key);
 
 
-		if (!(m._data[n].key == key))
+		if (!(m._data[n].pair.first == key))
+		{
 			return;
 			return;
+		}
 
 
 		uint32_t x;
 		uint32_t x;
 		uint32_t y;
 		uint32_t y;
 
 
-		if (left(m, n) == NIL || right(m, n) == NIL)
+		if (left(m, n) == m._sentinel || right(m, n) == m._sentinel)
+		{
 			y = n;
 			y = n;
+		}
 		else
 		else
+		{
 			y = successor(m, n);
 			y = successor(m, n);
+		}
 
 
-		if (left(m, y) != NIL)
+		if (left(m, y) != m._sentinel)
+		{
 			x = left(m, y);
 			x = left(m, y);
+		}
 		else
 		else
+		{
 			x = right(m, y);
 			x = right(m, y);
+		}
 
 
 		m._data[x].parent = parent(m, y);
 		m._data[x].parent = parent(m, y);
 
 
-		if (parent(m, y) != NIL)
+		if (parent(m, y) != map_internal::NIL)
 		{
 		{
 			if (y == left(m, parent(m, y)))
 			if (y == left(m, parent(m, y)))
+			{
 				m._data[parent(m, y)].left = x;
 				m._data[parent(m, y)].left = x;
+			}
 			else
 			else
+			{
 				m._data[parent(m, y)].right = x;
 				m._data[parent(m, y)].right = x;
+			}
 		}
 		}
 		else
 		else
+		{
 			m._root = x;
 			m._root = x;
+		}
 
 
 		if (y != n)
 		if (y != n)
 		{
 		{
-			m._data[n].key = m._data[y].key;
-			m._data[n].value = m._data[y].value;
+			m._data[n].pair.first = m._data[y].pair.first;
+			m._data[n].pair.second = m._data[y].pair.second;
 		}
 		}
 
 
 		// Do the fixup
 		// Do the fixup
-		if (color(m, y) == BLACK)
+		if (color(m, y) == map_internal::BLACK)
 		{
 		{
 			uint32_t y;
 			uint32_t y;
 
 
-			while (x != m._root && color(m, x) == BLACK)
+			while (x != m._root && color(m, x) == map_internal::BLACK)
 			{
 			{
 				if (x == left(m, parent(m, x)))
 				if (x == left(m, parent(m, x)))
 				{
 				{
 					y = right(m, parent(m, x));
 					y = right(m, parent(m, x));
 
 
-					if (color(m, y) == RED)
+					if (color(m, y) == map_internal::RED)
 					{
 					{
-						m._data[y].color = BLACK;
-						m._data[parent(m, x)].color = RED;
+						m._data[y].color = map_internal::BLACK;
+						m._data[parent(m, x)].color = map_internal::RED;
 						rotate_left(m, parent(m, x));
 						rotate_left(m, parent(m, x));
 						y = right(m, parent(m, x));
 						y = right(m, parent(m, x));
 					}
 					}
 
 
-					if (color(m, left(m, y)) == BLACK && color(m, right(m, y)) == BLACK)
+					if (color(m, left(m, y)) == map_internal::BLACK && color(m, right(m, y)) == map_internal::BLACK)
 					{
 					{
-						m._data[y].color = RED;
+						m._data[y].color = map_internal::RED;
 						x = parent(m, x);
 						x = parent(m, x);
 					}
 					}
 					else
 					else
 					{
 					{
-						if (color(m, right(m, y)) == BLACK)
+						if (color(m, right(m, y)) == map_internal::BLACK)
 						{
 						{
-							m._data[left(m, y)].color = BLACK;
-							m._data[y].color = RED;
+							m._data[left(m, y)].color = map_internal::BLACK;
+							m._data[y].color = map_internal::RED;
 							rotate_right(m, y);
 							rotate_right(m, y);
 							y = right(m, parent(m, x));
 							y = right(m, parent(m, x));
 						}
 						}
 
 
 						m._data[y].color = color(m, parent(m, x));
 						m._data[y].color = color(m, parent(m, x));
-						m._data[parent(m, x)].color = BLACK;
-						m._data[right(m, y)].color = BLACK;
+						m._data[parent(m, x)].color = map_internal::BLACK;
+						m._data[right(m, y)].color = map_internal::BLACK;
 						rotate_left(m, parent(m, x));
 						rotate_left(m, parent(m, x));
 						x = m._root;
 						x = m._root;
 					}
 					}
@@ -610,58 +656,67 @@ namespace map
 				{
 				{
 					y = left(m, parent(m, x));
 					y = left(m, parent(m, x));
 
 
-					if (color(m, y) == RED)
+					if (color(m, y) == map_internal::RED)
 					{
 					{
-						m._data[y].color = BLACK;
-						m._data[parent(m, x)].color = RED;
+						m._data[y].color = map_internal::BLACK;
+						m._data[parent(m, x)].color = map_internal::RED;
 						rotate_right(m, parent(m, x));
 						rotate_right(m, parent(m, x));
 						y = left(m, parent(m, x));
 						y = left(m, parent(m, x));
 					}
 					}
 
 
-					if (color(m, right(m, y)) == BLACK && color(m, left(m, y)) == BLACK)
+					if (color(m, right(m, y)) == map_internal::BLACK && color(m, left(m, y)) == map_internal::BLACK)
 					{
 					{
-						m._data[y].color = RED;
+						m._data[y].color = map_internal::RED;
 						x = parent(m, x);
 						x = parent(m, x);
 					}
 					}
 					else
 					else
 					{
 					{
-						if (color(m, left(m, y)) == BLACK)
+						if (color(m, left(m, y)) == map_internal::BLACK)
 						{
 						{
-							m._data[right(m, y)].color = BLACK;
-							m._data[y].color = RED;
+							m._data[right(m, y)].color = map_internal::BLACK;
+							m._data[y].color = map_internal::RED;
 							rotate_left(m, y);
 							rotate_left(m, y);
 							y = left(m, parent(m, x));
 							y = left(m, parent(m, x));
 						}
 						}
 
 
 						m._data[y].color = color(m, parent(m, x));
 						m._data[y].color = color(m, parent(m, x));
-						m._data[parent(m, x)].color = BLACK;
-						m._data[left(m, y)].color = BLACK;
+						m._data[parent(m, x)].color = map_internal::BLACK;
+						m._data[left(m, y)].color = map_internal::BLACK;
 						rotate_right(m, parent(m, x));
 						rotate_right(m, parent(m, x));
 						x = m._root;
 						x = m._root;
 					}
 					}
 				}
 				}
 			}
 			}
 
 
-			m._data[x].color = BLACK;
+			m._data[x].color = map_internal::BLACK;
 		}
 		}
 
 
 		destroy(m, y);
 		destroy(m, y);
-#ifdef RBTREE_VERIFY
-		dbg_verify(m, m._root);
-#endif
+	 	#ifdef RBTREE_VERIFY
+			map_internal::dbg_verify(m, m._root);
+	 	#endif
 	}
 	}
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	void clear(Map<TKey, TValue>& m)
 	void clear(Map<TKey, TValue>& m)
 	{
 	{
 		vector::clear(m._data);
 		vector::clear(m._data);
-		m._root = map_internal::NIL;
+
+		m._root = 0;
+		m._sentinel = 0;
+
+		typename Map<TKey, TValue>::Node r(*m._data._allocator);
+		r.left = map_internal::NIL;
+		r.right = map_internal::NIL;
+		r.parent = map_internal::NIL;
+		r.color = map_internal::BLACK;
+		vector::push_back(m._data, r);
 	}
 	}
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
 	const typename Map<TKey, TValue>::Node* begin(const Map<TKey, TValue>& m)
 	const typename Map<TKey, TValue>::Node* begin(const Map<TKey, TValue>& m)
 	{
 	{
-		return vector::begin(m._data);
+		return vector::begin(m._data) + 1; // Skip sentinel at index 0
 	}
 	}
 
 
 	template <typename TKey, typename TValue>
 	template <typename TKey, typename TValue>
@@ -673,9 +728,9 @@ namespace map
 
 
 template <typename TKey, typename TValue>
 template <typename TKey, typename TValue>
 inline Map<TKey, TValue>::Map(Allocator& a)
 inline Map<TKey, TValue>::Map(Allocator& a)
-	: _root(map_internal::NIL)
-	, _data(a)
+	: _data(a)
 {
 {
+	map::clear(*this);
 }
 }
 
 
 template <typename TKey, typename TValue>
 template <typename TKey, typename TValue>

+ 91 - 0
src/core/containers/pair.h

@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#pragma once
+
+namespace crown
+{
+
+template <typename T1, typename T2, int T1Aware, int T2Aware>
+struct Pair
+{
+};
+
+template <typename T1, typename T2>
+struct Pair<T1, T2, 0, 0>
+{
+	Pair(T1 f, T2 s) : first(f), second(s)
+	{
+	}
+
+	Pair(Allocator& /*a*/)
+	{
+	}
+
+	T1 first;
+	T2 second;
+};
+
+template <typename T1, typename T2>
+struct Pair<T1, T2, 1, 0>
+{
+	Pair(T1 f, T2 s) : first(f), second(s)
+	{
+	}
+
+	Pair(Allocator& a)
+		: first(a)
+	{
+	}
+
+	T1 first;
+	T2 second;
+};
+
+template <typename T1, typename T2>
+struct Pair<T1, T2, 0, 1>
+{
+	Pair(T1 f, T2 s) : first(f), second(s)
+	{
+	}
+
+	Pair(Allocator& a)
+		: second(a)
+	{
+	}
+
+	T1 first;
+	T2 second;
+};
+
+template <typename T1, typename T2>
+struct Pair<T1, T2, 1, 1>
+{
+	Pair(T1 f, T2 s) : first(f), second(s)
+	{
+	}
+
+	Pair(Allocator& a)
+		: first(a)
+		, second(a)
+	{
+	}
+
+	T1 first;
+	T2 second;
+};
+
+#define PAIR(first, second) Pair<first, second, IS_ALLOCATOR_AWARE(first), IS_ALLOCATOR_AWARE(second)>
+
+template <typename T1, typename T2>
+PAIR(T1, T2) make_pair(Allocator& a, T1 first, T2 second)
+{
+	PAIR(T1, T2) pair(a);
+	pair.first = first;
+	pair.second = second;
+	return pair;
+}
+
+} // namespace crown

+ 2 - 1
src/core/containers/vector.h

@@ -163,7 +163,8 @@ namespace vector
 		if (v._capacity == v._size)
 		if (v._capacity == v._size)
 			grow(v, 0);
 			grow(v, 0);
 
 
-		new (v._data + v._size) T(item);
+		construct<T>(v._data + v._size, *v._allocator, IS_ALLOCATOR_AWARE_TYPE(T)());
+		v._data[v._size] = item;
 
 
 		return v._size++;
 		return v._size++;
 	}
 	}

+ 1 - 1
src/core/json/json_parser.cpp

@@ -320,7 +320,7 @@ void JSONElement::to_keys(Vector<DynamicString>& keys) const
 	const Map<DynamicString, const char*>::Node* it = map::begin(object);
 	const Map<DynamicString, const char*>::Node* it = map::begin(object);
 	while (it != map::end(object))
 	while (it != map::end(object))
 	{
 	{
-		vector::push_back(keys, (*it).key);
+		vector::push_back(keys, (*it).pair.first);
 		it++;
 		it++;
 	}
 	}
 }
 }

+ 30 - 0
src/core/types.h

@@ -6,6 +6,7 @@
 #pragma once
 #pragma once
 
 
 #include "config.h"
 #include "config.h"
+#include "memory_types.h"
 #include <cstddef>
 #include <cstddef>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -52,6 +53,35 @@ struct StringId64
 typedef StringId64 ResourceId;
 typedef StringId64 ResourceId;
 
 
 #define INVALID_ID 65535
 #define INVALID_ID 65535
+#define ALLOCATOR_AWARE typedef int allocator_aware
+
+/// Convert integer to type.
+template <int v>
+struct Int2Type { enum {value=v}; };
+
+/// Determines if a class is allocator aware.
+template <class T>
+struct is_allocator_aware {
+
+        template <typename C>
+        static char test_fun(typename C::allocator_aware *);
+
+        template <typename C>
+        static int test_fun(...);
+
+public:
+        enum {
+                value = (sizeof(test_fun<T>(0)) == sizeof(char))
+        };
+};
+
+#define IS_ALLOCATOR_AWARE(T) is_allocator_aware<T>::value
+#define IS_ALLOCATOR_AWARE_TYPE(T) Int2Type< IS_ALLOCATOR_AWARE(T) >
+
+/// Allocator aware constuction
+template <class T> inline T &construct(void *p, Allocator& a, Int2Type<true>) {new (p) T(a); return *(T *)p;}
+template <class T> inline T &construct(void *p, Allocator& /*a*/, Int2Type<false>) {new (p) T; return *(T *)p;}
+template <class T> inline T &construct(void *p, Allocator& a) {return construct<T>(p, a, IS_ALLOCATOR_AWARE_TYPE(T)());}
 
 
 struct Id
 struct Id
 {
 {