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
Line 
1/*
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:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#include "load_param.h"
17
18#include "list.h"
19#include "base_object.h"
20
21#include <stdarg.h>
22
23/**
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, ...)
30*/
31BaseLoadParam::BaseLoadParam(const TiXmlElement* root, BaseObject* object, const char* paramName,
32                             int paramCount, bool multi, const void* pointerToParam, ...)
33{
34  this->setClassID(CL_LOAD_PARAM, "LoadParam");
35
36  this->loadString = NULL;
37  this->pointerToParam = pointerToParam;
38
39  if (paramCount == 0 || this->pointerToParam)
40    this->loadString = "none";
41  else
42    {
43      if (likely(!multi))
44        this->loadString = grabParameter(root, paramName);
45      else
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        }
54    }
55
56  this->paramDesc = NULL;
57  if (LoadClassDescription::parametersDescription)
58  {
59    // locating the class
60    this->classDesc = LoadClassDescription::addClass(object->getClassName());
61
62    if ((this->paramDesc = this->classDesc->addParam(paramName)) != NULL)
63    {
64
65      this->paramDesc->paramCount = paramCount;
66      this->paramDesc->types = new char*[paramCount];
67      this->paramDesc->defaultValues = new char*[paramCount];
68
69      va_list types;
70      va_start (types, pointerToParam);
71      char defaultVal[512];
72      for(int i = 0; i < paramCount; i++)
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
79        //! @todo SWITCH CASE WITH l_[TYPE]_TYPE -> much faster
80          // default value description
81        if (!strcmp(tmpTypeName, l_INT_NAME))
82        {
83          sprintf(defaultVal, "%d", va_arg(types, l_INT_TYPE));
84        }
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      }
109      va_end(types);
110
111      int argCount = 0;
112    }
113  }
114}
115
116/**
117 * @param descriptionText The text to set as a description for this Parameter
118 * @returns a pointer to itself.
119*/
120BaseLoadParam* BaseLoadParam::describe(const char* descriptionText)
121{
122  if (LoadClassDescription::parametersDescription && this->paramDesc && !this->paramDesc->getDescription())
123    {
124      this->paramDesc->setDescription(descriptionText);
125    }
126  return this;
127}
128
129/**
130 * @param paramName the name of the parameter to load
131*/
132LoadParamDescription::LoadParamDescription(const char* paramName)
133{
134  this->types = NULL;
135  this->description = NULL;
136  this->defaultValues = NULL;
137  this->paramName = new char[strlen(paramName)+1];
138  strcpy(this->paramName, paramName);
139}
140
141/**
142 *  removes all the alocated memory
143*/
144LoadParamDescription::~LoadParamDescription()
145{
146  if (this->types != NULL)
147  {
148    for(int i = 0; i < this->paramCount; i++)
149    {
150      delete []this->types[i];
151    }
152  }
153  if (this->defaultValues != NULL)
154  {
155    for(int i = 0; i < this->paramCount; i++)
156    {
157      delete[] this->defaultValues[i];
158    }
159  }
160
161  delete[] this->types;
162  delete[] this->defaultValues;
163  delete[] this->paramName;
164  delete[] this->description;
165}
166
167/**
168 * @param descriptionText The text to set as a description for this Parameter
169*/
170void LoadParamDescription::setDescription(const char* descriptionText)
171{
172  this->description = new char[strlen(descriptionText)+1];
173  strcpy(this->description, descriptionText);
174}
175
176/**
177 *  prints out this parameter, its input method and the description (if availiable)
178*/
179void LoadParamDescription::print() const
180{
181  PRINT(3)(" <%s>", this->paramName);
182  for (int i = 0; i < this->paramCount; i++)
183    {
184      if (i > 0)
185        PRINT(3)(",");
186      PRINT(3)("%s", this->types[i]);
187    }
188  PRINT(3)("</%s>", this->paramName);
189  if (this->description)
190    PRINT(3)(" -- %s", this->description);
191  // default values
192  if (this->paramCount > 0)
193  {
194    PRINT(3)(" (Default: ");
195    for (int i = 0; i < this->paramCount; i++)
196    {
197      if (i > 0)
198        PRINT(3)(", ");
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      }
207    }
208    PRINT(3)(")");
209  }
210  PRINT(3)("\n");
211}
212
213/**
214 *  A list, that holds all the classes that are loadable (classes not objects!!)
215*/
216tList<LoadClassDescription>* LoadClassDescription::classList = NULL;
217
218/**
219 *  if the description of Parameters should be executed
220*/
221bool LoadClassDescription::parametersDescription = true;
222
223/**
224 * @param className the name of the class to be loadable
225*/
226LoadClassDescription::LoadClassDescription(const char* className)
227{
228  this->className = new char[strlen(className)+1];
229  strcpy(this->className, className);
230
231  if (LoadClassDescription::classList == NULL)
232    LoadClassDescription::classList = new tList<LoadClassDescription>;
233
234  LoadClassDescription::classList->add(this);
235
236  this->paramList = new tList<LoadParamDescription>;
237}
238
239/**
240 *  deletes a classDescription (deletes all the parameterDescriptions as well
241*/
242LoadClassDescription::~LoadClassDescription()
243{
244  tIterator<LoadParamDescription>* iterator = this->paramList->getIterator();
245  LoadParamDescription* enumParamDesc = iterator->firstElement();
246  while (enumParamDesc)
247    {
248      delete enumParamDesc;
249      enumParamDesc = iterator->nextElement();
250    }
251  delete iterator;
252  delete this->paramList;
253
254  delete[] this->className;
255}
256
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
275/**
276 *  adds a class to the list of loadable classes
277 * @param className The name of the class to add
278
279   this function searches for the className string, and if found just returns the appropriate Class.
280   Otherwise it returns a new classDescription
281*/
282LoadClassDescription* LoadClassDescription::addClass(const char* className)
283{
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  }
299  return new LoadClassDescription(className);
300}
301
302/**
303 *  does the same as addClass(const char* className), but with params
304 * @param paramName the name of the parameter to add.
305*/
306LoadParamDescription* LoadClassDescription::addParam(const char* paramName)
307{
308  tIterator<LoadParamDescription>* iterator = this->paramList->getIterator();
309  LoadParamDescription* enumParamDesc = iterator->firstElement();
310  while (enumParamDesc)
311    {
312      if (!strcmp(enumParamDesc->paramName, paramName))
313        {
314          delete iterator;
315          //return enumParamDesc;
316          return NULL;
317        }
318      enumParamDesc = iterator->nextElement();
319    }
320  delete iterator;
321
322  LoadParamDescription* newParam = new LoadParamDescription(paramName);
323
324  this->paramList->add(newParam);
325  return newParam;
326}
327
328/**
329 *  prints out all loadable Classes, and their parameters
330 * @param fileName prints the output to a File
331 * @todo implement it
332*/
333void LoadClassDescription::printAll(const char* fileName)
334{
335  PRINT(3)("===============================================================\n");
336  PRINT(3)(" Listing all the Loadable Options (loaded since Game started).\n\n");
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;
352
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");
360  PRINT(3)("===============================================================\n");
361}
362
363/**
364 * searches for classes, which beginn with classNameBegin
365 * @param classNameBegin the beginning string of a Class
366 * @return a NEW char-array with ClassNames. The LIST should be deleted afterwards,
367 * !! The strings MUST NOT be deleted !!
368 */
369tList<const char>* LoadClassDescription::searchClassWithShort(const char* classNameBegin)
370{
371  unsigned int searchLength = strlen(classNameBegin);
372  tList<const char>* retVal = new tList<const char>;
373
374  tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
375  LoadClassDescription* enumClassDesc = iterator->firstElement();
376  while (enumClassDesc)
377  {
378    if (strlen(enumClassDesc->className)>searchLength+1 &&
379        !strncasecmp(enumClassDesc->className, classNameBegin, searchLength))
380    {
381      retVal->add(enumClassDesc->className);
382    }
383    enumClassDesc = iterator->nextElement();
384  }
385  delete iterator;
386
387  return retVal;
388}
389
390// const LoadParamDescription* LoadParamDescription::getClass(const char* className)
391// {
392//   tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
393//   LoadClassDescription* enumClassDesc = iterator->firstElement();
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
408/**
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
412*/
413const char* grabParameter(const TiXmlElement* root, const char* parameterName)
414{
415  const TiXmlElement* element;
416  const TiXmlNode* node;
417
418  if (root == NULL)
419    return NULL;
420  assert( parameterName != NULL);
421
422  element = root->FirstChildElement( parameterName);
423  if( element == NULL) return NULL;
424
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.