-
Notifications
You must be signed in to change notification settings - Fork 12
/
iset.c
86 lines (77 loc) · 1.91 KB
/
iset.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <stdlib.h>
#include <string.h>
#include "roff.h"
#define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
#define CNTMIN (1 << 10)
#define CNTMAX (1 << 20)
/* iset structure to map integers to sets */
struct iset {
int **set;
int *sz;
int *len;
int cnt;
};
static void iset_extend(struct iset *iset, int cnt)
{
iset->set = mextend(iset->set, iset->cnt, cnt, sizeof(iset->set[0]));
iset->sz = mextend(iset->sz, iset->cnt, cnt, sizeof(iset->sz[0]));
iset->len = mextend(iset->len, iset->cnt, cnt, sizeof(iset->len[0]));
iset->cnt = cnt;
}
struct iset *iset_make(void)
{
struct iset *iset = xmalloc(sizeof(*iset));
memset(iset, 0, sizeof(*iset));
iset_extend(iset, CNTMIN);
return iset;
}
void iset_free(struct iset *iset)
{
int i;
for (i = 0; i < iset->cnt; i++)
free(iset->set[i]);
free(iset->set);
free(iset->len);
free(iset->sz);
free(iset);
}
int *iset_get(struct iset *iset, int key)
{
return key >= 0 && key < iset->cnt ? iset->set[key] : NULL;
}
int iset_len(struct iset *iset, int key)
{
return key >= 0 && key < iset->cnt ? iset->len[key] : 0;
}
void iset_put(struct iset *iset, int key, int ent)
{
if (key < 0 || key >= CNTMAX)
return;
if (key >= iset->cnt)
iset_extend(iset, ALIGN(key + 1, CNTMIN));
if (key >= 0 && key < iset->cnt && iset->len[key] + 1 >= iset->sz[key]) {
int olen = iset->sz[key];
int nlen = olen ? olen * 2 : 8;
void *nset = xmalloc(nlen * sizeof(iset->set[key][0]));
if (iset->set[key]) {
memcpy(nset, iset->set[key],
olen * sizeof(iset->set[key][0]));
free(iset->set[key]);
}
iset->sz[key] = nlen;
iset->set[key] = nset;
}
iset->set[key][iset->len[key]++] = ent;
iset->set[key][iset->len[key]] = -1;
}
/* check entry membership */
int iset_has(struct iset *iset, int key, int ent)
{
int i;
if (key < 0 || key >= iset->cnt || iset->len[key] == 0)
return 0;
for (i = 0; i < iset->len[key]; i++)
if (iset->set[key][i] == ent)
return 1;
return 0;
}