Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/CommandLineParser.h @ 7621

Last change on this file since 7621 was 7276, checked in by landauf, 14 years ago

until now we could group words and values in console commands and XML values using parentheses (…). now we have to use braces {…}, because that works better in connection with Tcl. in practice however this feature was never used before, so this change shouldn't affect anything.

  • Property svn:eol-style set to native
File size: 9.2 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 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#ifndef _CommandLine_H__
30#define _CommandLine_H__
31
32#include "CorePrereqs.h"
33
34#include <map>
35#include "util/OrxAssert.h"
36#include "util/MultiType.h"
37
38#define SetCommandLineArgument(name, defaultValue) \
39    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
40    = orxonox::CommandLineParser::addArgument(#name, defaultValue, false)
41#define SetCommandLineOnlyArgument(name, defaultValue) \
42    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
43    = orxonox::CommandLineParser::addArgument(#name, defaultValue, true)
44#define SetCommandLineSwitch(name) \
45    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
46    = orxonox::CommandLineParser::addArgument(#name, false, false)
47#define SetCommandLineOnlySwitch(name) \
48    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
49    = orxonox::CommandLineParser::addArgument(#name, false, true)
50
51
52namespace orxonox
53{
54    /**
55    @brief
56        Container class for a command line argument of any type supported by MultiType.
57
58        Whenever you want to have an option specified by a command line switch,
59        you need to first define it with SetCommandLineArgument(name, defaultValue).
60        It is then added to a map and possibly changed when the command line is being parsed.
61        If the option was not given, you can detect this by asking hasDefaultValue().
62
63        There is a possibility to define a short cut so you can write "-p 20" instead of "--port 20".
64        Note the difference between "-" and "--"!
65        Also, there is no restriction to the number of strings you add after --name.
66        So "--startVector {2, 4, 5}" is perfectly legal.
67
68        Retrieving an argument is possible with the getCommandLineArgument function of the
69        CommandLineParser class. It is a Singleton, but the public interface is static.
70    */
71    class _CoreExport CommandLineArgument
72    {
73        friend class CommandLineParser;
74
75    public:
76        //! Tells whether the value has been changed by the command line.
77        bool hasDefaultValue() const { return bHasDefaultValue_; }
78        //! Returns the name of the argument.
79        const std::string& getName() const { return name_; }
80
81        //! Returns the shortcut (example: "-p 22" for "--port 22") of the argument.
82        //! Evaluates to "" if there is none.
83        const std::string& getShortcut() const { return shortcut_; }
84        //! Sets the shortcut for the argument
85        CommandLineArgument& shortcut(const std::string& shortcut)
86        { this->shortcut_ = shortcut; return *this; }
87
88        //! Returns the usage information
89        const std::string& getInformation() const { return this->usageInformation_; }
90        //! Sets the option information when displaying orxonox usage.
91        CommandLineArgument& information(const std::string& usage)
92        { this->usageInformation_ = usage; return *this; }
93
94        //! Returns the actual value of the argument. Can be equal to default value.
95        MultiType getValue() const { return value_; }
96        //! Returns the given default value as type T.
97        MultiType getDefaultValue() const { return defaultValue_; }
98
99    private:
100        //! Constructor initialises both value_ and defaultValue_ with defaultValue.
101        CommandLineArgument(const std::string& name, const MultiType& defaultValue, bool bCommandLineOnly)
102            : bHasDefaultValue_(true)
103            , name_(name)
104            , value_(defaultValue)
105            , defaultValue_(defaultValue)
106            , bCommandLineOnly_(bCommandLineOnly)
107        { }
108
109        //! Undefined copy constructor
110        CommandLineArgument(const CommandLineArgument& instance);
111        ~CommandLineArgument() { }
112
113        //! Parses the value string of a command line argument.
114        void parse(const std::string& value, bool bParsingFile);
115
116        //! Tells whether the value has been changed by the command line.
117        bool bHasDefaultValue_;
118
119    private:
120        std::string name_;             //!< Name of the argument
121        std::string shortcut_;         //!< Shortcut of the argument. @see getShortcut().
122        std::string usageInformation_; //!< Tells about the usage of this parameter
123
124        MultiType   value_;            //!< The actual value
125        MultiType   defaultValue_;     //!< Default value. Should not be changed.
126        bool        bCommandLineOnly_; //!< Whether you cannot specify the value in a text file
127    };
128
129
130    /**
131    @brief
132        Global interface to command line options.
133        Allows to add and retrieve command line arguments. Also does the parsing.
134    @note
135        Internally it is a Singleton, but the public interface is static.
136    @see
137        CommandLineArgument
138    */
139    class _CoreExport CommandLineParser
140    {
141    public:
142
143        //! Parse redirection to internal member method.
144        static void parseCommandLine(const std::string& cmdLine) { _getInstance()._parseCommandLine(cmdLine); }
145        static void parseFile() { _getInstance()._parseFile(); }
146
147        static std::string getUsageInformation();
148
149        static const CommandLineArgument* getArgument(const std::string& name);
150        //! Writes the argument value in the given parameter.
151        template <class T>
152        static void getValue(const std::string& name, T* value)
153        { *value = (T)(getArgument(name)->getValue()); }
154        static MultiType getValue(const std::string& name)
155        { return getArgument(name)->getValue(); }
156        template <class T>
157        static CommandLineArgument& addArgument(const std::string& name, T defaultValue, bool bCommandLineOnly);
158
159        static bool existsArgument(const std::string& name)
160        {
161            std::map<std::string, CommandLineArgument*>::const_iterator it = _getInstance().cmdLineArgs_.find(name);
162            return !(it == _getInstance().cmdLineArgs_.end());
163        }
164
165        static void destroyAllArguments();
166
167    private:
168        //! Constructor initialises bFirstTimeParse_ with true.
169        CommandLineParser() : bFirstTimeParse_(true) { }
170        //! Undefined copy constructor
171        CommandLineParser(const CommandLineParser& instance);
172        ~CommandLineParser();
173
174        static CommandLineParser& _getInstance();
175
176        void _parseCommandLine(const std::string& cmdLine);
177        void _parseFile();
178        void _parse(const std::vector<std::string>& arguments, bool bParsingFile);
179        void checkFullArgument(const std::string& name, const std::string& value, bool bParsingFile);
180        void checkShortcut(const std::string& shortcut, const std::string& value, bool bParsingFile);
181
182        /**
183            Tells whether we parsed for the first time. The CommmandLineArguments are added before main().
184            So when we call parse() the first time, we need to create a map with all shortcuts since these
185            get added after addCommandLineArgument().
186        */
187        bool bFirstTimeParse_;
188
189        //! Holds all pointers to the arguments and serves as a search map by name.
190        std::map<std::string, CommandLineArgument*> cmdLineArgs_;
191        //! Search map by shortcut for the arguments.
192        std::map<std::string, CommandLineArgument*> cmdLineArgsShortcut_;
193    };
194
195    template <>
196    inline void CommandLineParser::getValue<std::string>(const std::string& name, std::string* value)
197    {
198        *value = getArgument(name)->getValue().getString();
199    }
200
201    /**
202    @brief
203        Adds a new CommandLineArgument to the internal map.
204        Note that only such arguments are actually valid.
205    @param name
206        Name of the argument. Shortcut can be added later.
207    @param defaultValue
208        Default value that is used when argument was not given.
209    */
210    template <class T>
211    CommandLineArgument& CommandLineParser::addArgument(const std::string& name, T defaultValue, bool bCommandLineOnly)
212    {
213        OrxAssert(!_getInstance().existsArgument(name),
214            "Cannot add a command line argument with name '" + name + "' twice.");
215        OrxAssert(MultiType(defaultValue).getType() != MT_Type::Bool || MultiType(defaultValue).getBool() != true,
216               "Boolean command line arguments with positive default values are not supported." << std::endl
217            << "Please use SetCommandLineSwitch and adjust your argument: " << name);
218
219        return *(_getInstance().cmdLineArgs_[name] = new CommandLineArgument(name, defaultValue, bCommandLineOnly));
220    }
221}
222
223#endif /* _CommandLine_H__ */
Note: See TracBrowser for help on using the repository browser.