xs_set.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. int *hash; /* hashed offsets */
  8. d_char *list; /* list of stored data */
  9. } xs_set;
  10. void xs_set_init(xs_set *s);
  11. d_char *xs_set_result(xs_set *s);
  12. void xs_set_free(xs_set *s);
  13. int xs_set_add(xs_set *s, const char *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. d_char *xs_set_result(xs_set *s)
  26. /* returns the set as a list and frees it */
  27. {
  28. d_char *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. free(xs_set_result(s));
  37. }
  38. static unsigned int _calc_hash(const char *data, int size)
  39. {
  40. unsigned int hash = 0x666;
  41. int n;
  42. for (n = 0; n < size; n++) {
  43. hash ^= data[n];
  44. hash *= 111111111;
  45. }
  46. return hash ^ hash >> 16;
  47. }
  48. static int _store_hash(xs_set *s, const char *data, int value)
  49. {
  50. unsigned int hash, i;
  51. int sz = xs_size(data);
  52. hash = _calc_hash(data, sz);
  53. while (s->hash[(i = hash % s->elems)]) {
  54. /* get the pointer to the stored data */
  55. char *p = &s->list[s->hash[i]];
  56. /* already here? */
  57. if (memcmp(p, data, sz) == 0)
  58. return 0;
  59. /* try next value */
  60. hash++;
  61. }
  62. /* store the new value */
  63. s->hash[i] = value;
  64. s->used++;
  65. return 1;
  66. }
  67. int xs_set_add(xs_set *s, const char *data)
  68. /* adds the data to the set */
  69. /* returns: 1 if added, 0 if already there */
  70. {
  71. /* is it 'full'? */
  72. if (s->used >= s->elems / 2) {
  73. char *p, *v;
  74. /* expand! */
  75. s->elems *= 2;
  76. s->used = 0;
  77. s->hash = xs_realloc(s->hash, s->elems * sizeof(int));
  78. memset(s->hash, '\0', s->elems * sizeof(int));
  79. /* add the list elements back */
  80. p = s->list;
  81. while (xs_list_iter(&p, &v))
  82. _store_hash(s, v, v - s->list);
  83. }
  84. int ret = _store_hash(s, data, xs_size(s->list));
  85. /* if it's new, add the data */
  86. if (ret)
  87. s->list = xs_list_append_m(s->list, data, xs_size(data));
  88. return ret;
  89. }
  90. #endif /* XS_IMPLEMENTATION */
  91. #endif /* XS_SET_H */