Implementation now in header files

This commit is contained in:
macbishop 2004-09-26 18:31:43 +00:00
parent 35aa53232d
commit 4fcee3ee11
6 changed files with 0 additions and 843 deletions

View File

@ -1,257 +0,0 @@
/******************************************************************************
*
* file: Arg.cpp
*
* 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.
*
*****************************************************************************/
#include <tclap/Arg.h>
#include <tclap/CommandLine.h>
using namespace std;
namespace TCLAP {
// defaults
bool Arg::_ignoreRest = false;
char Arg::_delimiter = ' ';
const char Arg::blankChar = '*';
const char Arg::flagStartChar = '-';
const string Arg::flagStartString = "-";
const string Arg::nameStartString = "--";
const string Arg::ignoreNameString = "ignore_rest";
Arg::Arg(const std::string& flag,
const std::string& name,
const std::string& desc,
bool req,
bool valreq,
Visitor* v) :
_flag(flag),
_name(name),
_description(desc),
_required(req),
_requireLabel("required"),
_valueRequired(valreq),
_alreadySet(false),
_visitor( v ),
_ignoreable(true),
_xorSet(false)
{
if ( _flag.length() > 1 )
throw(ArgException("Argument flag can only be one character long",
toString() ) );
if ( _name != ignoreNameString &&
( _flag == Arg::flagStartString ||
_flag == Arg::nameStartString ||
_flag == " " ) )
throw(ArgException("Argument flag cannot be either '" +
Arg::flagStartString + "' or '" +
Arg::nameStartString + "' or a space.",
toString() ) );
if ( ( _name.find( Arg::flagStartString, 0 ) != string::npos ) ||
( _name.find( Arg::nameStartString, 0 ) != string::npos ) ||
( _name.find( " ", 0 ) != string::npos ) )
throw(ArgException("Argument name cannot contain either '" +
Arg::flagStartString + "' or '" +
Arg::nameStartString + "' or space.",
toString() ) );
}
Arg::~Arg() { }
string Arg::shortID( const string& valueId ) const
{
string id = "";
if ( _flag != "" )
id = Arg::flagStartString + _flag;
else
id = Arg::nameStartString + _name;
string delim = " ";
delim[0] = Arg::_delimiter; // ugly!!!
if ( _valueRequired )
id += delim + "<" + valueId + ">";
if ( !_required )
id = "[" + id + "]";
return id;
}
string Arg::longID( const string& valueId ) const
{
string id = "";
if ( _flag != "" )
{
id += Arg::flagStartString + _flag;
if ( _valueRequired )
id += " <" + valueId + ">";
id += ", ";
}
id += Arg::nameStartString + _name;
if ( _valueRequired )
id += " <" + valueId + ">";
return id;
}
bool Arg::operator==(const Arg& a)
{
if ( ( _flag != "" && _flag == a._flag ) ||
_name == a._name ||
_description == a._description )
return true;
else
return false;
}
// should be overridden
bool Arg::processArg(int* i, vector<string>& args)
{
cerr << "WARNING: Ignoring unknown argument: " << args[*i] << endl;
return false;
}
string Arg::getDescription() const
{
string desc = "";
if ( _required )
desc = "(" + _requireLabel + ") ";
if ( _valueRequired )
desc += "(value required) ";
desc += _description;
return desc;
}
const string& Arg::getFlag() const { return _flag; }
const string& Arg::getName() const { return _name; }
bool Arg::isRequired() const { return _required; }
bool Arg::isValueRequired() const { return _valueRequired; }
bool Arg::isSet() const
{
if ( _alreadySet && !_xorSet )
return true;
else
return false;
}
bool Arg::isIgnoreable() const { return _ignoreable; }
void Arg::setRequireLabel( const string& s)
{
_requireLabel = s;
}
bool Arg::argMatches( const string& argFlag ) const
{
if ( argFlag == Arg::flagStartString + _flag ||
argFlag == Arg::nameStartString + _name )
return true;
else
return false;
}
string Arg::toString() const
{
string s = "";
if ( _flag != "" )
s += Arg::flagStartString + _flag + " ";
s += "(" + Arg::nameStartString + _name + ")";
return s;
}
void Arg::_checkWithVisitor() const
{
if ( _visitor != NULL )
_visitor->visit();
}
/**
* Implementation of trimFlag.
*/
void Arg::trimFlag(string& flag, string& value) const
{
int stop = 0;
for ( int i = 0; (unsigned int)i < flag.length(); i++ )
if ( flag[i] == Arg::_delimiter )
{
stop = i;
break;
}
if ( stop > 1 )
{
value = flag.substr(stop+1);
flag = flag.substr(0,stop);
}
}
/**
* Implementation of _hasBlanks.
*/
bool Arg::_hasBlanks( const string& s ) const
{
for ( int i = 1; (unsigned int)i < s.length(); i++ )
if ( s[i] == Arg::blankChar )
return true;
return false;
}
void Arg::forceRequired()
{
_required = true;
}
void Arg::xorSet()
{
_alreadySet = true;
_xorSet = true;
}
/**
* Overridden by Args that need to added to the end of the list.
*/
void Arg::addToList( list<Arg*>& argList ) const
{
argList.push_front( (Arg*)this );
}
}

