big update

This commit is contained in:
mes5k 2003-04-03 17:59:34 +00:00
parent 52b15b6e6e
commit aca51c23a8
8 changed files with 509 additions and 105 deletions

View File

@ -42,16 +42,18 @@ namespace TCLAP {
*/ */
class Arg class Arg
{ {
private:
static bool _ignoreRest;
protected: protected:
/** /**
* The single char flag used to identify the argument. * The single char flag used to identify the argument.
* This value (preceded by a dash {-}), can be used to identify * This value (preceded by a dash {-}), can be used to identify
* an argument on the command line. The _flag can be blank, * an argument on the command line. The _flag can be blank,
* in fact this is how unlabeled * in fact this is how unlabeled args work. Unlabeled args must
* ValueArgs work. If the _flag is blank, the _labeled valued * override appropriate functions to get correct handling. Note
* should be set to false. Note that the _flag does NOT include * that the _flag does NOT include the dash as part of the flag.
* the dash as part of the flag.
*/ */
string _flag; string _flag;
@ -88,13 +90,6 @@ class Arg
*/ */
bool _alreadySet; 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. * A pointer to a vistitor object.
* The visitor allows special handling to occur as soon as the * The visitor allows special handling to occur as soon as the
@ -108,8 +103,16 @@ class Arg
*/ */
void _checkWithVisitor() const; void _checkWithVisitor() const;
/**
* Whether this argument can be ignored, if desired.
*/
bool _ignoreable;
public: public:
static void beginIgnoring() { Arg::_ignoreRest = true; }
static bool ignoreRest() { return Arg::_ignoreRest; }
/** /**
* Primary constructor. * Primary constructor.
*/ */
@ -142,7 +145,6 @@ class Arg
*/ */
~Arg(); ~Arg();
/** /**
* Processes the argument. * Processes the argument.
* This is the method that handles the parsing and value assignment * 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 * emits that an argument has matched and is being ignored. This
* should never really be used, any subclass should implement its * should never really be used, any subclass should implement its
* own version of processArg. * own version of processArg.
* \param int* i - Pointer the the current argument in the list. * \param i - Pointer the the current argument in the list.
* \param int argc - Number of arguments. Passed in from main(). * \param args - Mutable list of strings. What is
* \param char** argv - List of strings. Passed in from main(). * passed in from main.
*/ */
virtual bool processArg(int *i, int argc, char** argv); virtual bool processArg(int *i, vector<string>& args);
/** /**
* Operator ==. * 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. * Returns the argument flag.
@ -176,7 +178,7 @@ class Arg
/** /**
* Returns the argument description. * Returns the argument description.
*/ */
const string& getDescription() const; string getDescription() const;
/** /**
* Indicates whether the argument is required. * Indicates whether the argument is required.
@ -194,10 +196,9 @@ class Arg
bool isAlreadySet() const; bool isAlreadySet() const;
/** /**
* Indicates whether the _flag value is blank or not. * Indicates whether the argument can be ignored, if desired.
* If the _flag is blank, the argument is considered unlabeled.
*/ */
bool isLabeled() const; bool isIgnoreable() const;
/** /**
* A method that tests whether a string matches this argument. * A method that tests whether a string matches this argument.
@ -211,7 +212,18 @@ class Arg
* Returns a simple string representation of the argument. * Returns a simple string representation of the argument.
* Primarily for debugging. * 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;
}; };
/** /**

View File

@ -25,7 +25,9 @@
#include <tclap/Arg.h> #include <tclap/Arg.h>
#include <tclap/SwitchArg.h> #include <tclap/SwitchArg.h>
#include <tclap/MultiArg.h> #include <tclap/MultiArg.h>
#include <tclap/UnlabeledMultiArg.h>
#include <tclap/ValueArg.h> #include <tclap/ValueArg.h>
#include <tclap/UnlabeledValueArg.h>
#include <tclap/Visitor.h> #include <tclap/Visitor.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -69,6 +71,7 @@ class CmdLine
#include "HelpVisitor.h" #include "HelpVisitor.h"
#include "VersionVisitor.h" #include "VersionVisitor.h"
#include "IgnoreRestVisitor.h"
#endif #endif

View File

@ -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 <tclap/Visitor.h>
#include <tclap/Arg.h>
namespace TCLAP {
class IgnoreRestVisitor: public Visitor
{
public:
IgnoreRestVisitor() : Visitor() {};
void visit() { Arg::beginIgnoring(); }
};
}
#endif

View File

@ -20,8 +20,8 @@
*****************************************************************************/ *****************************************************************************/
#ifndef __MULTIPLE_UNLABELED_ARGUMENT_HH__ #ifndef __MULTIPLE_ARGUMENT_HH__
#define __MULTIPLE_UNLABELED_ARGUMENT_HH__ #define __MULTIPLE_ARGUMENT_HH__
#include <string> #include <string>
#include <vector> #include <vector>
@ -39,28 +39,40 @@ class MultiArg : public Arg
vector<T> _values; vector<T> _values;
string _typeDesc;
void _extractValue(int i, vector<string>& args);
public: public:
MultiArg( const string& desc, MultiArg( const string& flag,
const string& name,
const string& desc,
bool req,
const string& typeDesc,
Visitor* v = NULL); Visitor* v = NULL);
~MultiArg(); ~MultiArg();
bool processArg(int* i, int argc, char** argv); virtual bool processArg(int* i, vector<string>& args);
const vector<T>& getValue() ; const vector<T>& getValue() ;
virtual string shortID(const string& val="val") const;
virtual string longID(const string& val="val") const;
}; };
template<class T> template<class T>
MultiArg<T>::MultiArg(const string& desc, Visitor* v) MultiArg<T>::MultiArg(const string& flag,
const string& name,
: Arg( "", // flag const string& desc,
"...", // name bool req,
desc, // description const string& typeDesc,
false, // required Visitor* v)
true, : Arg( flag, name, desc, req, true, v ),
v) // value required _typeDesc( typeDesc )
{ }; { };
template<class T> template<class T>
@ -70,12 +82,32 @@ template<class T>
const vector<T>& MultiArg<T>::getValue() { return _values; }; const vector<T>& MultiArg<T>::getValue() { return _values; };
template<class T> template<class T>
bool MultiArg<T>::processArg(int *i, int argc, char** argv) bool MultiArg<T>::processArg(int *i, vector<string>& 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<class T>
void MultiArg<T>::_extractValue(int i, vector<string>& args)
{ {
// can be called multiple times
T temp; T temp;
string ss(argv[*i]); istringstream is(args[i]);
istringstream is(ss);
is >> temp; is >> temp;
if ( is.fail() ) if ( is.fail() )
throw( ArgException("Couldn't read argument value!", toString())); throw( ArgException("Couldn't read argument value!", toString()));
@ -83,8 +115,22 @@ bool MultiArg<T>::processArg(int *i, int argc, char** argv)
_values.push_back(temp); _values.push_back(temp);
_checkWithVisitor(); _checkWithVisitor();
}
return true; template<class T>
string MultiArg<T>::shortID(const string& val) const
{
string id = Arg::shortID(_typeDesc) + " ... ";
return id;
}
template<class T>
string MultiArg<T>::longID(const string& val) const
{
string id = Arg::longID(_typeDesc) + " (accepted multiple times)";
return id;
} }
} }

View File

@ -39,6 +39,7 @@ class SwitchArg : public Arg
bool _value; bool _value;
public: public:
SwitchArg(const string& flag, SwitchArg(const string& flag,
@ -49,11 +50,14 @@ class SwitchArg : public Arg
~SwitchArg(); ~SwitchArg();
bool processArg(int* i, int argc, char** argv); virtual bool processArg(int* i, vector<string>& args);
bool combinedSwitchesMatch(string& combined);
bool getValue() ; bool getValue() ;
}; };
} }
#endif #endif

