hmap_templ.c 9.5 KB

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