Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 24, 2008, 12:43:13 AM (16 years ago)
Author:
rgrieder
Message:

Simplified CommandLineArgument by using the new MultiType.
That also enables to get a cmd argument even if you don't know the exact type. It simply gets converted.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/objecthierarchy/src/core/CommandLine.h

    r1764 r2003  
    3535#include "util/Debug.h"
    3636#include "util/Exception.h"
     37#include "util/MultiType.h"
    3738
    3839#define SetCommandLineArgument(name, defaultValue) \
    39     BaseCommandLineArgument& CmdArgumentDummyBoolVar##name \
     40    CommandLineArgument& CmdArgumentDummyBoolVar##name \
    4041    = orxonox::CommandLine::addArgument(#name, defaultValue)
    4142#define SetCommandLineSwitch(name) \
    42     BaseCommandLineArgument& CmdArgumentDummyBoolVar##name \
     43    CommandLineArgument& CmdArgumentDummyBoolVar##name \
    4344    = orxonox::CommandLine::addArgument(#name, false)
    4445
     
    6263    /**
    6364    @brief
    64         Base class for CommandLineArguments.
    65     */
    66     class _CoreExport BaseCommandLineArgument
    67     {
    68         friend class CommandLine;
    69 
    70     public:
    71         //! Tells whether the value has been changed by the command line.
    72         bool hasDefaultValue() const { return bHasDefaultValue_; }
    73         //! Returns the name of the argument.
    74         const std::string& getName() const { return name_; }
    75 
    76         //! Returns the shortcut (example: "-p 22" for "--port 22") of the argument.
    77         //! Evaluates to "" if none there is none.
    78         const std::string& getShortcut() const { return shortcut_; }
    79         //! Sets the shortcut for the argument
    80         BaseCommandLineArgument& setShortcut(const std::string& shortcut)
    81         { this->shortcut_ = shortcut; return *this; }
    82 
    83         //! Returns the usage information
    84         const std::string& getInformation() const { return this->usageInformation_; }
    85         //! Sets the option information when displaying orxonox usage.
    86         BaseCommandLineArgument& setInformation(const std::string& usage)
    87         { this->usageInformation_ = usage; return *this; }
    88 
    89     protected:
    90         BaseCommandLineArgument(const std::string& name)
    91             : bHasDefaultValue_(true)
    92             , name_(name)
    93         { }
    94 
    95         //! Undefined copy constructor
    96         BaseCommandLineArgument(const BaseCommandLineArgument& instance);
    97         virtual ~BaseCommandLineArgument() { }
    98 
    99         //! Parses the value string of a command line argument.
    100         virtual void parse(const std::string& value) = 0;
    101 
    102         //! Tells whether the value has been changed by the command line.
    103         bool bHasDefaultValue_;
    104 
    105     private:
    106         std::string name_;             //!< Name of the argument
    107         std::string shortcut_;         //!< Shortcut of the argument. @see getShortcut().
    108         std::string usageInformation_; //!< Tells about the usage of this parameter
    109     };
    110 
    111 
    112     /**
    113     @brief
    114         Container class for a command line argument of type T.
     65        Container class for a command line argument of any type supported by MultiType.
    11566       
    11667        Whenever you want to have an option specified by a command line switch,
     
    12778        CommandLine class. It is a Singleton, but the public interface is static.
    12879    */
    129     template <class T>
    130     class CommandLineArgument : public BaseCommandLineArgument
    131     {
    132         // Only let CommandLine change the value.
     80    class _CoreExport CommandLineArgument
     81    {
    13382        friend class CommandLine;
    13483
    13584    public:
     85        //! Tells whether the value has been changed by the command line.
     86        bool hasDefaultValue() const { return bHasDefaultValue_; }
     87        //! Returns the name of the argument.
     88        const std::string& getName() const { return name_; }
     89
     90        //! Returns the shortcut (example: "-p 22" for "--port 22") of the argument.
     91        //! Evaluates to "" if none there is none.
     92        const std::string& getShortcut() const { return shortcut_; }
     93        //! Sets the shortcut for the argument
     94        CommandLineArgument& shortcut(const std::string& shortcut)
     95        { this->shortcut_ = shortcut; return *this; }
     96
     97        //! Returns the usage information
     98        const std::string& getInformation() const { return this->usageInformation_; }
     99        //! Sets the option information when displaying orxonox usage.
     100        CommandLineArgument& information(const std::string& usage)
     101        { this->usageInformation_ = usage; return *this; }
     102
    136103        //! Returns the actual value of the argument. Can be equal to default value.
    137         T getValue() const { return value_; }
     104        MultiType getValue() const { return value_; }
    138105        //! Returns the given default value as type T.
    139         T getDefaultValue() const { return defaultValue_; }
     106        MultiType getDefaultValue() const { return defaultValue_; }
    140107
    141108    private:
    142109        //! Constructor initialises both value_ and defaultValue_ with defaultValue.
    143         CommandLineArgument(const std::string& name, const T& defaultValue)
    144             : BaseCommandLineArgument(name)
     110        CommandLineArgument(const std::string& name, const MultiType& defaultValue)
     111            : bHasDefaultValue_(true)
     112            , name_(name)
    145113            , value_(defaultValue)
    146114            , defaultValue_(defaultValue)
    147115        { }
    148116
    149         virtual void parse(const std::string& value);
    150 
    151         T value_;            //!< The actual value
    152         T defaultValue_;     //!< Default value. Should not be changed.
     117        //! Undefined copy constructor
     118        CommandLineArgument(const CommandLineArgument& instance);
     119        ~CommandLineArgument() { }
     120
     121        //! Parses the value string of a command line argument.
     122        void parse(const std::string& value);
     123
     124        //! Tells whether the value has been changed by the command line.
     125        bool bHasDefaultValue_;
     126
     127    private:
     128        std::string name_;             //!< Name of the argument
     129        std::string shortcut_;         //!< Shortcut of the argument. @see getShortcut().
     130        std::string usageInformation_; //!< Tells about the usage of this parameter
     131
     132        MultiType value_;            //!< The actual value
     133        MultiType defaultValue_;     //!< Default value. Should not be changed.
    153134    };
    154 
    155     /**
    156     @brief
    157         Parses a value string for a command line argument.
    158         It simply uses convertValue(Output, Input) to do that.
    159     */
    160     template <class T>
    161     void CommandLineArgument<T>::parse(const std::string& value)
    162     {
    163         if (convertValue(&this->value_, value))
    164         {
    165             this->bHasDefaultValue_ = false;
    166         }
    167         else
    168         {
    169             ThrowException(Argument, "Could not read command line argument '" + getName() + "'.");
    170         }
    171     }
    172 
    173     /**
    174     @brief
    175         Parses a value string for a command line argument.
    176         It simply uses convertValue(Output, Input) to do that.
    177         This is a template specialisation for bool type. That is necessary
    178         so that you can have simple command line switches.
    179     */
    180     template <>
    181     inline void CommandLineArgument<bool>::parse(const std::string& value)
    182     {
    183         if (convertValue(&this->value_, value))
    184         {
    185             this->bHasDefaultValue_ = false;
    186         }
    187         else if (value == "")
    188         {
    189             this->bHasDefaultValue_ = false;
    190             this->value_ = true;
    191         }
    192         else
    193         {
    194             ThrowException(Argument, "Could not read command line argument '" + getName() + "'.");
    195         }
    196     }
    197135
    198136
     
    215153        static std::string getUsageInformation();
    216154
    217         template <class T>
    218         static const CommandLineArgument<T>* getArgument(const std::string& name);
     155        static const CommandLineArgument* getArgument(const std::string& name);
    219156        //! Writes the argument value in the given parameter.
    220157        template <class T>
    221158        static void getValue(const std::string& name, T* value)
    222         { *value = getArgument<T>(name)->getValue(); }
     159        { *value = (T)(getArgument(name)->getValue()); }
     160        static MultiType getValue(const std::string& name)
     161        { return getArgument(name)->getValue(); }
    223162        template <class T>
    224         static BaseCommandLineArgument& addArgument(const std::string& name, T defaultValue);
     163        static CommandLineArgument& addArgument(const std::string& name, T defaultValue);
     164
     165        static bool existsArgument(const std::string& name)
     166        {
     167            std::map<std::string, CommandLineArgument*>::const_iterator it = _getInstance().cmdLineArgs_.find(name);
     168            return !(it == _getInstance().cmdLineArgs_.end());
     169        }
     170
    225171
    226172    private:
     
    237183        void checkShortcut(const std::string& shortcut, const std::string& value);
    238184
    239         template <class T>
    240         BaseCommandLineArgument* createArg(const std::string& name, T defaultValue, Int2Type<0> isString);
    241         template <class T>
    242         BaseCommandLineArgument* createArg(const std::string& name, T defaultValue, Int2Type<1> isString);
    243 
    244185        /**
    245             Tells whether we parse the first expression. The CommmandLineArguments are added before main().
     186            Tells whether we parsed for the first time. The CommmandLineArguments are added before main().
    246187            So when we call parse() the first time, we need to create a map with all shortcuts since these
    247188            get added after addCommandLineArgument().
     
    250191
    251192        //! Holds all pointers to the arguments and serves as a search map by name.
    252         std::map<std::string, BaseCommandLineArgument*> cmdLineArgs_;
     193        std::map<std::string, CommandLineArgument*> cmdLineArgs_;
    253194        //! Search map by chortcut for the arguments.
    254         std::map<std::string, BaseCommandLineArgument*> cmdLineArgsShortcut_;
     195        std::map<std::string, CommandLineArgument*> cmdLineArgsShortcut_;
    255196    };
    256197
    257 
    258     /**
    259     @brief
    260         Retrieves a CommandLineArgument.
    261         The method throws an exception if 'name' was not found or the value could not be converted.
    262     @note
    263         You shold of course not call this method before the command line has been parsed.
    264     */
    265     template <class T>
    266     const CommandLineArgument<T>* CommandLine::getArgument(const std::string& name)
    267     {
    268         std::map<std::string, BaseCommandLineArgument*>::const_iterator it = _getInstance().cmdLineArgs_.find(name);
    269         if (it == _getInstance().cmdLineArgs_.end())
    270         {
    271             ThrowException(Argument, "Could find command line argument '" + name + "'.");
    272         }
    273         else
    274         {
    275             CommandLineArgument<T>* arg = dynamic_cast<CommandLineArgument<T>* >(it->second);
    276             if (arg == 0)
    277             {
    278                 ThrowException(Argument, "Could not convert command line argument value to requested type. " \
    279                     "You should use exactly the same type as predefined.");
    280             }
    281             else
    282             {
    283                 return arg;
    284             }
    285         }
    286     }
    287198
    288199    /**
     
    294205    @param defaultValue
    295206        Default value that is used when argument was not given.
    296     @note
    297         In order to store char* strings as std::string too, there's
    298         little bit of template programming involved:
    299         StaticConversions::exists determines whether T converts to std::string.
    300         Int2Type<int> is then used to call the right function. One returns
    301         a CommandLineArgument<T> and the other CommandLineArgument<std::string>.
    302207    */
    303208    template <class T>
    304     BaseCommandLineArgument& CommandLine::addArgument(const std::string& name, T defaultValue)
    305     {
    306         std::map<std::string, BaseCommandLineArgument*>::const_iterator it = _getInstance().cmdLineArgs_.find(name);
     209    CommandLineArgument& CommandLine::addArgument(const std::string& name, T defaultValue)
     210    {
     211        std::map<std::string, CommandLineArgument*>::const_iterator it = _getInstance().cmdLineArgs_.find(name);
    307212        OrxAssert(it == _getInstance().cmdLineArgs_.end(),
    308213            "Cannot add a command line argument with name '" + name + "' twice.");
    309214
    310         return *(_getInstance().cmdLineArgs_[name] =
    311             _getInstance().createArg(name, defaultValue, Int2Type<StaticConversion<T, std::string>::exists>()));
    312     }
    313 
    314     /**
    315         Returns a new CommandLineArgument<T>.
    316     */
    317     template <class T>
    318     BaseCommandLineArgument* CommandLine::createArg(const std::string& name, T defaultValue, Int2Type<0> isPrime)
    319     {
    320         return new CommandLineArgument<T>(name, defaultValue);
    321     }
    322 
    323     /**
    324         Returns a new CommandLineArgument<std::string>.
    325     */
    326     template <class T>
    327     BaseCommandLineArgument* CommandLine::createArg(const std::string& name, T defaultValue, Int2Type<1> isPrime)
    328     {
    329         return new CommandLineArgument<std::string>(name, defaultValue);
     215        return *(_getInstance().cmdLineArgs_[name] = new CommandLineArgument(name, defaultValue));
    330216    }
    331217}
Note: See TracChangeset for help on using the changeset viewer.