xs_set.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /* copyright (c) 2022 - 2024 grunfink et al. / 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. int *hash; /* hashed offsets */
  8. xs_list *list; /* list of stored data */
  9. } xs_set;
  10. void xs_set_init(xs_set *s);
  11. xs_list *xs_set_result(xs_set *s);
  12. void xs_set_free(xs_set *s);
  13. int xs_set_add(xs_set *s, const xs_val *data);
  14. #ifdef XS_IMPLEMENTATION
  15. void xs_set_init(xs_set *s)
  16. /* initializes a set */
  17. {
  18. /* arbitrary default */
  19. s->elems = 256;
  20. s->used = 0;
  21. s->hash = xs_realloc(NULL, s->elems * sizeof(int));
  22. s->list = xs_list_new();
  23. memset(s->hash, '\0', s->elems * sizeof(int));
  24. }
  25. xs_list *xs_set_result(xs_set *s)
  26. /* returns the set as a list and frees it */
  27. {
  28. xs_list *list = s->list;
  29. s->list = NULL;
  30. s->hash = xs_free(s->hash);
  31. return list;
  32. }
  33. void xs_set_free(xs_set *s)
  34. /* frees a set, dropping the list */
  35. {
  36. xs_free(xs_set_result(s));
  37. }
  38. static int _store_hash(xs_set *s, const char *data, int value)
  39. {
  40. unsigned int hash, i;
  41. int sz = xs_size(data);
  42. hash = xs_hash_func(data, sz);
  43. while (s->hash[(i = hash % s->elems)]) {
  44. /* get the pointer to the stored data */
  45. char *p = &s->list[s->hash[i]];
  46. /* already here? */
  47. if (memcmp(p, data, sz) == 0)
  48. return 0;
  49. /* try next value */
  50. hash++;
  51. }
  52. /* store the new value */
  53. s->hash[i] = value;
  54. s->used++;
  55. return 1;
  56. }
  57. int xs_set_add(xs_set *s, const xs_val *data)
  58. /* adds the data to the set */
  59. /* returns: 1 if added, 0 if already there */
  60. {
  61. /* is it 'full'? */
  62. if (s->used >= s->elems / 2) {
  63. const xs_val *v;
  64. /* expand! */
  65. s->elems *= 2;
  66. s->used = 0;
  67. s->hash = xs_realloc(s->hash, s->elems * sizeof(int));
  68. memset(s->hash, '\0', s->elems * sizeof(int));
  69. /* add the list elements back */
  70. xs_list_foreach(s->list, v)
  71. _store_hash(s, v, v - s->list);
  72. }
  73. int ret = _store_hash(s, data, xs_size(s->list));
  74. /* if it's new, add the data */
  75. if (ret)
  76. s->list = xs_list_append(s->list, data);
  77. return ret;
  78. }
  79. #endif /* XS_IMPLEMENTATION */
  80. #endif /* XS_SET_H */