• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavutil/tree.c

Go to the documentation of this file.
00001 /*
00002  * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
00003  *
00004  * This file is part of Libav.
00005  *
00006  * Libav is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * Libav is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with Libav; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include "log.h"
00022 #include "tree.h"
00023 
00024 typedef struct AVTreeNode {
00025     struct AVTreeNode *child[2];
00026     void *elem;
00027     int state;
00028 } AVTreeNode;
00029 
00030 const int av_tree_node_size = sizeof(AVTreeNode);
00031 
00032 void *av_tree_find(const AVTreeNode *t, void *key,
00033                    int (*cmp)(void *key, const void *b), void *next[2])
00034 {
00035     if (t) {
00036         unsigned int v = cmp(key, t->elem);
00037         if (v) {
00038             if (next) next[v >> 31] = t->elem;
00039             return av_tree_find(t->child[(v >> 31) ^ 1], key, cmp, next);
00040         } else {
00041             if (next) {
00042                 av_tree_find(t->child[0], key, cmp, next);
00043                 av_tree_find(t->child[1], key, cmp, next);
00044             }
00045             return t->elem;
00046         }
00047     }
00048     return NULL;
00049 }
00050 
00051 void *av_tree_insert(AVTreeNode **tp, void *key,
00052                      int (*cmp)(void *key, const void *b), AVTreeNode **next)
00053 {
00054     AVTreeNode *t = *tp;
00055     if (t) {
00056         unsigned int v = cmp(t->elem, key);
00057         void *ret;
00058         if (!v) {
00059             if (*next)
00060                 return t->elem;
00061             else if (t->child[0] || t->child[1]) {
00062                 int i = !t->child[0];
00063                 void *next_elem[2];
00064                 av_tree_find(t->child[i], key, cmp, next_elem);
00065                 key = t->elem = next_elem[i];
00066                 v = -i;
00067             } else {
00068                 *next = t;
00069                 *tp = NULL;
00070                 return NULL;
00071             }
00072         }
00073         ret = av_tree_insert(&t->child[v >> 31], key, cmp, next);
00074         if (!ret) {
00075             int i = (v >> 31) ^ !!*next;
00076             AVTreeNode **child = &t->child[i];
00077             t->state += 2 * i - 1;
00078 
00079             if (!(t->state & 1)) {
00080                 if (t->state) {
00081                     /* The following code is equivalent to
00082                     if((*child)->state*2 == -t->state)
00083                         rotate(child, i^1);
00084                     rotate(tp, i);
00085 
00086                     with rotate():
00087                     static void rotate(AVTreeNode **tp, int i) {
00088                         AVTreeNode *t= *tp;
00089 
00090                         *tp= t->child[i];
00091                         t->child[i]= t->child[i]->child[i^1];
00092                         (*tp)->child[i^1]= t;
00093                         i= 4*t->state + 2*(*tp)->state + 12;
00094                           t  ->state=                     ((0x614586 >> i) & 3)-1;
00095                         (*tp)->state= ((*tp)->state>>1) + ((0x400EEA >> i) & 3)-1;
00096                     }
00097                     but such a rotate function is both bigger and slower
00098                     */
00099                     if (( *child )->state * 2 == -t->state) {
00100                         *tp                    = (*child)->child[i ^ 1];
00101                         (*child)->child[i ^ 1] = (*tp)->child[i];
00102                         (*tp)->child[i]        = *child;
00103                         *child                 = ( *tp )->child[i ^ 1];
00104                         (*tp)->child[i ^ 1]    = t;
00105 
00106                         (*tp)->child[0]->state = -((*tp)->state > 0);
00107                         (*tp)->child[1]->state =   (*tp)->state < 0;
00108                         (*tp)->state           = 0;
00109                     } else {
00110                         *tp                    = *child;
00111                         *child                 = (*child)->child[i ^ 1];
00112                         (*tp)->child[i ^ 1]    = t;
00113                         if ((*tp)->state) t->state = 0;
00114                         else              t->state >>= 1;
00115                         (*tp)->state           = -t->state;
00116                     }
00117                 }
00118             }
00119             if (!(*tp)->state ^ !!*next)
00120                 return key;
00121         }
00122         return ret;
00123     } else {
00124         *tp   = *next;
00125         *next = NULL;
00126         if (*tp) {
00127             (*tp)->elem = key;
00128             return NULL;
00129         } else
00130             return key;
00131     }
00132 }
00133 
00134 void av_tree_destroy(AVTreeNode *t)
00135 {
00136     if (t) {
00137         av_tree_destroy(t->child[0]);
00138         av_tree_destroy(t->child[1]);
00139         av_free(t);
00140     }
00141 }
00142 
00143 void av_tree_enumerate(AVTreeNode *t, void *opaque,
00144                        int (*cmp)(void *opaque, void *elem),
00145                        int (*enu)(void *opaque, void *elem))
00146 {
00147     if (t) {
00148         int v = cmp ? cmp(opaque, t->elem) : 0;
00149         if (v >= 0)
00150             av_tree_enumerate(t->child[0], opaque, cmp, enu);
00151         if (v == 0)
00152             enu(opaque, t->elem);
00153         if (v <= 0)
00154             av_tree_enumerate(t->child[1], opaque, cmp, enu);
00155     }
00156 }
00157 
00158 #ifdef TEST
00159 
00160 #include "lfg.h"
00161 
00162 static int check(AVTreeNode *t)
00163 {
00164     if (t) {
00165         int left  = check(t->child[0]);
00166         int right = check(t->child[1]);
00167 
00168         if (left>999 || right>999)
00169             return 1000;
00170         if (right - left != t->state)
00171             return 1000;
00172         if (t->state>1 || t->state<-1)
00173             return 1000;
00174         return FFMAX(left, right) + 1;
00175     }
00176     return 0;
00177 }
00178 
00179 static void print(AVTreeNode *t, int depth)
00180 {
00181     int i;
00182     for (i = 0; i < depth * 4; i++) av_log(NULL, AV_LOG_ERROR, " ");
00183     if (t) {
00184         av_log(NULL, AV_LOG_ERROR, "Node %p %2d %p\n", t, t->state, t->elem);
00185         print(t->child[0], depth + 1);
00186         print(t->child[1], depth + 1);
00187     } else
00188         av_log(NULL, AV_LOG_ERROR, "NULL\n");
00189 }
00190 
00191 static int cmp(void *a, const void *b)
00192 {
00193     return (uint8_t *) a - (const uint8_t *) b;
00194 }
00195 
00196 int main (void)
00197 {
00198     int i;
00199     void *k;
00200     AVTreeNode *root = NULL, *node = NULL;
00201     AVLFG prng;
00202 
00203     av_lfg_init(&prng, 1);
00204 
00205     for (i = 0; i < 10000; i++) {
00206         int j = av_lfg_get(&prng) % 86294;
00207         if (check(root) > 999) {
00208             av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
00209         print(root, 0);
00210             return -1;
00211         }
00212         av_log(NULL, AV_LOG_ERROR, "inserting %4d\n", j);
00213         if (!node)
00214             node = av_mallocz(av_tree_node_size);
00215         av_tree_insert(&root, (void *) (j + 1), cmp, &node);
00216 
00217         j = av_lfg_get(&prng) % 86294;
00218         {
00219             AVTreeNode *node2 = NULL;
00220             av_log(NULL, AV_LOG_ERROR, "removing %4d\n", j);
00221             av_tree_insert(&root, (void *) (j + 1), cmp, &node2);
00222             k = av_tree_find(root, (void *) (j + 1), cmp, NULL);
00223             if (k)
00224                 av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i);
00225         }
00226     }
00227     return 0;
00228 }
00229 #endif
Generated on Sun Apr 22 2012 21:54:09 for Libav by doxygen 1.7.1