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