You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
7.6KB

  1. /*
  2. * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * Libav is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "error.h"
  21. #include "log.h"
  22. #include "mem.h"
  23. #include "tree.h"
  24. typedef struct AVTreeNode {
  25. struct AVTreeNode *child[2];
  26. void *elem;
  27. int state;
  28. } AVTreeNode;
  29. struct AVTreeNode *av_tree_node_alloc(void)
  30. {
  31. return av_mallocz(sizeof(struct AVTreeNode));
  32. }
  33. void *av_tree_find(const AVTreeNode *t, void *key,
  34. int (*cmp)(void *key, const void *b), void *next[2])
  35. {
  36. if (t) {
  37. unsigned int v = cmp(key, t->elem);
  38. if (v) {
  39. if (next)
  40. next[v >> 31] = t->elem;
  41. return av_tree_find(t->child[(v >> 31) ^ 1], key, cmp, next);
  42. } else {
  43. if (next) {
  44. av_tree_find(t->child[0], key, cmp, next);
  45. av_tree_find(t->child[1], key, cmp, next);
  46. }
  47. return t->elem;
  48. }
  49. }
  50. return NULL;
  51. }
  52. void *av_tree_insert(AVTreeNode **tp, void *key,
  53. int (*cmp)(void *key, const void *b), AVTreeNode **next)
  54. {
  55. AVTreeNode *t = *tp;
  56. if (t) {
  57. unsigned int v = cmp(t->elem, key);
  58. void *ret;
  59. if (!v) {
  60. if (*next)
  61. return t->elem;
  62. else if (t->child[0] || t->child[1]) {
  63. int i = !t->child[0];
  64. void *next_elem[2];
  65. av_tree_find(t->child[i], key, cmp, next_elem);
  66. key = t->elem = next_elem[i];
  67. v = -i;
  68. } else {
  69. *next = t;
  70. *tp = NULL;
  71. return NULL;
  72. }
  73. }
  74. ret = av_tree_insert(&t->child[v >> 31], key, cmp, next);
  75. if (!ret) {
  76. int i = (v >> 31) ^ !!*next;
  77. AVTreeNode **child = &t->child[i];
  78. t->state += 2 * i - 1;
  79. if (!(t->state & 1)) {
  80. if (t->state) {
  81. /* The following code is equivalent to
  82. * if ((*child)->state * 2 == -t->state)
  83. * rotate(child, i ^ 1);
  84. * rotate(tp, i);
  85. *
  86. * with rotate():
  87. * static void rotate(AVTreeNode **tp, int i)
  88. * {
  89. * AVTreeNode *t= *tp;
  90. *
  91. * *tp = t->child[i];
  92. * t->child[i] = t->child[i]->child[i ^ 1];
  93. * (*tp)->child[i ^ 1] = t;
  94. * i = 4 * t->state + 2 * (*tp)->state + 12;
  95. * t->state = ((0x614586 >> i) & 3) - 1;
  96. * (*tp)->state = ((0x400EEA >> i) & 3) - 1 +
  97. * ((*tp)->state >> 1);
  98. * }
  99. * but such a rotate function is both bigger and slower
  100. */
  101. if ((*child)->state * 2 == -t->state) {
  102. *tp = (*child)->child[i ^ 1];
  103. (*child)->child[i ^ 1] = (*tp)->child[i];
  104. (*tp)->child[i] = *child;
  105. *child = (*tp)->child[i ^ 1];
  106. (*tp)->child[i ^ 1] = t;
  107. (*tp)->child[0]->state = -((*tp)->state > 0);
  108. (*tp)->child[1]->state = (*tp)->state < 0;
  109. (*tp)->state = 0;
  110. } else {
  111. *tp = *child;
  112. *child = (*child)->child[i ^ 1];
  113. (*tp)->child[i ^ 1] = t;
  114. if ((*tp)->state)
  115. t->state = 0;
  116. else
  117. t->state >>= 1;
  118. (*tp)->state = -t->state;
  119. }
  120. }
  121. }
  122. if (!(*tp)->state ^ !!*next)
  123. return key;
  124. }
  125. return ret;
  126. } else {
  127. *tp = *next;
  128. *next = NULL;
  129. if (*tp) {
  130. (*tp)->elem = key;
  131. return NULL;
  132. } else
  133. return key;
  134. }
  135. }
  136. void av_tree_destroy(AVTreeNode *t)
  137. {
  138. if (t) {
  139. av_tree_destroy(t->child[0]);
  140. av_tree_destroy(t->child[1]);
  141. av_free(t);
  142. }
  143. }
  144. void av_tree_enumerate(AVTreeNode *t, void *opaque,
  145. int (*cmp)(void *opaque, void *elem),
  146. int (*enu)(void *opaque, void *elem))
  147. {
  148. if (t) {
  149. int v = cmp ? cmp(opaque, t->elem) : 0;
  150. if (v >= 0)
  151. av_tree_enumerate(t->child[0], opaque, cmp, enu);
  152. if (v == 0)
  153. enu(opaque, t->elem);
  154. if (v <= 0)
  155. av_tree_enumerate(t->child[1], opaque, cmp, enu);
  156. }
  157. }
  158. #ifdef TEST
  159. #include "common.h"
  160. #include "lfg.h"
  161. static int check(AVTreeNode *t)
  162. {
  163. if (t) {
  164. int left = check(t->child[0]);
  165. int right = check(t->child[1]);
  166. if (left > 999 || right > 999)
  167. return 1000;
  168. if (right - left != t->state)
  169. return 1000;
  170. if (t->state > 1 || t->state < -1)
  171. return 1000;
  172. return FFMAX(left, right) + 1;
  173. }
  174. return 0;
  175. }
  176. static void print(AVTreeNode *t, int depth)
  177. {
  178. int i;
  179. for (i = 0; i < depth * 4; i++)
  180. av_log(NULL, AV_LOG_ERROR, " ");
  181. if (t) {
  182. av_log(NULL, AV_LOG_ERROR, "Node %p %2d %p\n", t, t->state, t->elem);
  183. print(t->child[0], depth + 1);
  184. print(t->child[1], depth + 1);
  185. } else
  186. av_log(NULL, AV_LOG_ERROR, "NULL\n");
  187. }
  188. static int cmp(void *a, const void *b)
  189. {
  190. return (uint8_t *) a - (const uint8_t *) b;
  191. }
  192. int main(void)
  193. {
  194. int i;
  195. AVTreeNode *root = NULL, *node = NULL;
  196. AVLFG prng;
  197. av_lfg_init(&prng, 1);
  198. for (i = 0; i < 10000; i++) {
  199. AVTreeNode *node2 = NULL;
  200. intptr_t j = av_lfg_get(&prng) % 86294;
  201. void *ret, *jj = (void *)(j + 1);
  202. while (ret = av_tree_find(root, jj, cmp, NULL)) {
  203. j = av_lfg_get(&prng) % 86294;
  204. jj = (void *)(j + 1);
  205. }
  206. if (check(root) > 999) {
  207. av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
  208. print(root, 0);
  209. return 1;
  210. }
  211. if (!node)
  212. node = av_tree_node_alloc();
  213. if (!node) {
  214. av_log(NULL, AV_LOG_ERROR, "Memory allocation failure.\n");
  215. return 1;
  216. }
  217. av_tree_insert(&root, jj, cmp, &node);
  218. while (ret = av_tree_find(root, jj, cmp, NULL)) {
  219. j = av_lfg_get(&prng) % 86294;
  220. jj = (void *)(j + 1);
  221. }
  222. ret = av_tree_insert(&root, jj, cmp, &node2);
  223. if (ret != jj)
  224. av_tree_destroy(node2);
  225. ret = av_tree_find(root, jj, cmp, NULL);
  226. if (ret)
  227. av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i);
  228. }
  229. av_tree_destroy(root);
  230. return 0;
  231. }
  232. #endif