This adds macros to implement (and/or declare) type-safe wrapper functions
around the callbacks required in the LHASH code for the "doall" functions. Also - fix the evil function pointer casting in the two lh_doall functions by deferring to a static utility function. Previously lh_doall() was invoking lh_doall_arg() by casting the callback to the 2-parameter prototype and passing in a NULL argument. This appears to have been working thus far but it's not a hot idea. If the extra level of indirection becomes a performance hit, we can just provide two virtually identical implementations for each variant later on.
This commit is contained in:
parent
ad2e032049
commit
18602745de
@ -267,19 +267,8 @@ void *lh_retrieve(LHASH *lh, const void *data)
|
||||
return((void *)ret);
|
||||
}
|
||||
|
||||
void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func)
|
||||
{
|
||||
/* Yikes that's bad - we're accepting a function that accepts 2
|
||||
* parameters (albeit we have to waive type-safety here) and then
|
||||
* forcibly calling that callback with *3* parameters leaving the 3rd
|
||||
* NULL. Obviously this "works" otherwise it wouldn't have survived so
|
||||
* long, but is it "good"??
|
||||
* FIXME: Use an internal function from this and the "_arg" version that
|
||||
* doesn't assume the ability to mutate function prototypes so badly. */
|
||||
lh_doall_arg(lh, (LHASH_DOALL_ARG_FN_TYPE)func, NULL);
|
||||
}
|
||||
|
||||
void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, const void *arg)
|
||||
static void doall_util_fn(LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func,
|
||||
LHASH_DOALL_ARG_FN_TYPE func_arg, const void *arg)
|
||||
{
|
||||
int i;
|
||||
LHASH_NODE *a,*n;
|
||||
@ -294,12 +283,25 @@ void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, const void *arg)
|
||||
/* 28/05/91 - eay - n added so items can be deleted
|
||||
* via lh_doall */
|
||||
n=a->next;
|
||||
func(a->data,arg);
|
||||
if(use_arg)
|
||||
func_arg(a->data,arg);
|
||||
else
|
||||
func(a->data);
|
||||
a=n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func)
|
||||
{
|
||||
doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)NULL, NULL);
|
||||
}
|
||||
|
||||
void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, const void *arg)
|
||||
{
|
||||
doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)NULL, func, arg);
|
||||
}
|
||||
|
||||
static void expand(LHASH *lh)
|
||||
{
|
||||
LHASH_NODE **n,**n1,**n2,*np;
|
||||
|
@ -115,6 +115,25 @@ typedef void (*LHASH_DOALL_ARG_FN_TYPE)(const void *, const void *);
|
||||
return f_name(a,b); }
|
||||
#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP
|
||||
|
||||
/* Third: "doall" functions */
|
||||
#define DECLARE_LHASH_DOALL_FN(f_name,o_type) \
|
||||
void f_name##_LHASH_DOALL(const void *);
|
||||
#define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \
|
||||
void f_name##_LHASH_DOALL(const void *arg) { \
|
||||
o_type a = (o_type)arg; \
|
||||
return f_name(a); }
|
||||
#define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL
|
||||
|
||||
/* Fourth: "doall_arg" functions */
|
||||
#define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
|
||||
void f_name##_LHASH_DOALL_ARG(const void *, const void *);
|
||||
#define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
|
||||
void f_name##_LHASH_DOALL_ARG(const void *arg1, const void *arg2) { \
|
||||
o_type a = (o_type)arg1; \
|
||||
a_type b = (a_type)arg2; \
|
||||
return f_name(a,b); }
|
||||
#define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG
|
||||
|
||||
typedef struct lhash_st
|
||||
{
|
||||
LHASH_NODE **b;
|
||||
|
Loading…
x
Reference in New Issue
Block a user