You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

434 lines
12 KiB

  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. #ifndef TCLAP_MULTIPLE_ARGUMENT_H
  22. #define TCLAP_MULTIPLE_ARGUMENT_H
  23. #include <string>
  24. #include <vector>
  25. #include "Arg.h"
  26. #include "Constraint.h"
  27. namespace TCLAP {
  28. /**
  29. * An argument that allows multiple values of type T to be specified. Very
  30. * similar to a ValueArg, except a vector of values will be returned
  31. * instead of just one.
  32. */
  33. template<class T>
  34. class MultiArg : public Arg
  35. {
  36. public:
  37. typedef std::vector<T> container_type;
  38. typedef typename container_type::iterator iterator;
  39. typedef typename container_type::const_iterator const_iterator;
  40. protected:
  41. /**
  42. * The list of values parsed from the CmdLine.
  43. */
  44. std::vector<T> _values;
  45. /**
  46. * The description of type T to be used in the usage.
  47. */
  48. std::string _typeDesc;
  49. /**
  50. * A list of constraint on this Arg.
  51. */
  52. Constraint<T>* _constraint;
  53. /**
  54. * Extracts the value from the string.
  55. * Attempts to parse string as type T, if this fails an exception
  56. * is thrown.
  57. * \param val - The string to be read.
  58. */
  59. void _extractValue( const std::string& val );
  60. /**
  61. * Used by XorHandler to decide whether to keep parsing for this arg.
  62. */
  63. bool _allowMore;
  64. public:
  65. /**
  66. * Constructor.
  67. * \param flag - The one character flag that identifies this
  68. * argument on the command line.
  69. * \param name - A one word name for the argument. Can be
  70. * used as a long flag on the command line.
  71. * \param desc - A description of what the argument is for or
  72. * does.
  73. * \param req - Whether the argument is required on the command
  74. * line.
  75. * \param typeDesc - A short, human readable description of the
  76. * type that this object expects. This is used in the generation
  77. * of the USAGE statement. The goal is to be helpful to the end user
  78. * of the program.
  79. * \param v - An optional visitor. You probably should not
  80. * use this unless you have a very good reason.
  81. */
  82. MultiArg( const std::string& flag,
  83. const std::string& name,
  84. const std::string& desc,
  85. bool req,
  86. const std::string& typeDesc,
  87. Visitor* v = NULL);
  88. /**
  89. * Constructor.
  90. * \param flag - The one character flag that identifies this
  91. * argument on the command line.
  92. * \param name - A one word name for the argument. Can be
  93. * used as a long flag on the command line.
  94. * \param desc - A description of what the argument is for or
  95. * does.
  96. * \param req - Whether the argument is required on the command
  97. * line.
  98. * \param typeDesc - A short, human readable description of the
  99. * type that this object expects. This is used in the generation
  100. * of the USAGE statement. The goal is to be helpful to the end user
  101. * of the program.
  102. * \param parser - A CmdLine parser object to add this Arg to
  103. * \param v - An optional visitor. You probably should not
  104. * use this unless you have a very good reason.
  105. */
  106. MultiArg( const std::string& flag,
  107. const std::string& name,
  108. const std::string& desc,
  109. bool req,
  110. const std::string& typeDesc,
  111. CmdLineInterface& parser,
  112. Visitor* v = NULL );
  113. /**
  114. * Constructor.
  115. * \param flag - The one character flag that identifies this
  116. * argument on the command line.
  117. * \param name - A one word name for the argument. Can be
  118. * used as a long flag on the command line.
  119. * \param desc - A description of what the argument is for or
  120. * does.
  121. * \param req - Whether the argument is required on the command
  122. * line.
  123. * \param constraint - A pointer to a Constraint object used
  124. * to constrain this Arg.
  125. * \param v - An optional visitor. You probably should not
  126. * use this unless you have a very good reason.
  127. */
  128. MultiArg( const std::string& flag,
  129. const std::string& name,
  130. const std::string& desc,
  131. bool req,
  132. Constraint<T>* constraint,
  133. Visitor* v = NULL );
  134. /**
  135. * Constructor.
  136. * \param flag - The one character flag that identifies this
  137. * argument on the command line.
  138. * \param name - A one word name for the argument. Can be
  139. * used as a long flag on the command line.
  140. * \param desc - A description of what the argument is for or
  141. * does.
  142. * \param req - Whether the argument is required on the command
  143. * line.
  144. * \param constraint - A pointer to a Constraint object used
  145. * to constrain this Arg.
  146. * \param parser - A CmdLine parser object to add this Arg to
  147. * \param v - An optional visitor. You probably should not
  148. * use this unless you have a very good reason.
  149. */
  150. MultiArg( const std::string& flag,
  151. const std::string& name,
  152. const std::string& desc,
  153. bool req,
  154. Constraint<T>* constraint,
  155. CmdLineInterface& parser,
  156. Visitor* v = NULL );
  157. /**
  158. * Handles the processing of the argument.
  159. * This re-implements the Arg version of this method to set the
  160. * _value of the argument appropriately. It knows the difference
  161. * between labeled and unlabeled.
  162. * \param i - Pointer the the current argument in the list.
  163. * \param args - Mutable list of strings. Passed from main().
  164. */
  165. virtual bool processArg(int* i, std::vector<std::string>& args);
  166. /**
  167. * Returns a vector of type T containing the values parsed from
  168. * the command line.
  169. */
  170. const std::vector<T>& getValue();
  171. /**
  172. * Returns an iterator over the values parsed from the command
  173. * line.
  174. */
  175. const_iterator begin() const { return _values.begin(); }
  176. /**
  177. * Returns the end of the values parsed from the command
  178. * line.
  179. */
  180. const_iterator end() const { return _values.end(); }
  181. /**
  182. * Returns the a short id string. Used in the usage.
  183. * \param val - value to be used.
  184. */
  185. virtual std::string shortID(const std::string& val="val") const;
  186. /**
  187. * Returns the a long id string. Used in the usage.
  188. * \param val - value to be used.
  189. */
  190. virtual std::string longID(const std::string& val="val") const;
  191. /**
  192. * Once we've matched the first value, then the arg is no longer
  193. * required.
  194. */
  195. virtual bool isRequired() const;
  196. virtual bool allowMore();
  197. virtual void reset();
  198. private:
  199. /**
  200. * Prevent accidental copying
  201. */
  202. MultiArg<T>(const MultiArg<T>& rhs);
  203. MultiArg<T>& operator=(const MultiArg<T>& rhs);
  204. };
  205. template<class T>
  206. MultiArg<T>::MultiArg(const std::string& flag,
  207. const std::string& name,
  208. const std::string& desc,
  209. bool req,
  210. const std::string& typeDesc,
  211. Visitor* v) :
  212. Arg( flag, name, desc, req, true, v ),
  213. _values(std::vector<T>()),
  214. _typeDesc( typeDesc ),
  215. _constraint( NULL ),
  216. _allowMore(false)
  217. {
  218. _acceptsMultipleValues = true;
  219. }
  220. template<class T>
  221. MultiArg<T>::MultiArg(const std::string& flag,
  222. const std::string& name,
  223. const std::string& desc,
  224. bool req,
  225. const std::string& typeDesc,
  226. CmdLineInterface& parser,
  227. Visitor* v)
  228. : Arg( flag, name, desc, req, true, v ),
  229. _values(std::vector<T>()),
  230. _typeDesc( typeDesc ),
  231. _constraint( NULL ),
  232. _allowMore(false)
  233. {
  234. parser.add( this );
  235. _acceptsMultipleValues = true;
  236. }
  237. /**
  238. *
  239. */
  240. template<class T>
  241. MultiArg<T>::MultiArg(const std::string& flag,
  242. const std::string& name,
  243. const std::string& desc,
  244. bool req,
  245. Constraint<T>* constraint,
  246. Visitor* v)
  247. : Arg( flag, name, desc, req, true, v ),
  248. _values(std::vector<T>()),
  249. _typeDesc( constraint->shortID() ),
  250. _constraint( constraint ),
  251. _allowMore(false)
  252. {
  253. _acceptsMultipleValues = true;
  254. }
  255. template<class T>
  256. MultiArg<T>::MultiArg(const std::string& flag,
  257. const std::string& name,
  258. const std::string& desc,
  259. bool req,
  260. Constraint<T>* constraint,
  261. CmdLineInterface& parser,
  262. Visitor* v)
  263. : Arg( flag, name, desc, req, true, v ),
  264. _values(std::vector<T>()),
  265. _typeDesc( constraint->shortID() ),
  266. _constraint( constraint ),
  267. _allowMore(false)
  268. {
  269. parser.add( this );
  270. _acceptsMultipleValues = true;
  271. }
  272. template<class T>
  273. const std::vector<T>& MultiArg<T>::getValue() { return _values; }
  274. template<class T>
  275. bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
  276. {
  277. if ( _ignoreable && Arg::ignoreRest() )
  278. return false;
  279. if ( _hasBlanks( args[*i] ) )
  280. return false;
  281. std::string flag = args[*i];
  282. std::string value = "";
  283. trimFlag( flag, value );
  284. if ( argMatches( flag ) )
  285. {
  286. if ( Arg::delimiter() != ' ' && value == "" )
  287. throw( ArgParseException(
  288. "Couldn't find delimiter for this argument!",
  289. toString() ) );
  290. // always take the first one, regardless of start string
  291. if ( value == "" )
  292. {
  293. (*i)++;
  294. if ( static_cast<unsigned int>(*i) < args.size() )
  295. _extractValue( args[*i] );
  296. else
  297. throw( ArgParseException("Missing a value for this argument!",
  298. toString() ) );
  299. }
  300. else
  301. _extractValue( value );
  302. /*
  303. // continuing taking the args until we hit one with a start string
  304. while ( (unsigned int)(*i)+1 < args.size() &&
  305. args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
  306. args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
  307. _extractValue( args[++(*i)] );
  308. */
  309. _alreadySet = true;
  310. _checkWithVisitor();
  311. return true;
  312. }
  313. else
  314. return false;
  315. }
  316. /**
  317. *
  318. */
  319. template<class T>
  320. std::string MultiArg<T>::shortID(const std::string& val) const
  321. {
  322. static_cast<void>(val); // Ignore input, don't warn
  323. return Arg::shortID(_typeDesc) + " ... ";
  324. }
  325. /**
  326. *
  327. */
  328. template<class T>
  329. std::string MultiArg<T>::longID(const std::string& val) const
  330. {
  331. static_cast<void>(val); // Ignore input, don't warn
  332. return Arg::longID(_typeDesc) + " (accepted multiple times)";
  333. }
  334. /**
  335. * Once we've matched the first value, then the arg is no longer
  336. * required.
  337. */
  338. template<class T>
  339. bool MultiArg<T>::isRequired() const
  340. {
  341. if ( _required )
  342. {
  343. if ( _values.size() > 1 )
  344. return false;
  345. else
  346. return true;
  347. }
  348. else
  349. return false;
  350. }
  351. template<class T>
  352. void MultiArg<T>::_extractValue( const std::string& val )
  353. {
  354. try {
  355. T tmp;
  356. ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory());
  357. _values.push_back(tmp);
  358. } catch( ArgParseException &e) {
  359. throw ArgParseException(e.error(), toString());
  360. }
  361. if ( _constraint != NULL )
  362. if ( ! _constraint->check( _values.back() ) )
  363. throw( CmdLineParseException( "Value '" + val +
  364. "' does not meet constraint: " +
  365. _constraint->description(),
  366. toString() ) );
  367. }
  368. template<class T>
  369. bool MultiArg<T>::allowMore()
  370. {
  371. bool am = _allowMore;
  372. _allowMore = true;
  373. return am;
  374. }
  375. template<class T>
  376. void MultiArg<T>::reset()
  377. {
  378. Arg::reset();
  379. _values.clear();
  380. }
  381. } // namespace TCLAP
  382. #endif