File Coverage

keyval.h
Criterion Covered Total %
statement 142 142 100.0
branch 78 88 88.6
condition n/a
subroutine n/a
pod n/a
total 220 230 95.6


line stmt bran cond sub pod time code
1             #ifndef MPU_KEYVAL_H
2             #define MPU_KEYVAL_H
3              
4             /* This includes:
5             * keyval_t simple key/val type, both UV
6             * set a key value set, with "add" function for new=old+new
7             * setlist key (UV) plus dynamic array of UVs. "append" functionality
8             *
9             * Key=0 is not allowed.
10             */
11              
12              
13             #include "ptypes.h"
14              
15             typedef struct {
16             UV key;
17             UV val;
18             } keyval_t;
19              
20             typedef struct {
21             keyval_t *keyval;
22             UV mask;
23             long maxsize;
24             long size;
25             } set_t;
26              
27              
28              
29              
30             #if BITS_PER_WORD == 32
31             static UV _hash(UV x) {
32             x = ((x >> 16) ^ x) * 0x45d9f3b;
33             x = ((x >> 16) ^ x) * 0x45d9f3b;
34             x = (x >> 16) ^ x;
35             return x;
36             }
37             #else
38 165834           static UV _hash(UV x) {
39 165834           x = (x ^ (x >> 30)) * UVCONST(0xbf58476d1ce4e5b9);
40 165834           x = (x ^ (x >> 27)) * UVCONST(0x94d049bb133111eb);
41 165834           x = x ^ (x >> 31);
42 165834           return x;
43             }
44             #endif
45              
46              
47             /******************************************************************************/
48              
49 774           static void init_set(set_t *S, UV isize) {
50 774           int bits = 0;
51 6789 100         while (isize > 0) {
52 6015           bits++;
53 6015           isize >>= 1;
54             }
55 774           S->size = 0;
56 774           S->maxsize = UVCONST(1) << ((bits < 3) ? 3 : bits);
57 774           S->mask = S->maxsize - 1;
58 774 50         Newz(0,S->keyval,S->maxsize,keyval_t);
59 774           }
60              
61 774           static void free_set(set_t *S) {
62 774           S->size = S->maxsize = 0;
63 774           Safefree(S->keyval);
64 774           }
65              
66 10           static void _set_expand(set_t *S) {
67 10           long i, max = S->maxsize, newmax = max*2, newsize = 0, newmask = newmax-1;
68             keyval_t *nkv;
69 10 50         Newz(0, nkv, newmax, keyval_t);
70 146 100         for (i = 0; i < max; i++) {
71 136           UV key = S->keyval[i].key;
72 136 100         if (key != 0) {
73 105           UV h = _hash(key) & newmask;
74 131 100         while (nkv[h].key > 0 && nkv[h].key != key)
    50          
75 26           h = (h+1) & newmask;
76 105           nkv[h] = S->keyval[i];
77 105           newsize++;
78             }
79             }
80 10           Safefree(S->keyval);
81 10           S->keyval = nkv;
82 10           S->maxsize = newmax;
83 10           S->mask = newmax-1;
84 10 50         MPUassert(newsize == S->size, "keyval set size mismatch");
85 10           }
86              
87 84177           static long set_search(set_t S, UV key) {
88 84177           long h = _hash(key) & S.mask;
89 105841 100         while (S.keyval[h].key > 0 && S.keyval[h].key != key)
    100          
90 21664           h = (h+1) & S.mask; /* Linear probe */
91 84177 100         return (S.keyval[h].key == key) ? h : -1;
92             }
93              
94 84177           static UV set_getval(set_t S, UV key) {
95 84177           long i = set_search(S, key);
96 84177 100         return (i == -1) ? 0 : S.keyval[i].val;
97             }
98              
99 80832           static void set_addsum(set_t *S, keyval_t kv) {
100 80832           UV h = _hash(kv.key) & S->mask;
101 95206 100         while (S->keyval[h].key > 0 && S->keyval[h].key != kv.key)
    100          
102 14374           h = (h+1) & S->mask;
103 80832 100         if (S->keyval[h].key == kv.key) {
104             /* if (kv.val > UV_MAX - S->keyval[h].val) croak("add overflow\n"); */
105 38652           S->keyval[h].val += kv.val;
106             } else {
107 42180           S->keyval[h] = kv;
108 42180 100         if (S->size++ > 0.65 * S->maxsize)
109 10           _set_expand(S);
110             }
111 80832           }
112              
113 734           static void set_merge(set_t *S, set_t T) {
114             long j;
115 511238 100         for (j = 0; j < T.maxsize; j++)
116 510504 100         if (T.keyval[j].key > 0)
117 40396           set_addsum(S, T.keyval[j]);
118 734           }
119              
120             /******************************************************************************/
121              
122             typedef struct {
123             UV key;
124             UV *vals;
125             long size;
126             long maxsize;
127             } keylist_t;
128              
129             typedef struct {
130             keylist_t *keylist;
131             UV mask;
132             long maxsize;
133             long size;
134             } set_list_t;
135              
136 42           static void init_setlist(set_list_t *L, UV isize) {
137 42           int bits = 0;
138 214 100         while (isize > 0) {
139 172           bits++;
140 172           isize >>= 1;
141             }
142 42           L->size = 0;
143 42           L->maxsize = UVCONST(1) << ((bits < 3) ? 3 : bits);
144 42           L->mask = L->maxsize - 1;
145 42 50         Newz(0, L->keylist, L->maxsize, keylist_t);
146 42           }
147              
148 42           static void free_setlist(set_list_t *L) {
149             long i;
150 1122 100         for (i = 0; i < L->maxsize; i++)
151 1080 100         if (L->keylist[i].size > 0)
152 181           Safefree(L->keylist[i].vals);
153 42           Safefree(L->keylist);
154 42           L->size = L->maxsize = 0;
155 42           }
156              
157 2           static void _setlist_expand(set_list_t *L) {
158 2           long i, max = L->maxsize, newmax = max*2, newsize = 0, newmask = newmax-1;
159             keylist_t *nlist;
160 2 50         Newz(0, nlist, newmax, keylist_t);
161 34 100         for (i = 0; i < max; i++) {
162 32           UV key = L->keylist[i].key;
163 32 100         if (key != 0) {
164 24           UV h = _hash(key) & newmask;
165 27 100         while (nlist[h].key > 0 && nlist[h].key != key)
    50          
166 3           h = (h+1) & newmask;
167 24           nlist[h] = L->keylist[i];
168 24           newsize++;
169             }
170             }
171 2           Safefree(L->keylist);
172 2           L->keylist = nlist;
173 2           L->maxsize = newmax;
174 2           L->mask = newmax-1;
175 2 50         MPUassert(newsize == L->size, "setlist size mismatch");
176 2           }
177              
178 439           static long setlist_search(set_list_t L, UV key) {
179 439           long h = _hash(key) & L.mask;
180 461 100         while (L.keylist[h].key > 0 && L.keylist[h].key != key)
    100          
181 22           h = (h+1) & L.mask; /* Linear probe */
182 439 100         return (L.keylist[h].key == key) ? h : -1;
183             }
184              
185 257           static void setlist_addlist(set_list_t *L, UV key, long nvals, UV* list, UV mult) {
186             UV *vptr;
187 257           long j, h = _hash(key) & L->mask;
188 293 100         while (L->keylist[h].key > 0 && L->keylist[h].key != key)
    100          
189 36           h = (h+1) & L->mask;
190 257 100         if (L->keylist[h].key == key) {
191 76           long size = L->keylist[h].size;
192 76           long maxsize = L->keylist[h].maxsize;
193 76 100         if (size + nvals > maxsize) {
194 2           maxsize = 2 * (size+nvals);
195 2 50         Renew(L->keylist[h].vals, maxsize, UV);
196 2           L->keylist[h].maxsize = maxsize;
197             }
198 76           vptr = L->keylist[h].vals + size;
199 201 100         for (j = 0; j < nvals; j++) {
200             /* if (list[j] > UV_MAX/mult) croak("overflow in addlist mult"); */
201 125           vptr[j] = list[j] * mult;
202             }
203 76           L->keylist[h].size = size + nvals;
204             } else {
205 181 100         long maxsize = (nvals < 5) ? 12 : (nvals+1) * 2;
206 181 50         New(0, L->keylist[h].vals, maxsize, UV);
207 181           L->keylist[h].maxsize = maxsize;
208 181           vptr = L->keylist[h].vals;
209 383 100         for (j = 0; j < nvals; j++) {
210             /* if (list[j] > UV_MAX/mult) croak("overflow in addlist mult"); */
211 202           vptr[j] = list[j] * mult;
212             }
213 181           L->keylist[h].size = nvals;
214 181           L->keylist[h].key = key;
215 181 100         if (L->size++ > 0.65 * L->maxsize)
216 2           _setlist_expand(L);
217             }
218 257           }
219              
220 5           static void setlist_addval(set_list_t *L, UV key, UV val) {
221 5           setlist_addlist(L, key, 1, &val, 1);
222 5           }
223              
224 439           static UV* setlist_getlist(UV *nvals, set_list_t L, UV key) {
225 439           long i = setlist_search(L, key);
226 439 100         if (i == -1) {
227 298           *nvals = 0;
228 298           return 0;
229             }
230 141           *nvals = L.keylist[i].size;
231 141           return L.keylist[i].vals;
232             }
233              
234 37           static void setlist_merge(set_list_t *L, set_list_t T) {
235             long j;
236 845 100         for (j = 0; j < T.maxsize; j++) {
237 808 100         if (T.keylist[j].key > 0) {
238 116           UV key = T.keylist[j].key;
239 116           UV nvals = T.keylist[j].size;
240 116           UV *vals = T.keylist[j].vals;
241 116           setlist_addlist(L, key, nvals, vals, 1);
242             }
243             }
244 37           }
245              
246             #if 0
247             static void setlist_zerolist(set_list_t *L, UV key) {
248             long i = setlist_search(*L, key);
249             if (i != -1) {
250             Safefree(L->keylist[i].vals);
251             L->keylist[i].vals = 0;
252             L->keylist[i].size = L->keylist[i].maxsize = 0;
253             }
254             }
255             #endif
256              
257             #endif