[hash] Add a couple of data-oriented functions

Hash_Select returns a list of elements that match a given criterion
(select callback returning non-0).

Hash_ForEach simply calls a function for every element.
This commit is contained in:
Bill Currie 2022-04-25 00:18:22 +09:00
parent df4116a55d
commit 8bd626a3e4
2 changed files with 65 additions and 0 deletions

View file

@ -38,6 +38,8 @@
typedef struct hashtab_s hashtab_t;
typedef struct hashlink_s hashlink_t;
typedef int (*hash_select_t) (void *ele, void *data);
typedef void (*hash_action_t) (void *ele, void *data);
/** create a new hash table.
\param tsize table size. larger values will give better distribution, but
@ -213,6 +215,32 @@ size_t Hash_NumElements (hashtab_t *tab) __attribute__((pure));
*/
void **Hash_GetList (hashtab_t *tab);
/** list of all matching elements in the table.
\param tab the table to search
\param select function that tests for a match. The expected return value
is 0 for no match, non-zero for a match.
\param data context data passed to the \a select function
\return a null terminated list of element pointers for all matchin
elements in the table
\note it is the caller's responsibilty to free() the list.
returned list is guaranteed to be in reverse order of insertion for
elements with the same key. ie, deleting items from the list in list order
will delete the correct items.
*/
void **Hash_Select (hashtab_t *tab, hash_select_t select, void *data);
/** call a function for all elements in the table.
\param tab the table to search
\param action function to call for each elelemnt
\param data context data passed to the \a action function
call order is guaranteed to be in reverse order of insertion for
elements with the same key
*/
void Hash_ForEach (hashtab_t *tab, hash_action_t action, void *data);
/** dump statistics about the hash table
\param tab the table to dump
*/

View file

@ -447,6 +447,43 @@ Hash_GetList (hashtab_t *tab)
return list;
}
VISIBLE void **
Hash_Select (hashtab_t *tab, hash_select_t select, void *data)
{
void **list;
void **l;
size_t ind;
l = list = malloc ((tab->num_ele + 1) * sizeof (void *));
if (!list)
return 0;
for (ind = 0; ind < tab->tab_size; ind++) {
hashlink_t *lnk;
for (lnk = tab->tab[ind]; lnk; lnk = lnk->next) {
if (select (lnk->data, data)) {
*l++ = lnk->data;
}
}
}
*l++ = 0;
return list;
}
VISIBLE void
Hash_ForEach (hashtab_t *tab, hash_action_t action, void *data)
{
size_t ind;
for (ind = 0; ind < tab->tab_size; ind++) {
hashlink_t *lnk;
for (lnk = tab->tab[ind]; lnk; lnk = lnk->next) {
action (lnk->data, data);
}
}
}
static inline double
sqr (double x)
{