diff options
Diffstat (limited to 'xs_set.h')
| -rw-r--r-- | xs_set.h | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/xs_set.h b/xs_set.h new file mode 100644 index 0000000..c983ce6 --- /dev/null +++ b/xs_set.h | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* copyright (c) 2022 grunfink - MIT license */ | ||
| 2 | |||
| 3 | #ifndef _XS_SET_H | ||
| 4 | |||
| 5 | #define _XS_SET_H | ||
| 6 | |||
| 7 | typedef struct _xs_set { | ||
| 8 | int elems; /* number of hash entries */ | ||
| 9 | int used; /* number of used hash entries */ | ||
| 10 | d_char *list; /* list of stored data */ | ||
| 11 | int hash[0]; /* hashed offsets */ | ||
| 12 | } xs_set; | ||
| 13 | |||
| 14 | xs_set *xs_set_new(int elems); | ||
| 15 | void xs_set_free(xs_set *s); | ||
| 16 | int xs_set_add(xs_set *s, char *data); | ||
| 17 | |||
| 18 | |||
| 19 | #ifdef XS_IMPLEMENTATION | ||
| 20 | |||
| 21 | xs_set *xs_set_new(int elems) | ||
| 22 | /* creates a new set with a maximum of size hashed data */ | ||
| 23 | { | ||
| 24 | int sz = sizeof(struct _xs_set) + sizeof(int) * elems; | ||
| 25 | xs_set *s = calloc(sz, 1); | ||
| 26 | |||
| 27 | /* initialize */ | ||
| 28 | s->elems = elems; | ||
| 29 | s->list = xs_list_new(); | ||
| 30 | |||
| 31 | return s; | ||
| 32 | } | ||
| 33 | |||
| 34 | |||
| 35 | void xs_set_free(xs_set *s) | ||
| 36 | /* frees a set */ | ||
| 37 | { | ||
| 38 | free(s->list); | ||
| 39 | free(s); | ||
| 40 | } | ||
| 41 | |||
| 42 | |||
| 43 | unsigned int _xs_set_hash(char *data, int size) | ||
| 44 | { | ||
| 45 | unsigned int hash = 0x666; | ||
| 46 | int n; | ||
| 47 | |||
| 48 | for (n = 0; n < size; n++) { | ||
| 49 | hash ^= data[n]; | ||
| 50 | hash *= 111111111; | ||
| 51 | } | ||
| 52 | |||
| 53 | return hash ^ hash >> 16; | ||
| 54 | } | ||
| 55 | |||
| 56 | |||
| 57 | int xs_set_add(xs_set *s, char *data) | ||
| 58 | /* adds the data to the set */ | ||
| 59 | /* returns: 1 if added, 0 if already there, -1 if it's full */ | ||
| 60 | { | ||
| 61 | unsigned int hash, i; | ||
| 62 | int sz = xs_size(data); | ||
| 63 | |||
| 64 | hash = _xs_set_hash(data, sz); | ||
| 65 | |||
| 66 | while (s->hash[(i = hash % s->elems)]) { | ||
| 67 | /* get the pointer to the stored data */ | ||
| 68 | char *p = &s->list[s->hash[i]]; | ||
| 69 | |||
| 70 | /* already here? */ | ||
| 71 | if (memcmp(p, data, sz) == 0) | ||
| 72 | return 0; | ||
| 73 | |||
| 74 | /* try next value */ | ||
| 75 | hash++; | ||
| 76 | } | ||
| 77 | |||
| 78 | /* is it full? fail */ | ||
| 79 | if (s->used == s->elems / 2) | ||
| 80 | return -1; | ||
| 81 | |||
| 82 | /* store the position */ | ||
| 83 | s->hash[i] = xs_size(s->list); | ||
| 84 | |||
| 85 | /* add the data */ | ||
| 86 | s->list = xs_list_append_m(s->list, data, sz); | ||
| 87 | |||
| 88 | s->used++; | ||
| 89 | |||
| 90 | return 1; | ||
| 91 | } | ||
| 92 | |||
| 93 | #endif /* XS_IMPLEMENTATION */ | ||
| 94 | |||
| 95 | #endif /* XS_SET_H */ \ No newline at end of file | ||