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