View File

@ -1,262 +0,0 @@
/******************************************************************************
*
* file: CmdLine.cpp
*
* 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.
*
*****************************************************************************/
#include <tclap/CommandLine.h>
using namespace std;
namespace TCLAP {
CmdLine::CmdLine(const string& n, const string& m, const string& v )
: _progName(n),
_message(m),
_version(v),
_numRequired(0),
_delimiter(' ')
{
_constructor();
}
CmdLine::CmdLine(const string& m, char delim, const string& v )
: _progName("not_set_yet"),
_message(m),
_version(v),
_numRequired(0),
_delimiter(delim)
{
_constructor();
}
CmdLine::~CmdLine()
{
list<Arg*>::iterator argIter;
list<Visitor*>::iterator visIter;
for( argIter = _argDeleteOnExitList.begin();
argIter != _argDeleteOnExitList.end();
++argIter)
delete *argIter;
for( visIter = _visitorDeleteOnExitList.begin();
visIter != _visitorDeleteOnExitList.end();
++visIter)
delete *visIter;
}
void CmdLine::_constructor()
{
Visitor *v;
Arg::setDelimiter( _delimiter );
v = new HelpVisitor( this );
SwitchArg* help = new SwitchArg("h","help",
"Displays usage information and exits.",
false, v);
add( *help );
deleteOnExit(help);
deleteOnExit(v);
v = new VersionVisitor( this );
SwitchArg* vers = new SwitchArg("v","version",
"Displays version information and exits.",
false, v);
add( *vers );
deleteOnExit(vers);
deleteOnExit(v);
v = new IgnoreRestVisitor();
SwitchArg* ignore = new SwitchArg(Arg::flagStartString,
Arg::ignoreNameString,
"Ignores the rest of the labeled arguments following this flag.",
false, v);
add( *ignore );
deleteOnExit(ignore);
deleteOnExit(v);
}
void CmdLine::xorAdd( vector<Arg*>& ors )
{
_xorHandler.add( ors );
for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
{
(*it)->forceRequired();
(*it)->setRequireLabel( "OR required" );
add( *it );
}
}
void CmdLine::xorAdd( Arg& a, Arg& b )
{
vector<Arg*> ors;
ors.push_back( &a );
ors.push_back( &b );
xorAdd( ors );
}
void CmdLine::add( Arg& a )
{
add( &a );
}
void CmdLine::add( Arg* a )
{
for( ArgIterator iter = _argList.begin(); iter != _argList.end(); iter++ )
if ( *a == *(*iter) )
throw( ArgException( "Argument with same flag/name already exists!",
a->longID() ) );
a->addToList( _argList );
if ( a->isRequired() ) _numRequired++;
}
void CmdLine::version(int exitVal)
{
cout << endl << _progName << " version: " << _version << endl << endl;
exit( exitVal );
}
void CmdLine::_shortUsage( ostream& os )
{
string s = _progName + " " + _xorHandler.shortUsage();
for (ArgIterator it = _argList.begin(); it != _argList.end(); it++)
if ( !_xorHandler.contains( (*it) ) )
s += " " + (*it)->shortID();
spacePrint( os, s, 75, 3, (int)(_progName.length()) + 2 );
}
void CmdLine::_longUsage( ostream& os )
{
_xorHandler.printLongUsage( os );
for (ArgIterator it = _argList.begin(); it != _argList.end(); it++)
if ( !_xorHandler.contains( (*it) ) )
{
spacePrint( os, (*it)->longID(), 75, 3, 3 );
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
os << endl;
}
os << endl;
spacePrint( os, _message, 75, 3, 0 );
}
void CmdLine::usage( int exitVal )
{
cout << endl << "USAGE: " << endl << endl;
_shortUsage( cout );
cout << endl << endl << "Where: " << endl << endl;
_longUsage( cout );
cout << endl;
exit( exitVal );
}
void CmdLine::parse(int argc, char** argv)
{
try {
_progName = argv[0];
// this step is necessary so that we have easy access to mutable strings.
vector<string> args;
for (int i = 1; i < argc; i++)
args.push_back(argv[i]);
int requiredCount = 0;
for (int i = 0; (unsigned int)i < args.size(); i++)
{
bool matched = false;
for (ArgIterator it = _argList.begin(); it != _argList.end(); it++)
{
if ( (*it)->processArg( &i, args ) )
{
requiredCount += _xorHandler.check( *it );
matched = true;
break;
}
}
// checks to see if the argument is an empty combined switch ...
// and if so, then we've actually matched it
if ( !matched && _emptyCombined( args[i] ) )
matched = true;
if ( !matched && !Arg::ignoreRest() )
throw( ArgException("Couldn't find match for argument",args[i]));
}
if ( requiredCount < _numRequired )
throw( ArgException("One or more required arguments missing!") );
if ( requiredCount > _numRequired )
throw( ArgException("Too many arguments!") );
} catch ( ArgException e )
{
cerr << "PARSE ERROR: " << e.argId() << endl
<< " " << e.error() << endl << endl;
cerr << "Brief USAGE: " << endl;
_shortUsage( cerr );
cerr << endl << "For complete USAGE and HELP type: "
<< endl << " " << _progName << " --help" << endl << endl;
exit(1);
}
}
bool CmdLine::_emptyCombined(const string& s)
{
if ( s[0] != Arg::flagStartChar )
return false;
for ( int i = 1; (unsigned int)i < s.length(); i++ )
if ( s[i] != Arg::blankChar )
return false;
return true;
}
void CmdLine::deleteOnExit(Arg* ptr)
{
_argDeleteOnExitList.push_back(ptr);
}
void CmdLine::deleteOnExit(Visitor* ptr)
{
_visitorDeleteOnExitList.push_back(ptr);
}
}

