Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/util/loading/load_param.cc @ 5577

Last change on this file since 5577 was 5535, checked in by hdavid, 19 years ago

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

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        defaultVal[0] = '\0';
77          // parameters parsed
78        int tmpType = va_arg (types, int);
79        this->paramDesc->types[i] = tmpType;
80        switch (tmpType)
81        {
82          case ParameterInt:
83            sprintf(defaultVal, "%d", va_arg(types, int));
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;
97        }
98        this->paramDesc->defaultValues[i] = new char[strlen(defaultVal)+1];
99        strcpy(this->paramDesc->defaultValues[i], defaultVal);
100      }
101      va_end(types);
102
103      int argCount = 0;
104    }
105  }
106}
107
108/**
109 * @param descriptionText The text to set as a description for this Parameter
110 * @returns a pointer to itself.
111*/
112BaseLoadParam* BaseLoadParam::describe(const char* descriptionText)
113{
114  if (LoadClassDescription::parametersDescription && this->paramDesc && !this->paramDesc->getDescription())
115    {
116      this->paramDesc->setDescription(descriptionText);
117    }
118  return this;
119}
120
121/**
122 * @param paramName the name of the parameter to load
123*/
124LoadParamDescription::LoadParamDescription(const char* paramName)
125{
126  this->types = NULL;
127  this->description = NULL;
128  this->defaultValues = NULL;
129  this->paramName = new char[strlen(paramName)+1];
130  strcpy(this->paramName, paramName);
131}
132
133/**
134 *  removes all the alocated memory
135*/
136LoadParamDescription::~LoadParamDescription()
137{
138  if (this->defaultValues != NULL)
139  {
140    for(int i = 0; i < this->paramCount; i++)
141    {
142      delete[] this->defaultValues[i];
143    }
144  }
145
146  delete[] this->types;
147  delete[] this->defaultValues;
148  delete[] this->paramName;
149  delete[] this->description;
150}
151
152/**
153 * @param descriptionText The text to set as a description for this Parameter
154*/
155void LoadParamDescription::setDescription(const char* descriptionText)
156{
157  this->description = new char[strlen(descriptionText)+1];
158  strcpy(this->description, descriptionText);
159}
160
161/**
162 *  prints out this parameter, its input method and the description (if availiable)
163*/
164void LoadParamDescription::print() const
165{
166  PRINT(3)(" <%s>", this->paramName);
167  for (int i = 0; i < this->paramCount; i++)
168    {
169      if (i > 0)
170        PRINT(3)(",");
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      }
201    }
202  PRINT(3)("</%s>", this->paramName);
203  if (this->description)
204    PRINT(3)(" -- %s", this->description);
205  // default values
206  if (this->paramCount > 0)
207  {
208    PRINT(3)(" (Default: ");
209    for (int i = 0; i < this->paramCount; i++)
210    {
211      if (i > 0)
212        PRINT(3)(", ");
213      if (this->types[i] & ParameterString)
214      { // leave brackets !!
215        PRINT(3)("\"%s\"", this->defaultValues[i]);
216      }
217      else
218      {
219        PRINT(3)("%s", this->defaultValues[i]);
220      }
221    }
222    PRINT(3)(")");
223  }
224  PRINT(3)("\n");
225}
226
227/**
228 *  A list, that holds all the classes that are loadable (classes not objects!!)
229*/
230tList<LoadClassDescription>* LoadClassDescription::classList = NULL;
231
232/**
233 *  if the description of Parameters should be executed
234*/
235bool LoadClassDescription::parametersDescription = false;
236
237/**
238 * @param className the name of the class to be loadable
239*/
240LoadClassDescription::LoadClassDescription(const char* className)
241{
242  this->className = new char[strlen(className)+1];
243  strcpy(this->className, className);
244
245  if (LoadClassDescription::classList == NULL)
246    LoadClassDescription::classList = new tList<LoadClassDescription>;
247
248  LoadClassDescription::classList->add(this);
249
250  this->paramList = new tList<LoadParamDescription>;
251}
252
253/**
254 *  deletes a classDescription (deletes all the parameterDescriptions as well
255*/
256LoadClassDescription::~LoadClassDescription()
257{
258  tIterator<LoadParamDescription>* iterator = this->paramList->getIterator();
259  LoadParamDescription* enumParamDesc = iterator->firstElement();
260  while (enumParamDesc)
261    {
262      delete enumParamDesc;
263      enumParamDesc = iterator->nextElement();
264    }
265  delete iterator;
266  delete this->paramList;
267
268  delete[] this->className;
269}
270
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
289/**
290 *  adds a class to the list of loadable classes
291 * @param className The name of the class to add
292
293   this function searches for the className string, and if found just returns the appropriate Class.
294   Otherwise it returns a new classDescription
295*/
296LoadClassDescription* LoadClassDescription::addClass(const char* className)
297{
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  }
313  return new LoadClassDescription(className);
314}
315
316/**
317 *  does the same as addClass(const char* className), but with params
318 * @param paramName the name of the parameter to add.
319*/
320LoadParamDescription* LoadClassDescription::addParam(const char* paramName)
321{
322  tIterator<LoadParamDescription>* iterator = this->paramList->getIterator();
323  LoadParamDescription* enumParamDesc = iterator->firstElement();
324  while (enumParamDesc)
325    {
326      if (!strcmp(enumParamDesc->paramName, paramName))
327        {
328          delete iterator;
329          //return enumParamDesc;
330          return NULL;
331        }
332      enumParamDesc = iterator->nextElement();
333    }
334  delete iterator;
335
336  LoadParamDescription* newParam = new LoadParamDescription(paramName);
337
338  this->paramList->add(newParam);
339  return newParam;
340}
341
342/**
343 *  prints out all loadable Classes, and their parameters
344 * @param fileName prints the output to a File
345 * @todo implement it
346*/
347void LoadClassDescription::printAll(const char* fileName)
348{
349  PRINT(3)("===============================================================\n");
350  PRINT(3)(" Listing all the Loadable Options (loaded since Game started).\n\n");
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;
366
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");
374  PRINT(3)("===============================================================\n");
375}
376
377/**
378 * searches for classes, which beginn with classNameBegin
379 * @param classNameBegin the beginning string of a Class
380 * @return a NEW char-array with ClassNames. The LIST should be deleted afterwards,
381 * !! The strings MUST NOT be deleted !!
382 */
383tList<const char>* LoadClassDescription::searchClassWithShort(const char* classNameBegin)
384{
385  unsigned int searchLength = strlen(classNameBegin);
386  tList<const char>* retVal = new tList<const char>;
387
388  tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
389  LoadClassDescription* enumClassDesc = iterator->firstElement();
390  while (enumClassDesc)
391  {
392    if (strlen(enumClassDesc->className)>searchLength+1 &&
393        !strncasecmp(enumClassDesc->className, classNameBegin, searchLength))
394    {
395      retVal->add(enumClassDesc->className);
396    }
397    enumClassDesc = iterator->nextElement();
398  }
399  delete iterator;
400
401  return retVal;
402}
403
404// const LoadParamDescription* LoadParamDescription::getClass(const char* className)
405// {
406//   tIterator<LoadClassDescription>* iterator = LoadClassDescription::classList->getIterator();
407//   LoadClassDescription* enumClassDesc = iterator->firstElement();
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
422/**
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
426*/
427const char* grabParameter(const TiXmlElement* root, const char* parameterName)
428{
429  const TiXmlElement* element;
430  const TiXmlNode* node;
431
432  if (root == NULL)
433    return NULL;
434  assert( parameterName != NULL);
435
436  element = root->FirstChildElement( parameterName);
437  if( element == NULL) return NULL;
438
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.