Program Listing for File cmd_line.hpp
↰ Return to documentation for file (include/ecl/command_line/cmd_line.hpp
)
/*****************************************************************************
** Ifdefs
*****************************************************************************/
#ifndef TCLAP_CMDLINE_H
#define TCLAP_CMDLINE_H
#include "switch_arg.hpp"
#include "multi_switch_arg.hpp"
#include "unlabeled_value_arg.hpp"
#include "unlabeled_multi_arg.hpp"
#include "xor_handler.hpp"
#include "help_visitor.hpp"
#include "version_visitor.hpp"
#include "ignore_rest_visitor.hpp"
#include "cmd_line_output.hpp"
#include "std_output.hpp"
#include "constraint.hpp"
#include "values_constraint.hpp"
#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <iomanip>
#include <algorithm>
namespace ecl {
class CmdLine : public CmdLineInterface
{
protected:
std::list<Arg*> _argList;
std::string _progName;
std::string _message;
std::string _version;
int _numRequired;
char _delimiter;
XorHandler _xorHandler;
std::list<Arg*> _argDeleteOnExitList;
std::list<Visitor*> _visitorDeleteOnExitList;
CmdLineOutput* _output;
bool _emptyCombined(const std::string& s);
void deleteOnExit(Arg* ptr);
void deleteOnExit(Visitor* ptr);
private:
void _constructor();
bool _userSetOutput;
bool _helpAndVersion;
public:
CmdLine(const std::string& message,
const char delimiter = ' ',
const std::string& version = "none",
bool helpAndVersion = true);
virtual ~CmdLine();
void add( Arg& a );
void add( Arg* a );
void xorAdd( Arg& a, Arg& b );
void xorAdd( std::vector<Arg*>& xors );
void parse(int argc, char** argv);
CmdLineOutput* getOutput();
void setOutput(CmdLineOutput* co);
std::string& getVersion();
std::string& getProgramName();
std::list<Arg*>& getArgList();
XorHandler& getXorHandler();
char getDelimiter();
std::string& getMessage();
bool hasHelpAndVersion();
};
//Begin CmdLine.cpp
inline CmdLine::CmdLine(const std::string& m,
char delim,
const std::string& v,
bool help )
: _progName("not_set_yet"),
_message(m),
_version(v),
_numRequired(0),
_delimiter(delim),
_userSetOutput(false),
_helpAndVersion(help)
{
_constructor();
}
inline CmdLine::~CmdLine()
{
ArgListIterator argIter;
VisitorListIterator visIter;
for( argIter = _argDeleteOnExitList.begin();
argIter != _argDeleteOnExitList.end();
++argIter)
delete *argIter;
for( visIter = _visitorDeleteOnExitList.begin();
visIter != _visitorDeleteOnExitList.end();
++visIter)
delete *visIter;
if ( !_userSetOutput )
delete _output;
}
inline void CmdLine::_constructor()
{
_output = new StdOutput;
Arg::setDelimiter( _delimiter );
Visitor* v;
if ( _helpAndVersion )
{
v = new HelpVisitor( this, &_output );
SwitchArg* help = new SwitchArg("h","help",
"Displays usage information and exits.",
false, v);
add( help );
deleteOnExit(help);
deleteOnExit(v);
v = new VersionVisitor( this, &_output );
SwitchArg* vers = new SwitchArg("","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);
}
inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
{
_xorHandler.add( ors );
for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
{
(*it)->forceRequired();
(*it)->setRequireLabel( "OR required" );
add( *it );
}
}
inline void CmdLine::xorAdd( Arg& a, Arg& b )
{
std::vector<Arg*> ors;
ors.push_back( &a );
ors.push_back( &b );
xorAdd( ors );
}
inline void CmdLine::add( Arg& a )
{
add( &a );
}
inline void CmdLine::add( Arg* a )
{
for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
if ( *a == *(*it) )
throw( SpecificationException(
"Argument with same flag/name already exists!",
a->longID() ) );
a->addToList( _argList );
if ( a->isRequired() )
_numRequired++;
}
inline void CmdLine::parse(int argc, char** argv)
{
try {
_progName = argv[0];
// this step is necessary so that we have easy access to mutable strings.
std::vector<std::string> args;
for (int i = 1; i < argc; i++)
args.push_back(argv[i]);
int requiredCount = 0;
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
{
bool matched = false;
for (ArgListIterator 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(CmdLineParseException("Couldn't find match for argument",
args[i]));
}
if ( requiredCount < _numRequired )
throw(CmdLineParseException("One or more required arguments missing!"));
if ( requiredCount > _numRequired )
throw(CmdLineParseException("Too many arguments!"));
} catch ( ArgException &e ) {
_output->failure(*this, e); exit(1);
}
}
inline bool CmdLine::_emptyCombined(const std::string& s)
{
if ( s[0] != Arg::flagStartChar() )
return false;
for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
if ( s[i] != Arg::blankChar() )
return false;
return true;
}
inline void CmdLine::deleteOnExit(Arg* ptr)
{
_argDeleteOnExitList.push_back(ptr);
}
inline void CmdLine::deleteOnExit(Visitor* ptr)
{
_visitorDeleteOnExitList.push_back(ptr);
}
inline CmdLineOutput* CmdLine::getOutput()
{
return _output;
}
inline void CmdLine::setOutput(CmdLineOutput* co)
{
_userSetOutput = true;
_output = co;
}
inline std::string& CmdLine::getVersion()
{
return _version;
}
inline std::string& CmdLine::getProgramName()
{
return _progName;
}
inline std::list<Arg*>& CmdLine::getArgList()
{
return _argList;
}
inline XorHandler& CmdLine::getXorHandler()
{
return _xorHandler;
}
inline char CmdLine::getDelimiter()
{
return _delimiter;
}
inline std::string& CmdLine::getMessage()
{
return _message;
}
inline bool CmdLine::hasHelpAndVersion()
{
return _helpAndVersion;
}
//End CmdLine.cpp
} // namespace ecl
#endif