diff --git a/Makefile b/Makefile index d3a45c9..d0e09d2 100644 --- a/Makefile +++ b/Makefile @@ -15,13 +15,14 @@ dep: $(CC) -I/usr/local/include -MM *.c > makefile.depend activitypub.o: activitypub.c xs.h xs_encdec.h xs_json.h xs_curl.h \ - xs_mime.h xs_openssl.h snac.h + xs_mime.h xs_openssl.h xs_regex.h snac.h data.o: data.c xs.h xs_io.h xs_json.h xs_openssl.h snac.h -html.o: html.c xs.h xs_io.h xs_json.h xs_regex.h snac.h +html.o: html.c xs.h xs_io.h xs_encdec.h xs_json.h xs_regex.h xs_set.h \ + snac.h http.o: http.c xs.h xs_io.h xs_encdec.h xs_openssl.h xs_curl.h snac.h httpd.o: httpd.c xs.h xs_io.h xs_encdec.h xs_json.h xs_socket.h \ xs_httpd.h snac.h main.o: main.c xs.h xs_io.h xs_encdec.h xs_json.h snac.h snac.o: snac.c xs.h xs_io.h xs_encdec.h xs_json.h xs_curl.h xs_openssl.h \ - xs_socket.h xs_httpd.h xs_mime.h xs_regex.h snac.h + xs_socket.h xs_httpd.h xs_mime.h xs_regex.h xs_set.h snac.h webfinger.o: webfinger.c xs.h xs_encdec.h xs_json.h xs_curl.h snac.h diff --git a/html.c b/html.c index 21ee151..1e7788d 100644 --- a/html.c +++ b/html.c @@ -6,6 +6,7 @@ #include "xs_encdec.h" #include "xs_json.h" #include "xs_regex.h" +#include "xs_set.h" #include "snac.h" diff --git a/snac.c b/snac.c index d0ab4e9..3c9fd40 100644 --- a/snac.c +++ b/snac.c @@ -13,6 +13,7 @@ #include "xs_httpd.h" #include "xs_mime.h" #include "xs_regex.h" +#include "xs_set.h" #include "snac.h" 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 @@ +/* copyright (c) 2022 grunfink - MIT license */ + +#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 */ + d_char *list; /* list of stored data */ + int hash[0]; /* hashed offsets */ +} xs_set; + +xs_set *xs_set_new(int elems); +void xs_set_free(xs_set *s); +int xs_set_add(xs_set *s, char *data); + + +#ifdef XS_IMPLEMENTATION + +xs_set *xs_set_new(int elems) +/* creates a new set with a maximum of size hashed data */ +{ + int sz = sizeof(struct _xs_set) + sizeof(int) * elems; + xs_set *s = calloc(sz, 1); + + /* initialize */ + s->elems = elems; + s->list = xs_list_new(); + + return s; +} + + +void xs_set_free(xs_set *s) +/* frees a set */ +{ + free(s->list); + free(s); +} + + +unsigned int _xs_set_hash(char *data, int size) +{ + unsigned int hash = 0x666; + int n; + + for (n = 0; n < size; n++) { + hash ^= data[n]; + hash *= 111111111; + } + + return hash ^ hash >> 16; +} + + +int xs_set_add(xs_set *s, char *data) +/* adds the data to the set */ +/* returns: 1 if added, 0 if already there, -1 if it's full */ +{ + unsigned int hash, i; + int sz = xs_size(data); + + hash = _xs_set_hash(data, sz); + + 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++; + } + + /* is it full? fail */ + if (s->used == s->elems / 2) + return -1; + + /* store the position */ + s->hash[i] = xs_size(s->list); + + /* add the data */ + s->list = xs_list_append_m(s->list, data, sz); + + s->used++; + + return 1; +} + +#endif /* XS_IMPLEMENTATION */ + +#endif /* XS_SET_H */ \ No newline at end of file