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