Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 *
17
smbidmapnew(void)
18
{
19
	SmbIdMap *m;
20
	m = smbemallocz(sizeof(SmbIdMap), 1);
21
	m->freeindex = -1;
22
	return m;
23
}
24
 
25
void
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
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
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
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
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 *
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
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
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
}