UniversalIndentGUI 1.2.0
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines