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.

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