View File

@ -1,12 +0,0 @@
lib_LIBRARIES = libtclap.a
libtclap_a_SOURCES = Arg.cpp \
CmdLine.cpp \
SwitchArg.cpp \
XorHandler.cpp \
PrintSensibly.cpp
INCLUDES = -I$(top_srcdir)/include
AM_CXXFLAGS = -Wall

View File

@ -1,88 +0,0 @@
/******************************************************************************
*
* file: PrintSensibly.cpp
*
* Copyright (c) 2004, 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.
*
*****************************************************************************/
#include <tclap/PrintSensibly.h>
using namespace std;
namespace TCLAP {
void spacePrint( ostream& os,
const string& s,
int maxWidth,
int indentSpaces,
int secondLineOffset )
{
int len = (int)(s.length());
if ( (len + indentSpaces > maxWidth) && maxWidth > 0 )
{
int allowedLen = maxWidth - indentSpaces;
int start = 0;
while ( start < len )
{
// find the substring length
int stringLen = min( len - start, allowedLen );
// trim the length so it doesn't end in middle of a word
if ( stringLen == allowedLen )
while ( s[stringLen+start] != ' ' &&
s[stringLen+start] != ',' &&
s[stringLen+start] != '|' )
stringLen--;
// check for newlines
for ( int i = 0; i < stringLen; i++ )
if ( s[start+i] == '\n' )
stringLen = i+1;
// print the indent
for ( int i = 0; i < indentSpaces; i++ )
os << " ";
if ( start == 0 )
{
// handle second line offsets
indentSpaces += secondLineOffset;
// adjust allowed len
allowedLen -= secondLineOffset;
}
os << s.substr(start,stringLen) << endl;
// so we don't start a line with a space
if ( s[stringLen+start] == ' ' )
start++;
start += stringLen;
}
}
else
{
for ( int i = 0; i < indentSpaces; i++ )
os << " ";
os << s << endl;
}
}
}

