Main MRPT website > C++ reference
MRPT logo
CmdLine.h
Go to the documentation of this file.
1 
2 /******************************************************************************
3  *
4  * file: CmdLine.h
5  *
6  * Copyright (c) 2003, Michael E. Smoot .
7  * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
8  * All rights reverved.
9  *
10  * See the file COPYING in the top directory of this distribution for
11  * more information.
12  *
13  * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
14  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19  * DEALINGS IN THE SOFTWARE.
20  *
21  *****************************************************************************/
22 
23 #ifndef TCLAP_CMDLINE_H
24 #define TCLAP_CMDLINE_H
25 
30 
35 
38 
41 
42 #include <string>
43 #include <vector>
44 #include <list>
45 #include <iostream>
46 #include <iomanip>
47 #include <algorithm>
48 
49 namespace TCLAP {
50 
51 /**
52  * The base class that manages the command line definition and passes
53  * along the parsing to the appropriate Arg classes.
54  */
55 class CmdLine : public CmdLineInterface
56 {
57  protected:
58 
59  /**
60  * The list of arguments that will be tested against the
61  * command line.
62  */
63  std::list<Arg*> _argList;
64 
65  /**
66  * The name of the program. Set to argv[0].
67  */
68  std::string _progName;
69 
70  /**
71  * A message used to describe the program. Used in the usage output.
72  */
73  std::string _message;
74 
75  /**
76  * The version to be displayed with the --version switch.
77  */
78  std::string _version;
79 
80  /**
81  * The number of arguments that are required to be present on
82  * the command line. This is set dynamically, based on the
83  * Args added to the CmdLine object.
84  */
86 
87  /**
88  * The character that is used to separate the argument flag/name
89  * from the value. Defaults to ' ' (space).
90  */
91  char _delimiter;
92 
93  /**
94  * The handler that manages xoring lists of args.
95  */
97 
98  /**
99  * A list of Args to be explicitly deleted when the destructor
100  * is called. At the moment, this only includes the three default
101  * Args.
102  */
103  std::list<Arg*> _argDeleteOnExitList;
104 
105  /**
106  * A list of Visitors to be explicitly deleted when the destructor
107  * is called. At the moment, these are the Vistors created for the
108  * default Args.
109  */
110  std::list<Visitor*> _visitorDeleteOnExitList;
111 
112  /**
113  * Object that handles all output for the CmdLine.
114  */
116 
117  /**
118  * Checks whether a name/flag string matches entirely matches
119  * the Arg::blankChar. Used when multiple switches are combined
120  * into a single argument.
121  * \param s - The message to be used in the usage.
122  */
123  bool _emptyCombined(const std::string& s);
124 
125  /**
126  * Perform a delete ptr; operation on ptr when this object is deleted.
127  */
128  void deleteOnExit(Arg* ptr);
129 
130  /**
131  * Perform a delete ptr; operation on ptr when this object is deleted.
132  */
133  void deleteOnExit(Visitor* ptr);
134 
135  private:
136 
137  /**
138  * Encapsulates the code common to the constructors (which is all
139  * of it).
140  */
141  void _constructor();
142 
143  /**
144  * Is set to true when a user sets the output object. We use this so
145  * that we don't delete objects that are created outside of this lib.
146  */
148 
149  /**
150  * Whether or not to automatically create help and version switches.
151  */
153 
154  public:
155 
156  /**
157  * Command line constructor. Defines how the arguments will be
158  * parsed.
159  * \param message - The message to be used in the usage
160  * output.
161  * \param delimiter - The character that is used to separate
162  * the argument flag/name from the value. Defaults to ' ' (space).
163  * \param version - The version number to be used in the
164  * --version switch.
165  * \param helpAndVersion - Whether or not to create the Help and
166  * Version switches. Defaults to true.
167  */
168  CmdLine(const std::string& message,
169  const char delimiter = ' ',
170  const std::string& version = "none",
171  bool helpAndVersion = true);
172 
173  /**
174  * Deletes any resources allocated by a CmdLine object.
175  */
176  virtual ~CmdLine();
177 
178  /**
179  * Adds an argument to the list of arguments to be parsed.
180  * \param a - Argument to be added.
181  */
182  void add( Arg& a );
183 
184  /**
185  * An alternative add. Functionally identical.
186  * \param a - Argument to be added.
187  */
188  void add( Arg* a );
189 
190  /**
191  * Add two Args that will be xor'd. If this method is used, add does
192  * not need to be called.
193  * \param a - Argument to be added and xor'd.
194  * \param b - Argument to be added and xor'd.
195  */
196  void xorAdd( Arg& a, Arg& b );
197 
198  /**
199  * Add a list of Args that will be xor'd. If this method is used,
200  * add does not need to be called.
201  * \param xors - List of Args to be added and xor'd.
202  */
203  void xorAdd( std::vector<Arg*>& xors );
204 
205  /**
206  * Parses the command line.
207  * \param argc - Number of arguments.
208  * \param argv - Array of arguments.
209  * \return (Added by JLBC for MRPT): Return false if the program should exit (error in args, it was --help, etc...)
210  */
211  bool parse(int argc, char** argv);
212 
213  /**
214  *
215  */
217 
218  /**
219  *
220  */
221  void setOutput(CmdLineOutput* co);
222 
223  /**
224  *
225  */
226  std::string& getVersion();
227 
228  /**
229  *
230  */
231  std::string& getProgramName();
232 
233  /**
234  *
235  */
236  std::list<Arg*>& getArgList();
237 
238  /**
239  *
240  */
242 
243  /**
244  *
245  */
246  char getDelimiter();
247 
248  /**
249  *
250  */
251  std::string& getMessage();
252 
253  /**
254  *
255  */
256  bool hasHelpAndVersion();
257 };
258 
259 
260 ///////////////////////////////////////////////////////////////////////////////
261 //Begin CmdLine.cpp
262 ///////////////////////////////////////////////////////////////////////////////
263 
264 inline CmdLine::CmdLine(const std::string& m,
265  char delim,
266  const std::string& v,
267  bool help )
268 : _progName("not_set_yet"),
269  _message(m),
270  _version(v),
271  _numRequired(0),
272  _delimiter(delim),
273  _userSetOutput(false),
274  _helpAndVersion(help)
275 {
276  _constructor();
277 }
278 
280 {
281  ArgListIterator argIter;
282  VisitorListIterator visIter;
283 
284  for( argIter = _argDeleteOnExitList.begin();
285  argIter != _argDeleteOnExitList.end();
286  ++argIter)
287  delete *argIter;
288 
289  for( visIter = _visitorDeleteOnExitList.begin();
290  visIter != _visitorDeleteOnExitList.end();
291  ++visIter)
292  delete *visIter;
293 
294  if ( !_userSetOutput )
295  delete _output;
296 }
297 
299 {
300  _output = new StdOutput;
301 
303 
304  Visitor* v;
305 
306  if ( _helpAndVersion )
307  {
308  v = new HelpVisitor( this, &_output );
309  SwitchArg* help = new SwitchArg("h","help",
310  "Displays usage information and exits.",
311  false, v);
312  add( help );
313  deleteOnExit(help);
314  deleteOnExit(v);
315 
316  v = new VersionVisitor( this, &_output );
317  SwitchArg* vers = new SwitchArg("","version",
318  "Displays version information and exits.",
319  false, v);
320  add( vers );
321  deleteOnExit(vers);
322  deleteOnExit(v);
323  }
324 
325  v = new IgnoreRestVisitor();
326  SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
328  "Ignores the rest of the labeled arguments following this flag.",
329  false, v);
330  add( ignore );
331  deleteOnExit(ignore);
332  deleteOnExit(v);
333 }
334 
335 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
336 {
337  _xorHandler.add( ors );
338 
339  for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
340  {
341  (*it)->forceRequired();
342  (*it)->setRequireLabel( "OR required" );
343 
344  add( *it );
345  }
346 }
347 
348 inline void CmdLine::xorAdd( Arg& a, Arg& b )
349 {
350  std::vector<Arg*> ors;
351  ors.push_back( &a );
352  ors.push_back( &b );
353  xorAdd( ors );
354 }
355 
356 inline void CmdLine::add( Arg& a )
357 {
358  add( &a );
359 }
360 
361 inline void CmdLine::add( Arg* a )
362 {
363  for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
364  if ( *a == *(*it) )
365  throw( SpecificationException(
366  "Argument with same flag/name already exists!",
367  a->longID() ) );
368 
369  a->addToList( _argList );
370 
371  if ( a->isRequired() )
372  _numRequired++;
373 }
374 
375 inline bool CmdLine::parse(int argc, char** argv)
376 {
377  try {
378 
379  _progName = argv[0];
380 
381  // this step is necessary so that we have easy access to mutable strings.
382  std::vector<std::string> args;
383  for (int i = 1; i < argc; i++)
384  args.push_back(argv[i]);
385 
386  int requiredCount = 0;
387 
388  for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
389  {
390  bool matched = false;
391  for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
392  {
393  if ( (*it)->processArg( &i, args ) )
394  {
395  requiredCount += _xorHandler.check( *it );
396  matched = true;
397  break;
398  }
399  }
400 
401  // checks to see if the argument is an empty combined switch ...
402  // and if so, then we've actually matched it
403  if ( !matched && _emptyCombined( args[i] ) )
404  matched = true;
405 
406  if ( !matched && !Arg::ignoreRest() )
407  throw(CmdLineParseException("Couldn't find match for argument",
408  args[i]));
409  }
410 
411  if ( requiredCount < _numRequired )
412  throw(CmdLineParseException("One or more required arguments missing!"));
413 
414  if ( requiredCount > _numRequired )
415  throw(CmdLineParseException("Too many arguments!"));
416 
417  return true; // Ok
418 
419  }
420  catch ( ActionDoneException e )
421  {
422  return false; // Done
423  }
424  catch ( ArgException e )
425  {
426  _output->failure(*this,e);
427  return false; // Error
428  }
429 }
430 
431 inline bool CmdLine::_emptyCombined(const std::string& s)
432 {
433  if ( s[0] != Arg::flagStartChar() )
434  return false;
435 
436  for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
437  if ( s[i] != Arg::blankChar() )
438  return false;
439 
440  return true;
441 }
442 
443 inline void CmdLine::deleteOnExit(Arg* ptr)
444 {
445  _argDeleteOnExitList.push_back(ptr);
446 }
447 
449 {
450  _visitorDeleteOnExitList.push_back(ptr);
451 }
452 
454 {
455  return _output;
456 }
457 
459 {
460  _userSetOutput = true;
461  _output = co;
462 }
463 
464 inline std::string& CmdLine::getVersion()
465 {
466  return _version;
467 }
468 
469 inline std::string& CmdLine::getProgramName()
470 {
471  return _progName;
472 }
473 
474 inline std::list<Arg*>& CmdLine::getArgList()
475 {
476  return _argList;
477 }
478 
480 {
481  return _xorHandler;
482 }
483 
485 {
486  return _delimiter;
487 }
488 
489 inline std::string& CmdLine::getMessage()
490 {
491  return _message;
492 }
493 
495 {
496  return _helpAndVersion;
497 }
498 
499 ///////////////////////////////////////////////////////////////////////////////
500 //End CmdLine.cpp
501 ///////////////////////////////////////////////////////////////////////////////
502 
503 
504 
505 } //namespace TCLAP
506 #endif



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