/* 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 "list.h" #include "compiler.h" #include "debug.h" #include #include #include "shell_command.h" using namespace std; SHELL_COMMAND_STATIC(debug, ClassList, ClassList::debugS) ->describe("Shows all registered classes, if param1: is a valid ClassName only values of this class are shown. param2: how much output") ->defaultValues(2, NULL, 1); /** * Creates a new ClassList */ ClassList::ClassList(const long& classID, const char* className) { this->next = NULL; this->className = className; this->classID = classID; this->objectList = new tList; ++ClassList::classCount; } /** * standard deconstructor */ ClassList::~ClassList () { delete this->objectList; if(ClassList::classList != NULL) { delete ClassList::classList; ClassList::classList = NULL; } --ClassList::classCount; } //! the first class that is registered ClassList* ClassList::first = NULL; //! the Count of classes unsigned int ClassList::classCount = 0; //! a List of all strings of all classes, that have registered so far. tList* ClassList::classList = NULL; /** * 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 */ void ClassList::addToClassList(BaseObject* objectPointer, const long& classID, const char* className) { ClassList* regClass; PRINTF(5)("subscribe a %s\n", className ); if(ClassList::first == NULL) ClassList::first = regClass = new ClassList(classID, className); else { ClassList* tmp = ClassList::first; while (likely(tmp != NULL)) { if (tmp->classID == classID) { regClass = tmp; break; } if (unlikely(tmp->next == NULL)) { tmp->next = regClass = new ClassList(classID, className); break; } tmp = tmp->next; } } regClass->objectList->add(objectPointer); } /** * removes an Object from a the ClassList * @param objectPointer the Object to delete from the List */ void ClassList::removeFromClassList(BaseObject* objectPointer) { ClassList* tmp = ClassList::first; while (likely(tmp != NULL)) { if (objectPointer->isA(tmp->classID)) { tmp->objectList->remove(objectPointer); } tmp = tmp->next; } } /** * 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 tList* ClassList::getClassList() { if (unlikely(ClassList::classList != NULL && ClassList::classList->getSize() != ClassList::classCount)) { delete ClassList::classList; ClassList::classList = NULL; } if (unlikely(ClassList::classList == NULL)) ClassList::classList = new tList; if(likely(ClassList::first != NULL)) { ClassList* tmpCL = ClassList::first; while (likely(tmpCL != NULL)) { ClassList::classList->add(tmpCL->className); tmpCL = tmpCL->next; } } return ClassList::classList; } /** * 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 */ tList* ClassList::getList(long classID) { if(unlikely(ClassList::first == NULL)) return NULL; else { ClassList* tmpCL = ClassList::first; while (likely(tmpCL != NULL)) { if (unlikely(tmpCL->classID == classID)) return tmpCL->objectList; tmpCL = tmpCL->next; } } return NULL; } /** * 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 */tList* ClassList::getList(const char* className) { if(unlikely(ClassList::first == NULL)) return NULL; else { ClassList* tmpCL = ClassList::first; while (likely(tmpCL != NULL)) { if (unlikely(!strcmp(tmpCL->className, className))) return tmpCL->objectList; tmpCL = tmpCL->next; } } return NULL; } /** * checks if the BaseObject* object exists. * @param name 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 char* name, long classID) { if(unlikely(ClassList::first == NULL) || name == NULL) return NULL; else { ClassList* tmp = ClassList::first; while (likely(tmp != NULL)) { if (tmp->classID == classID || classID == CL_NULL) { tIterator* iterator = tmp->objectList->getIterator(); BaseObject* enumBO = iterator->firstElement(); const char* tmpName; while (enumBO != NULL) { tmpName = enumBO->getName(); if (tmpName && !strcmp(tmpName, name)) { delete iterator; return enumBO; } enumBO = iterator->nextElement(); } delete iterator; break; } tmp = tmp->next; } } return NULL; } /** * 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, long classID) { if(unlikely(ClassList::first == NULL)) return false; else { ClassList* tmp = ClassList::first; while (likely(tmp != NULL)) { if (tmp->classID == classID || classID == CL_NULL) { tIterator* iterator = tmp->objectList->getIterator(); BaseObject* enumBO = iterator->firstElement(); while (enumBO != NULL) { if (enumBO == object) { delete iterator; return true; } enumBO = iterator->nextElement(); } delete iterator; break; } tmp = tmp->next; } } return false; } /** * 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) { ClassList* tmp = ClassList::first; while (likely(tmp != NULL)) { if (object->isA(tmp->classID)) { PRINT(0)("=%s=-", tmp->className); } tmp = tmp->next; } } /** * 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 char* ClassList::IDToString(long classID) { if(likely(ClassList::first != NULL)) { ClassList* tmpCL = ClassList::first; while (likely(tmpCL != NULL)) { if (tmpCL->classID == classID) return tmpCL->className; tmpCL = tmpCL->next; } } return NULL; } /** * 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. */ long ClassList::StringToID(const char* className) { if (className == NULL) return CL_NULL; if(likely(ClassList::first != NULL)) { ClassList* tmpCL = ClassList::first; while (likely(tmpCL != NULL)) { if (!strcasecmp(tmpCL->className, className)) return tmpCL->classID; tmpCL = tmpCL->next; } } return CL_NULL; } /** * 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, long 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::classCount); ClassList* tmp = ClassList::first; char niceString[100]; unsigned int lenCount = 0; while (likely(tmp != NULL)) { if ((debugLevel >= 1 || tmp->objectList->getSize() > 0 ) && (classID == CL_NULL || unlikely (classID == tmp->classID))) { lenCount = 1; while (pow(10,lenCount) <= tmp->objectList->getSize()) ++lenCount; for (int i=0; i < 30-strlen(tmp->className) - lenCount; i++) (niceString[i]) = ' '; niceString[30-strlen(tmp->className) - lenCount] = '\0'; PRINT(0)("| CLASS %s:%s %d\n", tmp->className, niceString, tmp->objectList->getSize()); if (debugLevel >=2 && tmp->objectList->getSize() > 0) { PRINT(0)("| Listing Instances:\n"); tIterator* iterator = tmp->objectList->getIterator(); BaseObject* enumBO = iterator->firstElement(); while (enumBO) { PRINT(0)("| (class %s): NAME(%s)->%p ", enumBO->getClassName(), enumBO->getName(), enumBO); if (debugLevel == 3) ClassList::whatIs(enumBO); PRINT(0)("\n"); enumBO = iterator->nextElement(); } delete iterator; } } tmp = tmp->next; } PRINT(0)("=======================CL=\n"); } /** * 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 char* className, unsigned int debugLevel) { ClassList::debug(debugLevel, ClassList::StringToID(className)); }