Add config cf_cmp_ functions

This commit is contained in:
Andrew Bettison 2013-02-27 18:11:18 +10:30
parent 133c34325f
commit 5939aa9edc
4 changed files with 256 additions and 34 deletions

38
conf.h
View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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, <repr> and
* cf_fmt_<repr> that convert the given 'type' from and to a string respectively:
* - The <repr> functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and
* The string representation. This name specifies a trio of functions, cf_opt_<repr>(),
* cf_fmt_<repr>() and cf_cmp_<repr>():
* - The cf_opt_<repr>() functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and
* VALUE_STRING take a (const char *) argument pointing to nul-terminated text. The
* <repr> 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_<repr> function is the inverse of <repr>. The cf_fmt_<repr>
* 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 <repr>(), would produce the same original value. If the value is invalid
* (outside the legal range) or malloc() fails, then cf_fmt_<repr> returns NULL. The
* cf_fmt_<repr> 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
* <repr> would produce the same original value.
* - Each cf_fmt_<repr>() function is the inverse of cf_opt_<repr>. The cf_fmt_<repr>
* 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_<repr>(), would produce the same original value. If the value is invalid (outside
* the legal range) then cf_fmt_<repr> returns CFINVALID or CFEMPTY. The cf_fmt_<repr>
* 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_<repr> would produce
* the same original value.
* - Each cf_cmp_<repr>() 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_<repr>(). 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)