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.

243 lines
7.2KB

  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 "log.h"
  21. #include "mem.h"
  22. #include "tree.h"
  23. typedef struct AVTreeNode {
  24. struct AVTreeNode *child[2];
  25. void *elem;
  26. int state;
  27. } AVTreeNode;
  28. #if FF_API_CONTEXT_SIZE
  29. const int av_tree_node_size = sizeof(AVTreeNode);
  30. #endif
  31. struct AVTreeNode *av_tree_node_alloc(void)
  32. {
  33. return av_mallocz(sizeof(struct AVTreeNode));
  34. }
  35. void *av_tree_find(const AVTreeNode *t, void *key,
  36. int (*cmp)(void *key, const void *b), void *next[2])
  37. {
  38. if (t) {
  39. unsigned int v = cmp(key, t->elem);
  40. if (v) {
  41. if (next)
  42. next[v >> 31] = t->elem;
  43. return av_tree_find(t->child[(v >> 31) ^ 1], key, cmp, next);
  44. } else {
  45. if (next) {
  46. av_tree_find(t->child[0], key, cmp, next);
  47. av_tree_find(t->child[1], key, cmp, next);
  48. }
  49. return t->elem;
  50. }
  51. }
  52. return NULL;
  53. }
  54. void *av_tree_insert(AVTreeNode **tp, void *key,
  55. int (*cmp)(void *key, const void *b), AVTreeNode **next)
  56. {
  57. AVTreeNode *t = *tp;
  58. if (t) {
  59. unsigned int v = cmp(t->elem, key);
  60. void *ret;
  61. if (!v) {
  62. if (*next)
  63. return t->elem;
  64. else if (t->child[0] || t->child[1]) {
  65. int i = !t->child[0];
  66. void *next_elem[2];
  67. av_tree_find(t->child[i], key, cmp, next_elem);
  68. key = t->elem = next_elem[i];
  69. v = -i;
  70. } else {
  71. *next = t;
  72. *tp = NULL;
  73. return NULL;
  74. }
  75. }
  76. ret = av_tree_insert(&t->child[v >> 31], key, cmp, next);
  77. if (!ret) {
  78. int i = (v >> 31) ^ !!*next;
  79. AVTreeNode **child = &t->child[i];
  80. t->state += 2 * i - 1;
  81. if (!(t->state & 1)) {
  82. if (t->state) {
  83. /* The following code is equivalent to
  84. * if ((*child)->state * 2 == -t->state)
  85. * rotate(child, i ^ 1);
  86. * rotate(tp, i);
  87. *
  88. * with rotate():
  89. * static void rotate(AVTreeNode **tp, int i)
  90. * {
  91. * AVTreeNode *t= *tp;
  92. *
  93. * *tp = t->child[i];
  94. * t->child[i] = t->child[i]->child[i ^ 1];
  95. * (*tp)->child[i ^ 1] = t;
  96. * i = 4 * t->state + 2 * (*tp)->state + 12;
  97. * t->state = ((0x614586 >> i) & 3) - 1;
  98. * (*tp)->state = ((0x400EEA >> i) & 3) - 1 +
  99. * ((*tp)->state >> 1);
  100. * }
  101. * but such a rotate function is both bigger and slower
  102. */
  103. if ((*child)->state * 2 == -t->state) {
  104. *tp = (*child)->child[i ^ 1];
  105. (*child)->child[i ^ 1] = (*tp)->child[i];
  106. (*tp)->child[i] = *child;
  107. *child = (*tp)->child[i ^ 1];
  108. (*tp)->child[i ^ 1] = t;
  109. (*tp)->child[0]->state = -((*tp)->state > 0);
  110. (*tp)->child[1]->state = (*tp)->state < 0;
  111. (*tp)->state = 0;
  112. } else {
  113. *tp = *child;
  114. *child = (*child)->child[i ^ 1];
  115. (*tp)->child[i ^ 1] = t;
  116. if ((*tp)->state)
  117. t->state = 0;
  118. else
  119. t->state >>= 1;
  120. (*tp)->state = -t->state;
  121. }
  122. }
  123. }
  124. if (!(*tp)->state ^ !!*next)
  125. return key;
  126. }
  127. return ret;
  128. } else {
  129. *tp = *next;
  130. *next = NULL;
  131. if (*tp) {
  132. (*tp)->elem = key;
  133. return NULL;
  134. } else
  135. return key;
  136. }
  137. }
  138. void av_tree_destroy(AVTreeNode *t)
  139. {
  140. if (t) {
  141. av_tree_destroy(t->child[0]);
  142. av_tree_destroy(t->child[1]);
  143. av_free(t);
  144. }
  145. }
  146. void av_tree_enumerate(AVTreeNode *t, void *opaque,
  147. int (*cmp)(void *opaque, void *elem),
  148. int (*enu)(void *opaque, void *elem))
  149. {
  150. if (t) {
  151. int v = cmp ? cmp(opaque, t->elem) : 0;
  152. if (v >= 0)
  153. av_tree_enumerate(t->child[0], opaque, cmp, enu);
  154. if (v == 0)
  155. enu(opaque, t->elem);
  156. if (v <= 0)
  157. av_tree_enumerate(t->child[1], opaque, cmp, enu);
  158. }
  159. }
  160. #ifdef TEST
  161. #include "common.h"
  162. #include "lfg.h"
  163. static int check(AVTreeNode *t)
  164. {
  165. if (t) {
  166. int left = check(t->child[0]);
  167. int right = check(t->child[1]);
  168. if (left > 999 || right > 999)
  169. return 1000;
  170. if (right - left != t->state)
  171. return 1000;
  172. if (t->state > 1 || t->state < -1)
  173. return 1000;
  174. return FFMAX(left, right) + 1;
  175. }
  176. return 0;
  177. }
  178. static void print(AVTreeNode *t, int depth)
  179. {
  180. int i;
  181. for (i = 0; i < depth * 4; i++)
  182. av_log(NULL, AV_LOG_ERROR, " ");
  183. if (t) {
  184. av_log(NULL, AV_LOG_ERROR, "Node %p %2d %p\n", t, t->state, t->elem);
  185. print(t->child[0], depth + 1);
  186. print(t->child[1], depth + 1);
  187. } else
  188. av_log(NULL, AV_LOG_ERROR, "NULL\n");
  189. }
  190. static int cmp(void *a, const void *b)
  191. {
  192. return (uint8_t *) a - (const uint8_t *) b;
  193. }
  194. int main(void)
  195. {
  196. int i;
  197. void *k;
  198. AVTreeNode *root = NULL, *node = NULL;
  199. AVLFG prng;
  200. av_lfg_init(&prng, 1);
  201. for (i = 0; i < 10000; i++) {
  202. int j = av_lfg_get(&prng) % 86294;
  203. if (check(root) > 999) {
  204. av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
  205. print(root, 0);
  206. return -1;
  207. }
  208. if (!node)
  209. node = av_tree_node_alloc();
  210. av_tree_insert(&root, (void *)(j + 1), cmp, &node);
  211. j = av_lfg_get(&prng) % 86294;
  212. {
  213. AVTreeNode *node2 = NULL;
  214. av_tree_insert(&root, (void *)(j + 1), cmp, &node2);
  215. k = av_tree_find(root, (void *)(j + 1), cmp, NULL);
  216. if (k)
  217. av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i);
  218. }
  219. }
  220. return 0;
  221. }
  222. #endif