smbidmap.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "headers.h"
  10. #define INITIALCHUNKSIZE 10
  11. typedef struct Entry {
  12. void *p;
  13. int32_t freechain;
  14. } Entry;
  15. struct SmbIdMap {
  16. Entry *array;
  17. uint32_t entries;
  18. int32_t freeindex;
  19. };
  20. SmbIdMap *
  21. smbidmapnew(void)
  22. {
  23. SmbIdMap *m;
  24. m = smbemallocz(sizeof(SmbIdMap), 1);
  25. m->freeindex = -1;
  26. return m;
  27. }
  28. void
  29. smbidmapremovebyid(SmbIdMap *m, int32_t id)
  30. {
  31. if (m == nil)
  32. return;
  33. assert(id > 0);
  34. id--;
  35. assert(id >= 0 && id < m->entries);
  36. assert(m->array[id].freechain == -2);
  37. m->array[id].freechain = m->freeindex;
  38. m->freeindex = id;
  39. }
  40. void
  41. smbidmapremove(SmbIdMap *m, void *thing)
  42. {
  43. int32_t id;
  44. if (m == nil)
  45. return;
  46. id = *(int32_t *)thing;
  47. smbidmapremovebyid(m, id);
  48. }
  49. void
  50. smbidmapremoveif(SmbIdMap *m, int (*f)(void *p, void *arg), void *arg)
  51. {
  52. int i;
  53. if (m == nil)
  54. return;
  55. for (i = 0; i < m->entries; i++)
  56. if (m->array[i].freechain == -2 && (*f)(m->array[i].p, arg))
  57. smbidmapremovebyid(m, i + 1);
  58. }
  59. static void
  60. grow(SmbIdMap *m)
  61. {
  62. int32_t x;
  63. int32_t oldentries = m->entries;
  64. if (m->entries == 0)
  65. m->entries = INITIALCHUNKSIZE;
  66. else
  67. m->entries *= 2;
  68. smberealloc(&m->array, sizeof(Entry) * m->entries);
  69. for (x = m->entries - 1; x >= oldentries; x--) {
  70. m->array[x].freechain = m->freeindex;
  71. m->freeindex = x;
  72. }
  73. }
  74. int32_t
  75. smbidmapadd(SmbIdMap *m, void *p)
  76. {
  77. int32_t i;
  78. if (m->freeindex < 0)
  79. grow(m);
  80. i = m->freeindex;
  81. m->freeindex = m->array[i].freechain;
  82. m->array[i].freechain = -2;
  83. m->array[i].p = p;
  84. *(int32_t *)p = i + 1;
  85. return i + 1;
  86. }
  87. void *
  88. smbidmapfind(SmbIdMap *m, int32_t id)
  89. {
  90. if (m == nil)
  91. return nil;
  92. if (id <= 0)
  93. return nil;
  94. id--;
  95. if (id < 0 || id > m->entries || m->array[id].freechain != -2)
  96. return nil;
  97. return m->array[id].p;
  98. }
  99. void
  100. smbidmapfree(SmbIdMap **mp, SMBIDMAPAPPLYFN *freefn, void *magic)
  101. {
  102. SmbIdMap *m = *mp;
  103. if (m) {
  104. int32_t i;
  105. if (freefn) {
  106. for (i = 0; i < m->entries; i++)
  107. if (m->array[i].freechain == -2)
  108. (*freefn)(magic, m->array[i].p);
  109. }
  110. free(m->array);
  111. free(m);
  112. *mp = nil;
  113. }
  114. }
  115. void
  116. smbidmapapply(SmbIdMap *m, SMBIDMAPAPPLYFN *applyfn, void *magic)
  117. {
  118. if (m) {
  119. int32_t i;
  120. for (i = 0; i < m->entries; i++)
  121. if (m->array[i].freechain == -2)
  122. (*applyfn)(magic, m->array[i].p);
  123. }
  124. }