mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 05:07:56 +00:00
Improve new config prototype code
Sort ARRAYs if optional key comparison function is given in schema, no longer the role of the validator function.
This commit is contained in:
parent
e2f6989fe8
commit
b940ac8617
65
config.h
65
config.h
@ -199,7 +199,7 @@ struct pattern_list {
|
||||
};
|
||||
#define PATTERN_LIST_EMPTY ((struct pattern_list){.patc = 0})
|
||||
|
||||
// Generate value structs, struct config_SECTION.
|
||||
// Generate value structs, struct config_NAME.
|
||||
#define STRUCT(__name, __validator...) \
|
||||
struct config_##__name {
|
||||
#define NODE(__type, __element, __default, __parser, __flags, __comment) \
|
||||
@ -218,9 +218,9 @@ struct pattern_list {
|
||||
struct config_##__name { \
|
||||
unsigned ac; \
|
||||
struct config_##__name##__element {
|
||||
#define KEY_ATOM(__type, __eltparser) \
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
__type key;
|
||||
#define KEY_STRING(__strsize, __eltparser) \
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
char key[(__strsize) + 1];
|
||||
#define VALUE_ATOM(__type, __eltparser) \
|
||||
__type value;
|
||||
@ -270,7 +270,7 @@ struct pattern_list {
|
||||
|
||||
strbuf strbuf_cf_flags(strbuf, int);
|
||||
|
||||
// Generate default functions, dfl_config_SECTION().
|
||||
// Generate default functions, dfl_config_NAME().
|
||||
|
||||
#define STRUCT(__name, __validator...) \
|
||||
int dfl_config_##__name(struct config_##__name *s) {
|
||||
@ -292,8 +292,8 @@ strbuf strbuf_cf_flags(strbuf, int);
|
||||
a->ac = 0; \
|
||||
return CFOK; \
|
||||
}
|
||||
#define KEY_ATOM(__type, __eltparser)
|
||||
#define KEY_STRING(__strsize, __eltparser)
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...)
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...)
|
||||
#define VALUE_ATOM(__type, __eltparser)
|
||||
#define VALUE_STRING(__strsize, __eltparser)
|
||||
#define VALUE_NODE(__type, __eltparser)
|
||||
@ -353,9 +353,9 @@ struct cf_om_node {
|
||||
#define ARRAY(__name, __validator...) \
|
||||
int opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
||||
__VALIDATOR(__name, ##__validator)
|
||||
#define KEY_ATOM(__type, __eltparser) \
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
int __eltparser(__type *, const char *);
|
||||
#define KEY_STRING(__strsize, __eltparser) \
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
int __eltparser(char *, size_t, const char *);
|
||||
#define VALUE_ATOM(__type, __eltparser) \
|
||||
int __eltparser(__type *, const char *);
|
||||
@ -369,6 +369,55 @@ struct cf_om_node {
|
||||
int __eltparser(struct config_##__structname *, const struct cf_om_node *);
|
||||
#define END_ARRAY(__size)
|
||||
#include "config_schema.h"
|
||||
#undef __VALIDATOR
|
||||
#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 array key comparison function prototypes.
|
||||
#define STRUCT(__name, __validator...)
|
||||
#define NODE(__type, __element, __default, __parser, __flags, __comment)
|
||||
#define ATOM(__type, __element, __default, __parser, __flags, __comment)
|
||||
#define STRING(__size, __element, __default, __parser, __flags, __comment)
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __parser, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __validator...) \
|
||||
typedef int __compare_func__config_##__name##__t
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
(const __type *, const __type *);
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
(const char *, const char *);
|
||||
#define VALUE_ATOM(__type, __eltparser)
|
||||
#define VALUE_STRING(__strsize, __eltparser)
|
||||
#define VALUE_NODE(__type, __eltparser)
|
||||
#define VALUE_SUB_STRUCT(__structname)
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltparser)
|
||||
#define END_ARRAY(__size)
|
||||
#include "config_schema.h"
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#define ARRAY(__name, __validator...) \
|
||||
__compare_func__config_##__name##__t __dummy__compare_func__config_##__name
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc;
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc;
|
||||
#include "config_schema.h"
|
||||
#undef STRUCT
|
||||
#undef NODE
|
||||
#undef ATOM
|
||||
|
@ -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, parsefunc)
|
||||
* KEY_STRING(strlen, parsefunc)
|
||||
* KEY_ATOM(type, parsefunc[, comparefunc])
|
||||
* KEY_STRING(strlen, parsefunc[, comparefunc])
|
||||
*
|
||||
* and value-declaration is one of:
|
||||
*
|
||||
@ -155,6 +155,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* nul-terminated text. The parse functions for NODE, NODE_STRUCT, VALUE_NODE and
|
||||
* VALUE_NODE_STRUCT 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).
|
||||
* '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
|
||||
@ -195,7 +198,7 @@ ATOM(uint32_t, tick_ms, 0, opt_uint32_nonzero,, "Tick interval f
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(mdp_iftypelist)
|
||||
KEY_ATOM(short, opt_interface_type)
|
||||
KEY_ATOM(short, opt_interface_type, cmp_short)
|
||||
VALUE_SUB_STRUCT(mdp_iftype)
|
||||
END_ARRAY(5)
|
||||
|
||||
@ -205,7 +208,7 @@ SUB_STRUCT(mdp_iftypelist, iftype,)
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(argv, vld_argv)
|
||||
KEY_ATOM(unsigned short, opt_ushort_nonzero)
|
||||
KEY_ATOM(unsigned short, opt_ushort_nonzero, cmp_ushort)
|
||||
VALUE_STRING(128, opt_str)
|
||||
END_ARRAY(16)
|
||||
|
||||
@ -250,7 +253,7 @@ ATOM(uint16_t, port, PORT_DNA, opt_port,, "Port number")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(host_list)
|
||||
KEY_ATOM(sid_t, opt_sid)
|
||||
KEY_ATOM(sid_t, opt_sid, cmp_sid)
|
||||
VALUE_SUB_STRUCT(host)
|
||||
END_ARRAY(32)
|
||||
|
||||
|
109
config_test.c
109
config_test.c
@ -267,6 +267,11 @@ void warn_children(const char *file, unsigned line, const struct cf_om_node *nod
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void warn_duplicate_node(const struct cf_om_node *parent, const char *key)
|
||||
{
|
||||
warn_node(__FILE__, __LINE__, parent, key, "is duplicate");
|
||||
}
|
||||
|
||||
void warn_missing_node(const struct cf_om_node *parent, const char *key)
|
||||
{
|
||||
warn_node(__FILE__, __LINE__, parent, key, "is missing");
|
||||
@ -632,20 +637,47 @@ int opt_ushort_nonzero(unsigned short *ushortp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cmp_argv(const struct config_argv__element *a, const struct config_argv__element *b)
|
||||
int cmp_short(const short *a, const short *b)
|
||||
{
|
||||
return a->key < b->key ? -1 : a->key > b->key ? 1 : 0;
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cmp_ushort(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);
|
||||
}
|
||||
|
||||
int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int result)
|
||||
{
|
||||
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) cmp_argv);
|
||||
unsigned short last_key = 0;
|
||||
int i;
|
||||
if (array->ac) {
|
||||
unsigned short last_key = array->av[0].key;
|
||||
for (i = 1; i < array->ac; ++i) {
|
||||
unsigned short key = array->av[i].key;
|
||||
if (last_key > key) {
|
||||
warn_node(__FILE__, __LINE__, parent, NULL, "array is not sorted");
|
||||
return CFERROR;
|
||||
}
|
||||
last_key = key;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < array->ac; ++i) {
|
||||
unsigned short key = array->av[i].key;
|
||||
assert(key >= 1);
|
||||
while (last_key != -1 && ++last_key < key && last_key <= sizeof(array->av)) {
|
||||
assert(key >= last_key);
|
||||
if (last_key == key) {
|
||||
char labelkey[12];
|
||||
sprintf(labelkey, "%u", last_key);
|
||||
warn_duplicate_node(parent, labelkey);
|
||||
result |= CFINVALID;
|
||||
}
|
||||
while (++last_key < key && last_key <= sizeof(array->av)) {
|
||||
char labelkey[12];
|
||||
sprintf(labelkey, "%u", last_key);
|
||||
warn_missing_node(parent, labelkey);
|
||||
@ -907,6 +939,48 @@ bye:
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generate array element comparison functions.
|
||||
#define STRUCT(__name, __validator...)
|
||||
#define NODE(__type, __element, __default, __parser, __flags, __comment)
|
||||
#define ATOM(__type, __element, __default, __parser, __flags, __comment)
|
||||
#define STRING(__size, __element, __default, __parser, __flags, __comment)
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __parser, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __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, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc); \
|
||||
return cmp ? (*cmp)(&a->key, &b->key) : 0;
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc); \
|
||||
return cmp ? (*cmp)(a->key, b->key) : 0;
|
||||
#define VALUE_ATOM(__type, __eltparser)
|
||||
#define VALUE_STRING(__strsize, __eltparser)
|
||||
#define VALUE_NODE(__type, __eltparser)
|
||||
#define VALUE_SUB_STRUCT(__structname)
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltparser)
|
||||
#define END_ARRAY(__size) \
|
||||
}
|
||||
#include "config_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)
|
||||
@ -981,6 +1055,8 @@ bye:
|
||||
|
||||
#define ARRAY(__name, __validator...) \
|
||||
int opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
|
||||
__compare_func__config_##__name##__t *cmp = NULL; \
|
||||
int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \
|
||||
int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
|
||||
int result = CFOK; \
|
||||
int i, n; \
|
||||
@ -1018,6 +1094,8 @@ bye:
|
||||
warn_list_overflow(node->nodv[i]); \
|
||||
} \
|
||||
array->ac = n; \
|
||||
if (cmp) \
|
||||
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \
|
||||
if (validator) \
|
||||
result = (*validator)(node, array, result); \
|
||||
if (result & ~CFEMPTY) { \
|
||||
@ -1028,13 +1106,22 @@ bye:
|
||||
result |= CFEMPTY; \
|
||||
return result; \
|
||||
}
|
||||
#define KEY_ATOM(__type, __eltparser) __ARRAY_KEY(__eltparser(&array->av[n].key, child->key))
|
||||
#define KEY_STRING(__strsize, __eltparser) __ARRAY_KEY(__eltparser(array->av[n].key, sizeof array->av[n].key, child->key))
|
||||
#define VALUE_ATOM(__type, __eltparser) __ARRAY_VALUE(child->text ? __eltparser(&array->av[n].value, child->text) : CFEMPTY)
|
||||
#define VALUE_STRING(__strsize, __eltparser) __ARRAY_VALUE(child->text ? __eltparser(array->av[n].value, sizeof array->av[n].value, child->text) : CFEMPTY)
|
||||
#define VALUE_NODE(__type, __eltparser) __ARRAY_VALUE(__eltparser(&array->av[n].value, child))
|
||||
#define VALUE_SUB_STRUCT(__structname) __ARRAY_VALUE(opt_config_##__structname(&array->av[n].value, child))
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltparser) __ARRAY_VALUE(__eltparser(&array->av[n].value, child))
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
__ARRAY_KEY(__eltparser(&array->av[n].key, child->key)) \
|
||||
cmp = (NULL, ##__cmpfunc);
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
__ARRAY_KEY(__eltparser(array->av[n].key, sizeof array->av[n].key, child->key)) \
|
||||
cmp = (NULL, ##__cmpfunc);
|
||||
#define VALUE_ATOM(__type, __eltparser) \
|
||||
__ARRAY_VALUE(child->text ? __eltparser(&array->av[n].value, child->text) : CFEMPTY)
|
||||
#define VALUE_STRING(__strsize, __eltparser) \
|
||||
__ARRAY_VALUE(child->text ? __eltparser(array->av[n].value, sizeof array->av[n].value, child->text) : CFEMPTY)
|
||||
#define VALUE_NODE(__type, __eltparser) \
|
||||
__ARRAY_VALUE(__eltparser(&array->av[n].value, child))
|
||||
#define VALUE_SUB_STRUCT(__structname) \
|
||||
__ARRAY_VALUE(opt_config_##__structname(&array->av[n].value, child))
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltparser) \
|
||||
__ARRAY_VALUE(__eltparser(&array->av[n].value, child))
|
||||
|
||||
#include "config_schema.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user