Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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