1
0

xs_set.h 2.8 KB

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