nagios4/lib/fanout.c

116 lines
2.1 KiB
C
Raw Permalink Normal View History

2017-05-19 23:37:19 +02:00
#include <unistd.h>
#include "fanout.h"
struct fanout_entry {
unsigned long key;
void *data;
struct fanout_entry *next;
};
struct fanout_table {
unsigned long alloc;
struct fanout_entry **entries;
};
fanout_table *fanout_create(unsigned long size)
{
fanout_table *t = calloc(1, sizeof(*t));
if (!t)
return NULL;
t->entries = calloc(size, sizeof(struct fanout_entry *));
if (!t->entries) {
free(t);
return NULL;
}
t->alloc = size;
return t;
}
void fanout_destroy(fanout_table *t, void (*destructor)(void *))
{
unsigned long i;
struct fanout_entry **entries, *next;
if (!t || !t->entries || !t->alloc)
return;
/* protect against destructors calling fanout_remove() */
entries = t->entries;
t->entries = NULL;
for (i = 0; i < t->alloc; i++) {
struct fanout_entry *entry;
for (entry = entries[i]; entry; entry = next) {
void *data = entry->data;
next = entry->next;
free(entry);
if (destructor) {
destructor(data);
}
}
}
free(entries);
free(t);
}
int fanout_add(struct fanout_table *t, unsigned long key, void *data)
{
struct fanout_entry *entry;
if (!t || !t->entries || !t->alloc || !data)
return -1;
entry = calloc(1, sizeof(*entry));
if (!entry)
return -1;
entry->key = key;
entry->data = data;
entry->next = t->entries[key % t->alloc];
t->entries[key % t->alloc] = entry;
return 0;
}
void *fanout_get(fanout_table *t, unsigned long key)
{
struct fanout_entry *entry;
unsigned long slot;
if (!t || !t->entries || !t->alloc)
return NULL;
slot = key % t->alloc;
for (entry = t->entries[slot]; entry; entry = entry->next) {
if (entry->key == key)
return entry->data;
}
return NULL;
}
void *fanout_remove(fanout_table *t, unsigned long key)
{
struct fanout_entry *entry, *next, *prev = NULL;
unsigned long slot;
if (!t || !t->entries || !t->alloc)
return NULL;
slot = key % t->alloc;
for (entry = t->entries[slot]; entry; prev = entry, entry = next) {
next = entry->next;
if (entry->key == key) {
void *data = entry->data;
if (prev) {
prev->next = entry->next;
} else {
t->entries[slot] = entry->next;
}
free(entry);
return data;
}
}
return NULL;
}