diff --git a/include/tclap/Arg.h b/include/tclap/Arg.h index 97dcd77..4e0e238 100644 --- a/include/tclap/Arg.h +++ b/include/tclap/Arg.h @@ -42,16 +42,18 @@ namespace TCLAP { */ class Arg { + private: + static bool _ignoreRest; + protected: /** * The single char flag used to identify the argument. * This value (preceded by a dash {-}), can be used to identify * an argument on the command line. The _flag can be blank, - * in fact this is how unlabeled - * ValueArgs work. If the _flag is blank, the _labeled valued - * should be set to false. Note that the _flag does NOT include - * the dash as part of the flag. + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. */ string _flag; @@ -88,13 +90,6 @@ class Arg */ bool _alreadySet; - /** - * Indicates whether the _flag is set or not. - * If the argument doesn't require a flag then the argument is - * handled differently. - */ - bool _labeled; - /** * A pointer to a vistitor object. * The visitor allows special handling to occur as soon as the @@ -107,9 +102,17 @@ class Arg * Performs the special handling described by the Vistitor. */ void _checkWithVisitor() const; - + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + public: + static void beginIgnoring() { Arg::_ignoreRest = true; } + static bool ignoreRest() { return Arg::_ignoreRest; } + /** * Primary constructor. */ @@ -142,7 +145,6 @@ class Arg */ ~Arg(); - /** * Processes the argument. * This is the method that handles the parsing and value assignment @@ -150,18 +152,18 @@ class Arg * emits that an argument has matched and is being ignored. This * should never really be used, any subclass should implement its * own version of processArg. - * \param int* i - Pointer the the current argument in the list. - * \param int argc - Number of arguments. Passed in from main(). - * \param char** argv - List of strings. Passed in from main(). + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. */ - virtual bool processArg(int *i, int argc, char** argv); + virtual bool processArg(int *i, vector& args); /** * Operator ==. - * Equality operator. + * Equality operator. Must be virtual to handle unlabeled args. */ - bool operator==(const Arg&); + virtual bool operator==(const Arg&); /** * Returns the argument flag. @@ -176,7 +178,7 @@ class Arg /** * Returns the argument description. */ - const string& getDescription() const; + string getDescription() const; /** * Indicates whether the argument is required. @@ -194,10 +196,9 @@ class Arg bool isAlreadySet() const; /** - * Indicates whether the _flag value is blank or not. - * If the _flag is blank, the argument is considered unlabeled. + * Indicates whether the argument can be ignored, if desired. */ - bool isLabeled() const; + bool isIgnoreable() const; /** * A method that tests whether a string matches this argument. @@ -211,7 +212,18 @@ class Arg * Returns a simple string representation of the argument. * Primarily for debugging. */ - string toString() const; + virtual string toString() const; + + /** + * Returns a short ID for the usage. + */ + virtual string shortID( const string& valueId = "val" ) const; + + /** + * Returns a long ID for the usage. + */ + virtual string longID( const string& valueId = "val" ) const; + }; /** diff --git a/include/tclap/CmdLine.h b/include/tclap/CmdLine.h index 2b3cf0f..b7fc930 100644 --- a/include/tclap/CmdLine.h +++ b/include/tclap/CmdLine.h @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -69,6 +71,7 @@ class CmdLine #include "HelpVisitor.h" #include "VersionVisitor.h" +#include "IgnoreRestVisitor.h" #endif diff --git a/include/tclap/IgnoreRestVisitor.h b/include/tclap/IgnoreRestVisitor.h new file mode 100644 index 0000000..fa67856 --- /dev/null +++ b/include/tclap/IgnoreRestVisitor.h @@ -0,0 +1,41 @@ + +/****************************************************************************** + * + * file: IgnoreRestVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef __IGNORE_REST_VISITOR_H__ +#define __IGNORE_REST_VISITOR_H__ + +#include +#include + +namespace TCLAP { + +class IgnoreRestVisitor: public Visitor +{ + public: + IgnoreRestVisitor() : Visitor() {}; + + void visit() { Arg::beginIgnoring(); } +}; + +} + +#endif diff --git a/include/tclap/MultiArg.h b/include/tclap/MultiArg.h index 91583b2..5569304 100644 --- a/include/tclap/MultiArg.h +++ b/include/tclap/MultiArg.h @@ -20,8 +20,8 @@ *****************************************************************************/ -#ifndef __MULTIPLE_UNLABELED_ARGUMENT_HH__ -#define __MULTIPLE_UNLABELED_ARGUMENT_HH__ +#ifndef __MULTIPLE_ARGUMENT_HH__ +#define __MULTIPLE_ARGUMENT_HH__ #include #include @@ -38,29 +38,41 @@ class MultiArg : public Arg protected: vector _values; + + string _typeDesc; + + void _extractValue(int i, vector& args); public: - MultiArg( const string& desc, + MultiArg( const string& flag, + const string& name, + const string& desc, + bool req, + const string& typeDesc, Visitor* v = NULL); ~MultiArg(); - bool processArg(int* i, int argc, char** argv); + virtual bool processArg(int* i, vector& args); const vector& getValue() ; + + virtual string shortID(const string& val="val") const; + virtual string longID(const string& val="val") const; + }; template -MultiArg::MultiArg(const string& desc, Visitor* v) - -: Arg( "", // flag - "...", // name - desc, // description - false, // required - true, - v) // value required +MultiArg::MultiArg(const string& flag, + const string& name, + const string& desc, + bool req, + const string& typeDesc, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _typeDesc( typeDesc ) { }; template @@ -70,12 +82,32 @@ template const vector& MultiArg::getValue() { return _values; }; template -bool MultiArg::processArg(int *i, int argc, char** argv) +bool MultiArg::processArg(int *i, vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] ) ) + { + (*i)++; + if ( *i < args.size() ) + { + _extractValue( *i, args ); + return true; + } + else + throw( ArgException("Missing a value for this argument!", + toString() ) ); + } + else + return false; +} + +template +void MultiArg::_extractValue(int i, vector& args) { - // can be called multiple times T temp; - string ss(argv[*i]); - istringstream is(ss); + istringstream is(args[i]); is >> temp; if ( is.fail() ) throw( ArgException("Couldn't read argument value!", toString())); @@ -83,8 +115,22 @@ bool MultiArg::processArg(int *i, int argc, char** argv) _values.push_back(temp); _checkWithVisitor(); +} - return true; +template +string MultiArg::shortID(const string& val) const +{ + string id = Arg::shortID(_typeDesc) + " ... "; + + return id; +} + +template +string MultiArg::longID(const string& val) const +{ + string id = Arg::longID(_typeDesc) + " (accepted multiple times)"; + + return id; } } diff --git a/include/tclap/SwitchArg.h b/include/tclap/SwitchArg.h index c200cd9..1d78a44 100644 --- a/include/tclap/SwitchArg.h +++ b/include/tclap/SwitchArg.h @@ -38,7 +38,8 @@ class SwitchArg : public Arg protected: bool _value; - + + public: SwitchArg(const string& flag, @@ -49,11 +50,14 @@ class SwitchArg : public Arg ~SwitchArg(); - bool processArg(int* i, int argc, char** argv); + virtual bool processArg(int* i, vector& args); + + bool combinedSwitchesMatch(string& combined); bool getValue() ; }; + } #endif diff --git a/include/tclap/UnlabeledMultiArg.h b/include/tclap/UnlabeledMultiArg.h new file mode 100644 index 0000000..217575a --- /dev/null +++ b/include/tclap/UnlabeledMultiArg.h @@ -0,0 +1,101 @@ + +/****************************************************************************** + * + * file: UnlabeledMultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef __MULTIPLE_UNLABELED_ARGUMENT_HH__ +#define __MULTIPLE_UNLABELED_ARGUMENT_HH__ + +#include +#include +#include +#include + +using namespace std; + +namespace TCLAP { + +template +class UnlabeledMultiArg : public MultiArg +{ + public: + + UnlabeledMultiArg( const string& name, + const string& desc, + const string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL ); + + virtual bool processArg(int* i, vector& args); + + virtual string shortID(const string& val="val") const; + virtual string longID(const string& val="val") const; + virtual bool operator==(const Arg& a) const; + +}; + +template +UnlabeledMultiArg::UnlabeledMultiArg(const string& name, + const string& desc, + const string& typeDesc, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, false, typeDesc, v) +{ + _ignoreable = ignoreable; +}; + +template +bool UnlabeledMultiArg::processArg(int *i, vector& args) +{ + // never ignore an unlabeled multi arg + + _extractValue( *i, args ); + return true; +} + +template +string UnlabeledMultiArg::shortID(const string& val) const +{ + string id = "<" + _typeDesc + "> ..."; + + return id; +} + +template +string UnlabeledMultiArg::longID(const string& val) const +{ + string id = "<" + _typeDesc + "> (accepted multiple times)"; + + return id; +} + +template +bool UnlabeledMultiArg::operator==(const Arg& a) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +} + +#endif diff --git a/include/tclap/UnlabeledValueArg.h b/include/tclap/UnlabeledValueArg.h new file mode 100644 index 0000000..1713653 --- /dev/null +++ b/include/tclap/UnlabeledValueArg.h @@ -0,0 +1,174 @@ + +/****************************************************************************** + * + * file: UnlabeledValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef __UNLABELED_VALUE_ARGUMENT_HH__ +#define __UNLABELED_VALUE_ARGUMENT_HH__ + +#include +#include +#include +#include +#include + +using namespace std; + +namespace TCLAP { + +/** + * The basic unlabeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when an UnlabeledValueArg + * is reached in the list of args that the CmdLine iterates over. + */ +template +class UnlabeledValueArg : public ValueArg +{ + public: + + /** + * UnlabeledValueArg constructor. + * Note that this constructor does not have a required flag. Any + * unlabeled argument added to the CmdLine is by default required. + * If you want optional, unlabeled arguments then use an + * UnlabeledMultiArg. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg(const string& name, + const string& desc, + T value, + const string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int* i, vector& args ); + + /** + * Overrides shortID for specific behavior. + */ + virtual string shortID(const string& val="val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual string longID(const string& val="val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg& a ) const; + +}; + +/** + * Constructor implemenation. + */ +template +UnlabeledValueArg::UnlabeledValueArg(const string& name, + const string& desc, + T val, + const string& typeDesc, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, true, val, typeDesc, v) +{ + _ignoreable = ignoreable; +}; + +/** + * Implementation of processArg(). + */ +template +bool UnlabeledValueArg::processArg(int *i, vector& args) +{ + // never ignore an unlabeled arg + + if ( _alreadySet ) + return false; + + _extractValue( *i, args ); + _alreadySet = true; + return true; +} + +/** + * Overriding shortID for specific output. + */ +template +string UnlabeledValueArg::shortID(const string& val) const +{ + string id = "<" + _typeDesc + ">"; + + return id; +} + +/** + * Overriding longID for specific output. + */ +template +string UnlabeledValueArg::longID(const string& val) const +{ + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + string id = "<" + _typeDesc + ">"; + + return id; +} + +/** + * Overriding operator== for specific behavior. + */ +template +bool UnlabeledValueArg::operator==(const Arg& a ) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +} +#endif diff --git a/include/tclap/ValueArg.h b/include/tclap/ValueArg.h index b97d28c..7dc2d5b 100644 --- a/include/tclap/ValueArg.h +++ b/include/tclap/ValueArg.h @@ -34,11 +34,12 @@ using namespace std; namespace TCLAP { /** - * The basic argument that parses a value. + * The basic labeled argument that parses a value. * This is a template class, which means the type T defines the type * that a given object will attempt to parse when the flag/name is matched - * on the command line. Note that a ValueArg does not necessarily have to - * have a flag specified, making this an unlabled argument. + * on the command line. While there is nothing stopping you from creating + * an unflagged ValueArg, it is unwise and would cause significant problems. + * Instead use an UnlabeledValueArg. */ template class ValueArg : public Arg @@ -53,10 +54,23 @@ class ValueArg : public Arg T _value; /** - * Extracts the value at position i from the argv list. + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. */ - void _extractValue( int i, char** argv ); - + string _typeDesc; + + /** + * Extracts the string at position i from the args list. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param i - The index of the argument to extract. + * \param args - Mutable list of strings. + */ + void _extractValue( int i, vector& args ); + public: /** @@ -65,22 +79,31 @@ class ValueArg : public Arg * but that would make you a bad person. It would also cause * an exception to be thrown. If you want an unlabeled argument, * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. */ ValueArg(const string& flag, const string& name, const string& desc, bool req, T value, + const string& typeDesc, Visitor* v = NULL); - /** - * Unlabeled ValueArg constructor. - */ - ValueArg(const string& name, - const string& desc, - T value, - Visitor* v = NULL); - /** * Destructor. */ @@ -91,21 +114,33 @@ class ValueArg : public Arg * This re-implements the Arg version of this method to set the * _value of the argument appropriately. It knows the difference * between labeled and unlabeled. - * \param int* i - Pointer the the current argument in the list. - * \param int argc - Number of arguments. Passed in from main(). - * \param char** argv - List of strings. Passed in from main(). + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). */ - virtual bool processArg(int* i, int argc, char** argv); + virtual bool processArg(int* i, vector& args ); /** * Returns the value of the argument. */ T& getValue() ; + + /** + * Specialization of shortID. + */ + virtual string shortID(const string& val = "val") const; + + /** + * Specialization of longID. + */ + virtual string longID(const string& val = "val") const; + }; + /** - * Labeled constructor implementation. + * Constructor implementation. */ template ValueArg::ValueArg(const string& flag, @@ -113,25 +148,11 @@ ValueArg::ValueArg(const string& flag, const string& desc, bool req, T val, + const string& typeDesc, Visitor* v) : Arg(flag, name, desc, req, true, v), - _value( val ) -{ - if ( _flag == "" ) - throw( ArgException( "No flag specified for labeled ValueArg!", - toString() ) ); -}; - -/** - * Unlabeled constructor implemenation. - */ -template -ValueArg::ValueArg(const string& name, - const string& desc, - T val, - Visitor* v) -: Arg("", name, desc, true, true, v), - _value( val ) + _value( val ), + _typeDesc( typeDesc ) { }; /** @@ -150,11 +171,12 @@ T& ValueArg::getValue() { return _value; }; * Implementation of processArg(). */ template -bool ValueArg::processArg(int *i, int argc, char** argv) +bool ValueArg::processArg(int *i, vector& args) { - if ( _labeled ) - { - string flag = argv[*i]; + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + string flag = args[*i]; if ( argMatches( flag ) ) { @@ -162,9 +184,9 @@ bool ValueArg::processArg(int *i, int argc, char** argv) throw( ArgException("Argument already set!", toString()) ); (*i)++; - if (*i < argc ) + if (*i < args.size() ) { - _extractValue( *i, argv); + _extractValue( *i, args); _alreadySet = true; @@ -175,40 +197,41 @@ bool ValueArg::processArg(int *i, int argc, char** argv) else throw( ArgException("Missing a value for this argument!", toString() ) ); - } else return false; - } - else - { - if ( _alreadySet ) - return false; - - if ( *i < argc ) - { - _extractValue( *i, argv ); - _alreadySet = true; - return true; - } - else - throw( ArgException("Missing a value for this argument!", - toString())); - } } /** * Implementation of _extractValue. */ template -void ValueArg::_extractValue(int i, char** argv) +void ValueArg::_extractValue(int i, vector& args) { - string ss(argv[i]); - istringstream is(ss); + istringstream is(args[i]); is >> _value; if ( is.fail() ) throw( ArgException("Couldn't read argument value!", toString() ) ); } +/** + * Implementation of shortID. + */ +template +string ValueArg::shortID(const string& val) const +{ + return Arg::shortID( _typeDesc ); +} + +/** + * Implementation of longID. + */ +template +string ValueArg::longID(const string& val) const +{ + return Arg::longID( _typeDesc ); +} + + } #endif