A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

353 lignes
12 KiB

  1. /*
  2. * avl_tree.h - intrusive, nonrecursive AVL tree data structure (self-balancing
  3. * binary search tree), header file
  4. *
  5. * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
  6. * Slight changes for compatibility by Ben Kurtovic <ben.kurtovic@gmail.com>
  7. *
  8. * To the extent possible under law, the author(s) have dedicated all copyright
  9. * and related and neighboring rights to this software to the public domain
  10. * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
  11. * Dedication (the "CC0").
  12. *
  13. * This software is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
  16. *
  17. * You should have received a copy of the CC0 along with this software; if not
  18. * see <http://creativecommons.org/publicdomain/zero/1.0/>.
  19. */
  20. #ifndef _AVL_TREE_H_
  21. #define _AVL_TREE_H_
  22. #include <stddef.h>
  23. #if !defined(_MSC_VER) || (_MSC_VER >= 1600)
  24. # include <stdint.h>
  25. #endif
  26. #ifdef __GNUC__
  27. # define AVL_INLINE inline __attribute__((always_inline))
  28. #elif defined(_MSC_VER) && (_MSC_VER < 1900)
  29. # define AVL_INLINE __inline
  30. #else
  31. # define AVL_INLINE inline
  32. #endif
  33. /* Node in an AVL tree. Embed this in some other data structure. */
  34. struct avl_tree_node {
  35. /* Pointer to left child or NULL */
  36. struct avl_tree_node *left;
  37. /* Pointer to right child or NULL */
  38. struct avl_tree_node *right;
  39. /* Pointer to parent combined with the balance factor. This saves 4 or
  40. * 8 bytes of memory depending on the CPU architecture.
  41. *
  42. * Low 2 bits: One greater than the balance factor of this subtree,
  43. * which is equal to height(right) - height(left). The mapping is:
  44. *
  45. * 00 => -1
  46. * 01 => 0
  47. * 10 => +1
  48. * 11 => undefined
  49. *
  50. * The rest of the bits are the pointer to the parent node. It must be
  51. * 4-byte aligned, and it will be NULL if this is the root node and
  52. * therefore has no parent. */
  53. uintptr_t parent_balance;
  54. };
  55. /* Cast an AVL tree node to the containing data structure. */
  56. #define avl_tree_entry(entry, type, member) \
  57. ((type *) ((char *) (entry) -offsetof(type, member)))
  58. /* Returns a pointer to the parent of the specified AVL tree node, or NULL if it
  59. * is already the root of the tree. */
  60. static AVL_INLINE struct avl_tree_node *
  61. avl_get_parent(const struct avl_tree_node *node)
  62. {
  63. return (struct avl_tree_node *) (node->parent_balance & ~3);
  64. }
  65. /* Marks the specified AVL tree node as unlinked from any tree. */
  66. static AVL_INLINE void
  67. avl_tree_node_set_unlinked(struct avl_tree_node *node)
  68. {
  69. node->parent_balance = (uintptr_t) node;
  70. }
  71. /* Returns true iff the specified AVL tree node has been marked with
  72. * avl_tree_node_set_unlinked() and has not subsequently been inserted into a
  73. * tree. */
  74. static AVL_INLINE int
  75. avl_tree_node_is_unlinked(const struct avl_tree_node *node)
  76. {
  77. return node->parent_balance == (uintptr_t) node;
  78. }
  79. /* (Internal use only) */
  80. extern void avl_tree_rebalance_after_insert(struct avl_tree_node **root_ptr,
  81. struct avl_tree_node *inserted);
  82. /*
  83. * Looks up an item in the specified AVL tree.
  84. *
  85. * @root
  86. * Pointer to the root of the AVL tree. (This can be NULL --- that just
  87. * means the tree is empty.)
  88. *
  89. * @cmp_ctx
  90. * First argument to pass to the comparison callback. This generally
  91. * should be a pointer to an object equal to the one being searched for.
  92. *
  93. * @cmp
  94. * Comparison callback. Must return < 0, 0, or > 0 if the first argument
  95. * is less than, equal to, or greater than the second argument,
  96. * respectively. The first argument will be @cmp_ctx and the second
  97. * argument will be a pointer to the AVL tree node of an item in the tree.
  98. *
  99. * Returns a pointer to the AVL tree node of the resulting item, or NULL if the
  100. * item was not found.
  101. *
  102. * Example:
  103. *
  104. * struct int_wrapper {
  105. * int data;
  106. * struct avl_tree_node index_node;
  107. * };
  108. *
  109. * static int _avl_cmp_int_to_node(const void *intptr,
  110. * const struct avl_tree_node *nodeptr)
  111. * {
  112. * int n1 = *(const int *)intptr;
  113. * int n2 = avl_tree_entry(nodeptr, struct int_wrapper, index_node)->data;
  114. * if (n1 < n2)
  115. * return -1;
  116. * else if (n1 > n2)
  117. * return 1;
  118. * else
  119. * return 0;
  120. * }
  121. *
  122. * bool contains_int(struct avl_tree_node *root, int n)
  123. * {
  124. * struct avl_tree_node *result;
  125. *
  126. * result = avl_tree_lookup(root, &n, _avl_cmp_int_to_node);
  127. * return result ? true : false;
  128. * }
  129. */
  130. static AVL_INLINE struct avl_tree_node *
  131. avl_tree_lookup(const struct avl_tree_node *root,
  132. const void *cmp_ctx,
  133. int (*cmp)(const void *, const struct avl_tree_node *))
  134. {
  135. const struct avl_tree_node *cur = root;
  136. while (cur) {
  137. int res = (*cmp)(cmp_ctx, cur);
  138. if (res < 0) {
  139. cur = cur->left;
  140. } else if (res > 0) {
  141. cur = cur->right;
  142. } else {
  143. break;
  144. }
  145. }
  146. return (struct avl_tree_node *) cur;
  147. }
  148. /* Same as avl_tree_lookup(), but uses a more specific type for the comparison
  149. * function. Specifically, with this function the item being searched for is
  150. * expected to be in the same format as those already in the tree, with an
  151. * embedded 'struct avl_tree_node'. */
  152. static AVL_INLINE struct avl_tree_node *
  153. avl_tree_lookup_node(const struct avl_tree_node *root,
  154. const struct avl_tree_node *node,
  155. int (*cmp)(const struct avl_tree_node *,
  156. const struct avl_tree_node *))
  157. {
  158. const struct avl_tree_node *cur = root;
  159. while (cur) {
  160. int res = (*cmp)(node, cur);
  161. if (res < 0) {
  162. cur = cur->left;
  163. } else if (res > 0) {
  164. cur = cur->right;
  165. } else {
  166. break;
  167. }
  168. }
  169. return (struct avl_tree_node *) cur;
  170. }
  171. /*
  172. * Inserts an item into the specified AVL tree.
  173. *
  174. * @root_ptr
  175. * Location of the AVL tree's root pointer. Indirection is needed because
  176. * the root node may change as a result of rotations caused by the
  177. * insertion. Initialize *root_ptr to NULL for an empty tree.
  178. *
  179. * @item
  180. * Pointer to the `struct avl_tree_node' embedded in the item to insert.
  181. * No members in it need be pre-initialized, although members in the
  182. * containing structure should be pre-initialized so that @cmp can use them
  183. * in comparisons.
  184. *
  185. * @cmp
  186. * Comparison callback. Must return < 0, 0, or > 0 if the first argument
  187. * is less than, equal to, or greater than the second argument,
  188. * respectively. The first argument will be @item and the second
  189. * argument will be a pointer to an AVL tree node embedded in some
  190. * previously-inserted item to which @item is being compared.
  191. *
  192. * If no item in the tree is comparatively equal (via @cmp) to @item, inserts
  193. * @item and returns NULL. Otherwise does nothing and returns a pointer to the
  194. * AVL tree node embedded in the previously-inserted item which compared equal
  195. * to @item.
  196. *
  197. * Example:
  198. *
  199. * struct int_wrapper {
  200. * int data;
  201. * struct avl_tree_node index_node;
  202. * };
  203. *
  204. * #define GET_DATA(i) avl_tree_entry((i), struct int_wrapper, index_node)->data
  205. *
  206. * static int _avl_cmp_ints(const struct avl_tree_node *node1,
  207. * const struct avl_tree_node *node2)
  208. * {
  209. * int n1 = GET_DATA(node1);
  210. * int n2 = GET_DATA(node2);
  211. * if (n1 < n2)
  212. * return -1;
  213. * else if (n1 > n2)
  214. * return 1;
  215. * else
  216. * return 0;
  217. * }
  218. *
  219. * bool insert_int(struct avl_tree_node **root_ptr, int data)
  220. * {
  221. * struct int_wrapper *i = malloc(sizeof(struct int_wrapper));
  222. * i->data = data;
  223. * if (avl_tree_insert(root_ptr, &i->index_node, _avl_cmp_ints)) {
  224. * // Duplicate.
  225. * free(i);
  226. * return false;
  227. * }
  228. * return true;
  229. * }
  230. */
  231. static AVL_INLINE struct avl_tree_node *
  232. avl_tree_insert(struct avl_tree_node **root_ptr,
  233. struct avl_tree_node *item,
  234. int (*cmp)(const struct avl_tree_node *, const struct avl_tree_node *))
  235. {
  236. struct avl_tree_node **cur_ptr = root_ptr, *cur = NULL;
  237. int res;
  238. while (*cur_ptr) {
  239. cur = *cur_ptr;
  240. res = (*cmp)(item, cur);
  241. if (res < 0) {
  242. cur_ptr = &cur->left;
  243. } else if (res > 0) {
  244. cur_ptr = &cur->right;
  245. } else {
  246. return cur;
  247. }
  248. }
  249. *cur_ptr = item;
  250. item->parent_balance = (uintptr_t) cur | 1;
  251. avl_tree_rebalance_after_insert(root_ptr, item);
  252. return NULL;
  253. }
  254. /* Removes an item from the specified AVL tree.
  255. * See implementation for details. */
  256. extern void avl_tree_remove(struct avl_tree_node **root_ptr,
  257. struct avl_tree_node *node);
  258. /* Nonrecursive AVL tree traversal functions */
  259. extern struct avl_tree_node *avl_tree_first_in_order(const struct avl_tree_node *root);
  260. extern struct avl_tree_node *avl_tree_last_in_order(const struct avl_tree_node *root);
  261. extern struct avl_tree_node *avl_tree_next_in_order(const struct avl_tree_node *node);
  262. extern struct avl_tree_node *avl_tree_prev_in_order(const struct avl_tree_node *node);
  263. extern struct avl_tree_node *
  264. avl_tree_first_in_postorder(const struct avl_tree_node *root);
  265. extern struct avl_tree_node *
  266. avl_tree_next_in_postorder(const struct avl_tree_node *prev,
  267. const struct avl_tree_node *prev_parent);
  268. /*
  269. * Iterate through the nodes in an AVL tree in sorted order.
  270. * You may not modify the tree during the iteration.
  271. *
  272. * @child_struct
  273. * Variable that will receive a pointer to each struct inserted into the
  274. * tree.
  275. * @root
  276. * Root of the AVL tree.
  277. * @struct_name
  278. * Type of *child_struct.
  279. * @struct_member
  280. * Member of @struct_name type that is the AVL tree node.
  281. *
  282. * Example:
  283. *
  284. * struct int_wrapper {
  285. * int data;
  286. * struct avl_tree_node index_node;
  287. * };
  288. *
  289. * void print_ints(struct avl_tree_node *root)
  290. * {
  291. * struct int_wrapper *i;
  292. *
  293. * avl_tree_for_each_in_order(i, root, struct int_wrapper, index_node)
  294. * printf("%d\n", i->data);
  295. * }
  296. */
  297. #define avl_tree_for_each_in_order(child_struct, root, struct_name, struct_member) \
  298. for (struct avl_tree_node *_cur = avl_tree_first_in_order(root); \
  299. _cur && \
  300. ((child_struct) = avl_tree_entry(_cur, struct_name, struct_member), 1); \
  301. _cur = avl_tree_next_in_order(_cur))
  302. /*
  303. * Like avl_tree_for_each_in_order(), but uses the reverse order.
  304. */
  305. #define avl_tree_for_each_in_reverse_order( \
  306. child_struct, root, struct_name, struct_member) \
  307. for (struct avl_tree_node *_cur = avl_tree_last_in_order(root); \
  308. _cur && \
  309. ((child_struct) = avl_tree_entry(_cur, struct_name, struct_member), 1); \
  310. _cur = avl_tree_prev_in_order(_cur))
  311. /*
  312. * Like avl_tree_for_each_in_order(), but iterates through the nodes in
  313. * postorder, so the current node may be deleted or freed.
  314. */
  315. #define avl_tree_for_each_in_postorder(child_struct, root, struct_name, struct_member) \
  316. for (struct avl_tree_node *_cur = avl_tree_first_in_postorder(root), *_parent; \
  317. _cur && \
  318. ((child_struct) = avl_tree_entry(_cur, struct_name, struct_member), 1) && \
  319. (_parent = avl_get_parent(_cur), 1); \
  320. _cur = avl_tree_next_in_postorder(_cur, _parent))
  321. #endif /* _AVL_TREE_H_ */