1 1.1 mrg /* 2 1.1 mrg * Copyright 2008-2009 Katholieke Universiteit Leuven 3 1.1 mrg * 4 1.1 mrg * Use of this software is governed by the MIT license 5 1.1 mrg * 6 1.1 mrg * Written by Sven Verdoolaege, K.U.Leuven, Departement 7 1.1 mrg * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 8 1.1 mrg */ 9 1.1 mrg 10 1.1 mrg #include <stdlib.h> 11 1.1 mrg #include <isl_hash_private.h> 12 1.1 mrg #include <isl/ctx.h> 13 1.1 mrg #include "isl_config.h" 14 1.1 mrg 15 1.1 mrg uint32_t isl_hash_string(uint32_t hash, const char *s) 16 1.1 mrg { 17 1.1 mrg for (; *s; s++) 18 1.1 mrg isl_hash_byte(hash, *s); 19 1.1 mrg return hash; 20 1.1 mrg } 21 1.1 mrg 22 1.1 mrg uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len) 23 1.1 mrg { 24 1.1 mrg int i; 25 1.1 mrg const char *s = p; 26 1.1 mrg for (i = 0; i < len; ++i) 27 1.1 mrg isl_hash_byte(hash, s[i]); 28 1.1 mrg return hash; 29 1.1 mrg } 30 1.1 mrg 31 1.1 mrg static unsigned int round_up(unsigned int v) 32 1.1 mrg { 33 1.1 mrg int old_v = v; 34 1.1 mrg 35 1.1 mrg while (v) { 36 1.1 mrg old_v = v; 37 1.1 mrg v ^= v & -v; 38 1.1 mrg } 39 1.1 mrg return old_v << 1; 40 1.1 mrg } 41 1.1 mrg 42 1.1 mrg int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table, 43 1.1 mrg int min_size) 44 1.1 mrg { 45 1.1 mrg size_t size; 46 1.1 mrg 47 1.1 mrg if (!table) 48 1.1 mrg return -1; 49 1.1 mrg 50 1.1 mrg if (min_size < 2) 51 1.1 mrg min_size = 2; 52 1.1 mrg table->bits = ffs(round_up(4 * (min_size + 1) / 3 - 1)) - 1; 53 1.1 mrg table->n = 0; 54 1.1 mrg 55 1.1 mrg size = 1 << table->bits; 56 1.1 mrg table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry, 57 1.1 mrg size); 58 1.1 mrg if (!table->entries) 59 1.1 mrg return -1; 60 1.1 mrg 61 1.1 mrg return 0; 62 1.1 mrg } 63 1.1 mrg 64 1.1 mrg /* Dummy comparison function that always returns false. 65 1.1 mrg */ 66 1.1 mrg static isl_bool no(const void *entry, const void *val) 67 1.1 mrg { 68 1.1 mrg return isl_bool_false; 69 1.1 mrg } 70 1.1 mrg 71 1.1 mrg /* Extend "table" to twice its size. 72 1.1 mrg * Return 0 on success and -1 on error. 73 1.1 mrg * 74 1.1 mrg * We reuse isl_hash_table_find to create entries in the extended table. 75 1.1 mrg * Since all entries in the original table are assumed to be different, 76 1.1 mrg * there is no need to compare them against each other. 77 1.1 mrg */ 78 1.1 mrg static int grow_table(struct isl_ctx *ctx, struct isl_hash_table *table) 79 1.1 mrg { 80 1.1 mrg int n; 81 1.1 mrg size_t old_size, size; 82 1.1 mrg struct isl_hash_table_entry *entries; 83 1.1 mrg uint32_t h; 84 1.1 mrg 85 1.1 mrg entries = table->entries; 86 1.1 mrg old_size = 1 << table->bits; 87 1.1 mrg size = 2 * old_size; 88 1.1 mrg table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry, 89 1.1 mrg size); 90 1.1 mrg if (!table->entries) { 91 1.1 mrg table->entries = entries; 92 1.1 mrg return -1; 93 1.1 mrg } 94 1.1 mrg 95 1.1 mrg n = table->n; 96 1.1 mrg table->n = 0; 97 1.1 mrg table->bits++; 98 1.1 mrg 99 1.1 mrg for (h = 0; h < old_size; ++h) { 100 1.1 mrg struct isl_hash_table_entry *entry; 101 1.1 mrg 102 1.1 mrg if (!entries[h].data) 103 1.1 mrg continue; 104 1.1 mrg 105 1.1 mrg entry = isl_hash_table_find(ctx, table, entries[h].hash, 106 1.1 mrg &no, NULL, 1); 107 1.1 mrg if (!entry) { 108 1.1 mrg table->bits--; 109 1.1 mrg free(table->entries); 110 1.1 mrg table->entries = entries; 111 1.1 mrg table->n = n; 112 1.1 mrg return -1; 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg *entry = entries[h]; 116 1.1 mrg } 117 1.1 mrg 118 1.1 mrg free(entries); 119 1.1 mrg 120 1.1 mrg return 0; 121 1.1 mrg } 122 1.1 mrg 123 1.1 mrg struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size) 124 1.1 mrg { 125 1.1 mrg struct isl_hash_table *table = NULL; 126 1.1 mrg 127 1.1 mrg table = isl_alloc_type(ctx, struct isl_hash_table); 128 1.1 mrg if (isl_hash_table_init(ctx, table, min_size)) 129 1.1 mrg goto error; 130 1.1 mrg return table; 131 1.1 mrg error: 132 1.1 mrg isl_hash_table_free(ctx, table); 133 1.1 mrg return NULL; 134 1.1 mrg } 135 1.1 mrg 136 1.1 mrg void isl_hash_table_clear(struct isl_hash_table *table) 137 1.1 mrg { 138 1.1 mrg if (!table) 139 1.1 mrg return; 140 1.1 mrg free(table->entries); 141 1.1 mrg } 142 1.1 mrg 143 1.1 mrg void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table) 144 1.1 mrg { 145 1.1 mrg if (!table) 146 1.1 mrg return; 147 1.1 mrg isl_hash_table_clear(table); 148 1.1 mrg free(table); 149 1.1 mrg } 150 1.1 mrg 151 1.1 mrg /* A dummy entry that is used by isl_hash_table_find 152 1.1 mrg * to make a distinction between a missing entry and an error condition. 153 1.1 mrg */ 154 1.1 mrg static struct isl_hash_table_entry none = { 0, NULL }; 155 1.1 mrg struct isl_hash_table_entry *isl_hash_table_entry_none = &none; 156 1.1 mrg 157 1.1 mrg struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx, 158 1.1 mrg struct isl_hash_table *table, 159 1.1 mrg uint32_t key_hash, 160 1.1 mrg isl_bool (*eq)(const void *entry, const void *val), 161 1.1 mrg const void *val, int reserve) 162 1.1 mrg { 163 1.1 mrg size_t size; 164 1.1 mrg uint32_t h, key_bits; 165 1.1 mrg 166 1.1 mrg key_bits = isl_hash_bits(key_hash, table->bits); 167 1.1 mrg size = 1 << table->bits; 168 1.1 mrg for (h = key_bits; table->entries[h].data; h = (h+1) % size) { 169 1.1 mrg isl_bool equal; 170 1.1 mrg 171 1.1 mrg if (table->entries[h].hash != key_hash) 172 1.1 mrg continue; 173 1.1 mrg equal = eq(table->entries[h].data, val); 174 1.1 mrg if (equal < 0) 175 1.1 mrg return NULL; 176 1.1 mrg if (equal) 177 1.1 mrg return &table->entries[h]; 178 1.1 mrg } 179 1.1 mrg 180 1.1 mrg if (!reserve) 181 1.1 mrg return isl_hash_table_entry_none; 182 1.1 mrg 183 1.1 mrg if (4 * table->n >= 3 * size) { 184 1.1 mrg if (grow_table(ctx, table) < 0) 185 1.1 mrg return NULL; 186 1.1 mrg return isl_hash_table_find(ctx, table, key_hash, eq, val, 1); 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg table->n++; 190 1.1 mrg table->entries[h].hash = key_hash; 191 1.1 mrg 192 1.1 mrg return &table->entries[h]; 193 1.1 mrg } 194 1.1 mrg 195 1.1 mrg /* Return the first entry containing data in "table". 196 1.1 mrg * Return isl_hash_table_entry_none is there is no such entry and 197 1.1 mrg * NULL on error. 198 1.1 mrg */ 199 1.1 mrg struct isl_hash_table_entry *isl_hash_table_first(struct isl_hash_table *table) 200 1.1 mrg { 201 1.1 mrg size_t size; 202 1.1 mrg uint32_t h; 203 1.1 mrg 204 1.1 mrg if (!table->entries) 205 1.1 mrg return NULL; 206 1.1 mrg 207 1.1 mrg size = 1 << table->bits; 208 1.1 mrg for (h = 0; h < size; ++ h) 209 1.1 mrg if (table->entries[h].data) 210 1.1 mrg return &table->entries[h]; 211 1.1 mrg 212 1.1 mrg return isl_hash_table_entry_none; 213 1.1 mrg } 214 1.1 mrg 215 1.1 mrg isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table, 216 1.1 mrg isl_stat (*fn)(void **entry, void *user), void *user) 217 1.1 mrg { 218 1.1 mrg size_t size; 219 1.1 mrg uint32_t h; 220 1.1 mrg 221 1.1 mrg if (!table->entries) 222 1.1 mrg return isl_stat_error; 223 1.1 mrg 224 1.1 mrg size = 1 << table->bits; 225 1.1 mrg for (h = 0; h < size; ++ h) 226 1.1 mrg if (table->entries[h].data && 227 1.1 mrg fn(&table->entries[h].data, user) < 0) 228 1.1 mrg return isl_stat_error; 229 1.1 mrg 230 1.1 mrg return isl_stat_ok; 231 1.1 mrg } 232 1.1 mrg 233 1.1 mrg /* Does "test" succeed on every (non-empty) entry of "table"? 234 1.1 mrg */ 235 1.1 mrg isl_bool isl_hash_table_every(isl_ctx *ctx, struct isl_hash_table *table, 236 1.1 mrg isl_bool (*test)(void **entry, void *user), void *user) 237 1.1 mrg { 238 1.1 mrg size_t size; 239 1.1 mrg uint32_t h; 240 1.1 mrg 241 1.1 mrg if (!table->entries) 242 1.1 mrg return isl_bool_error; 243 1.1 mrg 244 1.1 mrg size = 1 << table->bits; 245 1.1 mrg for (h = 0; h < size; ++ h) { 246 1.1 mrg isl_bool r; 247 1.1 mrg 248 1.1 mrg if (!table->entries[h].data) 249 1.1 mrg continue; 250 1.1 mrg r = test(&table->entries[h].data, user); 251 1.1 mrg if (r < 0 || !r) 252 1.1 mrg return r; 253 1.1 mrg } 254 1.1 mrg 255 1.1 mrg return isl_bool_true; 256 1.1 mrg } 257 1.1 mrg 258 1.1 mrg void isl_hash_table_remove(struct isl_ctx *ctx, 259 1.1 mrg struct isl_hash_table *table, 260 1.1 mrg struct isl_hash_table_entry *entry) 261 1.1 mrg { 262 1.1 mrg int h, h2; 263 1.1 mrg size_t size; 264 1.1 mrg 265 1.1 mrg if (!table || !entry) 266 1.1 mrg return; 267 1.1 mrg 268 1.1 mrg size = 1 << table->bits; 269 1.1 mrg h = entry - table->entries; 270 1.1 mrg isl_assert(ctx, h >= 0 && h < size, return); 271 1.1 mrg 272 1.1 mrg for (h2 = h+1; table->entries[h2 % size].data; h2++) { 273 1.1 mrg uint32_t bits = isl_hash_bits(table->entries[h2 % size].hash, 274 1.1 mrg table->bits); 275 1.1 mrg uint32_t offset = (size + bits - (h+1)) % size; 276 1.1 mrg if (offset <= h2 - (h+1)) 277 1.1 mrg continue; 278 1.1 mrg *entry = table->entries[h2 % size]; 279 1.1 mrg h = h2; 280 1.1 mrg entry = &table->entries[h % size]; 281 1.1 mrg } 282 1.1 mrg 283 1.1 mrg entry->hash = 0; 284 1.1 mrg entry->data = NULL; 285 1.1 mrg table->n--; 286 1.1 mrg } 287