00001
00011
00012
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 }
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
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
00430
00431
00432
00433
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 };
00518
00519
00520 #endif