/*! * @file shell_command.h * Definition of a on-screen-shell * * @todo also take Static functions */ #ifndef _SHELL_COMMAND_H #define _SHELL_COMMAND_H #include "base_object.h" #include "helper_functions.h" #include "substring.h" #include "functor_list.h" #include #define SHELL_COMMAND_MAX_SIZE //!< The maximum size of a Shell Command // FORWARD DECLARATION template class tList; /** * an easy to use Macro to create a Command * @param command the name of the command (without "" around the string) * @param class the name of the class to apply this command to (without the "" around the string) * @param function the function to call * * MEANING: * ShellCommandBase* someUniqueVarName = * ShellCommand::registerCommand("commandNameInShell", "ClassName", &ClassName::FunctionToCall); * * In the Shell you would call this Command using: * $ ClassName [ObjectName] commandNameInShell [parameters] */ #define SHELL_COMMAND(command, class, function) \ ShellCommandBase* shell_command_##class##_##command = ShellCommand::registerCommand(#command, #class, &class::function) //! an enumerator for the definition of the Type. typedef enum { ShellCommand_Objective = 1, ShellCommand_Static = 2, } ShellCommand_Type; //////////////// // BASE CLASS // //////////////// class ShellCommandBase; class ShellCommandAlias; //! A class to hold all Classes that have (once) registered Commands. class ShellCommandClass : public BaseObject { friend class ShellCommandBase; public: /** @returns the CommandClassList */ static const tList* getCommandClassList() { return ShellCommandClass::commandClassList; }; static bool getCommandListOfClass(const char* className, tList* stringList); static bool getCommandListOfAlias(tList* aliasList); static ShellCommandClass* getCommandClass(const char* className); static void unregisterAllCommands(); static void help (const char* className); private: ShellCommandClass(const char* className); ~ShellCommandClass(); static const ShellCommandClass* isRegistered(const char* className); static void initCommandClassList(); private: const char* className; //!< The Name of the Class. This should match the ClassName of the Commands Class. long classID; //!< The classID of this Class tList* commandList; //!< A list of Commands from this Class static tList* commandClassList; //!< A list of Classes static tList* aliasList; //!< An Alias to A Command. (only for classes with one Instance) }; //! a baseClass for all possible ShellCommands class ShellCommandBase : public BaseObject { friend class ShellCommandClass; public: static bool execute (const char* executionString); ShellCommandBase* describe(const char* description); ShellCommandBase* setAlias(const char* alias); ShellCommandBase* defaultValues(unsigned int count, ...); /** @returns the CommandList of the Shell */ static void unregisterCommand(const char* commandName, const char* className); static void debug(); protected: ShellCommandBase(const char* commandName, const char* className, unsigned int paramCount, ...); ~ShellCommandBase(); /** @returns the Type of this Function (either static or objective) */ inline ShellCommand_Type getType() { return this->functorType; }; static bool isRegistered(const char* commandName, const char* className, unsigned int paramCount, ...); static const char* paramToString(long parameter); void debugDyn(); private: /** executes a Command @param object the object to apply this to @param parameters the parameters the command takes */ virtual void executeCommand (BaseObject* object, const char* parameters) = 0; protected: ShellCommand_Type functorType; //!< The type of Function we've got (either static or objective). void* functionPointer; //!< The pointeer to the function of the Class (or static pointer if ClassID == CL_NULL ) unsigned int paramCount; //!< the count of parameters. unsigned int* parameters; //!< Parameters the function of this Command takes. char* defaultStrings[FUNCTOR_MAX_ARGUMENTS];//!< A list of default Strings stored. int defaultInts[FUNCTOR_MAX_ARGUMENTS]; //!< A list of default Ints stored. float defaultFloats[FUNCTOR_MAX_ARGUMENTS]; //!< A list of default Floats stored. bool defaultBools[FUNCTOR_MAX_ARGUMENTS]; //!< A list of default Bools stored. private: ShellCommandClass* shellClass; //!< A Pointer to the Shell-Class this Command belongs to. ShellCommandAlias* alias; //!< An Alias for the Class. const char* description; //!< A description for this commnand. (initially NULL). Assigned with (create)->describe("blablabla"); }; /////////////////////////////////////////////////// /////////////////////////////////////////////////// ///////////////////////////////// // MACRO DEFINITION EXTENSIONS // ///////////////////////////////// //! where to chek for default BOOL values #define l_BOOL_DEFGRAB(i) this->defaultBools[i] //! where to chek for default INT values #define l_INT_DEFGRAB(i) this->defaultInts[i] //! where to chek for default UINT values #define l_UINT_DEFGRAB(i) (unsigned int)this->defaultInts[i] //! where to chek for default LONG values #define l_LONG_DEFGRAB(i) (long)this->defaultInts[i] //! where to chek for default FLOAT values #define l_FLOAT_DEFGRAB(i) this->defaultFloats[i] //! where to chek for default STRING values #define l_STRING_DEFGRAB(i) this->defaultStrings[i] ////////////////////////// // COMMAND REGISTRATION // ////////////////////////// // SHELLCOMMAND can be redefined as ShellCommand or ShellCommandStatic // SHELLCOMMANDEXECUTER can be redefined too. // SHELLCOMMANDINCLASS // SHELLCOMMANDTYPE //! registers a command without any parameters #define ShellCommandRegister0() \ static SHELLCOMMAND* registerCommand(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)()) \ { \ if (isRegistered(commandName, className, 0)== true) \ return NULL; \ return new SHELLCOMMAND(commandName, className, function); \ } //! registers a command with 1 parameter #define ShellCommandRegister1(t1) \ static SHELLCOMMAND* registerCommand(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE), t1##_TYPE d1 = t1##_DEFAULT) \ { \ if (isRegistered(commandName, className, 1, t1##_PARAM)== true) \ return NULL; \ return new SHELLCOMMAND(commandName, className, function, d1); \ } //! registers a command with 2 parameters #define ShellCommandRegister2(t1,t2) \ static SHELLCOMMAND* registerCommand(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE), t1##_TYPE d1 = t1##_DEFAULT, t2##_TYPE d2 = t2##_DEFAULT) \ { \ if (isRegistered(commandName, className, 2, t1##_PARAM, t2##_PARAM)== true) \ return NULL; \ return new SHELLCOMMAND(commandName, className, function, d1, d2); \ } //! registers a command with 3 parameters #define ShellCommandRegister3(t1,t2,t3) \ static SHELLCOMMAND* registerCommand(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE, t3##_TYPE), t1##_TYPE d1 = t1##_DEFAULT, t2##_TYPE d2 = t2##_DEFAULT, t3##_TYPE d3 = t3##_DEFAULT) \ { \ if (isRegistered(commandName, className, 3, t1##_PARAM, t2##_PARAM, t3##_PARAM)== true) \ return NULL; \ return new SHELLCOMMAND(commandName, className, function, d1, d2, d3); \ } //! registers a command with 4 parameters #define ShellCommandRegister4(t1,t2,t3,t4) \ static SHELLCOMMAND* registerCommand(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE, t3##_TYPE, t4##_TYPE), t1##_TYPE d1 = t1##_DEFAULT, t2##_TYPE d2 = t2##_DEFAULT, t3##_TYPE d3 = t3##_DEFAULT, t4##_TYPE d4 = t4##_DEFAULT) \ { \ if (isRegistered(commandName, className, 4, t1##_PARAM, t2##_PARAM, t3##_PARAM, t4##_PARAM)== true) \ return NULL; \ return new SHELLCOMMAND(commandName, className, function, d1, d2, d3, d4); \ } //! registers a command with 5 parameters #define ShellCommandRegister5(t1,t2,t3,t4,t5) \ static SHELLCOMMAND* registerCommand(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE, t3##_TYPE, t4##_TYPE, t5##_TYPE), t1##_TYPE d1 = t1##_DEFAULT, t2##_TYPE d2 = t2##_DEFAULT, t3##_TYPE d3 = t3##_DEFAULT, t4##_TYPE d4 = t4##_DEFAULT, t5##_TYPE d5 = t5##_DEFAULT) \ { \ if (isRegistered(commandName, className, 5, t1##_PARAM, t2##_PARAM, t3##_PARAM, t4##_PARAM, t5##_PARAM)== true) \ return NULL; \ return new ShellCommand(commandName, className, function, d1, d2, d3, d4, d5); \ } ////////////////// // CONSTRUCTORS // ///////////////// //! creates a command that takes no parameters #define ShellCommandConstructor0() \ void SHELLCOMMANDINCLASS(*functionPointer_0)(); \ SHELLCOMMAND(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)()) \ : ShellCommandBase(commandName, className, 0) \ { \ this->functorType = SHELLCOMMANDTYPE; \ this->functionPointer_0 = function; \ } //! creates a command that takes one parameter #define ShellCommandConstructor1(t1) \ void SHELLCOMMANDINCLASS(*functionPointer_1_##t1)(t1##_TYPE); \ SHELLCOMMAND(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE), t1##_TYPE d1) \ : ShellCommandBase(commandName, className, 1, t1##_PARAM, d1) \ { \ this->functorType = SHELLCOMMANDTYPE; \ this->functionPointer_1_##t1 = function; \ } //! creates a command that takes two parameters #define ShellCommandConstructor2(t1,t2) \ void SHELLCOMMANDINCLASS(*functionPointer_2_##t1##_##t2)(t1##_TYPE, t2##_TYPE); \ SHELLCOMMAND(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE), t1##_TYPE d1, t2##_TYPE d2) \ : ShellCommandBase(commandName, className, 2, t1##_PARAM, d1, t2##_PARAM, d2) \ { \ this->functorType = SHELLCOMMANDTYPE; \ this->functionPointer_2_##t1##_##t2 = function; \ } //! creates a command that takes three parameter #define ShellCommandConstructor3(t1,t2,t3) \ void SHELLCOMMANDINCLASS(*functionPointer_3_##t1##_##t2##_##t3)(t1##_TYPE, t2##_TYPE, t3##_TYPE); \ SHELLCOMMAND(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE, t3##_TYPE), t1##_TYPE d1, t2##_TYPE d2, t3##_TYPE d3) \ : ShellCommandBase(commandName, className, 3, t1##_PARAM, d1, t2##_PARAM, d2, t3##_PARAM, d3) \ { \ this->functorType = SHELLCOMMANDTYPE; \ this->functionPointer_3_##t1##_##t2##_##t3 = function; \ } //! creates a command that takes four parameter #define ShellCommandConstructor4(t1,t2,t3,t4) \ void SHELLCOMMANDINCLASS(*functionPointer_4_##t1##_##t2##_##t3##_##t4)(t1##_TYPE, t2##_TYPE, t3##_TYPE, t4##_TYPE); \ SHELLCOMMAND(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE, t3##_TYPE, t4##_TYPE), t1##_TYPE d1, t2##_TYPE d2, t3##_TYPE d3, t4##_TYPE d4) \ : ShellCommandBase(commandName, className, 4, t1##_PARAM, d1, t2##_PARAM, d2, t3##_PARAM, d3, t4##_PARAM, d4) \ { \ this->functorType = SHELLCOMMANDTYPE; \ this->functionPointer_4_##t1##_##t2##_##t3##_##t4 = function; \ } //! creates a command that takes five parameter #define ShellCommandConstructor5(t1,t2,t3,t4,t5) \ void SHELLCOMMANDINCLASS(*functionPointer_5_##t1##_##t2##_##t3##_##t4##_##t5)(t1##_TYPE, t2##_TYPE, t3##_TYPE, t4##_TYPE, t5##_TYPE); \ SHELLCOMMAND(const char* commandName, const char* className, void SHELLCOMMANDINCLASS(*function)(t1##_TYPE, t2##_TYPE, t3##_TYPE, t4##_TYPE, t5##_TYPE), t1##_TYPE d1, t2##_TYPE d2, t3##_TYPE d3, t4##_TYPE d4, t5##_TYPE d5) \ : ShellCommandBase(commandName, className, 5, t1##_PARAM, d1, t2##_PARAM, d2, t3##_PARAM, d3, t4##_PARAM, d4, t5##_PARAM, d5) \ { \ this->functorType = SHELLCOMMANDTYPE; \ this->functionPointer_5_##t1##_##t2##_##t3##_##t4##_##t5 = function; \ } /////////////// // EXECUTION // /////////////// //! execute-macro for functions with no parameters #define ShellCommandExecute0() \ if (this->paramCount == 0) \ SHELLCOMMANDEXECUTER(_0)() //! execute-macro for functions with one parameter #define ShellCommandExecute1(t1) \ else if (this->paramCount == 1 && this->parameters[0] == t1##_PARAM) \ SHELLCOMMANDEXECUTER(_1_##t1)(t1##_FUNC(parameters, t1##_DEFGRAB(0))) //! execute-macro for functions with two parameters #define ShellCommandExecute2(t1,t2) \ else if (this->paramCount == 2 && this->parameters[0] == t1##_PARAM && this->parameters[1] == t2##_PARAM) \ SHELLCOMMANDEXECUTER(_2_##t1##_##t2)(t1##_FUNC(sub.getString(0), t1##_DEFGRAB(0)), t2##_FUNC(sub.getString(1), t2##_DEFGRAB(1))) //! execute-macro for functions with three parameters #define ShellCommandExecute3(t1,t2,t3) \ else if (this->paramCount == 3 && this->parameters[0] == t1##_PARAM && this->parameters[1] == t2##_PARAM && this->parameters[2] == t3##_PARAM) \ SHELLCOMMANDEXECUTER(_3_##t1##_##t2##_##t3)(t1##_FUNC(sub.getString(0), t1##_DEFGRAB(0)), t2##_FUNC(sub.getString(1), t2##_DEFGRAB(1)), t3##_FUNC(sub.getString(2), t3##_DEFGRAB(2))) //! execute-macro for functions with four parameters #define ShellCommandExecute4(t1,t2,t3,t4) \ else if (this->paramCount == 4 && this->parameters[0] == t1##_PARAM && this->parameters[1] == t2##_PARAM && this->parameters[2] == t3##_PARAM && this->parameters[3] == t4##_PARAM) \ SHELLCOMMANDEXECUTER(_4_##t1##_##t2##_##t3##_##t4)(t1##_FUNC(sub.getString(0), t1##_DEFGRAB(0)), t2##_FUNC(sub.getString(1), t2##_DEFGRAB(1)), t3##_FUNC(sub.getString(2), t3##_DEFGRAB(2)), t4##_FUNC(sub.getString(3), t4##_DEFGRAB(3))) //! execute-macro for functions with five parameters #define ShellCommandExecute5(t1,t2,t3,t4,t5) \ else if (this->paramCount == 5 && this->parameters[0] == t1##_PARAM && this->parameters[1] == t2##_PARAM && this->parameters[2] == t3##_PARAM && this->parameters[3] == t4##_PARAM && this->parameters[4] == t5##_PARAM) \ SHELLCOMMANDEXECUTER(_5_##t1##_##t2##_##t3##_##t4##_##t5)(t1##_FUNC(sub.getString(0), t1##_DEFGRAB(0)), t2##_FUNC(sub.getString(1), t2##_DEFGRAB(1)), t3##_FUNC(sub.getString(2), t3##_DEFGRAB(2)), t4##_FUNC(sub.getString(3), t4##_DEFGRAB(3)), t5##_FUNC(sub.getString(4), t5##_DEFGRAB(4))) //! keeps information about a ShellCommand template class ShellCommand : public ShellCommandBase { public: #ifdef FUNCTOR_LIST #undef FUNCTOR_LIST #endif #ifdef SHELLCOMMAND #undef SHELLCOMMAND #endif #define SHELLCOMMAND ShellCommand #ifdef SHELLCOMMANDEXECUTER #undef SHELLCOMMANDEXECUTER #endif #define SHELLCOMMANDEXECUTER(nameExt) (dynamic_cast(object)->*functionPointer##nameExt) #ifdef SHELLCOMMANDINCLASS #undef SHELLCOMMANDINCLASS #endif #define SHELLCOMMANDINCLASS(FUNCTION) (T::FUNCTION) #ifdef SHELLCOMMANDTYPE #undef SHELLCOMMANDTYPE #endif #define SHELLCOMMANDTYPE ShellCommand_Objective //! FUNCTOR_LIST is the List of command-registerers #define FUNCTOR_LIST(x) ShellCommandRegister ## x #include "functor_list.h" #undef FUNCTOR_LIST private: //! FUNCTOR_LIST is the List of CommandConstructors #define FUNCTOR_LIST(x) ShellCommandConstructor ## x #include "functor_list.h" #undef FUNCTOR_LIST virtual void executeCommand (BaseObject* object, const char* parameters) { SubString sub(parameters, true); //! FUNCTOR_LIST is the List of Executive Functions #define FUNCTOR_LIST(x) ShellCommandExecute ## x #include "functor_list.h" #undef FUNCTOR_LIST } }; //! keeps information about a ShellCommand, that points to a Static Function template class ShellCommandStatic : public ShellCommandBase { public: #ifdef FUNCTOR_LIST #undef FUNCTOR_LIST #endif #ifdef SHELLCOMMAND #undef SHELLCOMMAND #endif #define SHELLCOMMAND ShellCommandStatic #ifdef SHELLCOMMANDEXECUTER #undef SHELLCOMMANDEXECUTER #endif #define SHELLCOMMANDEXECUTER(nameExt) functionPointer##nameExt #ifdef SHELLCOMMANDINCLASS #undef SHELLCOMMANDINCLASS #endif #define SHELLCOMMANDINCLASS(FUNCTION) (FUNCTION) #ifdef SHELLCOMMANDTYPE #undef SHELLCOMMANDTYPE #endif #define SHELLCOMMANDTYPE ShellCommand_Static //! FUNCTOR_LIST is the List of command-registerers #define FUNCTOR_LIST(x) ShellCommandRegister ## x #include "functor_list.h" #undef FUNCTOR_LIST private: //! FUNCTOR_LIST is the List of CommandConstructors #define FUNCTOR_LIST(x) ShellCommandConstructor ## x #include "functor_list.h" #undef FUNCTOR_LIST virtual void executeCommand (BaseObject* object, const char* parameters) { SubString sub(parameters, true); //! FUNCTOR_LIST is the List of Executive Functions #define FUNCTOR_LIST(x) ShellCommandExecute ## x #include "functor_list.h" #undef FUNCTOR_LIST } }; //! A Class, that handles aliases. class ShellCommandAlias { friend class ShellCommandBase; public: /** @returns the Name of the Alias. */ const char* getName() const { return this->aliasName; }; /** @returns the Command, this Alias is asociated with */ ShellCommandBase* getCommand() const { return this->command; }; private: /** @param aliasName the name of the Alias @param command the Command, to associate this alias with */ ShellCommandAlias(const char* aliasName, ShellCommandBase* command) { this->aliasName = aliasName; this->command = command; }; private: const char* aliasName; //!< the name of the Alias ShellCommandBase* command; //!< a pointer to the command, this alias executes. }; #endif /* _SHELL_COMMAND_H */