/* 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: ... */ #include "load_param.h" #include "list.h" #include "base_object.h" #include /** \param object The object this Parameter is loaded too. \param root: the XML-element to load this option from. \param paramName: The name of the parameter loaded. \param paramCount: how many parameters this loading-function takes \param multi: if false LoadParam assumes only one occurence of this parameter in root, if true it assumes multiple occurences. \param ...: the parameter information */ BaseLoadParam::BaseLoadParam(const TiXmlElement* root, BaseObject* object, const char* paramName, int paramCount, bool multi, ...) { this->loadString = NULL; if (paramCount == 0) this->loadString = "none"; else { if (likely(!multi)) this->loadString = grabParameter(root, paramName); else { if (!strcmp(root->Value(), paramName)) { const TiXmlNode* val = root->FirstChild(); if( val->ToText()) this->loadString = val->Value(); } } } this->paramDesc = NULL; if (LoadClassDescription::parametersDescription) { // locating the class this->classDesc = LoadClassDescription::addClass(object->getClassName()); this->paramDesc = this->classDesc->addParam(paramName); this->paramDesc->types = new char*[paramCount]; this->paramDesc->paramCount = paramCount; va_list types; va_start (types, multi); for(int i = 0; i < paramCount; i++) { const char* tmpTypeName = va_arg (types, const char*); this->paramDesc->types[i] = new char[strlen(tmpTypeName)+1]; strcpy(this->paramDesc->types[i], tmpTypeName); } va_end(types); int argCount = 0; } } /** \param descriptionText The text to set as a description for this Parameter \returns a pointer to itself. */ BaseLoadParam* BaseLoadParam::describe(const char* descriptionText) { if (LoadClassDescription::parametersDescription && this->paramDesc && !this->paramDesc->getDescription()) { this->paramDesc->setDescription(descriptionText); } return this; } /** \param paramName the name of the parameter to load */ LoadParamDescription::LoadParamDescription(const char* paramName) { this->types = NULL; this->description = NULL; this->paramName = new char[strlen(paramName)+1]; strcpy(this->paramName, paramName); } /** \brief removes all the alocated memory */ LoadParamDescription::~LoadParamDescription(void) { for(int i = 0; i < this->paramCount; i++) { delete this->types[i]; } delete []this->types; delete []this->paramName; delete []this->description; } /** \param descriptionText The text to set as a description for this Parameter */ void LoadParamDescription::setDescription(const char* descriptionText) { this->description = new char[strlen(descriptionText)+1]; strcpy(this->description, descriptionText); } /** \brief prints out this parameter, its input method and the description (if availiable) */ void LoadParamDescription::print(void) const { PRINT(3)(" <%s>", this->paramName); for (int i = 0; i < this->paramCount; i++) { if (i > 0) PRINT(3)(","); PRINT(3)("%s", this->types[i]); } PRINT(3)("", this->paramName); if (this->description) PRINT(3)(" -- %s", this->description); PRINT(3)("\n"); } /** \brief A list, that holds all the classes that are loadable (classes not objects!!) */ tList* LoadClassDescription::classList = new tList; /** \brief if the description of Parameters should be executed */ bool LoadClassDescription::parametersDescription = true; /** \param className the name of the class to be loadable */ LoadClassDescription::LoadClassDescription(const char* className) { this->className = new char[strlen(className)+1]; strcpy(this->className, className); classList->add(this); this->paramList = new tList; } /** \brief deletes a classDescription (deletes all the parameterDescriptions as well */ LoadClassDescription::~LoadClassDescription(void) { delete []this->className; tIterator* iterator = this->paramList->getIterator(); LoadParamDescription* enumParamDesc = iterator->nextElement(); while (enumParamDesc) { delete enumParamDesc; enumParamDesc = iterator->nextElement(); } delete iterator; } /** \brief adds a class to the list of loadable classes \param className The name of the class to add this function searches for the className string, and if found just returns the appropriate Class. Otherwise it returns a new classDescription */ LoadClassDescription* LoadClassDescription::addClass(const char* className) { tIterator* iterator = LoadClassDescription::classList->getIterator(); LoadClassDescription* enumClassDesc = iterator->nextElement(); while (enumClassDesc) { if (!strcmp(enumClassDesc->className, className)) { delete iterator; return enumClassDesc; } enumClassDesc = iterator->nextElement(); } delete iterator; return new LoadClassDescription(className); } /** \brief does the same as addClass(const char* className), but with params \param paramName the name of the parameter to add. */ LoadParamDescription* LoadClassDescription::addParam(const char* paramName) { tIterator* iterator = this->paramList->getIterator(); LoadParamDescription* enumParamDesc = iterator->nextElement(); while (enumParamDesc) { if (!strcmp(enumParamDesc->paramName, paramName)) { delete iterator; return enumParamDesc; } enumParamDesc = iterator->nextElement(); } delete iterator; this->paramList->add(new LoadParamDescription(paramName)); return paramList->lastElement(); } /** \brief prints out all loadable Classes, and their parameters */ void LoadClassDescription::printAll(const char* fileName) { PRINT(3)("===============================================================\n"); PRINT(3)(" Listing all the Loadable Options (loaded since Game started).\n\n"); tIterator* classIT = LoadClassDescription::classList->getIterator(); LoadClassDescription* enumClassDesc = classIT->nextElement(); while (enumClassDesc) { PRINT(3)("<%s>\n", enumClassDesc->className); tIterator* paramIT = enumClassDesc->paramList->getIterator(); LoadParamDescription* enumParamDesc = paramIT->nextElement(); while (enumParamDesc) { enumParamDesc->print(); enumParamDesc = paramIT->nextElement(); } delete paramIT; PRINT(3)("\n\n", enumClassDesc->className); enumClassDesc = classIT->nextElement(); } delete classIT; PRINT(3)("===============================================================\n"); } /** \param root: The XML-element to grab a parameter from \param parameterName: the parameter to grab \returns the Value of the parameter if found, NULL otherwise */ const char* grabParameter(const TiXmlElement* root, const char* parameterName) { const TiXmlElement* element; const TiXmlNode* node; if (root == NULL) return NULL; assert( parameterName != NULL); element = root->FirstChildElement( parameterName); if( element == NULL) return NULL; node = element->FirstChild(); while( node != NULL) { if( node->ToText()) return node->Value(); node = node->NextSibling(); } return NULL; }