View File

@ -1,114 +0,0 @@
/******************************************************************************
*
* file: SwitchArg.cpp
*
* 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.
*
*****************************************************************************/
#include <tclap/SwitchArg.h>
#include <tclap/CommandLine.h>
using namespace std;
namespace TCLAP {
SwitchArg::SwitchArg(const string& flag,
const string& name,
const string& desc,
bool _default,
Visitor* v )
: Arg(flag, name, desc, false, false, v),
_value( _default )
{ }
SwitchArg::SwitchArg(const string& flag,
const string& name,
const string& desc,
bool _default,
CmdLine& parser,
Visitor* v )
: Arg(flag, name, desc, false, false, v),
_value( _default )
{
parser.add( this );
}
bool SwitchArg::getValue() { return _value; }
bool SwitchArg::combinedSwitchesMatch(string& combinedSwitches )
{
// make sure this is actually a combined switch
if ( combinedSwitches[0] != Arg::flagStartString[0] )
return false;
// make sure it isn't a long name
if ( combinedSwitches.substr( 0, Arg::nameStartString.length() ) ==
Arg::nameStartString )
return false;
// ok, we're not specifying a ValueArg, so we know that we have
// a combined switch list.
for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
if ( combinedSwitches[i] == _flag[0] )
{
// update the combined switches so this one is no longer present
// this is necessary so that no unlabeled args are matched
// later in the processing.
//combinedSwitches.erase(i,1);
combinedSwitches[i] = Arg::blankChar;
return true;
}
// none of the switches passed in the list match.
return false;
}
bool SwitchArg::processArg(int *i, vector<string>& args)
{
if ( _ignoreable && Arg::ignoreRest() )
return false;
if ( argMatches( args[*i] ) || combinedSwitchesMatch( args[*i] ) )
{
// If we match on a combined switch, then we want to return false
// so that other switches in the combination will also have a
// chance to match.
bool ret = false;
if ( argMatches( args[*i] ) )
ret = true;
if ( _alreadySet )
throw(ArgException("Argument already set!", toString()));
_alreadySet = true;
if ( _value == true )
_value = false;
else
_value = true;
_checkWithVisitor();
return ret;
}
else
return false;
}
}

View File

@ -1,110 +0,0 @@
/******************************************************************************
*
* file: XorHandler.cpp
*
* 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.
*
*****************************************************************************/
#include <tclap/XorHandler.h>
using namespace std;
namespace TCLAP {
XorHandler::XorHandler( )
{ }
void XorHandler::add( vector<Arg*>& ors )
{
_orList.push_back( ors );
}
string XorHandler::shortUsage()
{
string out = "";
for ( int i = 0; (unsigned int)i < _orList.size(); i++ )
{
out += " {";
for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end(); it++ )
out += (*it)->shortID() + "|";
out[out.length()-1] = '}';
}
return out;
}
void XorHandler::printLongUsage( ostream& os )
{
for ( int i = 0; (unsigned int)i < _orList.size(); i++ )
{
for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end();
it++ )
{
spacePrint( os, (*it)->longID(), 75, 3, 3 );
spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
if ( it+1 != _orList[i].end() )
spacePrint(os, "-- OR --", 75, 9);
}
os << endl << endl;
}
}
int XorHandler::check( const Arg* a )
{
// iterate over each XOR list
for ( int i = 0; (unsigned int)i < _orList.size(); i++ )
{
// if the XOR list contains the arg..
if ( find( _orList[i].begin(), _orList[i].end(), a ) !=
_orList[i].end() )
{
// go through and set each arg that is not a
for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end();
it++ )
if ( a != (*it) )
(*it)->xorSet();
// return the number of required args that have now been set
return (int)_orList[i].size();
}
}
if ( a->isRequired() )
return 1;
else
return 0;
}
bool XorHandler::contains( const Arg* a )
{
for ( int i = 0; (unsigned int)i < _orList.size(); i++ )
for ( ArgVectorIterator it = _orList[i].begin();
it != _orList[i].end();
it++ )
if ( a == (*it) )
return true;
return false;
}
}