2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
13 #include "isl_config.h"
15 uint32_t isl_hash_string(uint32_t hash
, const char *s
)
18 isl_hash_byte(hash
, *s
);
22 uint32_t isl_hash_mem(uint32_t hash
, const void *p
, size_t len
)
26 for (i
= 0; i
< len
; ++i
)
27 isl_hash_byte(hash
, s
[i
]);
31 static unsigned int round_up(unsigned int v
)
42 int isl_hash_table_init(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
52 table
->bits
= ffs(round_up(4 * (min_size
+ 1) / 3 - 1)) - 1;
55 size
= 1 << table
->bits
;
56 table
->entries
= isl_calloc_array(ctx
, struct isl_hash_table_entry
,
64 /* Dummy comparison function that always returns false.
66 static isl_bool
no(const void *entry
, const void *val
)
68 return isl_bool_false
;
71 /* Extend "table" to twice its size.
72 * Return 0 on success and -1 on error.
74 * We reuse isl_hash_table_find to create entries in the extended table.
75 * Since all entries in the original table are assumed to be different,
76 * there is no need to compare them against each other.
78 static int grow_table(struct isl_ctx
*ctx
, struct isl_hash_table
*table
)
81 size_t old_size
, size
;
82 struct isl_hash_table_entry
*entries
;
85 entries
= table
->entries
;
86 old_size
= 1 << table
->bits
;
88 table
->entries
= isl_calloc_array(ctx
, struct isl_hash_table_entry
,
90 if (!table
->entries
) {
91 table
->entries
= entries
;
99 for (h
= 0; h
< old_size
; ++h
) {
100 struct isl_hash_table_entry
*entry
;
102 if (!entries
[h
].data
)
105 entry
= isl_hash_table_find(ctx
, table
, entries
[h
].hash
,
109 free(table
->entries
);
110 table
->entries
= entries
;
123 struct isl_hash_table
*isl_hash_table_alloc(struct isl_ctx
*ctx
, int min_size
)
125 struct isl_hash_table
*table
= NULL
;
127 table
= isl_alloc_type(ctx
, struct isl_hash_table
);
128 if (isl_hash_table_init(ctx
, table
, min_size
))
132 isl_hash_table_free(ctx
, table
);
136 void isl_hash_table_clear(struct isl_hash_table
*table
)
140 free(table
->entries
);
143 void isl_hash_table_free(struct isl_ctx
*ctx
, struct isl_hash_table
*table
)
147 isl_hash_table_clear(table
);
151 /* A dummy entry that is used by isl_hash_table_find
152 * to make a distinction between a missing entry and an error condition.
154 static struct isl_hash_table_entry none
= { 0, NULL
};
155 struct isl_hash_table_entry
*isl_hash_table_entry_none
= &none
;
157 struct isl_hash_table_entry
*isl_hash_table_find(struct isl_ctx
*ctx
,
158 struct isl_hash_table
*table
,
160 isl_bool (*eq
)(const void *entry
, const void *val
),
161 const void *val
, int reserve
)
164 uint32_t h
, key_bits
;
166 key_bits
= isl_hash_bits(key_hash
, table
->bits
);
167 size
= 1 << table
->bits
;
168 for (h
= key_bits
; table
->entries
[h
].data
; h
= (h
+1) % size
) {
171 if (table
->entries
[h
].hash
!= key_hash
)
173 equal
= eq(table
->entries
[h
].data
, val
);
177 return &table
->entries
[h
];
181 return isl_hash_table_entry_none
;
183 if (4 * table
->n
>= 3 * size
) {
184 if (grow_table(ctx
, table
) < 0)
186 return isl_hash_table_find(ctx
, table
, key_hash
, eq
, val
, 1);
190 table
->entries
[h
].hash
= key_hash
;
192 return &table
->entries
[h
];
195 isl_stat
isl_hash_table_foreach(isl_ctx
*ctx
, struct isl_hash_table
*table
,
196 isl_stat (*fn
)(void **entry
, void *user
), void *user
)
202 return isl_stat_error
;
204 size
= 1 << table
->bits
;
205 for (h
= 0; h
< size
; ++ h
)
206 if (table
->entries
[h
].data
&&
207 fn(&table
->entries
[h
].data
, user
) < 0)
208 return isl_stat_error
;
213 void isl_hash_table_remove(struct isl_ctx
*ctx
,
214 struct isl_hash_table
*table
,
215 struct isl_hash_table_entry
*entry
)
220 if (!table
|| !entry
)
223 size
= 1 << table
->bits
;
224 h
= entry
- table
->entries
;
225 isl_assert(ctx
, h
>= 0 && h
< size
, return);
227 for (h2
= h
+1; table
->entries
[h2
% size
].data
; h2
++) {
228 uint32_t bits
= isl_hash_bits(table
->entries
[h2
% size
].hash
,
230 uint32_t offset
= (size
+ bits
- (h
+1)) % size
;
231 if (offset
<= h2
- (h
+1))
233 *entry
= table
->entries
[h2
% size
];
235 entry
= &table
->entries
[h
% size
];