source: Daodan/MSYS2/mingw32/include/isl/hmap_templ.c@ 1170

Last change on this file since 1170 was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

File size: 9.5 KB
Line 
1/*
2 * Copyright 2011 INRIA Saclay
3 * Copyright 2013 Ecole Normale Superieure
4 *
5 * Use of this software is governed by the MIT license
6 *
7 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
8 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
9 * 91893 Orsay, France
10 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
11 */
12
13#include <isl/ctx.h>
14#include <isl/hash.h>
15
16#define ISL_xCAT(A,B) A ## B
17#define ISL_CAT(A,B) ISL_xCAT(A,B)
18#define ISL_xFN(TYPE,NAME) TYPE ## _ ## NAME
19#define ISL_FN(TYPE,NAME) ISL_xFN(TYPE,NAME)
20#define ISL_xS(TYPE1,TYPE2,NAME) struct isl_ ## TYPE1 ## _ ## TYPE2 ## _ ## NAME
21#define ISL_yS(TYPE1,TYPE2,NAME) ISL_xS(TYPE1,TYPE2,NAME)
22#define ISL_S(NAME) ISL_yS(ISL_KEY,ISL_VAL,NAME)
23
24struct ISL_HMAP {
25 int ref;
26 isl_ctx *ctx;
27 struct isl_hash_table table;
28};
29
30ISL_S(pair) {
31 ISL_KEY *key;
32 ISL_VAL *val;
33};
34
35__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,alloc)(isl_ctx *ctx, int min_size)
36{
37 ISL_HMAP *hmap;
38
39 hmap = isl_calloc_type(ctx, ISL_HMAP);
40 if (!hmap)
41 return NULL;
42
43 hmap->ctx = ctx;
44 isl_ctx_ref(ctx);
45 hmap->ref = 1;
46
47 if (isl_hash_table_init(ctx, &hmap->table, min_size) < 0)
48 return ISL_FN(ISL_HMAP,free)(hmap);
49
50 return hmap;
51}
52
53static isl_stat free_pair(void **entry, void *user)
54{
55 ISL_S(pair) *pair = *entry;
56 ISL_FN(ISL_KEY,free)(pair->key);
57 ISL_FN(ISL_VAL,free)(pair->val);
58 free(pair);
59 *entry = NULL;
60 return isl_stat_ok;
61}
62
63__isl_null ISL_HMAP *ISL_FN(ISL_HMAP,free)(__isl_take ISL_HMAP *hmap)
64{
65 if (!hmap)
66 return NULL;
67 if (--hmap->ref > 0)
68 return NULL;
69 isl_hash_table_foreach(hmap->ctx, &hmap->table, &free_pair, NULL);
70 isl_hash_table_clear(&hmap->table);
71 isl_ctx_deref(hmap->ctx);
72 free(hmap);
73 return NULL;
74}
75
76isl_ctx *ISL_FN(ISL_HMAP,get_ctx)(__isl_keep ISL_HMAP *hmap)
77{
78 return hmap ? hmap->ctx : NULL;
79}
80
81/* Add a mapping from "key" to "val" to the associative array
82 * pointed to by user.
83 */
84static isl_stat add_key_val(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val,
85 void *user)
86{
87 ISL_HMAP **hmap = (ISL_HMAP **) user;
88
89 *hmap = ISL_FN(ISL_HMAP,set)(*hmap, key, val);
90
91 if (!*hmap)
92 return isl_stat_error;
93
94 return isl_stat_ok;
95}
96
97__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,dup)(__isl_keep ISL_HMAP *hmap)
98{
99 ISL_HMAP *dup;
100
101 if (!hmap)
102 return NULL;
103
104 dup = ISL_FN(ISL_HMAP,alloc)(hmap->ctx, hmap->table.n);
105 if (ISL_FN(ISL_HMAP,foreach)(hmap, &add_key_val, &dup) < 0)
106 return ISL_FN(ISL_HMAP,free)(dup);
107
108 return dup;
109}
110
111__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,cow)(__isl_take ISL_HMAP *hmap)
112{
113 if (!hmap)
114 return NULL;
115
116 if (hmap->ref == 1)
117 return hmap;
118 hmap->ref--;
119 return ISL_FN(ISL_HMAP,dup)(hmap);
120}
121
122__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,copy)(__isl_keep ISL_HMAP *hmap)
123{
124 if (!hmap)
125 return NULL;
126
127 hmap->ref++;
128 return hmap;
129}
130
131static isl_bool has_key(const void *entry, const void *c_key)
132{
133 const ISL_S(pair) *pair = entry;
134 ISL_KEY *key = (ISL_KEY *) c_key;
135
136 return ISL_KEY_IS_EQUAL(pair->key, key);
137}
138
139/* If "hmap" contains a value associated to "key", then return
140 * (isl_bool_true, copy of value).
141 * Otherwise, return
142 * (isl_bool_false, NULL).
143 * If an error occurs, then return
144 * (isl_bool_error, NULL).
145 */
146__isl_give ISL_MAYBE(ISL_VAL) ISL_FN(ISL_HMAP,try_get)(
147 __isl_keep ISL_HMAP *hmap, __isl_keep ISL_KEY *key)
148{
149 struct isl_hash_table_entry *entry;
150 ISL_S(pair) *pair;
151 uint32_t hash;
152 ISL_MAYBE(ISL_VAL) res = { isl_bool_false, NULL };
153
154 if (!hmap || !key)
155 goto error;
156
157 hash = ISL_FN(ISL_KEY,get_hash)(key);
158 entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
159 &has_key, key, 0);
160
161 if (!entry)
162 goto error;
163 if (entry == isl_hash_table_entry_none)
164 return res;
165
166 pair = entry->data;
167
168 res.valid = isl_bool_true;
169 res.value = ISL_FN(ISL_VAL,copy)(pair->val);
170 if (!res.value)
171 res.valid = isl_bool_error;
172 return res;
173error:
174 res.valid = isl_bool_error;
175 res.value = NULL;
176 return res;
177}
178
179/* If "hmap" contains a value associated to "key", then return
180 * isl_bool_true. Otherwise, return isl_bool_false.
181 * Return isl_bool_error on error.
182 */
183isl_bool ISL_FN(ISL_HMAP,has)(__isl_keep ISL_HMAP *hmap,
184 __isl_keep ISL_KEY *key)
185{
186 ISL_MAYBE(ISL_VAL) res;
187
188 res = ISL_FN(ISL_HMAP,try_get)(hmap, key);
189 ISL_FN(ISL_VAL,free)(res.value);
190
191 return res.valid;
192}
193
194/* If "hmap" contains a value associated to "key", then return
195 * a copy of that value. Otherwise, return NULL.
196 * Return NULL on error.
197 */
198__isl_give ISL_VAL *ISL_FN(ISL_HMAP,get)(__isl_keep ISL_HMAP *hmap,
199 __isl_take ISL_KEY *key)
200{
201 ISL_VAL *res;
202
203 res = ISL_FN(ISL_HMAP,try_get)(hmap, key).value;
204 ISL_FN(ISL_KEY,free)(key);
205 return res;
206}
207
208/* Remove the mapping between "key" and its associated value (if any)
209 * from "hmap".
210 *
211 * If "key" is not mapped to anything, then we leave "hmap" untouched"
212 */
213__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,drop)(__isl_take ISL_HMAP *hmap,
214 __isl_take ISL_KEY *key)
215{
216 struct isl_hash_table_entry *entry;
217 ISL_S(pair) *pair;
218 uint32_t hash;
219
220 if (!hmap || !key)
221 goto error;
222
223 hash = ISL_FN(ISL_KEY,get_hash)(key);
224 entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
225 &has_key, key, 0);
226 if (!entry)
227 goto error;
228 if (entry == isl_hash_table_entry_none) {
229 ISL_FN(ISL_KEY,free)(key);
230 return hmap;
231 }
232
233 hmap = ISL_FN(ISL_HMAP,cow)(hmap);
234 if (!hmap)
235 goto error;
236 entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
237 &has_key, key, 0);
238 ISL_FN(ISL_KEY,free)(key);
239
240 if (!entry)
241 return ISL_FN(ISL_HMAP,free)(hmap);
242 if (entry == isl_hash_table_entry_none)
243 isl_die(hmap->ctx, isl_error_internal,
244 "missing entry" , return ISL_FN(ISL_HMAP,free)(hmap));
245
246 pair = entry->data;
247 isl_hash_table_remove(hmap->ctx, &hmap->table, entry);
248 ISL_FN(ISL_KEY,free)(pair->key);
249 ISL_FN(ISL_VAL,free)(pair->val);
250 free(pair);
251
252 return hmap;
253error:
254 ISL_FN(ISL_KEY,free)(key);
255 ISL_FN(ISL_HMAP,free)(hmap);
256 return NULL;
257}
258
259/* Add a mapping from "key" to "val" to "hmap".
260 * If "key" was already mapped to something else, then that mapping
261 * is replaced.
262 * If key happened to be mapped to "val" already, then we leave
263 * "hmap" untouched.
264 */
265__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,set)(__isl_take ISL_HMAP *hmap,
266 __isl_take ISL_KEY *key, __isl_take ISL_VAL *val)
267{
268 struct isl_hash_table_entry *entry;
269 ISL_S(pair) *pair;
270 uint32_t hash;
271
272 if (!hmap || !key || !val)
273 goto error;
274
275 hash = ISL_FN(ISL_KEY,get_hash)(key);
276 entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
277 &has_key, key, 0);
278 if (!entry)
279 goto error;
280 if (entry != isl_hash_table_entry_none) {
281 isl_bool equal;
282 pair = entry->data;
283 equal = ISL_VAL_IS_EQUAL(pair->val, val);
284 if (equal < 0)
285 goto error;
286 if (equal) {
287 ISL_FN(ISL_KEY,free)(key);
288 ISL_FN(ISL_VAL,free)(val);
289 return hmap;
290 }
291 }
292
293 hmap = ISL_FN(ISL_HMAP,cow)(hmap);
294 if (!hmap)
295 goto error;
296
297 entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
298 &has_key, key, 1);
299
300 if (!entry)
301 goto error;
302
303 if (entry->data) {
304 pair = entry->data;
305 ISL_FN(ISL_VAL,free)(pair->val);
306 pair->val = val;
307 ISL_FN(ISL_KEY,free)(key);
308 return hmap;
309 }
310
311 pair = isl_alloc_type(hmap->ctx, ISL_S(pair));
312 if (!pair)
313 goto error;
314
315 entry->data = pair;
316 pair->key = key;
317 pair->val = val;
318 return hmap;
319error:
320 ISL_FN(ISL_KEY,free)(key);
321 ISL_FN(ISL_VAL,free)(val);
322 return ISL_FN(ISL_HMAP,free)(hmap);
323}
324
325/* Internal data structure for isl_map_to_basic_set_foreach.
326 *
327 * fn is the function that should be called on each entry.
328 * user is the user-specified final argument to fn.
329 */
330ISL_S(foreach_data) {
331 isl_stat (*fn)(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val,
332 void *user);
333 void *user;
334};
335
336/* Call data->fn on a copy of the key and value in *entry.
337 */
338static isl_stat call_on_copy(void **entry, void *user)
339{
340 ISL_S(pair) *pair = *entry;
341 ISL_S(foreach_data) *data = (ISL_S(foreach_data) *) user;
342
343 return data->fn(ISL_FN(ISL_KEY,copy)(pair->key),
344 ISL_FN(ISL_VAL,copy)(pair->val), data->user);
345}
346
347/* Call "fn" on each pair of key and value in "hmap".
348 */
349isl_stat ISL_FN(ISL_HMAP,foreach)(__isl_keep ISL_HMAP *hmap,
350 isl_stat (*fn)(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val,
351 void *user),
352 void *user)
353{
354 ISL_S(foreach_data) data = { fn, user };
355
356 if (!hmap)
357 return isl_stat_error;
358
359 return isl_hash_table_foreach(hmap->ctx, &hmap->table,
360 &call_on_copy, &data);
361}
362
363/* Internal data structure for print_pair.
364 *
365 * p is the printer on which the associative array is being printed.
366 * first is set if the current key-value pair is the first to be printed.
367 */
368ISL_S(print_data) {
369 isl_printer *p;
370 int first;
371};
372
373/* Print the given key-value pair to data->p.
374 */
375static isl_stat print_pair(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val,
376 void *user)
377{
378 ISL_S(print_data) *data = user;
379
380 if (!data->first)
381 data->p = isl_printer_print_str(data->p, ", ");
382 data->p = ISL_KEY_PRINT(data->p, key);
383 data->p = isl_printer_print_str(data->p, ": ");
384 data->p = ISL_VAL_PRINT(data->p, val);
385 data->first = 0;
386
387 ISL_FN(ISL_KEY,free)(key);
388 ISL_FN(ISL_VAL,free)(val);
389 return isl_stat_ok;
390}
391
392/* Print the associative array to "p".
393 */
394__isl_give isl_printer *ISL_FN(isl_printer_print,ISL_HMAP_SUFFIX)(
395 __isl_take isl_printer *p, __isl_keep ISL_HMAP *hmap)
396{
397 ISL_S(print_data) data;
398
399 if (!p || !hmap)
400 return isl_printer_free(p);
401
402 p = isl_printer_print_str(p, "{");
403 data.p = p;
404 data.first = 1;
405 if (ISL_FN(ISL_HMAP,foreach)(hmap, &print_pair, &data) < 0)
406 data.p = isl_printer_free(data.p);
407 p = data.p;
408 p = isl_printer_print_str(p, "}");
409
410 return p;
411}
412
413void ISL_FN(ISL_HMAP,dump)(__isl_keep ISL_HMAP *hmap)
414{
415 isl_printer *printer;
416
417 if (!hmap)
418 return;
419
420 printer = isl_printer_to_file(ISL_FN(ISL_HMAP,get_ctx)(hmap), stderr);
421 printer = ISL_FN(isl_printer_print,ISL_HMAP_SUFFIX)(printer, hmap);
422 printer = isl_printer_end_line(printer);
423
424 isl_printer_free(printer);
425}
Note: See TracBrowser for help on using the repository browser.