MultiArg.h

Go to the documentation of this file.
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 <tclap/Arg.h>
00030 #include <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 MultiArg;
00049 
00050 namespace MULTI_ARG_HELPER {
00051 
00052 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY };
00053 
00063 template<class T>
00064 class ValueExtractor 
00065 {
00066     friend class MultiArg<T>;
00067   
00068     private:
00069 
00074         std::vector<T> &_values;
00075   
00080         ValueExtractor(std::vector<T> &values) : _values(values) {}
00081   
00087         int extractValue( const std::string& val ) 
00088         {
00089             T temp;
00090 
00091 #if defined(HAVE_SSTREAM)
00092             std::istringstream is(val);
00093 #elif defined(HAVE_STRSTREAM)
00094             std::istrstream is(val.c_str());
00095 #else
00096 #error "Need a stringstream (sstream or strstream) to compile!"
00097 #endif
00098 
00099             int valuesRead = 0;
00100     
00101             while ( is.good() ) 
00102             {
00103                 if ( is.peek() != EOF )
00104                     is >> temp; 
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             _values.push_back(temp);
00118     
00119             return 0;
00120         } 
00121 };
00122 
00128 template<>
00129 class ValueExtractor<std::string> 
00130 {
00131     friend class MultiArg<std::string>;
00132 
00133     private:
00134 
00139         std::vector<std::string> &_values;
00140   
00145         ValueExtractor(std::vector<std::string> &values) : _values(values) {}
00146 
00152         int extractValue( const std::string& val ) 
00153         {
00154             _values.push_back( val );
00155             return 0;
00156         }
00157 };
00158 
00159 } //namespace MULTI_ARG_HELPER
00160 
00166 template<class T>
00167 class MultiArg : public Arg
00168 {
00169     protected:
00170 
00174         std::vector<T> _values;
00175 
00179         std::string _typeDesc;
00180 
00184         Constraint<T>* _constraint;
00185 
00192         void _extractValue( const std::string& val );
00193 
00194         bool _allowMore;
00195 
00196     public:
00197 
00215         MultiArg( const std::string& flag,
00216                   const std::string& name,
00217                   const std::string& desc,
00218                   bool req,
00219                   const std::string& typeDesc,
00220                   Visitor* v = NULL);
00221 
00240         MultiArg( const std::string& flag, 
00241                   const std::string& name,
00242                   const std::string& desc,
00243                   bool req,
00244                   const std::string& typeDesc,
00245                   CmdLineInterface& parser,
00246                   Visitor* v = NULL );
00247 
00263         MultiArg( const std::string& flag,
00264                   const std::string& name,
00265                   const std::string& desc,
00266                   bool req,
00267                   Constraint<T>* constraint,
00268                   Visitor* v = NULL );
00269           
00286         MultiArg( const std::string& flag, 
00287                   const std::string& name,
00288                   const std::string& desc,
00289                   bool req,
00290                   Constraint<T>* constraint,
00291                   CmdLineInterface& parser,
00292                   Visitor* v = NULL );
00293           
00302         virtual bool processArg(int* i, std::vector<std::string>& args); 
00303 
00308         const std::vector<T>& getValue();
00309 
00314         virtual std::string shortID(const std::string& val="val") const;
00315 
00320         virtual std::string longID(const std::string& val="val") const;
00321 
00326         virtual bool isRequired() const;
00327 
00328         virtual bool allowMore();
00329 
00330 };
00331 
00332 template<class T>
00333 MultiArg<T>::MultiArg(const std::string& flag, 
00334                       const std::string& name,
00335                       const std::string& desc,
00336                       bool req,
00337                       const std::string& typeDesc,
00338                       Visitor* v)
00339 : Arg( flag, name, desc, req, true, v ),
00340   _typeDesc( typeDesc ),
00341   _constraint( NULL ),
00342   _allowMore(false)
00343 { 
00344     _acceptsMultipleValues = true;
00345 }
00346 
00347 template<class T>
00348 MultiArg<T>::MultiArg(const std::string& flag, 
00349                       const std::string& name,
00350                       const std::string& desc,
00351                       bool req,
00352                       const std::string& typeDesc,
00353                       CmdLineInterface& parser,
00354                       Visitor* v)
00355 : Arg( flag, name, desc, req, true, v ),
00356   _typeDesc( typeDesc ),
00357   _constraint( NULL ),
00358   _allowMore(false)
00359 { 
00360     parser.add( this );
00361     _acceptsMultipleValues = true;
00362 }
00363 
00367 template<class T>
00368 MultiArg<T>::MultiArg(const std::string& flag, 
00369                       const std::string& name,
00370                       const std::string& desc,
00371                       bool req,
00372                       Constraint<T>* constraint,
00373                       Visitor* v)
00374 : Arg( flag, name, desc, req, true, v ),
00375   _typeDesc( constraint->shortID() ),
00376   _constraint( constraint ),
00377   _allowMore(false)
00378 { 
00379     _acceptsMultipleValues = true;
00380 }
00381 
00382 template<class T>
00383 MultiArg<T>::MultiArg(const std::string& flag, 
00384                       const std::string& name,
00385                       const std::string& desc,
00386                       bool req,
00387                       Constraint<T>* constraint,
00388                       CmdLineInterface& parser,
00389                       Visitor* v)
00390 : Arg( flag, name, desc, req, true, v ),
00391   _typeDesc( constraint->shortID() ),
00392   _constraint( constraint ),
00393   _allowMore(false)
00394 { 
00395     parser.add( this );
00396     _acceptsMultipleValues = true;
00397 }
00398 
00399 template<class T>
00400 const std::vector<T>& MultiArg<T>::getValue() { return _values; }
00401 
00402 template<class T>
00403 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) 
00404 {
00405     if ( _ignoreable && Arg::ignoreRest() )
00406         return false;
00407 
00408     if ( _hasBlanks( args[*i] ) )
00409         return false;
00410 
00411     std::string flag = args[*i];
00412     std::string value = "";
00413 
00414     trimFlag( flag, value );
00415 
00416     if ( argMatches( flag ) )
00417     {
00418         if ( Arg::delimiter() != ' ' && value == "" )
00419             throw( ArgParseException( 
00420                        "Couldn't find delimiter for this argument!",
00421                        toString() ) );
00422 
00423         // always take the first one, regardless of start string
00424         if ( value == "" )
00425         {
00426             (*i)++;
00427             if ( static_cast<unsigned int>(*i) < args.size() )
00428                 _extractValue( args[*i] );
00429             else
00430                 throw( ArgParseException("Missing a value for this argument!",
00431                                          toString() ) );
00432         } 
00433         else
00434             _extractValue( value );
00435 
00436         /*
00437         // continuing taking the args until we hit one with a start string 
00438         while ( (unsigned int)(*i)+1 < args.size() &&
00439                 args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
00440                 args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 
00441                 _extractValue( args[++(*i)] );
00442         */
00443 
00444         _alreadySet = true;
00445         _checkWithVisitor();
00446 
00447         return true;
00448     }
00449     else
00450         return false;
00451 }
00452 
00456 template<class T>
00457 std::string MultiArg<T>::shortID(const std::string& val) const
00458 {
00459     std::string id = Arg::shortID(_typeDesc) + " ... ";
00460 
00461     return id;
00462 }
00463 
00467 template<class T>
00468 std::string MultiArg<T>::longID(const std::string& val) const
00469 {
00470     std::string id = Arg::longID(_typeDesc) + "  (accepted multiple times)";
00471 
00472     return id;
00473 }
00474 
00479 template<class T>
00480 bool MultiArg<T>::isRequired() const
00481 {
00482     if ( _required )
00483     {
00484         if ( _values.size() > 1 )
00485             return false;
00486         else
00487             return true;
00488     }
00489     else
00490         return false;
00491 
00492 }
00493 
00494 template<class T>
00495 void MultiArg<T>::_extractValue( const std::string& val ) 
00496 {
00497     MULTI_ARG_HELPER::ValueExtractor<T> ve(_values);
00498           
00499     int err = ve.extractValue(val);
00500 
00501     if ( err == MULTI_ARG_HELPER::EXTRACT_FAILURE )
00502         throw( ArgParseException("Couldn't read argument value "
00503                                  "from string '" + val + "'", toString() ) );
00504 
00505     if(err == MULTI_ARG_HELPER::EXTRACT_TOO_MANY)
00506         throw( ArgParseException("More than one valid value "
00507                                  "parsed from string '" + val + "'", 
00508                                  toString() ) );            
00509     if ( _constraint != NULL )
00510         if ( ! _constraint->check( _values.back() ) )
00511             throw( CmdLineParseException( "Value '" + val +
00512                                           "' does not meet constraint: " +
00513                                           _constraint->description(), 
00514                                           toString() ) );
00515 }
00516         
00517 template<class T>
00518 bool MultiArg<T>::allowMore()
00519 {
00520     bool am = _allowMore;
00521     _allowMore = true;
00522     return am;
00523 }
00524 
00525 } // namespace TCLAP
00526 
00527 #endif

Generated on Thu Dec 14 23:01:53 2006 for tclap by  doxygen 1.5.1