Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/command/Executor.cc @ 9550

Last change on this file since 9550 was 9550, checked in by landauf, 11 years ago

merged testing branch back to trunk. unbelievable it took me 13 months to finish this chore…

  • Property svn:eol-style set to native
File size: 9.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 *   Inspiration: Executor by Benjamin Grauer
28 */
29
30/**
31    @file
32    @brief Implementation of orxonox::Executor
33*/
34
35#include "Executor.h"
36
37#include <algorithm>
38
39#include "util/Convert.h"
40#include "util/Output.h"
41#include "util/StringUtils.h"
42#include "util/SubString.h"
43#include "CommandExecutor.h"
44
45namespace orxonox
46{
47    /**
48        @brief Constructor: Creates an executor.
49        @param functor The wrapped functor
50        @param name The name of the executor (optional, used mostly for debug output)
51    */
52    Executor::Executor(const FunctorPtr& functor, const std::string& name)
53    {
54        this->functor_ = functor;
55        this->name_ = name;
56    }
57
58    /**
59        @brief Copy-constructor: Creates a new executor with the same values and a clone of the wrapped Functor.
60    */
61    Executor::Executor(const Executor& other) : name_(other.name_)
62    {
63        for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
64            defaultValue_[i] = other.defaultValue_[i];
65        this->functor_ = other.functor_->clone();
66    }
67
68    /**
69        @brief Destructor
70    */
71    Executor::~Executor()
72    {
73    }
74
75    /**
76        @brief Calls the wrapped function with arguments that are passed in a string.
77        @param arguments The arguments that should be passed to the function, separated by @a delimiter
78        @param error A pointer to a variable (or NULL) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
79        @param delimiter The delimiter that is used to separate the arguments in the string @a arguments
80        @param bPrintError If true, errors are printed to the console if the function couldn't be executed with the given arguments
81        @return Returns the return value of the function (or MultiType::Null if there is no return value)
82    */
83    MultiType Executor::parse(const std::string& arguments, int* error, const std::string& delimiter, bool bPrintError) const
84    {
85        return this->parse(SubString(arguments, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0'), error, delimiter, bPrintError);
86    }
87
88    /**
89        @brief Calls the wrapped function with arguments that are passed as tokens in a SubString
90        @param arguments The arguments that should be passed to the function
91        @param error A pointer to a variable (or NULL) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
92        @param delimiter The delimiter that was used to separate the arguments in the SubString @a arguments (used to join the surplus arguments)
93        @param bPrintError If true, errors are printed to the console if the function couldn't be executed with the given arguments
94        @return Returns the return value of the function (or MultiType::Null if there is no return value)
95    */
96    MultiType Executor::parse(const SubString& arguments, int* error, const std::string& delimiter, bool bPrintError) const
97    {
98        // evaluate the arguments
99        MultiType arg[MAX_FUNCTOR_ARGUMENTS];
100        unsigned int argCount = this->evaluateArguments(arguments, arg, error, delimiter);
101
102        // check if an error occurred
103        if (error && *error)
104        {
105            if (bPrintError)
106                orxout(internal_warning) << "Can't call executor " << this->name_ << " through parser: Not enough arguments or default values given (input: " << arguments.join() << ")." << endl;
107            return MultiType::Null;
108        }
109
110        orxout(verbose, context::misc::executor) << "Executor::parse: \"" << arguments.join(delimiter) << "\" -> " << argCount << " arguments: " << arg[0] << " / " << arg[1] << " / " << arg[2] << " / " << arg[3] << " / " << arg[4] << endl;
111
112        // execute the function with the evaluated arguments (the default values of the executor are also included in these arguments)
113        switch (argCount)
114        {
115            case 0:  return (*this->functor_)();
116            case 1:  return (*this->functor_)(arg[0]);
117            case 2:  return (*this->functor_)(arg[0], arg[1]);
118            case 3:  return (*this->functor_)(arg[0], arg[1], arg[2]);
119            case 4:  return (*this->functor_)(arg[0], arg[1], arg[2], arg[3]);
120            case 5:
121            default: return (*this->functor_)(arg[0], arg[1], arg[2], arg[3], arg[4]);
122        }
123    }
124
125    /**
126        @brief Converts the arguments in a SubString to the right type, so they can be used to execute the function without further conversions.
127        @param arguments The arguments that should be converted
128        @param arg An array of MultiType where the converted arguments will be stored
129        @param error A pointer to a variable (or NULL) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
130        @param delimiter The delimiter that was used to separate the arguments in the SubString @a arguments (used to join the surplus arguments)
131        @return Returns the number of evaluated arguments
132    */
133    int Executor::evaluateArguments(const SubString& arguments, MultiType arg[MAX_FUNCTOR_ARGUMENTS], int* error, const std::string& delimiter) const
134    {
135        unsigned int paramCount = this->functor_->getParamCount();
136        unsigned int argumentCount = arguments.size();
137
138        // if there are not enough params given, check if there are default values
139        for (unsigned int i = argumentCount; i < paramCount; i++)
140        {
141            if (this->defaultValue_[i].null())
142            {
143                if (error)
144                    *error = CommandExecutor::Incomplete;
145                return 0;
146            }
147        }
148
149        // assign all given arguments to the multitypes
150        for (unsigned int i = 0; i < std::min(std::min(argumentCount, paramCount), MAX_FUNCTOR_ARGUMENTS); i++)
151            arg[i] = arguments[i];
152
153        // fill the remaining multitypes with default values
154        for (unsigned int i = argumentCount; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
155            arg[i] = this->defaultValue_[i];
156
157        // assign the remaining arguments all to the last parameter if it is a string
158        if ((paramCount <= MAX_FUNCTOR_ARGUMENTS) &&(argumentCount > paramCount) && (paramCount == 1 || this->functor_->getTypenameParam(paramCount - 1) == "string"))
159            arg[paramCount - 1] = arguments.subSet(paramCount - 1).join(delimiter);
160
161        // evaluate the parameter types through the functor
162        for (unsigned int i = 0; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
163            this->functor_->evaluateArgument(i, arg[i]);
164
165        if (error)
166            *error = CommandExecutor::Success;
167        return paramCount;
168    }
169
170    /// Defines the default value for the first parameter.
171    void Executor::setDefaultValues(const MultiType& arg1)
172    {
173        this->defaultValue_[0] = arg1;
174    }
175
176    /// Defines the default value for the first two parameters.
177    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2)
178    {
179        this->defaultValue_[0] = arg1;
180        this->defaultValue_[1] = arg2;
181    }
182
183    /// Defines the default value for the first three parameters.
184    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
185    {
186        this->defaultValue_[0] = arg1;
187        this->defaultValue_[1] = arg2;
188        this->defaultValue_[2] = arg3;
189    }
190
191    /// Defines the default value for the first four parameters.
192    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
193    {
194        this->defaultValue_[0] = arg1;
195        this->defaultValue_[1] = arg2;
196        this->defaultValue_[2] = arg3;
197        this->defaultValue_[3] = arg4;
198    }
199
200    /// Defines the default value for the first five parameters.
201    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
202    {
203        this->defaultValue_[0] = arg1;
204        this->defaultValue_[1] = arg2;
205        this->defaultValue_[2] = arg3;
206        this->defaultValue_[3] = arg4;
207        this->defaultValue_[4] = arg5;
208    }
209
210    /// Defines the default value for a parameter with given index (the first parameter has index 0).
211    void Executor::setDefaultValue(unsigned int index, const MultiType& arg)
212    {
213        if (index < MAX_FUNCTOR_ARGUMENTS)
214            this->defaultValue_[index] = arg;
215    }
216
217    /// 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.
218    bool Executor::allDefaultValuesSet() const
219    {
220        for (unsigned int i = 0; i < this->functor_->getParamCount(); i++)
221            if (this->defaultValue_[i].null())
222                return false;
223
224        return true;
225    }
226}
Note: See TracBrowser for help on using the repository browser.