Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell_command.cc @ 5189

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

orxonox/trunk: minor function, to retrieve a List of Commands from a ClassList

File size: 14.0 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//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
17
18#include "shell_command.h"
19
20#include "list.h"
21#include "debug.h"
22#include "class_list.h"
23
24#include "key_names.h"
25#include <stdarg.h>
26#include <stdio.h>
27#include <string.h>
28
29using namespace std;
30
31/**
32 * creates a new ShellCommandClass
33 * @param className the Name of the command-class to create
34 */
35ShellCommandClass::ShellCommandClass(const char* className)
36{
37  this->setClassID(CL_SHELL_COMMAND_CLASS, "ShellCommandClass");
38  this->setName(className);
39
40  this->className = className;
41  this->classID = CL_NULL;
42  this->commandList = new tList<ShellCommandBase>;
43
44  ShellCommandClass::commandClassList->add(this);
45}
46
47/**
48 * destructs the shellCommandClass again
49 */
50ShellCommandClass::~ShellCommandClass()
51{
52  tIterator<ShellCommandBase>* iterator = this->commandList->getIterator();
53  ShellCommandBase* elem = iterator->firstElement();
54  while(elem != NULL)
55  {
56    delete elem;
57    elem = iterator->nextElement();
58  }
59  delete iterator;
60  delete this->commandList;
61}
62
63tList<const char>* ShellCommandClass::getCommandListOfClass(const char* className)
64{
65  tList<const char>* retList;
66  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
67  ShellCommandClass* elem = iterator->firstElement();
68  while(elem != NULL)
69  {
70    if (!strcmp (elem->getName(), className))
71    {
72      tIterator<ShellCommandBase>* itFkt = elem->commandList->getIterator();
73      ShellCommandBase* command = itFkt->firstElement();
74      while (command != NULL)
75      {
76        retList->add(command->getName());
77        command = itFkt->nextElement();
78      }
79      delete itFkt;
80    }
81
82    elem = iterator->nextElement();
83  }
84  delete iterator;
85  return retList;
86}
87
88/**
89 * unregisters all Commands that exist
90 */
91void ShellCommandClass::unregisterAllCommands()
92{
93  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
94  ShellCommandClass* elem = iterator->firstElement();
95  while(elem != NULL)
96  {
97    delete elem;
98
99    elem = iterator->nextElement();
100  }
101  delete iterator;
102
103  delete ShellCommandClass::commandClassList;
104  ShellCommandClass::commandClassList = NULL;
105}
106
107const ShellCommandClass* ShellCommandClass::isRegistered(const char* className)
108{
109  if (ShellCommandClass::commandClassList == NULL)
110    initCommandClassList();
111
112  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
113  ShellCommandClass* elem = iterator->firstElement();
114  while(elem != NULL)
115  {
116    if (!strcmp(className, elem->className))
117    {
118      if (elem->classID == CL_NULL)
119        elem->classID = ClassList::StringToID(className);
120
121      delete iterator;
122      return elem;
123    }
124    elem = iterator->nextElement();
125  }
126  delete iterator;
127  return NULL;
128}
129
130/**
131 * searches for a CommandClass
132 * @param className the name of the CommandClass
133 * @returns the CommandClass if found, or a new CommandClass if not
134 */
135ShellCommandClass* ShellCommandClass::getCommandClass(const char* className)
136{
137  if (ShellCommandClass::commandClassList == NULL)
138    initCommandClassList();
139
140  tIterator<ShellCommandClass>* iterator = ShellCommandClass::commandClassList->getIterator();
141  ShellCommandClass* elem = iterator->firstElement();
142  while(elem != NULL)
143  {
144    if (!strcmp(className, elem->className))
145    {
146      delete iterator;
147      return elem;
148    }
149    elem = iterator->nextElement();
150  }
151  delete iterator;
152  return new ShellCommandClass(className);
153}
154
155/**
156 * initializes the CommandList (if it is NULL)
157 */
158void ShellCommandClass::initCommandClassList()
159{
160  if (ShellCommandClass::commandClassList == NULL)
161  {
162    ShellCommandClass::commandClassList = new tList<ShellCommandClass>;
163    ShellCommand<ShellCommandBase>::registerCommand("debug", "ShellCommand", &ShellCommandBase::debugDyn);
164  }
165}
166
167tList<ShellCommandClass>* ShellCommandClass::commandClassList = NULL;
168
169/**
170 * constructs and registers a new Command
171 * @param commandName the name of the Command
172 * @param className the name of the class to apply this command to
173 * @param paramCount the count of parameters this command takes
174 * @return self
175 */
176ShellCommandBase::ShellCommandBase(const char* commandName, const char* className, unsigned int paramCount, ...)
177{
178  this->setClassID(CL_SHELL_COMMAND, "ShellCommand");
179  this->setName(commandName);
180  this->description = NULL;
181
182//  this->classID = classID;
183  ShellCommandClass::getCommandClass(className)->commandList->add(this); //ClassList::IDToString(classID);
184
185  // handling parameters, and storing them:
186  if (paramCount > FUNCTOR_MAX_ARGUMENTS)
187    paramCount = FUNCTOR_MAX_ARGUMENTS;
188  this->paramCount = paramCount;
189  this->parameters = new unsigned int[paramCount];
190
191  va_list parameterList;
192  va_start(parameterList, paramCount);
193
194  for (unsigned int i = 0; i < paramCount; i++)
195  {
196    this->parameters[i] = va_arg(parameterList, int);
197
198    switch (this->parameters[i])
199    {
200      case ParameterBool:
201        this->defaultBools[i] = va_arg(parameterList, int);
202        break;
203      case ParameterChar:
204        this->defaultStrings[i] = new char[2];
205        sprintf(this->defaultStrings[0], "%c",  va_arg(parameterList, int));
206        break;
207      case ParameterString:
208        this->defaultStrings[i] = va_arg(parameterList, char*);
209        break;
210      case ParameterInt:
211        this->defaultInts[i] = va_arg(parameterList, int);
212        break;
213      case ParameterUInt:
214        this->defaultInts[i] = va_arg(parameterList, unsigned int);
215        break;
216      case ParameterFloat:
217        this->defaultFloats[i] = va_arg(parameterList, double);
218        break;
219      case ParameterLong:
220        this->defaultInts[i] = va_arg(parameterList, long);
221        break;
222      default:
223        break;
224    }
225  }
226}
227
228/**
229 * deconstructs a ShellCommand
230 * @return
231 */
232ShellCommandBase::~ShellCommandBase()
233{
234  delete[] this->parameters;
235}
236
237/**
238 * unregister an existing commandName
239 * @param className the name of the Class the command belongs to.
240 * @param commandName the name of the command itself
241 *
242 * @todo implement
243 */
244void ShellCommandBase::unregisterCommand(const char* commandName, const char* className)
245{
246  if (ShellCommandClass::commandClassList == NULL)
247    ShellCommandClass::initCommandClassList();
248
249 const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
250
251 if (checkClass != NULL)
252  {
253    tIterator<ShellCommandBase>* iterator = checkClass->commandList->getIterator();
254    ShellCommandBase* elem = iterator->firstElement();
255    while(elem != NULL)
256    {
257      if (!strcmp(commandName, elem->getName()))
258      {
259        checkClass->commandList->remove(elem);
260        delete elem;
261        break;
262      }
263      elem = iterator->nextElement();
264    }
265    delete iterator;
266
267    if (checkClass->commandList->getSize() == 0)
268    {
269      ShellCommandClass::commandClassList->remove(checkClass);
270      delete checkClass;
271    }
272  }
273}
274
275/**
276 * checks if a command has already been registered.
277 * @param commandName the name of the Command
278 * @param className the name of the Class the command should apply to.
279 * @param paramCount how many arguments the Command takes
280 * @returns true, if the command is registered/false otherwise
281 *
282 * This is used internally, to see, if we have multiple command subscriptions.
283 * This is checked in the registerCommand-function.
284 */
285bool ShellCommandBase::isRegistered(const char* commandName, const char* className, unsigned int paramCount, ...)
286{
287  if (ShellCommandClass::commandClassList == NULL)
288  {
289    ShellCommandClass::initCommandClassList();
290    return false;
291  }
292
293  const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
294  if (checkClass != NULL)
295  {
296    tIterator<ShellCommandBase>* iterator = checkClass->commandList->getIterator();
297    ShellCommandBase* elem = iterator->firstElement();
298    while(elem != NULL)
299   {
300     if (!strcmp(commandName, elem->getName()))
301     {
302       PRINTF(2)("Command already registered\n");
303       delete iterator;
304       return true;
305      }
306     elem = iterator->nextElement();
307   }
308   delete iterator;
309   return false;
310  }
311  else
312    return false;
313}
314
315
316/**
317 * executes commands
318 * @param executionString the string containing the following input
319 * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
320 * @return true on success, false otherwise.
321 */
322bool ShellCommandBase::execute(const char* executionString)
323{
324//   if (ShellCommandBase::commandList == NULL)
325//     return false;
326//
327//   tIterator<ShellCommandBase>* iterator = ShellCommandBase::commandList->getIterator();
328//   ShellCommandBase* elem = iterator->firstElement();
329//   while(elem != NULL)
330//   {
331//     printf("%s::%s\n", elem->className, elem->getName());
332//     if (!strncasecmp (executionString, elem->className, strlen(elem->className)) &&
333//          (*(executionString+strlen(elem->className)) == ' ' ||
334//           *(executionString+strlen(elem->className)) == ':' ))
335//     {
336//       const char* commandBegin = executionString + strlen(elem->className);
337//
338//       PRINTF(4)("Class %s matches\n", elem->className);
339//       BaseObject* objectPointer = NULL;
340//       if (ClassList::StringToID(elem->className) & CL_MASK_SINGLETON == CL_MASK_SINGLETON)
341//       {
342//         while(*commandBegin == ' ')
343//           commandBegin++;
344//         if (strncmp (commandBegin, elem->getName(), strlen(elem->getName())) ||
345//             *(commandBegin + strlen(elem->getName())) != ' ' &&
346//             *(commandBegin + strlen(elem->getName())) != '\0')
347//         {
348//           elem = iterator->nextElement();
349//           continue;
350//         }
351//         PRINTF(4)("Command %s matches\n", elem->getName());
352//         // getting singleton-reference
353//         tList<BaseObject>* list =  ClassList::getList(elem->className);
354//         if (list != NULL)
355//           objectPointer = list->firstElement();
356//       }
357//       else
358//       {
359//         // checking for the Object
360//         while(*commandBegin == ' ')
361//           commandBegin++;
362//         tList<BaseObject>* list = ClassList::getList(elem->className);
363//         if (list == NULL)
364//           break;
365//         tIterator<BaseObject>* iterBO = list->getIterator();
366//         BaseObject* enumBO = iterBO->firstElement();
367//         while(enumBO != NULL)
368//         {
369//           if(!strncmp(commandBegin, enumBO->getName(), strlen(enumBO->getName())))
370//           {
371//             PRINTF(4)("Object %s matches\n", enumBO->getName());
372//             objectPointer = enumBO;
373//             break;
374//           }
375//           enumBO = iterBO->nextElement();
376//         }
377//         delete iterBO;
378//
379//         // break on no object Found. We cannot operate on Classes, but on Objects
380//         if (objectPointer == NULL)
381//           break;
382//         commandBegin = commandBegin + strlen(objectPointer->getName());
383//         while(*commandBegin == ' ')
384//           commandBegin++;
385//         // checking for the requested function.
386//         if (strncmp (commandBegin, elem->getName(), strlen(elem->getName())))
387//         {
388//           elem = iterator->nextElement();
389//           continue;
390//         }
391//         PRINTF(4)("Function '%s' found\n", commandBegin);
392//       }
393//       const char* paramBegin = strchr(commandBegin, ' ');
394//       if (paramBegin == NULL)
395//         paramBegin = commandBegin + strlen(elem->getName());
396//       while (*paramBegin == ' ')
397//         paramBegin++;
398//
399//       PRINTF(3)("Parameters to Pass: %s\n", paramBegin);
400//       if (objectPointer != NULL && paramBegin != NULL)
401//       {
402//         elem->executeCommand(objectPointer, paramBegin);
403//         delete iterator;
404//         return true;
405//       }
406//     }
407//     elem = iterator->nextElement();
408//   }
409//   delete iterator;
410//   return true;
411}
412
413/**
414 * lets a command be described
415 * @param description the description of the Given command
416 */
417ShellCommandBase* ShellCommandBase::describe(const char* description)
418{
419  if (this == NULL)
420    return NULL;
421 else
422 {
423   this->description = description;
424   return this;
425 }
426}
427
428/**
429 * see ShellCommandBase::debug()
430 */
431void ShellCommandBase::debugDyn()
432{
433  this->debug();
434}
435
436/**
437 * prints out nice information about the Shells Commands
438 */
439void ShellCommandBase::debug()
440{
441  if (ShellCommandClass::commandClassList == NULL)
442  {
443    PRINT(0)("No Command registered.\n");
444    return;
445  }
446
447  tIterator<ShellCommandClass>* iteratorCL = ShellCommandClass::commandClassList->getIterator();
448  ShellCommandClass* elemCL = iteratorCL->firstElement();
449  while(elemCL != NULL)
450  {
451    PRINT(0)("Class:'%s' registered %d commands: \n", elemCL->className, elemCL->commandList->getSize());
452    tIterator<ShellCommandBase>* iterator = elemCL->commandList->getIterator();
453    const ShellCommandBase* elem = iterator->firstElement();
454    while(elem != NULL)
455    {
456      PRINT(0)("  command:'%s' : params:%d: ", elem->getName(), elem->paramCount);
457      for (unsigned int i = 0; i< elem->paramCount; i++)
458       printf("%s ", ShellCommandBase::paramToString(elem->parameters[i]));
459      if (elem->description != NULL)
460       printf("- %s", elem->description);
461      printf("\n");
462
463      elem = iterator->nextElement();
464    }
465    delete iterator;
466    elemCL = iteratorCL->nextElement();
467  }
468  delete iteratorCL;
469}
470
471/**
472 * converts a Parameter to a String
473 * @param parameter the Parameter we have.
474 * @returns the Name of the Parameter at Hand
475 */
476const char* ShellCommandBase::paramToString(long parameter)
477{
478  switch (parameter)
479  {
480    case ParameterBool:
481      return "BOOL";
482      break;
483    case ParameterChar:
484      return "CHAR";
485      break;
486    case ParameterString:
487      return "STRING";
488      break;
489    case ParameterInt:
490      return "INT";
491      break;
492    case ParameterUInt:
493      return "UINT";
494      break;
495    case ParameterFloat:
496      return "FLOAT";
497      break;
498    case ParameterLong:
499      return "LONG";
500      break;
501    default:
502      return "NULL";
503      break;
504  }
505}
Note: See TracBrowser for help on using the repository browser.