1 // -*- c-basic-offset: 4; related-file-name: "../../lib/args.cc" -*-
2 #ifndef CLICK_ARGS_HH
3 #define CLICK_ARGS_HH
4 #include <click/type_traits.hh>
5 #include <click/vector.hh>
6 #include <click/string.hh>
7 #include <click/confparse.hh>
8 #include <click/timestamp.hh>
9 #if CLICK_BSDMODULE
10 # include <machine/stdarg.h>
11 #else
12 # include <stdarg.h>
13 #endif
14 CLICK_DECLS
15 class Element;
16 class ErrorHandler;
17
18 /** @class ArgContext
19 @brief Argument context class.
20
21 The ArgContext class encapsulates state useful for parsing arguments: an
22 element context and an ErrorHandler for reporting parse errors.
23
24 Args is derived from ArgContext. Some parser functions take an ArgContext
25 reference rather than an Args reference. This clarifies that the parser
26 function doesn't modify Args internals. Also, ArgContext objects are smaller
27 and quicker to construct than Args objects.
28 */
29 class ArgContext { public:
30
31 /** @brief Construct an argument context.
32 * @param errh optional error handler */
ArgContext(ErrorHandler * errh=0)33 ArgContext(ErrorHandler *errh = 0)
34 : _errh(errh), _arg_keyword(0), _read_status(false) {
35 #if !CLICK_TOOL
36 _context = 0;
37 #endif
38 }
39
40 #if !CLICK_TOOL
41 /** @brief Construct an argument context.
42 * @param context optional element context
43 * @param errh optional error handler */
ArgContext(const Element * context,ErrorHandler * errh=0)44 ArgContext(const Element *context, ErrorHandler *errh = 0)
45 : _context(context), _errh(errh), _arg_keyword(0), _read_status(false) {
46 }
47
48 /** @brief Return the element context. */
context() const49 const Element *context() const {
50 return _context;
51 }
52 #endif
53
54 /** @brief Return the associated error handler. */
errh() const55 ErrorHandler *errh() const {
56 return _errh;
57 }
58
59 /** @brief Return a prefix string associated with the current argument.
60 *
61 * If the current argument is keyword FOO, returns "FOO: ". */
62 String error_prefix() const;
63
64 /** @brief Report a parse error for the current argument. */
65 void error(const char *fmt, ...) const;
66
67 /** @brief Report a parse warning for the current argument. */
68 void warning(const char *fmt, ...) const;
69
70 /** @brief Report a message for the current argument. */
71 void message(const char *fmt, ...) const;
72
73 void xmessage(const String &anno, const String &str) const;
74 void xmessage(const String &anno, const char *fmt, va_list val) const;
75
76 protected:
77
78 #if !CLICK_TOOL
79 const Element *_context;
80 #endif
81 ErrorHandler *_errh;
82 const char *_arg_keyword;
83 mutable bool _read_status;
84
85 };
86
87
88 /** @cond never */
89 template <typename T> struct Args_has_enable_direct_parse {
90 private:
91 template <typename X> static char test(typename X::enable_direct_parse *);
92 template <typename> static int test(...);
93 public:
94 enum { value = (sizeof(test<T>(0)) == 1) };
95 };
96 template <typename P, bool direct = Args_has_enable_direct_parse<P>::value>
97 struct Args_parse_helper;
98 template <typename P> struct Args_parse_helper<P, false> {
99 template <typename T, typename A>
slotArgs_parse_helper100 static inline T *slot(T &variable, A &args) {
101 return args.slot(variable);
102 }
103 template <typename T, typename A>
initialized_slotArgs_parse_helper104 static inline T *initialized_slot(T &variable, A &args) {
105 return args.initialized_slot(variable);
106 }
107 template <typename T, typename A>
parseArgs_parse_helper108 static inline bool parse(P parser, const String &str, T &s, A &args) {
109 return parser.parse(str, s, args);
110 }
111 template <typename T1, typename T2, typename A>
parseArgs_parse_helper112 static inline bool parse(P parser, const String &str, T1 &s1, T2 &s2, A &args) {
113 return parser.parse(str, s1, s2, args);
114 }
115 };
116 template <typename P> struct Args_parse_helper<P, true> {
117 template <typename T, typename A>
slotArgs_parse_helper118 static inline T *slot(T &variable, A &) {
119 return &variable;
120 }
121 template <typename T, typename A>
initialized_slotArgs_parse_helper122 static inline T *initialized_slot(T &variable, A &) {
123 return &variable;
124 }
125 template <typename T, typename A>
parseArgs_parse_helper126 static inline bool parse(P parser, const String &str, T &s, A &args) {
127 return parser.direct_parse(str, s, args);
128 }
129 template <typename T1, typename T2, typename A>
parseArgs_parse_helper130 static inline bool parse(P parser, const String &str, T1 &s1, T2 &s2, A &args) {
131 return parser.direct_parse(str, s1, s2, args);
132 }
133 };
134 /** @endcond never */
135
136
137 /** @class Args
138 @brief Argument parser class.
139
140 Args parses Click configuration strings in a type-safe manner.
141
142 Args manages <em>arguments</em> and <em>result slots</em>. Arguments are
143 strings to be parsed and result slots are parsed values.
144
145 The read() functions parse arguments into result slots.
146
147 @code
148 Args args;
149 args.push_back("A 1"); // add argument
150
151 int a_result;
152 args.read("A", a_result); // parse "A" into a result slot
153 @endcode
154
155 As arguments are parsed, Args marks them off and adds new result slots.
156 Each result slot is paired with a variable belonging to the caller.
157 However, the caller's variables aren't modified until the parse
158 <em>executes</em> via complete(), consume(), or execute().
159
160 @code
161 Args args; args.push_back("A 1");
162
163 int a_result = 0;
164 args.read("A", a_result);
165 assert(a_result == 0); // parsed value not yet assigned
166 args.execute(); // this call assigns results
167 assert(a_result == 1);
168 @endcode
169
170 If Args encounters a parse error, then execution doesn't modify
171 <em>any</em> of the caller's variables.
172
173 @code
174 Args args; args.push_back("A 1, B NOT_AN_INTEGER");
175
176 int a_result = 0, b_result = 0;
177 args.read("A", a_result) // succeeds
178 .read("B", b_result) // fails, since B is not an integer
179 .execute();
180 assert(a_result == 0 && b_result == 0);
181 @endcode
182
183 Each read() function comes in five variants. read() reads an optional
184 keyword argument. read_m() reads a mandatory keyword argument: if the
185 argument was not supplied, Args will report a parse error. read_p() reads
186 an optional positional argument. If the keyword was not supplied, but a
187 positional argument was, that is used. read_mp() reads a mandatory
188 positional argument. Positional arguments are parsed in order. The fifth
189 variant of read() takes an integer <em>flags</em> argument; flags include
190 Args::positional, Args::mandatory, and others, such as Args::deprecated.
191
192 The complete() execution method checks that every argument has been
193 successfully parsed and reports an error if not. consume()
194 doesn't check for completion, but removes parsed arguments from the
195 argument set. Execution methods return 0 on success and <0 on failure.
196 You can check the parse status before execution using status().
197
198 Args methods are designed to chain. All read() methods (and some others)
199 return a reference to the Args itself. It is often possible to parse a
200 whole set of arguments using a single temporary Args. For example:
201
202 @code
203 Vector<String> conf;
204 conf.push_back("A 1");
205 conf.push_back("B 2");
206
207 int a, b;
208 if (Args(conf).read("A", a)
209 .read("B", b)
210 .complete() >= 0)
211 click_chatter("Success! a=%d, b=%d", a, b);
212 @endcode
213
214 The actual work of parsing is handled by <em>parser objects</em>. Many
215 common variable types have default parsers defined by the DefaultArg<T>
216 template. For example, the default parser for an integer value understands
217 the common textual representations of integers. You can also pass a parser
218 explicitly. For example:
219
220 @code
221 int a, b, c;
222 args.read("A", a) // parse A using DefaultArg<int> = IntArg()
223 .read("B", IntArg(2), b); // parse B using IntArg(2): base-2
224 @endcode
225
226 Args generally calls a parser object's parse() method with three arguments:
227
228 <ol>
229 <li>const String &<b>str</b>: The string to be parsed.</li>
230 <li>T &<b>result</b>: A reference to the result. The parsed value, if any,
231 should be stored here. (This points to storage local to Args, not to
232 the caller's variable.)</li>
233 <li>Args &<b>args</b>: A reference to the calling Args object, for error
234 reporting.</li>
235 </ol>
236
237 The parse() method should return true if the parse succeeds and false if it
238 fails. Type-specific error messages should be reported using methods like
239 <b>args</b>.error(). For generic errors, the parse() method can simply
240 return false; Args will generate a "KEYWORD: parse error" message.
241
242 Most parsers are <em>disciplined</em>, meaning that they modify
243 <b>result</b> only if the parse succeeds. This doesn't matter in the
244 context of Args, but can matter to users who call a parse function
245 directly.
246 */
247 class Args : public ArgContext {
248 struct Slot;
249
250 public:
251
252 /** @brief Construct an argument parser.
253 * @param errh optional error handler */
254 Args(ErrorHandler *errh = 0);
255
256 /** @brief Construct an argument parser parsing a copy of @a conf.
257 * @param conf list of configuration arguments
258 * @param errh optional error handler */
259 Args(const Vector<String> &conf, ErrorHandler *errh = 0);
260
261 #if !CLICK_TOOL
262 /** @brief Construct an argument parser.
263 * @param context optional element context
264 * @param errh optional error handler */
265 Args(const Element *context, ErrorHandler *errh = 0);
266
267 /** @brief Construct an argument parser parsing a copy of @a conf.
268 * @param conf list of configuration arguments
269 * @param context optional element context
270 * @param errh optional error handler */
271 Args(const Vector<String> &conf, const Element *context,
272 ErrorHandler *errh = 0);
273 #endif
274
275
276
277 /** @brief Copy construct an argument parser.
278 * @note @a x's results are not copied. */
279 Args(const Args &x);
280
281 ~Args();
282
283 /** @brief Assign to a copy of @a x.
284 * @pre results_empty() && @a x.results_empty() */
285 Args &operator=(const Args &x);
286
287
288 /** @brief Return true iff this parser has no arguments or results. */
empty() const289 bool empty() const {
290 return (!_conf || !_conf->size()) && !_slots && _simple_slotbuf[0] == 0;
291 }
292
293 /** @brief Return true iff this parser has no results. */
results_empty() const294 bool results_empty() const {
295 return !_slots && _simple_slotbuf[0] == 0;
296 }
297
298
299 /** @brief Remove all arguments.
300 * @return *this */
clear()301 Args &clear() {
302 if (_conf)
303 _conf->clear();
304 _kwpos.clear();
305 return *this;
306 }
307
308 /** @brief Bind this parser's arguments to @a conf.
309 * @param conf reference to new arguments
310 * @return *this
311 * @post This Args shares @a conf with the caller.
312 * For instance, consume() will modify @a conf. */
313 Args &bind(Vector<String> &conf);
314
315 /** @brief Append argument @a arg to this parser.
316 * @return *this */
317 Args &push_back(const String &arg);
318
319 /** @brief Append arguments in the range [@a begin, @a end) to this parser.
320 * @return *this */
push_back(Iter begin,Iter end)321 template<typename Iter> Args &push_back(Iter begin, Iter end) {
322 while (begin != end) {
323 push_back(*begin);
324 ++begin;
325 }
326 return *this;
327 }
328
329 /** @brief Append the space-separated words in @a str to this parser.
330 * @return *this */
331 Args &push_back_words(const String &str);
332
333 /** @brief Append the comma-separated arguments in @a str to this parser.
334 * @return *this */
335 Args &push_back_args(const String &str);
336
337 /** @brief Reset the parse status for every argument.
338 * @return *this
339 *
340 * For example:
341 * @code
342 * Vector<String> conf; conf.push_back("1"); conf.push_back("2");
343 * int a, b;
344 * Args(conf).read_p("A", a).read_p("B", b).execute();
345 * assert(a == 1 && b == 2);
346 * Args(conf).read_p("A", a).reset().read_p("B", b).execute();
347 * assert(a == 1 && b == 1);
348 * @endcode
349 * Results are not affected. */
reset()350 Args &reset() {
351 reset_from(0);
352 return *this;
353 }
354
355
356 static constexpr int mandatory = 1; ///< read flag for mandatory arguments
357 static constexpr int positional = 2; ///< read flag for positional arguments
358 static constexpr int deprecated = 4; ///< read flag for deprecated arguments
359 static constexpr int firstmatch = 8; ///< read flag to take first matching argument
360
361 /** @brief Read an argument using its type's default parser.
362 * @param keyword argument name
363 * @param x reference to result
364 * @return *this
365 *
366 * Creates a result slot for @a x and calls
367 * DefaultArg<T>().parse(string, result, *this). */
368 template <typename T>
read(const char * keyword,T & x)369 Args &read(const char *keyword, T &x) {
370 return read(keyword, 0, x);
371 }
372 template <typename T>
read_m(const char * keyword,T & x)373 Args &read_m(const char *keyword, T &x) {
374 return read(keyword, mandatory, x);
375 }
376 template <typename T>
read_p(const char * keyword,T & x)377 Args &read_p(const char *keyword, T &x) {
378 return read(keyword, positional, x);
379 }
380 template <typename T>
read_mp(const char * keyword,T & x)381 Args &read_mp(const char *keyword, T &x) {
382 return read(keyword, mandatory | positional, x);
383 }
384 template <typename T>
read(const char * keyword,int flags,T & x)385 Args &read(const char *keyword, int flags, T &x) {
386 args_base_read(this, keyword, flags, x);
387 return *this;
388 }
389
390 /** @brief Read an argument using the default parser, or set it to a
391 * default value if the argument is was not supplied.
392 * @param keyword argument name
393 * @param x reference to result
394 * @param default_value default value
395 * @return *this
396 *
397 * Creates a result slot for @a x. If @a keyword was supplied, calls
398 * DefaultArg<T>().parse(string, result, this). Otherwise, assigns the
399 * result to @a value. */
400 template <typename T, typename V>
read_or_set(const char * keyword,T & x,const V & default_value)401 Args &read_or_set(const char *keyword, T &x, const V &default_value) {
402 return read_or_set(keyword, 0, x, default_value);
403 }
404 template <typename T, typename V>
read_or_set_p(const char * keyword,T & x,const V & default_value)405 Args &read_or_set_p(const char *keyword, T &x, const V &default_value) {
406 return read_or_set(keyword, positional, x, default_value);
407 }
408 template <typename T, typename V>
read_or_set(const char * keyword,int flags,T & x,const V & default_value)409 Args &read_or_set(const char *keyword, int flags, T &x, const V &default_value) {
410 args_base_read_or_set(this, keyword, flags, x, default_value);
411 return *this;
412 }
413
414 /** @brief Read an argument using a specified parser.
415 * @param keyword argument name
416 * @param parser parser object
417 * @param x reference to result
418 * @return *this
419 *
420 * Creates a result slot for @a x and calls @a parser.parse(string,
421 * result, *this). */
422 template <typename P, typename T>
read(const char * keyword,P parser,T & x)423 Args &read(const char *keyword, P parser, T &x) {
424 return read(keyword, 0, parser, x);
425 }
426 template <typename P, typename T>
read_m(const char * keyword,P parser,T & x)427 Args &read_m(const char *keyword, P parser, T &x) {
428 return read(keyword, mandatory, parser, x);
429 }
430 template <typename P, typename T>
read_p(const char * keyword,P parser,T & x)431 Args &read_p(const char *keyword, P parser, T &x) {
432 return read(keyword, positional, parser, x);
433 }
434 template <typename P, typename T>
read_mp(const char * keyword,P parser,T & x)435 Args &read_mp(const char *keyword, P parser, T &x) {
436 return read(keyword, mandatory | positional, parser, x);
437 }
438 template <typename P, typename T>
read(const char * keyword,int flags,P parser,T & x)439 Args &read(const char *keyword, int flags, P parser, T &x) {
440 args_base_read(this, keyword, flags, parser, x);
441 return *this;
442 }
443
444 /** @brief Read an argument using a specified parser, or set it to a
445 * default value if the argument is was not supplied.
446 * @param keyword argument name
447 * @param parser parser object
448 * @param x reference to result variable
449 * @param default_value default value
450 * @return *this
451 *
452 * Creates a result slot for @a x. If argument @a keyword was supplied,
453 * calls @a parser.parse(string, result, *this). Otherwise, assigns the
454 * result to @a default_value. */
455 template <typename P, typename T, typename V>
read_or_set(const char * keyword,P parser,T & x,const V & default_value)456 Args &read_or_set(const char *keyword, P parser, T &x, const V &default_value) {
457 return read_or_set(keyword, 0, parser, x, default_value);
458 }
459 template <typename P, typename T, typename V>
read_or_set_p(const char * keyword,P parser,T & x,const V & default_value)460 Args &read_or_set_p(const char *keyword, P parser, T &x, const V &default_value) {
461 return read_or_set(keyword, positional, parser, x, default_value);
462 }
463 template <typename P, typename T, typename V>
read_or_set(const char * keyword,int flags,P parser,T & x,const V & default_value)464 Args &read_or_set(const char *keyword, int flags, P parser, T &x, const V &default_value) {
465 args_base_read_or_set(this, keyword, flags, parser, x, default_value);
466 return *this;
467 }
468
469 /** @brief Read an argument using a specified parser with two results.
470 * @param keyword argument name
471 * @param parser parser object
472 * @param x1 reference to first result
473 * @param x2 reference to second result
474 * @return *this
475 *
476 * Creates results for @a x1 and @a x2 and calls @a parser.parse(string,
477 * result1, result2, *this). */
478 template<typename P, typename T1, typename T2>
read(const char * keyword,P parser,T1 & x1,T2 & x2)479 Args &read(const char *keyword, P parser, T1 &x1, T2 &x2) {
480 return read(keyword, 0, parser, x1, x2);
481 }
482 template<typename P, typename T1, typename T2>
read_m(const char * keyword,P parser,T1 & x1,T2 & x2)483 Args &read_m(const char *keyword, P parser, T1 &x1, T2 &x2) {
484 return read(keyword, mandatory, parser, x1, x2);
485 }
486 template<typename P, typename T1, typename T2>
read_p(const char * keyword,P parser,T1 & x1,T2 & x2)487 Args &read_p(const char *keyword, P parser, T1 &x1, T2 &x2) {
488 return read(keyword, positional, parser, x1, x2);
489 }
490 template<typename P, typename T1, typename T2>
read_mp(const char * keyword,P parser,T1 & x1,T2 & x2)491 Args &read_mp(const char *keyword, P parser, T1 &x1, T2 &x2) {
492 return read(keyword, mandatory | positional, parser, x1, x2);
493 }
494 template<typename P, typename T1, typename T2>
read(const char * keyword,int flags,P parser,T1 & x1,T2 & x2)495 Args &read(const char *keyword, int flags, P parser, T1 &x1, T2 &x2) {
496 args_base_read(this, keyword, flags, parser, x1, x2);
497 return *this;
498 }
499
500 /** @brief Pass an argument to a specified parser.
501 * @param keyword argument name
502 * @param parser parser object
503 * @return *this
504 *
505 * Calls @a parser.parse(string, *this). */
506 template <typename P>
read_with(const char * keyword,P parser)507 Args &read_with(const char *keyword, P parser) {
508 return read_with(keyword, 0, parser);
509 }
510 template <typename P>
read_m_with(const char * keyword,P parser)511 Args &read_m_with(const char *keyword, P parser) {
512 return read_with(keyword, mandatory, parser);
513 }
514 template <typename P>
read_p_with(const char * keyword,P parser)515 Args &read_p_with(const char *keyword, P parser) {
516 return read_with(keyword, positional, parser);
517 }
518 template <typename P>
read_mp_with(const char * keyword,P parser)519 Args &read_mp_with(const char *keyword, P parser) {
520 return read_with(keyword, mandatory | positional, parser);
521 }
522 template <typename P>
read_with(const char * keyword,int flags,P parser)523 Args &read_with(const char *keyword, int flags, P parser) {
524 args_base_read_with(this, keyword, flags, parser);
525 return *this;
526 }
527
528 /** @brief Pass an argument to a specified parser.
529 * @param keyword argument name
530 * @param parser parser object
531 * @param x reference to result
532 * @return *this
533 *
534 * Creates a result slot for @a x and calls @a parser.parse(string,
535 * result, *this).
536 *
537 * @deprecated Use read(keyword, parser, variable) instead. */
538 template <typename P, typename T>
read_with(const char * keyword,P parser,T & x)539 Args &read_with(const char *keyword, P parser, T &x) {
540 return read(keyword, parser, x);
541 }
542 template <typename P, typename T>
read_m_with(const char * keyword,P parser,T & x)543 Args &read_m_with(const char *keyword, P parser, T &x) {
544 return read_m(keyword, parser, x);
545 }
546 template <typename P, typename T>
read_p_with(const char * keyword,P parser,T & x)547 Args &read_p_with(const char *keyword, P parser, T &x) {
548 return read_p(keyword, parser, x);
549 }
550 template <typename P, typename T>
read_mp_with(const char * keyword,P parser,T & x)551 Args &read_mp_with(const char *keyword, P parser, T &x) {
552 return read_mp(keyword, parser, x);
553 }
554 template <typename P, typename T>
read_with(const char * keyword,int flags,P parser,T & x)555 Args &read_with(const char *keyword, int flags, P parser, T &x) {
556 return read(keyword, flags, parser, x);
557 }
558
559 /** @brief Pass all matching arguments to a specified parser.
560 * @param keyword argument name
561 * @param parser parser object
562 * @return *this
563 *
564 * Calls @a parser.parse(string, *this) zero or more times.
565 *
566 * @note The value of read_status() is true iff at least one argument
567 * matched and all matching arguments successfully parsed. */
568 template <typename P>
read_all_with(const char * keyword,P parser)569 Args &read_all_with(const char *keyword, P parser) {
570 return read_all_with(keyword, 0, parser);
571 }
572 template <typename P>
read_all_with(const char * keyword,int flags,P parser)573 Args &read_all_with(const char *keyword, int flags, P parser) {
574 args_base_read_all_with(this, keyword, flags | firstmatch, parser);
575 return *this;
576 }
577
578 /** @brief Pass all matching arguments to a specified parser.
579 * @param keyword argument name
580 * @param parser parser object
581 * @param x reference to result
582 * @return *this
583 *
584 * Creates a result for @a x and calls @a parser.parse(string, result,
585 * *this) zero or more times, once per matching argument.
586 *
587 * @note The value of read_status() is true iff at least one argument
588 * matched and all matching arguments successfully parsed. */
589 template <typename P, typename T>
read_all_with(const char * keyword,P parser,T & x)590 Args &read_all_with(const char *keyword, P parser, T &x) {
591 return read_all_with(keyword, 0, parser, x);
592 }
593 template <typename P, typename T>
read_all_with(const char * keyword,int flags,P parser,T & x)594 Args &read_all_with(const char *keyword, int flags, P parser, T &x) {
595 args_base_read_all_with(this, keyword, flags | firstmatch, parser, x);
596 return *this;
597 }
598
599 /** @brief Pass all matching arguments to a specified parser.
600 * @param keyword argument name
601 * @param parser parser object
602 * @param x reference to vector of results
603 * @return *this
604 *
605 * For each @a keyword argument, calls @a parser.parse(string, value,
606 * *this). The resulting values are collected into a vector result slot
607 * for @a x.
608 *
609 * @note The value of read_status() is true iff at least one argument
610 * matched and all matching arguments successfully parsed. */
611 template <typename P, typename T>
read_all(const char * keyword,P parser,Vector<T> & x)612 Args &read_all(const char *keyword, P parser, Vector<T> &x) {
613 return read_all(keyword, 0, parser, x);
614 }
615 template <typename T>
read_all(const char * keyword,Vector<T> & x)616 Args &read_all(const char *keyword, Vector<T> &x) {
617 return read_all(keyword, 0, DefaultArg<T>(), x);
618 }
619 template <typename P, typename T>
read_all(const char * keyword,int flags,P parser,Vector<T> & x)620 Args &read_all(const char *keyword, int flags, P parser, Vector<T> &x) {
621 args_base_read_all(this, keyword, flags | firstmatch, parser, x);
622 return *this;
623 }
624 template <typename P, typename T>
read_all(const char * keyword,int flags,Vector<T> & x)625 Args &read_all(const char *keyword, int flags, Vector<T> &x) {
626 return read_all(keyword, flags, DefaultArg<T>(), x);
627 }
628
629
630 /** @brief Return the current parse status. */
status() const631 bool status() const {
632 return _status;
633 }
634 /** @brief Set @a x to the current parse status.
635 * @return *this */
status(bool & x)636 Args &status(bool &x) {
637 x = _status;
638 return *this;
639 }
640 /** @overload */
status(bool & x) const641 const Args &status(bool &x) const {
642 x = _status;
643 return *this;
644 }
645
646 /** @brief Return true iff the last read request succeeded.
647 *
648 * This function should only be called after a read. */
read_status() const649 bool read_status() const {
650 return _read_status;
651 }
652 /** @brief Set @a x to the success status of the last read request.
653 *
654 * This function should only be called after a read. */
read_status(bool & x)655 Args &read_status(bool &x) {
656 x = _read_status;
657 return *this;
658 }
659 /** @overload */
read_status(bool & x) const660 const Args &read_status(bool &x) const {
661 x = _read_status;
662 return *this;
663 }
664
665
666 /** @brief Remove all arguments matched so far. */
667 Args &strip();
668
669 /** @brief Assign results.
670 * @return 0 if the parse succeeded, <0 otherwise
671 * @post results_empty()
672 *
673 * Results are only assigned if status() is true (the parse is successful
674 * so far). Clears results as a side effect. */
675 int execute();
676
677 /** @brief Assign results and remove matched arguments.
678 * @return 0 if the parse succeeded, <0 otherwise
679 * @post results_empty()
680 *
681 * Matched arguments are always removed. Results are only assigned if
682 * status() is true (the parse is successful so far). Clears results as a
683 * side effect. */
684 int consume();
685
686 /** @brief Assign results if all arguments matched.
687 * @return 0 if the parse succeeded, <0 otherwise
688 * @post results_empty()
689 *
690 * Results are only assigned if status() is true (the parse is successful
691 * so far) and all arguments have been parsed. Clears results as a side
692 * effect. */
693 int complete();
694
695
696 /** @brief Create and return a result slot for @a x.
697 *
698 * If T is a trivially copyable type, such as int, then the resulting
699 * slot might not be initialized. */
700 template <typename T>
slot(T & x)701 T *slot(T &x) {
702 if (has_trivial_copy<T>::value)
703 return reinterpret_cast<T *>(simple_slot(&x, sizeof(T)));
704 else
705 return complex_slot(x);
706 }
707
708 /** @brief Create and return a result slot for @a x.
709 *
710 * The resulting slot is always default-initialized. */
711 template <typename T>
initialized_slot(T & x)712 T *initialized_slot(T &x) {
713 T *s = slot(x);
714 if (has_trivial_copy<T>::value)
715 *s = T();
716 return s;
717 }
718
719 /** @brief Add a result that assigns @a x to @a value.
720 * @return *this */
721 template <typename T, typename V>
set(T & x,const V & value)722 Args &set(T &x, const V &value) {
723 if (T *s = slot(x))
724 *s = value;
725 return *this;
726 }
727
728
729 /** @cond never */
730 template<typename T>
base_read(const char * keyword,int flags,T & variable)731 void base_read(const char *keyword, int flags, T &variable) {
732 Slot *slot_status;
733 if (String str = find(keyword, flags, slot_status)) {
734 T *s = Args_parse_helper<DefaultArg<T> >::slot(variable, *this);
735 postparse(s && Args_parse_helper<DefaultArg<T> >::parse(DefaultArg<T>(), str, *s, *this), slot_status);
736 }
737 }
738
739 template<typename T, typename V>
base_read_or_set(const char * keyword,int flags,T & variable,const V & value)740 void base_read_or_set(const char *keyword, int flags, T &variable, const V &value) {
741 Slot *slot_status;
742 String str = find(keyword, flags, slot_status);
743 T *s = Args_parse_helper<DefaultArg<T> >::slot(variable, *this);
744 postparse(s && (str ? Args_parse_helper<DefaultArg<T> >::parse(DefaultArg<T>(), str, *s, *this) : (*s = value, true)), slot_status);
745 }
746
747 template<typename P, typename T>
base_read(const char * keyword,int flags,P parser,T & variable)748 void base_read(const char *keyword, int flags, P parser, T &variable) {
749 Slot *slot_status;
750 if (String str = find(keyword, flags, slot_status)) {
751 T *s = Args_parse_helper<P>::slot(variable, *this);
752 postparse(s && Args_parse_helper<P>::parse(parser, str, *s, *this), slot_status);
753 }
754 }
755
756 template<typename T, typename P, typename V>
base_read_or_set(const char * keyword,int flags,P parser,T & variable,const V & value)757 void base_read_or_set(const char *keyword, int flags, P parser, T &variable, const V &value) {
758 Slot *slot_status;
759 String str = find(keyword, flags, slot_status);
760 T *s = Args_parse_helper<P>::slot(variable, *this);
761 postparse(s && (str ? Args_parse_helper<P>::parse(parser, str, *s, *this) : (*s = value, true)), slot_status);
762 }
763
764 template<typename P, typename T1, typename T2>
base_read(const char * keyword,int flags,P parser,T1 & variable1,T2 & variable2)765 void base_read(const char *keyword, int flags,
766 P parser, T1 &variable1, T2 &variable2) {
767 Slot *slot_status;
768 if (String str = find(keyword, flags, slot_status)) {
769 T1 *s1 = Args_parse_helper<P>::slot(variable1, *this);
770 T2 *s2 = Args_parse_helper<P>::slot(variable2, *this);
771 postparse(s1 && s2 && Args_parse_helper<P>::parse(parser, str, *s1, *s2, *this), slot_status);
772 }
773 }
774
775 template<typename P>
base_read_with(const char * keyword,int flags,P parser)776 void base_read_with(const char *keyword, int flags, P parser) {
777 Slot *slot_status;
778 if (String str = find(keyword, flags, slot_status))
779 postparse(parser.parse(str, *this), slot_status);
780 }
781
782 template<typename P>
base_read_all_with(const char * keyword,int flags,P parser)783 void base_read_all_with(const char *keyword, int flags, P parser) {
784 Slot *slot_status;
785 int read_status = -1;
786 while (String str = find(keyword, flags, slot_status)) {
787 postparse(parser.parse(str, *this), slot_status);
788 read_status = (read_status != 0) && _read_status;
789 flags &= ~mandatory;
790 }
791 _read_status = (read_status == 1);
792 }
793
794 template<typename P, typename T>
base_read_all_with(const char * keyword,int flags,P parser,T & variable)795 void base_read_all_with(const char *keyword, int flags, P parser, T &variable) {
796 Slot *slot_status;
797 int read_status = -1;
798 T *s = Args_parse_helper<P>::initialized_slot(variable, *this);
799 while (String str = find(keyword, flags, slot_status)) {
800 postparse(s && Args_parse_helper<P>::parse(parser, str, *s, *this), slot_status);
801 read_status = (read_status != 0) && _read_status;
802 flags &= ~mandatory;
803 }
804 _read_status = (read_status == 1);
805 }
806
807 template<typename P, typename T>
base_read_all(const char * keyword,int flags,P parser,Vector<T> & variable)808 void base_read_all(const char *keyword, int flags, P parser, Vector<T> &variable) {
809 Slot *slot_status;
810 int read_status = -1;
811 Vector<T> *s = slot(variable);
812 while (String str = find(keyword, flags, slot_status)) {
813 T sx = T();
814 postparse(parser.parse(str, sx, *this), slot_status);
815 if (_read_status)
816 s->push_back(sx);
817 read_status = (read_status != 0) && _read_status;
818 flags &= ~mandatory;
819 }
820 _read_status = (read_status == 1);
821 }
822 /** @endcond never */
823
824 private:
825
826 struct Slot {
SlotArgs::Slot827 Slot() {
828 }
~SlotArgs::Slot829 virtual ~Slot() {
830 }
831 virtual void store() = 0;
832 Slot *_next;
833 };
834
835 struct BytesSlot : public Slot {
BytesSlotArgs::BytesSlot836 BytesSlot(void *ptr, size_t size)
837 : _ptr(ptr), _slot(new char[size]), _size(size) {
838 }
~BytesSlotArgs::BytesSlot839 ~BytesSlot() {
840 delete[] _slot;
841 }
storeArgs::BytesSlot842 void store() {
843 memcpy(_ptr, _slot, _size);
844 }
845 void *_ptr;
846 char *_slot;
847 size_t _size;
848 };
849
850 template<typename T>
851 struct SlotT : public Slot {
SlotTArgs::SlotT852 SlotT(T *ptr)
853 : _ptr(ptr) {
854 }
storeArgs::SlotT855 void store() {
856 assign_consume(*_ptr, _slot);
857 }
858 T *_ptr;
859 T _slot;
860 };
861
862 enum {
863 #if SIZEOF_VOID_P == 4
864 simple_slotbuf_size = 24
865 #else
866 simple_slotbuf_size = 48
867 #endif
868 };
869
870 #if !CLICK_DEBUG_ARGS_USAGE
871 bool _my_conf;
872 #else
873 bool _my_conf : 1;
874 bool _consumed : 1;
875 #endif
876 bool _status;
877 uint8_t _simple_slotpos;
878
879 Vector<String> *_conf;
880 Vector<int> _kwpos;
881
882 Slot *_slots;
883 uint8_t _simple_slotbuf[simple_slotbuf_size];
884
885 inline void initialize(const Vector<String> *conf);
886 void reset_from(int i);
887
888 String find(const char *keyword, int flags, Slot *&slot_status);
889 void postparse(bool ok, Slot *slot_status);
890 void check_complete();
891
892 static inline int simple_slot_size(int size);
893 inline void simple_slot_info(int offset, int size,
894 void *&slot, void **&pointer);
895 void *simple_slot(void *data, size_t size);
896 template<typename T> T *complex_slot(T &variable);
897
898 };
899
900 extern const ArgContext blank_args;
901
902
903 template<typename T>
904 struct DefaultArg {
905 };
906
907 template<typename T>
complex_slot(T & variable)908 T *Args::complex_slot(T &variable)
909 {
910 if (SlotT<T> *s = new SlotT<T>(&variable)) {
911 s->_next = _slots;
912 _slots = s;
913 return &s->_slot;
914 } else {
915 error("out of memory");
916 return 0;
917 }
918 }
919
920
921 /** @cond never */
922 /* These functions are here because some GCC versions ignore noinline
923 attributes on member function templates. */
924 template<typename T>
925 void args_base_read(Args *args, const char *keyword, int flags, T &variable)
926 CLICK_NOINLINE;
927 template<typename T>
args_base_read(Args * args,const char * keyword,int flags,T & variable)928 void args_base_read(Args *args, const char *keyword, int flags, T &variable)
929 {
930 args->base_read(keyword, flags, variable);
931 }
932
933 template<typename T, typename V>
934 void args_base_read_or_set(Args *args, const char *keyword, int flags,
935 T &variable, const V &value) CLICK_NOINLINE;
936 template<typename T, typename V>
args_base_read_or_set(Args * args,const char * keyword,int flags,T & variable,const V & value)937 void args_base_read_or_set(Args *args, const char *keyword, int flags,
938 T &variable, const V &value)
939 {
940 args->base_read_or_set(keyword, flags, variable, value);
941 }
942
943 template<typename P, typename T>
944 void args_base_read(Args *args, const char *keyword, int flags,
945 P parser, T &variable) CLICK_NOINLINE;
946 template<typename P, typename T>
args_base_read(Args * args,const char * keyword,int flags,P parser,T & variable)947 void args_base_read(Args *args, const char *keyword, int flags,
948 P parser, T &variable)
949 {
950 args->base_read(keyword, flags, parser, variable);
951 }
952
953 template<typename P, typename T, typename V>
954 void args_base_read_or_set(Args *args, const char *keyword, int flags,
955 P parser, T &variable, const V &value) CLICK_NOINLINE;
956 template<typename P, typename T, typename V>
args_base_read_or_set(Args * args,const char * keyword,int flags,P parser,T & variable,const V & value)957 void args_base_read_or_set(Args *args, const char *keyword, int flags,
958 P parser, T &variable, const V &value)
959 {
960 args->base_read_or_set(keyword, flags, parser, variable, value);
961 }
962
963 template<typename P, typename T1, typename T2>
964 void args_base_read(Args *args, const char *keyword, int flags,
965 P parser, T1 &variable1, T2 &variable2) CLICK_NOINLINE;
966 template<typename P, typename T1, typename T2>
args_base_read(Args * args,const char * keyword,int flags,P parser,T1 & variable1,T2 & variable2)967 void args_base_read(Args *args, const char *keyword, int flags,
968 P parser, T1 &variable1, T2 &variable2)
969 {
970 args->base_read(keyword, flags, parser, variable1, variable2);
971 }
972
973 template<typename P>
974 void args_base_read_with(Args *args, const char *keyword, int flags, P parser)
975 CLICK_NOINLINE;
976 template<typename P>
args_base_read_with(Args * args,const char * keyword,int flags,P parser)977 void args_base_read_with(Args *args, const char *keyword, int flags, P parser)
978 {
979 args->base_read_with(keyword, flags, parser);
980 }
981
982 template<typename P>
983 void args_base_read_all_with(Args *args, const char *keyword, int flags, P parser)
984 CLICK_NOINLINE;
985 template<typename P>
args_base_read_all_with(Args * args,const char * keyword,int flags,P parser)986 void args_base_read_all_with(Args *args, const char *keyword, int flags, P parser)
987 {
988 args->base_read_all_with(keyword, flags, parser);
989 }
990
991 template<typename P, typename T>
992 void args_base_read_all_with(Args *args, const char *keyword, int flags,
993 P parser, T &variable) CLICK_NOINLINE;
994 template<typename P, typename T>
args_base_read_all_with(Args * args,const char * keyword,int flags,P parser,T & variable)995 void args_base_read_all_with(Args *args, const char *keyword, int flags,
996 P parser, T &variable)
997 {
998 args->base_read_all_with(keyword, flags, parser, variable);
999 }
1000
1001 template <typename P, typename T>
1002 void args_base_read_all(Args *args, const char *keyword, int flags,
1003 P parser, Vector<T> &variable) CLICK_NOINLINE;
1004 template <typename P, typename T>
args_base_read_all(Args * args,const char * keyword,int flags,P parser,Vector<T> & variable)1005 void args_base_read_all(Args *args, const char *keyword, int flags,
1006 P parser, Vector<T> &variable)
1007 {
1008 args->base_read_all(keyword, flags, parser, variable);
1009 }
1010 /** @endcond never */
1011
1012
1013 class NumArg { public:
1014 enum {
1015 status_ok = 0,
1016 status_inval = EINVAL,
1017 status_range = ERANGE,
1018 #if defined(ENOTSUP)
1019 status_notsup = ENOTSUP,
1020 #elif defined(ENOTSUPP)
1021 status_notsup = ENOTSUPP,
1022 #else
1023 status_notsup,
1024 #endif
1025 status_unitless
1026 };
1027 };
1028
1029
1030 /** @class IntArg
1031 @brief Parser class for integers.
1032
1033 IntArg(@a base) reads integers in base @a base. @a base defaults to 0,
1034 which means arguments are parsed in base 10 by default, but prefixes 0x, 0,
1035 and 0b parse hexadecimal, octal, and binary numbers, respectively.
1036
1037 Integer overflow is treated as an error.
1038
1039 @sa SaturatingIntArg, BoundedIntArg */
1040 class IntArg : public NumArg { public:
1041
1042 typedef uint32_t limb_type;
1043
IntArg(int b=0)1044 IntArg(int b = 0)
1045 : base(b) {
1046 }
1047
1048 const char *parse(const char *begin, const char *end,
1049 bool is_signed, int size,
1050 limb_type *value, int nlimb);
1051
1052 template<typename V>
parse_saturating(const String & str,V & result,const ArgContext & args=blank_args)1053 bool parse_saturating(const String &str, V &result, const ArgContext &args = blank_args) {
1054 constexpr bool is_signed = integer_traits<V>::is_signed;
1055 constexpr int nlimb = int((sizeof(V) + sizeof(limb_type) - 1) / sizeof(limb_type));
1056 limb_type x[nlimb];
1057 if (parse(str.begin(), str.end(), is_signed, int(sizeof(V)), x, nlimb)
1058 != str.end())
1059 status = status_inval;
1060 if (status && status != status_range) {
1061 args.error("invalid number");
1062 return false;
1063 }
1064 typedef typename make_unsigned<V>::type unsigned_v_type;
1065 extract_integer(x, reinterpret_cast<unsigned_v_type &>(result));
1066 return true;
1067 }
1068
1069 template<typename V>
parse(const String & str,V & result,const ArgContext & args=blank_args)1070 bool parse(const String &str, V &result, const ArgContext &args = blank_args) {
1071 V x;
1072 if (!parse_saturating(str, x, args)
1073 || (status && status != status_range))
1074 return false;
1075 else if (status == status_range) {
1076 range_error(args, integer_traits<V>::is_signed,
1077 click_int_large_t(x));
1078 return false;
1079 } else {
1080 result = x;
1081 return true;
1082 }
1083 }
1084
1085 int base;
1086 int status;
1087
1088 protected:
1089
1090 static const char *span(const char *begin, const char *end,
1091 bool is_signed, int &b);
1092 void range_error(const ArgContext &args, bool is_signed,
1093 click_int_large_t value);
1094
1095 };
1096
1097 /** @class SaturatingIntArg
1098 @brief Parser class for integers with saturating overflow.
1099
1100 SaturatingIntArg(@a base) is like IntArg(@a base), but integer overflow is
1101 not an error; instead, the closest representable value is returned.
1102
1103 @sa IntArg */
1104 class SaturatingIntArg : public IntArg { public:
SaturatingIntArg(int b=0)1105 SaturatingIntArg(int b = 0)
1106 : IntArg(b) {
1107 }
1108
1109 template<typename V>
parse(const String & str,V & result,const ArgContext & args=blank_args)1110 bool parse(const String &str, V &result, const ArgContext &args = blank_args) {
1111 return parse_saturating(str, result, args);
1112 }
1113 };
1114
1115 /** @class BoundedIntArg
1116 @brief Parser class for integers with explicit bounds.
1117
1118 BoundedIntArg(@a min, @a max, @a base) is like IntArg(@a base), but numbers
1119 less than @a min or greater than @a max are treated as errors.
1120
1121 @sa IntArg */
1122 class BoundedIntArg : public IntArg { public:
1123 template <typename T>
BoundedIntArg(T min_value,T max_value,int b=0)1124 BoundedIntArg(T min_value, T max_value, int b = 0)
1125 : IntArg(b), min_value(min_value), max_value(max_value) {
1126 static_assert(integer_traits<T>::is_integral, "BoundedIntArg argument must be integral");
1127 is_signed = integer_traits<T>::is_signed;
1128 }
1129
1130 template <typename V>
parse(const String & str,V & result,const ArgContext & args=blank_args)1131 bool parse(const String &str, V &result, const ArgContext &args = blank_args) {
1132 V x;
1133 if (!IntArg::parse(str, x, args))
1134 return false;
1135 else if (!check_min(typename integer_traits<V>::max_type(x))) {
1136 range_error(args, is_signed, min_value);
1137 return false;
1138 } else if (!check_max(typename integer_traits<V>::max_type(x))) {
1139 range_error(args, is_signed, max_value);
1140 return false;
1141 } else {
1142 result = x;
1143 return true;
1144 }
1145 }
1146
check_min(click_int_large_t x) const1147 inline bool check_min(click_int_large_t x) const {
1148 if (is_signed)
1149 return x >= min_value;
1150 else
1151 return x >= 0 && click_uint_large_t(x) >= click_uint_large_t(min_value);
1152 }
check_min(click_uint_large_t x) const1153 inline bool check_min(click_uint_large_t x) const {
1154 if (is_signed)
1155 return min_value < 0 || x >= click_uint_large_t(min_value);
1156 else
1157 return click_uint_large_t(x) >= click_uint_large_t(min_value);
1158 }
check_max(click_int_large_t x) const1159 inline bool check_max(click_int_large_t x) const {
1160 if (is_signed)
1161 return x <= max_value;
1162 else
1163 return x >= 0 && click_uint_large_t(x) <= click_uint_large_t(max_value);
1164 }
check_max(click_uint_large_t x) const1165 inline bool check_max(click_uint_large_t x) const {
1166 if (is_signed)
1167 return max_value >= 0 && x <= click_uint_large_t(max_value);
1168 else
1169 return click_uint_large_t(x) <= click_uint_large_t(max_value);
1170 }
1171
1172 click_intmax_t min_value;
1173 click_intmax_t max_value;
1174 bool is_signed;
1175 };
1176
1177 template<> struct DefaultArg<unsigned char> : public IntArg {};
1178 template<> struct DefaultArg<signed char> : public IntArg {};
1179 template<> struct DefaultArg<char> : public IntArg {};
1180 template<> struct DefaultArg<unsigned short> : public IntArg {};
1181 template<> struct DefaultArg<short> : public IntArg {};
1182 template<> struct DefaultArg<unsigned int> : public IntArg {};
1183 template<> struct DefaultArg<int> : public IntArg {};
1184 template<> struct DefaultArg<unsigned long> : public IntArg {};
1185 template<> struct DefaultArg<long> : public IntArg {};
1186 #if HAVE_LONG_LONG
1187 template<> struct DefaultArg<unsigned long long> : public IntArg {};
1188 template<> struct DefaultArg<long long> : public IntArg {};
1189 #endif
1190
1191
1192 /** @class FixedPointArg
1193 @brief Parser class for fixed-point numbers with @a b bits of fraction. */
1194 class FixedPointArg : public NumArg { public:
FixedPointArg(int b,int exponent=0)1195 explicit FixedPointArg(int b, int exponent = 0)
1196 : fraction_bits(b), exponent_delta(exponent) {
1197 }
1198 inline bool parse_saturating(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1199 bool parse(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1200 bool parse_saturating(const String &str, int32_t &result, const ArgContext &args = blank_args);
1201 bool parse(const String &str, int32_t &result, const ArgContext &args = blank_args);
1202 int fraction_bits;
1203 int exponent_delta;
1204 int status;
1205 private:
1206 bool underparse(const String &str, bool is_signed, uint32_t &result);
1207 };
1208
1209 inline bool
parse_saturating(const String & str,uint32_t & result,const ArgContext &)1210 FixedPointArg::parse_saturating(const String &str, uint32_t &result, const ArgContext &)
1211 {
1212 return underparse(str, false, result);
1213 }
1214
1215 /** @class DecimalFixedPointArg
1216 @brief Parser class for fixed-point numbers with @a d decimal digits of fraction. */
1217 class DecimalFixedPointArg : public NumArg { public:
DecimalFixedPointArg(int d,int exponent=0)1218 DecimalFixedPointArg(int d, int exponent = 0)
1219 : fraction_digits(d), exponent_delta(exponent) {
1220 }
1221 inline bool parse_saturating(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1222 bool parse(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1223 bool parse_saturating(const String &str, int32_t &result, const ArgContext &args = blank_args);
1224 bool parse(const String &str, int32_t &result, const ArgContext &args = blank_args);
1225 bool parse_saturating(const String &str, uint32_t &iresult, uint32_t &fresult, const ArgContext &args = blank_args);
1226 bool parse(const String &str, uint32_t &iresult, uint32_t &fresult, const ArgContext &args = blank_args);
1227 int fraction_digits;
1228 int exponent_delta;
1229 int status;
1230 private:
1231 bool underparse(const String &str, bool is_signed, uint32_t &result);
1232 };
1233
1234 inline bool
parse_saturating(const String & str,uint32_t & result,const ArgContext &)1235 DecimalFixedPointArg::parse_saturating(const String &str, uint32_t &result, const ArgContext &)
1236 {
1237 return underparse(str, false, result);
1238 }
1239
1240
1241 #if HAVE_FLOAT_TYPES
1242 /** @class DoubleArg
1243 @brief Parser class for double-precision floating point numbers. */
1244 class DoubleArg : public NumArg { public:
DoubleArg()1245 DoubleArg() {
1246 }
1247 bool parse(const String &str, double &result, const ArgContext &args = blank_args);
1248 int status;
1249 };
1250
1251 template<> struct DefaultArg<double> : public DoubleArg {};
1252 #endif
1253
1254
1255 /** @class BoolArg
1256 @brief Parser class for booleans. */
1257 class BoolArg { public:
1258 static bool parse(const String &str, bool &result, const ArgContext &args = blank_args);
unparse(bool x)1259 static String unparse(bool x) {
1260 return String(x);
1261 }
1262 };
1263
1264 template<> struct DefaultArg<bool> : public BoolArg {};
1265
1266
1267 class UnitArg { public:
UnitArg(const char * unit_def,const char * prefix_chars_def)1268 explicit UnitArg(const char *unit_def, const char *prefix_chars_def)
1269 : units_(reinterpret_cast<const unsigned char *>(unit_def)),
1270 prefix_chars_(reinterpret_cast<const unsigned char *>(prefix_chars_def)) {
1271 }
1272 const char *parse(const char *begin, const char *end, int &power, int &factor) const;
1273 private:
1274 const unsigned char *units_;
1275 const unsigned char *prefix_chars_;
1276 void check_units();
1277 };
1278
1279
1280 /** @class BandwidthArg
1281 @brief Parser class for bandwidth specifications.
1282
1283 Handles suffixes such as "Gbps", "k", etc. */
1284 class BandwidthArg : public NumArg { public:
1285 bool parse(const String &str, uint32_t &result, const ArgContext & = blank_args);
1286 static String unparse(uint32_t x);
1287 int status;
1288 };
1289
1290
1291 #if !CLICK_TOOL
1292 /** @class AnnoArg
1293 @brief Parser class for annotation specifications. */
1294 class AnnoArg { public:
AnnoArg(int s)1295 AnnoArg(int s)
1296 : size(s) {
1297 }
1298 bool parse(const String &str, int &result, const ArgContext &args = blank_args);
1299 private:
1300 int size;
1301 };
1302 #endif
1303
1304
1305 /** @class SecondsArg
1306 @brief Parser class for seconds and powers thereof.
1307
1308 The @a d argument is the number of digits of fraction to parse.
1309 For example, to parse milliseconds, use SecondsArg(3). */
1310 class SecondsArg : public NumArg { public:
SecondsArg(int d=0)1311 SecondsArg(int d = 0)
1312 : fraction_digits(d) {
1313 }
1314 bool parse_saturating(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1315 bool parse(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1316 #if HAVE_FLOAT_TYPES
1317 bool parse(const String &str, double &result, const ArgContext &args = blank_args);
1318 #endif
1319 int fraction_digits;
1320 int status;
1321 };
1322
1323
1324 /** @class AnyArg
1325 @brief Parser class that accepts any argument. */
1326 class AnyArg { public:
parse(const String &,const ArgContext &=blank_args)1327 static bool parse(const String &, const ArgContext & = blank_args) {
1328 return true;
1329 }
parse(const String & str,String & result,const ArgContext &=blank_args)1330 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1331 result = str;
1332 return true;
1333 }
parse(const String & str,Vector<String> & result,const ArgContext &=blank_args)1334 static bool parse(const String &str, Vector<String> &result, const ArgContext & = blank_args) {
1335 result.push_back(str);
1336 return true;
1337 }
1338 };
1339
1340
1341 bool cp_string(const String &str, String *result, String *rest);
1342
1343 /** @class StringArg
1344 @brief Parser class for possibly-quoted strings. */
1345 class StringArg { public:
parse(const String & str,String & result,const ArgContext &=blank_args)1346 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1347 return cp_string(str, &result, 0);
1348 }
1349 };
1350
1351 template<> struct DefaultArg<String> : public StringArg {};
1352
1353
1354 bool cp_keyword(const String &str, String *result, String *rest);
1355
1356 /** @class KeywordArg
1357 @brief Parser class for keywords. */
1358 class KeywordArg { public:
parse(const String & str,String & result,const ArgContext &=blank_args)1359 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1360 return cp_keyword(str, &result, 0);
1361 }
1362 };
1363
1364
1365 bool cp_word(const String &str, String *result, String *rest);
1366
1367 /** @class KeywordArg
1368 @brief Parser class for words. */
1369 class WordArg { public:
parse(const String & str,String & result,const ArgContext &=blank_args)1370 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1371 return cp_word(str, &result, 0);
1372 }
1373 };
1374
1375
1376 #if CLICK_USERLEVEL || CLICK_TOOL
1377 /** @class FilenameArg
1378 @brief Parser class for filenames. */
1379 class FilenameArg { public:
1380 static bool parse(const String &str, String &result, const ArgContext &args = blank_args);
1381 };
1382 #endif
1383
1384
1385 #if !CLICK_TOOL
1386 /** @class ElementArg
1387 @brief Parser class for elements. */
1388 class ElementArg { public:
1389 static bool parse(const String &str, Element *&result, const ArgContext &args);
1390 };
1391
1392 template<> struct DefaultArg<Element *> : public ElementArg {};
1393
1394 /** @class ElementCastArg
1395 @brief Parser class for elements of type @a t. */
1396 class ElementCastArg { public:
ElementCastArg(const char * t)1397 ElementCastArg(const char *t)
1398 : type(t) {
1399 }
1400 bool parse(const String &str, Element *&result, const ArgContext &args);
parse(const String & str,T * & result,const ArgContext & args)1401 template<typename T> bool parse(const String &str, T *&result, const ArgContext &args) {
1402 return parse(str, reinterpret_cast<Element *&>(result), args);
1403 }
1404 const char *type;
1405 };
1406 #endif
1407
1408 CLICK_ENDDECLS
1409 #endif
1410