Main MRPT website > C++ reference
MRPT logo
MultiArg.h
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * file: MultiArg.h
4  *
5  * Copyright (c) 2003, Michael E. Smoot .
6  * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
7  * All rights reverved.
8  *
9  * See the file COPYING in the top directory of this distribution for
10  * more information.
11  *
12  * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
13  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18  * DEALINGS IN THE SOFTWARE.
19  *
20  *****************************************************************************/
21 
22 
23 #ifndef TCLAP_MULTIPLE_ARGUMENT_H
24 #define TCLAP_MULTIPLE_ARGUMENT_H
25 
26 #include <string>
27 #include <vector>
28 
31 
32 //#ifdef HAVE_CONFIG_H
33 //#include <config.h>
34 //#else
35 #define HAVE_SSTREAM
36 //#endif
37 
38 #if defined(HAVE_SSTREAM)
39 #include <sstream>
40 #elif defined(HAVE_STRSTREAM)
41 #include <strstream>
42 #else
43 #error "Need a stringstream (sstream or strstream) to compile!"
44 #endif
45 
46 namespace TCLAP {
47 
48 template<class T> class MultiArg;
49 
50 namespace MULTI_ARG_HELPER {
51 
53 
54 /**
55  * This class is used to extract a value from an argument.
56  * It is used because we need a special implementation to
57  * deal with std::string and making a specialiced function
58  * puts it in the T segment, thus generating link errors.
59  * Having a specialiced class makes the symbols weak.
60  * This is not pretty but I don't know how to make it
61  * work any other way.
62  */
63 template<class T>
65 {
66  friend class MultiArg<T>;
67 
68  private:
69 
70  /**
71  * Reference to the vector of values where the result of the
72  * extraction will be put.
73  */
74  std::vector<T> &_values;
75 
76  /**
77  * Constructor.
78  * \param values - Where the values extracted will be put.
79  */
80  ValueExtractor(std::vector<T> &values) : _values(values) {}
81 
82  /**
83  * Method that will attempt to parse the input stream for values
84  * of type T.
85  * \param val - Where the values parsed will be put.
86  */
87  int extractValue( const std::string& val )
88  {
89  T temp;
90 
91 #if defined(HAVE_SSTREAM)
92  std::istringstream is(val);
93 #elif defined(HAVE_STRSTREAM)
94  std::istrstream is(val.c_str());
95 #else
96 #error "Need a stringstream (sstream or strstream) to compile!"
97 #endif
98 
99  int valuesRead = 0;
100 
101  while ( is.good() )
102  {
103  if ( is.peek() != EOF )
104  is >> temp;
105  else
106  break;
107 
108  valuesRead++;
109  }
110 
111  if ( is.fail() )
112  return EXTRACT_FAILURE;
113 
114  if ( valuesRead > 1 )
115  return EXTRACT_TOO_MANY;
116 
117  _values.push_back(temp);
118 
119  return 0;
120  }
121 };
122 
123 /**
124  * Specialization for string. This is necessary because istringstream
125  * operator>> is not able to ignore spaces... meaning -x "X Y" will only
126  * read 'X'... and thus the specialization.
127  */
128 template<>
129 class ValueExtractor<std::string>
130 {
131  friend class MultiArg<std::string>;
132 
133  private:
134 
135  /**
136  * Reference to the vector of strings where the result of the
137  * extraction will be put.
138  */
139  std::vector<std::string> &_values;
140 
141  /**
142  * Constructor.
143  * \param values - Where the strings extracted will be put.
144  */
145  ValueExtractor(std::vector<std::string> &values) : _values(values) {}
146 
147  /**
148  * Method that will attempt to parse the input stream for values
149  * of type std::string.
150  * \param val - Where the values parsed will be put.
151  */
152  int extractValue( const std::string& val )
153  {
154  _values.push_back( val );
155  return 0;
156  }
157 };
158 
159 } //namespace MULTI_ARG_HELPER
160 
161 /**
162  * An argument that allows multiple values of type T to be specified. Very
163  * similar to a ValueArg, except a vector of values will be returned
164  * instead of just one.
165  */
166 template<class T>
167 class MultiArg : public Arg
168 {
169  protected:
170 
171  /**
172  * The list of values parsed from the CmdLine.
173  */
174  std::vector<T> _values;
175 
176  /**
177  * The description of type T to be used in the usage.
178  */
179  std::string _typeDesc;
180 
181  /**
182  * A list of constraint on this Arg.
183  */
185 
186  /**
187  * Extracts the value from the string.
188  * Attempts to parse string as type T, if this fails an exception
189  * is thrown.
190  * \param val - The string to be read.
191  */
192  void _extractValue( const std::string& val );
193 
195 
196  public:
197 
198  /**
199  * Constructor.
200  * \param flag - The one character flag that identifies this
201  * argument on the command line.
202  * \param name - A one word name for the argument. Can be
203  * used as a long flag on the command line.
204  * \param desc - A description of what the argument is for or
205  * does.
206  * \param req - Whether the argument is required on the command
207  * line.
208  * \param typeDesc - A short, human readable description of the
209  * type that this object expects. This is used in the generation
210  * of the USAGE statement. The goal is to be helpful to the end user
211  * of the program.
212  * \param v - An optional visitor. You probably should not
213  * use this unless you have a very good reason.
214  */
215  MultiArg( const std::string& flag,
216  const std::string& name,
217  const std::string& desc,
218  bool req,
219  const std::string& typeDesc,
220  Visitor* v = NULL);
221 
222  /**
223  * Constructor.
224  * \param flag - The one character flag that identifies this
225  * argument on the command line.
226  * \param name - A one word name for the argument. Can be
227  * used as a long flag on the command line.
228  * \param desc - A description of what the argument is for or
229  * does.
230  * \param req - Whether the argument is required on the command
231  * line.
232  * \param typeDesc - A short, human readable description of the
233  * type that this object expects. This is used in the generation
234  * of the USAGE statement. The goal is to be helpful to the end user
235  * of the program.
236  * \param parser - A CmdLine parser object to add this Arg to
237  * \param v - An optional visitor. You probably should not
238  * use this unless you have a very good reason.
239  */
240  MultiArg( const std::string& flag,
241  const std::string& name,
242  const std::string& desc,
243  bool req,
244  const std::string& typeDesc,
245  CmdLineInterface& parser,
246  Visitor* v = NULL );
247 
248  /**
249  * Constructor.
250  * \param flag - The one character flag that identifies this
251  * argument on the command line.
252  * \param name - A one word name for the argument. Can be
253  * used as a long flag on the command line.
254  * \param desc - A description of what the argument is for or
255  * does.
256  * \param req - Whether the argument is required on the command
257  * line.
258  * \param constraint - A pointer to a Constraint object used
259  * to constrain this Arg.
260  * \param v - An optional visitor. You probably should not
261  * use this unless you have a very good reason.
262  */
263  MultiArg( const std::string& flag,
264  const std::string& name,
265  const std::string& desc,
266  bool req,
267  Constraint<T>* constraint,
268  Visitor* v = NULL );
269 
270  /**
271  * Constructor.
272  * \param flag - The one character flag that identifies this
273  * argument on the command line.
274  * \param name - A one word name for the argument. Can be
275  * used as a long flag on the command line.
276  * \param desc - A description of what the argument is for or
277  * does.
278  * \param req - Whether the argument is required on the command
279  * line.
280  * \param constraint - A pointer to a Constraint object used
281  * to constrain this Arg.
282  * \param parser - A CmdLine parser object to add this Arg to
283  * \param v - An optional visitor. You probably should not
284  * use this unless you have a very good reason.
285  */
286  MultiArg( const std::string& flag,
287  const std::string& name,
288  const std::string& desc,
289  bool req,
290  Constraint<T>* constraint,
291  CmdLineInterface& parser,
292  Visitor* v = NULL );
293 
294  /**
295  * Handles the processing of the argument.
296  * This re-implements the Arg version of this method to set the
297  * _value of the argument appropriately. It knows the difference
298  * between labeled and unlabeled.
299  * \param i - Pointer the the current argument in the list.
300  * \param args - Mutable list of strings. Passed from main().
301  */
302  virtual bool processArg(int* i, std::vector<std::string>& args);
303 
304  /**
305  * Returns a vector of type T containing the values parsed from
306  * the command line.
307  */
308  const std::vector<T>& getValue();
309 
310  /**
311  * Returns the a short id string. Used in the usage.
312  * \param val - value to be used.
313  */
314  virtual std::string shortID(const std::string& val="val") const;
315 
316  /**
317  * Returns the a long id string. Used in the usage.
318  * \param val - value to be used.
319  */
320  virtual std::string longID(const std::string& val="val") const;
321 
322  /**
323  * Once we've matched the first value, then the arg is no longer
324  * required.
325  */
326  virtual bool isRequired() const;
327 
328  virtual bool allowMore();
329 
330 };
331 
332 template<class T>
333 MultiArg<T>::MultiArg(const std::string& flag,
334  const std::string& name,
335  const std::string& desc,
336  bool req,
337  const std::string& typeDesc,
338  Visitor* v)
339 : Arg( flag, name, desc, req, true, v ),
340  _typeDesc( typeDesc ),
341  _constraint( NULL ),
342  _allowMore(false)
343 {
344  _acceptsMultipleValues = true;
345 }
346 
347 template<class T>
348 MultiArg<T>::MultiArg(const std::string& flag,
349  const std::string& name,
350  const std::string& desc,
351  bool req,
352  const std::string& typeDesc,
353  CmdLineInterface& parser,
354  Visitor* v)
355 : Arg( flag, name, desc, req, true, v ),
356  _typeDesc( typeDesc ),
357  _constraint( NULL ),
358  _allowMore(false)
359 {
360  parser.add( this );
361  _acceptsMultipleValues = true;
362 }
363 
364 /**
365  *
366  */
367 template<class T>
368 MultiArg<T>::MultiArg(const std::string& flag,
369  const std::string& name,
370  const std::string& desc,
371  bool req,
372  Constraint<T>* constraint,
373  Visitor* v)
374 : Arg( flag, name, desc, req, true, v ),
375  _typeDesc( constraint->shortID() ),
376  _constraint( constraint ),
377  _allowMore(false)
378 {
379  _acceptsMultipleValues = true;
380 }
381 
382 template<class T>
383 MultiArg<T>::MultiArg(const std::string& flag,
384  const std::string& name,
385  const std::string& desc,
386  bool req,
387  Constraint<T>* constraint,
388  CmdLineInterface& parser,
389  Visitor* v)
390 : Arg( flag, name, desc, req, true, v ),
391  _typeDesc( constraint->shortID() ),
392  _constraint( constraint ),
393  _allowMore(false)
394 {
395  parser.add( this );
396  _acceptsMultipleValues = true;
397 }
398 
399 template<class T>
400 const std::vector<T>& MultiArg<T>::getValue() { return _values; }
401 
402 template<class T>
403 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
404 {
405  if ( _ignoreable && Arg::ignoreRest() )
406  return false;
407 
408  if ( _hasBlanks( args[*i] ) )
409  return false;
410 
411  std::string flag = args[*i];
412  std::string value = "";
413 
414  trimFlag( flag, value );
415 
416  if ( argMatches( flag ) )
417  {
418  if ( Arg::delimiter() != ' ' && value == "" )
419  throw( ArgParseException(
420  "Couldn't find delimiter for this argument!",
421  toString() ) );
422 
423  // always take the first one, regardless of start string
424  if ( value == "" )
425  {
426  (*i)++;
427  if ( static_cast<unsigned int>(*i) < args.size() )
428  _extractValue( args[*i] );
429  else
430  throw( ArgParseException("Missing a value for this argument!",
431  toString() ) );
432  }
433  else
434  _extractValue( value );
435 
436  /*
437  // continuing taking the args until we hit one with a start string
438  while ( (unsigned int)(*i)+1 < args.size() &&
439  args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
440  args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
441  _extractValue( args[++(*i)] );
442  */
443 
444  _alreadySet = true;
445  _checkWithVisitor();
446 
447  return true;
448  }
449  else
450  return false;
451 }
452 
453 /**
454  *
455  */
456 template<class T>
457 std::string MultiArg<T>::shortID(const std::string& val) const
458 {
459  std::string id = Arg::shortID(_typeDesc) + " ... ";
460 
461  return id;
462 }
463 
464 /**
465  *
466  */
467 template<class T>
468 std::string MultiArg<T>::longID(const std::string& val) const
469 {
470  std::string id = Arg::longID(_typeDesc) + " (accepted multiple times)";
471 
472  return id;
473 }
474 
475 /**
476  * Once we've matched the first value, then the arg is no longer
477  * required.
478  */
479 template<class T>
481 {
482  if ( _required )
483  {
484  if ( _values.size() > 1 )
485  return false;
486  else
487  return true;
488  }
489  else
490  return false;
491 
492 }
493 
494 template<class T>
495 void MultiArg<T>::_extractValue( const std::string& val )
496 {
498 
499  int err = ve.extractValue(val);
500 
502  throw( ArgParseException("Couldn't read argument value "
503  "from string '" + val + "'", toString() ) );
504 
506  throw( ArgParseException("More than one valid value "
507  "parsed from string '" + val + "'",
508  toString() ) );
509  if ( _constraint != NULL )
510  if ( ! _constraint->check( _values.back() ) )
511  throw( CmdLineParseException( "Value '" + val +
512  "' does not meet constraint: " +
513  _constraint->description(),
514  toString() ) );
515 }
516 
517 template<class T>
519 {
520  bool am = _allowMore;
521  _allowMore = true;
522  return am;
523 }
524 
525 } // namespace TCLAP
526 
527 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013