Main MRPT website > C++ reference
MRPT logo

ValueArg.h

Go to the documentation of this file.
00001 /****************************************************************************** 
00002  * 
00003  *  file:  ValueArg.h
00004  * 
00005  *  Copyright (c) 2003, Michael E. Smoot .
00006  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
00007  *  All rights reverved.
00008  * 
00009  *  See the file COPYING in the top directory of this distribution for
00010  *  more information.
00011  *  
00012  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 
00013  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
00014  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
00015  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
00016  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
00017  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
00018  *  DEALINGS IN THE SOFTWARE.  
00019  *  
00020  *****************************************************************************/ 
00021 
00022 
00023 #ifndef TCLAP_VALUE_ARGUMENT_H
00024 #define TCLAP_VALUE_ARGUMENT_H
00025 
00026 #include <string>
00027 #include <vector>
00028 
00029 #include <mrpt/otherlibs/tclap/Arg.h>
00030 #include <mrpt/otherlibs/tclap/Constraint.h>
00031 
00032 //#ifdef HAVE_CONFIG_H
00033 //#include <config.h>
00034 //#else
00035 #define HAVE_SSTREAM
00036 //#endif
00037 
00038 #if defined(HAVE_SSTREAM)
00039 #include <sstream>
00040 #elif defined(HAVE_STRSTREAM)
00041 #include <strstream>
00042 #else
00043 #error "Need a stringstream (sstream or strstream) to compile!"
00044 #endif
00045 
00046 namespace TCLAP {
00047 
00048 template<class T> class ValueArg;
00049 
00050 namespace VALUE_ARG_HELPER {
00051 
00052 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY };
00053 
00054 /**
00055  * This class is used to extract a value from an argument. 
00056  * It is used because we need a special implementation to
00057  * deal with std::string and making a specialiced function
00058  * puts it in the T segment, thus generating link errors.
00059  * Having a specialiced class makes the symbols weak.
00060  * This is not pretty but I don't know how to make it
00061  * work any other way.
00062  */
00063 template<class T> class ValueExtractor 
00064 {
00065         /**
00066          *
00067          */
00068         friend class ValueArg<T>;
00069 
00070         private:
00071 
00072                 /**
00073                  * Reference to the value where the result of the extraction will 
00074                  * be put.
00075                  */
00076         T &_value;
00077 
00078                 /**
00079                  * Constructor.
00080                  * \param value - Where the value extracted will be put.
00081                  */
00082         ValueExtractor(T &value) : _value(value) { }
00083 
00084                 /**
00085                  * Method that will attempt to parse the input stream for a value
00086                  * of type T.
00087                  * \param val - Where the value parsed will be put.
00088                  */
00089         int extractValue( const std::string& val ) 
00090                 {
00091 
00092 #if defined(HAVE_SSTREAM)
00093                         std::istringstream is(val);
00094 #elif defined(HAVE_STRSTREAM)
00095                         std::istrstream is(val.c_str());
00096 #else
00097 #error "Need a stringstream (sstream or strstream) to compile!"
00098 #endif
00099 
00100             int valuesRead = 0;
00101             while ( is.good() ) 
00102                         {
00103                 if ( is.peek() != EOF )
00104                     is >> _value;
00105                 else
00106                     break;
00107         
00108                 valuesRead++;
00109             }
00110       
00111             if ( is.fail() ) 
00112                 return EXTRACT_FAILURE;
00113 
00114             if ( valuesRead > 1 )
00115                 return EXTRACT_TOO_MANY;
00116 
00117             return 0;
00118         }
00119 };
00120 
00121 /**
00122  * Specialization for string.  This is necessary because istringstream
00123  * operator>> is not able to ignore spaces...  meaning -x "X Y" will only 
00124  * read 'X'... and thus the specialization.
00125  */
00126 template<> class ValueExtractor<std::string> 
00127 {
00128         /**
00129          *
00130          */
00131     friend class ValueArg<std::string>;
00132 
00133     private:
00134         
00135                 /**
00136                  * Reference to the value where the result of the extraction will 
00137                  * be put.
00138                  */
00139         std::string &_value;
00140 
00141                 /**
00142                  * Constructor.
00143                  * \param value - Where the value extracted will be put.
00144                  */
00145         ValueExtractor(std::string &value) : _value(value) {}
00146 
00147                 /**
00148                  * Method that will attempt to parse the input stream for a value
00149                  * of type std::string.
00150                  * \param val - Where the string parsed will be put.
00151                  */
00152         int extractValue( const std::string& val ) 
00153                 {
00154             _value = val;
00155             return 0;
00156         }
00157 };
00158 
00159 } //namespace VALUE_ARG_HELPER 
00160 
00161 /**
00162  * The basic labeled argument that parses a value.
00163  * This is a template class, which means the type T defines the type
00164  * that a given object will attempt to parse when the flag/name is matched
00165  * on the command line.  While there is nothing stopping you from creating
00166  * an unflagged ValueArg, it is unwise and would cause significant problems.
00167  * Instead use an UnlabeledValueArg.
00168  */
00169 template<class T>
00170 class ValueArg : public Arg 
00171 {
00172     protected:
00173 
00174         /**
00175          * The value parsed from the command line.
00176          * Can be of any type, as long as the >> operator for the type
00177          * is defined.
00178          */
00179         T _value;
00180 
00181         /**
00182          * A human readable description of the type to be parsed.
00183          * This is a hack, plain and simple.  Ideally we would use RTTI to
00184          * return the name of type T, but until there is some sort of
00185          * consistent support for human readable names, we are left to our
00186          * own devices.
00187          */
00188         std::string _typeDesc;
00189 
00190         /**
00191          * A Constraint this Arg must conform to. 
00192          */
00193         Constraint<T>* _constraint;
00194 
00195         /**
00196          * Extracts the value from the string.
00197          * Attempts to parse string as type T, if this fails an exception
00198          * is thrown.
00199          * \param val - value to be parsed. 
00200          */
00201         void _extractValue( const std::string& val );
00202 
00203         public:
00204 
00205         /**
00206          * Labeled ValueArg constructor.
00207          * You could conceivably call this constructor with a blank flag, 
00208          * but that would make you a bad person.  It would also cause
00209          * an exception to be thrown.   If you want an unlabeled argument, 
00210          * use the other constructor.
00211          * \param flag - The one character flag that identifies this
00212          * argument on the command line.
00213          * \param name - A one word name for the argument.  Can be
00214          * used as a long flag on the command line.
00215          * \param desc - A description of what the argument is for or
00216          * does.
00217          * \param req - Whether the argument is required on the command
00218          * line.
00219          * \param value - The default value assigned to this argument if it
00220          * is not present on the command line.
00221          * \param typeDesc - A short, human readable description of the
00222          * type that this object expects.  This is used in the generation
00223          * of the USAGE statement.  The goal is to be helpful to the end user
00224          * of the program.
00225          * \param v - An optional visitor.  You probably should not
00226          * use this unless you have a very good reason.
00227          */
00228         ValueArg( const std::string& flag, 
00229                   const std::string& name, 
00230                   const std::string& desc, 
00231                   bool req, 
00232                   T value,
00233                   const std::string& typeDesc,
00234                   Visitor* v = NULL);
00235                                  
00236                                  
00237         /**
00238          * Labeled ValueArg constructor.
00239          * You could conceivably call this constructor with a blank flag, 
00240          * but that would make you a bad person.  It would also cause
00241          * an exception to be thrown.   If you want an unlabeled argument, 
00242          * use the other constructor.
00243          * \param flag - The one character flag that identifies this
00244          * argument on the command line.
00245          * \param name - A one word name for the argument.  Can be
00246          * used as a long flag on the command line.
00247          * \param desc - A description of what the argument is for or
00248          * does.
00249          * \param req - Whether the argument is required on the command
00250          * line.
00251          * \param value - The default value assigned to this argument if it
00252          * is not present on the command line.
00253          * \param typeDesc - A short, human readable description of the
00254          * type that this object expects.  This is used in the generation
00255          * of the USAGE statement.  The goal is to be helpful to the end user
00256          * of the program.
00257          * \param parser - A CmdLine parser object to add this Arg to
00258          * \param v - An optional visitor.  You probably should not
00259          * use this unless you have a very good reason.
00260          */
00261         ValueArg( const std::string& flag, 
00262                   const std::string& name, 
00263                   const std::string& desc, 
00264                   bool req, 
00265                   T value,
00266                   const std::string& typeDesc,
00267                   CmdLineInterface& parser,
00268                   Visitor* v = NULL );
00269  
00270         /**
00271          * Labeled ValueArg constructor.
00272          * You could conceivably call this constructor with a blank flag, 
00273          * but that would make you a bad person.  It would also cause
00274          * an exception to be thrown.   If you want an unlabeled argument, 
00275          * use the other constructor.
00276          * \param flag - The one character flag that identifies this
00277          * argument on the command line.
00278          * \param name - A one word name for the argument.  Can be
00279          * used as a long flag on the command line.
00280          * \param desc - A description of what the argument is for or
00281          * does.
00282          * \param req - Whether the argument is required on the command
00283          * line.
00284          * \param value - The default value assigned to this argument if it
00285          * is not present on the command line.
00286          * \param constraint - A pointer to a Constraint object used
00287                  * to constrain this Arg.
00288          * \param parser - A CmdLine parser object to add this Arg to.
00289          * \param v - An optional visitor.  You probably should not
00290          * use this unless you have a very good reason.
00291          */
00292         ValueArg( const std::string& flag, 
00293                   const std::string& name, 
00294                   const std::string& desc, 
00295                   bool req, 
00296                   T value,
00297                   Constraint<T>* constraint,
00298                   CmdLineInterface& parser,
00299                   Visitor* v = NULL );
00300           
00301         /**
00302          * Labeled ValueArg constructor.
00303          * You could conceivably call this constructor with a blank flag, 
00304          * but that would make you a bad person.  It would also cause
00305          * an exception to be thrown.   If you want an unlabeled argument, 
00306          * use the other constructor.
00307          * \param flag - The one character flag that identifies this
00308          * argument on the command line.
00309          * \param name - A one word name for the argument.  Can be
00310          * used as a long flag on the command line.
00311          * \param desc - A description of what the argument is for or
00312          * does.
00313          * \param req - Whether the argument is required on the command
00314          * line.
00315          * \param value - The default value assigned to this argument if it
00316          * is not present on the command line.
00317          * \param constraint - A pointer to a Constraint object used
00318                  * to constrain this Arg.
00319          * \param v - An optional visitor.  You probably should not
00320          * use this unless you have a very good reason.
00321          */
00322         ValueArg( const std::string& flag, 
00323                   const std::string& name, 
00324                   const std::string& desc, 
00325                   bool req, 
00326                   T value,
00327                   Constraint<T>* constraint,
00328                   Visitor* v = NULL );
00329 
00330         /**
00331          * Handles the processing of the argument.
00332          * This re-implements the Arg version of this method to set the
00333          * _value of the argument appropriately.  It knows the difference
00334          * between labeled and unlabeled.
00335          * \param i - Pointer the the current argument in the list.
00336          * \param args - Mutable list of strings. Passed 
00337          * in from main().
00338          */
00339         virtual bool processArg(int* i, std::vector<std::string>& args); 
00340 
00341         /**
00342          * Returns the value of the argument.
00343          */
00344         T& getValue() ;
00345 
00346         /**
00347          * Specialization of shortID.
00348          * \param val - value to be used.
00349          */
00350         virtual std::string shortID(const std::string& val = "val") const;
00351 
00352         /**
00353          * Specialization of longID.
00354          * \param val - value to be used.
00355          */
00356         virtual std::string longID(const std::string& val = "val") const;
00357 
00358 };
00359 
00360 
00361 /**
00362  * Constructor implementation.
00363  */
00364 template<class T>
00365 ValueArg<T>::ValueArg(const std::string& flag, 
00366                       const std::string& name, 
00367                       const std::string& desc, 
00368                       bool req, 
00369                       T val,
00370                       const std::string& typeDesc,
00371                       Visitor* v)
00372 : Arg(flag, name, desc, req, true, v),
00373   _value( val ),
00374   _typeDesc( typeDesc ),
00375   _constraint( NULL )
00376 { }
00377 
00378 template<class T>
00379 ValueArg<T>::ValueArg(const std::string& flag, 
00380                       const std::string& name, 
00381                       const std::string& desc, 
00382                       bool req, 
00383                       T val,
00384                       const std::string& typeDesc,
00385                       CmdLineInterface& parser,
00386                       Visitor* v)
00387 : Arg(flag, name, desc, req, true, v),
00388   _value( val ),
00389   _typeDesc( typeDesc ),
00390   _constraint( NULL )
00391 { 
00392     parser.add( this );
00393 }
00394 
00395 template<class T>
00396 ValueArg<T>::ValueArg(const std::string& flag, 
00397                       const std::string& name, 
00398                       const std::string& desc, 
00399                       bool req, 
00400                       T val,
00401                       Constraint<T>* constraint,
00402                       Visitor* v)
00403 : Arg(flag, name, desc, req, true, v),
00404   _value( val ),
00405   _typeDesc( constraint->shortID() ),
00406   _constraint( constraint )
00407 { }
00408 
00409 template<class T>
00410 ValueArg<T>::ValueArg(const std::string& flag, 
00411                       const std::string& name, 
00412                       const std::string& desc, 
00413                       bool req, 
00414                       T val,
00415                       Constraint<T>* constraint,
00416                       CmdLineInterface& parser,
00417                       Visitor* v)
00418 : Arg(flag, name, desc, req, true, v),
00419   _value( val ),
00420   _typeDesc( constraint->shortID() ),
00421   _constraint( constraint )
00422 { 
00423     parser.add( this );
00424 }
00425 
00426 
00427 /**
00428  * Implementation of getValue().
00429  */
00430 template<class T>
00431 T& ValueArg<T>::getValue() { return _value; }
00432 
00433 /**
00434  * Implementation of processArg().
00435  */
00436 template<class T>
00437 bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
00438 {
00439     if ( _ignoreable && Arg::ignoreRest() )
00440                 return false;
00441 
00442     if ( _hasBlanks( args[*i] ) )
00443                 return false;
00444 
00445     std::string flag = args[*i];
00446 
00447     std::string value = "";
00448     trimFlag( flag, value );
00449 
00450     if ( argMatches( flag ) )
00451     {
00452         if ( _alreadySet )
00453                         throw( CmdLineParseException("Argument already set!", toString()) );
00454 
00455         if ( Arg::delimiter() != ' ' && value == "" )
00456                         throw( ArgParseException( 
00457                                                         "Couldn't find delimiter for this argument!",
00458                              toString() ) );
00459 
00460         if ( value == "" )
00461         {
00462             (*i)++;
00463             if ( static_cast<unsigned int>(*i) < args.size() ) 
00464                                 _extractValue( args[*i] );
00465             else
00466                                 throw( ArgParseException("Missing a value for this argument!",
00467                                                     toString() ) );
00468         }
00469         else
00470                         _extractValue( value );
00471                                 
00472         _alreadySet = true;
00473         _checkWithVisitor();
00474         return true;
00475     }   
00476     else
00477                 return false;
00478 }
00479 
00480 /**
00481  * Implementation of shortID.
00482  */
00483 template<class T>
00484 std::string ValueArg<T>::shortID(const std::string& val) const
00485 {
00486     return Arg::shortID( _typeDesc ); 
00487 }
00488 
00489 /**
00490  * Implementation of longID.
00491  */
00492 template<class T>
00493 std::string ValueArg<T>::longID(const std::string& val) const
00494 {
00495     return Arg::longID( _typeDesc ); 
00496 }
00497 
00498 template<class T>
00499 void ValueArg<T>::_extractValue( const std::string& val ) 
00500 {
00501         VALUE_ARG_HELPER::ValueExtractor<T> ve(_value);
00502 
00503         int err = ve.extractValue(val);
00504 
00505         if ( err == VALUE_ARG_HELPER::EXTRACT_FAILURE )
00506                 throw( ArgParseException("Couldn't read argument value from string '" +
00507                                      val + "'", toString() ) );
00508 
00509         if ( err == VALUE_ARG_HELPER::EXTRACT_TOO_MANY )
00510                 throw( ArgParseException(
00511                                         "More than one valid value parsed from string '" +
00512                                     val + "'", toString() ) );
00513 
00514         if ( _constraint != NULL )
00515                 if ( ! _constraint->check( _value ) )
00516                         throw( CmdLineParseException( "Value '" + val + 
00517                                                                               "' does not meet constraint: " + 
00518                                                                                   _constraint->description(),
00519                                                                                   toString() ) );
00520 }
00521 
00522 } // namespace TCLAP
00523 
00524 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN: at Sat Mar 26 06:16:28 UTC 2011