tclap  1.2.0
CmdLine.h
Go to the documentation of this file.
1 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
2 
3 /******************************************************************************
4  *
5  * file: CmdLine.h
6  *
7  * Copyright (c) 2003, Michael E. Smoot .
8  * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
9  * All rights reverved.
10  *
11  * See the file COPYING in the top directory of this distribution for
12  * more information.
13  *
14  * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  *
22  *****************************************************************************/
23 
24 #ifndef TCLAP_CMDLINE_H
25 #define TCLAP_CMDLINE_H
26 
27 #include <tclap/SwitchArg.h>
28 #include <tclap/MultiSwitchArg.h>
31 
32 #include <tclap/XorHandler.h>
33 #include <tclap/HelpVisitor.h>
34 #include <tclap/VersionVisitor.h>
36 
37 #include <tclap/CmdLineOutput.h>
38 #include <tclap/StdOutput.h>
39 
40 #include <tclap/Constraint.h>
41 #include <tclap/ValuesConstraint.h>
42 
43 #include <string>
44 #include <vector>
45 #include <list>
46 #include <iostream>
47 #include <iomanip>
48 #include <algorithm>
49 #include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
50 
51 namespace TCLAP {
52 
53 template<typename T> void DelPtr(T ptr)
54 {
55  delete ptr;
56 }
57 
58 template<typename C> void ClearContainer(C &c)
59 {
60  typedef typename C::value_type value_type;
61  std::for_each(c.begin(), c.end(), DelPtr<value_type>);
62  c.clear();
63 }
64 
65 
70 class CmdLine : public CmdLineInterface
71 {
72  protected:
73 
78  std::list<Arg*> _argList;
79 
83  std::string _progName;
84 
88  std::string _message;
89 
93  std::string _version;
94 
101 
107 
112 
118  std::list<Arg*> _argDeleteOnExitList;
119 
125  std::list<Visitor*> _visitorDeleteOnExitList;
126 
131 
136 
140  void missingArgsException();
141 
148  bool _emptyCombined(const std::string& s);
149 
153  void deleteOnExit(Arg* ptr);
154 
158  void deleteOnExit(Visitor* ptr);
159 
160 private:
161 
166  void _constructor();
167 
168 
173  bool _userSetOutput;
174 
178  bool _helpAndVersion;
179 
180  public:
181 
194  CmdLine(const std::string& message,
195  const char delimiter = ' ',
196  const std::string& version = "none",
197  bool helpAndVersion = true);
198 
202  virtual ~CmdLine();
203 
208  void add( Arg& a );
209 
214  void add( Arg* a );
215 
222  void xorAdd( Arg& a, Arg& b );
223 
229  void xorAdd( std::vector<Arg*>& xors );
230 
236  void parse(int argc, const char * const * argv);
237 
243  void parse(std::vector<std::string>& args);
244 
249 
253  void setOutput(CmdLineOutput* co);
254 
258  std::string& getVersion();
259 
263  std::string& getProgramName();
264 
268  std::list<Arg*>& getArgList();
269 
274 
278  char getDelimiter();
279 
283  std::string& getMessage();
284 
288  bool hasHelpAndVersion();
289 
295  void setExceptionHandling(const bool state);
296 
303  bool getExceptionHandling() const;
304 
308  void reset();
309 
310 };
311 
312 
314 //Begin CmdLine.cpp
316 
317 inline CmdLine::CmdLine(const std::string& m,
318  char delim,
319  const std::string& v,
320  bool help )
321 : _progName("not_set_yet"),
322  _message(m),
323  _version(v),
324  _numRequired(0),
325  _delimiter(delim),
326  _handleExceptions(true),
327  _userSetOutput(false),
328  _helpAndVersion(help)
329 {
330  _constructor();
331 }
332 
334 {
337 
338  if ( !_userSetOutput ) {
339  delete _output;
340  _output = 0;
341  }
342 }
343 
344 inline void CmdLine::_constructor()
345 {
346  _output = new StdOutput;
347 
349 
350  Visitor* v;
351 
352  if ( _helpAndVersion )
353  {
354  v = new HelpVisitor( this, &_output );
355  SwitchArg* help = new SwitchArg("h","help",
356  "Displays usage information and exits.",
357  false, v);
358  add( help );
359  deleteOnExit(help);
360  deleteOnExit(v);
361 
362  v = new VersionVisitor( this, &_output );
363  SwitchArg* vers = new SwitchArg("","version",
364  "Displays version information and exits.",
365  false, v);
366  add( vers );
367  deleteOnExit(vers);
368  deleteOnExit(v);
369  }
370 
371  v = new IgnoreRestVisitor();
372  SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
374  "Ignores the rest of the labeled arguments following this flag.",
375  false, v);
376  add( ignore );
377  deleteOnExit(ignore);
378  deleteOnExit(v);
379 }
380 
381 inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
382 {
383  _xorHandler.add( ors );
384 
385  for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
386  {
387  (*it)->forceRequired();
388  (*it)->setRequireLabel( "OR required" );
389 
390  add( *it );
391  }
392 }
393 
394 inline void CmdLine::xorAdd( Arg& a, Arg& b )
395 {
396  std::vector<Arg*> ors;
397  ors.push_back( &a );
398  ors.push_back( &b );
399  xorAdd( ors );
400 }
401 
402 inline void CmdLine::add( Arg& a )
403 {
404  add( &a );
405 }
406 
407 inline void CmdLine::add( Arg* a )
408 {
409  for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
410  if ( *a == *(*it) )
411  throw( SpecificationException(
412  "Argument with same flag/name already exists!",
413  a->longID() ) );
414 
415  a->addToList( _argList );
416 
417  if ( a->isRequired() )
418  _numRequired++;
419 }
420 
421 
422 inline void CmdLine::parse(int argc, const char * const * argv)
423 {
424  // this step is necessary so that we have easy access to
425  // mutable strings.
426  std::vector<std::string> args;
427  for (int i = 0; i < argc; i++)
428  args.push_back(argv[i]);
429 
430  parse(args);
431 }
432 
433 inline void CmdLine::parse(std::vector<std::string>& args)
434 {
435  bool shouldExit = false;
436  int estat = 0;
437 
438  try {
439  _progName = args.front();
440  args.erase(args.begin());
441 
442  int requiredCount = 0;
443 
444  for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
445  bool matched = false;
446  for (ArgListIterator it = _argList.begin();
447  it != _argList.end(); it++) {
448  if ( (*it)->processArg( &i, args ) )
449  {
450  requiredCount += _xorHandler.check( *it );
451  matched = true;
452  break;
453  }
454  }
455 
456  // checks to see if the argument is an empty combined
457  // switch and if so, then we've actually matched it
458  if ( !matched && _emptyCombined( args[i] ) )
459  matched = true;
460 
461  if ( !matched && !Arg::ignoreRest() )
462  throw(CmdLineParseException("Couldn't find match "
463  "for argument",
464  args[i]));
465  }
466 
467  if ( requiredCount < _numRequired )
469 
470  if ( requiredCount > _numRequired )
471  throw(CmdLineParseException("Too many arguments!"));
472 
473  } catch ( ArgException& e ) {
474  // If we're not handling the exceptions, rethrow.
475  if ( !_handleExceptions) {
476  throw;
477  }
478 
479  try {
480  _output->failure(*this,e);
481  } catch ( ExitException &ee ) {
482  estat = ee.getExitStatus();
483  shouldExit = true;
484  }
485  } catch (ExitException &ee) {
486  // If we're not handling the exceptions, rethrow.
487  if ( !_handleExceptions) {
488  throw;
489  }
490 
491  estat = ee.getExitStatus();
492  shouldExit = true;
493  }
494 
495  if (shouldExit)
496  exit(estat);
497 }
498 
499 inline bool CmdLine::_emptyCombined(const std::string& s)
500 {
501  if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
502  return false;
503 
504  for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
505  if ( s[i] != Arg::blankChar() )
506  return false;
507 
508  return true;
509 }
510 
512 {
513  int count = 0;
514 
515  std::string missingArgList;
516  for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
517  {
518  if ( (*it)->isRequired() && !(*it)->isSet() )
519  {
520  missingArgList += (*it)->getName();
521  missingArgList += ", ";
522  count++;
523  }
524  }
525  missingArgList = missingArgList.substr(0,missingArgList.length()-2);
526 
527  std::string msg;
528  if ( count > 1 )
529  msg = "Required arguments missing: ";
530  else
531  msg = "Required argument missing: ";
532 
533  msg += missingArgList;
534 
535  throw(CmdLineParseException(msg));
536 }
537 
538 inline void CmdLine::deleteOnExit(Arg* ptr)
539 {
540  _argDeleteOnExitList.push_back(ptr);
541 }
542 
544 {
545  _visitorDeleteOnExitList.push_back(ptr);
546 }
547 
549 {
550  return _output;
551 }
552 
554 {
555  _userSetOutput = true;
556  _output = co;
557 }
558 
559 inline std::string& CmdLine::getVersion()
560 {
561  return _version;
562 }
563 
564 inline std::string& CmdLine::getProgramName()
565 {
566  return _progName;
567 }
568 
569 inline std::list<Arg*>& CmdLine::getArgList()
570 {
571  return _argList;
572 }
573 
575 {
576  return _xorHandler;
577 }
578 
580 {
581  return _delimiter;
582 }
583 
584 inline std::string& CmdLine::getMessage()
585 {
586  return _message;
587 }
588 
590 {
591  return _helpAndVersion;
592 }
593 
594 inline void CmdLine::setExceptionHandling(const bool state)
595 {
596  _handleExceptions = state;
597 }
598 
599 inline bool CmdLine::getExceptionHandling() const
600 {
601  return _handleExceptions;
602 }
603 
604 inline void CmdLine::reset()
605 {
606  for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
607  {
608  (*it)->reset();
609  }
610 
611  _progName.clear();
612 }
613 
615 //End CmdLine.cpp
617 
618 
619 
620 } //namespace TCLAP
621 #endif