snac2/xs_set.h

114 lines
2.3 KiB
C
Raw Permalink Normal View History

2024-01-04 08:22:03 +00:00
/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
2022-09-28 08:27:01 +00:00
#ifndef _XS_SET_H
#define _XS_SET_H
typedef struct _xs_set {
int elems; /* number of hash entries */
int used; /* number of used hash entries */
2022-11-21 10:14:24 +00:00
int *hash; /* hashed offsets */
2023-01-28 16:49:02 +00:00
xs_list *list; /* list of stored data */
2022-09-28 08:27:01 +00:00
} xs_set;
2022-11-21 10:14:24 +00:00
void xs_set_init(xs_set *s);
2023-01-28 16:49:02 +00:00
xs_list *xs_set_result(xs_set *s);
2022-09-28 08:27:01 +00:00
void xs_set_free(xs_set *s);
2023-01-28 16:49:02 +00:00
int xs_set_add(xs_set *s, const xs_val *data);
2022-09-28 08:27:01 +00:00
#ifdef XS_IMPLEMENTATION
2022-11-21 10:14:24 +00:00
void xs_set_init(xs_set *s)
/* initializes a set */
{
/* arbitrary default */
s->elems = 256;
s->used = 0;
s->hash = xs_realloc(NULL, s->elems * sizeof(int));
s->list = xs_list_new();
2022-09-28 08:27:01 +00:00
2022-11-21 10:14:24 +00:00
memset(s->hash, '\0', s->elems * sizeof(int));
2022-09-28 08:27:01 +00:00
}
2023-01-28 16:49:02 +00:00
xs_list *xs_set_result(xs_set *s)
2022-11-28 11:19:57 +00:00
/* returns the set as a list and frees it */
2022-09-28 08:27:01 +00:00
{
2023-01-28 16:49:02 +00:00
xs_list *list = s->list;
2022-11-28 11:19:57 +00:00
s->list = NULL;
2022-11-21 10:14:24 +00:00
s->hash = xs_free(s->hash);
2022-11-28 11:19:57 +00:00
return list;
}
void xs_set_free(xs_set *s)
/* frees a set, dropping the list */
{
free(xs_set_result(s));
2022-09-28 08:27:01 +00:00
}
2022-11-21 10:14:24 +00:00
static int _store_hash(xs_set *s, const char *data, int value)
2022-09-28 08:27:01 +00:00
{
unsigned int hash, i;
int sz = xs_size(data);
2023-07-03 14:41:51 +00:00
hash = xs_hash_func(data, sz);
2022-09-28 08:27:01 +00:00
while (s->hash[(i = hash % s->elems)]) {
/* get the pointer to the stored data */
char *p = &s->list[s->hash[i]];
/* already here? */
if (memcmp(p, data, sz) == 0)
return 0;
/* try next value */
hash++;
}
2022-11-21 10:14:24 +00:00
/* store the new value */
s->hash[i] = value;
2022-09-28 08:27:01 +00:00
s->used++;
return 1;
}
2022-11-21 10:14:24 +00:00
2023-01-28 16:49:02 +00:00
int xs_set_add(xs_set *s, const xs_val *data)
2022-11-21 10:14:24 +00:00
/* adds the data to the set */
/* returns: 1 if added, 0 if already there */
{
/* is it 'full'? */
if (s->used >= s->elems / 2) {
char *p, *v;
/* expand! */
s->elems *= 2;
s->used = 0;
s->hash = xs_realloc(s->hash, s->elems * sizeof(int));
memset(s->hash, '\0', s->elems * sizeof(int));
/* add the list elements back */
p = s->list;
while (xs_list_iter(&p, &v))
_store_hash(s, v, v - s->list);
}
int ret = _store_hash(s, data, xs_size(s->list));
/* if it's new, add the data */
if (ret)
s->list = xs_list_append_m(s->list, data, xs_size(data));
return ret;
}
2022-09-28 08:27:01 +00:00
#endif /* XS_IMPLEMENTATION */
#endif /* XS_SET_H */