From 5939aa9edcfc2757985c2d18a8538a938ad4be70 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Wed, 27 Feb 2013 18:11:18 +1030 Subject: [PATCH] Add config cf_cmp_ functions --- conf.h | 38 ++++++++----- conf_parse.c | 73 +++++++++++++++++++++++++ conf_schema.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++--- conf_schema.h | 32 ++++++----- 4 files changed, 256 insertions(+), 34 deletions(-) diff --git a/conf.h b/conf.h index 2712e814..912dbe05 100644 --- a/conf.h +++ b/conf.h @@ -401,50 +401,64 @@ struct pattern_list { #define STRUCT(__name, __validator...) \ int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \ int cf_fmt_config_##__name(struct cf_om_node **, const struct config_##__name *); \ + int cf_cmp_config_##__name(const struct config_##__name *, const struct config_##__name *); \ __VALIDATOR(__name, ##__validator) #define NODE(__type, __element, __default, __repr, __flags, __comment) \ int cf_opt_##__repr(__type *, const struct cf_om_node *); \ - int cf_fmt_##__repr(struct cf_om_node **, const __type *); + int cf_fmt_##__repr(struct cf_om_node **, const __type *); \ + int cf_cmp_##__repr(const __type *, const __type *); #define ATOM(__type, __element, __default, __repr, __flags, __comment) \ int cf_opt_##__repr(__type *, const char *); \ - int cf_fmt_##__repr(const char **, const __type *); + int cf_fmt_##__repr(const char **, const __type *); \ + int cf_cmp_##__repr(const __type *, const __type *); #define STRING(__size, __element, __default, __repr, __flags, __comment) \ int cf_opt_##__repr(char *, size_t, const char *); \ - int cf_fmt_##__repr(const char **, const char *); + int cf_fmt_##__repr(const char **, const char *); \ + int cf_cmp_##__repr(const char *, const char *); #define SUB_STRUCT(__structname, __element, __flags) \ int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); \ - int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); + int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); \ + int cf_cmp_config_##__structname(const struct config_##__structname *, const struct config_##__structname *); #define NODE_STRUCT(__structname, __element, __repr, __flags) \ SUB_STRUCT(__structname, __element, __flags) \ int cf_opt_##__repr(struct config_##__structname *, const struct cf_om_node *); \ - int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); + int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \ + int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *); #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \ int cf_fmt_config_##__name(struct cf_om_node **, const struct config_##__name *); \ + int cf_cmp_config_##__name(const struct config_##__name *, const struct config_##__name *); \ __VALIDATOR(__name, ##__validator) #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ int cf_opt_##__keyrepr(__type *, const char *); \ - int cf_fmt_##__keyrepr(const char **, const __type *); + int cf_fmt_##__keyrepr(const char **, const __type *); \ + int cf_cmp_##__keyrepr(const __type *, const __type *); #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ int cf_opt_##__keyrepr(char *, size_t, const char *); \ - int cf_fmt_##__keyrepr(const char **, const char *); + int cf_fmt_##__keyrepr(const char **, const char *); \ + int cf_cmp_##__keyrepr(const char *, const char *); #define VALUE_ATOM(__type, __eltrepr) \ int cf_opt_##__eltrepr(__type *, const char *); \ - int cf_fmt_##__eltrepr(const char **, const __type *); + int cf_fmt_##__eltrepr(const char **, const __type *); \ + int cf_cmp_##__eltrepr(const __type *, const __type *); #define VALUE_STRING(__strsize, __eltrepr) \ int cf_opt_##__eltrepr(char *, size_t, const char *); \ - int cf_fmt_##__eltrepr(const char **, const char *); + int cf_fmt_##__eltrepr(const char **, const char *); \ + int cf_cmp_##__eltrepr(const char *, const char *); #define VALUE_NODE(__type, __eltrepr) \ int cf_opt_##__eltrepr(__type *, const struct cf_om_node *); \ - int cf_fmt_##__eltrepr(struct cf_om_node **, const __type *); + int cf_fmt_##__eltrepr(struct cf_om_node **, const __type *); \ + int cf_cmp_##__eltrepr(const __type *, const __type *); #define VALUE_SUB_STRUCT(__structname) \ int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); \ - int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); + int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); \ + int cf_cmp_config_##__structname(const struct config_##__structname *, const struct config_##__structname *); #define VALUE_NODE_STRUCT(__structname, __repr) \ VALUE_SUB_STRUCT(__structname) \ int cf_opt_##__repr(struct config_##__structname *, const struct cf_om_node *); \ - int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); + int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \ + int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *); #define END_ARRAY(__size) #include "conf_schema.h" #undef __VALIDATOR diff --git a/conf_parse.c b/conf_parse.c index 20d6ca9d..0b45ec6a 100644 --- a/conf_parse.c +++ b/conf_parse.c @@ -548,6 +548,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #undef SUB_STRUCT #undef NODE_STRUCT #undef END_STRUCT +#undef __FMT_TEXT +#undef __FMT_NODE +#undef __REMOVE_EMPTY +#undef __HANDLE_RET #undef ARRAY #undef KEY_ATOM #undef KEY_STRING @@ -559,3 +563,72 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #undef __ARRAY_KEY #undef END_ARRAY +// Generate comparison functions, cf_cmp_config_SECTION() +#define STRUCT(__name, __validator...) \ + int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \ + int c; +#define NODE(__type, __element, __default, __repr, __flags, __comment) \ + if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \ + return c; +#define ATOM(__type, __element, __default, __repr, __flags, __comment) \ + if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \ + return c; +#define STRING(__size, __element, __default, __repr, __flags, __comment) \ + if ((c = cf_cmp_##__repr(&a->__element[0], &b->__element[0]))) \ + return c; +#define SUB_STRUCT(__structname, __element, __flags) \ + if ((c = cf_cmp_config_##__structname(&a->__element, &b->__element))) \ + return c; +#define NODE_STRUCT(__structname, __element, __repr, __flags) \ + if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \ + return c; +#define END_STRUCT \ + return 0; \ + } +#define ARRAY(__name, __flags, __validator...) \ + int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \ + int c; \ + int i; \ + for (i = 0; i < a->ac && i < b->ac; ++i) { +#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ + if ((c = cf_cmp_##__keyrepr(&a->av[i].key, &b->av[i].key))) \ + return c; +#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ + if ((c = cf_cmp_##__keyrepr(&a->av[i].key[0], &b->av[i].key[0]))) \ + return c; +#define VALUE_ATOM(__type, __eltrepr) \ + if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \ + return c; +#define VALUE_STRING(__strsize, __eltrepr) \ + if ((c = cf_cmp_##__eltrepr(&a->av[i].value[0], &b->av[i].value[0]))) \ + return c; +#define VALUE_NODE(__type, __eltrepr) \ + if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \ + return c; +#define VALUE_SUB_STRUCT(__structname) \ + if ((c = cf_cmp_config_##__structname(&a->av[i].value, &b->av[i].value))) \ + return c; +#define VALUE_NODE_STRUCT(__structname, __eltrepr) \ + if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \ + return c; +#define END_ARRAY(__size) \ + } \ + return (a->ac < b->ac) ? -1 : (a->ac > b->ac) ? 1 : 0; \ + } +#include "conf_schema.h" +#undef STRUCT +#undef NODE +#undef ATOM +#undef STRING +#undef SUB_STRUCT +#undef NODE_STRUCT +#undef END_STRUCT +#undef ARRAY +#undef KEY_ATOM +#undef KEY_STRING +#undef VALUE_ATOM +#undef VALUE_STRING +#undef VALUE_NODE +#undef VALUE_SUB_STRUCT +#undef VALUE_NODE_STRUCT +#undef END_ARRAY diff --git a/conf_schema.c b/conf_schema.c index 5ad67efb..6b486b08 100644 --- a/conf_schema.c +++ b/conf_schema.c @@ -58,6 +58,11 @@ int cf_fmt_char_boolean(const char **textp, const char *booleanp) return CFINVALID; } +int cf_cmp_char_boolean(const char *a, const char *b) +{ + return !*a && *b ? -1 : *a && !*b ? 1 : 0; +} + int cf_opt_int_boolean(int *booleanp, const char *text) { char b; @@ -80,6 +85,11 @@ int cf_fmt_int_boolean(const char **textp, const int *booleanp) return CFINVALID; } +int cf_cmp_int_boolean(const int *a, const int *b) +{ + return !*a && *b ? -1 : *a && !*b ? 1 : 0; +} + int cf_opt_absolute_path(char *str, size_t len, const char *text) { if (text[0] != '/') @@ -99,6 +109,11 @@ int cf_fmt_absolute_path(const char **textp, const char *str) return CFOK; } +int cf_cmp_absolute_path(const char *a, const char *b) +{ + return strcmp(a, b); +} + int cf_opt_protocol(char *str, size_t len, const char *text) { if (!str_is_uri_scheme(text)) @@ -118,6 +133,11 @@ int cf_fmt_protocol(const char **textp, const char *str) return CFOK; } +int cf_cmp_protocol(const char *a, const char *b) +{ + return strcmp(a, b); +} + int cf_opt_rhizome_peer(struct config_rhizome_peer *rpeer, const struct cf_om_node *node) { if (!node->text) @@ -134,6 +154,11 @@ int cf_fmt_rhizome_peer(struct cf_om_node **parentp, const struct config_rhizome return cf_fmt_config_rhizome_peer(parentp, rpeer); } +int cf_cmp_rhizome_peer(const struct config_rhizome_peer *a, const struct config_rhizome_peer *b) +{ + return cf_cmp_config_rhizome_peer(a, b); +} + int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *rpeer, const char *text) { const char *protocol; @@ -182,6 +207,11 @@ int cf_fmt_str(const char **textp, const char *str) return CFOK; } +int cf_cmp_str(const char *a, const char *b) +{ + return strcmp(a, b); +} + int cf_opt_str_nonempty(char *str, size_t len, const char *text) { if (!text[0]) @@ -197,6 +227,11 @@ int cf_fmt_str_nonempty(const char **textp, const char *str) return CFOK; } +int cf_cmp_str_nonempty(const char *a, const char *b) +{ + return strcmp(a, b); +} + int cf_opt_int(int *intp, const char *text) { const char *end = text; @@ -215,6 +250,11 @@ int cf_fmt_int(const char **textp, const int *intp) return CFOK; } +int cf_cmp_int(const int *a, const int *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_opt_uint(unsigned int *uintp, const char *text) { const char *end = text; @@ -233,6 +273,11 @@ int cf_fmt_uint(const char **textp, const unsigned int *uintp) return CFOK; } +int cf_cmp_uint(const unsigned int *a, const unsigned int *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_opt_int32_nonneg(int32_t *intp, const char *text) { const char *end = text; @@ -251,6 +296,11 @@ static int cf_fmt_int32(const char **textp, const int32_t *intp) return CFOK; } +int cf_cmp_int32(const int32_t *a, const int32_t *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + static int cf_fmt_uint32(const char **textp, const uint32_t *uintp) { char buf[12]; @@ -259,6 +309,11 @@ static int cf_fmt_uint32(const char **textp, const uint32_t *uintp) return CFOK; } +int cf_cmp_uint32(const uint32_t *a, const uint32_t *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_fmt_int32_nonneg(const char **textp, const int32_t *intp) { if (*intp < 0) @@ -266,6 +321,11 @@ int cf_fmt_int32_nonneg(const char **textp, const int32_t *intp) return cf_fmt_int32(textp, intp); } +int cf_cmp_int32_nonneg(const int32_t *a, const int32_t *b) +{ + return cf_cmp_int32(a, b); +} + int cf_opt_uint32_nonzero(uint32_t *intp, const char *text) { const char *end = text; @@ -283,6 +343,11 @@ int cf_fmt_uint32_nonzero(const char **textp, const uint32_t *uintp) return cf_fmt_uint32(textp, uintp); } +int cf_cmp_uint32_nonzero(const uint32_t *a, const uint32_t *b) +{ + return cf_cmp_uint32(a, b); +} + int cf_opt_uint64_scaled(uint64_t *intp, const char *text) { uint64_t result; @@ -302,6 +367,11 @@ int cf_fmt_uint64_scaled(const char **textp, const uint64_t *uintp) return CFOK; } +int cf_cmp_uint64_scaled(const uint64_t *a, const uint64_t *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_opt_ushort_nonzero(unsigned short *ushortp, const char *text) { uint32_t ui; @@ -319,6 +389,11 @@ int cf_fmt_ushort(const char **textp, const unsigned short *ushortp) return CFOK; } +int cf_cmp_ushort(const unsigned short *a, const unsigned short *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_fmt_ushort_nonzero(const char **textp, const unsigned short *ushortp) { if (*ushortp == 0) @@ -326,19 +401,14 @@ int cf_fmt_ushort_nonzero(const char **textp, const unsigned short *ushortp) return cf_fmt_ushort(textp, ushortp); } -int cmp_short(const short *a, const short *b) +int cf_cmp_short(const short *a, const short *b) { return *a < *b ? -1 : *a > *b ? 1 : 0; } -int cmp_ushort(const unsigned short *a, const unsigned short *b) +int cf_cmp_ushort_nonzero(const unsigned short *a, const unsigned short *b) { - return *a < *b ? -1 : *a > *b ? 1 : 0; -} - -int cmp_sid(const sid_t *a, const sid_t *b) -{ - return memcmp(a->binary, b->binary, sizeof a->binary); + return cf_cmp_ushort(a, b); } int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int result) @@ -392,6 +462,11 @@ int cf_fmt_in_addr(const char **textp, const struct in_addr *addrp) return CFOK; } +int cf_cmp_in_addr(const struct in_addr *a, const struct in_addr *b) +{ + return memcmp(a, b, sizeof(struct in_addr)); +} + int cf_opt_uint16(uint16_t *uintp, const char *text) { uint16_t ui = 0; @@ -416,6 +491,11 @@ int cf_fmt_uint16(const char **textp, const uint16_t *uintp) return CFOK; } +int cf_cmp_uint16(const uint16_t *a, const uint16_t *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_opt_uint16_nonzero(uint16_t *uintp, const char *text) { uint16_t ui; @@ -432,6 +512,11 @@ int cf_fmt_uint16_nonzero(const char **textp, const uint16_t *uintp) return cf_fmt_uint16(textp, uintp); } +int cf_cmp_uint16_nonzero(const uint16_t *a, const uint16_t *b) +{ + return cf_cmp_uint16(a, b); +} + int cf_opt_sid(sid_t *sidp, const char *text) { if (!str_is_subscriber_id(text)) @@ -447,6 +532,11 @@ int cf_fmt_sid(const char **textp, const sid_t *sidp) return CFOK; } +int cf_cmp_sid(const sid_t *a, const sid_t *b) +{ + return memcmp(a->binary, b->binary, sizeof a->binary); +} + int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text) { if (!rhizome_str_is_bundle_key(text)) @@ -462,6 +552,11 @@ int cf_fmt_rhizome_bk(const char **textp, const rhizome_bk_t *bkp) return CFOK; } +int cf_cmp_rhizome_bk(const rhizome_bk_t *a, const rhizome_bk_t *b) +{ + return memcmp(a, b, sizeof a->binary); +} + int cf_opt_interface_type(short *typep, const char *text) { if (strcasecmp(text, "ethernet") == 0) { @@ -498,6 +593,11 @@ int cf_fmt_interface_type(const char **textp, const short *typep) return CFOK; } +int cf_cmp_interface_type(const short *a, const short *b) +{ + return *a < *b ? -1 : *a > *b ? 1 : 0; +} + int cf_opt_socket_type(short *typep, const char *text) { if (strcasecmp(text, "dgram") == 0) { @@ -529,6 +629,11 @@ int cf_fmt_socket_type(const char **textp, const short *typep) return CFOK; } +int cf_cmp_socket_type(const short *a, const short *b) +{ + return cf_cmp_short(a, b); +} + int cf_opt_encapsulation(short *encapp, const char *text) { if (strcasecmp(text, "overlay") == 0) { @@ -555,6 +660,11 @@ int cf_fmt_encapsulation(const char **textp, const short *encapp) return CFOK; } +int cf_cmp_encapsulation(const short *a, const short *b) +{ + return cf_cmp_short(a, b); +} + int cf_opt_pattern_list(struct pattern_list *listp, const char *text) { struct pattern_list list; @@ -606,6 +716,17 @@ int cf_fmt_pattern_list(const char **textp, const struct pattern_list *listp) return CFOK; } +int cf_cmp_pattern_list(const struct pattern_list *a, const struct pattern_list *b) +{ + unsigned i; + for (i = 0; i < a->patc && i < b->patc; ++i) { + int c = strcmp(a->patv[i], b->patv[i]); + if (c) + return c; + } + return (a->patc < b->patc) ? -1 : (a->patc > b->patc) ? 1 : 0; +} + /* Config parse function. Implements the original form of the 'interfaces' config option. Parses a * single text string of the form: * @@ -726,6 +847,11 @@ int cf_fmt_network_interface(struct cf_om_node **parentp, const struct config_ne return cf_fmt_config_network_interface(parentp, nifp); } +int cf_cmp_network_interface(const struct config_network_interface *a, const struct config_network_interface *b) +{ + return cf_cmp_config_network_interface(a, b); +} + int vld_network_interface(const struct cf_om_node *parent, struct config_network_interface *nifp, int result) { if (nifp->match.patc != 0 && nifp->file[0]) { @@ -829,3 +955,8 @@ int cf_fmt_interface_list(struct cf_om_node **parentp, const struct config_inter { return cf_fmt_config_interface_list(parentp, listp); } + +int cf_cmp_interface_list(const struct config_interface_list *a, const struct config_interface_list *b) +{ + return cf_cmp_config_interface_list(a, b); +} diff --git a/conf_schema.h b/conf_schema.h index 7750cc73..f10fa6e1 100644 --- a/conf_schema.h +++ b/conf_schema.h @@ -149,21 +149,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Only used for ATOM and NODE struct elements. Gives the default value for the element if * absent from the config file. * 'repr' - * The string representation. This name specifies a pair of functions, and - * cf_fmt_ that convert the given 'type' from and to a string respectively: - * - The functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and + * The string representation. This name specifies a trio of functions, cf_opt_(), + * cf_fmt_() and cf_cmp_(): + * - The cf_opt_() functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and * VALUE_STRING take a (const char *) argument pointing to nul-terminated text. The * functions for NODE and VALUE_NODE take a pointer to a COM node (const * struct cf_om_node *), and are responsible for parsing the node's text and all of its * descendents (children). - * - Each cf_fmt_ function is the inverse of . The cf_fmt_ - * functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and VALUE_STRING all take a - * pointer to a const 'type', and return a malloc()ed nul-terminated string which, if passed - * to (), would produce the same original value. If the value is invalid - * (outside the legal range) or malloc() fails, then cf_fmt_ returns NULL. The - * cf_fmt_ functions for NODE and VALUE_NODE take a pointer to a const 'type' and - * return a pointer to a malloc()ed COM node (struct cf_om_node *) which, if passed to - * would produce the same original value. + * - Each cf_fmt_() function is the inverse of cf_opt_. The cf_fmt_ + * functions for ATOM, KEY_ATOM, KEY_STRING, VALUE_ATOM and VALUE_STRING all take a pointer + * to a const 'type', and produce a malloc()ed nul-terminated string which, if passed to + * cf_opt_(), would produce the same original value. If the value is invalid (outside + * the legal range) then cf_fmt_ returns CFINVALID or CFEMPTY. The cf_fmt_ + * functions for NODE and VALUE_NODE take a pointer to a const 'type' and produce a + * malloc()ed COM node (struct cf_om_node *) which, if passed to cf_opt_ would produce + * the same original value. + * - Each cf_cmp_() function compares two values of the given 'type' and returns -1, 0 + * or 1 to indicate the natural ordering of the values. These functions are used to detect + * when config elements have their default values, to avoid calling cf_fmt_(). They + * are also used to sort array keys. * 'comparefunc' * A function used to sort an array after all elements have been parsed, and before being * validated (see below). @@ -248,7 +252,7 @@ ATOM(int32_t, packet_interval, -1, int32_nonneg,, "Minimum interva END_STRUCT ARRAY(mdp_iftypelist, NO_DUPLICATES) -KEY_ATOM(short, interface_type, cmp_short) +KEY_ATOM(short, interface_type, cf_cmp_short) VALUE_SUB_STRUCT(mdp_iftype) END_ARRAY(5) @@ -264,7 +268,7 @@ ATOM(uint16_t, local_port, 4131, uint16_nonzero,, "Local port numbe END_STRUCT ARRAY(argv, SORTED NO_DUPLICATES, vld_argv) -KEY_ATOM(unsigned short, ushort_nonzero, cmp_ushort) +KEY_ATOM(unsigned short, ushort_nonzero, cf_cmp_ushort) VALUE_STRING(128, str) END_ARRAY(16) @@ -346,7 +350,7 @@ ATOM(uint16_t, port, PORT_DNA, uint16_nonzero,, "Port number" END_STRUCT ARRAY(host_list, NO_DUPLICATES) -KEY_ATOM(sid_t, sid, cmp_sid) +KEY_ATOM(sid_t, sid, cf_cmp_sid) VALUE_SUB_STRUCT(host) END_ARRAY(32)