Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/util/loading/load_param.cc @ 5534

Last change on this file since 5534 was 5534, checked in by bensch, 19 years ago

orxonox/trunk: loadParam does not anymore produce a description. → it resulted in a possible segfault on fedora3. (not that this would make much sense to me, but well…)

File size: 12.4 KB
RevLine 
[4597]1/*
[4250]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
[4285]12   main-programmer: Benjamin Grauer
[4250]13   co-programmer: ...
14*/
15
[5332]16#include "functor_list.h"
17
[4250]18#include "load_param.h"
19
[4254]20#include "list.h"
21#include "base_object.h"
[4250]22
[4254]23#include <stdarg.h>
24
[4256]25/**
[4836]26 * @param object The object this Parameter is loaded too.
27 * @param root: the XML-element to load this option from.
28 * @param paramName: The name of the parameter loaded.
29 * @param paramCount: how many parameters this loading-function takes
30 * @param multi: if false LoadParam assumes only one occurence of this parameter in root, if true it assumes multiple occurences.
31 * @param ...: the parameter information (1. Parameter, 2. Default Value for the Parameter, ...)
[4256]32*/
[4496]33BaseLoadParam::BaseLoadParam(const TiXmlElement* root, BaseObject* object, const char* paramName,
[4598]34                             int paramCount, bool multi, const void* pointerToParam, ...)
[4251]35{
[4597]36  this->setClassID(CL_LOAD_PARAM, "LoadParam");
[4637]37
[4496]38  this->loadString = NULL;
[4598]39  this->pointerToParam = pointerToParam;
[4299]40
[4598]41  if (paramCount == 0 || this->pointerToParam)
[4501]42    this->loadString = "none";
[4496]43  else
44    {
[4501]45      if (likely(!multi))
[4597]46        this->loadString = grabParameter(root, paramName);
[4501]47      else
[4597]48        {
49          if (!strcmp(root->Value(), paramName))
50            {
51              const TiXmlNode* val = root->FirstChild();
52              if( val->ToText())
53                this->loadString = val->Value();
54            }
55        }
[4496]56    }
57
[4255]58  this->paramDesc = NULL;
[4254]59  if (LoadClassDescription::parametersDescription)
[4623]60  {
[4625]61    // locating the class
[4623]62    this->classDesc = LoadClassDescription::addClass(object->getClassName());
[4254]63
[4623]64    if ((this->paramDesc = this->classDesc->addParam(paramName)) != NULL)
65    {
66
67      this->paramDesc->paramCount = paramCount;
[5332]68      this->paramDesc->types = new int[paramCount];
[4623]69      this->paramDesc->defaultValues = new char*[paramCount];
[4254]70
71      va_list types;
[4598]72      va_start (types, pointerToParam);
[4623]73      char defaultVal[512];
[4254]74      for(int i = 0; i < paramCount; i++)
[4623]75      {
[5334]76        defaultVal[0] = '\0';
[4623]77          // parameters parsed
[5332]78        int tmpType = va_arg (types, int);
79        this->paramDesc->types[i] = tmpType;
80        switch (tmpType)
[4597]81        {
[5332]82          case ParameterInt:
[5334]83            sprintf(defaultVal, "%d", va_arg(types, int));
[5332]84            break;
85          case ParameterLong:
86            sprintf(defaultVal, "%0.3f", va_arg(types, l_LONG_TYPE));
87            break;
88          case ParameterFloat:
89            sprintf(defaultVal, "%0.3f", va_arg(types, double));
90            break;
91          case ParameterString:
92            sprintf(defaultVal, "%s", va_arg(types, l_STRING_TYPE));
93            break;
94          case ParameterXML:
95            sprintf(defaultVal, "");
96            break;
[4597]97        }
[4623]98        this->paramDesc->defaultValues[i] = new char[strlen(defaultVal)+1];
99        strcpy(this->paramDesc->defaultValues[i], defaultVal);
100      }
[4299]101      va_end(types);
[4254]102
103      int argCount = 0;
104    }
[4623]105  }
[4251]106}
[4250]107
[4860]108/**
[4836]109 * @param descriptionText The text to set as a description for this Parameter
110 * @returns a pointer to itself.
[4256]111*/
[4260]112BaseLoadParam* BaseLoadParam::describe(const char* descriptionText)
[4254]113{
[4255]114  if (LoadClassDescription::parametersDescription && this->paramDesc && !this->paramDesc->getDescription())
[4254]115    {
[4255]116      this->paramDesc->setDescription(descriptionText);
[4254]117    }
[4260]118  return this;
[4254]119}
120
[4256]121/**
[4836]122 * @param paramName the name of the parameter to load
[4256]123*/
[4254]124LoadParamDescription::LoadParamDescription(const char* paramName)
125{
126  this->types = NULL;
[4255]127  this->description = NULL;
[5211]128  this->defaultValues = NULL;
[4254]129  this->paramName = new char[strlen(paramName)+1];
130  strcpy(this->paramName, paramName);
131}
132
[4256]133/**
[4836]134 *  removes all the alocated memory
[4256]135*/
[4746]136LoadParamDescription::~LoadParamDescription()
[4254]137{
[5099]138  if (this->defaultValues != NULL)
[4623]139  {
[5099]140    for(int i = 0; i < this->paramCount; i++)
141    {
[5218]142      delete[] this->defaultValues[i];
[5099]143    }
[4623]144  }
145
[5211]146  delete[] this->types;
147  delete[] this->defaultValues;
148  delete[] this->paramName;
149  delete[] this->description;
[4254]150}
151
[4256]152/**
[4836]153 * @param descriptionText The text to set as a description for this Parameter
[4256]154*/
[4255]155void LoadParamDescription::setDescription(const char* descriptionText)
156{
[4256]157  this->description = new char[strlen(descriptionText)+1];
158  strcpy(this->description, descriptionText);
[4255]159}
[4254]160
[4256]161/**
[4836]162 *  prints out this parameter, its input method and the description (if availiable)
[4256]163*/
[4746]164void LoadParamDescription::print() const
[4255]165{
166  PRINT(3)(" <%s>", this->paramName);
167  for (int i = 0; i < this->paramCount; i++)
168    {
169      if (i > 0)
[4597]170        PRINT(3)(",");
[5332]171      switch (this->types[i])
172      {
173        default:
174          PRINTF(3)("none");
175          break;
176        case ParameterBool:
177          PRINT(3)("bool");
178          break;
179        case ParameterChar:
180          PRINT(3)("char");
181          break;
182        case ParameterString:
183          PRINT(3)("string");
184          break;
185        case ParameterInt:
186          PRINT(3)("int");
187          break;
188        case ParameterUInt:
189          PRINT(3)("Uint");
190          break;
191        case ParameterFloat:
192          PRINT(3)("float");
193          break;
194        case ParameterLong:
195          PRINT(3)("long");
196          break;
197        case ParameterXML:
198          PRINT(3)("XML");
199          break;
200      }
[4255]201    }
202  PRINT(3)("</%s>", this->paramName);
203  if (this->description)
204    PRINT(3)(" -- %s", this->description);
[4623]205  // default values
206  if (this->paramCount > 0)
207  {
[4637]208    PRINT(3)(" (Default: ");
[4623]209    for (int i = 0; i < this->paramCount; i++)
210    {
211      if (i > 0)
212        PRINT(3)(", ");
[5332]213      if (this->types[i] & ParameterString)
[4625]214      { // leave brackets !!
215        PRINT(3)("\"%s\"", this->defaultValues[i]);
216      }
217      else
218      {
219        PRINT(3)("%s", this->defaultValues[i]);
220      }
[4623]221    }
222    PRINT(3)(")");
223  }
[4255]224  PRINT(3)("\n");
225}
226
[4256]227/**
[4836]228 *  A list, that holds all the classes that are loadable (classes not objects!!)
[4256]229*/
[5226]230tList<LoadClassDescription>* LoadClassDescription::classList = NULL;
[4254]231
[4251]232/**
[4836]233 *  if the description of Parameters should be executed
[4251]234*/
[5534]235bool LoadClassDescription::parametersDescription = false;
[4254]236
[4256]237/**
[4836]238 * @param className the name of the class to be loadable
[4256]239*/
[4254]240LoadClassDescription::LoadClassDescription(const char* className)
241{
242  this->className = new char[strlen(className)+1];
243  strcpy(this->className, className);
244
[5226]245  if (LoadClassDescription::classList == NULL)
246    LoadClassDescription::classList = new tList<LoadClassDescription>;
[4254]247
[5226]248  LoadClassDescription::classList->add(this);
249
[4254]250  this->paramList = new tList<LoadParamDescription>;
251}
252
[4256]253/**
[4836]254 *  deletes a classDescription (deletes all the parameterDescriptions as well
[4256]255*/
[4746]256LoadClassDescription::~LoadClassDescription()
[4254]257{
258  tIterator<LoadParamDescription>* iterator = this->paramList->getIterator();
[5115]259  LoadParamDescription* enumParamDesc = iterator->firstElement();
[4254]260  while (enumParamDesc)
261    {
262      delete enumParamDesc;
263      enumParamDesc = iterator->nextElement();
264    }
265  delete iterator;
[5227]266  delete this->paramList;
[5226]267
268  delete[] this->className;
[4254]269}
270
[5226]271void LoadClassDescription::deleteAllDescriptions()
272{
273  if (LoadClassDescription::classList != NULL)
274  {
275    tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
276    LoadClassDescription* delElem = iterator->firstElement();
277    while (delElem != NULL)
278    {
279      delete delElem;
280      delElem = iterator->nextElement();
281    }
282    delete iterator;
283    delete LoadClassDescription::classList;
284  }
285  LoadClassDescription::classList = NULL;
286}
287
288
[4256]289/**
[4836]290 *  adds a class to the list of loadable classes
291 * @param className The name of the class to add
[4254]292
[4256]293   this function searches for the className string, and if found just returns the appropriate Class.
294   Otherwise it returns a new classDescription
295*/
[4254]296LoadClassDescription* LoadClassDescription::addClass(const char* className)
297{
[5226]298  if (LoadClassDescription::classList != NULL)
299  {
300    tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
301   LoadClassDescription* enumClassDesc = iterator->firstElement();
302   while (enumClassDesc)
303     {
304       if (!strcmp(enumClassDesc->className, className))
305         {
306           delete iterator;
307           return enumClassDesc;
308         }
309       enumClassDesc = iterator->nextElement();
310     }
311   delete iterator;
312  }
[4254]313  return new LoadClassDescription(className);
314}
315
[4256]316/**
[4836]317 *  does the same as addClass(const char* className), but with params
318 * @param paramName the name of the parameter to add.
[4256]319*/
[4254]320LoadParamDescription* LoadClassDescription::addParam(const char* paramName)
321{
322  tIterator<LoadParamDescription>* iterator = this->paramList->getIterator();
[5115]323  LoadParamDescription* enumParamDesc = iterator->firstElement();
[4254]324  while (enumParamDesc)
325    {
326      if (!strcmp(enumParamDesc->paramName, paramName))
[4597]327        {
328          delete iterator;
[5227]329          //return enumParamDesc;
330          return NULL;
[4597]331        }
[4254]332      enumParamDesc = iterator->nextElement();
333    }
334  delete iterator;
335
[5227]336  LoadParamDescription* newParam = new LoadParamDescription(paramName);
337
338  this->paramList->add(newParam);
339  return newParam;
[4254]340}
[4255]341
[4256]342/**
[4836]343 *  prints out all loadable Classes, and their parameters
[5100]344 * @param fileName prints the output to a File
345 * @todo implement it
[4256]346*/
[4260]347void LoadClassDescription::printAll(const char* fileName)
[4255]348{
[4259]349  PRINT(3)("===============================================================\n");
350  PRINT(3)(" Listing all the Loadable Options (loaded since Game started).\n\n");
[5226]351  if (LoadClassDescription::classList != NULL)
352  {
353    tIterator<LoadClassDescription>* classIT = LoadClassDescription::classList->getIterator();
354    LoadClassDescription* enumClassDesc = classIT->firstElement();
355    while (enumClassDesc)
356     {
357       PRINT(3)("<%s>\n", enumClassDesc->className);
358       tIterator<LoadParamDescription>* paramIT = enumClassDesc->paramList->getIterator();
359       LoadParamDescription* enumParamDesc = paramIT->firstElement();
360       while (enumParamDesc)
361         {
362           enumParamDesc->print();
363           enumParamDesc = paramIT->nextElement();
364         }
365       delete paramIT;
[4255]366
[5226]367       PRINT(3)("</%s>\n\n", enumClassDesc->className);
368       enumClassDesc = classIT->nextElement();
369     }
370    delete classIT;
371  }
372  else
373    PRINT(3)("no Classes defined so far\n");
[4259]374  PRINT(3)("===============================================================\n");
[4255]375}
[4492]376
[5100]377/**
378 * searches for classes, which beginn with classNameBegin
379 * @param classNameBegin the beginning string of a Class
[5113]380 * @return a NEW char-array with ClassNames. The LIST should be deleted afterwards,
[5100]381 * !! The strings MUST NOT be deleted !!
382 */
[5113]383tList<const char>* LoadClassDescription::searchClassWithShort(const char* classNameBegin)
[5100]384{
385  unsigned int searchLength = strlen(classNameBegin);
[5113]386  tList<const char>* retVal = new tList<const char>;
[4492]387
[5100]388  tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
[5115]389  LoadClassDescription* enumClassDesc = iterator->firstElement();
[5100]390  while (enumClassDesc)
391  {
392    if (strlen(enumClassDesc->className)>searchLength+1 &&
393        !strncasecmp(enumClassDesc->className, classNameBegin, searchLength))
394    {
[5113]395      retVal->add(enumClassDesc->className);
[5100]396    }
397    enumClassDesc = iterator->nextElement();
398  }
399  delete iterator;
[4492]400
[5100]401  return retVal;
402}
403
404// const LoadParamDescription* LoadParamDescription::getClass(const char* className)
405// {
406//   tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
[5115]407//   LoadClassDescription* enumClassDesc = iterator->firstElement();
[5100]408//   while (enumClassDesc)
409//   {
410//     if (!strcmp(enumClassDesc->className, classNameBegin, className))
411//     {
412//       delete iterator;
413//       return enumClassDesc;
414//     }
415//     enumClassDesc = iterator->nextElement();
416//   }
417//   delete iterator;
418//
419//   return NULL;
420// }
421
[4492]422/**
[4836]423 * @param root: The XML-element to grab a parameter from
424 * @param parameterName: the parameter to grab
425 * @returns the Value of the parameter if found, NULL otherwise
[4492]426*/
427const char* grabParameter(const TiXmlElement* root, const char* parameterName)
428{
429  const TiXmlElement* element;
430  const TiXmlNode* node;
[4597]431
[4492]432  if (root == NULL)
433    return NULL;
434  assert( parameterName != NULL);
[4597]435
[4492]436  element = root->FirstChildElement( parameterName);
437  if( element == NULL) return NULL;
[4597]438
[4492]439  node = element->FirstChild();
440  while( node != NULL)
441    {
442      if( node->ToText()) return node->Value();
443      node = node->NextSibling();
444    }
445  return NULL;
446}
Note: See TracBrowser for help on using the repository browser.