BASIS  version 1.2.3 (revision 2104)
MultiArg.h
00001 /****************************************************************************** 
00002  * 
00003  *  file:  MultiArg.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_MULTIPLE_ARGUMENT_H
00024 #define TCLAP_MULTIPLE_ARGUMENT_H
00025 
00026 #include <string>
00027 #include <vector>
00028 
00029 #include <sbia/tclap/Arg.h>
00030 #include <sbia/tclap/Constraint.h>
00031 
00032 namespace TCLAP {
00033 /**
00034  * An argument that allows multiple values of type T to be specified.  Very
00035  * similar to a ValueArg, except a vector of values will be returned
00036  * instead of just one.
00037  */
00038 template<class T>
00039 class MultiArg : public Arg
00040 {
00041 public:
00042     typedef std::vector<T> container_type;  
00043     typedef typename container_type::iterator iterator;
00044     typedef typename container_type::const_iterator const_iterator;
00045 
00046 protected:
00047 
00048     /**
00049      * The list of values parsed from the CmdLine.
00050      */
00051     std::vector<T> _values;
00052 
00053     /**
00054      * The description of type T to be used in the usage.
00055      */
00056     std::string _typeDesc;
00057 
00058     /**
00059      * A list of constraint on this Arg. 
00060      */
00061     Constraint<T>* _constraint;
00062 
00063     /**
00064      * Extracts the value from the string.
00065      * Attempts to parse string as type T, if this fails an exception
00066      * is thrown.
00067      * \param val - The string to be read.
00068      */
00069     void _extractValue( const std::string& val );
00070 
00071     /**
00072      * Used by XorHandler to decide whether to keep parsing for this arg.
00073      */
00074     bool _allowMore;
00075 
00076 public:
00077 
00078     /**
00079      * Constructor.
00080      * \param flag - The one character flag that identifies this
00081      * argument on the command line.
00082      * \param name - A one word name for the argument.  Can be
00083      * used as a long flag on the command line.
00084      * \param desc - A description of what the argument is for or
00085      * does.
00086      * \param req - Whether the argument is required on the command
00087      * line.
00088      * \param typeDesc - A short, human readable description of the
00089      * type that this object expects.  This is used in the generation
00090      * of the USAGE statement.  The goal is to be helpful to the end user
00091      * of the program.
00092      * \param v - An optional visitor.  You probably should not
00093      * use this unless you have a very good reason.
00094      */
00095     MultiArg( const std::string& flag,
00096                   const std::string& name,
00097                   const std::string& desc,
00098                   bool req,
00099                   const std::string& typeDesc,
00100                   Visitor* v = NULL);
00101 
00102     /**
00103      * Constructor.
00104      * \param flag - The one character flag that identifies this
00105      * argument on the command line.
00106      * \param name - A one word name for the argument.  Can be
00107      * used as a long flag on the command line.
00108      * \param desc - A description of what the argument is for or
00109      * does.
00110      * \param req - Whether the argument is required on the command
00111      * line.
00112      * \param typeDesc - A short, human readable description of the
00113      * type that this object expects.  This is used in the generation
00114      * of the USAGE statement.  The goal is to be helpful to the end user
00115      * of the program.
00116      * \param parser - A CmdLine parser object to add this Arg to
00117      * \param v - An optional visitor.  You probably should not
00118      * use this unless you have a very good reason.
00119      */
00120     MultiArg( const std::string& flag, 
00121                   const std::string& name,
00122                   const std::string& desc,
00123                   bool req,
00124                   const std::string& typeDesc,
00125                   CmdLineInterface& parser,
00126                   Visitor* v = NULL );
00127 
00128     /**
00129      * Constructor.
00130      * \param flag - The one character flag that identifies this
00131      * argument on the command line.
00132      * \param name - A one word name for the argument.  Can be
00133      * used as a long flag on the command line.
00134      * \param desc - A description of what the argument is for or
00135      * does.
00136      * \param req - Whether the argument is required on the command
00137      * line.
00138      * \param constraint - A pointer to a Constraint object used
00139      * to constrain this Arg.
00140      * \param v - An optional visitor.  You probably should not
00141      * use this unless you have a very good reason.
00142      */
00143     MultiArg( const std::string& flag,
00144                   const std::string& name,
00145                   const std::string& desc,
00146                   bool req,
00147                   Constraint<T>* constraint,
00148                   Visitor* v = NULL );
00149           
00150     /**
00151      * Constructor.
00152      * \param flag - The one character flag that identifies this
00153      * argument on the command line.
00154      * \param name - A one word name for the argument.  Can be
00155      * used as a long flag on the command line.
00156      * \param desc - A description of what the argument is for or
00157      * does.
00158      * \param req - Whether the argument is required on the command
00159      * line.
00160      * \param constraint - A pointer to a Constraint object used
00161      * to constrain this Arg.
00162      * \param parser - A CmdLine parser object to add this Arg to
00163      * \param v - An optional visitor.  You probably should not
00164      * use this unless you have a very good reason.
00165      */
00166     MultiArg( const std::string& flag, 
00167                   const std::string& name,
00168                   const std::string& desc,
00169                   bool req,
00170                   Constraint<T>* constraint,
00171                   CmdLineInterface& parser,
00172                   Visitor* v = NULL );
00173           
00174     /**
00175      * Handles the processing of the argument.
00176      * This re-implements the Arg version of this method to set the
00177      * _value of the argument appropriately.  It knows the difference
00178      * between labeled and unlabeled.
00179      * \param i - Pointer the the current argument in the list.
00180      * \param args - Mutable list of strings. Passed from main().
00181      */
00182     virtual bool processArg(int* i, std::vector<std::string>& args); 
00183 
00184     /**
00185      * Returns a vector of type T containing the values parsed from
00186      * the command line.
00187      */
00188     const std::vector<T>& getValue();
00189 
00190     /**
00191      * Returns an iterator over the values parsed from the command
00192      * line.
00193      */
00194     const_iterator begin() const { return _values.begin(); }
00195 
00196     /**
00197      * Returns the end of the values parsed from the command
00198      * line.
00199      */
00200     const_iterator end() const { return _values.end(); }
00201 
00202     /**
00203      * Returns the a short id string.  Used in the usage. 
00204      * \param val - value to be used.
00205      */
00206     virtual std::string shortID(const std::string& val="val") const;
00207 
00208     /**
00209      * Returns the a long id string.  Used in the usage. 
00210      * \param val - value to be used.
00211      */
00212     virtual std::string longID(const std::string& val="val") const;
00213 
00214     /**
00215      * Once we've matched the first value, then the arg is no longer
00216      * required.
00217      */
00218     virtual bool isRequired() const;
00219 
00220     virtual bool allowMore();
00221     
00222     virtual void reset();
00223 
00224 private:
00225     /**
00226      * Prevent accidental copying
00227      */
00228     MultiArg<T>(const MultiArg<T>& rhs);
00229     MultiArg<T>& operator=(const MultiArg<T>& rhs);
00230 
00231 };
00232 
00233 template<class T>
00234 MultiArg<T>::MultiArg(const std::string& flag, 
00235                       const std::string& name,
00236                       const std::string& desc,
00237                       bool req,
00238                       const std::string& typeDesc,
00239                       Visitor* v) :
00240    Arg( flag, name, desc, req, true, v ),
00241   _values(std::vector<T>()),
00242   _typeDesc( typeDesc ),
00243   _constraint( NULL ),
00244   _allowMore(false)
00245 { 
00246     _acceptsMultipleValues = true;
00247 }
00248 
00249 template<class T>
00250 MultiArg<T>::MultiArg(const std::string& flag, 
00251                       const std::string& name,
00252                       const std::string& desc,
00253                       bool req,
00254                       const std::string& typeDesc,
00255                       CmdLineInterface& parser,
00256                       Visitor* v)
00257 : Arg( flag, name, desc, req, true, v ),
00258   _values(std::vector<T>()),
00259   _typeDesc( typeDesc ),
00260   _constraint( NULL ),
00261   _allowMore(false)
00262 { 
00263     parser.add( this );
00264     _acceptsMultipleValues = true;
00265 }
00266 
00267 /**
00268  *
00269  */
00270 template<class T>
00271 MultiArg<T>::MultiArg(const std::string& flag, 
00272                       const std::string& name,
00273                       const std::string& desc,
00274                       bool req,
00275                       Constraint<T>* constraint,
00276                       Visitor* v)
00277 : Arg( flag, name, desc, req, true, v ),
00278   _values(std::vector<T>()),
00279   _typeDesc( constraint->shortID() ),
00280   _constraint( constraint ),
00281   _allowMore(false)
00282 { 
00283     _acceptsMultipleValues = true;
00284 }
00285 
00286 template<class T>
00287 MultiArg<T>::MultiArg(const std::string& flag, 
00288                       const std::string& name,
00289                       const std::string& desc,
00290                       bool req,
00291                       Constraint<T>* constraint,
00292                       CmdLineInterface& parser,
00293                       Visitor* v)
00294 : Arg( flag, name, desc, req, true, v ),
00295   _values(std::vector<T>()),
00296   _typeDesc( constraint->shortID() ),
00297   _constraint( constraint ),
00298   _allowMore(false)
00299 { 
00300     parser.add( this );
00301     _acceptsMultipleValues = true;
00302 }
00303 
00304 template<class T>
00305 const std::vector<T>& MultiArg<T>::getValue() { return _values; }
00306 
00307 template<class T>
00308 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) 
00309 {
00310     if ( _ignoreable && Arg::ignoreRest() )
00311         return false;
00312 
00313     if ( _hasBlanks( args[*i] ) )
00314         return false;
00315 
00316     std::string flag = args[*i];
00317     std::string value = "";
00318 
00319     trimFlag( flag, value );
00320 
00321     if ( argMatches( flag ) )
00322     {
00323         if ( Arg::delimiter() != ' ' && value == "" )
00324             throw( ArgParseException( 
00325                        "Couldn't find delimiter for this argument!",
00326                        toString() ) );
00327 
00328         // always take the first one, regardless of start string
00329         if ( value == "" )
00330         {
00331             (*i)++;
00332             if ( static_cast<unsigned int>(*i) < args.size() )
00333                 _extractValue( args[*i] );
00334             else
00335                 throw( ArgParseException("Missing a value for this argument!",
00336                                          toString() ) );
00337         } 
00338         else
00339             _extractValue( value );
00340 
00341         /*
00342         // continuing taking the args until we hit one with a start string 
00343         while ( (unsigned int)(*i)+1 < args.size() &&
00344                 args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
00345                 args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 
00346                 _extractValue( args[++(*i)] );
00347         */
00348 
00349         _alreadySet = true;
00350         _checkWithVisitor();
00351 
00352         return true;
00353     }
00354     else
00355         return false;
00356 }
00357 
00358 /**
00359  *
00360  */
00361 template<class T>
00362 std::string MultiArg<T>::shortID(const std::string& val) const
00363 {
00364     static_cast<void>(val); // Ignore input, don't warn
00365     return Arg::shortID(_typeDesc) + " ... ";
00366 }
00367 
00368 /**
00369  *
00370  */
00371 template<class T>
00372 std::string MultiArg<T>::longID(const std::string& val) const
00373 {
00374     static_cast<void>(val); // Ignore input, don't warn
00375     return Arg::longID(_typeDesc) + "  (accepted multiple times)";
00376 }
00377 
00378 /**
00379  * Once we've matched the first value, then the arg is no longer
00380  * required.
00381  */
00382 template<class T>
00383 bool MultiArg<T>::isRequired() const
00384 {
00385     if ( _required )
00386     {
00387         if ( _values.size() > 1 )
00388             return false;
00389         else
00390             return true;
00391     }
00392     else
00393         return false;
00394 
00395 }
00396 
00397 template<class T>
00398 void MultiArg<T>::_extractValue( const std::string& val ) 
00399 {
00400     try {
00401     T tmp;
00402     ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory());
00403     _values.push_back(tmp);
00404     } catch( ArgParseException &e) {
00405     throw ArgParseException(e.error(), toString());
00406     }
00407 
00408     if ( _constraint != NULL )
00409     if ( ! _constraint->check( _values.back() ) )
00410         throw( CmdLineParseException( "Value '" + val +
00411                       "' does not meet constraint: " +
00412                       _constraint->description(), 
00413                       toString() ) );
00414 }
00415         
00416 template<class T>
00417 bool MultiArg<T>::allowMore()
00418 {
00419     bool am = _allowMore;
00420     _allowMore = true;
00421     return am;
00422 }
00423 
00424 template<class T>
00425 void MultiArg<T>::reset()
00426 {
00427     Arg::reset();
00428     _values.clear();
00429 }
00430 
00431 } // namespace TCLAP
00432 
00433 #endif