1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Zack Rusin <zack@tungstengraphics.com>
33 #include "pipe/p_debug.h"
34 #include "pipe/p_util.h"
38 #define MAX(a, b) ((a > b) ? (a) : (b))
40 static const int MinNumBits
= 4;
42 static const unsigned char prime_deltas
[] = {
43 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
44 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
47 static int primeForNumBits(int numBits
)
49 return (1 << numBits
) + prime_deltas
[numBits
];
53 Returns the smallest integer n such that
54 primeForNumBits(n) >= hint.
56 static int countBits(int hint
)
66 if (numBits
>= (int)sizeof(prime_deltas
)) {
67 numBits
= sizeof(prime_deltas
) - 1;
68 } else if (primeForNumBits(numBits
) < hint
) {
75 struct cso_node
*next
;
80 struct cso_hash_data
{
81 struct cso_node
*fakeNext
;
82 struct cso_node
**buckets
;
92 struct cso_hash_data
*d
;
97 static void *cso_data_allocate_node(struct cso_hash_data
*hash
)
99 return MALLOC(hash
->nodeSize
);
102 static void cso_data_free_node(struct cso_node
*node
)
104 /* XXX still a leak here.
105 * Need to cast value ptr to original cso type, then free the
106 * driver-specific data hanging off of it. For example:
107 struct cso_sampler *csamp = (struct cso_sampler *) node->value;
114 static struct cso_node
*
115 cso_hash_create_node(struct cso_hash
*hash
,
116 unsigned akey
, void *avalue
,
117 struct cso_node
**anextNode
)
119 struct cso_node
*node
= cso_data_allocate_node(hash
->data
.d
);
121 node
->value
= avalue
;
123 node
->next
= (struct cso_node
*)(*anextNode
);
125 ++hash
->data
.d
->size
;
129 static void cso_data_rehash(struct cso_hash_data
*hash
, int hint
)
132 hint
= countBits(-hint
);
133 if (hint
< MinNumBits
)
135 hash
->userNumBits
= (short)hint
;
136 while (primeForNumBits(hint
) < (hash
->size
>> 1))
138 } else if (hint
< MinNumBits
) {
142 if (hash
->numBits
!= hint
) {
143 struct cso_node
*e
= (struct cso_node
*)(hash
);
144 struct cso_node
**oldBuckets
= hash
->buckets
;
145 int oldNumBuckets
= hash
->numBuckets
;
148 hash
->numBits
= (short)hint
;
149 hash
->numBuckets
= primeForNumBits(hint
);
150 hash
->buckets
= MALLOC(sizeof(struct cso_node
*) * hash
->numBuckets
);
151 for (i
= 0; i
< hash
->numBuckets
; ++i
)
152 hash
->buckets
[i
] = e
;
154 for (i
= 0; i
< oldNumBuckets
; ++i
) {
155 struct cso_node
*firstNode
= oldBuckets
[i
];
156 while (firstNode
!= e
) {
157 unsigned h
= firstNode
->key
;
158 struct cso_node
*lastNode
= firstNode
;
159 struct cso_node
*afterLastNode
;
160 struct cso_node
**beforeFirstNode
;
162 while (lastNode
->next
!= e
&& lastNode
->next
->key
== h
)
163 lastNode
= lastNode
->next
;
165 afterLastNode
= lastNode
->next
;
166 beforeFirstNode
= &hash
->buckets
[h
% hash
->numBuckets
];
167 while (*beforeFirstNode
!= e
)
168 beforeFirstNode
= &(*beforeFirstNode
)->next
;
169 lastNode
->next
= *beforeFirstNode
;
170 *beforeFirstNode
= firstNode
;
171 firstNode
= afterLastNode
;
178 static void cso_data_might_grow(struct cso_hash_data
*hash
)
180 if (hash
->size
>= hash
->numBuckets
)
181 cso_data_rehash(hash
, hash
->numBits
+ 1);
184 static void cso_data_has_shrunk(struct cso_hash_data
*hash
)
186 if (hash
->size
<= (hash
->numBuckets
>> 3) &&
187 hash
->numBits
> hash
->userNumBits
) {
188 int max
= MAX(hash
->numBits
-2, hash
->userNumBits
);
189 cso_data_rehash(hash
, max
);
193 static struct cso_node
*cso_data_first_node(struct cso_hash_data
*hash
)
195 struct cso_node
*e
= (struct cso_node
*)(hash
);
196 struct cso_node
**bucket
= hash
->buckets
;
197 int n
= hash
->numBuckets
;
206 static struct cso_node
**cso_hash_find_node(struct cso_hash
*hash
, unsigned akey
)
208 struct cso_node
**node
;
210 if (hash
->data
.d
->numBuckets
) {
211 node
= (struct cso_node
**)(&hash
->data
.d
->buckets
[akey
% hash
->data
.d
->numBuckets
]);
212 assert(*node
== hash
->data
.e
|| (*node
)->next
);
213 while (*node
!= hash
->data
.e
&& (*node
)->key
!= akey
)
214 node
= &(*node
)->next
;
216 node
= (struct cso_node
**)((const struct cso_node
* const *)(&hash
->data
.e
));
221 struct cso_hash_iter
cso_hash_insert(struct cso_hash
*hash
,
222 unsigned key
, void *data
)
224 cso_data_might_grow(hash
->data
.d
);
227 struct cso_node
**nextNode
= cso_hash_find_node(hash
, key
);
228 struct cso_node
*node
= cso_hash_create_node(hash
, key
, data
, nextNode
);
229 struct cso_hash_iter iter
= {hash
, node
};
234 struct cso_hash
* cso_hash_create(void)
236 struct cso_hash
*hash
= MALLOC_STRUCT(cso_hash
);
237 hash
->data
.d
= MALLOC_STRUCT(cso_hash_data
);
238 hash
->data
.d
->fakeNext
= 0;
239 hash
->data
.d
->buckets
= 0;
240 hash
->data
.d
->size
= 0;
241 hash
->data
.d
->nodeSize
= sizeof(struct cso_node
);
242 hash
->data
.d
->userNumBits
= (short)MinNumBits
;
243 hash
->data
.d
->numBits
= 0;
244 hash
->data
.d
->numBuckets
= 0;
249 void cso_hash_delete(struct cso_hash
*hash
)
251 struct cso_node
*e_for_x
= (struct cso_node
*)(hash
->data
.d
);
252 struct cso_node
**bucket
= (struct cso_node
**)(hash
->data
.d
->buckets
);
253 int n
= hash
->data
.d
->numBuckets
;
255 struct cso_node
*cur
= *bucket
++;
256 while (cur
!= e_for_x
) {
257 struct cso_node
*next
= cur
->next
;
258 cso_data_free_node(cur
);
262 FREE(hash
->data
.d
->buckets
);
267 struct cso_hash_iter
cso_hash_find(struct cso_hash
*hash
,
270 struct cso_node
**nextNode
= cso_hash_find_node(hash
, key
);
271 struct cso_hash_iter iter
= {hash
, *nextNode
};
275 unsigned cso_hash_iter_key(struct cso_hash_iter iter
)
277 if (!iter
.node
|| iter
.hash
->data
.e
== iter
.node
)
279 return iter
.node
->key
;
282 void * cso_hash_iter_data(struct cso_hash_iter iter
)
284 if (!iter
.node
|| iter
.hash
->data
.e
== iter
.node
)
286 return iter
.node
->value
;
289 static struct cso_node
*cso_hash_data_next(struct cso_node
*node
)
292 struct cso_node
*next
;
294 struct cso_hash_data
*d
;
297 struct cso_node
**bucket
;
302 debug_printf("iterating beyond the last element\n");
308 start
= (node
->key
% a
.d
->numBuckets
) + 1;
309 bucket
= a
.d
->buckets
+ start
;
310 n
= a
.d
->numBuckets
- start
;
320 static struct cso_node
*cso_hash_data_prev(struct cso_node
*node
)
324 struct cso_hash_data
*d
;
327 struct cso_node
*sentinel
;
328 struct cso_node
**bucket
;
335 start
= a
.d
->numBuckets
- 1;
337 start
= node
->key
% a
.d
->numBuckets
;
340 bucket
= a
.d
->buckets
+ start
;
342 if (*bucket
!= sentinel
) {
343 struct cso_node
*prev
= *bucket
;
344 while (prev
->next
!= sentinel
)
353 debug_printf("iterating backward beyond first element\n");
357 struct cso_hash_iter
cso_hash_iter_next(struct cso_hash_iter iter
)
359 struct cso_hash_iter next
= {iter
.hash
, cso_hash_data_next(iter
.node
)};
363 int cso_hash_iter_is_null(struct cso_hash_iter iter
)
365 if (!iter
.node
|| iter
.node
== iter
.hash
->data
.e
)
370 void * cso_hash_take(struct cso_hash
*hash
,
373 struct cso_node
**node
= cso_hash_find_node(hash
, akey
);
374 if (*node
!= hash
->data
.e
) {
375 void *t
= (*node
)->value
;
376 struct cso_node
*next
= (*node
)->next
;
377 cso_data_free_node(*node
);
379 --hash
->data
.d
->size
;
380 cso_data_has_shrunk(hash
->data
.d
);
386 struct cso_hash_iter
cso_hash_iter_prev(struct cso_hash_iter iter
)
388 struct cso_hash_iter prev
= {iter
.hash
,
389 cso_hash_data_prev(iter
.node
)};
393 struct cso_hash_iter
cso_hash_first_node(struct cso_hash
*hash
)
395 struct cso_hash_iter iter
= {hash
, cso_data_first_node(hash
->data
.d
)};
399 int cso_hash_size(struct cso_hash
*hash
)
401 return hash
->data
.d
->size
;