MultiArg.h
Go to the documentation of this file.
1 // ===========================================================================
2 // Copyright (c) 2011-2012 University of Pennsylvania
3 // Copyright (c) 2013-2016 Andreas Schuh
4 // All rights reserved.
5 //
6 // See COPYING file for license information or visit
7 // https://cmake-basis.github.io/download.html#license
8 // ===========================================================================
9 
10 /**
11  * @file basis/MultiArg.h
12  * @brief Extends TCLAP's MultiArg implementation.
13  *
14  * Instead of always only consuming one argument after the argument name or
15  * flag, this MultiArg implementation consumes N arguments, where the number
16  * of arguments N is set to a fixed number at construction time.
17  */
18 
19 #pragma once
20 #ifndef _BASIS_MULTIARG_H
21 #define _BASIS_MULTIARG_H
22 
23 
24 #include "tclap/MultiArg.h"
25 
26 
27 namespace basis {
28 
29 
30 /**
31  * @brief An argument that allows multiple values of type T to be specified.
32  *
33  * Very similar to a TCLAP::ValueArg, except a vector of values will be returned
34  * instead of just one. Unlike TCLAP::MultiArg, this argument will each time
35  * its option keyword or flag is encountered process N > 0 argument values,
36  * where the number N is specified at construction time. Moreover, this argument
37  * can be given several times. Hence, the returned vector of values has length
38  * N * M, where M is the number of times the argument was given on the
39  * command-line.
40  *
41  * Copyright (c) 2011 University of Pennsylvania. All rights reserved.<br />
42  * See http://www.rad.upenn.edu/sbia/software/license.html or COPYING file.
43  *
44  * @ingroup CxxCmdLine
45  */
46 template <class T>
47 class MultiArg : public TCLAP::MultiArg<T>
48 {
49  // -----------------------------------------------------------------------
50  // construction / destruction
51 public:
52 
53  /**
54  * @brief Constructor.
55  *
56  * @param [in] flag The one character flag that identifies this
57  * argument on the command line.
58  * @param [in] name A one word name for the argument. Can be
59  * used as a long flag on the command line.
60  * @param [in] desc A description of what the argument is for or does.
61  * @param [in] req Whether the argument is required on the command-line.
62  * @param [in] typeDesc A short, human readable description of the
63  * type that this object expects. This is used in
64  * the generation of the USAGE statement. The goal
65  * is to be helpful to the end user of the program.
66  * @param [in] n Number of values per argument occurrence.
67  * @param [in] once Accept argument only once.
68  * @param [in] v An optional visitor. You probably should not
69  * use this unless you have a very good reason.
70  */
71  MultiArg(const std::string& flag,
72  const std::string& name,
73  const std::string& desc,
74  bool req,
75  const std::string& typeDesc,
76  unsigned int n = 1,
77  bool once = false,
78  TCLAP::Visitor* v = NULL);
79 
80  /**
81  * @brief Constructor.
82  *
83  * @param [in] flag The one character flag that identifies this
84  * argument on the command line.
85  * @param [in] name A one word name for the argument. Can be
86  * used as a long flag on the command line.
87  * @param [in] desc A description of what the argument is for or does.
88  * @param [in] req Whether the argument is required on the command-line.
89  * @param [in] typeDesc A short, human readable description of the
90  * type that this object expects. This is used in
91  * the generation of the USAGE statement. The goal
92  * is to be helpful to the end user of the program.
93  * @param [in] parser A CmdLine parser object to add this Arg to
94  * @param [in] n Number of values per argument occurrence.
95  * @param [in] once Accept argument only once.
96  * @param [in] v An optional visitor. You probably should not
97  * use this unless you have a very good reason.
98  */
99  MultiArg(const std::string& flag,
100  const std::string& name,
101  const std::string& desc,
102  bool req,
103  const std::string& typeDesc,
104  TCLAP::CmdLineInterface& parser,
105  unsigned int n = 1,
106  bool once = false,
107  TCLAP::Visitor* v = NULL);
108 
109  /**
110  * @brief Constructor.
111  *
112  * @param [in] flag The one character flag that identifies this
113  * argument on the command line.
114  * @param [in] name A one word name for the argument. Can be
115  * used as a long flag on the command line.
116  * @param [in] desc A description of what the argument is for or does.
117  * @param [in] req Whether the argument is required on the command-line.
118  * @param [in] constraint A pointer to a Constraint object used
119  * to constrain this Arg.
120  * @param [in] n Number of values per argument occurrence.
121  * @param [in] once Accept argument only once.
122  * @param [in] v An optional visitor. You probably should not
123  * use this unless you have a very good reason.
124  */
125  MultiArg(const std::string& flag,
126  const std::string& name,
127  const std::string& desc,
128  bool req,
129  TCLAP::Constraint<T>* constraint,
130  unsigned int n = 1,
131  bool once = false,
132  TCLAP::Visitor* v = NULL);
133 
134  /**
135  * @brief Constructor.
136  *
137  * @param [in] flag The one character flag that identifies this
138  * argument on the command line.
139  * @param [in] name A one word name for the argument. Can be
140  * used as a long flag on the command line.
141  * @param [in] desc A description of what the argument is for or does.
142  * @param [in] req Whether the argument is required on the command-line.
143  * @param [in] constraint A pointer to a Constraint object used
144  * to constrain this Arg.
145  * @param [in] parser A CmdLine parser object to add this Arg to.
146  * @param [in] n Number of values per argument occurrence.
147  * @param [in] once Accept argument only once.
148  * @param [in] v An optional visitor. You probably should not
149  * use this unless you have a very good reason.
150  */
151  MultiArg(const std::string& flag,
152  const std::string& name,
153  const std::string& desc,
154  bool req,
155  TCLAP::Constraint<T>* constraint,
156  TCLAP::CmdLineInterface& parser,
157  unsigned int n = 1,
158  bool once = false,
159  TCLAP::Visitor* v = NULL);
160 
161  // -----------------------------------------------------------------------
162  // parsing
163 public:
164 
165  /**
166  * @brief Handles the processing of the argument.
167  *
168  * This re-implements the TCLAP::MultiArg version of this method to set
169  * the _value of the argument appropriately. It knows the difference
170  * between labeled and unlabeled.
171  *
172  * @param [in, out] i Pointer to the current argument in the list.
173  * @param [in, out] args Mutable list of strings. Passed from main().
174  */
175  virtual bool processArg(int* i, std::vector<std::string>& args);
176 
177  /**
178  * @brief Whether the argument is required or not.
179  *
180  * Once we've matched the first value, then the arg is no longer required,
181  * except if the argument is only accepted once with multiple values.
182  */
183  virtual bool isRequired() const;
184 
185  // -----------------------------------------------------------------------
186  // unsupported
187 private:
188 
189  MultiArg<T>(const MultiArg<T>&); ///< Not implemented.
190  MultiArg<T>& operator=(const MultiArg<T>&); ///< Not implemented.
191 
192  // -----------------------------------------------------------------------
193  // member variables
194 protected:
195 
196  unsigned int _numberOfArguments; ///< Number of values to process each time.
197 
198 }; // class MultiArg
199 
200 
201 // ===========================================================================
202 // template definitions
203 // ===========================================================================
204 
205 // ---------------------------------------------------------------------------
206 template <class T>
207 MultiArg<T>::MultiArg(const std::string& flag,
208  const std::string& name,
209  const std::string& desc,
210  bool req,
211  const std::string& typeDesc,
212  unsigned int n,
213  bool once,
214  TCLAP::Visitor* v)
215 :
216  TCLAP::MultiArg<T>(flag, name, desc, req, typeDesc, v),
218 {
219  if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
220 }
221 
222 // ---------------------------------------------------------------------------
223 template <class T>
224 MultiArg<T>::MultiArg(const std::string& flag,
225  const std::string& name,
226  const std::string& desc,
227  bool req,
228  const std::string& typeDesc,
229  TCLAP::CmdLineInterface& parser,
230  unsigned int n,
231  bool once,
232  TCLAP::Visitor* v)
233 :
234  TCLAP::MultiArg<T>(flag, name, desc, req, typeDesc, parser, v),
236 {
237  if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
238 }
239 
240 // ---------------------------------------------------------------------------
241 template <class T>
242 MultiArg<T>::MultiArg(const std::string& flag,
243  const std::string& name,
244  const std::string& desc,
245  bool req,
246  TCLAP::Constraint<T>* constraint,
247  unsigned int n,
248  bool once,
249  TCLAP::Visitor* v)
250 :
251  TCLAP::MultiArg<T>(flag, name, desc, req, constraint, v),
253 {
254  if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
255 }
256 
257 // ---------------------------------------------------------------------------
258 template <class T>
259 MultiArg<T>::MultiArg(const std::string& flag,
260  const std::string& name,
261  const std::string& desc,
262  bool req,
263  TCLAP::Constraint<T>* constraint,
264  TCLAP::CmdLineInterface& parser,
265  unsigned int n,
266  bool once,
267  TCLAP::Visitor* v)
268 :
269  TCLAP::MultiArg<T>(flag, name, desc, req, constraint, parser, v),
271 {
272  if (once) TCLAP::MultiArg<T>::_acceptsMultipleValues = false;
273 }
274 
275 // ---------------------------------------------------------------------------
276 template <class T>
277 bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
278 {
279  if (TCLAP::MultiArg<T>::_ignoreable && TCLAP::Arg::ignoreRest()) {
280  return false;
281  }
282  if (TCLAP::MultiArg<T>::_hasBlanks( args[*i] )) return false;
283  // separate flag and value if delimiter is not ' '
284  std::string flag = args[*i];
285  std::string value = "";
286  TCLAP::MultiArg<T>::trimFlag(flag, value);
287  if (!TCLAP::MultiArg<T>::argMatches(flag)) return false;
288  // check if delimiter was found
289  if (TCLAP::Arg::delimiter() != ' ' && value == "") {
291  "Couldn't find delimiter for this argument!",
292  TCLAP::MultiArg<T>::toString());
293  }
294  // always take the first one, regardless of number of arguments
295  if (value == "")
296  {
297  if (TCLAP::MultiArg<T>::_alreadySet &&
298  !TCLAP::MultiArg<T>::_acceptsMultipleValues) {
299  throw TCLAP::CmdLineParseException("Argument already set!",
300  TCLAP::MultiArg<T>::toString());
301  }
302  (*i)++;
303  if (static_cast<unsigned int>(*i) < args.size()) {
304  TCLAP::MultiArg<T>::_extractValue(args[*i]);
305  } else {
307  "Missing a value for this argument!",
308  TCLAP::MultiArg<T>::toString());
309  }
310  } else {
311  TCLAP::MultiArg<T>::_extractValue(value);
312  }
313  // continue extracting values until number of arguments processed
314  for (unsigned int n = 1; n < _numberOfArguments; n++) {
315  (*i)++;
316  if (static_cast<unsigned int>(*i) < args.size()) {
317  TCLAP::MultiArg<T>::_extractValue(args[*i]);
318  } else {
320  "Too few values for this argument!",
321  TCLAP::MultiArg<T>::toString());
322  }
323  }
324  TCLAP::MultiArg<T>::_alreadySet = true;
325  TCLAP::MultiArg<T>::_allowMore = false;
326  TCLAP::MultiArg<T>::_checkWithVisitor();
327  return true;
328 }
329 
330 template <class T>
332 {
333  if (TCLAP::MultiArg<T>::_required) {
334  if (TCLAP::MultiArg<T>::_acceptsMultipleValues
335  && TCLAP::MultiArg<T>::_values.size() > 1) {
336  return false;
337  } else {
338  return true;
339  }
340  } else {
341  return false;
342  }
343 }
344 
345 
346 } // namespace basis
347 
348 
349 #endif // _BASIS_MULTIARG_H
virtual bool isRequired() const
Whether the argument is required or not.
Definition: MultiArg.h:331
An argument that allows multiple values of type T to be specified.
Definition: MultiArg.h:47
Definition: basis.h:34
TCLAP::ArgParseException ArgParseException
Exception thrown on command-line argument parsing error.
Definition: except.h:67
virtual bool processArg(int *i, std::vector< std::string > &args)
Handles the processing of the argument.
Definition: MultiArg.h:277
unsigned int _numberOfArguments
Number of values to process each time.
Definition: MultiArg.h:196
MultiArg(const std::string &flag, const std::string &name, const std::string &desc, bool req, const std::string &typeDesc, unsigned int n=1, bool once=false, TCLAP::Visitor *v=NULL)
Constructor.
Definition: MultiArg.h:207
TCLAP::CmdLineParseException CmdLineParseException
Exception thrown on command-line parsing error.
Definition: except.h:70