diff engine/core/model/model.cpp @ 145:e7a431577c95

Cleaned the basic model up. Code is cleaner now and a bit faster. Some code path were never tested in depth :-( Added a 'time_to_load' attribute to XMLMapLoader, which records the seconds it took to load a map. Down from 6s to 5.6s for reio de hola. Yay!
author phoku@33b003aa-7bff-0310-803a-e67f0ece8222
date Thu, 09 Oct 2008 08:23:13 +0000
parents 90005975cdbb
children 9d94f4676d17
line wrap: on
line diff
--- a/engine/core/model/model.cpp	Thu Oct 09 06:18:36 2008 +0000
+++ b/engine/core/model/model.cpp	Thu Oct 09 08:23:13 2008 +0000
@@ -42,13 +42,14 @@
 
 	Model::Model(): 
 		FifeClass(),
+		m_last_namespace(NULL),
 		m_timeprovider(NULL) {
 	}
 
 	Model::~Model() {
 		purge(m_maps);
 		for(std::list<namespace_t>::iterator nspace = m_namespaces.begin(); nspace != m_namespaces.end(); ++nspace)
-			purge(nspace->second);
+			purge_map(nspace->second);
 		purge(m_pathers);
 		purge(m_created_grids);
 		purge(m_adopted_grids);
@@ -128,76 +129,68 @@
 	}
 
 	std::list<std::string> Model::getNamespaces() const {
-		std::list<std::string> lst;
+		std::list<std::string> namespace_list;
 		std::list<namespace_t>::const_iterator nspace = m_namespaces.begin();
 		for(; nspace != m_namespaces.end(); ++nspace) {
-			lst.push_back(nspace->first);
+			namespace_list.push_back(nspace->first);
 		}
-
-		return lst;
+		return namespace_list;
 	}
 
 	Object* Model::createObject(const std::string& identifier, const std::string& name_space, Object* parent) {
-
-		std::list<namespace_t>::iterator nspace = m_namespaces.begin();
-		for(; nspace != m_namespaces.end(); ++nspace) {
-			if(nspace->first == name_space) break;
+		// Find or create namespace
+		namespace_t* nspace = selectNamespace(name_space);
+		if(!nspace) {
+			m_namespaces.push_back(namespace_t(name_space,objectmap_t()));
+			nspace = selectNamespace(name_space);
 		}
 
-		if(nspace == m_namespaces.end()) {
-			m_namespaces.push_back(namespace_t(name_space,std::list<Object*>()));
-			nspace = m_namespaces.end();
-			--nspace;
+		// Check for nameclashes
+		objectmap_t::const_iterator it = nspace->second.find(identifier);
+		if( it != nspace->second.end() ) {
+			throw NameClash(identifier);
 		}
 
-		std::list<Object*>::const_iterator it = nspace->second.begin();
-		for(; it != nspace->second.end(); ++it) {
-			if(identifier == (*it)->getId())
-				throw NameClash(identifier);
-		}
-
+		// Finally insert & create
 		Object* object = new Object(identifier, name_space, parent);
-		nspace->second.push_back(object);
+		nspace->second[identifier] = object;
 		return object;
 	}
 
 	bool Model::deleteObject(Object* object) {
+		// WARNING: This code has obviously not been tested (thoroughly).
+
+		// Check if any instances exist. If yes - bail out.
 		std::list<Layer*>::const_iterator jt;
 		std::vector<Instance*>::const_iterator kt;
 		for(std::list<Map*>::iterator it = m_maps.begin(); it != m_maps.end(); ++it) {
 			for(jt = (*it)->getLayers().begin(); jt != (*it)->getLayers().end(); ++jt) {
 				for(kt = (*jt)->getInstances().begin(); kt != (*jt)->getInstances().end(); ++kt) {
 					Object* o = (*kt)->getObject();
-					while(o != 0) {
-						if(o == object)
-							return false;
+					if(o == object) {
+						return false;
 					}
 				}
 			}
 		}
 
-		std::string name_space = object->getNamespace();
-		std::list<namespace_t>::iterator nspace = m_namespaces.begin();
-		for(; nspace != m_namespaces.end(); ++nspace) {
-			if(nspace->first == name_space) break;
-		}
-
-		if(nspace == m_namespaces.end())
+		// Check if the namespace exists
+		namespace_t* nspace = selectNamespace(object->getNamespace());
+		if(!nspace)
 			return true;
 
-		std::list<Object*>::iterator it = nspace->second.begin();
-		for(; it != nspace->second.end(); ++it) {
-			if(*it == object) {
-				delete *it;
-				nspace->second.erase(it);
-				return true;
-			}
+		// If yes - delete+erase object.
+		objectmap_t::iterator it = nspace->second.find(object->getId());
+		if( it != nspace->second.end()) {
+			delete it->second;
+			nspace->second.erase(it);
 		}
 
 		return true;
 	}
 
 	bool Model::deleteObjects() {
+		// If we have layers with instances - bail out.
 		std::list<Layer*>::const_iterator jt;
 		for(std::list<Map*>::iterator it = m_maps.begin(); it != m_maps.end(); ++it) {
 			for(jt = (*it)->getLayers().begin(); jt != (*it)->getLayers().end(); ++jt) {
@@ -206,42 +199,63 @@
 			}
 		}
 
+		// Otherwise delete every object in every namespace
 		std::list<namespace_t>::iterator nspace = m_namespaces.begin();
 		while(nspace != m_namespaces.end()) {
-			std::list<Object*>::iterator it = nspace->second.begin();
+			objectmap_t::iterator it = nspace->second.begin();
 			for(; it != nspace->second.end(); ++it) {
-				delete *it;
+				delete it->second;
 			}
 			nspace = m_namespaces.erase(nspace);
 		}
+		m_last_namespace = 0;
 		return true;
 	}
 
 	Object* Model::getObject(const std::string& id, const std::string& name_space) {
-		std::list<namespace_t>::iterator nspace = m_namespaces.begin();
-		for(; nspace != m_namespaces.end(); ++nspace) {
-			if(nspace->first == name_space) {
-				std::list<Object*>::iterator obj = nspace->second.begin();
-				for(; obj != nspace->second.end(); ++obj)
-					if((*obj)->getId() == id) return *obj;
-			}
+		namespace_t* nspace = selectNamespace(name_space);
+		if(nspace) {
+			objectmap_t::iterator it = nspace->second.find(id);
+			if( it !=  nspace->second.end() )
+				return it->second;
 		}
-		for(; nspace != m_namespaces.end(); ++nspace) {
-			std::list<Object*>::iterator obj = nspace->second.begin();
-			for(; obj != nspace->second.end(); ++obj)
-				if((*obj)->getId() == id) return *obj;
-		}
- 
 		return 0;
 	}
 
-	const std::list<Object*>& Model::getObjects(const std::string& name_space) const {
+	std::list<Object*> Model::getObjects(const std::string& name_space) const {
+		std::list<Object*> object_list;
+		const namespace_t* nspace = selectNamespace(name_space);
+		if(nspace) {
+			objectmap_t::const_iterator it = nspace->second.begin();
+			for(; it != nspace->second.end(); ++it )
+				object_list.push_back(it->second);
+			return object_list;
+		}
+		throw NotFound(name_space);
+	}
+
+	const Model::namespace_t* Model::selectNamespace(const std::string& name_space) const {
 		std::list<namespace_t>::const_iterator nspace = m_namespaces.begin();
 		for(; nspace != m_namespaces.end(); ++nspace) {
-			if(nspace->first == name_space) return nspace->second;
+			if( nspace->first == name_space ) {
+				return &(*nspace);
+			}
 		}
+		return 0;
+	}
 
-		throw NotFound(name_space);
+	Model::namespace_t* Model::selectNamespace(const std::string& name_space) {
+		if( m_last_namespace && m_last_namespace->first == name_space )
+			return m_last_namespace;
+		std::list<namespace_t>::iterator nspace = m_namespaces.begin();
+		for(; nspace != m_namespaces.end(); ++nspace) {
+			if( nspace->first == name_space ) {
+				m_last_namespace = &(*nspace);
+				return m_last_namespace;
+			}
+		}
+		m_last_namespace = 0;
+		return 0;
 	}
 
 	void Model::update() {