tclap  1.2.0
Arg.h
Go to the documentation of this file.
1 // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
2 
3 /******************************************************************************
4  *
5  * file: Arg.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 
25 #ifndef TCLAP_ARGUMENT_H
26 #define TCLAP_ARGUMENT_H
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #else
31 #define HAVE_SSTREAM
32 #endif
33 
34 #include <string>
35 #include <vector>
36 #include <list>
37 #include <iostream>
38 #include <iomanip>
39 #include <cstdio>
40 
41 #if defined(HAVE_SSTREAM)
42 #include <sstream>
44 #elif defined(HAVE_STRSTREAM)
45 #include <strstream>
46 typedef std::istrstream istringstream;
47 #else
48 #error "Need a stringstream (sstream or strstream) to compile!"
49 #endif
50 
51 #include <tclap/ArgException.h>
52 #include <tclap/Visitor.h>
53 #include <tclap/CmdLineInterface.h>
54 #include <tclap/ArgTraits.h>
55 #include <tclap/StandardTraits.h>
56 
57 namespace TCLAP {
58 
64 class Arg
65 {
66  private:
67 
71  static bool& ignoreRestRef() { static bool ign = false; return ign; }
72 
77  static char& delimiterRef() { static char delim = ' '; return delim; }
78 
79  protected:
80 
89  std::string _flag;
90 
98  std::string _name;
99 
103  std::string _description;
104 
108  bool _required;
109 
114  std::string _requireLabel;
115 
122 
129 
137 
142 
147  bool _xorSet;
148 
150 
154  void _checkWithVisitor() const;
155 
169  Arg( const std::string& flag,
170  const std::string& name,
171  const std::string& desc,
172  bool req,
173  bool valreq,
174  Visitor* v = NULL );
175 
176  public:
180  virtual ~Arg();
181 
186  virtual void addToList( std::list<Arg*>& argList ) const;
187 
191  static void beginIgnoring() { ignoreRestRef() = true; }
192 
196  static bool ignoreRest() { return ignoreRestRef(); }
197 
202  static char delimiter() { return delimiterRef(); }
203 
208  static char blankChar() { return (char)7; }
209 
213  static char flagStartChar() { return '-'; }
214 
219  static const std::string flagStartString() { return "-"; }
220 
225  static const std::string nameStartString() { return "--"; }
226 
230  static const std::string ignoreNameString() { return "ignore_rest"; }
231 
236  static void setDelimiter( char c ) { delimiterRef() = c; }
237 
245  virtual bool processArg(int *i, std::vector<std::string>& args) = 0;
246 
252  virtual bool operator==(const Arg& a) const;
253 
257  const std::string& getFlag() const;
258 
262  const std::string& getName() const;
263 
267  std::string getDescription() const;
268 
272  virtual bool isRequired() const;
273 
278  void forceRequired();
279 
284  void xorSet();
285 
289  bool isValueRequired() const;
290 
295  bool isSet() const;
296 
300  bool isIgnoreable() const;
301 
310  virtual bool argMatches( const std::string& s ) const;
311 
316  virtual std::string toString() const;
317 
322  virtual std::string shortID( const std::string& valueId = "val" ) const;
323 
328  virtual std::string longID( const std::string& valueId = "val" ) const;
329 
337  virtual void trimFlag( std::string& flag, std::string& value ) const;
338 
345  bool _hasBlanks( const std::string& s ) const;
346 
352  void setRequireLabel( const std::string& s );
353 
358  virtual bool allowMore();
359 
364  virtual bool acceptsMultipleValues();
365 
370  virtual void reset();
371 };
372 
376 typedef std::list<Arg*>::iterator ArgListIterator;
377 
381 typedef std::vector<Arg*>::iterator ArgVectorIterator;
382 
386 typedef std::list<Visitor*>::iterator VisitorListIterator;
387 
388 /*
389  * Extract a value of type T from it's string representation contained
390  * in strVal. The ValueLike parameter used to select the correct
391  * specialization of ExtractValue depending on the value traits of T.
392  * ValueLike traits use operator>> to assign the value from strVal.
393  */
394 template<typename T> void
395 ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
396 {
397  static_cast<void>(vl); // Avoid warning about unused vl
398  std::istringstream is(strVal);
399 
400  int valuesRead = 0;
401  while ( is.good() ) {
402  if ( is.peek() != EOF )
403 #ifdef TCLAP_SETBASE_ZERO
404  is >> std::setbase(0) >> destVal;
405 #else
406  is >> destVal;
407 #endif
408  else
409  break;
410 
411  valuesRead++;
412  }
413 
414  if ( is.fail() )
415  throw( ArgParseException("Couldn't read argument value "
416  "from string '" + strVal + "'"));
417 
418 
419  if ( valuesRead > 1 )
420  throw( ArgParseException("More than one valid value parsed from "
421  "string '" + strVal + "'"));
422 
423 }
424 
425 /*
426  * Extract a value of type T from it's string representation contained
427  * in strVal. The ValueLike parameter used to select the correct
428  * specialization of ExtractValue depending on the value traits of T.
429  * StringLike uses assignment (operator=) to assign from strVal.
430  */
431 template<typename T> void
432 ExtractValue(T &destVal, const std::string& strVal, StringLike sl)
433 {
434  static_cast<void>(sl); // Avoid warning about unused sl
435  SetString(destVal, strVal);
436 }
437 
439 //BEGIN Arg.cpp
441 
442 inline Arg::Arg(const std::string& flag,
443  const std::string& name,
444  const std::string& desc,
445  bool req,
446  bool valreq,
447  Visitor* v) :
448  _flag(flag),
449  _name(name),
450  _description(desc),
451  _required(req),
452  _requireLabel("required"),
453  _valueRequired(valreq),
454  _alreadySet(false),
455  _visitor( v ),
456  _ignoreable(true),
457  _xorSet(false),
458  _acceptsMultipleValues(false)
459 {
460  if ( _flag.length() > 1 )
462  "Argument flag can only be one character long", toString() ) );
463 
464  if ( _name != ignoreNameString() &&
465  ( _flag == Arg::flagStartString() ||
467  _flag == " " ) )
468  throw(SpecificationException("Argument flag cannot be either '" +
469  Arg::flagStartString() + "' or '" +
470  Arg::nameStartString() + "' or a space.",
471  toString() ) );
472 
473  if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
474  ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
475  ( _name.find( " ", 0 ) != std::string::npos ) )
476  throw(SpecificationException("Argument name begin with either '" +
477  Arg::flagStartString() + "' or '" +
478  Arg::nameStartString() + "' or space.",
479  toString() ) );
480 
481 }
482 
483 inline Arg::~Arg() { }
484 
485 inline std::string Arg::shortID( const std::string& valueId ) const
486 {
487  std::string id = "";
488 
489  if ( _flag != "" )
490  id = Arg::flagStartString() + _flag;
491  else
492  id = Arg::nameStartString() + _name;
493 
494  if ( _valueRequired )
495  id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
496 
497  if ( !_required )
498  id = "[" + id + "]";
499 
500  return id;
501 }
502 
503 inline std::string Arg::longID( const std::string& valueId ) const
504 {
505  std::string id = "";
506 
507  if ( _flag != "" )
508  {
509  id += Arg::flagStartString() + _flag;
510 
511  if ( _valueRequired )
512  id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
513 
514  id += ", ";
515  }
516 
517  id += Arg::nameStartString() + _name;
518 
519  if ( _valueRequired )
520  id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
521 
522  return id;
523 
524 }
525 
526 inline bool Arg::operator==(const Arg& a) const
527 {
528  if ( ( _flag != "" && _flag == a._flag ) || _name == a._name)
529  return true;
530  else
531  return false;
532 }
533 
534 inline std::string Arg::getDescription() const
535 {
536  std::string desc = "";
537  if ( _required )
538  desc = "(" + _requireLabel + ") ";
539 
540 // if ( _valueRequired )
541 // desc += "(value required) ";
542 
543  desc += _description;
544  return desc;
545 }
546 
547 inline const std::string& Arg::getFlag() const { return _flag; }
548 
549 inline const std::string& Arg::getName() const { return _name; }
550 
551 inline bool Arg::isRequired() const { return _required; }
552 
553 inline bool Arg::isValueRequired() const { return _valueRequired; }
554 
555 inline bool Arg::isSet() const
556 {
557  if ( _alreadySet && !_xorSet )
558  return true;
559  else
560  return false;
561 }
562 
563 inline bool Arg::isIgnoreable() const { return _ignoreable; }
564 
565 inline void Arg::setRequireLabel( const std::string& s)
566 {
567  _requireLabel = s;
568 }
569 
570 inline bool Arg::argMatches( const std::string& argFlag ) const
571 {
572  if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) ||
573  argFlag == Arg::nameStartString() + _name )
574  return true;
575  else
576  return false;
577 }
578 
579 inline std::string Arg::toString() const
580 {
581  std::string s = "";
582 
583  if ( _flag != "" )
584  s += Arg::flagStartString() + _flag + " ";
585 
586  s += "(" + Arg::nameStartString() + _name + ")";
587 
588  return s;
589 }
590 
591 inline void Arg::_checkWithVisitor() const
592 {
593  if ( _visitor != NULL )
594  _visitor->visit();
595 }
596 
600 inline void Arg::trimFlag(std::string& flag, std::string& value) const
601 {
602  int stop = 0;
603  for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ )
604  if ( flag[i] == Arg::delimiter() )
605  {
606  stop = i;
607  break;
608  }
609 
610  if ( stop > 1 )
611  {
612  value = flag.substr(stop+1);
613  flag = flag.substr(0,stop);
614  }
615 
616 }
617 
621 inline bool Arg::_hasBlanks( const std::string& s ) const
622 {
623  for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
624  if ( s[i] == Arg::blankChar() )
625  return true;
626 
627  return false;
628 }
629 
630 inline void Arg::forceRequired()
631 {
632  _required = true;
633 }
634 
635 inline void Arg::xorSet()
636 {
637  _alreadySet = true;
638  _xorSet = true;
639 }
640 
644 inline void Arg::addToList( std::list<Arg*>& argList ) const
645 {
646  argList.push_front( const_cast<Arg*>(this) );
647 }
648 
649 inline bool Arg::allowMore()
650 {
651  return false;
652 }
653 
655 {
656  return _acceptsMultipleValues;
657 }
658 
659 inline void Arg::reset()
660 {
661  _xorSet = false;
662  _alreadySet = false;
663 }
664 
666 //END Arg.cpp
668 
669 } //namespace TCLAP
670 
671 #endif
672