Main MRPT website > C++ reference
MRPT logo

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 <mrpt/otherlibs/tclap/SwitchArg.h>
00027 #include <mrpt/otherlibs/tclap/MultiSwitchArg.h>
00028 #include <mrpt/otherlibs/tclap/UnlabeledValueArg.h>
00029 #include <mrpt/otherlibs/tclap/UnlabeledMultiArg.h>
00030 
00031 #include <mrpt/otherlibs/tclap/XorHandler.h>
00032 #include <mrpt/otherlibs/tclap/HelpVisitor.h>
00033 #include <mrpt/otherlibs/tclap/VersionVisitor.h>
00034 #include <mrpt/otherlibs/tclap/IgnoreRestVisitor.h>
00035 
00036 #include <mrpt/otherlibs/tclap/CmdLineOutput.h>
00037 #include <mrpt/otherlibs/tclap/StdOutput.h>
00038 
00039 #include <mrpt/otherlibs/tclap/Constraint.h>
00040 #include <mrpt/otherlibs/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 
00051 /**
00052  * The base class that manages the command line definition and passes
00053  * along the parsing to the appropriate Arg classes.
00054  */
00055 class CmdLine : public CmdLineInterface
00056 {
00057         protected:
00058 
00059                 /**
00060                  * The list of arguments that will be tested against the
00061                  * command line.
00062                  */
00063                 std::list<Arg*> _argList;
00064 
00065                 /**
00066                  * The name of the program.  Set to argv[0].
00067                  */
00068                 std::string _progName;
00069 
00070                 /**
00071                  * A message used to describe the program.  Used in the usage output.
00072                  */
00073                 std::string _message;
00074 
00075                 /**
00076                  * The version to be displayed with the --version switch.
00077                  */
00078                 std::string _version;
00079 
00080                 /**
00081                  * The number of arguments that are required to be present on
00082                  * the command line. This is set dynamically, based on the
00083                  * Args added to the CmdLine object.
00084                  */
00085                 int _numRequired;
00086 
00087                 /**
00088                  * The character that is used to separate the argument flag/name
00089                  * from the value.  Defaults to ' ' (space).
00090                  */
00091                 char _delimiter;
00092 
00093                 /**
00094                  * The handler that manages xoring lists of args.
00095                  */
00096                 XorHandler _xorHandler;
00097 
00098                 /**
00099                  * A list of Args to be explicitly deleted when the destructor
00100                  * is called.  At the moment, this only includes the three default
00101                  * Args.
00102                  */
00103                 std::list<Arg*> _argDeleteOnExitList;
00104 
00105                 /**
00106                  * A list of Visitors to be explicitly deleted when the destructor
00107                  * is called.  At the moment, these are the Vistors created for the
00108                  * default Args.
00109                  */
00110                 std::list<Visitor*> _visitorDeleteOnExitList;
00111 
00112                 /**
00113                  * Object that handles all output for the CmdLine.
00114                  */
00115                 CmdLineOutput* _output;
00116 
00117                 /**
00118                  * Checks whether a name/flag string matches entirely matches
00119                  * the Arg::blankChar.  Used when multiple switches are combined
00120                  * into a single argument.
00121                  * \param s - The message to be used in the usage.
00122                  */
00123                 bool _emptyCombined(const std::string& s);
00124 
00125                 /**
00126                  * Perform a delete ptr; operation on ptr when this object is deleted.
00127                  */
00128                 void deleteOnExit(Arg* ptr);
00129 
00130                 /**
00131                  * Perform a delete ptr; operation on ptr when this object is deleted.
00132                  */
00133                 void deleteOnExit(Visitor* ptr);
00134 
00135         private:
00136 
00137                 /**
00138                  * Encapsulates the code common to the constructors (which is all
00139                  * of it).
00140                  */
00141                 void _constructor();
00142 
00143                 /**
00144                  * Is set to true when a user sets the output object. We use this so
00145                  * that we don't delete objects that are created outside of this lib.
00146                  */
00147                 bool _userSetOutput;
00148 
00149                 /**
00150                  * Whether or not to automatically create help and version switches.
00151                  */
00152                 bool _helpAndVersion;
00153 
00154         public:
00155 
00156                 /**
00157                  * Command line constructor. Defines how the arguments will be
00158                  * parsed.
00159                  * \param message - The message to be used in the usage
00160                  * output.
00161                  * \param delimiter - The character that is used to separate
00162                  * the argument flag/name from the value.  Defaults to ' ' (space).
00163                  * \param version - The version number to be used in the
00164                  * --version switch.
00165                  * \param helpAndVersion - Whether or not to create the Help and
00166                  * Version switches. Defaults to true.
00167                  */
00168                 CmdLine(const std::string& message,
00169                                 const char delimiter = ' ',
00170                                 const std::string& version = "none",
00171                                 bool helpAndVersion = true);
00172 
00173                 /**
00174                  * Deletes any resources allocated by a CmdLine object.
00175                  */
00176                 virtual ~CmdLine();
00177 
00178                 /**
00179                  * Adds an argument to the list of arguments to be parsed.
00180                  * \param a - Argument to be added.
00181                  */
00182                 void add( Arg& a );
00183 
00184                 /**
00185                  * An alternative add.  Functionally identical.
00186                  * \param a - Argument to be added.
00187                  */
00188                 void add( Arg* a );
00189 
00190                 /**
00191                  * Add two Args that will be xor'd.  If this method is used, add does
00192                  * not need to be called.
00193                  * \param a - Argument to be added and xor'd.
00194                  * \param b - Argument to be added and xor'd.
00195                  */
00196                 void xorAdd( Arg& a, Arg& b );
00197 
00198                 /**
00199                  * Add a list of Args that will be xor'd.  If this method is used,
00200                  * add does not need to be called.
00201                  * \param xors - List of Args to be added and xor'd.
00202                  */
00203                 void xorAdd( std::vector<Arg*>& xors );
00204 
00205                 /**
00206                  * Parses the command line.
00207                  * \param argc - Number of arguments.
00208                  * \param argv - Array of arguments.
00209                  * \return (Added by JLBC for MRPT): Return false if the program should exit (error in args, it was --help, etc...)
00210                  */
00211                 bool parse(int argc, char** argv);
00212 
00213                 /**
00214                  *
00215                  */
00216                 CmdLineOutput* getOutput();
00217 
00218                 /**
00219                  *
00220                  */
00221                 void setOutput(CmdLineOutput* co);
00222 
00223                 /**
00224                  *
00225                  */
00226                 std::string& getVersion();
00227 
00228                 /**
00229                  *
00230                  */
00231                 std::string& getProgramName();
00232 
00233                 /**
00234                  *
00235                  */
00236                 std::list<Arg*>& getArgList();
00237 
00238                 /**
00239                  *
00240                  */
00241                 XorHandler& getXorHandler();
00242 
00243                 /**
00244                  *
00245                  */
00246                 char getDelimiter();
00247 
00248                 /**
00249                  *
00250                  */
00251                 std::string& getMessage();
00252 
00253                 /**
00254                  *
00255                  */
00256                 bool hasHelpAndVersion();
00257 };
00258 
00259 
00260 ///////////////////////////////////////////////////////////////////////////////
00261 //Begin CmdLine.cpp
00262 ///////////////////////////////////////////////////////////////////////////////
00263 
00264 inline CmdLine::CmdLine(const std::string& m,
00265                                         char delim,
00266                                                 const std::string& v,
00267                                                 bool help )
00268 : _progName("not_set_yet"),
00269   _message(m),
00270   _version(v),
00271   _numRequired(0),
00272   _delimiter(delim),
00273   _userSetOutput(false),
00274   _helpAndVersion(help)
00275 {
00276         _constructor();
00277 }
00278 
00279 inline CmdLine::~CmdLine()
00280 {
00281         ArgListIterator argIter;
00282         VisitorListIterator visIter;
00283 
00284         for( argIter = _argDeleteOnExitList.begin();
00285                  argIter != _argDeleteOnExitList.end();
00286                  ++argIter)
00287                 delete *argIter;
00288 
00289         for( visIter = _visitorDeleteOnExitList.begin();
00290                  visIter != _visitorDeleteOnExitList.end();
00291                  ++visIter)
00292                 delete *visIter;
00293 
00294         if ( !_userSetOutput )
00295                 delete _output;
00296 }
00297 
00298 inline void CmdLine::_constructor()
00299 {
00300         _output = new StdOutput;
00301 
00302         Arg::setDelimiter( _delimiter );
00303 
00304         Visitor* v;
00305 
00306         if ( _helpAndVersion )
00307         {
00308                 v = new HelpVisitor( this, &_output );
00309                 SwitchArg* help = new SwitchArg("h","help",
00310                                                 "Displays usage information and exits.",
00311                                                 false, v);
00312                 add( help );
00313                 deleteOnExit(help);
00314                 deleteOnExit(v);
00315 
00316                 v = new VersionVisitor( this, &_output );
00317                 SwitchArg* vers = new SwitchArg("","version",
00318                                         "Displays version information and exits.",
00319                                         false, v);
00320                 add( vers );
00321                 deleteOnExit(vers);
00322                 deleteOnExit(v);
00323         }
00324 
00325         v = new IgnoreRestVisitor();
00326         SwitchArg* ignore  = new SwitchArg(Arg::flagStartString(),
00327                                            Arg::ignoreNameString(),
00328                            "Ignores the rest of the labeled arguments following this flag.",
00329                                            false, v);
00330         add( ignore );
00331         deleteOnExit(ignore);
00332         deleteOnExit(v);
00333 }
00334 
00335 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
00336 {
00337         _xorHandler.add( ors );
00338 
00339         for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
00340         {
00341                 (*it)->forceRequired();
00342                 (*it)->setRequireLabel( "OR required" );
00343 
00344                 add( *it );
00345         }
00346 }
00347 
00348 inline void CmdLine::xorAdd( Arg& a, Arg& b )
00349 {
00350     std::vector<Arg*> ors;
00351     ors.push_back( &a );
00352     ors.push_back( &b );
00353         xorAdd( ors );
00354 }
00355 
00356 inline void CmdLine::add( Arg& a )
00357 {
00358         add( &a );
00359 }
00360 
00361 inline void CmdLine::add( Arg* a )
00362 {
00363         for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
00364                 if ( *a == *(*it) )
00365                         throw( SpecificationException(
00366                                 "Argument with same flag/name already exists!",
00367                                         a->longID() ) );
00368 
00369         a->addToList( _argList );
00370 
00371         if ( a->isRequired() )
00372                 _numRequired++;
00373 }
00374 
00375 inline bool CmdLine::parse(int argc, char** argv)
00376 {
00377         try {
00378 
00379         _progName = argv[0];
00380 
00381         // this step is necessary so that we have easy access to mutable strings.
00382         std::vector<std::string> args;
00383         for (int i = 1; i < argc; i++)
00384                 args.push_back(argv[i]);
00385 
00386         int requiredCount = 0;
00387 
00388         for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
00389         {
00390                 bool matched = false;
00391                 for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
00392         {
00393                         if ( (*it)->processArg( &i, args ) )
00394                         {
00395                                 requiredCount += _xorHandler.check( *it );
00396                                 matched = true;
00397                                 break;
00398                         }
00399         }
00400 
00401                 // checks to see if the argument is an empty combined switch ...
00402                 // and if so, then we've actually matched it
00403                 if ( !matched && _emptyCombined( args[i] ) )
00404                         matched = true;
00405 
00406                 if ( !matched && !Arg::ignoreRest() )
00407                         throw(CmdLineParseException("Couldn't find match for argument",
00408                                                      args[i]));
00409     }
00410 
00411         if ( requiredCount < _numRequired )
00412                 throw(CmdLineParseException("One or more required arguments missing!"));
00413 
00414         if ( requiredCount > _numRequired )
00415                 throw(CmdLineParseException("Too many arguments!"));
00416 
00417         return true; // Ok
00418 
00419         } 
00420         catch ( ActionDoneException e )
00421         {
00422                 return false; // Done
00423         }
00424         catch ( ArgException e )
00425         {
00426                 _output->failure(*this,e); 
00427                 return false; // Error 
00428         }
00429 }
00430 
00431 inline bool CmdLine::_emptyCombined(const std::string& s)
00432 {
00433         if ( s[0] != Arg::flagStartChar() )
00434                 return false;
00435 
00436         for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
00437                 if ( s[i] != Arg::blankChar() )
00438                         return false;
00439 
00440         return true;
00441 }
00442 
00443 inline void CmdLine::deleteOnExit(Arg* ptr)
00444 {
00445         _argDeleteOnExitList.push_back(ptr);
00446 }
00447 
00448 inline void CmdLine::deleteOnExit(Visitor* ptr)
00449 {
00450         _visitorDeleteOnExitList.push_back(ptr);
00451 }
00452 
00453 inline CmdLineOutput* CmdLine::getOutput()
00454 {
00455         return _output;
00456 }
00457 
00458 inline void CmdLine::setOutput(CmdLineOutput* co)
00459 {
00460         _userSetOutput = true;
00461         _output = co;
00462 }
00463 
00464 inline std::string& CmdLine::getVersion()
00465 {
00466         return _version;
00467 }
00468 
00469 inline std::string& CmdLine::getProgramName()
00470 {
00471         return _progName;
00472 }
00473 
00474 inline std::list<Arg*>& CmdLine::getArgList()
00475 {
00476         return _argList;
00477 }
00478 
00479 inline XorHandler& CmdLine::getXorHandler()
00480 {
00481         return _xorHandler;
00482 }
00483 
00484 inline char CmdLine::getDelimiter()
00485 {
00486         return _delimiter;
00487 }
00488 
00489 inline std::string& CmdLine::getMessage()
00490 {
00491         return _message;
00492 }
00493 
00494 inline bool CmdLine::hasHelpAndVersion()
00495 {
00496         return _helpAndVersion;
00497 }
00498 
00499 ///////////////////////////////////////////////////////////////////////////////
00500 //End CmdLine.cpp
00501 ///////////////////////////////////////////////////////////////////////////////
00502 
00503 
00504 
00505 } //namespace TCLAP
00506 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011