$search
00001 00011 /***************************************************************************** 00012 ** Ifdefs 00013 *****************************************************************************/ 00014 00015 #ifndef TCLAP_MULTIPLE_ARGUMENT_H 00016 #define TCLAP_MULTIPLE_ARGUMENT_H 00017 00018 #include <string> 00019 #include <vector> 00020 #include <cstdio> 00021 #include "arg.hpp" 00022 #include "constraint.hpp" 00023 00024 #define HAVE_SSTREAM 00025 00026 #if defined(HAVE_SSTREAM) 00027 #include <sstream> 00028 #elif defined(HAVE_STRSTREAM) 00029 #include <strstream> 00030 #else 00031 #error "Need a stringstream (sstream or strstream) to compile!" 00032 #endif 00033 00034 namespace ecl { 00035 00036 template<class T> class MultiArg; 00037 00038 namespace MultiArgHelper { 00039 00040 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY }; 00041 00053 template<class T> 00054 class ValueExtractor 00055 { 00056 friend class MultiArg<T>; 00057 00058 private: 00059 00064 std::vector<T> &_values; 00065 00070 ValueExtractor(std::vector<T> &values) : _values(values) {} 00071 00077 int extractValue( const std::string& val ) 00078 { 00079 T temp; 00080 00081 #if defined(HAVE_SSTREAM) 00082 std::istringstream is(val); 00083 #elif defined(HAVE_STRSTREAM) 00084 std::istrstream is(val.c_str()); 00085 #else 00086 #error "Need a stringstream (sstream or strstream) to compile!" 00087 #endif 00088 00089 int valuesRead = 0; 00090 00091 while ( is.good() ) 00092 { 00093 if ( is.peek() != EOF ) 00094 is >> temp; 00095 else 00096 break; 00097 00098 valuesRead++; 00099 } 00100 00101 if ( is.fail() ) 00102 return EXTRACT_FAILURE; 00103 00104 if ( valuesRead > 1 ) 00105 return EXTRACT_TOO_MANY; 00106 00107 _values.push_back(temp); 00108 00109 return 0; 00110 } 00111 }; 00112 00120 template<> 00121 class ValueExtractor<std::string> 00122 { 00123 friend class MultiArg<std::string>; 00124 00125 private: 00126 00131 std::vector<std::string> &_values; 00132 00137 ValueExtractor(std::vector<std::string> &values) : _values(values) {} 00138 00144 int extractValue( const std::string& val ) 00145 { 00146 _values.push_back( val ); 00147 return 0; 00148 } 00149 }; 00150 00151 } //namespace MultiArgHelper 00152 00158 template<class T> 00159 class MultiArg : public Arg 00160 { 00161 protected: 00162 00166 std::vector<T> _values; 00167 00171 std::string _typeDesc; 00172 00176 Constraint<T>* _constraint; 00177 00184 void _extractValue( const std::string& val ); 00185 00186 bool _allowMore; 00187 00188 public: 00189 00207 MultiArg( const std::string& flag, 00208 const std::string& name, 00209 const std::string& desc, 00210 bool req, 00211 const std::string& typeDesc, 00212 Visitor* v = NULL); 00213 00232 MultiArg( const std::string& flag, 00233 const std::string& name, 00234 const std::string& desc, 00235 bool req, 00236 const std::string& typeDesc, 00237 CmdLineInterface& parser, 00238 Visitor* v = NULL ); 00239 00255 MultiArg( const std::string& flag, 00256 const std::string& name, 00257 const std::string& desc, 00258 bool req, 00259 Constraint<T>* constraint, 00260 Visitor* v = NULL ); 00261 00278 MultiArg( const std::string& flag, 00279 const std::string& name, 00280 const std::string& desc, 00281 bool req, 00282 Constraint<T>* constraint, 00283 CmdLineInterface& parser, 00284 Visitor* v = NULL ); 00285 00294 virtual bool processArg(int* i, std::vector<std::string>& args); 00295 00300 const std::vector<T>& getValue(); 00301 00306 virtual std::string shortID(const std::string& val="val") const; 00307 00312 virtual std::string longID(const std::string& val="val") const; 00313 00318 virtual bool isRequired() const; 00319 00320 virtual bool allowMore(); 00321 00322 }; 00323 00324 template<class T> 00325 MultiArg<T>::MultiArg(const std::string& flag, 00326 const std::string& name, 00327 const std::string& desc, 00328 bool req, 00329 const std::string& typeDesc, 00330 Visitor* v) 00331 : Arg( flag, name, desc, req, true, v ), 00332 _typeDesc( typeDesc ), 00333 _constraint( NULL ), 00334 _allowMore(false) 00335 { 00336 _acceptsMultipleValues = true; 00337 } 00338 00339 template<class T> 00340 MultiArg<T>::MultiArg(const std::string& flag, 00341 const std::string& name, 00342 const std::string& desc, 00343 bool req, 00344 const std::string& typeDesc, 00345 CmdLineInterface& parser, 00346 Visitor* v) 00347 : Arg( flag, name, desc, req, true, v ), 00348 _typeDesc( typeDesc ), 00349 _constraint( NULL ), 00350 _allowMore(false) 00351 { 00352 parser.add( this ); 00353 _acceptsMultipleValues = true; 00354 } 00355 00359 template<class T> 00360 MultiArg<T>::MultiArg(const std::string& flag, 00361 const std::string& name, 00362 const std::string& desc, 00363 bool req, 00364 Constraint<T>* constraint, 00365 Visitor* v) 00366 : Arg( flag, name, desc, req, true, v ), 00367 _typeDesc( constraint->shortID() ), 00368 _constraint( constraint ), 00369 _allowMore(false) 00370 { 00371 _acceptsMultipleValues = true; 00372 } 00373 00374 template<class T> 00375 MultiArg<T>::MultiArg(const std::string& flag, 00376 const std::string& name, 00377 const std::string& desc, 00378 bool req, 00379 Constraint<T>* constraint, 00380 CmdLineInterface& parser, 00381 Visitor* v) 00382 : Arg( flag, name, desc, req, true, v ), 00383 _typeDesc( constraint->shortID() ), 00384 _constraint( constraint ), 00385 _allowMore(false) 00386 { 00387 parser.add( this ); 00388 _acceptsMultipleValues = true; 00389 } 00390 00391 template<class T> 00392 const std::vector<T>& MultiArg<T>::getValue() { return _values; } 00393 00394 template<class T> 00395 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) 00396 { 00397 if ( _ignoreable && Arg::ignoreRest() ) 00398 return false; 00399 00400 if ( _hasBlanks( args[*i] ) ) 00401 return false; 00402 00403 std::string flag = args[*i]; 00404 std::string value = ""; 00405 00406 trimFlag( flag, value ); 00407 00408 if ( argMatches( flag ) ) 00409 { 00410 if ( Arg::delimiter() != ' ' && value == "" ) 00411 throw( ArgParseException( 00412 "Couldn't find delimiter for this argument!", 00413 toString() ) ); 00414 00415 // always take the first one, regardless of start string 00416 if ( value == "" ) 00417 { 00418 (*i)++; 00419 if ( static_cast<unsigned int>(*i) < args.size() ) 00420 _extractValue( args[*i] ); 00421 else 00422 throw( ArgParseException("Missing a value for this argument!", 00423 toString() ) ); 00424 } 00425 else 00426 _extractValue( value ); 00427 00428 /* 00429 // continuing taking the args until we hit one with a start string 00430 while ( (unsigned int)(*i)+1 < args.size() && 00431 args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 00432 args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 00433 _extractValue( args[++(*i)] ); 00434 */ 00435 00436 _alreadySet = true; 00437 _checkWithVisitor(); 00438 00439 return true; 00440 } 00441 else 00442 return false; 00443 } 00444 00448 template<class T> 00449 std::string MultiArg<T>::shortID(const std::string& val) const 00450 { 00451 std::string id = Arg::shortID(_typeDesc) + " ... "; 00452 00453 return id; 00454 } 00455 00459 template<class T> 00460 std::string MultiArg<T>::longID(const std::string& val) const 00461 { 00462 std::string id = Arg::longID(_typeDesc) + " (accepted multiple times)"; 00463 00464 return id; 00465 } 00466 00471 template<class T> 00472 bool MultiArg<T>::isRequired() const 00473 { 00474 if ( _required ) 00475 { 00476 if ( _values.size() > 1 ) 00477 return false; 00478 else 00479 return true; 00480 } 00481 else 00482 return false; 00483 00484 } 00485 00486 template<class T> 00487 void MultiArg<T>::_extractValue( const std::string& val ) 00488 { 00489 MultiArgHelper::ValueExtractor<T> ve(_values); 00490 00491 int err = ve.extractValue(val); 00492 00493 if ( err == MultiArgHelper::EXTRACT_FAILURE ) 00494 throw( ArgParseException("Couldn't read argument value " 00495 "from string '" + val + "'", toString() ) ); 00496 00497 if(err == MultiArgHelper::EXTRACT_TOO_MANY) 00498 throw( ArgParseException("More than one valid value " 00499 "parsed from string '" + val + "'", 00500 toString() ) ); 00501 if ( _constraint != NULL ) 00502 if ( ! _constraint->check( _values.back() ) ) 00503 throw( CmdLineParseException( "Value '" + val + 00504 "' does not meet constraint: " + 00505 _constraint->description(), 00506 toString() ) ); 00507 } 00508 00509 template<class T> 00510 bool MultiArg<T>::allowMore() 00511 { 00512 bool am = _allowMore; 00513 _allowMore = true; 00514 return am; 00515 } 00516 00517 }; // namespace ecl 00518 00519 00520 #endif