/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ #include "class_list.h" #include "base_object.h" #include "compiler.h" #include "debug.h" #include /** * @brief Creates a new ClassList */ ClassList::ClassList(ClassID classID, unsigned long classIDFull, const std::string& className) : className(className) { this->classID = classID; this->classIDFull = classIDFull; } /** * @brief standard deconstructor */ ClassList::~ClassList () { // ClassList::classList->clear()); } //! a List of all known Classes. std::list* ClassList::classList = NULL; //! a List of all strings of all classes, that have registered so far. std::list ClassList::classNames; /** * @brief Adds a new Object to the ClassList (and if necessary a new Class) * @param objectPointer Pointer to the Object at hand * @param classID ID of the Given ObjectType \see ClassID * @param className name of the Class to add * * !! FIRST YOU HAVE TO CALL THIS FUNCTION ONCE * !! Before unsing the ClassList, as it creates the ClassLits */ ClassList* ClassList::addToClassList(BaseObject* objectPointer, ClassID classID, unsigned long classIDFull, const std::string& className) { if (unlikely(classList == NULL)) ClassList::classList = new std::list(); PRINTF(5)("subscribe a '%s'\n", className.c_str() ); ClassList* regClass = ClassList::getClassList(classID); if (regClass != NULL) { regClass->objectList.push_back(objectPointer); return regClass; } else { ClassList::classList->push_back(ClassList(classID, classIDFull, className)); ClassList::classList->back().objectList.push_back(objectPointer); return &ClassList::classList->back(); } } /** * @brief removes an Object from a the ClassList * @param objectPointer the Object to delete from the List */ void ClassList::removeFromClassList(BaseObject* objectPointer) { std::list::iterator cl; for(cl = ClassList::classList->begin(); cl != ClassList::classList->end(); cl++) { if (objectPointer->isA((*cl).classID)) { std::list::iterator bo = std::find ((*cl).objectList.begin(), (*cl).objectList.end(), objectPointer); if (bo != (*cl).objectList.end()) (*cl).objectList.erase(bo); } } } /** * @brief grabs the names of all Classes, and injects it into a List of const chars * @return the generated List * * This function first looks, if the List has been changed (by the ListSize) * befor it changes anything. */ const std::list* ClassList::getClassNames() { if (ClassList::classNames.size() != ClassList::classList->size()) { ClassList::classNames.clear(); std::list::const_iterator cl; for (cl = ClassList::classList->begin(); cl != ClassList::classList->end(); cl++) ClassList::classNames.push_back((*cl).className); } return &ClassList::classNames; } /** * @brief searches for classID and returns the list of Entities * @param classID the ID of the class to get the list from * @return the List accessed by classID, or NULL if not found */ const std::list* ClassList::getList(ClassID classID) { ClassList* fl; return ((fl = ClassList::getClassList(classID)) != NULL)? &(fl->objectList) : NULL; /* std::list::iterator classIT = find (classList->begin(), classList->end(), classID); return (likely(classIT != classList->end()))? &(*classIT).objectList : NULL;*/ /* for (classIT = ClassList::classList->begin(); classIT != ClassList::classList->end(); classIT++) { if ((*classIT) == classID ) return &(*classIT).objectList; } return NULL;*/ } /** * @brief searches for className and returns the list of Entities * @param className the name of the class to get the list from * @return the List accessed by classID, or NULL if not found */ const std::list* ClassList::getList(const std::string& className) { ClassList* fl; return ((fl = ClassList::getClassList(className)) != NULL)? &(fl->objectList) : NULL; /* std::list::iterator classIT = find (classList->begin(), classList->end(), className); return (likely(classIT != classList->end()))? &(*classIT).objectList : NULL;*/ /* for (classIT = ClassList::classList->begin(); classIT != ClassList::classList->end(); classIT++) { if ((*classIT) == className ) return &(*classIT).objectList; } return NULL;*/ } /** * !!PRIVATE!! * @param classID the ClassID to search for * @returns the ClassList with classID as specifyer, or NULL if not */ ClassList* ClassList::getClassList(ClassID classID) { std::list::iterator classIT = find (ClassList::classList->begin(), ClassList::classList->end(), classID); return (likely(classIT != classList->end()))? &(*classIT) : NULL; } /** * !!PRIVATE!! * @param className the ClassName to search for * @returns the ClassList with className as specifyer, or NULL if not */ ClassList* ClassList::getClassList(const std::string& className) { if (className.empty()) return NULL; std::list::iterator classIT = find (classList->begin(), classList->end(), className); return (likely(classIT != classList->end()))? &(*classIT) : NULL; } /** * @brief checks if the BaseObject* object exists. * @param objectName the name of the BaseObject to look for * @param classID if not CL_NULL it will only search through a specific type of Objects. Otherwise it will be searched everywhere. * @return true, if the Object Exists in the specified ClassID, false otherwise * @todo: speed this up!! */ BaseObject* ClassList::getObject(const std::string& objectName, ClassID classID) { if (classID != CL_NULL) { ClassList* cl = ClassList::getClassList(classID); if (cl != NULL) { std::list::iterator bo; for (bo = cl->objectList.begin(); bo != cl->objectList.end(); bo++) if (objectName == (*bo)->getName()) return (*bo); } } else { std::list::iterator cl; for (cl = ClassList::classList->begin(); cl != ClassList::classList->end(); cl++) { std::list::iterator bo; for (bo = (*cl).objectList.begin(); bo != (*cl).objectList.end(); bo++) if (objectName == (*bo)->getName()) return (*bo); } } return NULL; } /** * @brief checks if the BaseObject* object exists. * @param objectName the name of the BaseObject to look for * @param classID if not CL_NULL it will only search through a specific type of Objects. Otherwise it will be searched everywhere. * @return true, if the Object Exists in the specified ClassID, false otherwise * @todo: speed this up!! */ BaseObject* ClassList::getObject(const std::string& objectName, const std::string& className) { ClassList* cl = ClassList::getClassList(className); if (cl != NULL) { std::list::iterator bo; for (bo = cl->objectList.begin(); bo != cl->objectList.end(); bo++) if (objectName == (*bo)->getName()) return (*bo); } return NULL; } /** * @brief checks if the BaseObject* object exists. * @param object the Pointer to a BaseObject to check if it exists * @param classID if not CL_NULL it will only search through a specific type of Objects. Otherwise it will be searched everywhere. * @return true, if the Object Exists in the specified ClassID, false otherwise * @todo: speed this up!! */ bool ClassList::exists(const BaseObject* object, ClassID classID) { if (classID != CL_NULL) { ClassList* cl = ClassList::getClassList(classID); if (cl != NULL) { std::list::const_iterator bo = std::find (cl->objectList.begin(), cl->objectList.end(), object); return (bo != cl->objectList.end()); } } else { std::list::iterator cl; for (cl = ClassList::classList->begin(); cl != ClassList::classList->end(); cl++) { std::list::const_iterator bo = std::find ((*cl).objectList.begin(), (*cl).objectList.end(), object); if (bo != (*cl).objectList.end()) return true; } } return false; } bool ClassList::exists(const std::string& className, const std::string& objectName) { ClassList* cl = ClassList::getClassList(className); if (likely(cl != NULL)) { std::list::iterator bo; for (bo = cl->objectList.begin(); bo != cl->objectList.end(); bo++) if (objectName == (*bo)->getName()) return true; } return false; } /** * @brief prints out a string of all the types this Object matches * @param object a Pointer to the object to analyze */ void ClassList::whatIs(const BaseObject* object) { std::list::iterator cl; for (cl = ClassList::classList->begin(); cl != ClassList::classList->end(); cl++) if (object->isA((*cl).classID)) { PRINT(0)("=%s::0x%.8X=-", (*cl).className.c_str(), (*cl).classID); } } /** * @brief converts a ClassID into a string * @param classID the ClassID to search for * @return a String containing the name of the Class, NULL if the Class was not found */ const std::string& ClassList::IDToString(ClassID classID) { static const std::string empty(""); ClassList* cl = ClassList::getClassList(classID); return (cl != NULL) ? cl->className : empty; } /** * @brief converts a String into a ClassID * @param className the name of the class to search for * @return the ClassID. CL_NULL, if the class was not found. */ ClassID ClassList::StringToID(const std::string& className) { ClassList* cl = ClassList::getClassList(className); return (cl != NULL) ? cl->classID : CL_NULL; } /** * @brief checks if this ClassList is named className * @param className the Name to check this ClassList's ClassName against * @returns true on match, false otherwise */ bool ClassList::operator==(const std::string& className) { return (this->className == className); } /** * @brief Print out some very nice debug information * @param debugLevel the level of verbosity * @param classID the class that should be displayed (if CL_NULL (default) all classes will be displayed) */ void ClassList::debug(unsigned int debugLevel, ClassID classID) { if (debugLevel > 3) debugLevel = 3; PRINT(0)("==========================\n"); PRINT(0)("= CLASS_LIST (level %d) =\n", debugLevel); PRINT(0)("==========================\n"); PRINT(0)("| knows %d Classes\n|\n", ClassList::classList->size()); char niceString[100]; int lenCount = 0; std::list::iterator cl; for (cl = ClassList::classList->begin(); cl != ClassList::classList->end(); cl++) { if ((debugLevel >= 1 || (*cl).objectList.size() > 0 ) && (classID == CL_NULL || unlikely (classID == (*cl).classID))) { lenCount = 1; while (std::pow((float)10, (int)lenCount) <= (*cl).objectList.size()) ++lenCount; for (unsigned int i=0; i < 30-(*cl).className.size() - lenCount; i++) (niceString[i]) = ' '; niceString[30-(*cl).className.size() - lenCount] = '\0'; PRINT(0)("| CLASS %s::%s %d\n", (*cl).className.c_str(), niceString, (*cl).objectList.size()); if (debugLevel >=2 && (*cl).objectList.size() > 0) { PRINT(0)("| Listing Instances:\n"); std::list::const_iterator bo; for (bo = (*cl).objectList.begin(); bo != (*cl).objectList.end(); bo++) { PRINT(0)("| %s::%s::(0x%.8X->%p ", (*bo)->getClassCName(), (*bo)->getCName(), (*bo)->getClassID(), (*bo)); if (debugLevel == 3) ClassList::whatIs(*bo); PRINT(0)("\n"); } } } } PRINT(0)("=======================CL=\n"); } /** * @brief Print out some very nice debug information * @param debugLevel the level of verbosity * @param className the class that should be displayed. * @see ClassList::debug */ void ClassList::debugS(const std::string& className, unsigned int debugLevel) { ClassList::debug(debugLevel, ClassList::StringToID(className)); }