Click
Loading...
Searching...
No Matches
args.hh
1// -*- c-basic-offset: 4; related-file-name: "../../lib/args.cc" -*-
2#ifndef CLICK_ARGS_HH
3#define CLICK_ARGS_HH
5#include <click/vector.hh>
6#include <click/string.hh>
7#include <click/confparse.hh>
8#include <click/timestamp.hh>
9#include <click/bitvector.hh>
10#include <type_traits>
11#if CLICK_BSDMODULE
12# include <machine/stdarg.h>
13#else
14# include <stdarg.h>
15#endif
16CLICK_DECLS
17class Element;
18class ErrorHandler;
19
31class ArgContext { public:
32
36 : _errh(errh), _arg_keyword(0), _read_status(false) {
37#if !CLICK_TOOL
38 _context = 0;
39#endif
40 }
41
42#if !CLICK_TOOL
47 : _context(context), _errh(errh), _arg_keyword(0), _read_status(false) {
48 }
49
51 const Element *context() const {
52 return _context;
53 }
54#endif
55
57 ErrorHandler *errh() const {
58 return _errh;
59 }
60
64 String error_prefix() const;
65
67 void error(const char *fmt, ...) const;
68
70 void warning(const char *fmt, ...) const;
71
73 void message(const char *fmt, ...) const;
74
75 void xmessage(const String &anno, const String &str) const;
76 void xmessage(const String &anno, const char *fmt, va_list val) const;
77
78 protected:
79
80#if !CLICK_TOOL
81 const Element *_context;
82#endif
83 ErrorHandler *_errh;
84 const char *_arg_keyword;
85 mutable bool _read_status;
86
87};
88
89
91template <typename T> struct Args_has_enable_direct_parse {
92 private:
93 template <typename X> static char test(typename X::enable_direct_parse *);
94 template <typename> static int test(...);
95 public:
96 enum { value = (sizeof(test<T>(0)) == 1) };
97};
98template <typename P, bool direct = Args_has_enable_direct_parse<P>::value>
99struct Args_parse_helper;
100template <typename P> struct Args_parse_helper<P, false> {
101 template <typename T, typename A>
102 static inline T *slot(T &variable, A &args) {
103 return args.slot(variable);
104 }
105 template <typename T, typename A>
106 static inline T *initialized_slot(T &variable, A &args) {
107 return args.initialized_slot(variable);
108 }
109 template <typename T, typename A>
110 static inline bool parse(P parser, const String &str, T &s, A &args) {
111 return parser.parse(str, s, args);
112 }
113 template <typename T1, typename T2, typename A>
114 static inline bool parse(P parser, const String &str, T1 &s1, T2 &s2, A &args) {
115 return parser.parse(str, s1, s2, args);
116 }
117};
118template <typename P> struct Args_parse_helper<P, true> {
119 template <typename T, typename A>
120 static inline T *slot(T &variable, A &) {
121 return &variable;
122 }
123 template <typename T, typename A>
124 static inline T *initialized_slot(T &variable, A &) {
125 return &variable;
126 }
127 template <typename T, typename A>
128 static inline bool parse(P parser, const String &str, T &s, A &args) {
129 return parser.direct_parse(str, s, args);
130 }
131 template <typename T1, typename T2, typename A>
132 static inline bool parse(P parser, const String &str, T1 &s1, T2 &s2, A &args) {
133 return parser.direct_parse(str, s1, s2, args);
134 }
135};
249class Args : public ArgContext {
250 struct Slot;
251
252 public:
253
256 Args(ErrorHandler *errh = 0);
257
261 Args(const Vector<String> &conf, ErrorHandler *errh = 0);
262
263#if !CLICK_TOOL
267 Args(const Element *context, ErrorHandler *errh = 0);
268
273 Args(const Vector<String> &conf, const Element *context,
274 ErrorHandler *errh = 0);
275#endif
276
277
278
281 Args(const Args &x);
282
283 ~Args();
284
287 Args &operator=(const Args &x);
288
289
291 bool empty() const {
292 return (!_conf || !_conf->size()) && !_slots && _simple_slotbuf[0] == 0;
293 }
294
296 bool results_empty() const {
297 return !_slots && _simple_slotbuf[0] == 0;
298 }
299
300
304 if (_conf)
305 _conf->clear();
306 _kwpos.clear();
307 return *this;
308 }
309
315 Args &bind(Vector<String> &conf);
316
319 Args &push_back(const String &arg);
320
323 template<typename Iter> Args &push_back(Iter begin, Iter end) {
324 while (begin != end) {
325 push_back(*begin);
326 ++begin;
327 }
328 return *this;
329 }
330
333 Args &push_back_words(const String &str);
334
337 Args &push_back_args(const String &str);
338
353 reset_from(0);
354 return *this;
355 }
356
357
358 static constexpr int mandatory = 1;
359 static constexpr int positional = 2;
360 static constexpr int deprecated = 4;
361 static constexpr int firstmatch = 8;
362
370 template <typename T>
371 Args &read(const char *keyword, T &x) {
372 return read(keyword, 0, x);
373 }
374 template <typename T>
375 Args &read_m(const char *keyword, T &x) {
376 return read(keyword, mandatory, x);
377 }
378 template <typename T>
379 Args &read_p(const char *keyword, T &x) {
380 return read(keyword, positional, x);
381 }
382 template <typename T>
383 Args &read_mp(const char *keyword, T &x) {
384 return read(keyword, mandatory | positional, x);
385 }
386 template <typename T>
387 Args &read(const char *keyword, int flags, T &x) {
388 args_base_read(this, keyword, flags, x);
389 return *this;
390 }
391
402 template <typename T, typename V>
403 Args &read_or_set(const char *keyword, T &x, const V &default_value) {
404 return read_or_set(keyword, 0, x, default_value);
405 }
406 template <typename T, typename V>
407 Args &read_or_set_p(const char *keyword, T &x, const V &default_value) {
408 return read_or_set(keyword, positional, x, default_value);
409 }
410 template <typename T, typename V>
411 Args &read_or_set(const char *keyword, int flags, T &x, const V &default_value) {
412 args_base_read_or_set(this, keyword, flags, x, default_value);
413 return *this;
414 }
415
419 Args &validate(const char *keyword, bool present=false) {
420 Slot *slot_status;
421 String str = find(keyword, 0, slot_status);
422 if (str && !present) {
423 printf("A value was given for %s, but it was not given at time of devirtualization.\n", keyword);
424 assert(false);
425 }
426 return *this;
427 }
428
429 template <typename T>
430 Args &validate(const char *keyword, T &x, const char *static_value) {
431 DefaultArg<T> p = DefaultArg<T>();
432 T v;
433 p.parse(static_value, v);
434 return validate(keyword, x, v);
435 }
436
437 template <typename T, typename V>
438 Args &validate(const char *keyword, T &x, const V &static_value) {
439 Slot *slot_status;
440 String str = find(keyword, 0, slot_status);
441 if (!str) {
442 x = static_value;
443 return *this;
444 } else {
445 T *s = Args_parse_helper<DefaultArg<T> >::slot(x, *this);
446 postparse(s && (str ? Args_parse_helper<DefaultArg<T> >::parse(DefaultArg<T>(), str, *s, *this) : (*s = static_value, true)), slot_status);
447 if (*s != static_value) {
448 click_chatter("%s is not the expected value", keyword);
449 if (std::is_convertible<T,char *>::value) {
450 click_chatter("Given %s", x);
451 }
452 if (std::is_convertible<V,char *>::value) {
453 click_chatter("Given %s", static_value);
454 }
455 assert(*s == static_value);
456 }
457 }
458 return *this;
459 }
460
461
462 template <typename T, typename V>
463 Args &validate_f(const char *keyword, T &x, int flags, const V &static_value) {
464 //Todo : cleaner
465 Slot *slot_status;
466 String str = find(keyword, flags, slot_status);
467 if (!str) {
468 return *this;
469 } else {
470 T *s = Args_parse_helper<DefaultArg<T> >::slot(x, *this);
471 postparse(s && (str ? Args_parse_helper<DefaultArg<T> >::parse(DefaultArg<T>(), str, *s, *this) : (*s = static_value, true)), slot_status);
472 assert(*s == static_value);
473 }
474 return *this;
475 }
476
477 template <typename T, typename V>
478 Args &validate_p(const char *keyword, T &x, const V &static_value) {
479 return validate_f(keyword, x, positional, static_value);
480 }
481
482 template <typename T, typename V>
483 Args &validate_mp(const char *keyword, T &x, const V &static_value) {
484 return validate_f(keyword, x, positional | mandatory, static_value);
485 }
486
487 template <typename T>
488 Args &validate_p(const char *keyword, T &x, const char *static_value) {
489 DefaultArg<T> p = DefaultArg<T>();
490 T v;
491 p.parse(static_value, v);
492 return validate_f(keyword, x, positional, v);
493 }
494
495 template <typename T>
496 Args &validate_mp(const char *keyword, T &x, const char *static_value) {
497 DefaultArg<T> p = DefaultArg<T>();
498 T v;
499 p.parse(static_value, v);
500 return validate_f(keyword, x, positional | mandatory, v);
501 }
502
503
512 template <typename P, typename T>
513 Args &read(const char *keyword, P parser, T &x) {
514 return read(keyword, 0, parser, x);
515 }
516 template <typename P, typename T>
517 Args &read_m(const char *keyword, P parser, T &x) {
518 return read(keyword, mandatory, parser, x);
519 }
520 template <typename P, typename T>
521 Args &read_p(const char *keyword, P parser, T &x) {
522 return read(keyword, positional, parser, x);
523 }
524 template <typename P, typename T>
525 Args &read_mp(const char *keyword, P parser, T &x) {
526 return read(keyword, mandatory | positional, parser, x);
527 }
528 template <typename P, typename T>
529 Args &read(const char *keyword, int flags, P parser, T &x) {
530 args_base_read(this, keyword, flags, parser, x);
531 return *this;
532 }
533
545 template <typename P, typename T, typename V>
546 Args &read_or_set(const char *keyword, P parser, T &x, const V &default_value) {
547 return read_or_set(keyword, 0, parser, x, default_value);
548 }
549 template <typename P, typename T, typename V>
550 Args &read_or_set_p(const char *keyword, P parser, T &x, const V &default_value) {
551 return read_or_set(keyword, positional, parser, x, default_value);
552 }
553 template <typename P, typename T, typename V>
554 Args &read_or_set(const char *keyword, int flags, P parser, T &x, const V &default_value) {
555 args_base_read_or_set(this, keyword, flags, parser, x, default_value);
556 return *this;
557 }
558
568 template<typename P, typename T1, typename T2>
569 Args &read(const char *keyword, P parser, T1 &x1, T2 &x2) {
570 return read(keyword, 0, parser, x1, x2);
571 }
572 template<typename P, typename T1, typename T2>
573 Args &read_m(const char *keyword, P parser, T1 &x1, T2 &x2) {
574 return read(keyword, mandatory, parser, x1, x2);
575 }
576 template<typename P, typename T1, typename T2>
577 Args &read_p(const char *keyword, P parser, T1 &x1, T2 &x2) {
578 return read(keyword, positional, parser, x1, x2);
579 }
580 template<typename P, typename T1, typename T2>
581 Args &read_mp(const char *keyword, P parser, T1 &x1, T2 &x2) {
582 return read(keyword, mandatory | positional, parser, x1, x2);
583 }
584 template<typename P, typename T1, typename T2>
585 Args &read(const char *keyword, int flags, P parser, T1 &x1, T2 &x2) {
586 args_base_read(this, keyword, flags, parser, x1, x2);
587 return *this;
588 }
589
596 template <typename P>
597 Args &read_with(const char *keyword, P parser) {
598 return read_with(keyword, 0, parser);
599 }
600 template <typename P>
601 Args &read_m_with(const char *keyword, P parser) {
602 return read_with(keyword, mandatory, parser);
603 }
604 template <typename P>
605 Args &read_p_with(const char *keyword, P parser) {
606 return read_with(keyword, positional, parser);
607 }
608 template <typename P>
609 Args &read_mp_with(const char *keyword, P parser) {
610 return read_with(keyword, mandatory | positional, parser);
611 }
612 template <typename P>
613 Args &read_with(const char *keyword, int flags, P parser) {
614 args_base_read_with(this, keyword, flags, parser);
615 return *this;
616 }
617
628 template <typename P, typename T>
629 Args &read_with(const char *keyword, P parser, T &x) {
630 return read(keyword, parser, x);
631 }
632 template <typename P, typename T>
633 Args &read_m_with(const char *keyword, P parser, T &x) {
634 return read_m(keyword, parser, x);
635 }
636 template <typename P, typename T>
637 Args &read_p_with(const char *keyword, P parser, T &x) {
638 return read_p(keyword, parser, x);
639 }
640 template <typename P, typename T>
641 Args &read_mp_with(const char *keyword, P parser, T &x) {
642 return read_mp(keyword, parser, x);
643 }
644 template <typename P, typename T>
645 Args &read_with(const char *keyword, int flags, P parser, T &x) {
646 return read(keyword, flags, parser, x);
647 }
648
658 template <typename P>
659 Args &read_all_with(const char *keyword, P parser) {
660 return read_all_with(keyword, 0, parser);
661 }
662 template <typename P>
663 Args &read_all_with(const char *keyword, int flags, P parser) {
664 args_base_read_all_with(this, keyword, flags | firstmatch, parser);
665 return *this;
666 }
667
679 template <typename P, typename T>
680 Args &read_all_with(const char *keyword, P parser, T &x) {
681 return read_all_with(keyword, 0, parser, x);
682 }
683 template <typename P, typename T>
684 Args &read_all_with(const char *keyword, int flags, P parser, T &x) {
685 args_base_read_all_with(this, keyword, flags | firstmatch, parser, x);
686 return *this;
687 }
688
701 template <typename P, typename T>
702 Args &read_all(const char *keyword, P parser, Vector<T> &x) {
703 return read_all(keyword, 0, parser, x);
704 }
705 template <typename T>
706 Args &read_all(const char *keyword, Vector<T> &x) {
707 return read_all(keyword, 0, DefaultArg<T>(), x);
708 }
709 template <typename P, typename T>
710 Args &read_all(const char *keyword, int flags, P parser, Vector<T> &x) {
711 args_base_read_all(this, keyword, flags | firstmatch, parser, x);
712 return *this;
713 }
714 template <typename P, typename T>
715 Args &read_all(const char *keyword, int flags, Vector<T> &x) {
716 return read_all(keyword, flags, DefaultArg<T>(), x);
717 }
718
719
721 bool status() const {
722 return _status;
723 }
726 Args &status(bool &x) {
727 x = _status;
728 return *this;
729 }
731 const Args &status(bool &x) const {
732 x = _status;
733 return *this;
734 }
735
739 bool read_status() const {
740 return _read_status;
741 }
745 Args &read_status(bool &x) {
746 x = _read_status;
747 return *this;
748 }
750 const Args &read_status(bool &x) const {
751 x = _read_status;
752 return *this;
753 }
754
755
757 Args &strip();
758
765 int execute();
766
774 int consume();
775
783 int complete();
784
785
790 template <typename T>
791 T *slot(T &x) {
793 return reinterpret_cast<T *>(simple_slot(&x, sizeof(T)));
794 else
795 return complex_slot(x);
796 }
797
801 template <typename T>
803 T *s = slot(x);
805 *s = T();
806 return s;
807 }
808
811 template <typename T, typename V>
812 Args &set(T &x, const V &value) {
813 if (T *s = slot(x))
814 *s = value;
815 return *this;
816 }
817
818
820 template<typename T>
821 void base_read(const char *keyword, int flags, T &variable) {
822 Slot *slot_status;
823 if (String str = find(keyword, flags, slot_status)) {
824 T *s = Args_parse_helper<DefaultArg<T> >::slot(variable, *this);
825 postparse(s && Args_parse_helper<DefaultArg<T> >::parse(DefaultArg<T>(), str, *s, *this), slot_status);
826 }
827 }
828
829 template<typename T, typename V>
830 void base_read_or_set(const char *keyword, int flags, T &variable, const V &value) {
831 Slot *slot_status;
832 String str = find(keyword, flags, slot_status);
833 T *s = Args_parse_helper<DefaultArg<T> >::slot(variable, *this);
834 postparse(s && (str ? Args_parse_helper<DefaultArg<T> >::parse(DefaultArg<T>(), str, *s, *this) : (*s = value, true)), slot_status);
835 }
836
837 template<typename P, typename T>
838 void base_read(const char *keyword, int flags, P parser, T &variable) {
839 Slot *slot_status;
840 if (String str = find(keyword, flags, slot_status)) {
841 T *s = Args_parse_helper<P>::slot(variable, *this);
842 postparse(s && Args_parse_helper<P>::parse(parser, str, *s, *this), slot_status);
843 }
844 }
845
846 template<typename T, typename P, typename V>
847 void base_read_or_set(const char *keyword, int flags, P parser, T &variable, const V &value) {
848 Slot *slot_status;
849 String str = find(keyword, flags, slot_status);
850 T *s = Args_parse_helper<P>::slot(variable, *this);
851 postparse(s && (str ? Args_parse_helper<P>::parse(parser, str, *s, *this) : (*s = value, true)), slot_status);
852 }
853
854 template<typename P, typename T1, typename T2>
855 void base_read(const char *keyword, int flags,
856 P parser, T1 &variable1, T2 &variable2) {
857 Slot *slot_status;
858 if (String str = find(keyword, flags, slot_status)) {
859 T1 *s1 = Args_parse_helper<P>::slot(variable1, *this);
860 T2 *s2 = Args_parse_helper<P>::slot(variable2, *this);
861 postparse(s1 && s2 && Args_parse_helper<P>::parse(parser, str, *s1, *s2, *this), slot_status);
862 }
863 }
864
865 template<typename P>
866 void base_read_with(const char *keyword, int flags, P parser) {
867 Slot *slot_status;
868 if (String str = find(keyword, flags, slot_status))
869 postparse(parser.parse(str, *this), slot_status);
870 }
871
872 template<typename P>
873 void base_read_all_with(const char *keyword, int flags, P parser) {
874 Slot *slot_status;
875 int read_status = -1;
876 while (String str = find(keyword, flags, slot_status)) {
877 postparse(parser.parse(str, *this), slot_status);
878 read_status = (read_status != 0) && _read_status;
879 flags &= ~mandatory;
880 }
881 _read_status = (read_status == 1);
882 }
883
884 template<typename P, typename T>
885 void base_read_all_with(const char *keyword, int flags, P parser, T &variable) {
886 Slot *slot_status;
887 int read_status = -1;
888 T *s = Args_parse_helper<P>::initialized_slot(variable, *this);
889 while (String str = find(keyword, flags, slot_status)) {
890 postparse(s && Args_parse_helper<P>::parse(parser, str, *s, *this), slot_status);
891 read_status = (read_status != 0) && _read_status;
892 flags &= ~mandatory;
893 }
894 _read_status = (read_status == 1);
895 }
896
897 template<typename P, typename T>
898 void base_read_all(const char *keyword, int flags, P parser, Vector<T> &variable) {
899 Slot *slot_status;
900 int read_status = -1;
901 Vector<T> *s = slot(variable);
902 while (String str = find(keyword, flags, slot_status)) {
903 T sx = T();
904 postparse(parser.parse(str, sx, *this), slot_status);
905 if (_read_status)
906 s->push_back(sx);
907 read_status = (read_status != 0) && _read_status;
908 flags &= ~mandatory;
909 }
910 _read_status = (read_status == 1);
911 }
914 private:
915
916 struct Slot {
917 Slot() {
918 }
919 virtual ~Slot() {
920 }
921 virtual void store() = 0;
922 Slot *_next;
923 };
924
925 struct BytesSlot : public Slot {
926 BytesSlot(void *ptr, size_t size)
927 : _ptr(ptr), _slot(new char[size]), _size(size) {
928 }
929 ~BytesSlot() {
930 delete[] _slot;
931 }
932 void store() {
933 memcpy(_ptr, _slot, _size);
934 }
935 void *_ptr;
936 char *_slot;
937 size_t _size;
938 };
939
940 template<typename T>
941 struct SlotT : public Slot {
942 SlotT(T *ptr)
943 : _ptr(ptr) {
944 }
945 void store() {
946 assign_consume(*_ptr, _slot);
947 }
948 T *_ptr;
949 T _slot;
950 };
951
952 enum {
953#if SIZEOF_VOID_P == 4
954 simple_slotbuf_size = 24
955#else
956 simple_slotbuf_size = 48
957#endif
958 };
959
960#if !CLICK_DEBUG_ARGS_USAGE
961 bool _my_conf;
962#else
963 bool _my_conf : 1;
964 bool _consumed : 1;
965#endif
966 bool _status;
967 uint8_t _simple_slotpos;
968
969 Vector<String> *_conf;
970 Vector<int> _kwpos;
971
972 Slot *_slots;
973 uint8_t _simple_slotbuf[simple_slotbuf_size];
974
975 inline void initialize(const Vector<String> *conf);
976 void reset_from(int i);
977
978 String find(const char *keyword, int flags, Slot *&slot_status);
979 void postparse(bool ok, Slot *slot_status);
980 void check_complete();
981
982 static inline int simple_slot_size(int size);
983 inline void simple_slot_info(int offset, int size,
984 void *&slot, void **&pointer);
985 void *simple_slot(void *data, size_t size);
986 template<typename T> T *complex_slot(T &variable);
987
988};
989
990extern const ArgContext blank_args;
991
992
993template<typename T>
994struct DefaultArg {
995};
996
997template<typename T>
998T *Args::complex_slot(T &variable)
999{
1000 if (SlotT<T> *s = new SlotT<T>(&variable)) {
1001 s->_next = _slots;
1002 _slots = s;
1003 return &s->_slot;
1004 } else {
1005 error("out of memory");
1006 return 0;
1007 }
1008}
1009
1010
1012/* These functions are here because some GCC versions ignore noinline
1013 attributes on member function templates. */
1014template<typename T>
1015void args_base_read(Args *args, const char *keyword, int flags, T &variable)
1016 CLICK_NOINLINE;
1017template<typename T>
1018void args_base_read(Args *args, const char *keyword, int flags, T &variable)
1019{
1020 args->base_read(keyword, flags, variable);
1021}
1022
1023template<typename T, typename V>
1024void args_base_read_or_set(Args *args, const char *keyword, int flags,
1025 T &variable, const V &value) CLICK_NOINLINE;
1026template<typename T, typename V>
1027void args_base_read_or_set(Args *args, const char *keyword, int flags,
1028 T &variable, const V &value)
1029{
1030 args->base_read_or_set(keyword, flags, variable, value);
1031}
1032
1033template<typename P, typename T>
1034void args_base_read(Args *args, const char *keyword, int flags,
1035 P parser, T &variable) CLICK_NOINLINE;
1036template<typename P, typename T>
1037void args_base_read(Args *args, const char *keyword, int flags,
1038 P parser, T &variable)
1039{
1040 args->base_read(keyword, flags, parser, variable);
1041}
1042
1043template<typename P, typename T, typename V>
1044void args_base_read_or_set(Args *args, const char *keyword, int flags,
1045 P parser, T &variable, const V &value) CLICK_NOINLINE;
1046template<typename P, typename T, typename V>
1047void args_base_read_or_set(Args *args, const char *keyword, int flags,
1048 P parser, T &variable, const V &value)
1049{
1050 args->base_read_or_set(keyword, flags, parser, variable, value);
1051}
1052
1053template<typename P, typename T1, typename T2>
1054void args_base_read(Args *args, const char *keyword, int flags,
1055 P parser, T1 &variable1, T2 &variable2) CLICK_NOINLINE;
1056template<typename P, typename T1, typename T2>
1057void args_base_read(Args *args, const char *keyword, int flags,
1058 P parser, T1 &variable1, T2 &variable2)
1059{
1060 args->base_read(keyword, flags, parser, variable1, variable2);
1061}
1062
1063template<typename P>
1064void args_base_read_with(Args *args, const char *keyword, int flags, P parser)
1065 CLICK_NOINLINE;
1066template<typename P>
1067void args_base_read_with(Args *args, const char *keyword, int flags, P parser)
1068{
1069 args->base_read_with(keyword, flags, parser);
1070}
1071
1072template<typename P>
1073void args_base_read_all_with(Args *args, const char *keyword, int flags, P parser)
1074 CLICK_NOINLINE;
1075template<typename P>
1076void args_base_read_all_with(Args *args, const char *keyword, int flags, P parser)
1077{
1078 args->base_read_all_with(keyword, flags, parser);
1079}
1080
1081template<typename P, typename T>
1082void args_base_read_all_with(Args *args, const char *keyword, int flags,
1083 P parser, T &variable) CLICK_NOINLINE;
1084template<typename P, typename T>
1085void args_base_read_all_with(Args *args, const char *keyword, int flags,
1086 P parser, T &variable)
1087{
1088 args->base_read_all_with(keyword, flags, parser, variable);
1089}
1090
1091template <typename P, typename T>
1092void args_base_read_all(Args *args, const char *keyword, int flags,
1093 P parser, Vector<T> &variable) CLICK_NOINLINE;
1094template <typename P, typename T>
1095void args_base_read_all(Args *args, const char *keyword, int flags,
1096 P parser, Vector<T> &variable)
1097{
1098 args->base_read_all(keyword, flags, parser, variable);
1099}
1103class NumArg { public:
1104 enum {
1105 status_ok = 0,
1106 status_inval = EINVAL,
1107 status_range = ERANGE,
1108#if defined(ENOTSUP)
1109 status_notsup = ENOTSUP,
1110#elif defined(ENOTSUPP)
1111 status_notsup = ENOTSUPP,
1112#else
1113 status_notsup,
1114#endif
1115 status_unitless
1116 };
1117};
1118
1119
1130class IntArg : public NumArg { public:
1131
1132 typedef uint32_t limb_type;
1133
1134 IntArg(int b = 0)
1135 : base(b) {
1136 }
1137
1138 const char *parse(const char *begin, const char *end,
1139 bool is_signed, int size,
1140 limb_type *value, int nlimb);
1141
1142 template<typename V>
1143 bool parse_saturating(const String &str, V &result, const ArgContext &args = blank_args) {
1144 constexpr bool is_signed = integer_traits<V>::is_signed;
1145 constexpr int nlimb = int((sizeof(V) + sizeof(limb_type) - 1) / sizeof(limb_type));
1146 limb_type x[nlimb];
1147 if (parse(str.begin(), str.end(), is_signed, int(sizeof(V)), x, nlimb)
1148 != str.end())
1149 status = status_inval;
1150 if (status && status != status_range) {
1151 args.error("invalid number");
1152 return false;
1153 }
1154 typedef typename make_unsigned<V>::type unsigned_v_type;
1155 extract_integer(x, reinterpret_cast<unsigned_v_type &>(result));
1156 return true;
1157 }
1158
1159 template<typename V>
1160 String unparse(const V &v) {
1161 return String(v);
1162 }
1163 template<typename V>
1164 bool parse(const String &str, V &result, const ArgContext &args = blank_args) {
1165 V x;
1166 if (!parse_saturating(str, x, args)
1167 || (status && status != status_range))
1168 return false;
1169 else if (status == status_range) {
1170 range_error(args, integer_traits<V>::is_signed,
1171 click_int_large_t(x));
1172 return false;
1173 } else {
1174 result = x;
1175 return true;
1176 }
1177 }
1178
1179 int base;
1180 int status;
1181
1182 protected:
1183
1184 static const char *span(const char *begin, const char *end,
1185 bool is_signed, int &b);
1186 void range_error(const ArgContext &args, bool is_signed,
1187 click_int_large_t value);
1188
1189};
1190
1198class SaturatingIntArg : public IntArg { public:
1199 SaturatingIntArg(int b = 0)
1200 : IntArg(b) {
1201 }
1202
1203 template<typename V>
1204 bool parse(const String &str, V &result, const ArgContext &args = blank_args) {
1205 return parse_saturating(str, result, args);
1206 }
1207};
1208
1216class BoundedIntArg : public IntArg { public:
1217 template <typename T>
1218 BoundedIntArg(T min_value, T max_value, int b = 0)
1219 : IntArg(b), min_value(min_value), max_value(max_value) {
1220 static_assert(integer_traits<T>::is_integral, "BoundedIntArg argument must be integral");
1221 is_signed = integer_traits<T>::is_signed;
1222 }
1223
1224 template <typename V>
1225 bool parse(const String &str, V &result, const ArgContext &args = blank_args) {
1226 V x;
1227 if (!IntArg::parse(str, x, args))
1228 return false;
1229 else if (!check_min(typename integer_traits<V>::max_type(x))) {
1230 range_error(args, is_signed, min_value);
1231 return false;
1232 } else if (!check_max(typename integer_traits<V>::max_type(x))) {
1233 range_error(args, is_signed, max_value);
1234 return false;
1235 } else {
1236 result = x;
1237 return true;
1238 }
1239 }
1240
1241 inline bool check_min(click_int_large_t x) const {
1242 if (is_signed)
1243 return x >= min_value;
1244 else
1245 return x >= 0 && click_uint_large_t(x) >= click_uint_large_t(min_value);
1246 }
1247 inline bool check_min(click_uint_large_t x) const {
1248 if (is_signed)
1249 return min_value < 0 || x >= click_uint_large_t(min_value);
1250 else
1251 return click_uint_large_t(x) >= click_uint_large_t(min_value);
1252 }
1253 inline bool check_max(click_int_large_t x) const {
1254 if (is_signed)
1255 return x <= max_value;
1256 else
1257 return x >= 0 && click_uint_large_t(x) <= click_uint_large_t(max_value);
1258 }
1259 inline bool check_max(click_uint_large_t x) const {
1260 if (is_signed)
1261 return max_value >= 0 && x <= click_uint_large_t(max_value);
1262 else
1263 return click_uint_large_t(x) <= click_uint_large_t(max_value);
1264 }
1265
1266 click_intmax_t min_value;
1267 click_intmax_t max_value;
1268 bool is_signed;
1269};
1270
1271template<> struct DefaultArg<unsigned char> : public IntArg {};
1272template<> struct DefaultArg<signed char> : public IntArg {};
1273template<> struct DefaultArg<char> : public IntArg {};
1274template<> struct DefaultArg<unsigned short> : public IntArg {};
1275template<> struct DefaultArg<short> : public IntArg {};
1276template<> struct DefaultArg<unsigned int> : public IntArg {};
1277template<> struct DefaultArg<int> : public IntArg {};
1278template<> struct DefaultArg<unsigned long> : public IntArg {};
1279template<> struct DefaultArg<long> : public IntArg {};
1280#if HAVE_LONG_LONG
1281template<> struct DefaultArg<unsigned long long> : public IntArg {};
1282template<> struct DefaultArg<long long> : public IntArg {};
1283#endif
1284
1285
1288class FixedPointArg : public NumArg { public:
1289 explicit FixedPointArg(int b, int exponent = 0)
1290 : fraction_bits(b), exponent_delta(exponent) {
1291 }
1292 inline bool parse_saturating(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1293 bool parse(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1294 bool parse_saturating(const String &str, int32_t &result, const ArgContext &args = blank_args);
1295 bool parse(const String &str, int32_t &result, const ArgContext &args = blank_args);
1296 int fraction_bits;
1297 int exponent_delta;
1298 int status;
1299 private:
1300 bool underparse(const String &str, bool is_signed, uint32_t &result);
1301};
1302
1303inline bool
1304FixedPointArg::parse_saturating(const String &str, uint32_t &result, const ArgContext &)
1305{
1306 return underparse(str, false, result);
1307}
1308
1311class DecimalFixedPointArg : public NumArg { public:
1312 DecimalFixedPointArg(int d, int exponent = 0)
1313 : fraction_digits(d), exponent_delta(exponent) {
1314 }
1315 inline bool parse_saturating(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1316 bool parse(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1317 bool parse_saturating(const String &str, int32_t &result, const ArgContext &args = blank_args);
1318 bool parse(const String &str, int32_t &result, const ArgContext &args = blank_args);
1319 bool parse_saturating(const String &str, uint32_t &iresult, uint32_t &fresult, const ArgContext &args = blank_args);
1320 bool parse(const String &str, uint32_t &iresult, uint32_t &fresult, const ArgContext &args = blank_args);
1321 int fraction_digits;
1322 int exponent_delta;
1323 int status;
1324 private:
1325 bool underparse(const String &str, bool is_signed, uint32_t &result);
1326};
1327
1328inline bool
1329DecimalFixedPointArg::parse_saturating(const String &str, uint32_t &result, const ArgContext &)
1330{
1331 return underparse(str, false, result);
1332}
1333
1334
1335#if HAVE_FLOAT_TYPES
1338class DoubleArg : public NumArg { public:
1339 DoubleArg() {
1340 }
1341 bool parse(const String &str, double &result, const ArgContext &args = blank_args);
1342 int status;
1343};
1344
1345template<> struct DefaultArg<double> : public DoubleArg {};
1346#endif
1347
1348
1351class BoolArg { public:
1352 static bool parse(const String &str, bool &result, const ArgContext &args = blank_args);
1353 static String unparse(bool x) {
1354 return String(x);
1355 }
1356};
1357
1358template<> struct DefaultArg<bool> : public BoolArg {};
1359
1360
1361class UnitArg { public:
1362 explicit UnitArg(const char *unit_def, const char *prefix_chars_def)
1363 : units_(reinterpret_cast<const unsigned char *>(unit_def)),
1364 prefix_chars_(reinterpret_cast<const unsigned char *>(prefix_chars_def)) {
1365 }
1366 const char *parse(const char *begin, const char *end, int &power, int &factor) const;
1367 private:
1368 const unsigned char *units_;
1369 const unsigned char *prefix_chars_;
1370 void check_units();
1371};
1372
1373
1378class BandwidthArg : public NumArg { public:
1379 bool parse(const String &str, uint64_t &result, const ArgContext & = blank_args);
1380 static String unparse(uint32_t x);
1381 int status;
1382};
1383
1384
1386class BitvectorArg { public:
1387 static bool parse(const String &str, Bitvector &result, const ArgContext & = blank_args) {
1388 if (!result.parse(str, 0, 64)) {
1389 blank_args.error("%s is not a bitvecotr",str.c_str());
1390 return false;
1391 }
1392 return true;
1393 }
1394};
1395
1396template<> struct DefaultArg<Bitvector> : public BitvectorArg {};
1397
1398
1399
1400#if !CLICK_TOOL
1403class AnnoArg { public:
1404 AnnoArg(int s)
1405 : size(s) {
1406 }
1407 bool parse(const String &str, int &result, const ArgContext &args = blank_args);
1408 private:
1409 int size;
1410};
1411#endif
1412
1413
1419class SecondsArg : public NumArg { public:
1420 SecondsArg(int d = 0)
1421 : fraction_digits(d) {
1422 }
1423 bool parse_saturating(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1424 bool parse(const String &str, uint32_t &result, const ArgContext &args = blank_args);
1425#if HAVE_FLOAT_TYPES
1426 bool parse(const String &str, double &result, const ArgContext &args = blank_args);
1427#endif
1428 int fraction_digits;
1429 int status;
1430};
1431
1432
1435class AnyArg { public:
1436 static bool parse(const String &, const ArgContext & = blank_args) {
1437 return true;
1438 }
1439 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1440 result = str;
1441 return true;
1442 }
1443 static bool parse(const String &str, Vector<String> &result, const ArgContext & = blank_args) {
1444 result.push_back(str);
1445 return true;
1446 }
1447};
1448
1449
1450bool cp_string(const String &str, String *result, String *rest);
1451
1454class StringArg { public:
1455 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1456 return cp_string(str, &result, 0);
1457 }
1458};
1459
1460template<> struct DefaultArg<String> : public StringArg {};
1461
1462
1463bool cp_keyword(const String &str, String *result, String *rest);
1464
1467class KeywordArg { public:
1468 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1469 return cp_keyword(str, &result, 0);
1470 }
1471};
1472
1473
1474bool cp_word(const String &str, String *result, String *rest);
1475
1478class WordArg { public:
1479 static bool parse(const String &str, String &result, const ArgContext & = blank_args) {
1480 return cp_word(str, &result, 0);
1481 }
1482};
1483
1484
1485#if CLICK_USERLEVEL || CLICK_TOOL
1488class FilenameArg { public:
1489 static bool parse(const String &str, String &result, const ArgContext &args = blank_args);
1490};
1491#endif
1492
1493
1494#if !CLICK_TOOL
1497class ElementArg { public:
1498 static bool parse(const String &str, Element *&result, const ArgContext &args);
1499};
1500
1501template<> struct DefaultArg<Element *> : public ElementArg {};
1502
1505class ElementCastArg { public:
1506 ElementCastArg(const char *t)
1507 : type(t) {
1508 }
1509 bool parse(const String &str, Element *&result, const ArgContext &args);
1510 template<typename T> bool parse(const String &str, T *&result, const ArgContext &args) {
1511 return parse(str, reinterpret_cast<Element *&>(result), args);
1512 }
1513 const char *type;
1514};
1515#endif
1516
1517CLICK_ENDDECLS
1518#endif
Click's bitvector class.
Parser class for annotation specifications.
Definition args.hh:1403
Parser class that accepts any argument.
Definition args.hh:1435
Argument context class.
Definition args.hh:31
void message(const char *fmt,...) const
Report a message for the current argument.
Definition args.cc:321
const Element * context() const
Return the element context.
Definition args.hh:51
ArgContext(const Element *context, ErrorHandler *errh=0)
Construct an argument context.
Definition args.hh:46
ArgContext(ErrorHandler *errh=0)
Construct an argument context.
Definition args.hh:35
void error(const char *fmt,...) const
Report a parse error for the current argument.
Definition args.cc:303
String error_prefix() const
Return a prefix string associated with the current argument.
Definition args.cc:297
ErrorHandler * errh() const
Return the associated error handler.
Definition args.hh:57
void warning(const char *fmt,...) const
Report a parse warning for the current argument.
Definition args.cc:312
Argument parser class.
Definition args.hh:249
Args & status(bool &x)
Set x to the current parse status.
Definition args.hh:726
static constexpr int firstmatch
read flag to take first matching argument
Definition args.hh:361
Args & strip()
Remove all arguments matched so far.
Definition args.cc:446
Args & read_or_set(const char *keyword, T &x, const V &default_value)
Read an argument using the default parser, or set it to a default value if the argument is was not su...
Definition args.hh:403
Args & read(const char *keyword, P parser, T &x)
Read an argument using a specified parser.
Definition args.hh:513
bool status() const
Return the current parse status.
Definition args.hh:721
Args & read(const char *keyword, T &x)
Read an argument using its type's default parser.
Definition args.hh:371
Args & push_back_args(const String &str)
Append the comma-separated arguments in str to this parser.
Definition args.cc:199
Args & read_all_with(const char *keyword, P parser)
Pass all matching arguments to a specified parser.
Definition args.hh:659
bool read_status() const
Return true iff the last read request succeeded.
Definition args.hh:739
T * initialized_slot(T &x)
Create and return a result slot for x.
Definition args.hh:802
const Args & read_status(bool &x) const
Definition args.hh:750
Args & read(const char *keyword, P parser, T1 &x1, T2 &x2)
Read an argument using a specified parser with two results.
Definition args.hh:569
static constexpr int deprecated
read flag for deprecated arguments
Definition args.hh:360
static constexpr int positional
read flag for positional arguments
Definition args.hh:359
Args & read_with(const char *keyword, P parser, T &x)
Pass an argument to a specified parser.
Definition args.hh:629
Args & push_back(Iter begin, Iter end)
Append arguments in the range [begin, end) to this parser.
Definition args.hh:323
Args & read_all_with(const char *keyword, P parser, T &x)
Pass all matching arguments to a specified parser.
Definition args.hh:680
Args & read_status(bool &x)
Set x to the success status of the last read request.
Definition args.hh:745
bool results_empty() const
Return true iff this parser has no results.
Definition args.hh:296
int consume()
Assign results and remove matched arguments.
Definition args.cc:500
T * slot(T &x)
Create and return a result slot for x.
Definition args.hh:791
Args & operator=(const Args &x)
Assign to a copy of x.
Definition args.cc:109
int complete()
Assign results if all arguments matched.
Definition args.cc:510
Args & bind(Vector< String > &conf)
Bind this parser's arguments to conf.
Definition args.cc:171
Args & read_or_set(const char *keyword, P parser, T &x, const V &default_value)
Read an argument using a specified parser, or set it to a default value if the argument is was not su...
Definition args.hh:546
Args & push_back(const String &arg)
Append argument arg to this parser.
Definition args.cc:184
Args & push_back_words(const String &str)
Append the space-separated words in str to this parser.
Definition args.cc:214
static constexpr int mandatory
read flag for mandatory arguments
Definition args.hh:358
Args & reset()
Reset the parse status for every argument.
Definition args.hh:352
int execute()
Assign results.
Definition args.cc:480
Args & read_with(const char *keyword, P parser)
Pass an argument to a specified parser.
Definition args.hh:597
bool empty() const
Return true iff this parser has no arguments or results.
Definition args.hh:291
Args & validate(const char *keyword, bool present=false)
Definition args.hh:419
const Args & status(bool &x) const
Definition args.hh:731
Args & read_all(const char *keyword, P parser, Vector< T > &x)
Pass all matching arguments to a specified parser.
Definition args.hh:702
Args & clear()
Remove all arguments.
Definition args.hh:303
Args & set(T &x, const V &value)
Add a result that assigns x to value.
Definition args.hh:812
Parser class for bandwidth specifications.
Definition args.hh:1378
Vector of bits.
Definition bitvector.hh:21
Parser class for booleans.
Definition args.hh:1351
Parser class for integers with explicit bounds.
Definition args.hh:1216
Parser class for fixed-point numbers with d decimal digits of fraction.
Definition args.hh:1311
Parser class for double-precision floating point numbers.
Definition args.hh:1338
Parser class for elements.
Definition args.hh:1497
Parser class for elements of type t.
Definition args.hh:1505
Base class for Click elements.
Definition element.hh:42
Error reporting class.
Definition error.hh:90
Parser class for filenames.
Definition args.hh:1488
Parser class for fixed-point numbers with b bits of fraction.
Definition args.hh:1288
Parser class for integers.
Definition args.hh:1130
Parser class for keywords.
Definition args.hh:1467
Definition args.hh:1103
Parser class for integers with saturating overflow.
Definition args.hh:1198
Parser class for seconds and powers thereof.
Definition args.hh:1419
Parser class for possibly-quoted strings.
Definition args.hh:1454
A string of characters.
Definition string.hh:22
const char * c_str() const
Null-terminate the string.
Definition string.hh:519
const_iterator end() const
Return an iterator for the end of the string.
Definition string.hh:584
const_iterator begin() const
Return an iterator for the first character in the string.
Definition string.hh:576
Vector template.
Definition vector.hh:111
void clear()
Remove all elements.
Definition vector.hh:476
size_type size() const
Return the number of elements.
Definition vector.hh:231
void push_back(value_argument_type v)
Append element v.
Definition vector.hh:399
Support for parsing configuration strings.
Click's String class.
Template determining whether T may be copied by memcpy.
Definition type_traits.hh:66
Numeric traits template.
Definition type_traits.hh:244
The Timestamp class represents a moment or interval in time.
Type traits structures.
void extract_integer(const Limb *x, V &value)
Extract an integral type from a multi-limb integer.
Definition type_traits.hh:517
Click's vector container template.