View File

@ -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 <string>
#include <vector>
#include <sstream>
#include <tclap/Visitor.h>
using namespace std;
namespace TCLAP {
template<class T>
class UnlabeledMultiArg : public MultiArg<T>
{
public:
UnlabeledMultiArg( const string& name,
const string& desc,
const string& typeDesc,
bool ignoreable = false,
Visitor* v = NULL );
virtual bool processArg(int* i, vector<string>& 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<class T>
UnlabeledMultiArg<T>::UnlabeledMultiArg(const string& name,
const string& desc,
const string& typeDesc,
bool ignoreable,
Visitor* v)
: MultiArg<T>("", name, desc, false, typeDesc, v)
{
_ignoreable = ignoreable;
};
template<class T>
bool UnlabeledMultiArg<T>::processArg(int *i, vector<string>& args)
{
// never ignore an unlabeled multi arg
_extractValue( *i, args );
return true;
}
template<class T>
string UnlabeledMultiArg<T>::shortID(const string& val) const
{
string id = "<" + _typeDesc + "> ...";
return id;
}
template<class T>
string UnlabeledMultiArg<T>::longID(const string& val) const
{
string id = "<" + _typeDesc + "> (accepted multiple times)";
return id;
}
template<class T>
bool UnlabeledMultiArg<T>::operator==(const Arg& a) const
{
if ( _name == a.getName() || _description == a.getDescription() )
return true;
else
return false;
}
}
#endif

View File

@ -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 <string>
#include <vector>
#include <sstream>
#include <tclap/Visitor.h>
#include <tclap/Arg.h>
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 T>
class UnlabeledValueArg : public ValueArg<T>
{
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<string>& 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<class T>
UnlabeledValueArg<T>::UnlabeledValueArg(const string& name,
const string& desc,
T val,
const string& typeDesc,
bool ignoreable,
Visitor* v)
: ValueArg<T>("", name, desc, true, val, typeDesc, v)
{
_ignoreable = ignoreable;
};
/**
* Implementation of processArg().
*/
template<class T>
bool UnlabeledValueArg<T>::processArg(int *i, vector<string>& args)
{
// never ignore an unlabeled arg
if ( _alreadySet )
return false;
_extractValue( *i, args );
_alreadySet = true;
return true;
}
/**
* Overriding shortID for specific output.
*/
template<class T>
string UnlabeledValueArg<T>::shortID(const string& val) const
{
string id = "<" + _typeDesc + ">";
return id;
}
/**
* Overriding longID for specific output.
*/
template<class T>
string UnlabeledValueArg<T>::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<class T>
bool UnlabeledValueArg<T>::operator==(const Arg& a ) const
{
if ( _name == a.getName() || _description == a.getDescription() )
return true;
else
return false;
}
}
#endif

View File

@ -34,11 +34,12 @@ using namespace std;
namespace TCLAP { 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 * 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 * 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 * on the command line. While there is nothing stopping you from creating
* have a flag specified, making this an unlabled argument. * an unflagged ValueArg, it is unwise and would cause significant problems.
* Instead use an UnlabeledValueArg.
*/ */
template<class T> template<class T>
class ValueArg : public Arg class ValueArg : public Arg
@ -53,9 +54,22 @@ class ValueArg : public Arg
T _value; 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<string>& args );
public: public:
@ -65,20 +79,29 @@ class ValueArg : public Arg
* but that would make you a bad person. It would also cause * but that would make you a bad person. It would also cause
* an exception to be thrown. If you want an unlabeled argument, * an exception to be thrown. If you want an unlabeled argument,
* use the other constructor. * 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, ValueArg(const string& flag,
const string& name, const string& name,
const string& desc, const string& desc,
bool req, bool req,
T value, T value,
Visitor* v = NULL); const string& typeDesc,
/**
* Unlabeled ValueArg constructor.
*/
ValueArg(const string& name,
const string& desc,
T value,
Visitor* v = NULL); Visitor* v = NULL);
/** /**
@ -91,21 +114,33 @@ class ValueArg : public Arg
* This re-implements the Arg version of this method to set the * This re-implements the Arg version of this method to set the
* _value of the argument appropriately. It knows the difference * _value of the argument appropriately. It knows the difference
* between labeled and unlabeled. * between labeled and unlabeled.
* \param int* i - Pointer the the current argument in the list. * \param i - Pointer the the current argument in the list.
* \param int argc - Number of arguments. Passed in from main(). * \param args - Mutable list of strings. Passed
* \param char** argv - List of strings. Passed in from main(). * in from main().
*/ */
virtual bool processArg(int* i, int argc, char** argv); virtual bool processArg(int* i, vector<string>& args );
/** /**
* Returns the value of the argument. * Returns the value of the argument.
*/ */
T& getValue() ; 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<class T> template<class T>
ValueArg<T>::ValueArg(const string& flag, ValueArg<T>::ValueArg(const string& flag,
@ -113,25 +148,11 @@ ValueArg<T>::ValueArg(const string& flag,
const string& desc, const string& desc,
bool req, bool req,
T val, T val,
const string& typeDesc,
Visitor* v) Visitor* v)
: Arg(flag, name, desc, req, true, v), : Arg(flag, name, desc, req, true, v),
_value( val ) _value( val ),
{ _typeDesc( typeDesc )
if ( _flag == "" )
throw( ArgException( "No flag specified for labeled ValueArg!",
toString() ) );
};
/**
* Unlabeled constructor implemenation.
*/
template<class T>
ValueArg<T>::ValueArg(const string& name,
const string& desc,
T val,
Visitor* v)
: Arg("", name, desc, true, true, v),
_value( val )
{ }; { };
/** /**
@ -150,11 +171,12 @@ T& ValueArg<T>::getValue() { return _value; };
* Implementation of processArg(). * Implementation of processArg().
*/ */
template<class T> template<class T>
bool ValueArg<T>::processArg(int *i, int argc, char** argv) bool ValueArg<T>::processArg(int *i, vector<string>& args)
{ {
if ( _labeled ) if ( _ignoreable && Arg::ignoreRest() )
{ return false;
string flag = argv[*i];
string flag = args[*i];
if ( argMatches( flag ) ) if ( argMatches( flag ) )
{ {
@ -162,9 +184,9 @@ bool ValueArg<T>::processArg(int *i, int argc, char** argv)
throw( ArgException("Argument already set!", toString()) ); throw( ArgException("Argument already set!", toString()) );
(*i)++; (*i)++;
if (*i < argc ) if (*i < args.size() )
{ {
_extractValue( *i, argv); _extractValue( *i, args);
_alreadySet = true; _alreadySet = true;
@ -175,40 +197,41 @@ bool ValueArg<T>::processArg(int *i, int argc, char** argv)
else else
throw( ArgException("Missing a value for this argument!", throw( ArgException("Missing a value for this argument!",
toString() ) ); toString() ) );
} }
else else
return false; 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. * Implementation of _extractValue.
*/ */
template<class T> template<class T>
void ValueArg<T>::_extractValue(int i, char** argv) void ValueArg<T>::_extractValue(int i, vector<string>& args)
{ {
string ss(argv[i]); istringstream is(args[i]);
istringstream is(ss);
is >> _value; is >> _value;
if ( is.fail() ) if ( is.fail() )
throw( ArgException("Couldn't read argument value!", toString() ) ); throw( ArgException("Couldn't read argument value!", toString() ) );
} }
/**
* Implementation of shortID.
*/
template<class T>
string ValueArg<T>::shortID(const string& val) const
{
return Arg::shortID( _typeDesc );
}
/**
* Implementation of longID.
*/
template<class T>
string ValueArg<T>::longID(const string& val) const
{
return Arg::longID( _typeDesc );
}
} }
#endif #endif