CmdLine.h

Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003  *
00004  *  file:  CmdLine.h
00005  *
00006  *  Copyright (c) 2003, Michael E. Smoot .
00007  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
00008  *  All rights reverved.
00009  *
00010  *  See the file COPYING in the top directory of this distribution for
00011  *  more information.
00012  *
00013  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
00014  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00016  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00018  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00019  *  DEALINGS IN THE SOFTWARE.
00020  *
00021  *****************************************************************************/
00022 
00023 #ifndef TCLAP_CMDLINE_H
00024 #define TCLAP_CMDLINE_H
00025 
00026 #include <tclap/SwitchArg.h>
00027 #include <tclap/MultiSwitchArg.h>
00028 #include <tclap/UnlabeledValueArg.h>
00029 #include <tclap/UnlabeledMultiArg.h>
00030 
00031 #include <tclap/XorHandler.h>
00032 #include <tclap/HelpVisitor.h>
00033 #include <tclap/VersionVisitor.h>
00034 #include <tclap/IgnoreRestVisitor.h>
00035 
00036 #include <tclap/CmdLineOutput.h>
00037 #include <tclap/StdOutput.h>
00038 
00039 #include <tclap/Constraint.h>
00040 #include <tclap/ValuesConstraint.h>
00041 
00042 #include <string>
00043 #include <vector>
00044 #include <list>
00045 #include <iostream>
00046 #include <iomanip>
00047 #include <algorithm>
00048 
00049 namespace TCLAP {
00050 
00055 class CmdLine : public CmdLineInterface
00056 {
00057     protected:
00058 
00063         std::list<Arg*> _argList;
00064 
00068         std::string _progName;
00069 
00073         std::string _message;
00074 
00078         std::string _version;
00079 
00085         int _numRequired;
00086 
00091         char _delimiter;
00092 
00096         XorHandler _xorHandler;
00097 
00103         std::list<Arg*> _argDeleteOnExitList;
00104 
00110         std::list<Visitor*> _visitorDeleteOnExitList;
00111 
00115         CmdLineOutput* _output;
00116 
00123         bool _emptyCombined(const std::string& s);
00124 
00128         void deleteOnExit(Arg* ptr);
00129 
00133         void deleteOnExit(Visitor* ptr);
00134 
00135     private:
00136 
00141         void _constructor();
00142 
00147         bool _userSetOutput;
00148 
00152         bool _helpAndVersion;
00153 
00154     public:
00155 
00168         CmdLine(const std::string& message,
00169                 const char delimiter = ' ',
00170                 const std::string& version = "none",
00171                 bool helpAndVersion = true);
00172 
00176         virtual ~CmdLine();
00177 
00182         void add( Arg& a );
00183 
00188         void add( Arg* a );
00189 
00196         void xorAdd( Arg& a, Arg& b );
00197 
00203         void xorAdd( std::vector<Arg*>& xors );
00204 
00210         void parse(int argc, char** argv);
00211 
00215         CmdLineOutput* getOutput();
00216 
00220         void setOutput(CmdLineOutput* co);
00221 
00225         std::string& getVersion();
00226 
00230         std::string& getProgramName();
00231 
00235         std::list<Arg*>& getArgList();
00236 
00240         XorHandler& getXorHandler();
00241 
00245         char getDelimiter();
00246 
00250         std::string& getMessage();
00251 
00255         bool hasHelpAndVersion();
00256 };
00257 
00258 
00260 //Begin CmdLine.cpp
00262 
00263 inline CmdLine::CmdLine(const std::string& m,
00264                         char delim,
00265                         const std::string& v,
00266                         bool help )
00267 : _progName("not_set_yet"),
00268   _message(m),
00269   _version(v),
00270   _numRequired(0),
00271   _delimiter(delim),
00272   _userSetOutput(false),
00273   _helpAndVersion(help)
00274 {
00275     _constructor();
00276 }
00277 
00278 inline CmdLine::~CmdLine()
00279 {
00280     ArgListIterator argIter;
00281     VisitorListIterator visIter;
00282 
00283     for( argIter = _argDeleteOnExitList.begin();
00284          argIter != _argDeleteOnExitList.end();
00285          ++argIter)
00286         delete *argIter;
00287 
00288     for( visIter = _visitorDeleteOnExitList.begin();
00289          visIter != _visitorDeleteOnExitList.end();
00290          ++visIter)
00291         delete *visIter;
00292 
00293     if ( !_userSetOutput )
00294         delete _output;
00295 }
00296 
00297 inline void CmdLine::_constructor()
00298 {
00299     _output = new StdOutput;
00300 
00301     Arg::setDelimiter( _delimiter );
00302 
00303     Visitor* v;
00304 
00305     if ( _helpAndVersion )
00306     {
00307         v = new HelpVisitor( this, &_output );
00308         SwitchArg* help = new SwitchArg("h","help",
00309                         "Displays usage information and exits.",
00310                         false, v);
00311         add( help );
00312         deleteOnExit(help);
00313         deleteOnExit(v);
00314 
00315         v = new VersionVisitor( this, &_output );
00316         SwitchArg* vers = new SwitchArg("","version",
00317                     "Displays version information and exits.",
00318                     false, v);
00319         add( vers );
00320         deleteOnExit(vers);
00321         deleteOnExit(v);
00322     }
00323 
00324     v = new IgnoreRestVisitor();
00325     SwitchArg* ignore  = new SwitchArg(Arg::flagStartString(),
00326                        Arg::ignoreNameString(),
00327                "Ignores the rest of the labeled arguments following this flag.",
00328                        false, v);
00329     add( ignore );
00330     deleteOnExit(ignore);
00331     deleteOnExit(v);
00332 }
00333 
00334 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
00335 {
00336     _xorHandler.add( ors );
00337 
00338     for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
00339     {
00340         (*it)->forceRequired();
00341         (*it)->setRequireLabel( "OR required" );
00342 
00343         add( *it );
00344     }
00345 }
00346 
00347 inline void CmdLine::xorAdd( Arg& a, Arg& b )
00348 {
00349     std::vector<Arg*> ors;
00350     ors.push_back( &a );
00351     ors.push_back( &b );
00352     xorAdd( ors );
00353 }
00354 
00355 inline void CmdLine::add( Arg& a )
00356 {
00357     add( &a );
00358 }
00359 
00360 inline void CmdLine::add( Arg* a )
00361 {
00362     for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
00363         if ( *a == *(*it) )
00364             throw( SpecificationException(
00365                     "Argument with same flag/name already exists!",
00366                     a->longID() ) );
00367 
00368     a->addToList( _argList );
00369 
00370     if ( a->isRequired() )
00371         _numRequired++;
00372 }
00373 
00374 inline void CmdLine::parse(int argc, char** argv)
00375 {
00376     try {
00377 
00378     _progName = argv[0];
00379 
00380     // this step is necessary so that we have easy access to mutable strings.
00381     std::vector<std::string> args;
00382     for (int i = 1; i < argc; i++)
00383         args.push_back(argv[i]);
00384 
00385     int requiredCount = 0;
00386 
00387     for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
00388     {
00389         bool matched = false;
00390         for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
00391         {
00392             if ( (*it)->processArg( &i, args ) )
00393             {
00394                 requiredCount += _xorHandler.check( *it );
00395                 matched = true;
00396                 break;
00397             }
00398         }
00399 
00400         // checks to see if the argument is an empty combined switch ...
00401         // and if so, then we've actually matched it
00402         if ( !matched && _emptyCombined( args[i] ) )
00403             matched = true;
00404 
00405         if ( !matched && !Arg::ignoreRest() )
00406             throw(CmdLineParseException("Couldn't find match for argument",
00407                                          args[i]));
00408     }
00409 
00410     if ( requiredCount < _numRequired )
00411         throw(CmdLineParseException("One or more required arguments missing!"));
00412 
00413     if ( requiredCount > _numRequired )
00414         throw(CmdLineParseException("Too many arguments!"));
00415 
00416     } catch ( ArgException e ) { _output->failure(*this,e); exit(1); }
00417 }
00418 
00419 inline bool CmdLine::_emptyCombined(const std::string& s)
00420 {
00421     if ( s[0] != Arg::flagStartChar() )
00422         return false;
00423 
00424     for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
00425         if ( s[i] != Arg::blankChar() )
00426             return false;
00427 
00428     return true;
00429 }
00430 
00431 inline void CmdLine::deleteOnExit(Arg* ptr)
00432 {
00433     _argDeleteOnExitList.push_back(ptr);
00434 }
00435 
00436 inline void CmdLine::deleteOnExit(Visitor* ptr)
00437 {
00438     _visitorDeleteOnExitList.push_back(ptr);
00439 }
00440 
00441 inline CmdLineOutput* CmdLine::getOutput()
00442 {
00443     return _output;
00444 }
00445 
00446 inline void CmdLine::setOutput(CmdLineOutput* co)
00447 {
00448     _userSetOutput = true;
00449     _output = co;
00450 }
00451 
00452 inline std::string& CmdLine::getVersion()
00453 {
00454     return _version;
00455 }
00456 
00457 inline std::string& CmdLine::getProgramName()
00458 {
00459     return _progName;
00460 }
00461 
00462 inline std::list<Arg*>& CmdLine::getArgList()
00463 {
00464     return _argList;
00465 }
00466 
00467 inline XorHandler& CmdLine::getXorHandler()
00468 {
00469     return _xorHandler;
00470 }
00471 
00472 inline char CmdLine::getDelimiter()
00473 {
00474     return _delimiter;
00475 }
00476 
00477 inline std::string& CmdLine::getMessage()
00478 {
00479     return _message;
00480 }
00481 
00482 inline bool CmdLine::hasHelpAndVersion()
00483 {
00484     return _helpAndVersion;
00485 }
00486 
00488 //End CmdLine.cpp
00490 
00491 
00492 
00493 } //namespace TCLAP
00494 #endif

Generated on Thu Dec 14 23:01:53 2006 for tclap by  doxygen 1.5.1