smbidmap.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "headers.h"
  2. #define INITIALCHUNKSIZE 10
  3. typedef struct Entry {
  4. void *p;
  5. long freechain;
  6. } Entry;
  7. struct SmbIdMap {
  8. Entry *array;
  9. ulong entries;
  10. long freeindex;
  11. };
  12. SmbIdMap *
  13. smbidmapnew(void)
  14. {
  15. SmbIdMap *m;
  16. m = smbemallocz(sizeof(SmbIdMap), 1);
  17. m->freeindex = -1;
  18. return m;
  19. }
  20. void
  21. smbidmapremovebyid(SmbIdMap *m, long id)
  22. {
  23. if (m == nil)
  24. return;
  25. assert(id > 0);
  26. id--;
  27. assert(id >= 0 && id < m->entries);
  28. assert(m->array[id].freechain == -2);
  29. m->array[id].freechain = m->freeindex;
  30. m->freeindex = id;
  31. }
  32. void
  33. smbidmapremove(SmbIdMap *m, void *thing)
  34. {
  35. long id;
  36. if (m == nil)
  37. return;
  38. id = *(long *)thing;
  39. smbidmapremovebyid(m, id);
  40. }
  41. void
  42. smbidmapremoveif(SmbIdMap *m, int (*f)(void *p, void *arg), void *arg)
  43. {
  44. int i;
  45. if (m == nil)
  46. return;
  47. for (i = 0; i < m->entries; i++)
  48. if (m->array[i].freechain == -2 && (*f)(m->array[i].p, arg))
  49. smbidmapremovebyid(m, i + 1);
  50. }
  51. static void
  52. grow(SmbIdMap *m)
  53. {
  54. long x;
  55. long oldentries = m->entries;
  56. if (m->entries == 0)
  57. m->entries = INITIALCHUNKSIZE;
  58. else
  59. m->entries *= 2;
  60. smberealloc(&m->array, sizeof(Entry) * m->entries);
  61. for (x = m->entries - 1; x >= oldentries; x--) {
  62. m->array[x].freechain = m->freeindex;
  63. m->freeindex = x;
  64. }
  65. }
  66. long
  67. smbidmapadd(SmbIdMap *m, void *p)
  68. {
  69. long i;
  70. if (m->freeindex < 0)
  71. grow(m);
  72. i = m->freeindex;
  73. m->freeindex = m->array[i].freechain;
  74. m->array[i].freechain = -2;
  75. m->array[i].p = p;
  76. *(long *)p = i + 1;
  77. return i + 1;
  78. }
  79. void *
  80. smbidmapfind(SmbIdMap *m, long id)
  81. {
  82. if (m == nil)
  83. return nil;
  84. if (id <= 0)
  85. return nil;
  86. id--;
  87. if (id < 0 || id > m->entries || m->array[id].freechain != -2)
  88. return nil;
  89. return m->array[id].p;
  90. }
  91. void
  92. smbidmapfree(SmbIdMap **mp, SMBIDMAPAPPLYFN *freefn, void *magic)
  93. {
  94. SmbIdMap *m = *mp;
  95. if (m) {
  96. long i;
  97. if (freefn) {
  98. for (i = 0; i < m->entries; i++)
  99. if (m->array[i].freechain == -2)
  100. (*freefn)(magic, m->array[i].p);
  101. }
  102. free(m->array);
  103. free(m);
  104. *mp = nil;
  105. }
  106. }
  107. void
  108. smbidmapapply(SmbIdMap *m, SMBIDMAPAPPLYFN *applyfn, void *magic)
  109. {
  110. if (m) {
  111. long i;
  112. for (i = 0; i < m->entries; i++)
  113. if (m->array[i].freechain == -2)
  114. (*applyfn)(magic, m->array[i].p);
  115. }
  116. }