00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #else
00034 #define HAVE_SSTREAM
00035 #endif
00036
00037 #if defined(HAVE_SSTREAM)
00038 #include <sstream>
00039 #elif defined(HAVE_STRSTREAM)
00040 #include <strstream>
00041 #else
00042 #error "Need a stringstream (sstream or strstream) to compile!"
00043 #endif
00044
00045 namespace TCLAP {
00046
00047 template<class T> class MultiArg;
00048
00049 namespace MULTI_ARG_HELPER {
00050
00051 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY };
00052
00062 template<class T>
00063 class ValueExtractor
00064 {
00065 friend class MultiArg<T>;
00066
00067 private:
00068
00073 std::vector<T> &_values;
00074
00079 ValueExtractor(std::vector<T> &values) : _values(values) {}
00080
00086 int extractValue( const std::string& val )
00087 {
00088 T temp;
00089
00090 #if defined(HAVE_SSTREAM)
00091 std::istringstream is(val);
00092 #elif defined(HAVE_STRSTREAM)
00093 std::istrstream is(val.c_str());
00094 #else
00095 #error "Need a stringstream (sstream or strstream) to compile!"
00096 #endif
00097
00098 int valuesRead = 0;
00099
00100 while ( is.good() )
00101 {
00102 if ( is.peek() != EOF )
00103 is >> temp;
00104 else
00105 break;
00106
00107 valuesRead++;
00108 }
00109
00110 if ( is.fail() )
00111 return EXTRACT_FAILURE;
00112
00113 if ( valuesRead > 1 )
00114 return EXTRACT_TOO_MANY;
00115
00116 _values.push_back(temp);
00117
00118 return 0;
00119 }
00120 };
00121
00127 template<>
00128 class ValueExtractor<std::string>
00129 {
00130 friend class MultiArg<std::string>;
00131
00132 private:
00133
00138 std::vector<std::string> &_values;
00139
00144 ValueExtractor(std::vector<std::string> &values) : _values(values) {}
00145
00151 int extractValue( const std::string& val )
00152 {
00153 _values.push_back( val );
00154 return 0;
00155 }
00156 };
00157
00158 }
00159
00165 template<class T>
00166 class MultiArg : public Arg
00167 {
00168 protected:
00169
00173 std::vector<T> _values;
00174
00181 std::vector<T> _allowed;
00182
00186 std::string _typeDesc;
00187
00194 void _extractValue( const std::string& val );
00195
00200 void _checkAllowed( const std::string& val );
00201
00202 public:
00203
00221 MultiArg( const std::string& flag,
00222 const std::string& name,
00223 const std::string& desc,
00224 bool req,
00225 const std::string& typeDesc,
00226 Visitor* v = NULL);
00227
00246 MultiArg( const std::string& flag,
00247 const std::string& name,
00248 const std::string& desc,
00249 bool req,
00250 const std::string& typeDesc,
00251 CmdLineInterface& parser,
00252 Visitor* v = NULL );
00253
00269 MultiArg( const std::string& flag,
00270 const std::string& name,
00271 const std::string& desc,
00272 bool req,
00273 const std::vector<T>& allowed,
00274 Visitor* v = NULL );
00275
00292 MultiArg( const std::string& flag,
00293 const std::string& name,
00294 const std::string& desc,
00295 bool req,
00296 const std::vector<T>& allowed,
00297 CmdLineInterface& parser,
00298 Visitor* v = NULL );
00299
00308 virtual bool processArg(int* i, std::vector<std::string>& args);
00309
00314 const std::vector<T>& getValue();
00315
00320 virtual std::string shortID(const std::string& val="val") const;
00321
00326 virtual std::string longID(const std::string& val="val") const;
00327
00332 virtual bool isRequired() const;
00333
00334 private:
00335
00339 void allowedInit();
00340 };
00341
00345 template<class T>
00346 void MultiArg<T>::allowedInit()
00347 {
00348 for ( unsigned int i = 0; i < _allowed.size(); i++ )
00349 {
00350
00351 #if defined(HAVE_SSTREAM)
00352 std::ostringstream os;
00353 #elif defined(HAVE_STRSTREAM)
00354 std::ostrstream os;
00355 #else
00356 #error "Need a stringstream (sstream or strstream) to compile!"
00357 #endif
00358
00359 os << _allowed[i];
00360
00361 std::string temp( os.str() );
00362
00363 if ( i > 0 )
00364 _typeDesc += "|";
00365
00366 _typeDesc += temp;
00367 }
00368 }
00369
00373 template<class T>
00374 MultiArg<T>::MultiArg(const std::string& flag,
00375 const std::string& name,
00376 const std::string& desc,
00377 bool req,
00378 const std::string& typeDesc,
00379 Visitor* v)
00380 : Arg( flag, name, desc, req, true, v ),
00381 _typeDesc( typeDesc )
00382 { }
00383
00384 template<class T>
00385 MultiArg<T>::MultiArg(const std::string& flag,
00386 const std::string& name,
00387 const std::string& desc,
00388 bool req,
00389 const std::string& typeDesc,
00390 CmdLineInterface& parser,
00391 Visitor* v)
00392 : Arg( flag, name, desc, req, true, v ),
00393 _typeDesc( typeDesc )
00394 {
00395 parser.add( this );
00396 }
00397
00401 template<class T>
00402 MultiArg<T>::MultiArg(const std::string& flag,
00403 const std::string& name,
00404 const std::string& desc,
00405 bool req,
00406 const std::vector<T>& allowed,
00407 Visitor* v)
00408 : Arg( flag, name, desc, req, true, v ),
00409 _allowed( allowed )
00410 {
00411 allowedInit();
00412 }
00413
00414 template<class T>
00415 MultiArg<T>::MultiArg(const std::string& flag,
00416 const std::string& name,
00417 const std::string& desc,
00418 bool req,
00419 const std::vector<T>& allowed,
00420 CmdLineInterface& parser,
00421 Visitor* v)
00422 : Arg( flag, name, desc, req, true, v ),
00423 _allowed( allowed )
00424 {
00425 allowedInit();
00426 parser.add( this );
00427 }
00428
00432 template<class T>
00433 const std::vector<T>& MultiArg<T>::getValue() { return _values; }
00434
00438 template<class T>
00439 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
00440 {
00441 if ( _ignoreable && Arg::ignoreRest() )
00442 return false;
00443
00444 if ( _hasBlanks( args[*i] ) )
00445 return false;
00446
00447 std::string flag = args[*i];
00448 std::string value = "";
00449
00450 trimFlag( flag, value );
00451
00452 if ( argMatches( flag ) )
00453 {
00454 if ( Arg::delimiter() != ' ' && value == "" )
00455 throw( ArgParseException(
00456 "Couldn't find delimiter for this argument!",
00457 toString() ) );
00458
00459 if ( value == "" )
00460 {
00461 (*i)++;
00462 if ( (unsigned int)*i < args.size() )
00463 _extractValue( args[*i] );
00464 else
00465 throw( ArgParseException("Missing a value for this argument!",
00466 toString() ) );
00467 }
00468 else
00469 _extractValue( value );
00470
00471 _checkWithVisitor();
00472
00473 return true;
00474 }
00475 else
00476 return false;
00477 }
00478
00482 template<class T>
00483 void MultiArg<T>::_checkAllowed( const std::string& val )
00484 {
00485 if ( _allowed.size() > 0 )
00486 if ( find(_allowed.begin(),_allowed.end(),_values.back())
00487 == _allowed.end() )
00488 throw( CmdLineParseException( "Couldn't find '" + val +
00489 "' in allowed list.", toString() ) );
00490 }
00491
00495 template<class T>
00496 std::string MultiArg<T>::shortID(const std::string& val) const
00497 {
00498 std::string id = Arg::shortID(_typeDesc) + " ... ";
00499
00500 return id;
00501 }
00502
00506 template<class T>
00507 std::string MultiArg<T>::longID(const std::string& val) const
00508 {
00509 std::string id = Arg::longID(_typeDesc) + " (accepted multiple times)";
00510
00511 return id;
00512 }
00513
00518 template<class T>
00519 bool MultiArg<T>::isRequired() const
00520 {
00521 if ( _required )
00522 {
00523 if ( _values.size() > 1 )
00524 return false;
00525 else
00526 return true;
00527 }
00528 else
00529 return false;
00530
00531 }
00532
00533 template<class T>
00534 void MultiArg<T>::_extractValue( const std::string& val )
00535 {
00536 MULTI_ARG_HELPER::ValueExtractor<T> ve(_values);
00537
00538 int err = ve.extractValue(val);
00539
00540 if ( err == MULTI_ARG_HELPER::EXTRACT_FAILURE )
00541 throw( ArgParseException("Couldn't read argument value "
00542 "from string '" + val + "'", toString() ) );
00543
00544 if(err == MULTI_ARG_HELPER::EXTRACT_TOO_MANY)
00545 throw( ArgParseException("More than one valid value "
00546 "parsed from string '" + val + "'",
00547 toString() ) );
00548 _checkAllowed( val );
00549 }
00550
00551
00552 }
00553
00554 #endif