aas.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #include <rid.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #define NIT_SHORT_NAMES
  5. #include <nit/macros.h>
  6. #include <nit/palloc.h>
  7. #include <nit/list.h>
  8. #include <nit/set.h>
  9. #include <nit/map.h>
  10. #include <nit/buf.h>
  11. #include <nit/gap.h>
  12. #include <nit/crs.h>
  13. #include "aas.h"
  14. Aas_rule *
  15. aas_rule_new(const Rid id, const Rid add_id, int64_t size)
  16. {
  17. Aas_rule *rule = palloc(rule);
  18. pcheck(rule, NULL);
  19. if (gap_init(&rule->vals, size) < 0) {
  20. free(rule);
  21. return NULL;
  22. }
  23. rule->next = NULL;
  24. rid_set(rule->id, id);
  25. rid_set(rule->add_id, add_id);
  26. return rule;
  27. }
  28. void
  29. aas_rule_free(Aas_rule *rule)
  30. {
  31. gap_dispose(&rule->vals);
  32. free(rule);
  33. }
  34. static int
  35. gap_contains(Nit_crs *crs, Nit_gap *gap, const Rid id)
  36. {
  37. Rid crs_id;
  38. crs_init(crs, gap, 0);
  39. while (!crs_movef(crs, sizeof(Rid))) {
  40. int cmp_val;
  41. crs_read(crs, crs_id, sizeof(Rid));
  42. if (!(cmp_val = rid_cmp(id, crs_id)))
  43. return 1;
  44. if (cmp_val > 0) {
  45. crs_moveb(crs, sizeof(Rid));
  46. return 0;
  47. }
  48. }
  49. return 0;
  50. }
  51. int
  52. aas_rule_add(Aas_rule *rule, const Rid id)
  53. {
  54. Nit_crs crs;
  55. if (gap_contains(&crs, &rule->vals, id))
  56. return 1;
  57. return crs_write(&crs, id, sizeof(Rid));
  58. }
  59. int
  60. aas_rule_remove(Aas_rule *rule, const Rid id)
  61. {
  62. Nit_crs crs;
  63. if (!gap_contains(&crs, &rule->vals, id))
  64. return 1;
  65. crs_erase(&crs, sizeof(Rid));
  66. return 0;
  67. }
  68. int
  69. aas_rule_same(Aas_rule *rule1, Aas_rule *rule2)
  70. {
  71. Nit_crs crs1;
  72. Nit_crs crs2;
  73. if (rid_cmp(rule1->add_id, rule2->add_id))
  74. return 0;
  75. crs_init(&crs1, &rule1->vals, 0);
  76. crs_init(&crs2, &rule2->vals, 0);
  77. while (1) {
  78. int move = crs_movef(&crs1, sizeof(Rid));
  79. Rid id1;
  80. Rid id2;
  81. if (move != crs_movef(&crs2, sizeof(Rid)))
  82. return 0;
  83. if (move < 0)
  84. break;
  85. crs_read(&crs1, id1, sizeof(Rid));
  86. crs_read(&crs2, id2, sizeof(Rid));
  87. if (rid_cmp(id1, id2))
  88. return 0;
  89. }
  90. return 1;
  91. }
  92. int
  93. aas_set_init(Aas_set *set, Aas_rule *rules, unsigned int sequence)
  94. {
  95. if (map_init(&set->vals, sequence) < 0)
  96. return -1;
  97. set->rules = rules;
  98. return 0;
  99. }
  100. static void
  101. set_free_func(void *key, void *val, void *extra)
  102. {
  103. (void) extra;
  104. (void) key;
  105. gap_free(val);
  106. }
  107. void
  108. aas_set_dispose(Aas_set *set, Nit_entry **entries)
  109. {
  110. Aas_rule *rules = set->rules;
  111. while (rules) {
  112. Aas_rule *tmp = rules;
  113. rules = rules->next;
  114. aas_rule_free(tmp);
  115. }
  116. map_recycle(&set->vals, set_free_func, NULL, entries);
  117. map_dispose(&set->vals);
  118. }
  119. Aas_set *
  120. aas_set_new(Aas_rule *rules, unsigned int sequence)
  121. {
  122. Aas_set *set = palloc(set);
  123. pcheck(set, NULL);
  124. if (aas_set_init(set, rules, sequence) < 0){
  125. free(set);
  126. return NULL;
  127. }
  128. return set;
  129. }
  130. void
  131. aas_set_free(Aas_set *set, Nit_entry **entries)
  132. {
  133. aas_set_dispose(set, entries);
  134. free(set);
  135. }
  136. static int
  137. vals_contains(Nit_map *set_vals, Nit_gap *rule_vals)
  138. {
  139. Nit_crs crs;
  140. crs_init(&crs, rule_vals, 0);
  141. while (!crs_movef(&crs, sizeof(Rid))) {
  142. Rid crs_id;
  143. crs_read(&crs, crs_id, sizeof(Rid));
  144. if (!set_contains(set_vals, crs_id, sizeof(Rid)))
  145. return 0;
  146. }
  147. return 1;
  148. }
  149. static int
  150. evoke_rule(Aas_rule *rule, Aas_set *set, Nit_entry **entries)
  151. {
  152. if (!vals_contains(&set->vals, &rule->vals))
  153. return 0;
  154. if (aas_set_add(set, rule->add_id, rule->id, entries) < 0)
  155. return -1;
  156. return 0;
  157. }
  158. int
  159. aas_set_rule(Aas_set *set, Aas_rule *rule, Nit_entry **entries)
  160. {
  161. if (aas_set_match_rule(set, rule))
  162. return 1;
  163. rule->next = set->rules;
  164. set->rules = rule;
  165. return evoke_rule(rule, set, entries);
  166. }
  167. Aas_rule *
  168. aas_set_unrule(Aas_set *set, const Rid id, Nit_entry **entries)
  169. {
  170. Aas_rule **rules = &set->rules;
  171. for (; *rules; rules = &(*rules)->next)
  172. if (!rid_cmp((*rules)->id, id)) {
  173. Aas_rule *rule = *rules;
  174. *rules = rule->next;
  175. aas_set_remove(set, rule->add_id, rule->id, entries);
  176. return rule;
  177. }
  178. return NULL;
  179. }
  180. static int
  181. evoke_rules(Aas_set *set, const Rid id, Nit_entry **entries)
  182. {
  183. Aas_rule *rule = set->rules;
  184. Nit_crs crs;
  185. for (; rule; rule = rule->next)
  186. if (gap_contains(&crs, &rule->vals, id) &&
  187. evoke_rule(rule, set, entries) < 0)
  188. return -1;
  189. return 0;
  190. }
  191. int
  192. aas_set_add(Aas_set *set, const Rid id, const Rid rule_id, Nit_entry **entries)
  193. {
  194. Nit_gap *gap = map_get(&set->vals, id, sizeof(Rid));
  195. if (gap) {
  196. Nit_crs crs;
  197. if (gap_contains(&crs, gap, rule_id))
  198. return 0;
  199. return crs_write(&crs, rule_id, sizeof(Rid));
  200. }
  201. if (!(gap = gap_new(sizeof(Rid))))
  202. return -1;
  203. gap_write(gap, rule_id, sizeof(Rid));
  204. if (map_add(&set->vals, id, sizeof(Rid), gap, entries) < 0) {
  205. gap_free(gap);
  206. return -1;
  207. }
  208. if (evoke_rules(set, id, entries) < 0) {
  209. map_remove(&set->vals, id, sizeof(Rid), entries);
  210. gap_free(gap);
  211. return -1;
  212. }
  213. return 0;
  214. }
  215. static void
  216. unevoke_rules(Aas_set *set, const Rid id, Nit_entry **entries)
  217. {
  218. Aas_rule *rule = set->rules;
  219. Nit_crs crs;
  220. for (; rule; rule = rule->next)
  221. if (gap_contains(&crs, &rule->vals, id))
  222. aas_set_remove(set, rule->add_id, rule->id, entries);
  223. return;
  224. }
  225. void
  226. aas_set_remove(Aas_set *set, const Rid id, const Rid rule_id,
  227. Nit_entry **entries)
  228. {
  229. Nit_gap *gap = map_get(&set->vals, id, sizeof(Rid));
  230. Nit_crs crs;
  231. if (!gap || !gap_contains(&crs, gap, rule_id))
  232. return;
  233. crs_erase(&crs, sizeof(Rid));
  234. if (gap_len(gap))
  235. return;
  236. map_remove(&set->vals, id, sizeof(Rid), entries);
  237. gap_free(gap);
  238. unevoke_rules(set, id, entries);
  239. }
  240. Aas_rule *
  241. aas_set_match_rule(Aas_set *set, Aas_rule *rule)
  242. {
  243. Aas_rule *rules = set->rules;
  244. for (; rules; rules = rules->next)
  245. if (aas_rule_same(rule, rules))
  246. return rules;
  247. return NULL;
  248. }
  249. Aas_rule *
  250. aas_set_get_rule(Aas_set *set, const Rid id)
  251. {
  252. Aas_rule *rules = set->rules;
  253. for (; rules; rules = rules->next)
  254. if (!rid_cmp(rules->id, id))
  255. return rules;
  256. return NULL;
  257. }