2
0
Эх сурвалжийг харах

Port IdArray and IdTable to NMF

Daniele Bartolini 11 жил өмнө
parent
commit
ddceb1a528

+ 144 - 156
engine/core/containers/IdArray.h

@@ -36,204 +36,192 @@ namespace crown
 /// Packed array of objects with lookup table.
 ///
 /// @ingroup Containers
-template <uint32_t MAX_NUM_ID, typename T>
-class IdArray
+template <uint32_t MAX, typename T>
+struct IdArray
 {
-public:
-
-	/// Creates the table for tracking exactly @a MAX_NUM_ID - 1 unique Ids.
-					IdArray();
+	/// Creates the table for tracking exactly @a MAX - 1 unique Ids.
+	IdArray();
 
 	/// Random access by index.
-	T&				operator[](uint32_t i);
+	T& operator[](uint32_t i);
 	/// Random access by index.
-	const T&		operator[](uint32_t i) const;
-
-	/// Returns a new Id.
-	Id				create(const T& object);
-
-	/// Destroys the object with the given @a id.
-	void			destroy(Id id);
-
-	/// Returns whether the table has the object with the given @a id
-	bool			has(Id id) const;
-
-	/// Returns the number of objects in the array.
-	uint32_t		size() const;
-
-	/// Returns the object with the given @a id.
-	T&				lookup(const Id& id);
-
-	T*				begin();
-	const T*		begin() const;
-	T*				end();
-	const T*		end() const;
-
-private:
-
-	// Returns the next available unique id.
-	uint16_t		next_id();
-
-public:
+	const T& operator[](uint32_t i) const;
 
 	// The index of the first unused id
-	uint16_t		m_freelist;
-
-	// The index of the last id in the id table
-	uint16_t		m_last_index;
+	uint16_t m_freelist;
 
 	// Next available unique id
-	uint16_t		m_next_id;
-	uint16_t		m_num_objects;
-
+	uint16_t m_next_id;
+	uint16_t m_size;
 
 	// The last valid id is reserved and cannot be used to
 	// refer to Ids from the outside
-	Id				m_sparse[MAX_NUM_ID];
-	uint16_t		m_sparse_to_dense[MAX_NUM_ID];
-	uint16_t		m_dense_to_sparse[MAX_NUM_ID];
-	T				m_objects[MAX_NUM_ID];
+	Id m_sparse[MAX];
+	uint16_t m_sparse_to_dense[MAX];
+	uint16_t m_dense_to_sparse[MAX];
+	T m_objects[MAX];
 };
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline IdArray<MAX_NUM_ID, T>::IdArray()
-	: m_freelist(INVALID_ID)
-	, m_last_index(0)
-	, m_next_id(0)
-	, m_num_objects(0)
+/// Functions to manipulate IdArray.
+///
+/// @ingroup Containers
+namespace id_array
 {
-	for (uint32_t i = 0; i < MAX_NUM_ID; i++)
-	{
-		m_sparse[i].id = INVALID_ID;
-	}
-}
+	/// Creates a new @a object in the array @a a and returns its id.
+	template <uint32_t MAX, typename T> Id create(IdArray<MAX, T>& a, const T& object);
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline T& IdArray<MAX_NUM_ID, T>::operator[](uint32_t i)
-{
-	CE_ASSERT(i < m_num_objects, "Index out of bounds");
-	return m_objects[i];
-}
+	/// Destroys the object with the given @a id.
+	template <uint32_t MAX, typename T> void destroy(IdArray<MAX, T>& a, Id id);
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline const T& IdArray<MAX_NUM_ID, T>::operator[](uint32_t i) const
-{
-	CE_ASSERT(i < m_num_objects, "Index out of bounds");
-	return m_objects[i];
-}
+	/// Returns whether the table has the object with the given @a id.
+	template <uint32_t MAX, typename T> bool has(const IdArray<MAX, T>& a, Id id);
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline Id IdArray<MAX_NUM_ID, T>::create(const T& object)
-{
-	CE_ASSERT(m_num_objects < MAX_NUM_ID, "Object list full");
+	/// Returns the number of objects in the array.
+	template <uint32_t MAX, typename T> uint32_t size(const IdArray<MAX, T>& a);
 
-	// Obtain a new id
-	Id id;
-	id.id = next_id();
+	/// Returns the object with the given @a id.
+	template <uint32_t MAX, typename T> T& get(const Id& id);
+
+	template <uint32_t MAX, typename T> T* begin(IdArray<MAX, T>& a);
+	template <uint32_t MAX, typename T> const T* begin(const IdArray<MAX, T>& a);
+	template <uint32_t MAX, typename T> T* end(IdArray<MAX, T>& a);
+	template <uint32_t MAX, typename T> const T* end(const IdArray<MAX, T>& a);
+} // namespace id_array
 
