xs_set.h 2.5 KB

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