isl_schedule_read.c: read_band: avoid double free on error path
[isl.git] / isl_hash.c
blobca25d0d5851d7b6363b51edd71bb9fc7e8418bb5
1 /*
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
8 */
10 #include <stdlib.h>
11 #include <isl_hash_private.h>
12 #include <isl/ctx.h>
13 #include "isl_config.h"
15 uint32_t isl_hash_string(uint32_t hash, const char *s)
17 for (; *s; s++)
18 isl_hash_byte(hash, *s);
19 return hash;
22 uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len)
24 int i;
25 const char *s = p;
26 for (i = 0; i < len; ++i)
27 isl_hash_byte(hash, s[i]);
28 return hash;
31 static unsigned int round_up(unsigned int v)
33 int old_v = v;
35 while (v) {
36 old_v = v;
37 v ^= v & -v;
39 return old_v << 1;
42 int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
43 int min_size)
45 size_t size;
47 if (!table)
48 return -1;
50 if (min_size < 2)
51 min_size = 2;
52 table->bits = ffs(round_up(4 * (min_size + 1) / 3 - 1)) - 1;
53 table->n = 0;
55 size = 1 << table->bits;
56 table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
57 size);
58 if (!table->entries)
59 return -1;
61 return 0;
64 /* Dummy comparison function that always returns false.
66 static int no(const void *entry, const void *val)
68 return 0;
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)
80 int n;
81 size_t old_size, size;
82 struct isl_hash_table_entry *entries;
83 uint32_t h;
85 entries = table->entries;
86 old_size = 1 << table->bits;
87 size = 2 * old_size;
88 table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
89 size);
90 if (!table->entries) {
91 table->entries = entries;
92 return -1;
95 n = table->n;
96 table->n = 0;
97 table->bits++;
99 for (h = 0; h < old_size; ++h) {
100 struct isl_hash_table_entry *entry;
102 if (!entries[h].data)
103 continue;
105 entry = isl_hash_table_find(ctx, table, entries[h].hash,
106 &no, NULL, 1);
107 if (!entry) {
108 table->bits--;
109 free(table->entries);
110 table->entries = entries;
111 table->n = n;
112 return -1;
115 *entry = entries[h];
118 free(entries);
120 return 0;
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))
129 goto error;
130 return table;
131 error:
132 isl_hash_table_free(ctx, table);
133 return NULL;
136 void isl_hash_table_clear(struct isl_hash_table *table)
138 if (!table)
139 return;
140 free(table->entries);
143 void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
145 if (!table)
146 return;
147 isl_hash_table_clear(table);
148 free(table);
151 /* A dummy entry that can be used to make a distinction between
152 * a missing entry and an error condition.
153 * It is used by isl_union_*_find_part_entry.
155 static struct isl_hash_table_entry none = { 0, NULL };
156 struct isl_hash_table_entry *isl_hash_table_entry_none = &none;
158 struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
159 struct isl_hash_table *table,
160 uint32_t key_hash,
161 int (*eq)(const void *entry, const void *val),
162 const void *val, int reserve)
164 size_t size;
165 uint32_t h, key_bits;
167 key_bits = isl_hash_bits(key_hash, table->bits);
168 size = 1 << table->bits;
169 for (h = key_bits; table->entries[h].data; h = (h+1) % size)
170 if (table->entries[h].hash == key_hash &&
171 eq(table->entries[h].data, val))
172 return &table->entries[h];
174 if (!reserve)
175 return NULL;
177 if (4 * table->n >= 3 * size) {
178 if (grow_table(ctx, table) < 0)
179 return NULL;
180 return isl_hash_table_find(ctx, table, key_hash, eq, val, 1);
183 table->n++;
184 table->entries[h].hash = key_hash;
186 return &table->entries[h];
189 isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table,
190 isl_stat (*fn)(void **entry, void *user), void *user)
192 size_t size;
193 uint32_t h;
195 if (!table->entries)
196 return isl_stat_error;
198 size = 1 << table->bits;
199 for (h = 0; h < size; ++ h)
200 if (table->entries[h].data &&
201 fn(&table->entries[h].data, user) < 0)
202 return isl_stat_error;
204 return isl_stat_ok;
207 void isl_hash_table_remove(struct isl_ctx *ctx,
208 struct isl_hash_table *table,
209 struct isl_hash_table_entry *entry)
211 int h, h2;
212 size_t size;
214 if (!table || !entry)
215 return;
217 size = 1 << table->bits;
218 h = entry - table->entries;
219 isl_assert(ctx, h >= 0 && h < size, return);
221 for (h2 = h+1; table->entries[h2 % size].data; h2++) {
222 uint32_t bits = isl_hash_bits(table->entries[h2 % size].hash,
223 table->bits);
224 uint32_t offset = (size + bits - (h+1)) % size;
225 if (offset <= h2 - (h+1))
226 continue;
227 *entry = table->entries[h2 % size];
228 h = h2;
229 entry = &table->entries[h % size];
232 entry->hash = 0;
233 entry->data = NULL;
234 table->n--;