xs_set.h 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* copyright (c) 2022 grunfink - MIT license */
  2. #ifndef _XS_SET_H
  3. #define _XS_SET_H
  4. typedef struct _xs_set {
  5. int elems; /* number of hash entries */
  6. int used; /* number of used hash entries */
  7. d_char *list; /* list of stored data */
  8. int hash[]; /* hashed offsets */
  9. } xs_set;
  10. xs_set *xs_set_new(int elems);
  11. void xs_set_free(xs_set *s);
  12. int xs_set_add(xs_set *s, const char *data);
  13. #ifdef XS_IMPLEMENTATION
  14. xs_set *xs_set_new(int elems)
  15. /* creates a new set with a maximum of size hashed data */
  16. {
  17. int sz = sizeof(struct _xs_set) + sizeof(int) * elems;
  18. xs_set *s = xs_realloc(NULL, sz);
  19. memset(s, '\0', sz);
  20. /* initialize */
  21. s->elems = elems;
  22. s->list = xs_list_new();
  23. return s;
  24. }
  25. void xs_set_free(xs_set *s)
  26. /* frees a set */
  27. {
  28. xs_free(s->list);
  29. xs_free(s);
  30. }
  31. unsigned int _xs_set_hash(const char *data, int size)
  32. {
  33. unsigned int hash = 0x666;
  34. int n;
  35. for (n = 0; n < size; n++) {
  36. hash ^= data[n];
  37. hash *= 111111111;
  38. }
  39. return hash ^ hash >> 16;
  40. }
  41. int xs_set_add(xs_set *s, const char *data)
  42. /* adds the data to the set */
  43. /* returns: 1 if added, 0 if already there, -1 if it's full */
  44. {
  45. unsigned int hash, i;
  46. int sz = xs_size(data);
  47. hash = _xs_set_hash(data, sz);
  48. while (s->hash[(i = hash % s->elems)]) {
  49. /* get the pointer to the stored data */
  50. char *p = &s->list[s->hash[i]];
  51. /* already here? */
  52. if (memcmp(p, data, sz) == 0)
  53. return 0;
  54. /* try next value */
  55. hash++;
  56. }
  57. /* is it full? fail */
  58. if (s->used == s->elems / 2)
  59. return -1;
  60. /* store the position */
  61. s->hash[i] = xs_size(s->list);
  62. /* add the data */
  63. s->list = xs_list_append_m(s->list, data, sz);
  64. s->used++;
  65. return 1;
  66. }
  67. #endif /* XS_IMPLEMENTATION */
  68. #endif /* XS_SET_H */