[Orxonox-commit 2647] r7352 - in code/branches/doc/src/libraries: core/command core/input util
landauf at orxonox.net
landauf at orxonox.net
Sat Sep 4 23:33:02 CEST 2010
Author: landauf
Date: 2010-09-04 23:33:02 +0200 (Sat, 04 Sep 2010)
New Revision: 7352
Modified:
code/branches/doc/src/libraries/core/command/ArgumentCompleter.h
code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.cc
code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.h
code/branches/doc/src/libraries/core/command/ArgumentCompletionListElement.h
code/branches/doc/src/libraries/core/command/CommandEvaluation.cc
code/branches/doc/src/libraries/core/command/CommandEvaluation.h
code/branches/doc/src/libraries/core/command/CommandExecutor.cc
code/branches/doc/src/libraries/core/command/CommandExecutor.h
code/branches/doc/src/libraries/core/command/ConsoleCommand.cc
code/branches/doc/src/libraries/core/command/ConsoleCommand.h
code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.cc
code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.h
code/branches/doc/src/libraries/core/command/Executor.cc
code/branches/doc/src/libraries/core/command/Executor.h
code/branches/doc/src/libraries/core/command/ExecutorPtr.h
code/branches/doc/src/libraries/core/command/Functor.h
code/branches/doc/src/libraries/core/command/FunctorPtr.h
code/branches/doc/src/libraries/core/input/Button.cc
code/branches/doc/src/libraries/core/input/InputCommands.cc
code/branches/doc/src/libraries/util/Debug.h
code/branches/doc/src/libraries/util/Math.h
code/branches/doc/src/libraries/util/MultiType.h
code/branches/doc/src/libraries/util/MultiTypeValue.h
code/branches/doc/src/libraries/util/Scope.h
code/branches/doc/src/libraries/util/ScopedSingletonManager.h
code/branches/doc/src/libraries/util/SharedPtr.h
code/branches/doc/src/libraries/util/Singleton.h
code/branches/doc/src/libraries/util/SmallObjectAllocator.h
code/branches/doc/src/libraries/util/StringUtils.h
code/branches/doc/src/libraries/util/SubString.cc
code/branches/doc/src/libraries/util/SubString.h
code/branches/doc/src/libraries/util/VA_NARGS.h
Log:
added documentation
also some small naming and readability changes in the code.
Modified: code/branches/doc/src/libraries/core/command/ArgumentCompleter.h
===================================================================
--- code/branches/doc/src/libraries/core/command/ArgumentCompleter.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ArgumentCompleter.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,29 @@
*
*/
+/**
+ @defgroup ArgumentCompletion Argument completion
+ @ingroup Command
+*/
+
+/**
+ @file
+ @ingroup Command ArgumentCompletion
+ @brief Definition of the orxonox::ArgumentCompleter class that is used to execute @ref ArgumentCompletionFunctions.h "argument completion functions".
+
+ An ArgumentCompleter can be assigned to an orxonox::ConsoleCommand using
+ @ref orxonox::ConsoleCommand::argumentCompleter "argumentCompleter()".
+ The ArgumentCompleter calls an argument completion function that is defined
+ in ArgumentCompletionFunctions.h. This can be used to list possible arguments
+ for console commands and to allow auto-completion.
+
+ Instances of ArgumentCompleter are usually not created manually but rather
+ by the macros defined in ArgumentCompletionFunctions.h. There you'll also
+ find some examples.
+
+ @see See the @ref ArgumentCompletionExample "examples".
+*/
+
#ifndef _ArgumentCompleter_H__
#define _ArgumentCompleter_H__
@@ -34,16 +57,30 @@
namespace orxonox
{
+ /**
+ @brief This class executes an argument completion function and returns a list of the possible arguments.
+
+ ArgumentCompleter is used to wrap argument completion functions as defined
+ in ArgumentCompletionFunctions.h and can be assigned to a ConsoleCommand to
+ create a list of possible arguments.
+
+ @see See ArgumentCompleter.h for more information.
+ @see See @ref ArgumentCompletionExample "ArgumentCompletionFunctions.h" for an example.
+ */
class _CoreExport ArgumentCompleter
{
public:
- ArgumentCompleter(ArgumentCompletionList (*function) (void), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(0), function_0_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(1), function_1_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(2), function_2_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(3), function_3_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(4), function_4_(function) {}
- ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(5), function_5_(function) {}
+ ArgumentCompleter(ArgumentCompletionList (*function) (void), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(0), function_0_(function) {} ///< Constructor, assigns a function-pointer with no arguments.
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(1), function_1_(function) {} ///< Constructor, assigns a function-pointer with one argument.
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(2), function_2_(function) {} ///< Constructor, assigns a function-pointer with two arguments.
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(3), function_3_(function) {} ///< Constructor, assigns a function-pointer with three arguments.
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(4), function_4_(function) {} ///< Constructor, assigns a function-pointer with four arguments.
+ ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(5), function_5_(function) {} ///< Constructor, assigns a function-pointer with five arguments.
+ /**
+ @brief Calls the argument completion function with a maximum of five parameters.
+ @return Returns the list of possible arguments, created by the argument completion function
+ */
ArgumentCompletionList operator()(const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "")
{
switch (this->paramCount_)
@@ -65,18 +102,19 @@
}
}
+ /// Returns true if the argument completion list supports multiple words.
inline bool useMultipleWords() const
{ return this->bUseMultipleWords_; }
private:
- bool bUseMultipleWords_;
- unsigned char paramCount_;
- ArgumentCompletionList (*function_0_) (void);
- ArgumentCompletionList (*function_1_) (const std::string& param1);
- ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2);
- ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3);
- ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4);
- ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5);
+ bool bUseMultipleWords_; ///< If true, the argument completion list supports multiple words
+ unsigned char paramCount_; ///< The number of parameters of the argument completion function
+ ArgumentCompletionList (*function_0_) (void); ///< Function-pointer for an argument completion function with no arguments
+ ArgumentCompletionList (*function_1_) (const std::string& param1); ///< Function-pointer for an argument completion function with one argument
+ ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2); ///< Function-pointer for an argument completion function with two arguments
+ ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3); ///< Function-pointer for an argument completion function with three arguments
+ ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4); ///< Function-pointer for an argument completion function with four arguments
+ ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5); ///< Function-pointer for an argument completion function with five arguments
};
}
Modified: code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.cc
===================================================================
--- code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,11 @@
*
*/
+/**
+ @file
+ @brief Implementation of all argument completion functions
+*/
+
#include "ArgumentCompletionFunctions.h"
#include <map>
@@ -52,6 +57,9 @@
{
namespace autocompletion
{
+ /**
+ @brief Fallback implementation, returns an empty list.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
{
return ArgumentCompletionList();
@@ -59,6 +67,9 @@
namespace detail
{
+ /**
+ @brief Returns true if a group of console commands is visible (i.e. if at least one command in this group is visible).
+ */
bool groupIsVisible(const std::map<std::string, ConsoleCommand*>& group, bool bOnlyShowHidden)
{
for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = group.begin(); it_command != group.end(); ++it_command)
@@ -68,44 +79,66 @@
return false;
}
+ /**
+ @brief Returns a list of all console command groups AND all console command shortcuts.
+ @param fragment The last argument
+ @param bOnlyShowHidden If true, only hidden groups and commands are returned
+ */
ArgumentCompletionList _groupsandcommands(const std::string& fragment, bool bOnlyShowHidden)
{
+ // note: this function returns only arguments that begin with "fragment", which would't be necessary for the
+ // auto-completion, but it's necessary to place the line-break "\n" between groups and commands
+ // only if both groups AND commands are in the list.
+
ArgumentCompletionList groupList;
std::string fragmentLC = getLowercase(fragment);
+ // get all the groups that are visible (except the shortcut group "")
const std::map<std::string, std::map<std::string, ConsoleCommand*> >& commands = ConsoleCommand::getCommands();
for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.begin(); it_group != commands.end(); ++it_group)
if (groupIsVisible(it_group->second, bOnlyShowHidden) && it_group->first != "" && (fragmentLC == "" || getLowercase(it_group->first).find_first_of(fragmentLC) == 0))
groupList.push_back(ArgumentCompletionListElement(it_group->first, getLowercase(it_group->first)));
+ // now add all shortcuts (in group "")
std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.find("");
if (it_group != commands.end())
{
+ // add a line-break if the list isn't empty
if (!groupList.empty())
groupList.push_back(ArgumentCompletionListElement("", "", "\n"));
+ // add the shortcuts
for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
if (it_command->second->isActive() && it_command->second->hasAccess() && (!it_command->second->isHidden())^bOnlyShowHidden && (fragmentLC == "" || getLowercase(it_command->first).find_first_of(fragmentLC) == 0))
groupList.push_back(ArgumentCompletionListElement(it_command->first, getLowercase(it_command->first)));
}
+ // if no shortcut was added, remove the line-break again
if (!groupList.empty() && groupList.back().getDisplay() == "\n")
groupList.pop_back();
return groupList;
}
+ /**
+ @brief Returns a list of all console commands in a given group.
+ @param fragment The last argument
+ @param group The group's name
+ @param bOnlyShowHidden If true, only hidden console commands are returned
+ */
ArgumentCompletionList _subcommands(const std::string& fragment, const std::string& group, bool bOnlyShowHidden)
{
ArgumentCompletionList commandList;
std::string groupLC = getLowercase(group);
+ // find the iterator of the given group
std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().begin();
for ( ; it_group != ConsoleCommand::getCommands().end(); ++it_group)
if (getLowercase(it_group->first) == groupLC)
break;
+ // add all commands in the group to the list
if (it_group != ConsoleCommand::getCommands().end())
{
for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
@@ -117,16 +150,27 @@
}
}
+ /**
+ @brief Returns a list of all console command groups AND all console command shortcuts.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(groupsandcommands)(const std::string& fragment)
{
return detail::_groupsandcommands(fragment, false);
}
+ /**
+ @brief Returns a list of all console commands in a given group.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(subcommands)(const std::string& fragment, const std::string& group)
{
return detail::_subcommands(fragment, group, false);
}
+ /**
+ @brief Returns a list of commands and groups and also supports auto-completion of the arguments of these commands.
+
+ This is a multi-word function, because commands are composed of 1-2 words and additional arguments.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(command)(const std::string& fragment)
{
CommandEvaluation evaluation = CommandExecutor::evaluate(fragment);
@@ -144,6 +188,13 @@
}
}
+ /**
+ @brief Returns a list of hidden commands and groups and also supports auto-completion of the arguments of these commands.
+
+ This is a multi-word function, because commands are composed of 1-2 words and additional arguments.
+
+ This function makes commands visible that would usually be hidden.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(hiddencommand)(const std::string& fragment)
{
SubString tokens(fragment, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0');
@@ -169,6 +220,13 @@
return ArgumentCompletionList();
}
+ /**
+ @brief Returns possible files and directories and also supports files in arbitrary deeply nested subdirectories.
+
+ This function returns files and directories in the given path. This allows to
+ navigate iteratively through the file system. The first argument @a fragment
+ is used to get the current path.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
{
ArgumentCompletionList dirlist;
@@ -210,6 +268,9 @@
return filelist;
}
+ /**
+ @brief Returns the sections of the config file.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingssections)()
{
ArgumentCompletionList sectionList;
@@ -221,6 +282,9 @@
return sectionList;
}
+ /**
+ @brief Returns the entries in a given section of the config file.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsentries)(const std::string& fragment, const std::string& section)
{
ArgumentCompletionList entryList;
@@ -234,6 +298,9 @@
return entryList;
}
+ /**
+ @brief Returns the current value of a given value in a given section of the config file.
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section)
{
ArgumentCompletionList oldValue;
@@ -254,6 +321,9 @@
return oldValue;
}
+ /**
+ @brief Returns a list of indexes of the available Tcl threads (see TclThreadManager).
+ */
ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
{
std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
Modified: code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.h
===================================================================
--- code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ArgumentCompletionFunctions.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,22 +26,158 @@
*
*/
+/**
+ @file
+ @ingroup Command ArgumentCompletion
+ @brief Declaration of all argument completion functions and macros used to define them.
+
+ @anchor ArgumentCompletionExample
+
+ Argument completion functions are used to create a list of possible arguments
+ for an orxonox::ConsoleCommand. These functions are usually wrapped by an instance
+ of orxonox::ArgumentCompleter.
+
+ Argument completion functions can be declared and implemented by using the macros
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION() and ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION()
+ respectively. They are necessary because they don't simply define the function, but they also
+ create a static helper function that returns an instance of orxonox::ArgumentCompleter which
+ wraps the defined function. This allows easier referencing of argument completion functions
+ by simply calling autocompletion::functionname().
+
+ Argument completion functions can take up to 5 arguments, all of type std::string.
+ The first argument is always the current argument which is being entered by the user
+ in the shell. The second argument is the argument before, so in fact arguments from
+ the shell are sent in reversed order to the argument completion function. This is
+ necessary because the number of arguments can be variable
+
+ Example: The user types the following into the shell:
+ @code
+ $ commandname argument1 argument2 argum
+ @endcode
+ Then he presses the @a tab key to print the possible arguments. Now the argument
+ completion function for the @a third argument of @a commandname will be called in
+ the following way:
+ @code
+ list = argcompfunction3("argum", "argument2", "argument1");
+ @endcode
+
+ Usually each argument is one word (without whitespaces in it), but some argument completion
+ functions need more than one word. This can be achieved by using ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI().
+ In this case all supernumerous words are passed to the first (!) argument.
+
+ An example to show how to declare, implement, and use an argument completion function:
+ @code
+ // ArgumentCompletionFunctions.h:
+ // ------------------------------
+
+ // Declaration of the function:
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION(month)(const std::string& fragment);
+
+ // ArgumentCompletionFunctions.cc:
+ // -------------------------------
+
+ // Implementation of the function
+ ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(month)(const std::string& fragment)
+ {
+ ArgumentCompletionList list;
+
+ // check if the first part of the argument is a number - if yes, the user likely wants to enter the month as a number
+ if (isNumber(fragment))
+ {
+ for (int month = 1; month <= 12; ++month)
+ list.push_back(ArgumentCompletionListElement(multi_cast<std::string>(month)));
+ }
+ else
+ {
+ list.push_back(ArgumentCompletionListElement("January", "january"));
+ list.push_back(ArgumentCompletionListElement("February", "february"));
+ list.push_back(ArgumentCompletionListElement("March", "march"));
+ list.push_back(ArgumentCompletionListElement("April", "april"));
+ list.push_back(ArgumentCompletionListElement("May", "may"));
+ list.push_back(ArgumentCompletionListElement("June", "june"));
+ list.push_back(ArgumentCompletionListElement("July", "july"));
+ list.push_back(ArgumentCompletionListElement("August", "august"));
+ list.push_back(ArgumentCompletionListElement("September", "september"));
+ list.push_back(ArgumentCompletionListElement("October", "october"));
+ list.push_back(ArgumentCompletionListElement("November", "november"));
+ list.push_back(ArgumentCompletionListElement("December", "december"));
+ }
+
+ return list;
+ }
+
+ // SomeFile:
+ // ---------
+
+ // A class to manage the date:
+ class Date
+ {
+ public:
+ static void setDate(int day, const std::string& month, int year);
+ };
+
+ // Define a console command that needs a date. Add argument completion for the month:
+ SetConsoleCommand("setDate", &Date::setDate).argumentCompleter(1, autocompletion::month());
+ @endcode
+
+ This example defines an argument completion function that returns a list of possible
+ months. If the first part of the argument is a number, it returns the numbers 1-12,
+ otherwise the name of the months are returned. Note how the list is composed by
+ instances of orxonox::ArgumentCompletionListElement. For the name of the months,
+ two strings are provided, one in normal case and one in lower case. See the documentation
+ of orxonox::ArgumentCompletionListElement for more information about this.
+
+ Also note that the argument completion list is assigned to the console command by using
+ @ref orxonox::ConsoleCommand::argumentCompleter "argumentCompleter()". The first argument
+ is the index of the argument:
+ - 0 is the first argument (@a day)
+ - 1 is the second argument (@a month)
+ - 2 is the third argument (@a year)
+
+ @a day and @a year don't need an argument completion function as they are just integers.
+
+ The function @c autocompletion::month() is automatically created by the macros
+ ARGUMENT_COMPLETION_FUNCTION_DECLARATION() and ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION()
+ and returns an orxonox::ArgumentCompleter that wraps the defined argument completion function.
+
+ The implemented argument completion function uses only one argument, the fragment of the
+ currently entered argument. More complex functions can also use the previous arguments
+ to return different arguments depending on the other arguments (for example to list the
+ members of a class, where the class-name is the first argument and the member the second).
+*/
+
#ifndef _ArgumentCompletionFunctions_H__
#define _ArgumentCompletionFunctions_H__
#include "core/CorePrereqs.h"
#include "ArgumentCompleter.h"
+/**
+ @brief Used to declare an argument completion function with name @a functionname.
+ @param functionname The name of the function, will also be used for the implementation of the function.
+ The macro also defines a static function that returns an orxonox::ArgumentCompleter
+ which wraps the defined function. This can be accessed by calling autocompletion::functionname();
+*/
#define ARGUMENT_COMPLETION_FUNCTION_DECLARATION(functionname) \
_CoreExport ArgumentCompleter* functionname(); \
_CoreExport ArgumentCompletionList acf_##functionname
+/**
+ @brief Used to implement an argument completion function.
+ @param functionname The name of the function
+*/
#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(functionname) \
_ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_INTERNAL(functionname, false)
+
+/**
+ @brief Used to implement an argument completion function which allows multiple words.
+ @param functionname The name of the function
+*/
#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(functionname) \
_ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_INTERNAL(functionname, true)
+/// Internal macro
#define _ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_INTERNAL(functionname, bUseMultipleWords) \
ArgumentCompleter* functionname() \
{ \
@@ -51,6 +187,7 @@
\
ArgumentCompletionList acf_##functionname
+/// Calls an argument completion function. Used for functions that return the results of another argument completion function.
#define ARGUMENT_COMPLETION_FUNCTION_CALL(functionname) acf_##functionname
Modified: code/branches/doc/src/libraries/core/command/ArgumentCompletionListElement.h
===================================================================
--- code/branches/doc/src/libraries/core/command/ArgumentCompletionListElement.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ArgumentCompletionListElement.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,12 @@
*
*/
+/**
+ @file
+ @ingroup Command ArgumentCompletion
+ @brief Definition of ArgumentCompletionList, which is used in @ref ArgumentCompletionFunctions.h "argument completion functions", and its element.
+*/
+
#ifndef _ArgumentCompletionListElement_H__
#define _ArgumentCompletionListElement_H__
@@ -36,39 +42,63 @@
namespace orxonox
{
- const int ACL_MODE_NORMAL = 1;
- const int ACL_MODE_COMPARABLE = 2;
- const int ACL_MODE_DISPLAY = 4;
+ const int ACL_MODE_NORMAL = 1; ///< A flag, used if there's a normal string
+ const int ACL_MODE_COMPARABLE = 2; ///< A flag, used if there's a different string used to compare
+ const int ACL_MODE_DISPLAY = 4; ///< A flag, used if there's a different string used to be displayed
typedef std::list<ArgumentCompletionListElement> ArgumentCompletionList;
+ /**
+ @brief This class is used in argument completion lists and contains up to three different strings, used in different situations.
+
+ A list containing elements of type ArgumentCompletionListElement is returned by
+ an @ref ArgumentCompletionFunctions.h "argument completion function". These elements
+ are composed of up to three strings with different usage:
+ - normal: What is used as the actual argument
+ - comparable: What is used to compere the argument to the input of the user (usually lowercase, except for case-sensitive arguments)
+ - display: This is displayed in the list of possible arguments - can differ from what is actually used for better readability
+
+ @remarks An element with an empty ("") 'comparable' string will be ignored by the argument
+ completion algorithms, but it's 'display' string will still be printed in the list. This
+ can be used to add additional information, whitespaces, linebreaks or whatever is needed
+ to format the output.
+ */
class _CoreExport ArgumentCompletionListElement
{
public:
+ /// Constructor: Normal, comparable, and display string are all the same.
ArgumentCompletionListElement(const std::string& normalcase) : mode_(ACL_MODE_NORMAL), normal_(normalcase) {}
+ /// Constructor: Normal and display string are the same, a different (usually lowercase) string is used for comparison.
ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase) : mode_(ACL_MODE_NORMAL | ACL_MODE_COMPARABLE), normal_(normalcase), comparable_(lowercase) {}
+ /// Constructor: Normal, comparable, and display are all different strings.
ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase, const std::string& display) : mode_(ACL_MODE_NORMAL | ACL_MODE_COMPARABLE | ACL_MODE_DISPLAY), normal_(normalcase), comparable_(lowercase), display_(display) {}
+ /// Returns the normal string which is used as the actual argument.
const std::string& getString() const
{ return this->normal_; }
+ /// Returns the comparable string which is used to compare arguments and user input
const std::string& getComparable() const
{ return (this->mode_ & ACL_MODE_COMPARABLE) ? this->comparable_ : this->normal_; }
+ /// Returns the display string which is used in the displayed list of possible arguments
const std::string& getDisplay() const
{ return (this->mode_ & ACL_MODE_DISPLAY) ? this->display_ : this->normal_; }
+ /// Returns true if there's a different string for comparison.
bool hasComparable() const
{ return (this->mode_ & ACL_MODE_COMPARABLE); }
+ /// Returns true if there's a different string to display.
bool hasDisplay() const
{ return (this->mode_ & ACL_MODE_DISPLAY); }
+ /// Overloaded operator for usage in maps and sets.
bool operator<(const ArgumentCompletionListElement& other) const
{ return (this->getComparable() < other.getComparable()); }
private:
- unsigned char mode_;
- std::string normal_;
- std::string comparable_;
- std::string display_;
+ unsigned char mode_; ///< The flags
+ std::string normal_; ///< The normal string
+ std::string comparable_; ///< The comparable (usually lowercase) string
+ std::string display_; ///< The string to display
};
}
Modified: code/branches/doc/src/libraries/core/command/CommandEvaluation.cc
===================================================================
--- code/branches/doc/src/libraries/core/command/CommandEvaluation.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/CommandEvaluation.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,11 @@
*
*/
+/**
+ @file
+ @brief Implementation of CommandEvaluation
+*/
+
#include "CommandEvaluation.h"
#include "util/StringUtils.h"
@@ -34,11 +39,17 @@
namespace orxonox
{
+ /**
+ @brief Constructor: Initializes the command evaluation with an empty command.
+ */
CommandEvaluation::CommandEvaluation()
{
this->initialize("");
}
+ /**
+ @brief Initializes all values.
+ */
void CommandEvaluation::initialize(const std::string& command)
{
this->execCommand_ = 0;
@@ -48,30 +59,43 @@
this->hintArgumentsOffset_ = 0;
this->bPossibleArgumentsRetrieved_ = false;
this->possibleArguments_.clear();
- this->bEvaluatedParams_ = false;
- this->bTriedToEvaluatedParams_ = false;
- this->numberOfEvaluatedParams_ = 0;
+ this->bEvaluatedArguments_ = false;
+ this->bTriedToEvaluatedArguments_ = false;
+ this->numberOfEvaluatedArguments_ = 0;
+ // split the command into tokens
this->tokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0');
}
+ /**
+ @brief Returns the number of tokens according to the definition of CommandExecutor (which counts also an empty argument at the end of the string).
+ */
unsigned int CommandEvaluation::getNumberOfArguments() const
{
unsigned int count = this->tokens_.size();
- if (count > 0 && this->string_[this->string_.size() - 1] != ' ')
+
+ // If the last char in the string is a space character (or the string is empty), add +1 to the number of tokens, because this counts as an additional (but empty) argument
+ if (count == 0 || this->string_[this->string_.size() - 1] == ' ')
+ return count + 1;
+ else
return count;
- else
- return count + 1;
}
+ /**
+ @brief Returns the last argument (which is the one the user currently enters into the shell).
+ */
const std::string& CommandEvaluation::getLastArgument() const
{
- if (this->tokens_.size() > 0 && this->string_[this->string_.size() - 1] != ' ')
+ // the string is empty or ends with a space character, the user is just about to enter a new argument (but its still empty). return a blank string in this case.
+ if (this->tokens_.size() == 0 || this->string_[this->string_.size() - 1] == ' ')
+ return BLANKSTRING;
+ else
return this->tokens_.back();
- else
- return BLANKSTRING;
}
+ /**
+ @brief Returns the token with the given index (or a blank string if it doesn't exist).
+ */
const std::string& CommandEvaluation::getToken(unsigned int i) const
{
if (i < this->tokens_.size())
@@ -80,6 +104,10 @@
return BLANKSTRING;
}
+ /**
+ @brief Executes the command which was evaluated by this object.
+ @return Returns the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+ */
int CommandEvaluation::execute()
{
int error;
@@ -87,10 +115,18 @@
return error;
}
+ /**
+ @brief Executes the command which was evaluated by this object and returns its return-value.
+ @param error A pointer to an integer (or NULL) which will be used to write error codes to (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+ @return Returns the result of the command (or MT_Type::Null if there is no return value)
+ */
MultiType CommandEvaluation::query(int* error)
{
+ // check if an error value was passed by reference
if (error)
{
+ // Determine the error-code and return if it is not Success
+
*error = CommandExecutor::Success;
if (!this->execCommand_)
@@ -104,110 +140,169 @@
return MT_Type::Null;
}
+ // check if it's possible to execute the command
if (this->execCommand_ && this->execCommand_->isActive() && this->execCommand_->hasAccess())
{
- if (!this->bTriedToEvaluatedParams_)
- this->evaluateParams(false);
+ // if the arguments weren't evaluated yet, do it now.
+ if (!this->bTriedToEvaluatedArguments_)
+ this->evaluateArguments(false);
- if (this->bEvaluatedParams_)
+ // check if the argument evaluation succeded
+ if (this->bEvaluatedArguments_)
{
- COUT(6) << "CE_execute (evaluation): " << this->execCommand_->getName() << " with " << this->numberOfEvaluatedParams_ << " params: " << this->param_[0] << ' ' << this->param_[1] << ' ' << this->param_[2] << ' ' << this->param_[3] << ' ' << this->param_[4] << std::endl;
- switch (this->numberOfEvaluatedParams_)
+ COUT(6) << "CE_execute (evaluation): " << this->execCommand_->getName() << " with " << this->numberOfEvaluatedArguments_ << " arguments: " << this->arguments_[0] << ' ' << this->arguments_[1] << ' ' << this->arguments_[2] << ' ' << this->arguments_[3] << ' ' << this->arguments_[4] << std::endl;
+
+ // pass as many arguments to the executor as were evaluated (thus the executor can still use additional default values)
+ switch (this->numberOfEvaluatedArguments_)
{
case 0: return (*this->execCommand_->getExecutor())();
- case 1: return (*this->execCommand_->getExecutor())(this->param_[0]);
- case 2: return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1]);
- case 3: return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2]);
- case 4: return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2], this->param_[3]);
+ case 1: return (*this->execCommand_->getExecutor())(this->arguments_[0]);
+ case 2: return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1]);
+ case 3: return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1], this->arguments_[2]);
+ case 4: return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1], this->arguments_[2], this->arguments_[3]);
case 5:
- default: return (*this->execCommand_->getExecutor())(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
+ default: return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1], this->arguments_[2], this->arguments_[3], this->arguments_[4]);
}
}
else if (error)
*error = CommandExecutor::Incomplete;
}
+ // return a null value in case of an error
return MT_Type::Null;
}
- int CommandEvaluation::evaluateParams(bool bPrintError)
+ /**
+ @brief Evaluates the arguments of the command.
+ @param bPrintError If true, the function prints an error message if it doesn't succeed
+ @return Returns the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+ */
+ int CommandEvaluation::evaluateArguments(bool bPrintError)
{
- this->bTriedToEvaluatedParams_ = true;
+ this->bTriedToEvaluatedArguments_ = true;
+ // check if there's a command to execute
if (!this->execCommand_)
{
if (bPrintError)
- COUT(1) << "Error: Can't evaluate params, no console command assigned." << std::endl;
+ COUT(1) << "Error: Can't evaluate arguments, no console command assigned." << std::endl;
return CommandExecutor::Error;
}
int error;
- this->numberOfEvaluatedParams_ = this->execCommand_->getExecutor()->evaluateParams(this->tokens_.subSet(this->execArgumentsOffset_), this->param_, &error, " ");
+
+ // try to evaluate the arguments using the executor of the evaluated command.
+ // the arguments are currently stored as strings in token_, but afterwards they will be converted to the right type and stored in arguments_
+ this->numberOfEvaluatedArguments_ = this->execCommand_->getExecutor()->evaluateArguments(this->tokens_.subSet(this->execArgumentsOffset_), this->arguments_, &error, " ");
+
+ // check if an error occurred
if (!error)
- this->bEvaluatedParams_ = true;
+ this->bEvaluatedArguments_ = true;
else if (bPrintError)
- COUT(1) << "Error: Can't evaluate params, not enough arguments given." << std::endl;
+ COUT(1) << "Error: Can't evaluate arguments, not enough arguments given." << std::endl;
return error;
}
- void CommandEvaluation::setEvaluatedParameter(unsigned int index, const MultiType& param)
+ /**
+ @brief Replaces an evaluated argument with a new value.
+ @param index The index of the parameter (the first argument has index 0)
+ @param arg The new value of the parameter
+ */
+ void CommandEvaluation::setEvaluatedArgument(unsigned int index, const MultiType& arg)
{
if (index < MAX_FUNCTOR_ARGUMENTS)
- this->param_[index] = param;
+ this->arguments_[index] = arg;
}
- MultiType CommandEvaluation::getEvaluatedParameter(unsigned int index) const
+ /**
+ @brief Returns the evaluated argument with given index.
+ @param index The index of the argument (the first argument has index 0)
+ */
+ MultiType CommandEvaluation::getEvaluatedArgument(unsigned int index) const
{
if (index < MAX_FUNCTOR_ARGUMENTS)
- return this->param_[index];
+ return this->arguments_[index];
return MT_Type::Null;
}
+ /**
+ @brief Completes the given command string using the list of possible arguments.
+ @return Returns the completed command string
+
+ This is called by the shell if the user presses the @a tab key. The currently entered
+ argument will be completed as good as possible by using the argument completion list
+ of the evaluated command.
+ */
std::string CommandEvaluation::complete()
{
+ // check if it's possible to complete the command
if (!this->hintCommand_ || !this->hintCommand_->isActive())
return this->string_;
+ // get the list of possible arguments
if (!this->bPossibleArgumentsRetrieved_)
this->retrievePossibleArguments();
+ // if the list is empty, return the current command string
if (CommandEvaluation::getSize(this->possibleArguments_) == 0)
{
return this->string_;
}
else
{
+ // get the first part of the command string from the beginning up to the last space character
std::string output = this->string_.substr(0, this->string_.find_last_of(' ') + 1);
+
+ // add the common begin of all possible arguments
output += CommandEvaluation::getCommonBegin(this->possibleArguments_);
+
+ // return the resulting string
return output;
}
}
+ /**
+ @brief Returns a string containing hints or possible arguments for the evaluated command.
+
+ This is called by the shell if the user presses the @a tab key. It prints a list of
+ possible arguments or other hints, returned by the argument completion list of the
+ evaluated command. If there's no such list, the syntax of the command is returned.
+ */
std::string CommandEvaluation::hint()
{
+ // check if it's possible to get hints for this command
if (!this->hintCommand_ || !this->hintCommand_->isActive())
return "";
+ // get the list of possible arguments
if (!this->bPossibleArgumentsRetrieved_)
this->retrievePossibleArguments();
+ // return the list of possible arguments if:
+ // a) it contains at least one non-empty argument
+ // b) it contains an entry that may be empty (not an actual argument, just a helping text) AND the command is valid
if (CommandEvaluation::getSize(this->possibleArguments_) > 0 || (!this->possibleArguments_.empty() && this->isValid()))
return CommandEvaluation::dump(this->possibleArguments_);
+ // at this point there's no valid argument in the list, so check if the command is actually valid
if (this->isValid())
{
+ // yes it is - return the syntax of the command
return CommandEvaluation::dump(this->hintCommand_);
}
else
{
+ // no the command is not valid
if (this->getNumberOfArguments() > 2)
{
+ // the user typed 2+ arguments, but they don't name a command - print an error
return std::string("Error: There is no command with name \"") + this->getToken(0) + " " + this->getToken(1) + "\".";
}
else
{
+ // the user typed 1-2 arguments, check what he tried to type and print a suitable error
std::string groupLC = getLowercase(this->getToken(0));
for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().begin(); it_group != ConsoleCommand::getCommandsLC().end(); ++it_group)
if (it_group->first == groupLC)
@@ -218,6 +313,10 @@
}
}
+ /**
+ @brief If the command couln't be evaluated because it doesn't exist, print a suggestion for
+ a command that looks close to the entered command (useful if the user mistyped the command).
+ */
std::string CommandEvaluation::getCommandSuggestion() const
{
std::string token0_LC = getLowercase(this->getToken(0));
@@ -226,6 +325,7 @@
std::string nearestCommand;
unsigned int nearestDistance = (unsigned int)-1;
+ // iterate through all groups and their commands and calculate the distance to the current command. keep the best.
for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().begin(); it_group != ConsoleCommand::getCommandsLC().end(); ++it_group)
{
if (it_group->first != "")
@@ -243,6 +343,7 @@
}
}
+ // now also iterate through all shortcuts and keep the best if it's better than the one found above.
std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().find("");
if (it_group != ConsoleCommand::getCommandsLC().end())
{
@@ -258,44 +359,71 @@
}
}
+ // return the command that's closest to the current one.
return nearestCommand;
}
+ /**
+ @brief Gets the possible arguments for the command in its current state.
+ */
void CommandEvaluation::retrievePossibleArguments()
{
this->bPossibleArgumentsRetrieved_ = true;
+
+ // we use the hintCommand_ to get possible arguments. get the index of the last argument. limit the index if its greater than the number of arguments supported by the command.
unsigned int argumentID = std::min(this->getNumberOfArguments() - this->hintArgumentsOffset_, this->hintCommand_->getExecutor()->getParamCount());
+
+ // get the argument completer for the given argument index
ArgumentCompleter* ac = this->hintCommand_->getArgumentCompleter(argumentID - 1);
+ // check if an argument completer exists
if (ac)
{
- MultiType param[MAX_FUNCTOR_ARGUMENTS];
+ MultiType arg[MAX_FUNCTOR_ARGUMENTS];
+ // the index of the last argument in the command string that is supported by this argument completer
size_t max = this->hintArgumentsOffset_ + this->hintCommand_->getExecutor()->getParamCount();
+ // write the argument strings to the argument array (in reversed order, as required by the argument completion function)
for (size_t i = 0; i < argumentID; ++i)
- param[i] = this->getToken(std::min(this->getNumberOfArguments(), (unsigned int)max) - i - 1);
+ arg[i] = this->getToken(std::min(this->getNumberOfArguments(), (unsigned int)max) - i - 1);
+ // check if there are more arguments given by the user than supported
if (this->getNumberOfArguments() > max)
{
+ // yes - now check if multiple words are supported by the argument completer
if (ac->useMultipleWords())
{
+ // yes - join the surplus arguments
std::string surplusArguments = this->tokens_.subSet(max - 1).join();
if (this->string_[this->string_.size() - 1] == ' ')
surplusArguments += ' ';
- this->possibleArguments_ = (*ac)(surplusArguments, param[1], param[2], param[3], param[4]);
+ // pass all surplus arguments as the first argument to the argument completer
+ this->possibleArguments_ = (*ac)(surplusArguments, arg[1], arg[2], arg[3], arg[4]);
+
+ // strip the list using the last argument
CommandEvaluation::strip(this->possibleArguments_, this->getToken(this->getNumberOfArguments() - 1));
}
+ else
+ {
+ // no - the user typed more arguments than supported, no action
+ }
}
else
{
- this->possibleArguments_ = (*ac)(param[0], param[1], param[2], param[3], param[4]);
- CommandEvaluation::strip(this->possibleArguments_, param[0]);
+ // no - so simply call the argument completer and get the list of arguments
+ this->possibleArguments_ = (*ac)(arg[0], arg[1], arg[2], arg[3], arg[4]);
+
+ // strip the list using the last argument (stored arg[0])
+ CommandEvaluation::strip(this->possibleArguments_, arg[0]);
}
}
}
+ /**
+ @brief Returns the size of an argument completion list - empty ("") arguments are not counted.
+ */
/* static */ size_t CommandEvaluation::getSize(const ArgumentCompletionList& list)
{
size_t count = 0;
@@ -305,26 +433,35 @@
return count;
}
+ /**
+ @brief Removes all elements from the list that don't start with @a fragment.
+ @param list The argument completion list
+ @param fragment The argument that is currently entered by the user and that needs to be completed
+ */
/* static */ void CommandEvaluation::strip(ArgumentCompletionList& list, const std::string& fragment)
{
std::string fragmentLC = getLowercase(fragment);
+ // iterate through the list
for (ArgumentCompletionList::iterator it = list.begin(); it != list.end(); )
{
const std::string& entry = it->getComparable();
+ // check if the argument is empty - if yes, keep it always in the list
if (entry == "")
{
++it;
continue;
}
+ // check the length of the argument - arguments smaller than 'fragment' are always erased
if (entry.size() < fragmentLC.size())
{
list.erase(it++);
}
else
{
+ // compare the argument char by char with 'fragment'
bool bErase = false;
for (size_t i = 0; i < fragmentLC.size(); ++i)
{
@@ -343,18 +480,24 @@
}
}
+ /**
+ @brief Returns the commond begin of all arguments in the list.
+ */
/* static */ std::string CommandEvaluation::getCommonBegin(const ArgumentCompletionList& list)
{
if (CommandEvaluation::getSize(list) == 0)
{
+ // no (non-empty) values in the list, return an empty string
return "";
}
else if (CommandEvaluation::getSize(list) == 1)
{
+ // only one (non-empty) value in the list - search it and return it
for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
{
if (it->getComparable() != "")
{
+ // arguments that have a separate string to be displayed need a little more care - just return them without modification. add a space character to the others.
if (it->hasDisplay())
return (it->getString());
else
@@ -366,31 +509,35 @@
}
else
{
+ // multiple arguments in the list - iterate through it and find the common begin of all arguments
std::string output;
for (unsigned int i = 0; true; i++)
{
- char tempComparable = 0;
- char temp = 0;
+ char tempComparable = '\0';
+ char temp = '\0';
for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
{
const std::string& argumentComparable = it->getComparable();
const std::string& argument = it->getString();
+ // ignore empty arguments
if (argumentComparable == "")
continue;
if (argument.size() > i)
{
- if (tempComparable == 0)
+ if (tempComparable == '\0')
{
+ // the first entry is always taken
tempComparable = argumentComparable[i];
temp = argument[i];
}
else
{
+ // all other entries need comparison to the first entry
if (tempComparable != argumentComparable[i])
return output;
- else if (temp != argument[i])
+ else if (temp != argument[i]) // the comparables match, but the normal chars don't - switch to comparable only
temp = tempComparable;
}
}
@@ -405,6 +552,9 @@
}
}
+ /**
+ @brief Joins the elements of the given list to a string.
+ */
/* static */ std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
{
std::string output;
@@ -412,30 +562,42 @@
{
output += it->getDisplay();
+ // add a space character between two elements for all non-empty arguments
if (it->getComparable() != "")
output += ' ';
}
return output;
}
+ /**
+ @brief Returns a string that explains the syntax of the given command.
+ */
/* static */ std::string CommandEvaluation::dump(const ConsoleCommand* command)
{
+ // get the name of the command
std::string output = command->getName();
+
+ // check if there are parameters
if (command->getExecutor()->getParamCount() > 0)
output += ": ";
+ // iterate through the parameters
for (unsigned int i = 0; i < command->getExecutor()->getParamCount(); i++)
{
+ // separate the parameters with a space character
if (i != 0)
output += ' ';
+ // print default values in [], others in {} braces
if (command->getExecutor()->defaultValueSet(i))
output += '[';
else
output += '{';
+ // add the type-name of the parameter
output += command->getExecutor()->getTypenameParam(i);
+ // print the default value if available
if (command->getExecutor()->defaultValueSet(i))
output += '=' + command->getExecutor()->getDefaultValue(i).getString() + ']';
else
Modified: code/branches/doc/src/libraries/core/command/CommandEvaluation.h
===================================================================
--- code/branches/doc/src/libraries/core/command/CommandEvaluation.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/CommandEvaluation.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,23 @@
*
*/
+/**
+ @defgroup CommandExecEval Command execution and evaluation
+ @ingroup Command
+*/
+
+/**
+ @file
+ @ingroup Command CommandExecEval
+ @brief Declaration of the orxonox::CommandEvaluation class which is returned by orxonox::CommandExecutor::evaluate().
+
+ The orxonox::CommandEvaluation class gathers all information about a command-string. It is used
+ internally by orxonox::CommandExecutor and can also be returned by it to provide more information
+ about a command. It's also possible to evaluate the arguments of a command to execute it faster.
+
+ @see See @ref CommandExecutorExample "this description" for an example.
+*/
+
#ifndef _CommandEvaluation_H__
#define _CommandEvaluation_H__
@@ -40,6 +57,26 @@
namespace orxonox
{
+ /**
+ @brief CommandEvaluation is used to gather information about a command and to evaluate its arguments
+
+ This class provides several information about a command-string, for example the
+ evaluated ConsoleCommand, but also other information like hints if the command
+ is not yet finished.
+
+ @note You don't have to call evaluateArguments() manually, it's also done automatically
+ if you call the command the first time. However you can of course do it at any earlier
+ time, for example to return an error message if it doesn't work.
+
+ @remarks execCommand_ and hintCommand_ can be different in this case: There are multiple
+ commands avaliable, let's say "tcl", "tclexecute", and "tclquery". The user enters
+ "tcl", which is already a valid command. Now execCommand_ points to the "tcl"-command,
+ but hintCommand_ still points to the autocompletion command of CommandExecutor, because
+ the auto-completion list must still return the three possible commands, "tcl tclexecute tclquery"
+ because the user may want to execute "tclquery" and needs auto-completion.
+
+ @see See @ref CommandExecutorExample "this description" for an example.
+ */
class _CoreExport CommandEvaluation
{
friend class CommandExecutor;
@@ -55,20 +92,30 @@
std::string getCommandSuggestion() const;
- int evaluateParams(bool bPrintError = false);
+ int evaluateArguments(bool bPrintError = false);
+ /// Returns true if the command evaluation contains a valid command that can be executed.
inline bool isValid() const
{ return (this->execCommand_ != 0); }
+ /// Returns the console command that was evaluated by this object.
inline const ConsoleCommand* getConsoleCommand() const
{ return this->execCommand_; }
- void setEvaluatedParameter(unsigned int index, const MultiType& param);
- MultiType getEvaluatedParameter(unsigned int index) const;
+ void setEvaluatedArgument(unsigned int index, const MultiType& arg);
+ MultiType getEvaluatedArgument(unsigned int index) const;
+ /**
+ @brief Returns a list of possible arguments for the given command.
+
+ Note that the command's arguments may not be complete yet, so in this case
+ this list returns the possibilities. They can then be used to display a list
+ of the possible arguments or to apply auto-completion.
+ */
const ArgumentCompletionList& getPossibleArguments() const
{ return this->possibleArguments_; }
+ /// Returns the number of possible arguments. Empty ("") arguments are not counted.
size_t getPossibleArgumentsSize() const
{ return CommandEvaluation::getSize(this->possibleArguments_); }
@@ -89,19 +136,19 @@
static std::string getCommonBegin(const ArgumentCompletionList& list);
- const ConsoleCommand* execCommand_;
- const ConsoleCommand* hintCommand_;
- SubString tokens_;
- std::string string_;
- unsigned int execArgumentsOffset_;
- unsigned int hintArgumentsOffset_;
- bool bPossibleArgumentsRetrieved_;
- ArgumentCompletionList possibleArguments_;
+ const ConsoleCommand* execCommand_; ///< The command that will be executed (can be NULL if the command is not valid)
+ const ConsoleCommand* hintCommand_; ///< The command that is used to display hints and argument lists (can be different to execCommand_ in some cases)
+ SubString tokens_; ///< The single words of the command string, split into tokens
+ std::string string_; ///< The original command string, entered by the user in the shell
+ unsigned int execArgumentsOffset_; ///< The index of the first argument in tokens_ used to execute the command
+ unsigned int hintArgumentsOffset_; ///< The index of the first argument in tokens_ used to display hints and argument lists
+ bool bPossibleArgumentsRetrieved_; ///< True if the list of possible arguments was already retrieved
+ ArgumentCompletionList possibleArguments_; ///< List of possible arguments for the command in the current state
- bool bEvaluatedParams_;
- bool bTriedToEvaluatedParams_;
- unsigned int numberOfEvaluatedParams_;
- MultiType param_[MAX_FUNCTOR_ARGUMENTS];
+ bool bEvaluatedArguments_; ///< True if the arguments of the command have been evaluated (and stored in arguments_)
+ bool bTriedToEvaluatedArguments_; ///< True if an attempt was started to evaluate the arguments (but not necessarily successful)
+ unsigned int numberOfEvaluatedArguments_; ///< The number of evaluated arguments (ranges from 0 to MAX_FUNCTOR_ARGUMENTS)
+ MultiType arguments_[MAX_FUNCTOR_ARGUMENTS]; ///< The evaluated arguments (the arguments from string_ or tokens_ converted to the right type)
};
}
Modified: code/branches/doc/src/libraries/core/command/CommandExecutor.cc
===================================================================
--- code/branches/doc/src/libraries/core/command/CommandExecutor.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/CommandExecutor.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,11 @@
*
*/
+/**
+ @file
+ @brief Implementation of CommandExecutor
+*/
+
#include "CommandExecutor.h"
#include "ConsoleCommand.h"
@@ -48,12 +53,21 @@
SetConsoleCommand("alias", &CommandExecutor::alias)
.argumentCompleter(1, autocompletion::command());
+ /**
+ @brief Returns a reference to the only instance of CommandExecutor.
+ */
/* static */ CommandExecutor& CommandExecutor::getInstance()
{
static CommandExecutor instance;
return instance;
}
+ /**
+ @brief Executes a command.
+ @param command A string containing the command
+ @param useTcl If true, the command is passed to tcl (see TclBind)
+ @return Returns the error-code (see @ref CommandExecutorErrorCodes "error codes")
+ */
/* static */ int CommandExecutor::execute(const std::string& command, bool useTcl)
{
int error;
@@ -61,49 +75,92 @@
return error;
}
+ /**
+ @brief Executes a command and returns its return-value.
+ @param command A string containing the command
+ @param error A pointer to a value (or NULL) where the error-code should be written to (see @ref CommandExecutorErrorCodes "error codes")
+ @param useTcl If true, the command is passed to tcl (see TclBind)
+ @return Returns the return-value of the command (if any - MT_Type::Null otherwise)
+ */
/* static */ MultiType CommandExecutor::queryMT(const std::string& command, int* error, bool useTcl)
{
if (useTcl)
+ {
+ // pass the command to tcl
return TclBind::eval(command, error);
+ }
else
{
CommandEvaluation evaluation;
+
+ // try to get the command evaluation from the cache
if (!CommandExecutor::getInstance().getCached(command, evaluation))
{
+ // it wasn't in the cache - evaluate the command
evaluation = CommandExecutor::evaluate(command);
- evaluation.evaluateParams();
+
+ // evaluate its arguments
+ evaluation.evaluateArguments();
+
+ // write the evaluation to the cache
CommandExecutor::getInstance().cache(command, evaluation);
}
+ // query the command and return its return-value
return evaluation.query(error);
}
}
+ /**
+ @brief Executes a command and returns its return-value as string.
+ @param command A string containing the command
+ @param error A pointer to a value (or NULL) where the error-code should be written to (see @ref CommandExecutorErrorCodes "error codes")
+ @param useTcl If true, the command is passed to tcl (see TclBind)
+ @return Returns the return-value of the command converted to a string (or "" if there's no return value)
+ */
/* static */ std::string CommandExecutor::query(const std::string& command, int* error, bool useTcl)
{
return CommandExecutor::queryMT(command, error, useTcl).getString();
}
+ /**
+ @brief Evaluates the given command.
+ @param command A string containing the command
+ @return Returns an instance of CommandEvaluation, which contains the evaluated ConsoleCommand, if the command is valid.
+
+ Evaluates the given command string and returns an instance of CommandEvaluation.
+ If the command is valid, this contains the evaluated ConsoleCommand. Otherwise it
+ can still be used to print hints or complete the command.
+
+ @note Tcl commands can not be evaluated. You have to pass them to execute() or to
+ TclBind directly.
+ */
/* static */ CommandEvaluation CommandExecutor::evaluate(const std::string& command)
{
+ // initialize the command evaluation
CommandEvaluation evaluation;
evaluation.initialize(command);
+ // assign the fallback-command to get hints about the possible commands and groups
evaluation.hintCommand_ = ConsoleCommand::getCommand(__CC_CommandExecutor_name, __CC_autocomplete_name);
+ // check if there's at least one argument
if (evaluation.getNumberOfArguments() >= 1)
{
+ // try to get a command from the first token
evaluation.execCommand_ = ConsoleCommand::getCommandLC(evaluation.getToken(0));
if (evaluation.execCommand_)
evaluation.execArgumentsOffset_ = 1;
else if (evaluation.getNumberOfArguments() >= 2)
{
+ // try to get a command from the first two tokens
evaluation.execCommand_ = ConsoleCommand::getCommandLC(evaluation.getToken(0), evaluation.getToken(1));
if (evaluation.execCommand_)
evaluation.execArgumentsOffset_ = 2;
}
}
+ // if a valid command was found and the user is already entering arguments, overwrite hintCommand_ with execCommand_
if (evaluation.execCommand_ && evaluation.getNumberOfArguments() > evaluation.execArgumentsOffset_)
{
evaluation.hintCommand_ = evaluation.execCommand_;
@@ -113,11 +170,18 @@
return evaluation;
}
+ /**
+ @brief Gets an evaluated command from the cache.
+ @param command The command that should be looked up in the cache
+ @param evaluation Reference to a CommandEvaluation that will be used to return the cached evaluation.
+ @return Returns true if the command was found in the cache
+ */
bool CommandExecutor::getCached(const std::string& command, CommandEvaluation& evaluation)
{
if (Shell::getCacheSize() == 0)
return false;
+ // check if the command is in the cache
std::map<std::string, CacheEntry>::iterator it = this->cache_.find(command);
if (it != this->cache_.end())
{
@@ -133,6 +197,9 @@
return false;
}
+ /**
+ @brief Writes a command evaluation for a given command to the cache.
+ */
void CommandExecutor::cache(const std::string& command, const CommandEvaluation& evaluation)
{
if (Shell::getCacheSize() == 0)
@@ -155,32 +222,49 @@
}
}
+ /**
+ @brief This function is used as console command which executes commands that are usually hidden.
+
+ The argument completion function of this console commands is used to find
+ and enter hidden commands and their arguments.
+ */
/* static */ MultiType CommandExecutor::unhide(const std::string& command)
{
return CommandExecutor::queryMT(command);
}
+ /**
+ @brief This function is used as console command which saves a command and optionally also it's arguments as a new console command with a new name.
+ @param alias The name of the new command alias
+ @param command The existing command and (optionally) its arguments
+ */
/* static */ void CommandExecutor::alias(const std::string& alias, const std::string& command)
{
+ // first check if the given command is valid, else print an error
CommandEvaluation evaluation = CommandExecutor::evaluate(command);
if (evaluation.isValid())
{
+ // it is valid - copy the executor of this command
ExecutorPtr executor = new Executor(*evaluation.getConsoleCommand()->getExecutor().get());
- if (!evaluation.evaluateParams())
+ // evaluate the arguments and if this returns no error, store them as default values
+ if (!evaluation.evaluateArguments())
{
for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
- executor->setDefaultValue(i, evaluation.getEvaluatedParameter(i));
+ executor->setDefaultValue(i, evaluation.getEvaluatedArgument(i));
}
+ // split the alias in tokens
SubString tokens(alias, " ");
+ // check if the alias already exists - print an error and return if it does
if ((tokens.size() == 1 && ConsoleCommand::getCommand(tokens[0])) || (tokens.size() == 2 && ConsoleCommand::getCommand(tokens[0], tokens[1])))
{
COUT(1) << "Error: A command with name \"" << alias << "\" already exists." << std::endl;
return;
}
+ // create a new console command with the given alias as its name
if (tokens.size() == 1)
createConsoleCommand(tokens[0], executor);
else if (tokens.size() == 2)
Modified: code/branches/doc/src/libraries/core/command/CommandExecutor.h
===================================================================
--- code/branches/doc/src/libraries/core/command/CommandExecutor.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/CommandExecutor.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,62 @@
*
*/
+/**
+ @file
+ @ingroup Command CommandExecEval
+ @brief Declaration of the orxonox::CommandExecutor class which is used to execute and evaluate @ref orxonox::ConsoleCommand "console commands".
+
+ @anchor CommandExecutorExample
+
+ orxonox::CommandExecutor can be used to execute console commands (see orxonox::ConsoleCommand).
+ Commands are strings that can be entered by the user in the shell or they can be part of a
+ script.
+
+ A command can be passed to orxonox::CommandExecutor::execute() which will execute them - eiter
+ directly, or - if requested - passes it to Tcl. See orxonox::TclBind for more information.
+ Appart from execute() the command can also be passed to orxonox::CommandExecutor::query() which
+ behaves the same except for that it returns the return value of the command.
+
+ If you don't want to execute the command, but rather gather more information about it, pass it
+ to orxonox::CommandExecutor::evaluate(). This function returns an instance of
+ orxonox::CommandEvaluation. This class provides more information about the command, for example
+ the evaluated instance of orxonox::ConsoleCommand. Its also possible to gather hints about the
+ command or to complete the command-string by using argument completion functions. More than that
+ the command evaluation can also evaluate the arguments, which allows faster execution of the
+ command.
+
+ Example:
+ @code
+ CommandExecutor::execute("log test"); // writes "test" to the console
+ CommandExecutor::execute("log [expr 1+1]"); // writes "2" to the console - expr is a Tcl command
+
+ CommandExecutor::query("expr 1+1"); // returns "2"
+ CommandExecutor::queryMT("expr 1+1"); // returns 2
+ @endcode
+
+ And another example about how to use evaluate():
+ @code
+ CommandEvaluation evaluation;
+ evaluation = CommandExecutor::evaluate("log test"); // returns an evaluation of "log test"
+
+ evaluation.execute(); // writes "test" to the console
+ evaluation.hint(); // returns "log: {string}"
+ @endcode
+
+ @anchor CommandExecutorErrorCodes
+
+ @b Error @b codes:
+
+ orxonox::CommandExecutor defines a number of error codes that are returned
+ by different functions that operate with commands:
+
+ - CommandExecutor::Success: No error
+ - CommandExecutor::Error: The command doesn't exist
+ - CommandExecutor::Incomplete: The command needs more arguments
+ - CommandExecutor::Deactivated: The command is not active
+ - CommandExecutor::Denied: The command needs a different @ref orxonox::AccessLevel "access level"
+*/
+
#ifndef _CommandExecutor_H__
#define _CommandExecutor_H__
@@ -41,6 +97,15 @@
// tolua_begin
namespace orxonox
{
+ /**
+ @brief This class is used to execute and evaluate command-strings.
+
+ CommandExecutor executes command-strings and returns evaluated commands. It's
+ also possible to execute Tcl commands if the corresponding argument of execute()
+ is true.
+
+ @see See @ref CommandExecutorExample "this description" for more information and some examples.
+ */
class _CoreExport CommandExecutor
{
// tolua_end
@@ -52,34 +117,35 @@
static CommandEvaluation evaluate(const std::string& command);
- static const int Success = 0;
- static const int Error = 1;
- static const int Incomplete = 2;
- static const int Deactivated = 3;
- static const int Denied = 4;
+ static const int Success = 0; ///< Error code for "success" (or no error)
+ static const int Error = 1; ///< Error code if the command doesn't exist
+ static const int Incomplete = 2; ///< Error code if the command needs more arguments
+ static const int Deactivated = 3; ///< Error code if the command is not active
+ static const int Denied = 4; ///< Error code if the command needs a different access level
static MultiType unhide(const std::string& command);
static void alias(const std::string& alias, const std::string& command);
- static void _autocomplete(const std::string& group, const std::string& name) {}
+ static void _autocomplete(const std::string& group, const std::string& name) {} ///< Pseudo console command used whenever no real command is available. In these cases this command provides auto-completion for console commands and groups.
private:
- CommandExecutor() {}
- CommandExecutor(const CommandExecutor& other);
- ~CommandExecutor() {}
+ CommandExecutor() {} ///< Empty constructor
+ CommandExecutor(const CommandExecutor& other); ///< Not implemented copy-constructor
+ ~CommandExecutor() {} ///< Empty destructor
static CommandExecutor& getInstance();
bool getCached(const std::string& command, CommandEvaluation& evaluation);
void cache(const std::string& command, const CommandEvaluation& evaluation);
+ /// Helper struct, used to store cached entries
struct CacheEntry
{
- CommandEvaluation evaluation_;
- std::list<std::string>::iterator iterator_;
+ CommandEvaluation evaluation_; ///< The command evaluation which is stored in the cache
+ std::list<std::string>::iterator iterator_; ///< The iterator of the corresponding element in cachelist_, used for faster access
};
- std::map<std::string, CacheEntry> cache_;
- std::list<std::string> cachelist_;
+ std::map<std::string, CacheEntry> cache_; ///< A map that connects command strings and evaluated commands in the cache
+ std::list<std::string> cachelist_; ///< A list used to sort the elements in the cache by their age
}; // tolua_export
} // tolua_export
Modified: code/branches/doc/src/libraries/core/command/ConsoleCommand.cc
===================================================================
--- code/branches/doc/src/libraries/core/command/ConsoleCommand.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ConsoleCommand.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,11 @@
*
*/
+/**
+ @file
+ @brief Implementation of the ConsoleCommand class.
+*/
+
#include "ConsoleCommand.h"
#include "util/Convert.h"
@@ -35,6 +40,13 @@
namespace orxonox
{
+ /**
+ @brief Constructor: Initializes all values and registers the command.
+ @param group The group of the command
+ @param name The name of the command
+ @param executor The executor of the command
+ @param bInitialized If true, the executor is used for both, the definition of the function-header AND to executute the command. If false, the command is inactive and needs to be assigned a function before it can be used.
+ */
ConsoleCommand::ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
{
this->bActive_ = true;
@@ -44,11 +56,8 @@
this->baseName_ = name;
this->baseFunctor_ = executor->getFunctor();
- this->argumentCompleter_[0] = 0;
- this->argumentCompleter_[1] = 0;
- this->argumentCompleter_[2] = 0;
- this->argumentCompleter_[3] = 0;
- this->argumentCompleter_[4] = 0;
+ for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
+ this->argumentCompleter_[i] = 0;
this->keybindMode_ = KeybindMode::OnPress;
this->inputConfiguredParam_ = -1;
@@ -59,40 +68,67 @@
ConsoleCommand::registerCommand(group, name, this);
}
+ /**
+ @brief Destructor: Unregisters the command.
+ */
ConsoleCommand::~ConsoleCommand()
{
ConsoleCommand::unregisterCommand(this);
}
+ /**
+ @brief Registers the command with the same name, but without group, as shortcut.
+ */
ConsoleCommand& ConsoleCommand::addShortcut()
{
ConsoleCommand::registerCommand("", this->baseName_, this);
return *this;
}
+ /**
+ @brief Registers the command with an alias as shortcut.
+ */
ConsoleCommand& ConsoleCommand::addShortcut(const std::string& name)
{
ConsoleCommand::registerCommand("", name, this);
return *this;
}
+ /**
+ @brief Registers the command in a different group but with the same name.
+ */
ConsoleCommand& ConsoleCommand::addGroup(const std::string& group)
{
ConsoleCommand::registerCommand(group, this->baseName_, this);
return *this;
}
+ /**
+ @brief Registers an alias of the command in a different group with a different name.
+ */
ConsoleCommand& ConsoleCommand::addGroup(const std::string& group, const std::string& name)
{
ConsoleCommand::registerCommand(group, name, this);
return *this;
}
+ /**
+ @brief Returns true if the command can be executed right now.
+
+ This returns only true, if the following conditions are met:
+ - The command is active
+ - The command has an executor
+ - The executor has a functor
+ - The functor is static or has an object
+ */
bool ConsoleCommand::isActive() const
{
return (this->bActive_ && this->executor_ && this->executor_->getFunctor() && (this->executor_->getFunctor()->getType() == Functor::Type::Static || this->executor_->getFunctor()->getRawObjectPointer()));
}
+ /**
+ @brief Returns true if the current state of the game matches the required access level.
+ */
bool ConsoleCommand::hasAccess() const
{
switch (this->accessLevel_)
@@ -109,16 +145,24 @@
}
}
+ /**
+ @brief Returns true if the headers of the given functor match the declaration of this command.
+ */
bool ConsoleCommand::headersMatch(const FunctorPtr& functor)
{
+ // get the minimum of the number of parameters of both commands
unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), functor->getParamCount());
+ // if the reduced headers don't match -> return false
if (this->baseFunctor_->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
return false;
+ // if the reduced headers match and the new functor has less or equal parameters -> return true
else if (functor->getParamCount() <= this->baseFunctor_->getParamCount())
return true;
+ // the headers match but the new functor has more arguments and there is no executor with default-values -> return false
else if (!this->executor_)
return false;
+ // the headers match but the new functor has more arguments, check if the executor has enough default-values
else
{
for (unsigned int i = this->baseFunctor_->getParamCount(); i < functor->getParamCount(); ++i)
@@ -134,14 +178,21 @@
}
}
+ /**
+ @brief Returns true if the headers of the given executor match the declaration of this command.
+ */
bool ConsoleCommand::headersMatch(const ExecutorPtr& executor)
{
+ // get the minimum of the number of parameters of both commands
unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), executor->getParamCount());
+ // if the reduced headers don't match -> return false
if (this->baseFunctor_->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
return false;
+ // if the reduced headers match and the new functor has less or equal parameters -> return true
else if (executor->getParamCount() <= this->baseFunctor_->getParamCount())
return true;
+ // the headers match but the new functor has more arguments, check if the new executor has enough default-values
else
{
for (unsigned int i = this->baseFunctor_->getParamCount(); i < executor->getParamCount(); ++i)
@@ -157,10 +208,18 @@
}
}
+ /**
+ @brief Changes the executor.
+ @param executor The new executor
+ @param bForce If true, the executor is always assigned, even if the headers don't match
+ @return Returns true if the assignment was successful
+ */
bool ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
{
+ // assign the executor if a) it's a null-pointer, b) its functor is a null-pointer, c) it's forced, d) the headers match
if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
{
+ // assign the executor and clear the object stack (because it's also a new function)
this->executor_ = executor;
this->objectStack_.clear();
return true;
@@ -172,10 +231,18 @@
}
}
+ /**
+ @brief Changes the functor of the current executor.
+ @param functor The new functor
+ @param bForce If true, the functor is always assigned, even if the headers don't match
+ @return Returns true if the assignment was successful
+ */
bool ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
{
+ // assign the functor if a) it's a null-pointer, b) it's forced, c) the headers match
if (!functor || bForce || this->headersMatch(functor))
{
+ // assign the functor (create a new executor if necessary) and clear the object stack
if (this->executor_)
this->executor_->setFunctor(functor);
else if (functor)
@@ -191,30 +258,47 @@
}
}
+ /**
+ @brief Pushes a new executor to the command-stack.
+ @param executor The new executor
+ @param bForce If true, the executor is always assigned, even if the headers don't match
+ */
void ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
{
+ // prepare the old function to be put on the stack
Command command;
command.executor_ = this->executor_;
if (command.executor_)
command.functor_ = this->executor_->getFunctor();
command.objectStack_ = this->objectStack_;
+ // check if the new executor can be assigned and push the old function to the stack
if (this->setFunction(executor, bForce))
this->commandStack_.push(command);
}
+ /**
+ @brief Pushes a new functor to the command-stack.
+ @param functor The new functor
+ @param bForce If true, the functor is always assigned, even if the headers don't match
+ */
void ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
{
+ // prepare the old function to be put on the stack
Command command;
command.executor_ = this->executor_;
if (command.executor_)
command.functor_ = this->executor_->getFunctor();
command.objectStack_ = this->objectStack_;
+ // check if the new functor can be assigned and push the old function to the stack
if (this->setFunction(functor, bForce))
this->commandStack_.push(command);
}
+ /**
+ @brief Pushes a copy of the current executor and functor on the stack.
+ */
void ConsoleCommand::pushFunction()
{
if (this->executor_)
@@ -223,21 +307,31 @@
COUT(1) << "Error: Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
}
+ /**
+ @brief Removes the current function from the stack and restores the old state.
+ */
void ConsoleCommand::popFunction()
{
Command command;
+
+ // check if there's a function on the stack
if (!this->commandStack_.empty())
{
+ // yes it is - assign it to command and remove it from the stack
command = this->commandStack_.top();
this->commandStack_.pop();
}
+ // restore the old executor (and also restore its functor in case this was changed in the meantime)
this->executor_ = command.executor_;
if (command.executor_)
this->executor_->setFunctor(command.functor_);
this->objectStack_ = command.objectStack_;
}
+ /**
+ @brief Sets the functor to NULL (which also deactivates the command).
+ */
void ConsoleCommand::resetFunction()
{
if (this->executor_)
@@ -245,17 +339,27 @@
this->objectStack_.clear();
}
+ /**
+ @brief Returns the current executor which can be used to execute the command.
+ */
const ExecutorPtr& ConsoleCommand::getExecutor() const
{
return this->executor_;
}
+ /**
+ @brief Changes the current object that is used to execute member-functions.
+ @return Returns true if the object was successfully changed
+ */
bool ConsoleCommand::setObject(void* object)
{
+ // check if there's an executor
if (this->executor_)
{
+ // check if there's a functor
if (this->executor_->getFunctor())
{
+ // change the object
this->executor_->getFunctor()->setRawObjectPointer(object);
return true;
}
@@ -268,6 +372,9 @@
return false;
}
+ /**
+ @brief Push a new object to the object-stack.
+ */
void ConsoleCommand::pushObject(void* object)
{
void* oldobject = this->getObject();
@@ -275,6 +382,9 @@
this->objectStack_.push_back(oldobject);
}
+ /**
+ @brief Removes the current object from the stack an restores the old object.
+ */
void ConsoleCommand::popObject()
{
void* newobject = 0;
@@ -286,6 +396,9 @@
this->setObject(newobject);
}
+ /**
+ @brief Returns the current object pointer that is used to execute member-functions.
+ */
void* ConsoleCommand::getObject() const
{
if (this->executor_ && this->executor_->getFunctor())
@@ -294,84 +407,115 @@
return 0;
}
- ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1)
+ /**
+ @brief Changes the default values of the current executor.
+ */
+ ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1)
{
if (this->executor_)
- this->executor_->setDefaultValues(param1);
+ this->executor_->setDefaultValues(arg1);
else
COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
return *this;
}
- ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2)
+ /**
+ @brief Changes the default values of the current executor.
+ */
+ ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2)
{
if (this->executor_)
- this->executor_->setDefaultValues(param1, param2);
+ this->executor_->setDefaultValues(arg1, arg2);
else
COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
return *this;
}
- ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
+ /**
+ @brief Changes the default values of the current executor.
+ */
+ ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
{
if (this->executor_)
- this->executor_->setDefaultValues(param1, param2, param3);
+ this->executor_->setDefaultValues(arg1, arg2, arg3);
else
COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
return *this;
}
- ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
+ /**
+ @brief Changes the default values of the current executor.
+ */
+ ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
{
if (this->executor_)
- this->executor_->setDefaultValues(param1, param2, param3, param4);
+ this->executor_->setDefaultValues(arg1, arg2, arg3, arg4);
else
COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
return *this;
}
- ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
+ /**
+ @brief Changes the default values of the current executor.
+ */
+ ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
{
if (this->executor_)
- this->executor_->setDefaultValues(param1, param2, param3, param4, param5);
+ this->executor_->setDefaultValues(arg1, arg2, arg3, arg4, arg5);
else
COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
return *this;
}
- ConsoleCommand& ConsoleCommand::defaultValue(unsigned int index, const MultiType& param)
+ /**
+ @brief Changes the default value of the argument with given index of the current executor.
+ @param index The index of the argument (the first argument has index 0)
+ @param arg The new default value
+ */
+ ConsoleCommand& ConsoleCommand::defaultValue(unsigned int index, const MultiType& arg)
{
if (this->executor_)
- this->executor_->setDefaultValue(index, param);
+ this->executor_->setDefaultValue(index, arg);
else
COUT(1) << "Error: Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << std::endl;
return *this;
}
- ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int param, ArgumentCompleter* completer)
+ /**
+ @brief Changes the argument completer for the given argument.
+ @param index The index of the argument (the first argument has index 0)
+ @param completer The new argument completer
+ */
+ ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int index, ArgumentCompleter* completer)
{
- if (param < 5)
- this->argumentCompleter_[param] = completer;
+ if (index < 5)
+ this->argumentCompleter_[index] = completer;
else
- COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
+ COUT(2) << "Warning: Couldn't add autocompletion-function for index " << index << " in console command \"" << this->baseName_ << "\": index out of bound." << std::endl;
return *this;
}
- ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
+ /**
+ @brief Returns the argument completer for the argument with given index.
+ */
+ ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int index) const
{
- if (param < 5)
- return this->argumentCompleter_[param];
+ if (index < 5)
+ return this->argumentCompleter_[index];
else
return 0;
}
+ /**
+ @brief Sets the description of this command.
+ */
ConsoleCommand& ConsoleCommand::description(const std::string& description)
{
this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
@@ -379,29 +523,41 @@
return *this;
}
+ /**
+ @brief Returns the description of this command.
+ */
const std::string& ConsoleCommand::getDescription() const
{
return GetLocalisation_noerror(this->description_);
}
- ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int param, const std::string& description)
+ /**
+ @brief Sets the description for an argument with given index.
+ */
+ ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int index, const std::string& description)
{
- if (param < MAX_FUNCTOR_ARGUMENTS)
+ if (index < MAX_FUNCTOR_ARGUMENTS)
{
- this->descriptionParam_[param] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(param));
- AddLanguageEntry(this->descriptionParam_[param], description);
+ this->descriptionParam_[index] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(index));
+ AddLanguageEntry(this->descriptionParam_[index], description);
}
return *this;
}
- const std::string& ConsoleCommand::getDescriptionParam(unsigned int param) const
+ /**
+ @brief Returns the description for the argument with given index.
+ */
+ const std::string& ConsoleCommand::getDescriptionParam(unsigned int index) const
{
- if (param < MAX_FUNCTOR_ARGUMENTS)
- return GetLocalisation_noerror(this->descriptionParam_[param]);
+ if (index < MAX_FUNCTOR_ARGUMENTS)
+ return GetLocalisation_noerror(this->descriptionParam_[index]);
return this->descriptionParam_[0];
}
+ /**
+ @brief Sets the description for the return-value.
+ */
ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
{
this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
@@ -409,19 +565,31 @@
return *this;
}
- const std::string& ConsoleCommand::getDescriptionReturnvalue(int param) const
+ /**
+ @brief Returns the description for the return-value.
+ */
+ const std::string& ConsoleCommand::getDescriptionReturnvalue(int index) const
{
return GetLocalisation_noerror(this->descriptionReturnvalue_);
}
+ /**
+ @brief Returns the command with given group an name.
+ @param group The group of the requested command
+ @param name The group of the requested command
+ @param bPrintError If true, an error is printed if the command doesn't exist
+ */
/* static */ const ConsoleCommand* ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
{
+ // find the group
std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMap().find(group);
if (it_group != ConsoleCommand::getCommandMap().end())
{
+ // find the name
std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
if (it_name != it_group->second.end())
{
+ // return the pointer
return it_name->second;
}
}
@@ -435,17 +603,26 @@
return 0;
}
+ /**
+ @brief Returns the command with given group an name in lowercase.
+ @param group The group of the requested command in lowercase
+ @param name The group of the requested command in lowercase
+ @param bPrintError If true, an error is printed if the command doesn't exist
+ */
/* static */ const ConsoleCommand* ConsoleCommand::getCommandLC(const std::string& group, const std::string& name, bool bPrintError)
{
std::string groupLC = getLowercase(group);
std::string nameLC = getLowercase(name);
+ // find the group
std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMapLC().find(groupLC);
if (it_group != ConsoleCommand::getCommandMapLC().end())
{
+ // find the name
std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(nameLC);
if (it_name != it_group->second.end())
{
+ // return the pointer
return it_name->second;
}
}
@@ -459,23 +636,33 @@
return 0;
}
+ /**
+ @brief Returns the static map that stores all console commands.
+ */
/* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMap()
{
static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMap;
return commandMap;
}
+ /**
+ @brief Returns the static map that stores all console commands in lowercase.
+ */
/* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMapLC()
{
static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMapLC;
return commandMapLC;
}
+ /**
+ @brief Registers a new command with given group an name by adding it to the command map.
+ */
/* static */ void ConsoleCommand::registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command)
{
if (name == "")
return;
+ // check if a command with this name already exists
if (ConsoleCommand::getCommand(group, name) != 0)
{
if (group == "")
@@ -485,39 +672,53 @@
}
else
{
+ // add the command to the map
ConsoleCommand::getCommandMap()[group][name] = command;
ConsoleCommand::getCommandMapLC()[getLowercase(group)][getLowercase(name)] = command;
}
}
+ /**
+ @brief Removes the command from the command map.
+ */
/* static */ void ConsoleCommand::unregisterCommand(ConsoleCommand* command)
{
+ // iterate through all groups
for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMap().begin(); it_group != ConsoleCommand::getCommandMap().end(); )
{
+ // iterate through all commands of each group
for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
{
+ // erase the command
if (it_name->second == command)
it_group->second.erase(it_name++);
else
++it_name;
}
+ // erase the group if it is empty now
if (it_group->second.empty())
ConsoleCommand::getCommandMap().erase(it_group++);
else
++it_group;
}
+ // now the same for the lowercase-map:
+
+ // iterate through all groups
for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMapLC().begin(); it_group != ConsoleCommand::getCommandMapLC().end(); )
{
+ // iterate through all commands of each group
for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
{
+ // erase the command
if (it_name->second == command)
it_group->second.erase(it_name++);
else
++it_name;
}
+ // erase the group if it is empty now
if (it_group->second.empty())
ConsoleCommand::getCommandMapLC().erase(it_group++);
else
@@ -525,8 +726,12 @@
}
}
+ /**
+ @brief Deletes all commands
+ */
/* static */ void ConsoleCommand::destroyAll()
{
+ // delete entries until the map is empty
while (!ConsoleCommand::getCommandMap().empty() && !ConsoleCommand::getCommandMap().begin()->second.empty())
delete ConsoleCommand::getCommandMap().begin()->second.begin()->second;
}
Modified: code/branches/doc/src/libraries/core/command/ConsoleCommand.h
===================================================================
--- code/branches/doc/src/libraries/core/command/ConsoleCommand.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ConsoleCommand.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,194 @@
*
*/
+/**
+ @defgroup ConsoleCommand Console commands
+ @ingroup Command
+*/
+
+/**
+ @file
+ @ingroup Command ConsoleCommand
+ @brief Declaration of the orxonox::ConsoleCommand class and the SetConsoleCommand() macro.
+
+ @anchor ConsoleCommandExample
+
+ Console commands can be used to write scripts, use key-bindings or simply to be
+ entered into the shell by the user. Instances of orxonox::ConsoleCommand define
+ the function of a command, and also more information like, for example, if it is
+ active, default values, and possible arguments.
+
+ Commands need to be registered to the system statically on startup by using the
+ SetConsoleCommand() or DeclareConsoleCommand() macros outside of a function.
+ This ensures that commands are known to the system at any time, so they can be
+ evaluated (see orxonox::CommandExecutor::evaluate()), for example for key-bindings.
+
+ Example:
+ @code
+ void myCoutFunction(const std::string& text) // Define a static function
+ {
+ COUT(0) << "Text: " << text << std::endl; // Print the text to the console
+ }
+
+ SetConsoleCommand("cout", &myCoutFunction); // Register the function as command with name "cout"
+ @endcode
+
+ Now you can open the shell and execute the command:
+ @code
+ $ cout Hello World
+ @endcode
+
+ Internally this command is now passed to orxonox::CommandExecutor::execute():
+ @code
+ CommandExecutor::execute("cout HelloWorld");
+ @endcode
+
+ CommandExecutor searches for a command with name "cout" and passes the arguments
+ "Hello World" to it. Because we registered myCoutFunction() with this command,
+ as a result the following text will be printed to the console:
+ @code
+ Text: Hello World
+ @endcode
+
+ You can add more attributes to the ConsoleCommand, by using the command-chain feature
+ of SetConsoleCommand(). For example like this:
+ @code
+ SetConsoleCommand("cout", &myCoutFunction)
+ .addGroup("output", "text")
+ .accessLevel(AccessLevel::Offline)
+ .defaultValues("no text");
+ @endcode
+
+ Open the shell again and try it:
+ @code
+ $ cout Hello World
+ Text: Hello World
+ $ output text Hello World
+ Text: Hello World
+ $ cout
+ Text: no text
+ @endcode
+
+ If you execute it online (note: the access level is "Offline"), you will see the
+ following (or something similar):
+ @code
+ $ cout Hello World
+ Error: Can't execute command "cout", access denied.
+ @endcode
+
+ If a command is executed, the arguments are passed to an underlying function,
+ whitch is wrapped by an orxonox::Functor which again is wrapped by an orxonox::Executor.
+ The Functor contains the function-pointer, as well as the object-pointer in
+ case of a non-static member-function. The executor stores possible default-values
+ for each argument of the function.
+
+ The function of a command can be changed at any time. It's possible to just exchange
+ the function-pointer of the underlying Functor if the headers of the functions are
+ exactly the same. But you can also exchange the Functor itself or even completely
+ replace the Executor. Also the other attributes of a ConsoleCommand can be modified
+ during the game, for example it can be activated or deactivated.
+
+ To do so, the function ModifyConsoleCommand() has to be used. It returns an instance
+ of orxonox::ConsoleCommand::ConsoleCommandManipulator which has an interface similar to
+ orxonox::ConsoleCommand, but with slight differences. You can use it the same way like
+ SetConsoleCommand(), meaning you can use command-chains to change different attributes at
+ the same time. ModifyConsoleCommand() must not be executed statically, but rather in a
+ function at some point of the execution of the program.
+
+ Example:
+ @code
+ void myOtherCoutFunction(const std::string& text) // Define a new static function
+ {
+ COUT(0) << "Uppercase: " << getUppercase(text) << std::endl; // Print the text in uppercase to the console
+ }
+
+ {
+ // ... // somewhere in the code
+
+ ModifyConsoleCommand("cout").setFunction(&myOtherCoutFunction); // Modify the underlying function of the command
+
+ // ...
+ }
+ @endcode
+
+ If you now enter the command into the shell, you'll see a different behavior:
+ @code
+ $ cout Hello World
+ Uppercase: HELLO WORLD
+ $ cout
+ Uppercase: NO TEXT
+ @endcode
+
+ A few important notes about changing functions:
+
+ Instead of changing the function with setFunction(), you can also create a command-stack
+ by using pushFunction() and popFunction(). It's important to note a few things about that,
+ because the underlying structure of Executor and Functor has a few pitfalls:
+ - If you push a new function-pointer, the same executor as before will be used (and, if
+ the headers match, even the same functor can be used, which is very fast)
+ - If you push a new Functor, the same executor as before will be used
+ - If you push a new Executor, everything is changed
+
+ Note that the executor contains the @b default @b values, so if you just exchange the
+ Functor, the default values remain the same. However if you decide to change the default
+ values at any point of the stack, <b>this will also change the default values on all
+ other stack-levels</b> that share the same executor. If you don't like this behavior,
+ you have to explicitly push a new executor before changing the default values, either by
+ calling pushFunction(executor) or by calling pushFunction(void) which pushes a copy of
+ the current executor to the stack.
+
+ Another important point are object pointers in case of non-static member-functions.
+ Whenever you set or push a new function, <b>you must add the object pointer again</b>
+ because objects are stored in the Functor which is usually exchanged if you change
+ the function.
+
+ You can also use a stack for objects, but note that this <b>object-stack is different for each
+ function</b> - so if you set a new function, the object-stack will be cleared. If you push
+ a new function, the old object-stack is stored in the stack, so it can be restored if
+ you pop the function.
+
+ %DeclareConsoleCommand():
+
+ Appart from SetConsoleCommand() you can also call DeclareConsoleCommand(). In contrast
+ to SetConsoleCommand(), this doesn't assign a function to the command. Indeed you have
+ to pass a function-pointer to DeclareConsoleCommand(), but it is only used to determine
+ the header of the future command-function. This allows to declare a command statically,
+ thus it's possible to evaluate key-bindings of this command, but the actual function
+ can be assigned at a later point.
+
+ Example:
+ @code
+ DeclareConsoleCommand("cout", &prototype::void__string);
+ @endcode
+
+ If you try to execute the command now, you see the following (or something similar):
+ @code
+ $ cout Hello World
+ Error: Can't execute command "cout", command is not active.
+ @endcode
+
+ You first have to assign a function to use the command:
+ @code
+ {
+ // ...
+
+ ModifyConsoleCommand("cout").setFunction(&myCoutFunction);
+
+ // ...
+ }
+ @endcode
+
+ Now you can use it:
+ @code
+ $ cout Hello World
+ Text: Hello World
+ @endcode
+
+ Note that the initial function prototype::void__string is defined in the namespace
+ orxonox::prototype. If there's no function with the desired header, you can extend
+ the collection of functions or simply use another function that has the same header.
+*/
+
#ifndef _ConsoleCommand_H__
#define _ConsoleCommand_H__
@@ -41,34 +229,89 @@
#include "Executor.h"
+/**
+ @brief Defines a console command. The macro is overloaded for 2-4 parameters.
+
+ This is an overloaded macro. Depending on the number of arguments a different
+ overloaded implementation of the macro will be chosen.
+
+ Console commands created with SetConsoleCommand() become active immediately and
+ the given function-pointer (and optionally the object) will be used to execute
+ the command.
+*/
#define SetConsoleCommand(...) \
BOOST_PP_EXPAND(BOOST_PP_CAT(SetConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+/**
+ @brief This macro is executed if you call SetConsoleCommand() with 2 arguments.
+ @param name The name (string) of the console command
+ @param functionpointer The function-pointer of the corresponding command-function
+*/
#define SetConsoleCommand2(name, functionpointer) \
SetConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
+/**
+ @brief This macro is executed if you call SetConsoleCommand() with 3 arguments.
+ @param group The group (string) of the console command
+ @param name The name (string) of the console command
+ @param functionpointer The function-pointer of the corresponding command-function
+*/
#define SetConsoleCommand3(group, name, functionpointer) \
SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
+/**
+ @brief This macro is executed if you call SetConsoleCommand() with 4 arguments.
+ @param group The group (string) of the console command
+ @param name The name (string) of the console command
+ @param functionpointer The function-pointer of the corresponding command-function
+ @param object The object that will be assigned to the command. Used for member-functions.
+*/
#define SetConsoleCommand4(group, name, functionpointer, object) \
SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
+/// Internal macro
#define SetConsoleCommandGeneric(group, name, functor) \
static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __LINE__) = (*orxonox::createConsoleCommand(group, name, orxonox::createExecutor(functor)))
+/**
+ @brief Declares a console command. The macro is overloaded for 2-3 parameters.
+
+ This is an overloaded macro. Depending on the number of arguments a different
+ overloaded implementation of the macro will be chosen.
+
+ Console commands created with DeclareConsoleCommand() don't use the the given
+ function-pointer to execute the command, it is only used to define the header
+ of the future command-function. The command is inactive until you manually
+ set a function with orxonox::ModifyConsoleCommand(). You can use a different
+ function-pointer than in the final command, as long as it has the same header.
+*/
#define DeclareConsoleCommand(...) \
BOOST_PP_EXPAND(BOOST_PP_CAT(DeclareConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+/**
+ @brief This macro is executed if you call DeclareConsoleCommand() with 2 arguments.
+ @param name The name (string) of the console command
+ @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
+*/
#define DeclareConsoleCommand2(name, functionpointer) \
DeclareConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
+/**
+ @brief This macro is executed if you call DeclareConsoleCommand() with 3 arguments.
+ @param group The group (string) of the console command
+ @param name The name (string) of the console command
+ @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
+*/
#define DeclareConsoleCommand3(group, name, functionpointer) \
DeclareConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
-#define DeclareConsoleCommand4(group, name, functionpointer, object) \
- DeclareConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
+/// Internal macro
#define DeclareConsoleCommandGeneric(group, name, functor) \
static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __LINE__) = (*orxonox::createConsoleCommand(group, name, orxonox::createExecutor(functor), false))
namespace orxonox
{
+ /**
+ @brief A small collection of functions that can be used in DeclareConsoleCommand() if
+ you don't want to use the real function-pointer.
+ */
namespace prototype
{
inline void void__void(void) {}
@@ -77,6 +320,9 @@
namespace AccessLevel
{
+ /**
+ @brief Possible access levels: A command can only be executed if the program is in the state which is requested by the access level.
+ */
enum Enum
{
All,
@@ -90,28 +336,56 @@
};
}
+ /**
+ @brief The ConsoleCommand class stores all information about a console command which can be executed by CommandExecutor.
+
+ Console commands can be entered by the user into the shell, called in scripts, or
+ used for key-bindings. They are simple text strings that can be executed by
+ CommandExecutor. CommandExecutor will search for a ConsoleCommand with the given
+ group and name and will execute it's Executor (which again calls the Functor and
+ this finally calls the command-function).
+
+ @see See @ref ConsoleCommandExample "ConsoleCommand.h" for more information and some examples.
+ */
class _CoreExport ConsoleCommand
{
friend struct ConsoleCommandManipulator;
+ /**
+ @brief Helper class that is used to put the current state of the ConsoleCommand on a stack.
+ */
struct Command
{
- ExecutorPtr executor_;
- FunctorPtr functor_;
- std::vector<void*> objectStack_;
+ ExecutorPtr executor_; ///< The executor
+ FunctorPtr functor_; ///< The function that is used with the executor - has to be stored separatley because the executor is often used with different functors
+ std::vector<void*> objectStack_; ///< The object stack
};
public:
+ /**
+ @brief Helper class that is used to manipulate console commands.
+
+ An instance of this class is returned if you call the ModifyConsoleCommand macro.
+ This class provides an interface which wraps some functions of ConsoleCommand. It
+ allows access to some private functions like setFunction() (that can't be called
+ right after SetConsoleCommand()) but it also hides some functions that shouln't be
+ called after the static declaration like addShortcut() or description().
+
+ @see See @ref ConsoleCommandExample "ConsoleCommand.h" for more information and examples.
+ */
struct ConsoleCommandManipulator
{
public:
+ /// Constructor: Creates a manipulator for a given ConsoleCommand.
ConsoleCommandManipulator(const ConsoleCommand* command) : command_(const_cast<ConsoleCommand*>(command)) {}
+ /// Changes the current function of the command. @param function The new function-pointer @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
template <class F>
inline ConsoleCommandManipulator& setFunction(F function, bool bForce = false)
{
if (this->command_)
{
+ // check if the headers match. If they do, only change the function-pointer of the current Functor instead of creating a new Functor
if (this->command_->getExecutor() && this->command_->getExecutor()->getFunctor() && this->command_->getExecutor()->getFunctor()->getFullIdentifier() == typeid(F))
{
FunctorPointer<F>* functor = static_cast<FunctorPointer<F>*>(this->command_->getExecutor()->getFunctor().get());
@@ -122,11 +396,13 @@
}
return *this;
}
+ /// Changes the current function of the command. @param function The new function-pointer @param object The new object-pointer (for member-functions) @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
template <class F, class O>
inline ConsoleCommandManipulator& setFunction(F function, O* object, bool bForce = false)
{
if (this->command_)
{
+ // check if the headers match. If they do, only change the function-pointer of the current Functor instead of creating a new Functor
if (this->command_->getExecutor() && this->command_->getExecutor()->getFunctor() && this->command_->getExecutor()->getFunctor()->getFullIdentifier() == typeid(F))
{
FunctorPointer<F, O>* functor = static_cast<FunctorPointer<F, O>*>(this->command_->getExecutor()->getFunctor().get());
@@ -138,79 +414,108 @@
}
return *this;
}
+ /// Changes the current Functor of the command. @param functor The new Functor @param bForce If true, the new Functor is always assigned, even if the headers don't match
inline ConsoleCommandManipulator& setFunction(const FunctorPtr& functor, bool bForce = false)
{ if (this->command_) { this->command_->setFunction(functor, bForce); } return *this; }
+ /// Changes the current Executor of the command. @param executor The new Executor @param bForce If true, the new Executor is always assigned, even if the headers don't match
inline ConsoleCommandManipulator& setFunction(const ExecutorPtr& executor, bool bForce = false)
{ if (this->command_) { this->command_->setFunction(executor, bForce); } return *this; }
+ /// Pushes a copy of the current Executor on the command-stack, that can be altered without changing the old Executor. @details This function is especially useful if you don't wan't to change the function, but only the default values of the executor.
inline ConsoleCommandManipulator& pushFunction()
{ if (this->command_) { this->command_->pushFunction(); } return *this; }
+ /// Pushes a new function on the command-stack. @param function The new function-pointer @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
template <class F>
inline ConsoleCommandManipulator& pushFunction(F function, bool bForce = false)
{ if (this->command_) { this->command_->pushFunction(createFunctor(function), bForce); } return *this; }
+ /// Pushes a new function on the command-stack. @param function The new function-pointer @param object The new object-pointer (for member-functions) @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
template <class F, class O>
inline ConsoleCommandManipulator& pushFunction(F function, O* object, bool bForce = false)
{ if (this->command_) { this->command_->pushFunction(createFunctor(function, object), bForce); } return *this; }
+ /// Pushes a new Functor on the command-stack. @param functor The new Functor @param bForce If true, the new Functor is always assigned, even if the headers don't match
inline ConsoleCommandManipulator& pushFunction(const FunctorPtr& functor, bool bForce = false)
{ if (this->command_) { this->command_->pushFunction(functor, bForce); } return *this; }
+ /// Pushes a new Executor on the command-stack. @param executor The new Executor @param bForce If true, the new Executor is always assigned, even if the headers don't match
inline ConsoleCommandManipulator& pushFunction(const ExecutorPtr& executor, bool bForce = false)
{ if (this->command_) { this->command_->pushFunction(executor, bForce); } return *this; }
+ /// Removes the current function from the stack and restores the old state. If there's no other function on the stack, the command is deactivated.
inline ConsoleCommandManipulator& popFunction()
{ if (this->command_) { this->command_->popFunction(); } return *this; }
+ /// Sets the current function-pointer to NULL, which also deactivates the command.
inline ConsoleCommandManipulator& resetFunction()
{ if (this->command_) { this->command_->resetFunction(); } return *this; }
+ /// Changes the current object (used for member-functions).
inline ConsoleCommandManipulator& setObject(void* object)
{ if (this->command_) { this->command_->setObject(object); } return *this; }
+ /// Pushes a new object on the object-stack.
inline ConsoleCommandManipulator& pushObject(void* object)
{ if (this->command_) { this->command_->pushObject(object); } return *this; }
+ /// Removes the current object from the object-stack and restores the old object (or NULL if there's no object left on the stack).
inline ConsoleCommandManipulator& popObject()
{ if (this->command_) { this->command_->popObject(); } return *this; }
+ /// Changes the activity of the command.
inline ConsoleCommandManipulator& setActive(bool bActive)
{ if (this->command_) { this->command_->setActive(bActive); } return *this; }
+ /// Activates the command.
inline ConsoleCommandManipulator& activate()
{ return this->setActive(true); }
+ /// Deactivates the command.
inline ConsoleCommandManipulator& deactivate()
{ return this->setActive(false); }
+ /// Changes the visibility of the command.
inline ConsoleCommandManipulator& setHidden(bool bHidden)
{ if (this->command_) { this->command_->setHidden(bHidden); } return *this; }
+ /// Hides the command (can still be executed, but is not visible in the list of available commands).
inline ConsoleCommandManipulator& hide()
{ return this->setHidden(true); }
+ /// Makes the command visible.
inline ConsoleCommandManipulator& show()
{ return this->setHidden(false); }
- inline ConsoleCommandManipulator& defaultValues(const MultiType& param1)
- { if (this->command_) { this->command_->defaultValues(param1); } return *this; }
- inline ConsoleCommandManipulator& defaultValues(const MultiType& param1, const MultiType& param2)
- { if (this->command_) { this->command_->defaultValues(param1, param2); } return *this; }
- inline ConsoleCommandManipulator& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
- { if (this->command_) { this->command_->defaultValues(param1, param2, param3); } return *this; }
- inline ConsoleCommandManipulator& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
- { if (this->command_) { this->command_->defaultValues(param1, param2, param3, param4); } return *this; }
- inline ConsoleCommandManipulator& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
- { if (this->command_) { this->command_->defaultValues(param1, param2, param3, param4, param5); } return *this; }
- inline ConsoleCommandManipulator& defaultValue(unsigned int index, const MultiType& param)
- { if (this->command_) { this->command_->defaultValue(index, param); } return *this; }
+ /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+ inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1)
+ { if (this->command_) { this->command_->defaultValues(arg1); } return *this; }
+ /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+ inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2)
+ { if (this->command_) { this->command_->defaultValues(arg1, arg2); } return *this; }
+ /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+ inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
+ { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3); } return *this; }
+ /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+ inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
+ { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3, arg4); } return *this; }
+ /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+ inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
+ { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3, arg4, arg5); } return *this; }
+ /// Changes the default value of the argument with given index of the current executor (doesn't modify executors on deeper levels of the command-stack).
+ inline ConsoleCommandManipulator& defaultValue(unsigned int index, const MultiType& arg)
+ { if (this->command_) { this->command_->defaultValue(index, arg); } return *this; }
+ /// Changes the access level of the command.
inline ConsoleCommandManipulator& accessLevel(AccessLevel::Enum level)
{ if (this->command_) { this->command_->accessLevel(level); } return *this; }
- inline ConsoleCommandManipulator& argumentCompleter(unsigned int param, ArgumentCompleter* completer)
- { if (this->command_) { this->command_->argumentCompleter(param, completer); } return *this; }
+ /// Changes the argument completer for the given parameter.
+ inline ConsoleCommandManipulator& argumentCompleter(unsigned int index, ArgumentCompleter* completer)
+ { if (this->command_) { this->command_->argumentCompleter(index, completer); } return *this; }
+ /// Defines the command to be an input command.
inline ConsoleCommandManipulator& setAsInputCommand()
{ if (this->command_) { this->command_->setAsInputCommand(); } return *this; }
+ /// Changes the keybind mode of the command.
inline ConsoleCommandManipulator& keybindMode(KeybindMode::Value mode)
{ if (this->command_) { this->command_->keybindMode(mode); } return *this; }
+ /// Sets the input configured param to the given index.
inline ConsoleCommandManipulator& inputConfiguredParam(int index)
{ if (this->command_) { this->command_->inputConfiguredParam(index); } return *this; }
private:
- ConsoleCommand* command_;
+ ConsoleCommand* command_; ///< The command which is being manipulated by this object
};
public:
@@ -222,56 +527,68 @@
ConsoleCommand& addGroup(const std::string& group);
ConsoleCommand& addGroup(const std::string& group, const std::string& name);
+ /// Returns the name that was first used for this command.
inline const std::string& getName() const
{ return this->baseName_; }
const ExecutorPtr& getExecutor() const;
+ /// Returns the functor that defines the required header for this command (but isn't necessarily executed).
inline const FunctorPtr& getBaseFunctor() const
{ return this->baseFunctor_; }
+ /// Changes the activity of the command.
inline ConsoleCommand& setActive(bool bActive)
{ this->bActive_ = bActive; return *this; }
+ /// Activates the command.
inline ConsoleCommand& activate()
{ return this->setActive(true); }
+ /// Deactivates the command.
inline ConsoleCommand& deactivate()
{ return this->setActive(false); }
+ /// Changes the visibility of the command.
inline ConsoleCommand& setHidden(bool bHidden)
{ this->bHidden_ = bHidden; return *this; }
+ /// Hides the command (can still be executed, but is not visible in the list of available commands).
inline ConsoleCommand& hide()
{ return this->setHidden(true); }
+ /// Makes the command visible.
inline ConsoleCommand& show()
{ return this->setHidden(false); }
bool isActive() const;
bool hasAccess() const;
+ /// Returns true if the command is currently hidden.
inline bool isHidden() const
{ return this->bHidden_; }
ConsoleCommand& description(const std::string& description);
const std::string& getDescription() const;
- ConsoleCommand& descriptionParam(unsigned int param, const std::string& description);
- const std::string& getDescriptionParam(unsigned int param) const;
+ ConsoleCommand& descriptionParam(unsigned int index, const std::string& description);
+ const std::string& getDescriptionParam(unsigned int index) const;
ConsoleCommand& descriptionReturnvalue(const std::string& description);
- const std::string& getDescriptionReturnvalue(int param) const;
+ const std::string& getDescriptionReturnvalue(int index) const;
- ConsoleCommand& defaultValues(const MultiType& param1);
- ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2);
- ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3);
- ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4);
- ConsoleCommand& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5);
- ConsoleCommand& defaultValue(unsigned int index, const MultiType& param);
+ ConsoleCommand& defaultValues(const MultiType& arg1);
+ ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2);
+ ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3);
+ ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4);
+ ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5);
+ ConsoleCommand& defaultValue(unsigned int index, const MultiType& arg);
+ /// Changes the access level of the command.
inline ConsoleCommand& accessLevel(AccessLevel::Enum level)
{ this->accessLevel_ = level; return *this; }
+ /// Returns the access level of the command.
inline AccessLevel::Enum getAccessLevel() const
{ return this->accessLevel_; }
- ConsoleCommand& argumentCompleter(unsigned int param, ArgumentCompleter* completer);
- ArgumentCompleter* getArgumentCompleter(unsigned int param) const;
+ ConsoleCommand& argumentCompleter(unsigned int index, ArgumentCompleter* completer);
+ ArgumentCompleter* getArgumentCompleter(unsigned int index) const;
+ /// Defines the command to be an input command
inline ConsoleCommand& setAsInputCommand()
{
this->keybindMode(KeybindMode::OnHold);
@@ -280,16 +597,21 @@
return *this;
}
+ /// Changes the keybind mode.
inline ConsoleCommand& keybindMode(KeybindMode::Value mode)
{ this->keybindMode_ = mode; return *this; }
+ /// Returns the keybind mode
inline KeybindMode::Value getKeybindMode() const
{ return this->keybindMode_; }
+ /// Changes the input configured param to the given index.
inline ConsoleCommand& inputConfiguredParam(int index)
{ this->inputConfiguredParam_ = index; return *this; }
+ /// Returns the input configured param.
inline int getInputConfiguredParam_() const
{ return this->inputConfiguredParam_; }
+ /// Returns a manipulator for this command.
inline ConsoleCommandManipulator getManipulator() const
{ return this; }
@@ -310,33 +632,37 @@
void popObject();
void* getObject() const;
- bool bActive_;
- bool bHidden_;
- AccessLevel::Enum accessLevel_;
- std::string baseName_;
- FunctorPtr baseFunctor_;
+ bool bActive_; ///< True if the command should be active (it can still be inactive, for example if the function is missing)
+ bool bHidden_; ///< True if the command is hidden (it is still executable, but not visible in the list of available commands)
+ AccessLevel::Enum accessLevel_; ///< The access level (the state of the game in which you can access the command)
+ std::string baseName_; ///< The name that was first assigned to the command
+ FunctorPtr baseFunctor_; ///< The functor that defines the header of the command-function
- ExecutorPtr executor_;
- std::stack<Command> commandStack_;
- std::vector<void*> objectStack_;
+ ExecutorPtr executor_; ///< The Executor that is used to execute the command
+ std::stack<Command> commandStack_; ///< A stack of commands, used to push and pop different functions
+ std::vector<void*> objectStack_; ///< A stack of objects, used to push and pop different objects for a function
- ArgumentCompleter* argumentCompleter_[5];
+ ArgumentCompleter* argumentCompleter_[MAX_FUNCTOR_ARGUMENTS]; ///< ArgumentCompleter for each argument
- KeybindMode::Value keybindMode_;
- int inputConfiguredParam_;
+ KeybindMode::Value keybindMode_; ///< The keybind mode
+ int inputConfiguredParam_; ///< The input configured param
- LanguageEntryLabel description_;
- LanguageEntryLabel descriptionReturnvalue_;
- LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS];
+ LanguageEntryLabel description_; ///< The description of the command
+ LanguageEntryLabel descriptionReturnvalue_; ///< A description of the return-value
+ LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS]; ///< A description for each argument
public:
+ /// Returns the map with all groups and commands.
static inline const std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommands()
{ return ConsoleCommand::getCommandMap(); }
+ /// Returns the map with all groups and commands in lowercase.
static inline const std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandsLC()
{ return ConsoleCommand::getCommandMapLC(); }
+ /// Returns a command (shortcut) with given name. @param name The name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
static inline const ConsoleCommand* getCommand(const std::string& name, bool bPrintError = false)
{ return ConsoleCommand::getCommand("", name, bPrintError); }
+ /// Returns a command (shortcut) with given name in lowercase. @param name The lowercase name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
static inline const ConsoleCommand* getCommandLC(const std::string& name, bool bPrintError = false)
{ return ConsoleCommand::getCommandLC("", name, bPrintError); }
@@ -353,13 +679,41 @@
static void unregisterCommand(ConsoleCommand* command);
};
+ /**
+ @brief Creates a new ConsoleCommand.
+ @param name The name of the command
+ @param executor The executor of the command
+ @param bInitialized If true, the command is ready to be executed, otherwise it has to be activated first.
+ */
inline ConsoleCommand* createConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized = true)
{ return new ConsoleCommand("", name, executor, bInitialized); }
+ /**
+ @brief Creates a new ConsoleCommand.
+ @param group The group of the command
+ @param name The name of the command
+ @param executor The executor of the command
+ @param bInitialized If true, the command is ready to be executed, otherwise it has to be activated first.
+ */
inline ConsoleCommand* createConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized = true)
{ return new ConsoleCommand(group, name, executor, bInitialized); }
+
+ /**
+ @brief Returns a manipulator for a command with the given name.
+
+ @note If the command doesn't exist, the manipulator contains a NULL pointer to the command,
+ but it can still be used without checks, because all functions of ConsoleCommandManipulator
+ check internally if the command exists.
+ */
inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& name)
{ return ConsoleCommand::getCommand(name, true); }
+ /**
+ @brief Returns a manipulator for a command with the given group and name.
+
+ @note If the command doesn't exist, the manipulator contains a NULL pointer to the command,
+ but it can still be used without checks, because all functions of ConsoleCommandManipulator
+ check internally if the command exists.
+ */
inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& group, const std::string& name)
{ return ConsoleCommand::getCommand(group, name, true); }
}
Modified: code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.cc
===================================================================
--- code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,11 @@
*
*/
+/**
+ @file
+ @brief Implementation of some console commands.
+*/
+
#include "ConsoleCommandCompilation.h"
#include <fstream>
@@ -50,6 +55,9 @@
SetConsoleCommand("calculate", calculate);
+ /**
+ @brief Reads the content of a file and executes the commands in it line by line.
+ */
void source(const std::string& filename)
{
static std::set<std::string> executingFiles;
@@ -85,11 +93,17 @@
file.close();
}
+ /**
+ @brief Simply returns the arguments.
+ */
std::string echo(const std::string& text)
{
return text;
}
+ /**
+ @brief Writes text to the console, depending on the first argument with or without a line-break after it.
+ */
void puts(bool newline, const std::string& text)
{
if (newline)
@@ -102,6 +116,9 @@
}
}
+ /**
+ @brief Writes text to a file.
+ */
void write(const std::string& filename, const std::string& text)
{
std::ofstream file;
@@ -117,6 +134,9 @@
file.close();
}
+ /**
+ @brief Appends text to a file.
+ */
void append(const std::string& filename, const std::string& text)
{
std::ofstream file;
@@ -132,6 +152,9 @@
file.close();
}
+ /**
+ @brief Reads text from a file
+ */
std::string read(const std::string& filename)
{
std::ifstream file;
@@ -157,6 +180,9 @@
return output;
}
+ /**
+ @brief Parses the mathematical expression and returns the result.
+ */
float calculate(const std::string& calculation)
{
ExprParser expr;
Modified: code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.h
===================================================================
--- code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ConsoleCommandCompilation.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,12 @@
*
*/
+/**
+ @file
+ @ingroup Command ConsoleCommand
+ @brief Declaration of some console commands.
+*/
+
#ifndef _ConsoleCommandCompilation_H__
#define _ConsoleCommandCompilation_H__
Modified: code/branches/doc/src/libraries/core/command/Executor.cc
===================================================================
--- code/branches/doc/src/libraries/core/command/Executor.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/Executor.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -27,6 +27,11 @@
* Inspiration: Executor by Benjamin Grauer
*/
+/**
+ @file
+ @brief Implementation of orxonox::Executor
+*/
+
#include "Executor.h"
#include <algorithm>
@@ -39,12 +44,20 @@
namespace orxonox
{
+ /**
+ @brief Constructor: Creates an executor.
+ @param functor The wrapped functor
+ @param name The name of the executor (optional, used mostly for debug output)
+ */
Executor::Executor(const FunctorPtr& functor, const std::string& name)
{
this->functor_ = functor;
this->name_ = name;
}
+ /**
+ @brief Copy-constructor: Creates a new executor with the same values and a clone of the wrapped Functor.
+ */
Executor::Executor(const Executor& other) : name_(other.name_)
{
for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
@@ -52,42 +65,72 @@
this->functor_ = other.functor_->clone();
}
+ /**
+ @brief Destructor
+ */
Executor::~Executor()
{
}
+ /**
+ @brief Calls the wrapped function with arguments that are passed in a string.
+ @param arguments The arguments that should be passed to the function, separated by @a delimiter
+ @param error A pointer to a variable (or NULL) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+ @param delimiter The delimiter that is used to separate the arguments in the string @a arguments
+ @param bPrintError If true, errors are printed to the console if the function couldn't be executed with the given arguments
+ @return Returns the return value of the function (or MT_Type::Null if there is no return value)
+ */
MultiType Executor::parse(const std::string& arguments, int* error, const std::string& delimiter, bool bPrintError) const
{
return this->parse(SubString(arguments, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0'), error, delimiter, bPrintError);
}
+ /**
+ @brief Calls the wrapped function with arguments that are passed as tokens in a SubString
+ @param arguments The arguments that should be passed to the function
+ @param error A pointer to a variable (or NULL) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+ @param delimiter The delimiter that was used to separate the arguments in the SubString @a arguments (used to join the surplus arguments)
+ @param bPrintError If true, errors are printed to the console if the function couldn't be executed with the given arguments
+ @return Returns the return value of the function (or MT_Type::Null if there is no return value)
+ */
MultiType Executor::parse(const SubString& arguments, int* error, const std::string& delimiter, bool bPrintError) const
{
- MultiType param[MAX_FUNCTOR_ARGUMENTS];
- unsigned int paramCount = this->evaluateParams(arguments, param, error, delimiter);
+ // evaluate the arguments
+ MultiType arg[MAX_FUNCTOR_ARGUMENTS];
+ unsigned int argCount = this->evaluateArguments(arguments, arg, error, delimiter);
+ // check if an error occurred
if (error && *error)
{
if (bPrintError)
- COUT(2) << "Warning: Can't call executor " << this->name_ << " through parser: Not enough parameters or default values given (input: " << arguments.join() << ")." << std::endl;
+ COUT(2) << "Warning: Can't call executor " << this->name_ << " through parser: Not enough arguments or default values given (input: " << arguments.join() << ")." << std::endl;
return MT_Type::Null;
}
- COUT(5) << "Executor::parse: \"" << arguments.join(delimiter) << "\" -> " << paramCount << " params: " << param[0] << " / " << param[1] << " / " << param[2] << " / " << param[3] << " / " << param[4] << std::endl;
+ COUT(5) << "Executor::parse: \"" << arguments.join(delimiter) << "\" -> " << argCount << " arguments: " << arg[0] << " / " << arg[1] << " / " << arg[2] << " / " << arg[3] << " / " << arg[4] << std::endl;
- switch (paramCount)
+ // execute the function with the evaluated arguments (the default values of the executor are also included in these arguments)
+ switch (argCount)
{
case 0: return (*this->functor_)();
- case 1: return (*this->functor_)(param[0]);
- case 2: return (*this->functor_)(param[0], param[1]);
- case 3: return (*this->functor_)(param[0], param[1], param[2]);
- case 4: return (*this->functor_)(param[0], param[1], param[2], param[3]);
+ case 1: return (*this->functor_)(arg[0]);
+ case 2: return (*this->functor_)(arg[0], arg[1]);
+ case 3: return (*this->functor_)(arg[0], arg[1], arg[2]);
+ case 4: return (*this->functor_)(arg[0], arg[1], arg[2], arg[3]);
case 5:
- default: return (*this->functor_)(param[0], param[1], param[2], param[3], param[4]);
+ default: return (*this->functor_)(arg[0], arg[1], arg[2], arg[3], arg[4]);
}
}
- int Executor::evaluateParams(const SubString& arguments, MultiType param[MAX_FUNCTOR_ARGUMENTS], int* error, const std::string& delimiter) const
+ /**
+ @brief Converts the arguments in a SubString to the right type, so they can be used to execute the function without further conversions.
+ @param arguments The arguments that should be converted
+ @param arg An array of MultiType where the converted arguments will be stored
+ @param error A pointer to a variable (or NULL) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+ @param delimiter The delimiter that was used to separate the arguments in the SubString @a arguments (used to join the surplus arguments)
+ @return Returns the number of evaluated arguments
+ */
+ int Executor::evaluateArguments(const SubString& arguments, MultiType arg[MAX_FUNCTOR_ARGUMENTS], int* error, const std::string& delimiter) const
{
unsigned int paramCount = this->functor_->getParamCount();
unsigned int argumentCount = arguments.size();
@@ -105,66 +148,73 @@
// assign all given arguments to the multitypes
for (unsigned int i = 0; i < std::min(std::min(argumentCount, paramCount), MAX_FUNCTOR_ARGUMENTS); i++)
- param[i] = arguments[i];
+ arg[i] = arguments[i];
// fill the remaining multitypes with default values
for (unsigned int i = argumentCount; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
- param[i] = this->defaultValue_[i];
+ arg[i] = this->defaultValue_[i];
// assign the remaining arguments all to the last parameter if it is a string
if ((paramCount <= MAX_FUNCTOR_ARGUMENTS) &&(argumentCount > paramCount) && (paramCount == 1 || this->functor_->getTypenameParam(paramCount - 1) == "string"))
- param[paramCount - 1] = arguments.subSet(paramCount - 1).join(delimiter);
+ arg[paramCount - 1] = arguments.subSet(paramCount - 1).join(delimiter);
- // evaluate the param types through the functor
+ // evaluate the parameter types through the functor
for (unsigned int i = 0; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
- this->functor_->evaluateParam(i, param[i]);
+ this->functor_->evaluateArgument(i, arg[i]);
if (error)
*error = CommandExecutor::Success;
return paramCount;
}
- void Executor::setDefaultValues(const MultiType& param1)
+ /// Defines the default value for the first parameter.
+ void Executor::setDefaultValues(const MultiType& arg1)
{
- this->defaultValue_[0] = param1;
+ this->defaultValue_[0] = arg1;
}
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2)
+ /// Defines the default value for the first two parameters.
+ void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2)
{
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
+ this->defaultValue_[0] = arg1;
+ this->defaultValue_[1] = arg2;
}
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3)
+ /// Defines the default value for the first three parameters.
+ void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
{
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- this->defaultValue_[2] = param3;
+ this->defaultValue_[0] = arg1;
+ this->defaultValue_[1] = arg2;
+ this->defaultValue_[2] = arg3;
}
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4)
+ /// Defines the default value for the first four parameters.
+ void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
{
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- this->defaultValue_[2] = param3;
- this->defaultValue_[3] = param4;
+ this->defaultValue_[0] = arg1;
+ this->defaultValue_[1] = arg2;
+ this->defaultValue_[2] = arg3;
+ this->defaultValue_[3] = arg4;
}
- void Executor::setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5)
+ /// Defines the default value for the first five parameters.
+ void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
{
- this->defaultValue_[0] = param1;
- this->defaultValue_[1] = param2;
- this->defaultValue_[2] = param3;
- this->defaultValue_[3] = param4;
- this->defaultValue_[4] = param5;
+ this->defaultValue_[0] = arg1;
+ this->defaultValue_[1] = arg2;
+ this->defaultValue_[2] = arg3;
+ this->defaultValue_[3] = arg4;
+ this->defaultValue_[4] = arg5;
}
- void Executor::setDefaultValue(unsigned int index, const MultiType& param)
+ /// Defines the default value for a parameter with given index (the first parameter has index 0).
+ void Executor::setDefaultValue(unsigned int index, const MultiType& arg)
{
if (index < MAX_FUNCTOR_ARGUMENTS)
- this->defaultValue_[index] = param;
+ this->defaultValue_[index] = arg;
}
+ /// Returns true if the executor has a default value for each parameter of the wrapped function, so it can be called without passing additional arguments.
bool Executor::allDefaultValuesSet() const
{
for (unsigned int i = 0; i < this->functor_->getParamCount(); i++)
Modified: code/branches/doc/src/libraries/core/command/Executor.h
===================================================================
--- code/branches/doc/src/libraries/core/command/Executor.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/Executor.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -27,6 +27,56 @@
* Inspiration: Executor by Benjamin Grauer
*/
+/**
+ @defgroup FunctorExecutor Functor and Executor
+ @ingroup Command
+*/
+
+/**
+ @file
+ @ingroup Command FunctorExecutor
+ @brief Declaration of the orxonox::Executor class and the createExecutor() functions.
+
+ @anchor ExecutorExample
+
+ orxonox::Executor is used to wrap an orxonox::Functor and to store default values for
+ its parameters. Usually one uses the function createExecutor() to create a new executor.
+ This function returns an orxonox::ExecutorPtr which is a typedef of @ref orxonox::SharedPtr
+ "SharedPtr<Executor>", used to manage the pointer to the executor.
+
+ Executors are mostly used to execute callbacks. Because some callback functions need arguments,
+ Executor provides an easy interface to store these arguments as default values, so the
+ executor can also be executed without arguments because it will use these default values.
+
+ The Executor doesn't contain the function-pointer directly. Instead it wraps an instance
+ of orxonox::Functor. See @ref FunctorExample "Functor.h" for more information and some
+ examples.
+
+ Example:
+ @code
+ void myFunction(int a, int b) // declare a static function
+ {
+ COUT(0) << "The sum is " << (a + b) << std::endl; // print the sum of a and b to the console
+ }
+
+ FunctorPtr functor = createFunctor(&myFunction); // create a functor that wraps the function-pointer
+ ExecutorPtr executor = createExecutor(functor); // create an executor that wraps the functor
+
+ (*executor)(2, 5); // calls the executor with arguments 2 and 5, prints "The sum is 7" to the console
+
+ executor->setDefaultValue(1, 10); // sets the default-value for the second parameter (note: paramters start at index 0) to 10
+
+ (*executor)(2); // calls the executor with argument 2 and default-value 10, prints "The sum is 12"
+
+ executor->setDefaultValue(0, 5); // sets the default-value for the first parameter to 5
+
+ (*executor)(); // calls the executor with default-values only, prints "The sum is 15"
+ @endcode
+
+ Because executors that were created with createExecutor() are managed by an orxonox::SharedPtr,
+ they don't need to be deleted after usage.
+*/
+
#ifndef _Executor_H__
#define _Executor_H__
@@ -39,6 +89,11 @@
namespace orxonox
{
+ /**
+ @brief This class is used to wrap a Functor and to store default values for any of its parameters.
+
+ @see See @ref ExecutorExample "Executor.h" for an example.
+ */
class _CoreExport Executor
{
public:
@@ -46,52 +101,68 @@
Executor(const Executor& other);
virtual ~Executor();
+ /// Calls the wrapped function with 0 arguments. If the function needs more arguments, the executor's default values are used.
inline MultiType operator()() const
{ return (*this->functor_)(this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1) const
- { return (*this->functor_)(param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2) const
- { return (*this->functor_)(param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3) const
- { return (*this->functor_)(param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
- { return (*this->functor_)(param1, param2, param3, param4, this->defaultValue_[4]); }
- inline MultiType operator()(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
- { return (*this->functor_)(param1, param2, param3, param4, param5); }
+ /// Calls the wrapped function with 1 argument. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(const MultiType& arg1) const
+ { return (*this->functor_)(arg1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ /// Calls the wrapped function with 2 arguments. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(const MultiType& arg1, const MultiType& arg2) const
+ { return (*this->functor_)(arg1, arg2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ /// Calls the wrapped function with 3 arguments. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3) const
+ { return (*this->functor_)(arg1, arg2, arg3, this->defaultValue_[3], this->defaultValue_[4]); }
+ /// Calls the wrapped function with 4 arguments. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4) const
+ { return (*this->functor_)(arg1, arg2, arg3, arg4, this->defaultValue_[4]); }
+ /// Calls the wrapped function with 5 arguments. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5) const
+ { return (*this->functor_)(arg1, arg2, arg3, arg4, arg5); }
MultiType parse(const std::string& arguments, int* error = 0, const std::string& delimiter = " ", bool bPrintError = false) const;
MultiType parse(const SubString& arguments, int* error = 0, const std::string& delimiter = " ", bool bPrintError = false) const;
- int evaluateParams(const SubString& arguments, MultiType param[MAX_FUNCTOR_ARGUMENTS], int* error = 0, const std::string& delimiter = " ") const;
+ int evaluateArguments(const SubString& arguments, MultiType arg[MAX_FUNCTOR_ARGUMENTS], int* error = 0, const std::string& delimiter = " ") const;
+ /// Changes the functor.
inline void setFunctor(const FunctorPtr& functor)
{ this->functor_ = functor; }
+ /// Returns the functor.
inline const FunctorPtr& getFunctor() const
{ return this->functor_; }
+ /// Changes the name of the executor.
inline void setName(const std::string& name)
{ this->name_ = name; }
+ /// Returns the name of the executor.
inline const std::string& getName() const
{ return this->name_; }
+ /// Returns the number of parameters of the wrapped function.
inline unsigned int getParamCount() const
{ return this->functor_->getParamCount(); }
+ /// Returns true if the wrapped function returns a value.
inline bool hasReturnvalue() const
{ return this->functor_->hasReturnvalue(); }
+ /// Returns the type of the wrapped function (static or member).
inline Functor::Type::Enum getType() const
{ return this->functor_->getType(); }
+ /// Returns the name of the type of a parameter with given index (the first parameter has index 0).
inline std::string getTypenameParam(unsigned int param) const
{ return this->functor_->getTypenameParam(param); }
+ /// Returns the name of the type of the return value.
inline std::string getTypenameReturnvalue() const
{ return this->functor_->getTypenameReturnvalue(); }
- void setDefaultValues(const MultiType& param1);
- void setDefaultValues(const MultiType& param1, const MultiType& param2);
- void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3);
- void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4);
- void setDefaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5);
- void setDefaultValue(unsigned int index, const MultiType& param);
+ void setDefaultValues(const MultiType& arg1);
+ void setDefaultValues(const MultiType& arg1, const MultiType& arg2);
+ void setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3);
+ void setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4);
+ void setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5);
+ void setDefaultValue(unsigned int index, const MultiType& arg);
+ /// Returns the default value for a parameter with given index (the first parameter has index 0).
inline MultiType getDefaultValue(unsigned int index) const
{
if (index < MAX_FUNCTOR_ARGUMENTS)
@@ -101,6 +172,8 @@
}
bool allDefaultValuesSet() const;
+
+ /// Returns true if the executor contains a default value for the parameter with given index (the first parameter has index 0).
inline bool defaultValueSet(unsigned int index) const
{
if (index < MAX_FUNCTOR_ARGUMENTS)
@@ -110,98 +183,100 @@
}
protected:
- FunctorPtr functor_;
- std::string name_;
- MultiType defaultValue_[MAX_FUNCTOR_ARGUMENTS];
+ FunctorPtr functor_; ///< The underlying Functor that wraps a function
+ std::string name_; ///< The name of the executor
+ MultiType defaultValue_[MAX_FUNCTOR_ARGUMENTS]; ///< The default values, one for each parameter
};
+ /**
+ @brief A child class of Executor, used to distinguish executors that wrap static functions from executors that wrap member-functions.
+
+ Behaves exactly like Executor, because static functions need no special treatment.
+ */
class _CoreExport ExecutorStatic : public Executor
{
public:
+ /// Constructor: Initializes the parent class
ExecutorStatic(const FunctorStaticPtr& functor, const std::string& name = "") : Executor(functor, name) {}
+ /// Destructor
virtual ~ExecutorStatic() {}
};
+ /**
+ @brief A child class of Executor, used for easier handling of non-static member-functions.
+
+ Overloads some functions that call the underlying FunctorMember and additionally pass
+ an object-pointer that is needed for non-static member-functions.
+ */
template <class T>
class ExecutorMember : public Executor
{
public:
+ /// Constructor: Initializes the parent class and the pointer to the member-functor.
ExecutorMember(const FunctorMemberPtr<T>& functor, const std::string& name = "") : Executor(functor, name), functorMember_(functor) {}
+ /// Destructor
virtual ~ExecutorMember() {}
using Executor::operator();
+ /// Calls the wrapped function with 0 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
inline MultiType operator()(T* object) const
{ return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1) const
- { return (*this->functorMember_)(object, param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2) const
- { return (*this->functorMember_)(object, param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3) const
- { return (*this->functorMember_)(object, param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, this->defaultValue_[4]); }
- inline MultiType operator()(T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, param5); }
+ /// Calls the wrapped function with 1 argument and an object-pointer. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(T* object, const MultiType& arg1) const
+ { return (*this->functorMember_)(object, arg1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ /// Calls the wrapped function with 2 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2) const
+ { return (*this->functorMember_)(object, arg1, arg2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+ /// Calls the wrapped function with 3 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2, const MultiType& arg3) const
+ { return (*this->functorMember_)(object, arg1, arg2, arg3, this->defaultValue_[3], this->defaultValue_[4]); }
+ /// Calls the wrapped function with 4 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4) const
+ { return (*this->functorMember_)(object, arg1, arg2, arg3, arg4, this->defaultValue_[4]); }
+ /// Calls the wrapped function with 5 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+ inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5) const
+ { return (*this->functorMember_)(object, arg1, arg2, arg3, arg4, arg5); }
-
- inline MultiType operator()(const T* object) const
- { return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1) const
- { return (*this->functorMember_)(object, param1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2) const
- { return (*this->functorMember_)(object, param1, param2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3) const
- { return (*this->functorMember_)(object, param1, param2, param3, this->defaultValue_[3], this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, this->defaultValue_[4]); }
- inline MultiType operator()(const T* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) const
- { return (*this->functorMember_)(object, param1, param2, param3, param4, param5); }
-
+ /// Changes the object-pointer of the underlying FunctorMember.
inline void setObject(T* object) const
{ this->functorMember_->setObject(object); }
- inline void setObject(const T* object) const
- { this->functorMember_->setObject(object); }
+ /// Returns the object-pointer of the underlying FunctorMember.
+ inline T* getObject() const
+ { return this->functorMember_->getObject(); }
using Executor::parse;
- MultiType parse(T* object, const std::string& params, int* error = 0, const std::string& delimiter = " ", bool bPrintError = false) const
+ /// Overloads Executor::parse() with an additional object-pointer.
+ MultiType parse(T* object, const std::string& arguments, int* error = 0, const std::string& delimiter = " ", bool bPrintError = false) const
{
T* oldobject = this->functorMember_->getObject();
this->functorMember_->setObject(object);
- const MultiType& result = this->Executor::parse(params, error, delimiter, bPrintError);
+ const MultiType& result = this->Executor::parse(arguments, error, delimiter, bPrintError);
this->functorMember_->setObject(oldobject);
return result;
}
- MultiType parse(const T* object, const std::string& params, int* error = 0, const std::string& delimiter = " ", bool bPrintError = false) const
- {
- T* oldobject = this->functorMember_->getObject();
-
- this->functorMember_->setObject(object);
- const MultiType& result = this->Executor::parse(params, error, delimiter, bPrintError);
- this->functorMember_->setObjects(oldobject);
-
- return result;
- }
-
protected:
- FunctorMemberPtr<T> functorMember_;
+ FunctorMemberPtr<T> functorMember_; ///< A pointer to the FunctorMember is stored separately to avoid casting when executing the function.
};
+ /// Creates a new Executor that wraps a given Functor.
inline ExecutorPtr createExecutor(const FunctorPtr& functor, const std::string& name = "")
{
return new Executor(functor, name);
}
+ /// Creates a new ExecutorMember that wraps a given FunctorMember.
template <class T>
inline ExecutorMemberPtr<T> createExecutor(const FunctorMemberPtr<T>& functor, const std::string& name = "")
{
return new ExecutorMember<T>(functor, name);
}
+ /// Creates a new ExecutorStatic that wraps a given FunctorStatic.
inline ExecutorStaticPtr createExecutor(const FunctorStaticPtr& functor, const std::string& name = "")
{
return new ExecutorStatic(functor, name);
Modified: code/branches/doc/src/libraries/core/command/ExecutorPtr.h
===================================================================
--- code/branches/doc/src/libraries/core/command/ExecutorPtr.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/ExecutorPtr.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,24 @@
*
*/
+/**
+ @file
+ @ingroup Command FunctorExecutor
+ @brief Typedefs and definitions of ExecutorPtr, ExecutorStaticPtr, and ExecutorMemberPtr
+
+ Instances of orxonox::Executor are usually managed by an orxonox::SharedPtr. This ensures
+ that Executors will be destroyed after usage. To make things easier, there's a typedef
+ that defines ExecutorPtr as SharedPtr<Executor>.
+
+ Because there's not only orxonox::Executor, but also orxonox::ExecutorStatic, and
+ orxonox::ExecutorMember, the shared pointers need to store them all and also reflect
+ their hierarchy - ExecutorStatic and ExecutorMember should not be mixed, but both can
+ be converted to Executor. This is achieved by using orxonox::SharedChildPtr.
+
+ Because it's not possible to use a typedef for a template, we have to define the
+ helper class ExecutorMemberPtr<T> that makes it easier to use ExecutorMember.
+*/
+
#ifndef _ExecutorPtr_H__
#define _ExecutorPtr_H__
@@ -34,10 +52,13 @@
namespace orxonox
{
+ /// ExecutorPtr is just a typedef of SharedPtr
typedef SharedPtr<Executor> ExecutorPtr;
+ /// ExecutorStaticPtr is just a typedef of SharedChildPtr
typedef SharedChildPtr<ExecutorStatic, ExecutorPtr> ExecutorStaticPtr;
+ /// It's not possible to use a typedef for ExecutorMemberPtr<T>, so we have to create a child-class instead. It inherits all functions from SharedChildPtr, but needs to (re-)implement some constructors.
template <class T>
class ExecutorMemberPtr : public SharedChildPtr<ExecutorMember<T>, ExecutorPtr>
{
Modified: code/branches/doc/src/libraries/core/command/Functor.h
===================================================================
--- code/branches/doc/src/libraries/core/command/Functor.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/Functor.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,90 @@
*
*/
+/**
+ @file
+ @ingroup Command FunctorExecutor
+ @brief Definition of orxonox::Functor and its specialized subclasses, as well as the createFunctor() functions.
+
+ @anchor FunctorExample
+
+ Functors can be used to wrap function-pointers. While function-pointers have a very
+ complicated syntax in C++, Functors are always the same and you can call the wrapped
+ function-pointer independently of its parameter with arguments of type MultiType. These
+ arguments are then automatically converted to the right type.
+
+ To create a Functor, the helper function createFunctor() is used. It returns an instance
+ of orxonox::FunctorPtr which is simply a typedef of @ref orxonox::SharedPtr "SharedPtr<Functor>".
+ This means you don't have to delete the Functor after using it, because it is managed
+ by the SharedPtr.
+
+ Example:
+ @code
+ int myStaticFunction(int value) // Definition of a static function
+ {
+ return (value * 2); // Return the double of the value
+ }
+
+ FunctorPtr functor = createFunctor(&myStaticFunction); // Create a Functor
+
+ int result = (*functor)(5); // Calls the functor with value = 5, result == 10
+
+ int result = (*functor)("7"); // Calls the functor with a string which is converted to an integer, result == 14
+ @endcode
+
+ Functors can also be used if you work with member-functions. In this case createFunctor()
+ returns an instance of orxonox::FunctorMemberPtr - this allows you to define the object
+ that will be used to call the function.
+
+ Example:
+ @code
+ class MyClass // Define a class
+ {
+ public:
+ MyClass(const std::string& text) // Constructor
+ {
+ this->text_ = text;
+ }
+
+ bool contains(const std::string& word) // Function that searches for "word" in "text"
+ {
+ return (this->text_.find(word) != std::string::npos);
+ }
+
+ private:
+ std::string text_; // Member variable
+ };
+
+ MyClass* object = new MyClass("Hello World"); // Create an object of type MyClass and set its text to "Hello World"
+
+ FunctorPtr functor = createFunctor(&MyClass:contains, object); // Create a Functor (note the object!)
+
+ bool result = (*functor)("World"); // result == true
+ bool result = (*functor)("test"); // result == false
+ @endcode
+
+ Instead of assigning the object directly to the functor when creating it, you can also define
+ it at any later point or when you call the functor. Note however that this works only with
+ orxonox::FunctorMember.
+
+ @code
+ MyClass* object1 = new MyClass("Hello World"); // Create an object
+ MyClass* object2 = new MyClass("this is a test"); // Create another object
+
+ FunctorMemberPtr functor = createFunctor(&MyClass:contains); // Create a FunctorMember (note: no object this time)
+
+ bool result = (*functor)("World"); // result == false and an error: "Error: Can't execute FunctorMember, no object set."
+
+ bool result = (*functor)(object1, "World"); // result == true
+ bool result = (*functor)(object1, "test"); // result == false
+ bool result = (*functor)(object2, "test"); // result == true
+
+ functor->setObject(object1); // Assign an object to the FunctorMember
+
+ bool result = (*functor)("World"); // result == true (no error this time, because the object was set using setObject())
+ @endcode
+*/
+
#ifndef _Functor_H__
#define _Functor_H__
@@ -39,42 +123,60 @@
namespace orxonox
{
- const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;
+ const unsigned int MAX_FUNCTOR_ARGUMENTS = 5; ///< The maximum number of parameters of a function that is supported by Functor
- template <class T>
- inline std::string _typeToString() { return "unknown"; }
+ namespace detail
+ {
+ template <class T>
+ inline std::string _typeToString() { return "unknown"; }
- template <> inline std::string _typeToString<void>() { return ""; }
- template <> inline std::string _typeToString<int>() { return "int"; }
- template <> inline std::string _typeToString<unsigned int>() { return "uint"; }
- template <> inline std::string _typeToString<char>() { return "char"; }
- template <> inline std::string _typeToString<unsigned char>() { return "uchar"; }
- template <> inline std::string _typeToString<short>() { return "short"; }
- template <> inline std::string _typeToString<unsigned short>() { return "ushort"; }
- template <> inline std::string _typeToString<long>() { return "long"; }
- template <> inline std::string _typeToString<unsigned long>() { return "ulong"; }
- template <> inline std::string _typeToString<long long>() { return "longlong"; }
- template <> inline std::string _typeToString<unsigned long long>() { return "ulonglong"; }
- template <> inline std::string _typeToString<float>() { return "float"; }
- template <> inline std::string _typeToString<double>() { return "double"; }
- template <> inline std::string _typeToString<long double>() { return "longdouble"; }
- template <> inline std::string _typeToString<bool>() { return "bool"; }
- template <> inline std::string _typeToString<std::string>() { return "string"; }
- template <> inline std::string _typeToString<Vector2>() { return "Vector2"; }
- template <> inline std::string _typeToString<Vector3>() { return "Vector3"; }
- template <> inline std::string _typeToString<Quaternion>() { return "Quaternion"; }
- template <> inline std::string _typeToString<ColourValue>() { return "ColourValue"; }
- template <> inline std::string _typeToString<Radian>() { return "Radian"; }
- template <> inline std::string _typeToString<Degree>() { return "Degree"; }
+ template <> inline std::string _typeToString<void>() { return "void"; }
+ template <> inline std::string _typeToString<int>() { return "int"; }
+ template <> inline std::string _typeToString<unsigned int>() { return "uint"; }
+ template <> inline std::string _typeToString<char>() { return "char"; }
+ template <> inline std::string _typeToString<unsigned char>() { return "uchar"; }
+ template <> inline std::string _typeToString<short>() { return "short"; }
+ template <> inline std::string _typeToString<unsigned short>() { return "ushort"; }
+ template <> inline std::string _typeToString<long>() { return "long"; }
+ template <> inline std::string _typeToString<unsigned long>() { return "ulong"; }
+ template <> inline std::string _typeToString<long long>() { return "longlong"; }
+ template <> inline std::string _typeToString<unsigned long long>() { return "ulonglong"; }
+ template <> inline std::string _typeToString<float>() { return "float"; }
+ template <> inline std::string _typeToString<double>() { return "double"; }
+ template <> inline std::string _typeToString<long double>() { return "longdouble"; }
+ template <> inline std::string _typeToString<bool>() { return "bool"; }
+ template <> inline std::string _typeToString<std::string>() { return "string"; }
+ template <> inline std::string _typeToString<Vector2>() { return "Vector2"; }
+ template <> inline std::string _typeToString<Vector3>() { return "Vector3"; }
+ template <> inline std::string _typeToString<Quaternion>() { return "Quaternion"; }
+ template <> inline std::string _typeToString<ColourValue>() { return "ColourValue"; }
+ template <> inline std::string _typeToString<Radian>() { return "Radian"; }
+ template <> inline std::string _typeToString<Degree>() { return "Degree"; }
+ }
+ /// Returns the name of type @a T as string.
template <class T>
- inline std::string typeToString() { return _typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
+ inline std::string typeToString() { return detail::_typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
+ /**
+ @brief The Functor classes are used to wrap function pointers.
+
+ Function-pointers in C++ have a pretty complicated syntax and you can't store
+ and call them unless you know the exact type. A Functor can be used to wrap
+ a function-pointer and to store it independent of its type. You can also call
+ it independently of its parameters by passing the arguments as MultiType. They
+ are converted automatically to the right type.
+
+ Functor is a pure virtual base class.
+
+ @see See @ref FunctorExample "Functor.h" for some examples.
+ */
class _CoreExport Functor
{
public:
struct Type
{
+ /// Defines the type of a function (static or member)
enum Enum
{
Static,
@@ -83,40 +185,43 @@
};
public:
+ /// Calls the function-pointer with up to five arguments. In case of a member-function, the assigned object-pointer is used to call the function. @return Returns the return-value of the function (if any; MT_Type::Null otherwise)
virtual MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
+ /// Creates a new instance of Functor with the same values like this (used instead of a copy-constructor)
virtual FunctorPtr clone() = 0;
+ /// Returns the type of the function: static or member.
virtual Type::Enum getType() const = 0;
+ /// Returns the number of parameters of the function.
virtual unsigned int getParamCount() const = 0;
+ /// Returns true if the function has a return-value.
virtual bool hasReturnvalue() const = 0;
- virtual std::string getTypenameParam(unsigned int param) const = 0;
+ /// Returns the type-name of the parameter with given index (the first parameter has index 0).
+ virtual std::string getTypenameParam(unsigned int index) const = 0;
+ /// Returns the type-name of the return-value.
virtual std::string getTypenameReturnvalue() const = 0;
- virtual void evaluateParam(unsigned int index, MultiType& param) const = 0;
+ /// Converts a given argument to the type of the parameter with given index (the first parameter has index 0).
+ virtual void evaluateArgument(unsigned int index, MultiType& argument) const = 0;
- virtual void setRawObjectPointer(void* object) {}
- virtual void* getRawObjectPointer() const { return 0; }
+ /// Assigns an object-pointer to the functor which is used to execute a member-function.
+ virtual void setRawObjectPointer(void* object) = 0;
+ /// Returns the object-pointer.
+ virtual void* getRawObjectPointer() const = 0;
- template <class F>
- inline bool setFunction(F* function)
- {
- if (this->getFullIdentifier() == typeid(F*))
- {
- modifyFunctor(this, function);
- return true;
- }
- return false;
- }
-
+ /// Returns the full identifier of the function-pointer which is defined as typeid(@a F), where @a F is the type of the stored function-pointer. Used to compare functors.
virtual const std::type_info& getFullIdentifier() const = 0;
+ /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
virtual const std::type_info& getHeaderIdentifier() const = 0;
+ /// Returns an identifier of the header of the function (doesn't include the function's class), but regards only the first @a params parameters. Used to compare functions if an Executor provides default-values for the other parameters.
virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
};
namespace detail
{
+ // helper class to determine if a functor is static or not
template <class O>
struct FunctorTypeStatic
{ enum { result = false }; };
@@ -125,16 +230,31 @@
{ enum { result = true }; };
}
+ /**
+ @brief FunctorMember is a child class of Functor and expands it with an object-pointer, that
+ is used for member-functions, as well as an overloaded execution operator.
+
+ @param O The type of the function's class (or void if it's a static function)
+
+ Note that FunctorMember is also used for static functions, but with T = void. FunctorStatic
+ is a typedef of FunctorMember<void>. The void* object-pointer is ignored in this case.
+
+ @see See @ref FunctorExample "Functor.h" for some examples.
+ */
template <class O>
class FunctorMember : public Functor
{
public:
+ /// Constructor: Stores the object-pointer.
FunctorMember(O* object = 0) : object_(object) {}
+ /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be NULL. @return Returns the return-value of the function (if any; MT_Type::Null otherwise)
virtual MultiType operator()(O* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
+ // see Functor::operator()()
MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null)
{
+ // call the function if it is static or if an object was assigned
if (detail::FunctorTypeStatic<O>::result || this->object_)
return (*this)(this->object_, param1, param2, param3, param4, param5);
else
@@ -144,45 +264,69 @@
}
}
+ // see Functor::getType()
Functor::Type::Enum getType() const
{ return detail::FunctorTypeStatic<O>::result ? Functor::Type::Static : Functor::Type::Member; }
+ /// Assigns an object-pointer to the functor which is used to execute a member-function.
inline void setObject(O* object)
{ this->object_ = object;}
+ /// Returns the object-pointer.
inline O* getObject() const
{ return this->object_; }
+ // see Functor::setRawObjectPointer()
inline void setRawObjectPointer(void* object)
{ this->object_ = (O*)object; }
+ // see Functor::getRawObjectPointer()
inline void* getRawObjectPointer() const
{ return this->object_; }
protected:
- O* object_;
+ O* object_; ///< The stored object-pointer, used to execute a member-function (or NULL for static functions)
};
+ /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
typedef FunctorMember<void> FunctorStatic;
+ /**
+ @brief FunctorPointer is a child class of FunctorMember and expands it with a function-pointer.
+ @param F The type of the function-pointer
+ @param O The type of the function's class (or void if it's a static function)
+
+ The template FunctorPointer has an additional template parameter that defines the type
+ of the function-pointer. This can be handy if you want to get or set the function-pointer.
+ You can then use a static_cast to cast a Functor to FunctorPointer if you know the type
+ of the function-pointer.
+
+ However FunctorPointer is not aware of the types of the different parameters or the
+ return value.
+ */
template <class F, class O = void>
class FunctorPointer : public FunctorMember<O>
{
public:
+ /// Constructor: Initializes the base class and stores the function-pointer.
FunctorPointer(F functionPointer, O* object = 0) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
+ /// Changes the function-pointer.
inline void setFunction(F functionPointer)
{ this->functionPointer_ = functionPointer; }
+ /// Returns the function-pointer.
inline F getFunction() const
{ return this->functionPointer_; }
+ // see Functor::getFullIdentifier()
const std::type_info& getFullIdentifier() const
{ return typeid(F); }
protected:
- F functionPointer_;
+ F functionPointer_; ///< The stored function-pointer
};
namespace detail
{
+ // Helper class to get the type of the function pointer with the given class, parameters, return-value, and constness
template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer { typedef R (O::*Type)(P1, P2, P3, P4, P5); };
template <class R, class O, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer<R, O, false, P1, P2, P3, P4, P5> { typedef R (O::*Type)(P1, P2, P3, P4, P5); };
template <class R, class O, class P1, class P2, class P3, class P4> struct FunctionPointer<R, O, false, P1, P2, P3, P4, void> { typedef R (O::*Type)(P1, P2, P3, P4); };
@@ -203,6 +347,7 @@
template <class R, class P1> struct FunctionPointer<R, void, false, P1, void, void, void, void> { typedef R (*Type)(P1); };
template <class R> struct FunctionPointer<R, void, false, void, void, void, void, void> { typedef R (*Type)(); };
+ // Helper class, used to call a function-pointer with a given object and parameters and to return its return-value (if available)
template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4, param5); } };
template <class R, class O, bool isconst, class P1, class P2, class P3, class P4> struct FunctorCaller<R, O, isconst, P1, P2, P3, P4, void> { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4); } };
template <class R, class O, bool isconst, class P1, class P2, class P3> struct FunctorCaller<R, O, isconst, P1, P2, P3, void, void> { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3); } };
@@ -228,10 +373,12 @@
template <bool isconst, class P1> struct FunctorCaller<void, void, isconst, P1, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1); return MT_Type::Null; } };
template <bool isconst> struct FunctorCaller<void, void, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, void, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(); return MT_Type::Null; } };
+ // Helper class, used to identify the header of a function-pointer (independent of its class)
template <class R, class P1, class P2, class P3, class P4, class P5>
struct FunctorHeaderIdentifier
{};
+ // Helper class to determine if a function has a returnvalue
template <class T>
struct FunctorHasReturnvalue
{ enum { result = true }; };
@@ -239,6 +386,7 @@
struct FunctorHasReturnvalue<void>
{ enum { result = false }; };
+ // Helper class to count the number of parameters
template <class P1, class P2, class P3, class P4, class P5>
struct FunctorParamCount
{ enum { result = 5 }; };
@@ -259,47 +407,74 @@
{ enum { result = 0 }; };
}
+ /**
+ @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
+ that need to know the exact types of the parameters, return-value, and class.
+
+ @param R The type of the return-value of the function
+ @param O The class of the function
+ @param isconst True if the function is a const member-function
+ @param P1 The type of the first parameter
+ @param P2 The type of the second parameter
+ @param P3 The type of the third parameter
+ @param P4 The type of the fourth parameter
+ @param P5 The type of the fifth parameter
+
+ This template has many parameters and is usually not used directly. It is created by
+ createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
+ are used directly. It implements all the virtual functions that are declared by its
+ base classes.
+
+ All template arguments can be void.
+ */
template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5>
class FunctorTemplate : public FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>
{
public:
+ /// Constructor: Initializes the base class.
FunctorTemplate(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object = 0) : FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>(functionPointer, object) {}
+ // see FunctorMember::operator()()
MultiType operator()(O* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null)
{
return detail::FunctorCaller<R, O, isconst, P1, P2, P3, P4, P5>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
}
+ // see Functor::clone()
FunctorPtr clone()
{
return new FunctorTemplate(*this);
}
- void evaluateParam(unsigned int index, MultiType& param) const
+ // see Functor::evaluateArgument()
+ void evaluateArgument(unsigned int index, MultiType& argument) const
{
switch (index)
{
- case 0: param.convert<P1>(); break;
- case 1: param.convert<P2>(); break;
- case 2: param.convert<P3>(); break;
- case 3: param.convert<P4>(); break;
- case 4: param.convert<P5>(); break;
+ case 0: argument.convert<P1>(); break;
+ case 1: argument.convert<P2>(); break;
+ case 2: argument.convert<P3>(); break;
+ case 3: argument.convert<P4>(); break;
+ case 4: argument.convert<P5>(); break;
}
}
+ // see Functor::getParamCount()
unsigned int getParamCount() const
{
return detail::FunctorParamCount<P1, P2, P3, P4, P5>::result;
}
+ // see Functor::hasReturnvalue()
bool hasReturnvalue() const
{
return detail::FunctorHasReturnvalue<R>::result;
}
- std::string getTypenameParam(unsigned int param) const
+ // see Functor::getTypenameParam()
+ std::string getTypenameParam(unsigned int index) const
{
- switch (param)
+ switch (index)
{
case 0: return typeToString<P1>();
case 1: return typeToString<P2>();
@@ -310,16 +485,19 @@
}
}
+ // see Functor::getTypenameReturnvalue()
std::string getTypenameReturnvalue() const
{
return typeToString<R>();
}
+ // see Functor::getHeaderIdentifier()
const std::type_info& getHeaderIdentifier() const
{
return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
}
+ // see Functor::getHeaderIdentifier(unsigned int)
const std::type_info& getHeaderIdentifier(unsigned int params) const
{
switch (params)
@@ -334,38 +512,38 @@
}
};
- template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, void, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, void, void, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1), OO* object) { return new FunctorTemplate<R, O, false, P1, void, void, void, void>(functionPointer, object); }
- template <class R, class O, class OO> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(), OO* object) { return new FunctorTemplate<R, O, false, void, void, void, void, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, void, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, void, void, void>(functionPointer, object); }
- template <class R, class O, class OO, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const, OO* object) { return new FunctorTemplate<R, O, true, P1, void, void, void, void>(functionPointer, object); }
- template <class R, class O, class OO> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const, OO* object) { return new FunctorTemplate<R, O, true, void, void, void, void, void>(functionPointer, object); }
+ template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, void, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1), OO* object) { return new FunctorTemplate<R, O, false, P1, void, void, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(), OO* object) { return new FunctorTemplate<R, O, false, void, void, void, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, void, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const, OO* object) { return new FunctorTemplate<R, O, true, P1, void, void, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+ template <class R, class O, class OO> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const, OO* object) { return new FunctorTemplate<R, O, true, void, void, void, void, void>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
- template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>(functionPointer); }
- template <class R, class O, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4)) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, void>(functionPointer); }
- template <class R, class O, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3)) { return new FunctorTemplate<R, O, false, P1, P2, P3, void, void>(functionPointer); }
- template <class R, class O, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2)) { return new FunctorTemplate<R, O, false, P1, P2, void, void, void>(functionPointer); }
- template <class R, class O, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1)) { return new FunctorTemplate<R, O, false, P1, void, void, void, void>(functionPointer); }
- template <class R, class O> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)()) { return new FunctorTemplate<R, O, false, void, void, void, void, void>(functionPointer); }
- template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>(functionPointer); }
- template <class R, class O, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, void>(functionPointer); }
- template <class R, class O, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, void, void>(functionPointer); }
- template <class R, class O, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const) { return new FunctorTemplate<R, O, true, P1, P2, void, void, void>(functionPointer); }
- template <class R, class O, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const) { return new FunctorTemplate<R, O, true, P1, void, void, void, void>(functionPointer); }
- template <class R, class O> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const) { return new FunctorTemplate<R, O, true, void, void, void, void, void>(functionPointer); }
+ template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4)) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3)) { return new FunctorTemplate<R, O, false, P1, P2, P3, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2)) { return new FunctorTemplate<R, O, false, P1, P2, void, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1)) { return new FunctorTemplate<R, O, false, P1, void, void, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)()) { return new FunctorTemplate<R, O, false, void, void, void, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2, class P3, class P4> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2, class P3> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1, class P2> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const) { return new FunctorTemplate<R, O, true, P1, P2, void, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O, class P1> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const) { return new FunctorTemplate<R, O, true, P1, void, void, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+ template <class R, class O> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const) { return new FunctorTemplate<R, O, true, void, void, void, void, void>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
- template <class R, class P1, class P2, class P3, class P4, class P5> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate<R, void, false, P1, P2, P3, P4, P5>(functionPointer); }
- template <class R, class P1, class P2, class P3, class P4> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4)) { return new FunctorTemplate<R, void, false, P1, P2, P3, P4, void>(functionPointer); }
- template <class R, class P1, class P2, class P3> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3)) { return new FunctorTemplate<R, void, false, P1, P2, P3, void, void>(functionPointer); }
- template <class R, class P1, class P2> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2)) { return new FunctorTemplate<R, void, false, P1, P2, void, void, void>(functionPointer); }
- template <class R, class P1> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1)) { return new FunctorTemplate<R, void, false, P1, void, void, void, void>(functionPointer); }
- template <class R> inline FunctorStaticPtr createFunctor(R (*functionPointer)()) { return new FunctorTemplate<R, void, false, void, void, void, void, void>(functionPointer); }
+ template <class R, class P1, class P2, class P3, class P4, class P5> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate<R, void, false, P1, P2, P3, P4, P5>(functionPointer); } ///< Creates a new Functor with the given function-pointer
+ template <class R, class P1, class P2, class P3, class P4> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4)) { return new FunctorTemplate<R, void, false, P1, P2, P3, P4, void>(functionPointer); } ///< Creates a new Functor with the given function-pointer
+ template <class R, class P1, class P2, class P3> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3)) { return new FunctorTemplate<R, void, false, P1, P2, P3, void, void>(functionPointer); } ///< Creates a new Functor with the given function-pointer
+ template <class R, class P1, class P2> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2)) { return new FunctorTemplate<R, void, false, P1, P2, void, void, void>(functionPointer); } ///< Creates a new Functor with the given function-pointer
+ template <class R, class P1> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1)) { return new FunctorTemplate<R, void, false, P1, void, void, void, void>(functionPointer); } ///< Creates a new Functor with the given function-pointer
+ template <class R> inline FunctorStaticPtr createFunctor(R (*functionPointer)()) { return new FunctorTemplate<R, void, false, void, void, void, void, void>(functionPointer); } ///< Creates a new Functor with the given function-pointer
}
#endif /* _Functor_H__ */
Modified: code/branches/doc/src/libraries/core/command/FunctorPtr.h
===================================================================
--- code/branches/doc/src/libraries/core/command/FunctorPtr.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/command/FunctorPtr.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -26,6 +26,26 @@
*
*/
+/**
+ @file
+ @ingroup Command FunctorExecutor
+ @brief Typedefs and definitions of FunctorPtr, FunctorMemberPtr, FunctorStaticPtr, and FunctorPointerPtr
+
+ Instances of orxonox::Functor are usually managed by an orxonox::SharedPtr. This ensures
+ that Functors will be destroyed after usage. To make things easier, there's a typedef
+ that defines FunctorPtr as SharedPtr<Functor>.
+
+ Because there's not only orxonox::Functor, but also orxonox::FunctorStatic, and
+ orxonox::FunctorMember, the shared pointers need to store them all and also reflect
+ their hierarchy - FunctorStatic and FunctorMember should not be mixed, but both can
+ be converted to Functor. This is achieved by using orxonox::SharedChildPtr.
+
+ Because it's not possible to use a typedef for a template, we have to define the
+ helper class FunctorMemberPtr<T> that makes it easier to use FunctorMember. The
+ same is also done for FunctorPointerPtr<T>, which can be converted to both,
+ FunctorMemberPtr<T> as well as FunctorPtr.
+*/
+
#ifndef _FunctorPtr_H__
#define _FunctorPtr_H__
@@ -34,8 +54,10 @@
namespace orxonox
{
+ /// FunctorPtr is just a typedef of SharedPtr
typedef SharedPtr<Functor> FunctorPtr;
+ /// It's not possible to use a typedef for FunctorMemberPtr<T>, so we have to create a child-class instead. It inherits all functions from SharedChildPtr, but needs to (re-)implement some constructors.
template <class T>
class FunctorMemberPtr : public SharedChildPtr<FunctorMember<T>, FunctorPtr>
{
@@ -45,8 +67,10 @@
inline FunctorMemberPtr(const SharedPtr<FunctorMember<T> >& other) : SharedChildPtr<FunctorMember<T>, FunctorPtr>(other) {}
};
+ /// FunctorStaticPtr is just FunctorMemberPtr with @a T = void
typedef FunctorMemberPtr<void> FunctorStaticPtr;
+ /// It's not possible to use a typedef for FunctorPointerPtr<T>, so we have to create a child-class instead. It inherits all functions from SharedChildPtr, but needs to (re-)implement some constructors.
template <class F, class T>
class FunctorPointerPtr : public SharedChildPtr<FunctorPointer<F, T>, FunctorMemberPtr<T> >
{
Modified: code/branches/doc/src/libraries/core/input/Button.cc
===================================================================
--- code/branches/doc/src/libraries/core/input/Button.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/input/Button.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -175,7 +175,7 @@
// evaluate the command
CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
- if (!eval.isValid() || eval.evaluateParams(true))
+ if (!eval.isValid() || eval.evaluateArguments(true))
{
parseError("Command evaluation of \"" + commandStr + "\"failed.", true);
continue;
Modified: code/branches/doc/src/libraries/core/input/InputCommands.cc
===================================================================
--- code/branches/doc/src/libraries/core/input/InputCommands.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/core/input/InputCommands.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -52,7 +52,7 @@
{
if (this->abs_ != 0.0f || this->rel_ != 0.0f)
{
- evaluation_.setEvaluatedParameter(paramIndex_, Vector2(abs_, rel_));
+ evaluation_.setEvaluatedArgument(paramIndex_, Vector2(abs_, rel_));
// reset
rel_ = 0.0;
abs_ = 0.0;
Modified: code/branches/doc/src/libraries/util/Debug.h
===================================================================
--- code/branches/doc/src/libraries/util/Debug.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/Debug.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -34,7 +34,7 @@
/**
@file
- at ingroup Util COUT
+ at ingroup COUT
@brief
Handles different output-levels of errors, warnings, infos, and debug information.
Modified: code/branches/doc/src/libraries/util/Math.h
===================================================================
--- code/branches/doc/src/libraries/util/Math.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/Math.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -33,7 +33,7 @@
/**
@file
- @ingroup Util Math
+ @ingroup Math
@brief Declaration and implementation of several math-functions, typedefs of some Ogre::Math classes to the orxonox namespace.
*/
Modified: code/branches/doc/src/libraries/util/MultiType.h
===================================================================
--- code/branches/doc/src/libraries/util/MultiType.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/MultiType.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -33,7 +33,7 @@
/**
@file
- @ingroup Util MultiType
+ @ingroup MultiType
@brief Declaration of the MultiType and some helper constructs.
@anchor MultiTypeExamples
Modified: code/branches/doc/src/libraries/util/MultiTypeValue.h
===================================================================
--- code/branches/doc/src/libraries/util/MultiTypeValue.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/MultiTypeValue.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -28,7 +28,7 @@
/**
@file
- @ingroup Util MultiType
+ @ingroup MultiType
@brief Declaration and Implementation of the MT_Value<T> class.
The MT_Value<T> class is used to hold a value of type T within a MultiType.
Modified: code/branches/doc/src/libraries/util/Scope.h
===================================================================
--- code/branches/doc/src/libraries/util/Scope.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/Scope.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -28,7 +28,7 @@
/**
@file
- at ingroup Util SingletonScope
+ at ingroup SingletonScope
@brief Declaration of the classes that are needed to use Scopes:
orxonox::Scope, orxonox::ScopeListener, and orxonox::ScopeManager.
Modified: code/branches/doc/src/libraries/util/ScopedSingletonManager.h
===================================================================
--- code/branches/doc/src/libraries/util/ScopedSingletonManager.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/ScopedSingletonManager.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -28,7 +28,7 @@
/**
@file
- @ingroup Util SingletonScope
+ @ingroup SingletonScope
@brief Definition of orxonox::ScopedSingletonManager, orxonox::ClassScopedSingletonManager, and the ManageScopedSingleton macro.
ScopedSingletonManager is used to create and destroy Singletons that belong to
Modified: code/branches/doc/src/libraries/util/SharedPtr.h
===================================================================
--- code/branches/doc/src/libraries/util/SharedPtr.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/SharedPtr.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -28,12 +28,12 @@
/**
@defgroup SharedPtr SharedPtr<T>
- @ingroup Util Object
+ @ingroup Util
*/
/**
@file
- @ingroup Util SharedPtr
+ @ingroup SharedPtr
@brief Definition of the SharedPtr template that is used to manage pointers.
@anchor SharedPtrExample
Modified: code/branches/doc/src/libraries/util/Singleton.h
===================================================================
--- code/branches/doc/src/libraries/util/Singleton.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/Singleton.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -33,7 +33,7 @@
/**
@file
- @ingroup Util SingletonScope
+ @ingroup SingletonScope
@brief Definition of the Singleton template that is used as base class for classes that allow only one instance.
@anchor SingletonExample
Modified: code/branches/doc/src/libraries/util/SmallObjectAllocator.h
===================================================================
--- code/branches/doc/src/libraries/util/SmallObjectAllocator.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/SmallObjectAllocator.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -28,12 +28,12 @@
/**
@defgroup SmallObjectAllocator SmallObjectAllocator
- @ingroup Util Object
+ @ingroup Util
*/
/**
@file
- @ingroup Util SmallObjectAllocator
+ @ingroup SmallObjectAllocator
@brief Declaration of SmallObjectAllocator
@anchor SmallObjectAllocatorExample
Modified: code/branches/doc/src/libraries/util/StringUtils.h
===================================================================
--- code/branches/doc/src/libraries/util/StringUtils.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/StringUtils.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -33,7 +33,7 @@
/**
@file
- @ingroup Util String
+ @ingroup String
@brief Declaration of several string manipulation functions, used in many parts of the game.
*/
Modified: code/branches/doc/src/libraries/util/SubString.cc
===================================================================
--- code/branches/doc/src/libraries/util/SubString.cc 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/SubString.cc 2010-09-04 21:33:02 UTC (rev 7352)
@@ -37,6 +37,11 @@
* Extended by Fabian 'x3n' Landau by the SL_PARENTHESES mode.
*/
+/**
+ @file
+ @brief Implementation of the SubString class.
+*/
+
#include "SubString.h"
#include <cstdio>
#include "Debug.h"
Modified: code/branches/doc/src/libraries/util/SubString.h
===================================================================
--- code/branches/doc/src/libraries/util/SubString.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/SubString.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -38,8 +38,8 @@
/**
@file
- @ingroup Util String
- @brief a small class to get the parts of a string separated by commas
+ @ingroup String
+ @brief A helper class to split a string into several tokens.
@anchor SubStringExample
Modified: code/branches/doc/src/libraries/util/VA_NARGS.h
===================================================================
--- code/branches/doc/src/libraries/util/VA_NARGS.h 2010-09-04 15:56:35 UTC (rev 7351)
+++ code/branches/doc/src/libraries/util/VA_NARGS.h 2010-09-04 21:33:02 UTC (rev 7352)
@@ -30,6 +30,37 @@
@file
@ingroup Util
@brief Declaration of the ORXONOX_VA_NARGS macro which returns the number of arguments passed to a variadic macro.
+
+ With this utility you can overload a macro for different numbers of arguments
+ (of course overloading is not possible for different types, as macros are not
+ type aware, but for different numbers of arguments is still very powerful).
+
+ Example: A macro to call functions
+ @code
+ myfunction(); // A static function
+ MyClass::myStaticFunction(); // A static class function
+ MyClass::myFunction(); // A member function
+
+ #define CallFunction(...) \ // Define a variadic macro that passes the arguments to the overloaded implementations
+ BOOST_PP_EXPAND(BOOST_PP_CAT(CallFunction, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+
+ #define CallFunction1(function) \ // Overloaded macro for 1 argument
+ function() // Calls the static function
+
+ #define CallFunction2(class, function) \ // Overloaded macro for 2 arguments
+ class::function() // Calls the static class function
+
+ #define CallFunction3(class, function, object) \ // Overloaded macro for 3 arguments
+ object->class::function() // Calls the function on the object
+
+
+ CallFunction(myFunction); // Call the macro with 1 argument
+ CallFunction(MyClass, myStaticFunction); // Call the macro with 2 arguments
+ CallFunction(MyClass, myFunction, new MyClass()); // Call the macro with 3 arguments
+ @endcode
+
+ Note that the first (variadic) macro concatenates the name "CallFunction" with
+ the number of arguments ("1" - "N"). Then all arguments are passed to the right macro.
*/
#include <boost/preprocessor/facilities/expand.hpp>
More information about the Orxonox-commit
mailing list