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 #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 }
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
00310 virtual std::string getValueAsString()const;
00311
00316 virtual std::string shortID(const std::string& val="val") const;
00317
00322 virtual std::string longID(const std::string& val="val") const;
00323
00328 virtual bool isRequired() const;
00329
00330 virtual bool allowMore();
00331
00332 };
00333
00334 template<class T>
00335 MultiArg<T>::MultiArg(const std::string& flag,
00336 const std::string& name,
00337 const std::string& desc,
00338 bool req,
00339 const std::string& typeDesc,
00340 Visitor* v)
00341 : Arg( flag, name, desc, req, true, v ),
00342 _typeDesc( typeDesc ),
00343 _constraint( NULL ),
00344 _allowMore(false)
00345 {
00346 _acceptsMultipleValues = true;
00347 }
00348
00349 template<class T>
00350 MultiArg<T>::MultiArg(const std::string& flag,
00351 const std::string& name,
00352 const std::string& desc,
00353 bool req,
00354 const std::string& typeDesc,
00355 CmdLineInterface& parser,
00356 Visitor* v)
00357 : Arg( flag, name, desc, req, true, v ),
00358 _typeDesc( typeDesc ),
00359 _constraint( NULL ),
00360 _allowMore(false)
00361 {
00362 parser.add( this );
00363 _acceptsMultipleValues = true;
00364 }
00365
00369 template<class T>
00370 MultiArg<T>::MultiArg(const std::string& flag,
00371 const std::string& name,
00372 const std::string& desc,
00373 bool req,
00374 Constraint<T>* constraint,
00375 Visitor* v)
00376 : Arg( flag, name, desc, req, true, v ),
00377 _typeDesc( constraint->shortID() ),
00378 _constraint( constraint ),
00379 _allowMore(false)
00380 {
00381 _acceptsMultipleValues = true;
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 Constraint<T>* constraint,
00390 CmdLineInterface& parser,
00391 Visitor* v)
00392 : Arg( flag, name, desc, req, true, v ),
00393 _typeDesc( constraint->shortID() ),
00394 _constraint( constraint ),
00395 _allowMore(false)
00396 {
00397 parser.add( this );
00398 _acceptsMultipleValues = true;
00399 }
00400
00401 template<class T>
00402 const std::vector<T>& MultiArg<T>::getValue() { return _values; }
00403
00404 template<class T>
00405 std::string MultiArg<T>::getValueAsString()const
00406 {
00407 #if defined(HAVE_SSTREAM)
00408 std::ostringstream os;
00409 #elif defined(HAVE_STRSTREAM)
00410 std::ostrstream os;
00411 #else
00412 #error "Need a stringstream (sstream or strstream) to compile!"
00413 #endif
00414 typename std::vector<T>::const_iterator it = _values.begin();
00415 typename std::vector<T>::const_iterator end = _values.end();
00416 if( it != end )
00417 {
00418 os << *it;
00419 ++it;
00420 }
00421 for( ; it != end; ++it )
00422 {
00423 os << " " << *it;
00424 }
00425 return os.str();
00426 }
00427
00428 template<class T>
00429 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
00430 {
00431 if ( _ignoreable && Arg::ignoreRest() )
00432 return false;
00433
00434 if ( _hasBlanks( args[*i] ) )
00435 return false;
00436
00437 std::string flag = args[*i];
00438 std::string value = "";
00439
00440 trimFlag( flag, value );
00441
00442 if ( argMatches( flag ) )
00443 {
00444 if ( Arg::delimiter() != ' ' && value == "" )
00445 throw( ArgParseException(
00446 "Couldn't find delimiter for this argument!",
00447 toString() ) );
00448
00449
00450 if ( value == "" )
00451 {
00452 (*i)++;
00453 if ( static_cast<unsigned int>(*i) < args.size() )
00454 _extractValue( args[*i] );
00455 else
00456 throw( ArgParseException("Missing a value for this argument!",
00457 toString() ) );
00458 }
00459 else
00460 _extractValue( value );
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 _alreadySet = true;
00471 _checkWithVisitor();
00472
00473 return true;
00474 }
00475 else
00476 return false;
00477 }
00478
00482 template<class T>
00483 std::string MultiArg<T>::shortID(const std::string&) const
00484 {
00485 std::string id = Arg::shortID(_typeDesc) + " ... ";
00486
00487 return id;
00488 }
00489
00493 template<class T>
00494 std::string MultiArg<T>::longID(const std::string&) const
00495 {
00496 std::string id = Arg::longID(_typeDesc) + " (accepted multiple times)";
00497
00498 return id;
00499 }
00500
00505 template<class T>
00506 bool MultiArg<T>::isRequired() const
00507 {
00508 if ( _required )
00509 {
00510 if ( _values.size() > 1 )
00511 return false;
00512 else
00513 return true;
00514 }
00515 else
00516 return false;
00517
00518 }
00519
00520 template<class T>
00521 void MultiArg<T>::_extractValue( const std::string& val )
00522 {
00523 MULTI_ARG_HELPER::ValueExtractor<T> ve(_values);
00524
00525 int err = ve.extractValue(val);
00526
00527 if ( err == MULTI_ARG_HELPER::EXTRACT_FAILURE )
00528 throw( ArgParseException("Couldn't read argument value "
00529 "from string '" + val + "'", toString() ) );
00530
00531 if(err == MULTI_ARG_HELPER::EXTRACT_TOO_MANY)
00532 throw( ArgParseException("More than one valid value "
00533 "parsed from string '" + val + "'",
00534 toString() ) );
00535 if ( _constraint != NULL )
00536 if ( ! _constraint->check( _values.back() ) )
00537 throw( CmdLineParseException( "Value '" + val +
00538 "' does not meet constraint: " +
00539 _constraint->description(),
00540 toString() ) );
00541 }
00542
00543 template<class T>
00544 bool MultiArg<T>::allowMore()
00545 {
00546 bool am = _allowMore;
00547 _allowMore = true;
00548 return am;
00549 }
00550
00551 }
00552
00553 #endif