Changeset 1515 for trunk/third_party/tclap/MultiArg.h
- Timestamp:
- 24/08/10 11:23:06 (21 months ago)
- File:
-
- 1 edited
-
trunk/third_party/tclap/MultiArg.h (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/third_party/tclap/MultiArg.h
r1506 r1515 28 28 29 29 #include <tclap/Arg.h> 30 31 #ifdef _____HAVE_CONFIG_H /* not needed */ 32 #include <config.h> 33 #else 34 #define HAVE_SSTREAM 35 #endif 36 37 #if defined(HAVE_SSTREAM) 38 #include <sstream> 39 #elif defined(HAVE_STRSTREAM) 40 #include <strstream> 41 #else 42 #error "Need a stringstream (sstream or strstream) to compile!" 43 #endif 30 #include <tclap/Constraint.h> 44 31 45 32 namespace TCLAP { 46 47 template<class T> class MultiArg;48 49 namespace MULTI_ARG_HELPER {50 51 enum Error_e { EXTRACT_FAILURE = 1000, EXTRACT_TOO_MANY };52 53 /**54 * This class is used to extract a value from an argument.55 * It is used because we need a special implementation to56 * deal with std::string and making a specialiced function57 * puts it in the T segment, thus generating link errors.58 * Having a specialiced class makes the symbols weak.59 * This is not pretty but I don't know how to make it60 * work any other way.61 */62 template<class T>63 class ValueExtractor64 {65 friend class MultiArg<T>;66 67 private:68 69 /**70 * Reference to the vector of values where the result of the71 * extraction will be put.72 */73 std::vector<T> &_values;74 75 /**76 * Constructor.77 * \param values - Where the values extracted will be put.78 */79 ValueExtractor(std::vector<T> &values) : _values(values) {}80 81 /**82 * Method that will attempt to parse the input stream for values83 * of type T.84 * \param val - Where the values parsed will be put.85 */86 int extractValue( const std::string& val )87 {88 T temp;89 90 #if defined(HAVE_SSTREAM)91 std::istringstream is(val);92 #elif defined(HAVE_STRSTREAM)93 std::istrstream is(val.c_str());94 #else95 #error "Need a stringstream (sstream or strstream) to compile!"96 #endif97 98 int valuesRead = 0;99 100 while ( is.good() )101 {102 if ( is.peek() != EOF )103 is >> temp;104 else105 break;106 107 valuesRead++;108 }109 110 if ( is.fail() )111 return EXTRACT_FAILURE;112 113 if ( valuesRead > 1 )114 return EXTRACT_TOO_MANY;115 116 _values.push_back(temp);117 118 return 0;119 }120 };121 122 /**123 * Specialization for string. This is necessary because istringstream124 * operator>> is not able to ignore spaces... meaning -x "X Y" will only125 * read 'X'... and thus the specialization.126 */127 template<>128 class ValueExtractor<std::string>129 {130 friend class MultiArg<std::string>;131 132 private:133 134 /**135 * Reference to the vector of strings where the result of the136 * extraction will be put.137 */138 std::vector<std::string> &_values;139 140 /**141 * Constructor.142 * \param values - Where the strings extracted will be put.143 */144 ValueExtractor(std::vector<std::string> &values) : _values(values) {}145 146 /**147 * Method that will attempt to parse the input stream for values148 * of type std::string.149 * \param val - Where the values parsed will be put.150 */151 int extractValue( const std::string& val )152 {153 _values.push_back( val );154 return 0;155 }156 };157 158 } //namespace MULTI_ARG_HELPER159 160 33 /** 161 34 * An argument that allows multiple values of type T to be specified. Very … … 166 39 class MultiArg : public Arg 167 40 { 168 protected: 169 170 /** 171 * The list of values parsed from the CmdLine. 172 */ 173 std::vector<T> _values; 174 175 /** 176 * A list of allowed values. 177 * A list of values allowed for this argument. If the value parsed 178 * for this arg is not found in this list, then an exception is 179 * thrown. If the list is empty, then any value is allowed. 180 */ 181 std::vector<T> _allowed; 182 183 /** 184 * The description of type T to be used in the usage. 185 */ 186 std::string _typeDesc; 187 188 /** 189 * Extracts the value from the string. 190 * Attempts to parse string as type T, if this fails an exception 191 * is thrown. 192 * \param val - The string to be read. 193 */ 194 void _extractValue( const std::string& val ); 195 196 /** 197 * Checks to see if parsed value is in allowed list. 198 * \param val - value parsed (only used in output). 199 */ 200 void _checkAllowed( const std::string& val ); 201 202 public: 203 204 /** 205 * Constructor. 206 * \param flag - The one character flag that identifies this 207 * argument on the command line. 208 * \param name - A one word name for the argument. Can be 209 * used as a long flag on the command line. 210 * \param desc - A description of what the argument is for or 211 * does. 212 * \param req - Whether the argument is required on the command 213 * line. 214 * \param typeDesc - A short, human readable description of the 215 * type that this object expects. This is used in the generation 216 * of the USAGE statement. The goal is to be helpful to the end user 217 * of the program. 218 * \param v - An optional visitor. You probably should not 219 * use this unless you have a very good reason. 220 */ 221 MultiArg( const std::string& flag, 41 public: 42 typedef std::vector<T> container_type; 43 typedef typename container_type::iterator iterator; 44 typedef typename container_type::const_iterator const_iterator; 45 46 protected: 47 48 /** 49 * The list of values parsed from the CmdLine. 50 */ 51 std::vector<T> _values; 52 53 /** 54 * The description of type T to be used in the usage. 55 */ 56 std::string _typeDesc; 57 58 /** 59 * A list of constraint on this Arg. 60 */ 61 Constraint<T>* _constraint; 62 63 /** 64 * Extracts the value from the string. 65 * Attempts to parse string as type T, if this fails an exception 66 * is thrown. 67 * \param val - The string to be read. 68 */ 69 void _extractValue( const std::string& val ); 70 71 /** 72 * Used by XorHandler to decide whether to keep parsing for this arg. 73 */ 74 bool _allowMore; 75 76 public: 77 78 /** 79 * Constructor. 80 * \param flag - The one character flag that identifies this 81 * argument on the command line. 82 * \param name - A one word name for the argument. Can be 83 * used as a long flag on the command line. 84 * \param desc - A description of what the argument is for or 85 * does. 86 * \param req - Whether the argument is required on the command 87 * line. 88 * \param typeDesc - A short, human readable description of the 89 * type that this object expects. This is used in the generation 90 * of the USAGE statement. The goal is to be helpful to the end user 91 * of the program. 92 * \param v - An optional visitor. You probably should not 93 * use this unless you have a very good reason. 94 */ 95 MultiArg( const std::string& flag, 222 96 const std::string& name, 223 97 const std::string& desc, … … 226 100 Visitor* v = NULL); 227 101 228 /**229 * Constructor.230 * \param flag - The one character flag that identifies this231 * argument on the command line.232 * \param name - A one word name for the argument. Can be233 * used as a long flag on the command line.234 * \param desc - A description of what the argument is for or235 * does.236 * \param req - Whether the argument is required on the command237 * line.238 * \param typeDesc - A short, human readable description of the239 * type that this object expects. This is used in the generation240 * of the USAGE statement. The goal is to be helpful to the end user241 * of the program.242 * \param parser - A CmdLine parser object to add this Arg to243 * \param v - An optional visitor. You probably should not244 * use this unless you have a very good reason.245 */246 MultiArg( const std::string& flag,102 /** 103 * Constructor. 104 * \param flag - The one character flag that identifies this 105 * argument on the command line. 106 * \param name - A one word name for the argument. Can be 107 * used as a long flag on the command line. 108 * \param desc - A description of what the argument is for or 109 * does. 110 * \param req - Whether the argument is required on the command 111 * line. 112 * \param typeDesc - A short, human readable description of the 113 * type that this object expects. This is used in the generation 114 * of the USAGE statement. The goal is to be helpful to the end user 115 * of the program. 116 * \param parser - A CmdLine parser object to add this Arg to 117 * \param v - An optional visitor. You probably should not 118 * use this unless you have a very good reason. 119 */ 120 MultiArg( const std::string& flag, 247 121 const std::string& name, 248 122 const std::string& desc, … … 252 126 Visitor* v = NULL ); 253 127 254 /**255 * Constructor.256 * \param flag - The one character flag that identifies this257 * argument on the command line.258 * \param name - A one word name for the argument. Can be259 * used as a long flag on the command line.260 * \param desc - A description of what the argument is for or261 * does.262 * \param req - Whether the argument is required on the command263 * line.264 * \param allowed - A vector of type T that where the values in the265 * vector are the only values allowed for the arg.266 * \param v - An optional visitor. You probably should not267 * use this unless you have a very good reason.268 */269 MultiArg( const std::string& flag,128 /** 129 * Constructor. 130 * \param flag - The one character flag that identifies this 131 * argument on the command line. 132 * \param name - A one word name for the argument. Can be 133 * used as a long flag on the command line. 134 * \param desc - A description of what the argument is for or 135 * does. 136 * \param req - Whether the argument is required on the command 137 * line. 138 * \param constraint - A pointer to a Constraint object used 139 * to constrain this Arg. 140 * \param v - An optional visitor. You probably should not 141 * use this unless you have a very good reason. 142 */ 143 MultiArg( const std::string& flag, 270 144 const std::string& name, 271 145 const std::string& desc, 272 146 bool req, 273 const std::vector<T>& allowed,147 Constraint<T>* constraint, 274 148 Visitor* v = NULL ); 275 149 276 /**277 * Constructor.278 * \param flag - The one character flag that identifies this279 * argument on the command line.280 * \param name - A one word name for the argument. Can be281 * used as a long flag on the command line.282 * \param desc - A description of what the argument is for or283 * does.284 * \param req - Whether the argument is required on the command285 * line.286 * \param allowed - A vector of type T that where the values in the287 * vector are the only values allowed for the arg.288 * \param parser - A CmdLine parser object to add this Arg to289 * \param v - An optional visitor. You probably should not290 * use this unless you have a very good reason.291 */292 MultiArg( const std::string& flag,150 /** 151 * Constructor. 152 * \param flag - The one character flag that identifies this 153 * argument on the command line. 154 * \param name - A one word name for the argument. Can be 155 * used as a long flag on the command line. 156 * \param desc - A description of what the argument is for or 157 * does. 158 * \param req - Whether the argument is required on the command 159 * line. 160 * \param constraint - A pointer to a Constraint object used 161 * to constrain this Arg. 162 * \param parser - A CmdLine parser object to add this Arg to 163 * \param v - An optional visitor. You probably should not 164 * use this unless you have a very good reason. 165 */ 166 MultiArg( const std::string& flag, 293 167 const std::string& name, 294 168 const std::string& desc, 295 169 bool req, 296 const std::vector<T>& allowed,170 Constraint<T>* constraint, 297 171 CmdLineInterface& parser, 298 172 Visitor* v = NULL ); 299 173 300 /** 301 * Handles the processing of the argument. 302 * This re-implements the Arg version of this method to set the 303 * _value of the argument appropriately. It knows the difference 304 * between labeled and unlabeled. 305 * \param i - Pointer the the current argument in the list. 306 * \param args - Mutable list of strings. Passed from main(). 307 */ 308 virtual bool processArg(int* i, std::vector<std::string>& args); 309 310 /** 311 * Returns a vector of type T containing the values parsed from 312 * the command line. 313 */ 314 const std::vector<T>& getValue(); 315 316 /** 317 * Returns the a short id string. Used in the usage. 318 * \param val - value to be used. 319 */ 320 virtual std::string shortID(const std::string& val="val") const; 321 322 /** 323 * Returns the a long id string. Used in the usage. 324 * \param val - value to be used. 325 */ 326 virtual std::string longID(const std::string& val="val") const; 327 328 /** 329 * Once we've matched the first value, then the arg is no longer 330 * required. 331 */ 332 virtual bool isRequired() const; 333 334 private: 335 336 /** 337 * Common initialization code for constructors with allowed vectors. 338 */ 339 void allowedInit(); 174 /** 175 * Handles the processing of the argument. 176 * This re-implements the Arg version of this method to set the 177 * _value of the argument appropriately. It knows the difference 178 * between labeled and unlabeled. 179 * \param i - Pointer the the current argument in the list. 180 * \param args - Mutable list of strings. Passed from main(). 181 */ 182 virtual bool processArg(int* i, std::vector<std::string>& args); 183 184 /** 185 * Returns a vector of type T containing the values parsed from 186 * the command line. 187 */ 188 const std::vector<T>& getValue(); 189 190 /** 191 * Returns an iterator over the values parsed from the command 192 * line. 193 */ 194 const_iterator begin() const { return _values.begin(); } 195 196 /** 197 * Returns the end of the values parsed from the command 198 * line. 199 */ 200 const_iterator end() const { return _values.end(); } 201 202 /** 203 * Returns the a short id string. Used in the usage. 204 * \param val - value to be used. 205 */ 206 virtual std::string shortID(const std::string& val="val") const; 207 208 /** 209 * Returns the a long id string. Used in the usage. 210 * \param val - value to be used. 211 */ 212 virtual std::string longID(const std::string& val="val") const; 213 214 /** 215 * Once we've matched the first value, then the arg is no longer 216 * required. 217 */ 218 virtual bool isRequired() const; 219 220 virtual bool allowMore(); 221 222 virtual void reset(); 223 340 224 }; 341 225 342 /**343 *344 */345 template<class T>346 void MultiArg<T>::allowedInit()347 {348 for ( unsigned int i = 0; i < _allowed.size(); i++ )349 {350 351 #if defined(HAVE_SSTREAM)352 std::ostringstream os;353 #elif defined(HAVE_STRSTREAM)354 std::ostrstream os;355 #else356 #error "Need a stringstream (sstream or strstream) to compile!"357 #endif358 359 os << _allowed[i];360 361 std::string temp( os.str() );362 363 if ( i > 0 )364 _typeDesc += "|";365 366 _typeDesc += temp;367 }368 }369 370 /**371 *372 */373 226 template<class T> 374 227 MultiArg<T>::MultiArg(const std::string& flag, … … 379 232 Visitor* v) 380 233 : Arg( flag, name, desc, req, true, v ), 381 _typeDesc( typeDesc ) 382 { } 234 _typeDesc( typeDesc ), 235 _constraint( NULL ), 236 _allowMore(false) 237 { 238 _acceptsMultipleValues = true; 239 } 383 240 384 241 template<class T> … … 391 248 Visitor* v) 392 249 : Arg( flag, name, desc, req, true, v ), 393 _typeDesc( typeDesc ) 250 _typeDesc( typeDesc ), 251 _constraint( NULL ), 252 _allowMore(false) 394 253 { 395 254 parser.add( this ); 255 _acceptsMultipleValues = true; 396 256 } 397 257 … … 404 264 const std::string& desc, 405 265 bool req, 406 const std::vector<T>& allowed,266 Constraint<T>* constraint, 407 267 Visitor* v) 408 268 : Arg( flag, name, desc, req, true, v ), 409 _allowed( allowed ) 269 _typeDesc( constraint->shortID() ), 270 _constraint( constraint ), 271 _allowMore(false) 410 272 { 411 allowedInit();273 _acceptsMultipleValues = true; 412 274 } 413 275 … … 417 279 const std::string& desc, 418 280 bool req, 419 const std::vector<T>& allowed,281 Constraint<T>* constraint, 420 282 CmdLineInterface& parser, 421 283 Visitor* v) 422 284 : Arg( flag, name, desc, req, true, v ), 423 _allowed( allowed ) 285 _typeDesc( constraint->shortID() ), 286 _constraint( constraint ), 287 _allowMore(false) 424 288 { 425 allowedInit();426 289 parser.add( this ); 427 } 428 429 /** 430 * 431 */ 290 _acceptsMultipleValues = true; 291 } 292 432 293 template<class T> 433 294 const std::vector<T>& MultiArg<T>::getValue() { return _values; } 434 295 435 /**436 *437 */438 296 template<class T> 439 297 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args) … … 457 315 toString() ) ); 458 316 317 // always take the first one, regardless of start string 459 318 if ( value == "" ) 460 319 { 461 320 (*i)++; 462 if ( (unsigned int)*i< args.size() )321 if ( static_cast<unsigned int>(*i) < args.size() ) 463 322 _extractValue( args[*i] ); 464 323 else 465 324 throw( ArgParseException("Missing a value for this argument!", 466 325 toString() ) ); 467 } 326 } 468 327 else 469 328 _extractValue( value ); 470 329 330 /* 331 // continuing taking the args until we hit one with a start string 332 while ( (unsigned int)(*i)+1 < args.size() && 333 args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 334 args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 335 _extractValue( args[++(*i)] ); 336 */ 337 338 _alreadySet = true; 471 339 _checkWithVisitor(); 472 340 … … 478 346 479 347 /** 480 * Checks to see if the value parsed is in the allowed list.348 * 481 349 */ 482 350 template<class T> 483 void MultiArg<T>::_checkAllowed( const std::string& val ) 484 { 485 if ( _allowed.size() > 0 ) 486 if ( find(_allowed.begin(),_allowed.end(),_values.back()) 487 == _allowed.end() ) 488 throw( CmdLineParseException( "Couldn't find '" + val + 489 "' in allowed list.", toString() ) ); 351 std::string MultiArg<T>::shortID(const std::string& val) const 352 { 353 static_cast<void>(val); // Ignore input, don't warn 354 return Arg::shortID(_typeDesc) + " ... "; 490 355 } 491 356 … … 494 359 */ 495 360 template<class T> 496 std::string MultiArg<T>::shortID(const std::string& val) const497 {498 std::string id = Arg::shortID(_typeDesc) + " ... ";499 500 return id;501 }502 503 /**504 *505 */506 template<class T>507 361 std::string MultiArg<T>::longID(const std::string& val) const 508 362 { 509 std::string id = Arg::longID(_typeDesc) + " (accepted multiple times)"; 510 511 return id; 363 static_cast<void>(val); // Ignore input, don't warn 364 return Arg::longID(_typeDesc) + " (accepted multiple times)"; 512 365 } 513 366 … … 534 387 void MultiArg<T>::_extractValue( const std::string& val ) 535 388 { 536 MULTI_ARG_HELPER::ValueExtractor<T> ve(_values); 537 538 int err = ve.extractValue(val); 539 540 if ( err == MULTI_ARG_HELPER::EXTRACT_FAILURE ) 541 throw( ArgParseException("Couldn't read argument value " 542 "from string '" + val + "'", toString() ) ); 543 544 if(err == MULTI_ARG_HELPER::EXTRACT_TOO_MANY) 545 throw( ArgParseException("More than one valid value " 546 "parsed from string '" + val + "'", 547 toString() ) ); 548 _checkAllowed( val ); 389 try { 390 T tmp; 391 ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory()); 392 _values.push_back(tmp); 393 } catch( ArgParseException &e) { 394 throw ArgParseException(e.error(), toString()); 395 } 396 397 if ( _constraint != NULL ) 398 if ( ! _constraint->check( _values.back() ) ) 399 throw( CmdLineParseException( "Value '" + val + 400 "' does not meet constraint: " + 401 _constraint->description(), 402 toString() ) ); 549 403 } 550 404 405 template<class T> 406 bool MultiArg<T>::allowMore() 407 { 408 bool am = _allowMore; 409 _allowMore = true; 410 return am; 411 } 412 413 template<class T> 414 void MultiArg<T>::reset() 415 { 416 Arg::reset(); 417 _values.clear(); 418 } 551 419 552 420 } // namespace TCLAP
Note: See TracChangeset
for help on using the changeset viewer.
