Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: minor cleanup (speed-issue) in LoadClassDescription, using enum insted of String, faster, more reliable

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