1 #include <dix-config.h>
10 #define INITHASHSIZE 6
11 #define MAXHASHSIZE 11
17 int elements
; /* number of elements inserted */
18 int bucketBits
; /* number of buckets is 1 << bucketBits */
19 struct xorg_list
*buckets
; /* array of bucket list heads */
22 HashCompareFunc compare
;
31 } BucketRec
, *BucketPtr
;
34 ht_create(int keySize
,
37 HashCompareFunc compare
,
42 HashTable ht
= malloc(sizeof(struct HashTableRec
));
48 ht
->keySize
= keySize
;
49 ht
->dataSize
= dataSize
;
51 ht
->compare
= compare
;
53 ht
->bucketBits
= INITHASHSIZE
;
54 numBuckets
= 1 << ht
->bucketBits
;
55 ht
->buckets
= xallocarray(numBuckets
, sizeof(*ht
->buckets
));
59 for (c
= 0; c
< numBuckets
; ++c
) {
60 xorg_list_init(&ht
->buckets
[c
]);
70 ht_destroy(HashTable ht
)
74 int numBuckets
= 1 << ht
->bucketBits
;
75 for (c
= 0; c
< numBuckets
; ++c
) {
76 xorg_list_for_each_entry_safe(it
, tmp
, &ht
->buckets
[c
], l
) {
77 xorg_list_del(&it
->l
);
88 double_size(HashTable ht
)
90 struct xorg_list
*newBuckets
;
91 int numBuckets
= 1 << ht
->bucketBits
;
92 int newBucketBits
= ht
->bucketBits
+ 1;
93 int newNumBuckets
= 1 << newBucketBits
;
96 newBuckets
= xallocarray(newNumBuckets
, sizeof(*ht
->buckets
));
98 for (c
= 0; c
< newNumBuckets
; ++c
) {
99 xorg_list_init(&newBuckets
[c
]);
102 for (c
= 0; c
< numBuckets
; ++c
) {
104 xorg_list_for_each_entry_safe(it
, tmp
, &ht
->buckets
[c
], l
) {
105 struct xorg_list
*newBucket
=
106 &newBuckets
[ht
->hash(ht
->cdata
, it
->key
, newBucketBits
)];
107 xorg_list_del(&it
->l
);
108 xorg_list_add(&it
->l
, newBucket
);
113 ht
->buckets
= newBuckets
;
114 ht
->bucketBits
= newBucketBits
;
122 ht_add(HashTable ht
, const void *key
)
124 unsigned index
= ht
->hash(ht
->cdata
, key
, ht
->bucketBits
);
125 struct xorg_list
*bucket
= &ht
->buckets
[index
];
126 BucketRec
*elem
= calloc(1, sizeof(BucketRec
));
130 elem
->key
= malloc(ht
->keySize
);
134 /* we avoid signaling an out-of-memory error if dataSize is 0 */
135 elem
->data
= calloc(1, ht
->dataSize
);
136 if (ht
->dataSize
&& !elem
->data
) {
139 xorg_list_add(&elem
->l
, bucket
);
142 memcpy(elem
->key
, key
, ht
->keySize
);
144 if (ht
->elements
> 4 * (1 << ht
->bucketBits
) &&
145 ht
->bucketBits
< MAXHASHSIZE
) {
146 if (!double_size(ht
)) {
148 xorg_list_del(&elem
->l
);
153 /* if memory allocation has failed due to dataSize being 0, return
154 a "dummy" pointer pointing at the of the key */
155 return elem
->data
? elem
->data
: ((char*) elem
->key
+ ht
->keySize
);
168 ht_remove(HashTable ht
, const void *key
)
170 unsigned index
= ht
->hash(ht
->cdata
, key
, ht
->bucketBits
);
171 struct xorg_list
*bucket
= &ht
->buckets
[index
];
174 xorg_list_for_each_entry(it
, bucket
, l
) {
175 if (ht
->compare(ht
->cdata
, key
, it
->key
) == 0) {
176 xorg_list_del(&it
->l
);
187 ht_find(HashTable ht
, const void *key
)
189 unsigned index
= ht
->hash(ht
->cdata
, key
, ht
->bucketBits
);
190 struct xorg_list
*bucket
= &ht
->buckets
[index
];
193 xorg_list_for_each_entry(it
, bucket
, l
) {
194 if (ht
->compare(ht
->cdata
, key
, it
->key
) == 0) {
195 return it
->data
? it
->data
: ((char*) it
->key
+ ht
->keySize
);
203 ht_dump_distribution(HashTable ht
)
206 int numBuckets
= 1 << ht
->bucketBits
;
207 for (c
= 0; c
< numBuckets
; ++c
) {
211 xorg_list_for_each_entry(it
, &ht
->buckets
[c
], l
) {
214 printf("%d: %d\n", c
, n
);
218 /* Picked the function from http://burtleburtle.net/bob/hash/doobs.html by
219 Bob Jenkins, which is released in public domain */
221 one_at_a_time_hash(const void *data
, int len
)
225 const char *key
= data
;
226 for (hash
=0, i
=0; i
<len
; ++i
) {
228 hash
+= (hash
<< 10);
232 hash
^= (hash
>> 11);
233 hash
+= (hash
<< 15);
238 ht_generic_hash(void *cdata
, const void *ptr
, int numBits
)
240 HtGenericHashSetupPtr setup
= cdata
;
241 return one_at_a_time_hash(ptr
, setup
->keySize
) & ~((~0U) << numBits
);
245 ht_generic_compare(void *cdata
, const void *l
, const void *r
)
247 HtGenericHashSetupPtr setup
= cdata
;
248 return memcmp(l
, r
, setup
->keySize
);
252 ht_resourceid_hash(void * cdata
, const void * data
, int numBits
)
254 const XID
* idPtr
= data
;
255 XID id
= *idPtr
& RESOURCE_ID_MASK
;
257 return HashResourceID(id
, numBits
);
261 ht_resourceid_compare(void* cdata
, const void* a
, const void* b
)
273 ht_dump_contents(HashTable ht
,
274 void (*print_key
)(void *opaque
, void *key
),
275 void (*print_value
)(void *opaque
, void *value
),
279 int numBuckets
= 1 << ht
->bucketBits
;
280 for (c
= 0; c
< numBuckets
; ++c
) {
285 xorg_list_for_each_entry(it
, &ht
->buckets
[c
], l
) {
289 print_key(opaque
, it
->key
);
291 print_value(opaque
, it
->data
);