Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: sandbox_qt/src/libraries/core/CommandLineParser.h @ 7428

Last change on this file since 7428 was 7424, checked in by rgrieder, 14 years ago

Added CommandlineParser again and adjusted it to work with QVariant instead of MultiType.
Also removed obsolete Game class.

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