Next step in tidying up the LHASH code. This commit defines DECLARE and

IMPLEMENT macros for defining wrapper functions for "hash" and "cmp" callbacks
that are specific to the underlying item type in a hash-table. This prevents
function pointer casting altogether, and also provides some type-safety
because the macro does per-variable casting from the (void *) type used in
LHASH itself to the type declared in the macro - and if that doesn't match the
prototype expected by the "hash" or "cmp" function then a compiler error will
result.

NB: IMPLEMENT macros are not required unless predeclared forms are required
(either in a header file, or further up in a C file than the implementation
needs to be). The DECLARE macros must occur after the type-specific hash/cmp
callbacks are declared. Also, the IMPLEMENT and DECLARE macros are such that
they can be prefixed with "static" if desired and a trailing semi-colon should
be appended (making it look more like a regular declaration and easier on
auto-formatting text-editors too).

Now that these macros are defined, I will next be commiting changes to a
number of places in the library where the casting was doing bad things. After
that, the final step will be to make the analogous changes for the lh_doall
and lh_doall_arg functions (more specifically, their callback parameters).
This commit is contained in:
Geoff Thorpe 2000-12-02 23:08:59 +00:00
parent c21c35e6a4
commit dfa46e502d

View file

@ -89,6 +89,35 @@ typedef unsigned long (*LHASH_HASH_FN_TYPE)(void *);
typedef void (*LHASH_DOALL_FN_TYPE)(void *);
typedef void (*LHASH_DOALL_ARG_FN_TYPE)(void *, void *);
/* Macros for declaring and implementing type-safe wrappers for LHASH callbacks.
* This way, callbacks can be provided to LHASH structures without function
* pointer casting and the macro-defined callbacks provide per-variable casting
* before deferring to the underlying type-specific callbacks. NB: It is
* possible to place a "static" in front of both the DECLARE and IMPLEMENT
* macros if the functions are strictly internal. To keep text-editors happy,
* the macro deliberately doesn't define a trailing semi-colon - so the macro
* can be placed just like a regular function declaration, with an optional
* "static" prefix and trailing simi-colon. */
/* First: "hash" functions */
#define DECLARE_LHASH_HASH_FN(f_name,o_type) \
unsigned long f_name##_LHASH_HASH(void *)
#define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \
unsigned long f_name##_LHASH_HASH(void *arg) { \
o_type a = (o_type)arg; \
return f_name(a); }
#define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH
/* Second: "compare" functions */
#define DECLARE_LHASH_COMP_FN(f_name,o_type) \
int f_name##_LHASH_COMP(void *, void *)
#define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \
int f_name##_LHASH_COMP(void *arg1, void *arg2) { \
o_type a = (o_type)arg1; \
o_type b = (o_type)arg2; \
return f_name(a,b); }
#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP
typedef struct lhash_st
{
LHASH_NODE **b;