Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: LoadParam had some major memory-leak… fixed them :)

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