tclap: CmdLine.h Source File

Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

# CmdLine.h

Go to the documentation of this file.

    00001 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
    00002
    00003 /******************************************************************************
    00004  *
    00005  *  file:  CmdLine.h
    00006  *
    00007  *  Copyright (c) 2003, Michael E. Smoot .
    00008  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
    00009  *  All rights reverved.
    00010  *
    00011  *  See the file COPYING in the top directory of this distribution for
    00012  *  more information.
    00013  *
    00014  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
    00015  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00016  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    00017  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00018  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00019  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00020  *  DEALINGS IN THE SOFTWARE.
    00021  *
    00022  *****************************************************************************/
    00023
    00024 #ifndef TCLAP_CMDLINE_H
    00025 #define TCLAP_CMDLINE_H
    00026
    00027 #include <tclap/SwitchArg.h>
    00028 #include <tclap/MultiSwitchArg.h>
    00029 #include <tclap/UnlabeledValueArg.h>
    00030 #include <tclap/UnlabeledMultiArg.h>
    00031
    00032 #include <tclap/XorHandler.h>
    00033 #include <tclap/HelpVisitor.h>
    00034 #include <tclap/VersionVisitor.h>
    00035 #include <tclap/IgnoreRestVisitor.h>
    00036
    00037 #include <tclap/CmdLineOutput.h>
    00038 #include <tclap/StdOutput.h>
    00039
    00040 #include <tclap/Constraint.h>
    00041 #include <tclap/ValuesConstraint.h>
    00042
    00043 #include <string>
    00044 #include <vector>
    00045 #include <list>
    00046 #include <iostream>
    00047 #include <iomanip>
    00048 #include <algorithm>
    00049 #include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
    00050
    00051 namespace TCLAP {
    00052
    00053 template<typename T> void DelPtr(T ptr)
    00054 {
    00055     delete ptr;
    00056 }
    00057
    00058 template<typename C> void ClearContainer(C &c)
    00059 {
    00060     typedef typename C::value_type value_type;
    00061     std::for_each(c.begin(), c.end(), DelPtr<value_type>);
    00062     c.clear();
    00063 }
    00064
    00065
    00070 class CmdLine : public CmdLineInterface
    00071 {
    00072     protected:
    00073
    00078         std::list<Arg*> _argList;
    00079
    00083         std::string _progName;
    00084
    00088         std::string _message;
    00089
    00093         std::string _version;
    00094
    00100         int _numRequired;
    00101
    00106         char _delimiter;
    00107
    00111         XorHandler _xorHandler;
    00112
    00118         std::list<Arg*> _argDeleteOnExitList;
    00119
    00125         std::list<Visitor*> _visitorDeleteOnExitList;
    00126
    00130         CmdLineOutput* _output;
    00131
    00135         bool _handleExceptions;
    00136
    00140         void missingArgsException();
    00141
    00148         bool _emptyCombined(const std::string& s);
    00149
    00153         void deleteOnExit(Arg* ptr);
    00154
    00158         void deleteOnExit(Visitor* ptr);
    00159
    00160 private:
    00161
    00166         void _constructor();
    00167
    00168
    00173         bool _userSetOutput;
    00174
    00178         bool _helpAndVersion;
    00179
    00180     public:
    00181
    00194         CmdLine(const std::string& message,
    00195                 const char delimiter = ' ',
    00196                 const std::string& version = "none",
    00197                 bool helpAndVersion = true);
    00198
    00202         virtual ~CmdLine();
    00203
    00208         void add( Arg& a );
    00209
    00214         void add( Arg* a );
    00215
    00222         void xorAdd( Arg& a, Arg& b );
    00223
    00229         void xorAdd( std::vector<Arg*>& xors );
    00230
    00236         void parse(int argc, const char * const * argv);
    00237
    00243         void parse(std::vector<std::string>& args);
    00244
    00248         CmdLineOutput* getOutput();
    00249
    00253         void setOutput(CmdLineOutput* co);
    00254
    00258         std::string& getVersion();
    00259
    00263         std::string& getProgramName();
    00264
    00268         std::list<Arg*>& getArgList();
    00269
    00273         XorHandler& getXorHandler();
    00274
    00278         char getDelimiter();
    00279
    00283         std::string& getMessage();
    00284
    00288         bool hasHelpAndVersion();
    00289
    00295         void setExceptionHandling(const bool state);
    00296
    00303         bool getExceptionHandling() const;
    00304
    00308         void reset();
    00309
    00310 };
    00311
    00312
    00314 //Begin CmdLine.cpp
    00316
    00317 inline CmdLine::CmdLine(const std::string& m,
    00318             char delim,
    00319             const std::string& v,
    00320             bool help )
    00321 : _progName("not_set_yet"),
    00322   _message(m),
    00323   _version(v),
    00324   _numRequired(0),
    00325   _delimiter(delim),
    00326   _handleExceptions(true),
    00327   _userSetOutput(false),
    00328   _helpAndVersion(help)
    00329 {
    00330     _constructor();
    00331 }
    00332
    00333 inline CmdLine::~CmdLine()
    00334 {
    00335     ClearContainer(_argDeleteOnExitList);
    00336     ClearContainer(_visitorDeleteOnExitList);
    00337
    00338     if ( !_userSetOutput ) {
    00339         delete _output;
    00340         _output = 0;
    00341     }
    00342 }
    00343
    00344 inline void CmdLine::_constructor()
    00345 {
    00346     _output = new StdOutput;
    00347
    00348     Arg::setDelimiter( _delimiter );
    00349
    00350     Visitor* v;
    00351
    00352     if ( _helpAndVersion )
    00353     {
    00354         v = new HelpVisitor( this, &_output );
    00355         SwitchArg* help = new SwitchArg("h","help",
    00356                         "Displays usage information and exits.",
    00357                         false, v);
    00358         add( help );
    00359         deleteOnExit(help);
    00360         deleteOnExit(v);
    00361
    00362         v = new VersionVisitor( this, &_output );
    00363         SwitchArg* vers = new SwitchArg("","version",
    00364                     "Displays version information and exits.",
    00365                     false, v);
    00366         add( vers );
    00367         deleteOnExit(vers);
    00368         deleteOnExit(v);
    00369     }
    00370
    00371     v = new IgnoreRestVisitor();
    00372     SwitchArg* ignore  = new SwitchArg(Arg::flagStartString(),
    00373                        Arg::ignoreNameString(),
    00374                "Ignores the rest of the labeled arguments following this flag.",
    00375                        false, v);
    00376     add( ignore );
    00377     deleteOnExit(ignore);
    00378     deleteOnExit(v);
    00379 }
    00380
    00381 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
    00382 {
    00383     _xorHandler.add( ors );
    00384
    00385     for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
    00386     {
    00387         (*it)->forceRequired();
    00388         (*it)->setRequireLabel( "OR required" );
    00389
    00390         add( *it );
    00391     }
    00392 }
    00393
    00394 inline void CmdLine::xorAdd( Arg& a, Arg& b )
    00395 {
    00396     std::vector<Arg*> ors;
    00397     ors.push_back( &a );
    00398     ors.push_back( &b );
    00399     xorAdd( ors );
    00400 }
    00401
    00402 inline void CmdLine::add( Arg& a )
    00403 {
    00404     add( &a );
    00405 }
    00406
    00407 inline void CmdLine::add( Arg* a )
    00408 {
    00409     for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
    00410         if ( *a == *(*it) )
    00411             throw( SpecificationException(
    00412                     "Argument with same flag/name already exists!",
    00413                     a->longID() ) );
    00414
    00415     a->addToList( _argList );
    00416
    00417     if ( a->isRequired() )
    00418         _numRequired++;
    00419 }
    00420
    00421
    00422 inline void CmdLine::parse(int argc, const char * const * argv)
    00423 {
    00424         // this step is necessary so that we have easy access to
    00425         // mutable strings.
    00426         std::vector<std::string> args;
    00427         for (int i = 0; i < argc; i++)
    00428             args.push_back(argv[i]);
    00429
    00430         parse(args);
    00431 }
    00432
    00433 inline void CmdLine::parse(std::vector<std::string>& args)
    00434 {
    00435     bool shouldExit = false;
    00436     int estat = 0;
    00437
    00438     try {
    00439         _progName = args.front();
    00440         args.erase(args.begin());
    00441
    00442         int requiredCount = 0;
    00443
    00444         for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
    00445             bool matched = false;
    00446             for (ArgListIterator it = _argList.begin();
    00447                  it != _argList.end(); it++) {
    00448                 if ( (*it)->processArg( &i, args ) )
    00449                     {
    00450                         requiredCount += _xorHandler.check( *it );
    00451                         matched = true;
    00452                         break;
    00453                     }
    00454             }
    00455
    00456             // checks to see if the argument is an empty combined
    00457             // switch and if so, then we've actually matched it
    00458             if ( !matched && _emptyCombined( args[i] ) )
    00459                 matched = true;
    00460
    00461             if ( !matched && !Arg::ignoreRest() )
    00462                 throw(CmdLineParseException("Couldn't find match "
    00463                                             "for argument",
    00464                                             args[i]));
    00465         }
    00466
    00467         if ( requiredCount < _numRequired )
    00468             missingArgsException();
    00469
    00470         if ( requiredCount > _numRequired )
    00471             throw(CmdLineParseException("Too many arguments!"));
    00472
    00473     } catch ( ArgException& e ) {
    00474         // If we're not handling the exceptions, rethrow.
    00475         if ( !_handleExceptions) {
    00476             throw;
    00477         }
    00478
    00479         try {
    00480             _output->failure(*this,e);
    00481         } catch ( ExitException &ee ) {
    00482             estat = ee.getExitStatus();
    00483             shouldExit = true;
    00484         }
    00485     } catch (ExitException &ee) {
    00486         // If we're not handling the exceptions, rethrow.
    00487         if ( !_handleExceptions) {
    00488             throw;
    00489         }
    00490
    00491         estat = ee.getExitStatus();
    00492         shouldExit = true;
    00493     }
    00494
    00495     if (shouldExit)
    00496         exit(estat);
    00497 }
    00498
    00499 inline bool CmdLine::_emptyCombined(const std::string& s)
    00500 {
    00501     if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
    00502         return false;
    00503
    00504     for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
    00505         if ( s[i] != Arg::blankChar() )
    00506             return false;
    00507
    00508     return true;
    00509 }
    00510
    00511 inline void CmdLine::missingArgsException()
    00512 {
    00513         int count = 0;
    00514
    00515         std::string missingArgList;
    00516         for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
    00517         {
    00518             if ( (*it)->isRequired() && !(*it)->isSet() )
    00519             {
    00520                 missingArgList += (*it)->getName();
    00521                 missingArgList += ", ";
    00522                 count++;
    00523             }
    00524         }
    00525         missingArgList = missingArgList.substr(0,missingArgList.length()-2);
    00526
    00527         std::string msg;
    00528         if ( count > 1 )
    00529             msg = "Required arguments missing: ";
    00530         else
    00531             msg = "Required argument missing: ";
    00532
    00533         msg += missingArgList;
    00534
    00535         throw(CmdLineParseException(msg));
    00536 }
    00537
    00538 inline void CmdLine::deleteOnExit(Arg* ptr)
    00539 {
    00540     _argDeleteOnExitList.push_back(ptr);
    00541 }
    00542
    00543 inline void CmdLine::deleteOnExit(Visitor* ptr)
    00544 {
    00545     _visitorDeleteOnExitList.push_back(ptr);
    00546 }
    00547
    00548 inline CmdLineOutput* CmdLine::getOutput()
    00549 {
    00550     return _output;
    00551 }
    00552
    00553 inline void CmdLine::setOutput(CmdLineOutput* co)
    00554 {
    00555     _userSetOutput = true;
    00556     _output = co;
    00557 }
    00558
    00559 inline std::string& CmdLine::getVersion()
    00560 {
    00561     return _version;
    00562 }
    00563
    00564 inline std::string& CmdLine::getProgramName()
    00565 {
    00566     return _progName;
    00567 }
    00568
    00569 inline std::list<Arg*>& CmdLine::getArgList()
    00570 {
    00571     return _argList;
    00572 }
    00573
    00574 inline XorHandler& CmdLine::getXorHandler()
    00575 {
    00576     return _xorHandler;
    00577 }
    00578
    00579 inline char CmdLine::getDelimiter()
    00580 {
    00581     return _delimiter;
    00582 }
    00583
    00584 inline std::string& CmdLine::getMessage()
    00585 {
    00586     return _message;
    00587 }
    00588
    00589 inline bool CmdLine::hasHelpAndVersion()
    00590 {
    00591     return _helpAndVersion;
    00592 }
    00593
    00594 inline void CmdLine::setExceptionHandling(const bool state)
    00595 {
    00596     _handleExceptions = state;
    00597 }
    00598
    00599 inline bool CmdLine::getExceptionHandling() const
    00600 {
    00601     return _handleExceptions;
    00602 }
    00603
    00604 inline void CmdLine::reset()
    00605 {
    00606     for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
    00607     {
    00608         (*it)->reset();
    00609     }
    00610
    00611     _progName.clear();
    00612 }
    00613
    00615 //End CmdLine.cpp
    00617
    00618
    00619
    00620 } //namespace TCLAP
    00621 #endif