Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

693 rader
17 KiB

  1. // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
  2. /******************************************************************************
  3. *
  4. * file: Arg.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. #ifndef TCLAP_ARGUMENT_H
  23. #define TCLAP_ARGUMENT_H
  24. #ifdef HAVE_CONFIG_H
  25. #include <config.h>
  26. #else
  27. #define HAVE_SSTREAM
  28. #endif
  29. #include <string>
  30. #include <vector>
  31. #include <list>
  32. #include <iostream>
  33. #include <iomanip>
  34. #include <cstdio>
  35. #if defined(HAVE_SSTREAM)
  36. #include <sstream>
  37. typedef std::istringstream istringstream;
  38. #elif defined(HAVE_STRSTREAM)
  39. #include <strstream>
  40. typedef std::istrstream istringstream;
  41. #else
  42. #error "Need a stringstream (sstream or strstream) to compile!"
  43. #endif
  44. #include "ArgException.h"
  45. #include "Visitor.h"
  46. #include "CmdLineInterface.h"
  47. #include "ArgTraits.h"
  48. #include "StandardTraits.h"
  49. namespace TCLAP {
  50. /**
  51. * A virtual base class that defines the essential data for all arguments.
  52. * This class, or one of its existing children, must be subclassed to do
  53. * anything.
  54. */
  55. class Arg
  56. {
  57. private:
  58. /**
  59. * Prevent accidental copying.
  60. */
  61. Arg(const Arg& rhs);
  62. /**
  63. * Prevent accidental copying.
  64. */
  65. Arg& operator=(const Arg& rhs);
  66. /**
  67. * Indicates whether the rest of the arguments should be ignored.
  68. */
  69. static bool& ignoreRestRef() { static bool ign = false; return ign; }
  70. /**
  71. * The delimiter that separates an argument flag/name from the
  72. * value.
  73. */
  74. static char& delimiterRef() { static char delim = ' '; return delim; }
  75. protected:
  76. /**
  77. * The single char flag used to identify the argument.
  78. * This value (preceded by a dash {-}), can be used to identify
  79. * an argument on the command line. The _flag can be blank,
  80. * in fact this is how unlabeled args work. Unlabeled args must
  81. * override appropriate functions to get correct handling. Note
  82. * that the _flag does NOT include the dash as part of the flag.
  83. */
  84. std::string _flag;
  85. /**
  86. * A single work namd indentifying the argument.
  87. * This value (preceded by two dashed {--}) can also be used
  88. * to identify an argument on the command line. Note that the
  89. * _name does NOT include the two dashes as part of the _name. The
  90. * _name cannot be blank.
  91. */
  92. std::string _name;
  93. /**
  94. * Description of the argument.
  95. */
  96. std::string _description;
  97. /**
  98. * Indicating whether the argument is required.
  99. */
  100. bool _required;
  101. /**
  102. * Label to be used in usage description. Normally set to
  103. * "required", but can be changed when necessary.
  104. */
  105. std::string _requireLabel;
  106. /**
  107. * Indicates whether a value is required for the argument.
  108. * Note that the value may be required but the argument/value
  109. * combination may not be, as specified by _required.
  110. */
  111. bool _valueRequired;
  112. /**
  113. * Indicates whether the argument has been set.
  114. * Indicates that a value on the command line has matched the
  115. * name/flag of this argument and the values have been set accordingly.
  116. */
  117. bool _alreadySet;
  118. /**
  119. * A pointer to a vistitor object.
  120. * The visitor allows special handling to occur as soon as the
  121. * argument is matched. This defaults to NULL and should not
  122. * be used unless absolutely necessary.
  123. */
  124. Visitor* _visitor;
  125. /**
  126. * Whether this argument can be ignored, if desired.
  127. */
  128. bool _ignoreable;
  129. /**
  130. * Indicates that the arg was set as part of an XOR and not on the
  131. * command line.
  132. */
  133. bool _xorSet;
  134. bool _acceptsMultipleValues;
  135. /**
  136. * Performs the special handling described by the Vistitor.
  137. */
  138. void _checkWithVisitor() const;
  139. /**
  140. * Primary constructor. YOU (yes you) should NEVER construct an Arg
  141. * directly, this is a base class that is extended by various children
  142. * that are meant to be used. Use SwitchArg, ValueArg, MultiArg,
  143. * UnlabeledValueArg, or UnlabeledMultiArg instead.
  144. *
  145. * \param flag - The flag identifying the argument.
  146. * \param name - The name identifying the argument.
  147. * \param desc - The description of the argument, used in the usage.
  148. * \param req - Whether the argument is required.
  149. * \param valreq - Whether the a value is required for the argument.
  150. * \param v - The visitor checked by the argument. Defaults to NULL.
  151. */
  152. Arg( const std::string& flag,
  153. const std::string& name,
  154. const std::string& desc,
  155. bool req,
  156. bool valreq,
  157. Visitor* v = NULL );
  158. public:
  159. /**
  160. * Destructor.
  161. */
  162. virtual ~Arg();
  163. /**
  164. * Adds this to the specified list of Args.
  165. * \param argList - The list to add this to.
  166. */
  167. virtual void addToList( std::list<Arg*>& argList ) const;
  168. /**
  169. * Begin ignoring arguments since the "--" argument was specified.
  170. */
  171. static void beginIgnoring() { ignoreRestRef() = true; }
  172. /**
  173. * Whether to ignore the rest.
  174. */
  175. static bool ignoreRest() { return ignoreRestRef(); }
  176. /**
  177. * The delimiter that separates an argument flag/name from the
  178. * value.
  179. */
  180. static char delimiter() { return delimiterRef(); }
  181. /**
  182. * The char used as a place holder when SwitchArgs are combined.
  183. * Currently set to the bell char (ASCII 7).
  184. */
  185. static char blankChar() { return (char)7; }
  186. /**
  187. * The char that indicates the beginning of a flag. Defaults to '-', but
  188. * clients can define TCLAP_FLAGSTARTCHAR to override.
  189. */
  190. #ifndef TCLAP_FLAGSTARTCHAR
  191. #define TCLAP_FLAGSTARTCHAR '-'
  192. #endif
  193. static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; }
  194. /**
  195. * The sting that indicates the beginning of a flag. Defaults to "-", but
  196. * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same
  197. * as TCLAP_FLAGSTARTCHAR.
  198. */
  199. #ifndef TCLAP_FLAGSTARTSTRING
  200. #define TCLAP_FLAGSTARTSTRING "-"
  201. #endif
  202. static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; }
  203. /**
  204. * The sting that indicates the beginning of a name. Defaults to "--", but
  205. * clients can define TCLAP_NAMESTARTSTRING to override.
  206. */
  207. #ifndef TCLAP_NAMESTARTSTRING
  208. #define TCLAP_NAMESTARTSTRING "--"
  209. #endif
  210. static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; }
  211. /**
  212. * The name used to identify the ignore rest argument.
  213. */
  214. static const std::string ignoreNameString() { return "ignore_rest"; }
  215. /**
  216. * Sets the delimiter for all arguments.
  217. * \param c - The character that delimits flags/names from values.
  218. */
  219. static void setDelimiter( char c ) { delimiterRef() = c; }
  220. /**
  221. * Pure virtual method meant to handle the parsing and value assignment
  222. * of the string on the command line.
  223. * \param i - Pointer the the current argument in the list.
  224. * \param args - Mutable list of strings. What is
  225. * passed in from main.
  226. */
  227. virtual bool processArg(int *i, std::vector<std::string>& args) = 0;
  228. /**
  229. * Operator ==.
  230. * Equality operator. Must be virtual to handle unlabeled args.
  231. * \param a - The Arg to be compared to this.
  232. */
  233. virtual bool operator==(const Arg& a) const;
  234. /**
  235. * Returns the argument flag.
  236. */
  237. const std::string& getFlag() const;
  238. /**
  239. * Returns the argument name.
  240. */
  241. const std::string& getName() const;
  242. /**
  243. * Returns the argument description.
  244. */
  245. std::string getDescription() const;
  246. /**
  247. * Indicates whether the argument is required.
  248. */
  249. virtual bool isRequired() const;
  250. /**
  251. * Sets _required to true. This is used by the XorHandler.
  252. * You really have no reason to ever use it.
  253. */
  254. void forceRequired();
  255. /**
  256. * Sets the _alreadySet value to true. This is used by the XorHandler.
  257. * You really have no reason to ever use it.
  258. */
  259. void xorSet();
  260. /**
  261. * Indicates whether a value must be specified for argument.
  262. */
  263. bool isValueRequired() const;
  264. /**
  265. * Indicates whether the argument has already been set. Only true
  266. * if the arg has been matched on the command line.
  267. */
  268. bool isSet() const;
  269. /**
  270. * Indicates whether the argument can be ignored, if desired.
  271. */
  272. bool isIgnoreable() const;
  273. /**
  274. * A method that tests whether a string matches this argument.
  275. * This is generally called by the processArg() method. This
  276. * method could be re-implemented by a child to change how
  277. * arguments are specified on the command line.
  278. * \param s - The string to be compared to the flag/name to determine
  279. * whether the arg matches.
  280. */
  281. virtual bool argMatches( const std::string& s ) const;
  282. /**
  283. * Returns a simple string representation of the argument.
  284. * Primarily for debugging.
  285. */
  286. virtual std::string toString() const;
  287. /**
  288. * Returns a short ID for the usage.
  289. * \param valueId - The value used in the id.
  290. */
  291. virtual std::string shortID( const std::string& valueId = "val" ) const;
  292. /**
  293. * Returns a long ID for the usage.
  294. * \param valueId - The value used in the id.
  295. */
  296. virtual std::string longID( const std::string& valueId = "val" ) const;
  297. /**
  298. * Trims a value off of the flag.
  299. * \param flag - The string from which the flag and value will be
  300. * trimmed. Contains the flag once the value has been trimmed.
  301. * \param value - Where the value trimmed from the string will
  302. * be stored.
  303. */
  304. virtual void trimFlag( std::string& flag, std::string& value ) const;
  305. /**
  306. * Checks whether a given string has blank chars, indicating that
  307. * it is a combined SwitchArg. If so, return true, otherwise return
  308. * false.
  309. * \param s - string to be checked.
  310. */
  311. bool _hasBlanks( const std::string& s ) const;
  312. /**
  313. * Sets the requireLabel. Used by XorHandler. You shouldn't ever
  314. * use this.
  315. * \param s - Set the requireLabel to this value.
  316. */
  317. void setRequireLabel( const std::string& s );
  318. /**
  319. * Used for MultiArgs and XorHandler to determine whether args
  320. * can still be set.
  321. */
  322. virtual bool allowMore();
  323. /**
  324. * Use by output classes to determine whether an Arg accepts
  325. * multiple values.
  326. */
  327. virtual bool acceptsMultipleValues();
  328. /**
  329. * Clears the Arg object and allows it to be reused by new
  330. * command lines.
  331. */
  332. virtual void reset();
  333. };
  334. /**
  335. * Typedef of an Arg list iterator.
  336. */
  337. typedef std::list<Arg*>::iterator ArgListIterator;
  338. /**
  339. * Typedef of an Arg vector iterator.
  340. */
  341. typedef std::vector<Arg*>::iterator ArgVectorIterator;
  342. /**
  343. * Typedef of a Visitor list iterator.
  344. */
  345. typedef std::list<Visitor*>::iterator VisitorListIterator;
  346. /*
  347. * Extract a value of type T from it's string representation contained
  348. * in strVal. The ValueLike parameter used to select the correct
  349. * specialization of ExtractValue depending on the value traits of T.
  350. * ValueLike traits use operator>> to assign the value from strVal.
  351. */
  352. template<typename T> void
  353. ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
  354. {
  355. static_cast<void>(vl); // Avoid warning about unused vl
  356. std::istringstream is(strVal);
  357. int valuesRead = 0;
  358. while ( is.good() ) {
  359. if ( is.peek() != EOF )
  360. #ifdef TCLAP_SETBASE_ZERO
  361. is >> std::setbase(0) >> destVal;
  362. #else
  363. is >> destVal;
  364. #endif
  365. else
  366. break;
  367. valuesRead++;
  368. }
  369. if ( is.fail() )
  370. throw( ArgParseException("Couldn't read argument value "
  371. "from string '" + strVal + "'"));
  372. if ( valuesRead > 1 )
  373. throw( ArgParseException("More than one valid value parsed from "
  374. "string '" + strVal + "'"));
  375. }
  376. /*
  377. * Extract a value of type T from it's string representation contained
  378. * in strVal. The ValueLike parameter used to select the correct
  379. * specialization of ExtractValue depending on the value traits of T.
  380. * StringLike uses assignment (operator=) to assign from strVal.
  381. */
  382. template<typename T> void
  383. ExtractValue(T &destVal, const std::string& strVal, StringLike sl)
  384. {
  385. static_cast<void>(sl); // Avoid warning about unused sl
  386. SetString(destVal, strVal);
  387. }
  388. //////////////////////////////////////////////////////////////////////
  389. //BEGIN Arg.cpp
  390. //////////////////////////////////////////////////////////////////////
  391. inline Arg::Arg(const std::string& flag,
  392. const std::string& name,
  393. const std::string& desc,
  394. bool req,
  395. bool valreq,
  396. Visitor* v) :
  397. _flag(flag),
  398. _name(name),
  399. _description(desc),
  400. _required(req),
  401. _requireLabel("required"),
  402. _valueRequired(valreq),
  403. _alreadySet(false),
  404. _visitor( v ),
  405. _ignoreable(true),
  406. _xorSet(false),
  407. _acceptsMultipleValues(false)
  408. {
  409. if ( _flag.length() > 1 )
  410. throw(SpecificationException(
  411. "Argument flag can only be one character long", toString() ) );
  412. if ( _name != ignoreNameString() &&
  413. ( _flag == Arg::flagStartString() ||
  414. _flag == Arg::nameStartString() ||
  415. _flag == " " ) )
  416. throw(SpecificationException("Argument flag cannot be either '" +
  417. Arg::flagStartString() + "' or '" +
  418. Arg::nameStartString() + "' or a space.",
  419. toString() ) );
  420. if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
  421. ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
  422. ( _name.find( " ", 0 ) != std::string::npos ) )
  423. throw(SpecificationException("Argument name begin with either '" +
  424. Arg::flagStartString() + "' or '" +
  425. Arg::nameStartString() + "' or space.",
  426. toString() ) );
  427. }
  428. inline Arg::~Arg() { }
  429. inline std::string Arg::shortID( const std::string& valueId ) const
  430. {
  431. std::string id = "";
  432. if ( _flag != "" )
  433. id = Arg::flagStartString() + _flag;
  434. else
  435. id = Arg::nameStartString() + _name;
  436. if ( _valueRequired )
  437. id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
  438. if ( !_required )
  439. id = "[" + id + "]";
  440. return id;
  441. }
  442. inline std::string Arg::longID( const std::string& valueId ) const
  443. {
  444. std::string id = "";
  445. if ( _flag != "" )
  446. {
  447. id += Arg::flagStartString() + _flag;
  448. if ( _valueRequired )
  449. id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
  450. id += ", ";
  451. }
  452. id += Arg::nameStartString() + _name;
  453. if ( _valueRequired )
  454. id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
  455. return id;
  456. }
  457. inline bool Arg::operator==(const Arg& a) const
  458. {
  459. if ( ( _flag != "" && _flag == a._flag ) || _name == a._name)
  460. return true;
  461. else
  462. return false;
  463. }
  464. inline std::string Arg::getDescription() const
  465. {
  466. std::string desc = "";
  467. if ( _required )
  468. desc = "(" + _requireLabel + ") ";
  469. // if ( _valueRequired )
  470. // desc += "(value required) ";
  471. desc += _description;
  472. return desc;
  473. }
  474. inline const std::string& Arg::getFlag() const { return _flag; }
  475. inline const std::string& Arg::getName() const { return _name; }
  476. inline bool Arg::isRequired() const { return _required; }
  477. inline bool Arg::isValueRequired() const { return _valueRequired; }
  478. inline bool Arg::isSet() const
  479. {
  480. if ( _alreadySet && !_xorSet )
  481. return true;
  482. else
  483. return false;
  484. }
  485. inline bool Arg::isIgnoreable() const { return _ignoreable; }
  486. inline void Arg::setRequireLabel( const std::string& s)
  487. {
  488. _requireLabel = s;
  489. }
  490. inline bool Arg::argMatches( const std::string& argFlag ) const
  491. {
  492. if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) ||
  493. argFlag == Arg::nameStartString() + _name )
  494. return true;
  495. else
  496. return false;
  497. }
  498. inline std::string Arg::toString() const
  499. {
  500. std::string s = "";
  501. if ( _flag != "" )
  502. s += Arg::flagStartString() + _flag + " ";
  503. s += "(" + Arg::nameStartString() + _name + ")";
  504. return s;
  505. }
  506. inline void Arg::_checkWithVisitor() const
  507. {
  508. if ( _visitor != NULL )
  509. _visitor->visit();
  510. }
  511. /**
  512. * Implementation of trimFlag.
  513. */
  514. inline void Arg::trimFlag(std::string& flag, std::string& value) const
  515. {
  516. int stop = 0;
  517. for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ )
  518. if ( flag[i] == Arg::delimiter() )
  519. {
  520. stop = i;
  521. break;
  522. }
  523. if ( stop > 1 )
  524. {
  525. value = flag.substr(stop+1);
  526. flag = flag.substr(0,stop);
  527. }
  528. }
  529. /**
  530. * Implementation of _hasBlanks.
  531. */
  532. inline bool Arg::_hasBlanks( const std::string& s ) const
  533. {
  534. for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
  535. if ( s[i] == Arg::blankChar() )
  536. return true;
  537. return false;
  538. }
  539. inline void Arg::forceRequired()
  540. {
  541. _required = true;
  542. }
  543. inline void Arg::xorSet()
  544. {
  545. _alreadySet = true;
  546. _xorSet = true;
  547. }
  548. /**
  549. * Overridden by Args that need to added to the end of the list.
  550. */
  551. inline void Arg::addToList( std::list<Arg*>& argList ) const
  552. {
  553. argList.push_front( const_cast<Arg*>(this) );
  554. }
  555. inline bool Arg::allowMore()
  556. {
  557. return false;
  558. }
  559. inline bool Arg::acceptsMultipleValues()
  560. {
  561. return _acceptsMultipleValues;
  562. }
  563. inline void Arg::reset()
  564. {
  565. _xorSet = false;
  566. _alreadySet = false;
  567. }
  568. //////////////////////////////////////////////////////////////////////
  569. //END Arg.cpp
  570. //////////////////////////////////////////////////////////////////////
  571. } //namespace TCLAP
  572. #endif