From 54ce857cff4ba0c88010a563e338aafe70f0f6d1 Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Fri, 1 Mar 2013 15:27:28 +1030 Subject: [PATCH] Improve config schema declaration Remove array key SORTED flag; all arrays are now sorted by key Use representation's comparison function for sorting arrays, not a schema-supplied comparison function. --- conf.h | 68 ++++++-------------------------------- conf_parse.c | 90 +++++++++++++-------------------------------------- conf_schema.h | 17 ++++------ 3 files changed, 39 insertions(+), 136 deletions(-) diff --git a/conf.h b/conf.h index 11706b0a..4d69364d 100644 --- a/conf.h +++ b/conf.h @@ -322,10 +322,10 @@ struct pattern_list { struct config_##__name { \ unsigned ac; \ struct config_##__name##__element { -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ - __type key; -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ - char key[(__strsize) + 1]; +#define KEY_ATOM(__type, __keyrepr) \ + __type key; // key must be first element in struct +#define KEY_STRING(__strsize, __keyrepr) \ + char key[(__strsize) + 1]; // key must be first element in struct #define VALUE_ATOM(__type, __eltrepr) \ __type value; #define VALUE_STRING(__strsize, __eltrepr) \ @@ -370,8 +370,8 @@ struct pattern_list { #define ARRAY(__name, __flags, __validator...) \ int cf_dfl_config_##__name(struct config_##__name *a); \ int cf_sch_config_##__name(struct cf_om_node **parentp); -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) +#define KEY_ATOM(__type, __keyrepr) +#define KEY_STRING(__strsize, __keyrepr) #define VALUE_ATOM(__type, __eltrepr) #define VALUE_STRING(__strsize, __eltrepr) #define VALUE_NODE(__type, __eltrepr) @@ -432,11 +432,11 @@ struct pattern_list { 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...) \ +#define KEY_ATOM(__type, __keyrepr) \ int cf_opt_##__keyrepr(__type *, const char *); \ int cf_fmt_##__keyrepr(const char **, const __type *); \ int cf_cmp_##__keyrepr(const __type *, const __type *); -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ +#define KEY_STRING(__strsize, __keyrepr) \ int cf_opt_##__keyrepr(char *, size_t, const char *); \ int cf_fmt_##__keyrepr(const char **, const char *); \ int cf_cmp_##__keyrepr(const char *, const char *); @@ -481,54 +481,6 @@ struct pattern_list { #undef VALUE_NODE_STRUCT #undef END_ARRAY -// Generate config array key comparison function prototypes. -#define STRUCT(__name, __validator...) -#define NODE(__type, __element, __default, __repr, __flags, __comment) -#define ATOM(__type, __element, __default, __repr, __flags, __comment) -#define STRING(__size, __element, __default, __repr, __flags, __comment) -#define SUB_STRUCT(__name, __element, __flags) -#define NODE_STRUCT(__name, __element, __repr, __flags) -#define END_STRUCT -#define ARRAY(__name, __flags, __validator...) \ - typedef int __compare_func__config_##__name##__t -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ - (const __type *, const __type *); -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ - (const char *, const char *); -#define VALUE_ATOM(__type, __eltrepr) -#define VALUE_STRING(__strsize, __eltrepr) -#define VALUE_NODE(__type, __eltrepr) -#define VALUE_SUB_STRUCT(__structname) -#define VALUE_NODE_STRUCT(__structname, __eltrepr) -#define END_ARRAY(__size) -#include "conf_schema.h" -#undef ARRAY -#undef KEY_ATOM -#undef KEY_STRING -#define ARRAY(__name, __flags, __validator...) \ - __compare_func__config_##__name##__t __dummy__compare_func__config_##__name -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ - ,##__cmpfunc; -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ - ,##__cmpfunc; -#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 - // Generate config array search-by-key function prototypes. #define STRUCT(__name, __validator...) #define NODE(__type, __element, __default, __repr, __flags, __comment) @@ -539,9 +491,9 @@ struct pattern_list { #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ int config_##__name##__get(const struct config_##__name *, -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ +#define KEY_ATOM(__type, __keyrepr) \ const __type *); -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ +#define KEY_STRING(__strsize, __keyrepr) \ const char *); #define VALUE_ATOM(__type, __eltrepr) #define VALUE_STRING(__strsize, __eltrepr) diff --git a/conf_parse.c b/conf_parse.c index 50896ef4..4271953e 100644 --- a/conf_parse.c +++ b/conf_parse.c @@ -42,8 +42,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. a->ac = 0; \ return CFOK; \ } -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) +#define KEY_ATOM(__type, __keyrepr) +#define KEY_STRING(__strsize, __keyrepr) #define VALUE_ATOM(__type, __eltrepr) #define VALUE_STRING(__strsize, __eltrepr) #define VALUE_NODE(__type, __eltrepr) @@ -68,60 +68,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #undef VALUE_NODE_STRUCT #undef END_ARRAY -// Generate array element comparison functions. -#define STRUCT(__name, __validator...) -#define NODE(__type, __element, __default, __repr, __flags, __comment) -#define ATOM(__type, __element, __default, __repr, __flags, __comment) -#define STRING(__size, __element, __default, __repr, __flags, __comment) -#define SUB_STRUCT(__name, __element, __flags) -#define NODE_STRUCT(__name, __element, __repr, __flags) -#define END_STRUCT -#define ARRAY(__name, __flags, __validator...) \ - static int __cmp_config_##__name(const struct config_##__name##__element *a, const struct config_##__name##__element *b) { \ - __compare_func__config_##__name##__t *cmp = (NULL -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ - ,##__cmpfunc); \ - return cmp ? (*cmp)(&a->key, &b->key) : memcmp(&a->key, &b->key, sizeof a->key); -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ - ,##__cmpfunc); \ - return cmp ? (*cmp)(a->key, b->key) : strcmp(a->key, b->key); -#define VALUE_ATOM(__type, __eltrepr) -#define VALUE_STRING(__strsize, __eltrepr) -#define VALUE_NODE(__type, __eltrepr) -#define VALUE_SUB_STRUCT(__structname) -#define VALUE_NODE_STRUCT(__structname, __eltrepr) -#define END_ARRAY(__size) \ - } -#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 - // Schema item flags. #define __MANDATORY (1<<0) #define __TEXT (1<<1) #define __CHILDREN (1<<2) -#define __SORTED (1<<3) -#define __NO_DUPLICATES (1<<4) +#define __NO_DUPLICATES (1<<3) // Schema flag symbols, to be used in the '__flags' macro arguments. #define MANDATORY |__MANDATORY #define USES_TEXT |__TEXT #define USES_CHILDREN |__CHILDREN -#define SORTED |__SORTED #define NO_DUPLICATES |__NO_DUPLICATES // Generate parsing functions, cf_opt_config_SECTION() @@ -188,14 +144,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define ARRAY(__name, __flags, __validator...) \ int cf_opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \ int flags = (0 __flags); \ - int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \ + int (*keycmp)(const void *, const void *) = NULL; \ int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \ int result = CFOK; \ int i, n; \ for (n = 0, i = 0; i < node->nodc && n < NELS(array->av); ++i) { \ const struct cf_om_node *child = node->nodv[i]; \ int ret = CFEMPTY; -#define __ARRAY_KEY(__parseexpr, __cmpfunc...) \ +#define __ARRAY_KEY(__parseexpr, __cmpfunc, __cmpfuncargs) \ + keycmp = (int (*)(const void *, const void *)) __cmpfunc; \ ret = (__parseexpr); \ if (ret == CFERROR) \ return CFERROR; \ @@ -205,7 +162,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. if (ret == CFOK && (flags & __NO_DUPLICATES)) { \ int j; \ for (j = 0; j < n; ++j) { \ - if ((*eltcmp)(&array->av[j], &array->av[n]) == 0) { \ + if (__cmpfunc __cmpfuncargs == 0) { \ cf_warn_duplicate_node(child, NULL); \ ret |= CFDUPLICATE; \ } \ @@ -237,8 +194,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. cf_warn_list_overflow(node->nodv[i]); \ } \ array->ac = n; \ - if (flags & __SORTED) \ - qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \ + qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) keycmp); \ if (validator) \ result = (*validator)(node, array, result); \ if (result & ~CFEMPTY) { \ @@ -249,10 +205,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. result |= CFEMPTY; \ return result; \ } -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ - __ARRAY_KEY(cf_opt_##__keyrepr(&array->av[n].key, child->key), ##__cmpfunc) -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ - __ARRAY_KEY(cf_opt_##__keyrepr(array->av[n].key, sizeof array->av[n].key, child->key), ##__cmpfunc) +#define KEY_ATOM(__type, __keyrepr) \ + __ARRAY_KEY(cf_opt_##__keyrepr(&array->av[n].key, child->key), cf_cmp_##__keyrepr, (&array->av[j].key, &array->av[n].key)) +#define KEY_STRING(__strsize, __keyrepr) \ + __ARRAY_KEY(cf_opt_##__keyrepr(array->av[n].key, sizeof array->av[n].key, child->key), cf_cmp_##__keyrepr, (&array->av[j].key[0], &array->av[n].key[0])) #define VALUE_ATOM(__type, __eltrepr) \ __ARRAY_VALUE(CFOK, child->text ? cf_opt_##__eltrepr(&array->av[n].value, child->text) : CFEMPTY) #define VALUE_STRING(__strsize, __eltrepr) \ @@ -293,21 +249,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ int config_##__name##__get(const struct config_##__name *array, -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ +#define KEY_ATOM(__type, __keyrepr) \ const __type *key) { \ - int (*cmp)(const __type *, const __type *) = (NULL, ##__cmpfunc); \ int i; \ for (i = 0; i < array->ac; ++i) \ - if ((cmp ? (*cmp)(key, &array->av[i].key) : memcmp(key, &array->av[i].key, sizeof *key)) == 0) \ + if ((cf_cmp_##__keyrepr(key, &array->av[i].key)) == 0) \ return i; \ return -1; \ } -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ +#define KEY_STRING(__strsize, __keyrepr) \ const char *key) { \ - int (*cmp)(const char *, const char *) = (NULL, ##__cmpfunc); \ int i; \ for (i = 0; i < array->ac; ++i) \ - if ((cmp ? (*cmp)(key, array->av[i].key) : strcmp(key, array->av[i].key)) == 0) \ + if ((cf_cmp_##__keyrepr(&key[0], &array->av[i].key[0])) == 0) \ return i; \ return -1; \ } @@ -375,9 +329,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. int cf_sch_config_##__name(struct cf_om_node **rootp) { \ int i; \ struct cf_om_node **childp; -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ +#define KEY_ATOM(__type, __keyrepr) \ __ADD_CHILD(rootp, "[" #__keyrepr "]") -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ +#define KEY_STRING(__strsize, __keyrepr) \ __ADD_CHILD(rootp, "[" #__keyrepr "]") #define VALUE_ATOM(__type, __eltrepr) \ __ATOM(childp, "(" #__eltrepr ")") @@ -538,9 +492,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. cf_om_free_node(parentp); \ return result; \ } -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ +#define KEY_ATOM(__type, __keyrepr) \ __ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key); -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ +#define KEY_STRING(__strsize, __keyrepr) \ __ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key[0]); #define VALUE_ATOM(__type, __eltrepr) \ __ARRAY_TEXT(cf_fmt_##__eltrepr, &array->av[i].value) @@ -603,10 +557,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. int c; \ int i; \ for (i = 0; i < a->ac && i < b->ac; ++i) { -#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ +#define KEY_ATOM(__type, __keyrepr) \ if ((c = cf_cmp_##__keyrepr(&a->av[i].key, &b->av[i].key))) \ return c; -#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ +#define KEY_STRING(__strsize, __keyrepr) \ if ((c = cf_cmp_##__keyrepr(&a->av[i].key[0], &b->av[i].key[0]))) \ return c; #define VALUE_ATOM(__type, __eltrepr) \ diff --git a/conf_schema.h b/conf_schema.h index f10fa6e1..65c02023 100644 --- a/conf_schema.h +++ b/conf_schema.h @@ -111,8 +111,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * where key-declaration is one of: * - * KEY_ATOM(type, repr[, comparefunc]) - * KEY_STRING(strlen, repr[, comparefunc]) + * KEY_ATOM(type, repr) + * KEY_STRING(strlen, repr) * * and value-declaration is one of: * @@ -168,9 +168,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 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). * 'validatorfunc' * A function that is called after the struct/array is fully parsed and populated. This * function can perform validation checks on the whole struct/array that cannot be performed by @@ -252,7 +249,7 @@ ATOM(int32_t, packet_interval, -1, int32_nonneg,, "Minimum interva END_STRUCT ARRAY(mdp_iftypelist, NO_DUPLICATES) -KEY_ATOM(short, interface_type, cf_cmp_short) +KEY_ATOM(short, interface_type) VALUE_SUB_STRUCT(mdp_iftype) END_ARRAY(5) @@ -267,8 +264,8 @@ ATOM(uint16_t, remote_port,4130, uint16_nonzero,, "Remote port numb ATOM(uint16_t, local_port, 4131, uint16_nonzero,, "Local port number") END_STRUCT -ARRAY(argv, SORTED NO_DUPLICATES, vld_argv) -KEY_ATOM(unsigned short, ushort_nonzero, cf_cmp_ushort) +ARRAY(argv, NO_DUPLICATES, vld_argv) +KEY_ATOM(unsigned short, ushort_nonzero) VALUE_STRING(128, str) END_ARRAY(16) @@ -350,7 +347,7 @@ ATOM(uint16_t, port, PORT_DNA, uint16_nonzero,, "Port number" END_STRUCT ARRAY(host_list, NO_DUPLICATES) -KEY_ATOM(sid_t, sid, cf_cmp_sid) +KEY_ATOM(sid_t, sid) VALUE_SUB_STRUCT(host) END_ARRAY(32) @@ -373,7 +370,7 @@ ATOM(char, default_route, 0, char_boolean,, "If true, use this ATOM(char, prefer_unicast, 0, char_boolean,, "If true, send unicast data as unicast IP packets if available") END_STRUCT -ARRAY(interface_list, SORTED NO_DUPLICATES) +ARRAY(interface_list, NO_DUPLICATES) KEY_ATOM(unsigned, uint) VALUE_NODE_STRUCT(network_interface, network_interface) END_ARRAY(10)