2 * Copyright 2011 INRIA Saclay
3 * Copyright 2013 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
8 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
10 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
15 #include <isl/stream.h>
17 #define ISL_xCAT(A,B) A ## B
18 #define ISL_CAT(A,B) ISL_xCAT(A,B)
19 #define ISL_xFN(TYPE,NAME) TYPE ## _ ## NAME
20 #define ISL_FN(TYPE,NAME) ISL_xFN(TYPE,NAME)
21 #define ISL_xS(TYPE1,TYPE2,NAME) struct isl_ ## TYPE1 ## _ ## TYPE2 ## _ ## NAME
22 #define ISL_yS(TYPE1,TYPE2,NAME) ISL_xS(TYPE1,TYPE2,NAME)
23 #define ISL_S(NAME) ISL_yS(ISL_KEY,ISL_VAL,NAME)
28 struct isl_hash_table table
;
36 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,alloc
)(isl_ctx
*ctx
, int min_size
)
40 hmap
= isl_calloc_type(ctx
, ISL_HMAP
);
48 if (isl_hash_table_init(ctx
, &hmap
->table
, min_size
) < 0)
49 return ISL_FN(ISL_HMAP
,free
)(hmap
);
54 static isl_stat
free_pair(void **entry
, void *user
)
56 ISL_S(pair
) *pair
= *entry
;
57 ISL_FN(ISL_KEY
,free
)(pair
->key
);
58 ISL_FN(ISL_VAL
,free
)(pair
->val
);
64 __isl_null ISL_HMAP
*ISL_FN(ISL_HMAP
,free
)(__isl_take ISL_HMAP
*hmap
)
70 isl_hash_table_foreach(hmap
->ctx
, &hmap
->table
, &free_pair
, NULL
);
71 isl_hash_table_clear(&hmap
->table
);
72 isl_ctx_deref(hmap
->ctx
);
77 isl_ctx
*ISL_FN(ISL_HMAP
,get_ctx
)(__isl_keep ISL_HMAP
*hmap
)
79 return hmap
? hmap
->ctx
: NULL
;
82 /* Add a mapping from "key" to "val" to the associative array
85 static isl_stat
add_key_val(__isl_take ISL_KEY
*key
, __isl_take ISL_VAL
*val
,
88 ISL_HMAP
**hmap
= (ISL_HMAP
**) user
;
90 *hmap
= ISL_FN(ISL_HMAP
,set
)(*hmap
, key
, val
);
93 return isl_stat_error
;
98 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,dup
)(__isl_keep ISL_HMAP
*hmap
)
105 dup
= ISL_FN(ISL_HMAP
,alloc
)(hmap
->ctx
, hmap
->table
.n
);
106 if (ISL_FN(ISL_HMAP
,foreach
)(hmap
, &add_key_val
, &dup
) < 0)
107 return ISL_FN(ISL_HMAP
,free
)(dup
);
112 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,cow
)(__isl_take ISL_HMAP
*hmap
)
120 return ISL_FN(ISL_HMAP
,dup
)(hmap
);
123 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,copy
)(__isl_keep ISL_HMAP
*hmap
)
132 static isl_bool
has_key(const void *entry
, const void *c_key
)
134 const ISL_S(pair
) *pair
= entry
;
135 ISL_KEY
*key
= (ISL_KEY
*) c_key
;
137 return ISL_KEY_IS_EQUAL(pair
->key
, key
);
140 /* If "hmap" contains a value associated to "key", then return
141 * (isl_bool_true, copy of value).
143 * (isl_bool_false, NULL).
144 * If an error occurs, then return
145 * (isl_bool_error, NULL).
147 __isl_give
ISL_MAYBE(ISL_VAL
) ISL_FN(ISL_HMAP
,try_get
)(
148 __isl_keep ISL_HMAP
*hmap
, __isl_keep ISL_KEY
*key
)
150 struct isl_hash_table_entry
*entry
;
153 ISL_MAYBE(ISL_VAL
) res
= { isl_bool_false
, NULL
};
158 hash
= ISL_FN(ISL_KEY
,get_hash
)(key
);
159 entry
= isl_hash_table_find(hmap
->ctx
, &hmap
->table
, hash
,
164 if (entry
== isl_hash_table_entry_none
)
169 res
.valid
= isl_bool_true
;
170 res
.value
= ISL_FN(ISL_VAL
,copy
)(pair
->val
);
172 res
.valid
= isl_bool_error
;
175 res
.valid
= isl_bool_error
;
180 /* If "hmap" contains a value associated to "key", then return
181 * isl_bool_true. Otherwise, return isl_bool_false.
182 * Return isl_bool_error on error.
184 isl_bool
ISL_FN(ISL_HMAP
,has
)(__isl_keep ISL_HMAP
*hmap
,
185 __isl_keep ISL_KEY
*key
)
187 ISL_MAYBE(ISL_VAL
) res
;
189 res
= ISL_FN(ISL_HMAP
,try_get
)(hmap
, key
);
190 ISL_FN(ISL_VAL
,free
)(res
.value
);
195 /* If "hmap" contains a value associated to "key", then return
196 * a copy of that value. Otherwise, return NULL.
197 * Return NULL on error.
199 __isl_give ISL_VAL
*ISL_FN(ISL_HMAP
,get
)(__isl_keep ISL_HMAP
*hmap
,
200 __isl_take ISL_KEY
*key
)
204 res
= ISL_FN(ISL_HMAP
,try_get
)(hmap
, key
).value
;
205 ISL_FN(ISL_KEY
,free
)(key
);
209 /* Remove the mapping between "key" and its associated value (if any)
212 * If "key" is not mapped to anything, then we leave "hmap" untouched"
214 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,drop
)(__isl_take ISL_HMAP
*hmap
,
215 __isl_take ISL_KEY
*key
)
217 struct isl_hash_table_entry
*entry
;
224 hash
= ISL_FN(ISL_KEY
,get_hash
)(key
);
225 entry
= isl_hash_table_find(hmap
->ctx
, &hmap
->table
, hash
,
229 if (entry
== isl_hash_table_entry_none
) {
230 ISL_FN(ISL_KEY
,free
)(key
);
234 hmap
= ISL_FN(ISL_HMAP
,cow
)(hmap
);
237 entry
= isl_hash_table_find(hmap
->ctx
, &hmap
->table
, hash
,
239 ISL_FN(ISL_KEY
,free
)(key
);
242 return ISL_FN(ISL_HMAP
,free
)(hmap
);
243 if (entry
== isl_hash_table_entry_none
)
244 isl_die(hmap
->ctx
, isl_error_internal
,
245 "missing entry" , return ISL_FN(ISL_HMAP
,free
)(hmap
));
248 isl_hash_table_remove(hmap
->ctx
, &hmap
->table
, entry
);
249 ISL_FN(ISL_KEY
,free
)(pair
->key
);
250 ISL_FN(ISL_VAL
,free
)(pair
->val
);
255 ISL_FN(ISL_KEY
,free
)(key
);
256 ISL_FN(ISL_HMAP
,free
)(hmap
);
260 /* Add a mapping from "key" to "val" to "hmap".
261 * If "key" was already mapped to something else, then that mapping
263 * If key happened to be mapped to "val" already, then we leave
266 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,set
)(__isl_take ISL_HMAP
*hmap
,
267 __isl_take ISL_KEY
*key
, __isl_take ISL_VAL
*val
)
269 struct isl_hash_table_entry
*entry
;
273 if (!hmap
|| !key
|| !val
)
276 hash
= ISL_FN(ISL_KEY
,get_hash
)(key
);
277 entry
= isl_hash_table_find(hmap
->ctx
, &hmap
->table
, hash
,
281 if (entry
!= isl_hash_table_entry_none
) {
284 equal
= ISL_VAL_IS_EQUAL(pair
->val
, val
);
288 ISL_FN(ISL_KEY
,free
)(key
);
289 ISL_FN(ISL_VAL
,free
)(val
);
294 hmap
= ISL_FN(ISL_HMAP
,cow
)(hmap
);
298 entry
= isl_hash_table_find(hmap
->ctx
, &hmap
->table
, hash
,
306 ISL_FN(ISL_VAL
,free
)(pair
->val
);
308 ISL_FN(ISL_KEY
,free
)(key
);
312 pair
= isl_alloc_type(hmap
->ctx
, ISL_S(pair
));
321 ISL_FN(ISL_KEY
,free
)(key
);
322 ISL_FN(ISL_VAL
,free
)(val
);
323 return ISL_FN(ISL_HMAP
,free
)(hmap
);
326 /* Internal data structure for isl_*_to_*_foreach.
328 * fn is the function that should be called on each entry.
329 * user is the user-specified final argument to fn.
331 ISL_S(foreach_data
) {
332 isl_stat (*fn
)(__isl_take ISL_KEY
*key
, __isl_take ISL_VAL
*val
,
337 /* Call data->fn on a copy of the key and value in *entry.
339 static isl_stat
call_on_copy(void **entry
, void *user
)
341 ISL_S(pair
) *pair
= *entry
;
342 ISL_S(foreach_data
) *data
= (ISL_S(foreach_data
) *) user
;
344 return data
->fn(ISL_FN(ISL_KEY
,copy
)(pair
->key
),
345 ISL_FN(ISL_VAL
,copy
)(pair
->val
), data
->user
);
348 /* Call "fn" on each pair of key and value in "hmap".
350 isl_stat
ISL_FN(ISL_HMAP
,foreach
)(__isl_keep ISL_HMAP
*hmap
,
351 isl_stat (*fn
)(__isl_take ISL_KEY
*key
, __isl_take ISL_VAL
*val
,
355 ISL_S(foreach_data
) data
= { fn
, user
};
358 return isl_stat_error
;
360 return isl_hash_table_foreach(hmap
->ctx
, &hmap
->table
,
361 &call_on_copy
, &data
);
364 /* Internal data structure for isl_*_to_*_every.
366 * "test" is the function that should be called on each entry,
367 * until any invocation returns isl_bool_false.
368 * "test_user" is the user-specified final argument to "test".
371 isl_bool (*test
)(__isl_keep ISL_KEY
*key
, __isl_keep ISL_VAL
*val
,
376 /* Call data->test on the key and value in *entry.
378 static isl_bool
call_on_pair(void **entry
, void *user
)
380 ISL_S(pair
) *pair
= *entry
;
381 ISL_S(every_data
) *data
= (ISL_S(every_data
) *) user
;
383 return data
->test(pair
->key
, pair
->val
, data
->test_user
);
386 /* Does "test" succeed on every entry of "hmap"?
388 isl_bool
ISL_FN(ISL_HMAP
,every
)(__isl_keep ISL_HMAP
*hmap
,
389 isl_bool (*test
)(__isl_keep ISL_KEY
*key
, __isl_keep ISL_VAL
*val
,
393 ISL_S(every_data
) data
= { test
, user
};
396 return isl_bool_error
;
398 return isl_hash_table_every(hmap
->ctx
, &hmap
->table
,
399 &call_on_pair
, &data
);
402 #ifdef ISL_HMAP_IS_EQUAL
404 /* Does "hmap" have an entry with key "key" and value "val"?
406 static isl_bool
has_entry(__isl_keep ISL_KEY
*key
, __isl_keep ISL_VAL
*val
,
409 ISL_HMAP
*hmap
= user
;
410 ISL_MAYBE(ISL_VAL
) maybe_val
;
413 maybe_val
= ISL_FN(ISL_HMAP
,try_get
)(hmap
, key
);
414 if (maybe_val
.valid
< 0 || !maybe_val
.valid
)
415 return maybe_val
.valid
;
416 equal
= ISL_VAL_IS_EQUAL(maybe_val
.value
, val
);
417 ISL_FN(ISL_VAL
,free
)(maybe_val
.value
);
421 /* Is "hmap1" (obviously) equal to "hmap2"?
423 * In particular, do the two associative arrays have
424 * the same number of entries and does every entry of the first
425 * also appear in the second?
427 isl_bool
ISL_HMAP_IS_EQUAL(__isl_keep ISL_HMAP
*hmap1
,
428 __isl_keep ISL_HMAP
*hmap2
)
430 if (!hmap1
|| !hmap2
)
431 return isl_bool_error
;
433 return isl_bool_true
;
434 if (hmap1
->table
.n
!= hmap2
->table
.n
)
435 return isl_bool_false
;
436 return ISL_FN(ISL_HMAP
,every
)(hmap1
, &has_entry
, hmap2
);
441 /* Internal data structure for print_pair.
443 * p is the printer on which the associative array is being printed.
444 * first is set if the current key-value pair is the first to be printed.
451 /* Print the given key-value pair to data->p.
453 static isl_stat
print_pair(__isl_take ISL_KEY
*key
, __isl_take ISL_VAL
*val
,
456 ISL_S(print_data
) *data
= user
;
459 data
->p
= isl_printer_print_str(data
->p
, ", ");
460 data
->p
= ISL_KEY_PRINT(data
->p
, key
);
461 data
->p
= isl_printer_print_str(data
->p
, ": ");
462 data
->p
= ISL_VAL_PRINT(data
->p
, val
);
465 ISL_FN(ISL_KEY
,free
)(key
);
466 ISL_FN(ISL_VAL
,free
)(val
);
470 /* Print the associative array to "p".
472 __isl_give isl_printer
*ISL_FN(isl_printer_print
,ISL_HMAP_SUFFIX
)(
473 __isl_take isl_printer
*p
, __isl_keep ISL_HMAP
*hmap
)
475 ISL_S(print_data
) data
;
478 return isl_printer_free(p
);
480 p
= isl_printer_print_str(p
, "{");
483 if (ISL_FN(ISL_HMAP
,foreach
)(hmap
, &print_pair
, &data
) < 0)
484 data
.p
= isl_printer_free(data
.p
);
486 p
= isl_printer_print_str(p
, "}");
491 void ISL_FN(ISL_HMAP
,dump
)(__isl_keep ISL_HMAP
*hmap
)
493 isl_printer
*printer
;
498 printer
= isl_printer_to_file(ISL_FN(ISL_HMAP
,get_ctx
)(hmap
), stderr
);
499 printer
= ISL_FN(isl_printer_print
,ISL_HMAP_SUFFIX
)(printer
, hmap
);
500 printer
= isl_printer_end_line(printer
);
502 isl_printer_free(printer
);
505 /* Return a string representation of "hmap".
507 __isl_give
char *ISL_FN(ISL_HMAP
,to_str
)(__isl_keep ISL_HMAP
*hmap
)
514 p
= isl_printer_to_str(ISL_FN(ISL_HMAP
,get_ctx
)(hmap
));
515 p
= ISL_FN(isl_printer_print
,ISL_HMAP_SUFFIX
)(p
, hmap
);
516 s
= isl_printer_get_str(p
);
522 #ifdef ISL_HMAP_HAVE_READ_FROM_STR
524 /* Read an associative array from "s".
525 * The input format corresponds to the way associative arrays are printed
526 * by isl_printer_print_*_to_*.
527 * In particular, each key-value pair is separated by a colon,
528 * the key-value pairs are separated by a comma and
529 * the entire associative array is surrounded by braces.
531 __isl_give ISL_HMAP
*ISL_FN(isl_stream_read
,ISL_HMAP_SUFFIX
)(isl_stream
*s
)
538 ctx
= isl_stream_get_ctx(s
);
539 hmap
= ISL_FN(ISL_HMAP
,alloc
)(ctx
, 0);
542 if (isl_stream_eat(s
, '{') < 0)
543 return ISL_FN(ISL_HMAP
,free
)(hmap
);
544 if (isl_stream_eat_if_available(s
, '}'))
550 key
= ISL_KEY_READ(s
);
551 if (isl_stream_eat(s
, ':') >= 0)
552 val
= ISL_VAL_READ(s
);
553 hmap
= ISL_FN(ISL_HMAP
,set
)(hmap
, key
, val
);
556 } while (isl_stream_eat_if_available(s
, ','));
557 if (isl_stream_eat(s
, '}') < 0)
558 return ISL_FN(ISL_HMAP
,free
)(hmap
);
562 /* Read an associative array from the string "str".
563 * The input format corresponds to the way associative arrays are printed
564 * by isl_printer_print_*_to_*.
565 * In particular, each key-value pair is separated by a colon,
566 * the key-value pairs are separated by a comma and
567 * the entire associative array is surrounded by braces.
569 __isl_give ISL_HMAP
*ISL_FN(ISL_HMAP
,read_from_str
)(isl_ctx
*ctx
,
575 s
= isl_stream_new_str(ctx
, str
);
578 hmap
= ISL_FN(isl_stream_read
,ISL_HMAP_SUFFIX
)(s
);