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})
|
#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...) \
|
#define STRUCT(__name, __validator...) \
|
||||||
struct config_##__name {
|
struct config_##__name {
|
||||||
#define NODE(__type, __element, __default, __parser, __flags, __comment) \
|
#define NODE(__type, __element, __default, __parser, __flags, __comment) \
|
||||||
@ -218,9 +218,9 @@ struct pattern_list {
|
|||||||
struct config_##__name { \
|
struct config_##__name { \
|
||||||
unsigned ac; \
|
unsigned ac; \
|
||||||
struct config_##__name##__element {
|
struct config_##__name##__element {
|
||||||
#define KEY_ATOM(__type, __eltparser) \
|
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||||
__type key;
|
__type key;
|
||||||
#define KEY_STRING(__strsize, __eltparser) \
|
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||||
char key[(__strsize) + 1];
|
char key[(__strsize) + 1];
|
||||||
#define VALUE_ATOM(__type, __eltparser) \
|
#define VALUE_ATOM(__type, __eltparser) \
|
||||||
__type value;
|
__type value;
|
||||||
@ -270,7 +270,7 @@ struct pattern_list {
|
|||||||
|
|
||||||
strbuf strbuf_cf_flags(strbuf, int);
|
strbuf strbuf_cf_flags(strbuf, int);
|
||||||
|
|
||||||
// Generate default functions, dfl_config_SECTION().
|
// Generate default functions, dfl_config_NAME().
|
||||||
|
|
||||||
#define STRUCT(__name, __validator...) \
|
#define STRUCT(__name, __validator...) \
|
||||||
int dfl_config_##__name(struct config_##__name *s) {
|
int dfl_config_##__name(struct config_##__name *s) {
|
||||||
@ -292,8 +292,8 @@ strbuf strbuf_cf_flags(strbuf, int);
|
|||||||
a->ac = 0; \
|
a->ac = 0; \
|
||||||
return CFOK; \
|
return CFOK; \
|
||||||
}
|
}
|
||||||
#define KEY_ATOM(__type, __eltparser)
|
#define KEY_ATOM(__type, __eltparser, __cmpfunc...)
|
||||||
#define KEY_STRING(__strsize, __eltparser)
|
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...)
|
||||||
#define VALUE_ATOM(__type, __eltparser)
|
#define VALUE_ATOM(__type, __eltparser)
|
||||||
#define VALUE_STRING(__strsize, __eltparser)
|
#define VALUE_STRING(__strsize, __eltparser)
|
||||||
#define VALUE_NODE(__type, __eltparser)
|
#define VALUE_NODE(__type, __eltparser)
|
||||||
@ -353,9 +353,9 @@ struct cf_om_node {
|
|||||||
#define ARRAY(__name, __validator...) \
|
#define ARRAY(__name, __validator...) \
|
||||||
int opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
int opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
||||||
__VALIDATOR(__name, ##__validator)
|
__VALIDATOR(__name, ##__validator)
|
||||||
#define KEY_ATOM(__type, __eltparser) \
|
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||||
int __eltparser(__type *, const char *);
|
int __eltparser(__type *, const char *);
|
||||||
#define KEY_STRING(__strsize, __eltparser) \
|
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||||
int __eltparser(char *, size_t, const char *);
|
int __eltparser(char *, size_t, const char *);
|
||||||
#define VALUE_ATOM(__type, __eltparser) \
|
#define VALUE_ATOM(__type, __eltparser) \
|
||||||
int __eltparser(__type *, const char *);
|
int __eltparser(__type *, const char *);
|
||||||
@ -369,6 +369,55 @@ struct cf_om_node {
|
|||||||
int __eltparser(struct config_##__structname *, const struct cf_om_node *);
|
int __eltparser(struct config_##__structname *, const struct cf_om_node *);
|
||||||
#define END_ARRAY(__size)
|
#define END_ARRAY(__size)
|
||||||
#include "config_schema.h"
|
#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 STRUCT
|
||||||
#undef NODE
|
#undef NODE
|
||||||
#undef ATOM
|
#undef ATOM
|
||||||
|
@ -111,8 +111,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||||||
*
|
*
|
||||||
* where key-declaration is one of:
|
* where key-declaration is one of:
|
||||||
*
|
*
|
||||||
* KEY_ATOM(type, parsefunc)
|
* KEY_ATOM(type, parsefunc[, comparefunc])
|
||||||
* KEY_STRING(strlen, parsefunc)
|
* KEY_STRING(strlen, parsefunc[, comparefunc])
|
||||||
*
|
*
|
||||||
* and value-declaration is one of:
|
* 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
|
* 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
|
* 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).
|
* 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'
|
* 'validatorfunc'
|
||||||
* A function that is called after the struct/array is fully parsed and populated. This
|
* 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
|
* 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
|
END_STRUCT
|
||||||
|
|
||||||
ARRAY(mdp_iftypelist)
|
ARRAY(mdp_iftypelist)
|
||||||
KEY_ATOM(short, opt_interface_type)
|
KEY_ATOM(short, opt_interface_type, cmp_short)
|
||||||
VALUE_SUB_STRUCT(mdp_iftype)
|
VALUE_SUB_STRUCT(mdp_iftype)
|
||||||
END_ARRAY(5)
|
END_ARRAY(5)
|
||||||
|
|
||||||
@ -205,7 +208,7 @@ SUB_STRUCT(mdp_iftypelist, iftype,)
|
|||||||
END_STRUCT
|
END_STRUCT
|
||||||
|
|
||||||
ARRAY(argv, vld_argv)
|
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)
|
VALUE_STRING(128, opt_str)
|
||||||
END_ARRAY(16)
|
END_ARRAY(16)
|
||||||
|
|
||||||
@ -250,7 +253,7 @@ ATOM(uint16_t, port, PORT_DNA, opt_port,, "Port number")
|
|||||||
END_STRUCT
|
END_STRUCT
|
||||||
|
|
||||||
ARRAY(host_list)
|
ARRAY(host_list)
|
||||||
KEY_ATOM(sid_t, opt_sid)
|
KEY_ATOM(sid_t, opt_sid, cmp_sid)
|
||||||
VALUE_SUB_STRUCT(host)
|
VALUE_SUB_STRUCT(host)
|
||||||
END_ARRAY(32)
|
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);
|
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)
|
void warn_missing_node(const struct cf_om_node *parent, const char *key)
|
||||||
{
|
{
|
||||||
warn_node(__FILE__, __LINE__, parent, key, "is missing");
|
warn_node(__FILE__, __LINE__, parent, key, "is missing");
|
||||||
@ -632,20 +637,47 @@ int opt_ushort_nonzero(unsigned short *ushortp, const char *text)
|
|||||||
return CFOK;
|
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)
|
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;
|
unsigned short last_key = 0;
|
||||||
int i;
|
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) {
|
for (i = 0; i < array->ac; ++i) {
|
||||||
unsigned short key = array->av[i].key;
|
unsigned short key = array->av[i].key;
|
||||||
assert(key >= 1);
|
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];
|
char labelkey[12];
|
||||||
sprintf(labelkey, "%u", last_key);
|
sprintf(labelkey, "%u", last_key);
|
||||||
warn_missing_node(parent, labelkey);
|
warn_missing_node(parent, labelkey);
|
||||||
@ -907,6 +939,48 @@ bye:
|
|||||||
return result;
|
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.
|
// Schema item flags.
|
||||||
#define __MANDATORY (1<<0)
|
#define __MANDATORY (1<<0)
|
||||||
#define __TEXT (1<<1)
|
#define __TEXT (1<<1)
|
||||||
@ -981,6 +1055,8 @@ bye:
|
|||||||
|
|
||||||
#define ARRAY(__name, __validator...) \
|
#define ARRAY(__name, __validator...) \
|
||||||
int opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
|
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 (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
|
||||||
int result = CFOK; \
|
int result = CFOK; \
|
||||||
int i, n; \
|
int i, n; \
|
||||||
@ -1018,6 +1094,8 @@ bye:
|
|||||||
warn_list_overflow(node->nodv[i]); \
|
warn_list_overflow(node->nodv[i]); \
|
||||||
} \
|
} \
|
||||||
array->ac = n; \
|
array->ac = n; \
|
||||||
|
if (cmp) \
|
||||||
|
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \
|
||||||
if (validator) \
|
if (validator) \
|
||||||
result = (*validator)(node, array, result); \
|
result = (*validator)(node, array, result); \
|
||||||
if (result & ~CFEMPTY) { \
|
if (result & ~CFEMPTY) { \
|
||||||
@ -1028,13 +1106,22 @@ bye:
|
|||||||
result |= CFEMPTY; \
|
result |= CFEMPTY; \
|
||||||
return result; \
|
return result; \
|
||||||
}
|
}
|
||||||
#define KEY_ATOM(__type, __eltparser) __ARRAY_KEY(__eltparser(&array->av[n].key, child->key))
|
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||||
#define KEY_STRING(__strsize, __eltparser) __ARRAY_KEY(__eltparser(array->av[n].key, sizeof array->av[n].key, child->key))
|
__ARRAY_KEY(__eltparser(&array->av[n].key, child->key)) \
|
||||||
#define VALUE_ATOM(__type, __eltparser) __ARRAY_VALUE(child->text ? __eltparser(&array->av[n].value, child->text) : CFEMPTY)
|
cmp = (NULL, ##__cmpfunc);
|
||||||
#define VALUE_STRING(__strsize, __eltparser) __ARRAY_VALUE(child->text ? __eltparser(array->av[n].value, sizeof array->av[n].value, child->text) : CFEMPTY)
|
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||||
#define VALUE_NODE(__type, __eltparser) __ARRAY_VALUE(__eltparser(&array->av[n].value, child))
|
__ARRAY_KEY(__eltparser(array->av[n].key, sizeof array->av[n].key, child->key)) \
|
||||||
#define VALUE_SUB_STRUCT(__structname) __ARRAY_VALUE(opt_config_##__structname(&array->av[n].value, child))
|
cmp = (NULL, ##__cmpfunc);
|
||||||
#define VALUE_NODE_STRUCT(__structname, __eltparser) __ARRAY_VALUE(__eltparser(&array->av[n].value, child))
|
#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"
|
#include "config_schema.h"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user