-	// Recycle slot if there are any
-	if (m_freelist != INVALID_ID)
+namespace id_array
+{
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline Id create(IdArray<MAX, T>& a, const T& object)
 	{
-		id.index = m_freelist;
-		m_freelist = m_sparse[m_freelist].index;
+		CE_ASSERT(a.m_size < MAX, "Object list full");
+
+		// Obtain a new id
+		Id id;
+		id.id = a.m_next_id++;
+
+		// Recycle slot if there are any
+		if (a.m_freelist != INVALID_ID)
+		{
+			id.index = a.m_freelist;
+			a.m_freelist = a.m_sparse[a.m_freelist].index;
+		}
+		else
+		{
+			id.index = a.m_size;
+		}
+
+		a.m_sparse[id.index] = id;
+		a.m_sparse_to_dense[id.index] = a.m_size;
+		a.m_dense_to_sparse[a.m_size] = id.index;
+		a.m_objects[a.m_size] = object;
+		a.m_size++;
+
+		return id;
 	}
-	else
+
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline void destroy(IdArray<MAX, T>& a, Id id)
 	{
-		id.index = m_last_index++;
+		CE_ASSERT(has(a, id), "IdArray does not have ID: %d,%d", id.id, id.index);
+
+		a.m_sparse[id.index].id = INVALID_ID;
+		a.m_sparse[id.index].index = a.m_freelist;
+		a.m_freelist = id.index;
+
+		// Swap with last element
+		const uint32_t last = a.m_size - 1;
+		CE_ASSERT(last >= a.m_sparse_to_dense[id.index], "Swapping with previous item");
+		a.m_objects[a.m_sparse_to_dense[id.index]] = a.m_objects[last];
+
+		// Update tables
+		uint16_t std = a.m_sparse_to_dense[id.index];
+		uint16_t dts = a.m_dense_to_sparse[last];
+		a.m_sparse_to_dense[dts] = std;
+		a.m_dense_to_sparse[std] = dts;
+		a.m_size--;
 	}
 
-	m_sparse[id.index] = id;
-	m_sparse_to_dense[id.index] = m_num_objects;
-	m_dense_to_sparse[m_num_objects] = id.index;
-	m_objects[m_num_objects] = object;
-	m_num_objects++;
-
-	return id;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline T& get(IdArray<MAX, T>& a, const Id& id)
+	{
+		CE_ASSERT(has(a, id), "IdArray does not have ID: %d,%d", id.id, id.index);
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline void IdArray<MAX_NUM_ID, T>::destroy(Id id)
-{
-	CE_ASSERT(has(id), "IdArray does not have ID: %d,%d", id.id, id.index);
-
-	m_sparse[id.index].id = INVALID_ID;
-	m_sparse[id.index].index = m_freelist;
-	m_freelist = id.index;
-
-	// Swap with last element
-	const uint32_t last = m_num_objects - 1;
-	CE_ASSERT(last >= m_sparse_to_dense[id.index], "Swapping with previous item");
-	m_objects[m_sparse_to_dense[id.index]] = m_objects[last];
-
-	// Update tables
-	uint16_t std = m_sparse_to_dense[id.index];
-	uint16_t dts = m_dense_to_sparse[last];
-	m_sparse_to_dense[dts] = std;
-	m_dense_to_sparse[std] = dts;
-	m_num_objects--;
-}
+		return a.m_objects[a.m_sparse_to_dense[id.index]];
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline T& IdArray<MAX_NUM_ID, T>::lookup(const Id& id)
-{
-	CE_ASSERT(has(id), "IdArray does not have ID: %d,%d", id.id, id.index);
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline bool has(const IdArray<MAX, T>& a, Id id)
+	{
+		return id.index < MAX && a.m_sparse[id.index].id == id.id;
+	}
 
-	return m_objects[m_sparse_to_dense[id.index]];
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline uint32_t size(const IdArray<MAX, T>& a)
+	{
+		return a.m_size;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline bool IdArray<MAX_NUM_ID, T>::has(Id id) const
-{
-	return id.index < MAX_NUM_ID && m_sparse[id.index].id == id.id;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline T* begin(IdArray<MAX, T>& a)
+	{
+		return a.m_objects;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline uint32_t IdArray<MAX_NUM_ID, T>::size() const
-{
-	return m_num_objects;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline const T* begin(const IdArray<MAX, T>& a)
+	{
+		return a.m_objects;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline uint16_t IdArray<MAX_NUM_ID, T>::next_id()
-{
-	return m_next_id++;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline T* end(IdArray<MAX, T>& a)
+	{
+		return a.m_objects + a.m_size;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline T* IdArray<MAX_NUM_ID, T>::begin()
-{
-	return m_objects;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX, typename T>
+	inline const T* end(const IdArray<MAX, T>& a)
+	{
+		return a.m_objects + a.m_size;
+	}
+} // namespace id_array
 
 //-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline const T* IdArray<MAX_NUM_ID, T>::begin() const
+template <uint32_t MAX, typename T>
+inline IdArray<MAX, T>::IdArray()
+	: m_freelist(INVALID_ID)
+	, m_next_id(0)
+	, m_size(0)
 {
-	return m_objects;
+	for (uint32_t i = 0; i < MAX; i++)
+	{
+		m_sparse[i].id = INVALID_ID;
+	}
 }
 
 //-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline T* IdArray<MAX_NUM_ID, T>::end()
+template <uint32_t MAX, typename T>
+inline T& IdArray<MAX, T>::operator[](uint32_t i)
 {
-	return m_objects + m_num_objects;
+	CE_ASSERT(i < m_size, "Index out of bounds");
+	return m_objects[i];
 }
 
 //-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID, typename T>
-inline const T* IdArray<MAX_NUM_ID, T>::end() const
+template <uint32_t MAX, typename T>
+inline const T& IdArray<MAX, T>::operator[](uint32_t i) const
 {
-	return m_objects + m_num_objects;
+	CE_ASSERT(i < m_size, "Index out of bounds");
+	return m_objects[i];
 }
 
 } // namespace crown

+ 93 - 104
engine/core/containers/IdTable.h

@@ -36,136 +36,125 @@ namespace crown
 /// Table of Ids.
 ///
 /// @ingroup Containers
-template <uint32_t MAX_NUM_ID>
-class IdTable
+template <uint32_t MAX>
+struct IdTable
 {
-public:
-
-	/// Creates the table for tracking exactly @a MAX_NUM_ID - 1 unique Ids.
-					IdTable();
-
-	/// Returns a new Id.
-	Id				create();
-
-	/// Destroys the specified @a id.
-	void			destroy(Id id);
-
-	/// Returns whether the table has the specified @a id
-	bool			has(Id id) const;
-
-	uint16_t		size() const;
-
-	const Id*		begin() const;
-	const Id*		end() const;
-
-private:
-
-	// Returns the next available unique id.
-	uint16_t		next_id();
-
-private:
+	/// Creates the table for tracking exactly @a MAX - 1 unique Ids.
+	IdTable();
 
 	// The index of the first unused id.
-	uint16_t		m_freelist;
-
-	// The index of the last id in the id table.
-	uint16_t		m_last_index;
+	uint16_t m_freelist;
 
 	// Next available unique id.
-	uint16_t		m_next_id;
-	uint16_t		m_size;
+	uint16_t m_next_id;
+	uint16_t m_size;
 
 	// Table of ids.
 	// The last valid id is reserved and cannot be used to
 	// refer to Ids from the outside.
-	Id				m_ids[MAX_NUM_ID];
+	Id m_ids[MAX];
 };
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline IdTable<MAX_NUM_ID>::IdTable()
-	: m_freelist(INVALID_ID)
-	, m_last_index(0)
-	, m_next_id(0)
-	, m_size(0)
-{
-	for (uint32_t i = 0; i < MAX_NUM_ID; i++)
-	{
-		m_ids[i].id = INVALID_ID;
-	}
-}
-
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline Id IdTable<MAX_NUM_ID>::create()
+/// Functions to manipulate IdTable.
+///
+/// @ingroup Containers
+namespace id_table
 {
-	// Obtain a new id
-	Id id;
-	id.id = next_id();
+	/// Creates a new Id in the table @a a and returns its value.
+	template <uint32_t MAX> Id create(IdTable<MAX>& a);
 
-	// Recycle slot if there are any
-	if (m_freelist != INVALID_ID)
-	{
-		id.index = m_freelist;
-		m_freelist = m_ids[m_freelist].index;
-	}
-	else
-	{
-		id.index = m_last_index++;
-	}
+	/// Destroys the @a id in the table @a a.
+	template <uint32_t MAX> void destroy(IdTable<MAX>& a, Id id);
 
-	m_ids[id.index] = id;
+	/// Returns whether the table @a a has the given @a id.
+	template <uint32_t MAX> bool has(const IdTable<MAX>& a, Id id);
 
-	m_size++;
+	/// Returns the number of ids in the table @a a.
+	template <uint32_t MAX> uint16_t size(const IdTable<MAX>& a);
 
-	return id;
-}
+	template <uint32_t MAX> const Id* begin(const IdTable<MAX>& a);
+	template <uint32_t MAX> const Id* end(const IdTable<MAX>& a);
+} // namespace id_table
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline void IdTable<MAX_NUM_ID>::destroy(Id id)
+namespace id_table
 {
-	CE_ASSERT(has(id), "IdTable does not have ID: %d,%d", id.id, id.index);
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX>
+	inline Id create(IdTable<MAX>& a)
+	{
+		// Obtain a new id
+		Id id;
+		id.id = a.m_next_id++;
+
+		// Recycle slot if there are any
+		if (a.m_freelist != INVALID_ID)
+		{
+			id.index = a.m_freelist;
+			a.m_freelist = a.m_ids[a.m_freelist].index;
+		}
+		else
+		{
+			id.index = a.m_size;
+		}
+
+		a.m_ids[id.index] = id;
+		a.m_size++;
+
+		return id;
+	}
 
-	m_ids[id.index].id = INVALID_ID;
-	m_ids[id.index].index = m_freelist;
-	m_freelist = id.index;
-	m_size--;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX>
+	inline void destroy(IdTable<MAX>& a, Id id)
+	{
+		CE_ASSERT(has(a, id), "IdTable does not have ID: %d,%d", id.id, id.index);
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline bool IdTable<MAX_NUM_ID>::has(Id id) const
-{
-	return id.index < MAX_NUM_ID && m_ids[id.index].id == id.id;
-}
+		a.m_ids[id.index].id = INVALID_ID;
+		a.m_ids[id.index].index = a.m_freelist;
+		a.m_freelist = id.index;
+		a.m_size--;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline uint16_t IdTable<MAX_NUM_ID>::size() const
-{
-	return m_size;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX>
+	inline bool has(const IdTable<MAX>& a, Id id)
+	{
+		return id.index < MAX && a.m_ids[id.index].id == id.id;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline const Id* IdTable<MAX_NUM_ID>::begin() const
-{
-	return m_ids;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX>
+	inline uint16_t size(const IdTable<MAX>& a)
+	{
+		return a.m_size;
+	}
 
-//-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline const Id* IdTable<MAX_NUM_ID>::end() const
-{
-	return m_ids + MAX_NUM_ID;
-}
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX>
+	inline const Id* begin(const IdTable<MAX>& a)
+	{
+		return a.m_ids;
+	}
+
+	//-----------------------------------------------------------------------------
+	template <uint32_t MAX>
+	inline const Id* end(const IdTable<MAX>& a)
+	{
+		return a.m_ids + MAX;
+	}
+} // namespace id_table
 
 //-----------------------------------------------------------------------------
-template <uint32_t MAX_NUM_ID>
-inline uint16_t IdTable<MAX_NUM_ID>::next_id()
+template <uint32_t MAX>
+inline IdTable<MAX>::IdTable()
+	: m_freelist(INVALID_ID)
+	, m_next_id(0)
+	, m_size(0)
 {
-	return m_next_id++;
+	for (uint32_t i = 0; i < MAX; i++)
+	{
+		m_ids[i].id = INVALID_ID;
+	}
 }
 
 } // namespace crown