annotate tree.c @ 510:b7593ce78422 libavutil

Make av_fifo*_read() ignore the available amount of data. This is more efficient as in practice the check is redundant most of the time. Callers which do not know if enough data is available have to check it with av_fifo_size(). Doing the check in *read() means the caller has no choice to skip the check when its known to be redundant. Also the return value was never documented in a public header so changing it should not break the API. Besides this fixes the case where read() failed on a 100% full fifo.
author michael
date Sun, 25 May 2008 22:20:39 +0000
parents 0839746f3fcf
children 5877edf05eb7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
1 /*
4ae092965c27 AVL tree
michael
parents:
diff changeset
2 * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
4ae092965c27 AVL tree
michael
parents:
diff changeset
3 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
4 * This file is part of FFmpeg.
4ae092965c27 AVL tree
michael
parents:
diff changeset
5 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
6 * FFmpeg is free software; you can redistribute it and/or
4ae092965c27 AVL tree
michael
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
4ae092965c27 AVL tree
michael
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
4ae092965c27 AVL tree
michael
parents:
diff changeset
9 * version 2.1 of the License, or (at your option) any later version.
4ae092965c27 AVL tree
michael
parents:
diff changeset
10 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
11 * FFmpeg is distributed in the hope that it will be useful,
4ae092965c27 AVL tree
michael
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
4ae092965c27 AVL tree
michael
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4ae092965c27 AVL tree
michael
parents:
diff changeset
14 * Lesser General Public License for more details.
4ae092965c27 AVL tree
michael
parents:
diff changeset
15 *
4ae092965c27 AVL tree
michael
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
4ae092965c27 AVL tree
michael
parents:
diff changeset
17 * License along with FFmpeg; if not, write to the Free Software
4ae092965c27 AVL tree
michael
parents:
diff changeset
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4ae092965c27 AVL tree
michael
parents:
diff changeset
19 */
4ae092965c27 AVL tree
michael
parents:
diff changeset
20
4ae092965c27 AVL tree
michael
parents:
diff changeset
21 #include "common.h"
4ae092965c27 AVL tree
michael
parents:
diff changeset
22 #include "log.h"
4ae092965c27 AVL tree
michael
parents:
diff changeset
23 #include "tree.h"
4ae092965c27 AVL tree
michael
parents:
diff changeset
24
4ae092965c27 AVL tree
michael
parents:
diff changeset
25 typedef struct AVTreeNode{
4ae092965c27 AVL tree
michael
parents:
diff changeset
26 struct AVTreeNode *child[2];
4ae092965c27 AVL tree
michael
parents:
diff changeset
27 void *elem;
4ae092965c27 AVL tree
michael
parents:
diff changeset
28 int state;
4ae092965c27 AVL tree
michael
parents:
diff changeset
29 }AVTreeNode;
4ae092965c27 AVL tree
michael
parents:
diff changeset
30
413
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
31 const int av_tree_node_size = sizeof(AVTreeNode);
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
32
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
33 void *av_tree_find(const AVTreeNode *t, void *key, int (*cmp)(void *key, const void *b), void *next[2]){
4ae092965c27 AVL tree
michael
parents:
diff changeset
34 if(t){
418
9f2461caf179 Flip key and element so types match, not that it matters for any code
michael
parents: 415
diff changeset
35 unsigned int v= cmp(key, t->elem);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
36 if(v){
418
9f2461caf179 Flip key and element so types match, not that it matters for any code
michael
parents: 415
diff changeset
37 if(next) next[v>>31]= t->elem;
9f2461caf179 Flip key and element so types match, not that it matters for any code
michael
parents: 415
diff changeset
38 return av_tree_find(t->child[(v>>31)^1], key, cmp, next);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
39 }else{
412
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
40 if(next){
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
41 av_tree_find(t->child[0], key, cmp, next);
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
42 av_tree_find(t->child[1], key, cmp, next);
357ac44f4720 Always set next correctly, even if a matching element is found (that is
michael
parents: 404
diff changeset
43 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
44 return t->elem;
4ae092965c27 AVL tree
michael
parents:
diff changeset
45 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
46 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
47 return NULL;
4ae092965c27 AVL tree
michael
parents:
diff changeset
48 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
49
413
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
50 void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const void *b), AVTreeNode **next){
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
51 AVTreeNode *t= *tp;
4ae092965c27 AVL tree
michael
parents:
diff changeset
52 if(t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
53 unsigned int v= cmp(t->elem, key);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
54 void *ret;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
55 if(!v){
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
56 if(*next)
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
57 return t->elem;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
58 else if(t->child[0]||t->child[1]){
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
59 int i= !t->child[0];
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
60 void *next_elem[2];
429
3be382cb92ba simplify
michael
parents: 425
diff changeset
61 av_tree_find(t->child[i], key, cmp, next_elem);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
62 key= t->elem= next_elem[i];
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
63 v= -i;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
64 }else{
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
65 *next= t;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
66 *tp=NULL;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
67 return NULL;
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
68 }
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
69 }
419
michael
parents: 418
diff changeset
70 ret= av_tree_insert(&t->child[v>>31], key, cmp, next);
michael
parents: 418
diff changeset
71 if(!ret){
michael
parents: 418
diff changeset
72 int i= (v>>31) ^ !!*next;
michael
parents: 418
diff changeset
73 AVTreeNode **child= &t->child[i];
michael
parents: 418
diff changeset
74 t->state += 2*i - 1;
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
75
419
michael
parents: 418
diff changeset
76 if(!(t->state&1)){
michael
parents: 418
diff changeset
77 if(t->state){
433
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
78 /* The following code is equivalent to
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
79 if((*child)->state*2 == -t->state)
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
80 rotate(child, i^1);
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
81 rotate(tp, i);
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
82
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
83 with rotate():
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
84 static void rotate(AVTreeNode **tp, int i){
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
85 AVTreeNode *t= *tp;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
86
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
87 *tp= t->child[i];
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
88 t->child[i]= t->child[i]->child[i^1];
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
89 (*tp)->child[i^1]= t;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
90 i= 4*t->state + 2*(*tp)->state + 12;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
91 t ->state= ((0x614586 >> i) & 3)-1;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
92 (*tp)->state= ((*tp)->state>>1) + ((0x400EEA >> i) & 3)-1;
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
93 }
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
94 but such a rotate function is both bigger and slower
0839746f3fcf Comment to explain how the add/remove core works.
michael
parents: 430
diff changeset
95 */
419
michael
parents: 418
diff changeset
96 if((*child)->state*2 == -t->state){
michael
parents: 418
diff changeset
97 *tp= (*child)->child[i^1];
michael
parents: 418
diff changeset
98 (*child)->child[i^1]= (*tp)->child[i];
michael
parents: 418
diff changeset
99 (*tp)->child[i]= *child;
michael
parents: 418
diff changeset
100 *child= (*tp)->child[i^1];
michael
parents: 418
diff changeset
101 (*tp)->child[i^1]= t;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
102
419
michael
parents: 418
diff changeset
103 (*tp)->child[0]->state= -((*tp)->state>0);
michael
parents: 418
diff changeset
104 (*tp)->child[1]->state= (*tp)->state<0 ;
michael
parents: 418
diff changeset
105 (*tp)->state=0;
michael
parents: 418
diff changeset
106 }else{
michael
parents: 418
diff changeset
107 *tp= *child;
michael
parents: 418
diff changeset
108 *child= (*child)->child[i^1];
michael
parents: 418
diff changeset
109 (*tp)->child[i^1]= t;
michael
parents: 418
diff changeset
110 if((*tp)->state) t->state = 0;
michael
parents: 418
diff changeset
111 else t->state>>= 1;
michael
parents: 418
diff changeset
112 (*tp)->state= -t->state;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
113 }
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
114 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
115 }
419
michael
parents: 418
diff changeset
116 if(!(*tp)->state ^ !!*next)
michael
parents: 418
diff changeset
117 return key;
michael
parents: 418
diff changeset
118 }
michael
parents: 418
diff changeset
119 return ret;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
120 }else{
413
a54e20281de9 Move *malloc() out of tree.c, that way the code can be used with
michael
parents: 412
diff changeset
121 *tp= *next; *next= NULL;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
122 (*tp)->elem= key;
4ae092965c27 AVL tree
michael
parents:
diff changeset
123 return NULL;
4ae092965c27 AVL tree
michael
parents:
diff changeset
124 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
125 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
126
4ae092965c27 AVL tree
michael
parents:
diff changeset
127 void av_tree_destroy(AVTreeNode *t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
128 av_tree_destroy(t->child[0]);
4ae092965c27 AVL tree
michael
parents:
diff changeset
129 av_tree_destroy(t->child[1]);
4ae092965c27 AVL tree
michael
parents:
diff changeset
130 av_free(t);
4ae092965c27 AVL tree
michael
parents:
diff changeset
131 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
132
4ae092965c27 AVL tree
michael
parents:
diff changeset
133 #if 0
4ae092965c27 AVL tree
michael
parents:
diff changeset
134 void av_tree_enumerate(AVTreeNode *t, void *opaque, int (*f)(void *opaque, void *elem)){
137
dbcf66639764 improve enumerate so arbitrary ranges can be enumerated quickly
michael
parents: 136
diff changeset
135 int v= f(opaque, t->elem);
dbcf66639764 improve enumerate so arbitrary ranges can be enumerated quickly
michael
parents: 136
diff changeset
136 if(v>=0) av_tree_enumerate(t->child[0], opaque, f);
dbcf66639764 improve enumerate so arbitrary ranges can be enumerated quickly
michael
parents: 136
diff changeset
137 if(v<=0) av_tree_enumerate(t->child[1], opaque, f);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
138 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
139 #endif
4ae092965c27 AVL tree
michael
parents:
diff changeset
140
4ae092965c27 AVL tree
michael
parents:
diff changeset
141 #ifdef TEST
415
1f1ebfcfa9cd Fix selftest.
michael
parents: 414
diff changeset
142 #undef random
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
143 static int check(AVTreeNode *t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
144 if(t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
145 int left= check(t->child[0]);
4ae092965c27 AVL tree
michael
parents:
diff changeset
146 int right= check(t->child[1]);
4ae092965c27 AVL tree
michael
parents:
diff changeset
147
4ae092965c27 AVL tree
michael
parents:
diff changeset
148 if(left>999 || right>999)
4ae092965c27 AVL tree
michael
parents:
diff changeset
149 return 1000;
4ae092965c27 AVL tree
michael
parents:
diff changeset
150 if(right - left != t->state)
4ae092965c27 AVL tree
michael
parents:
diff changeset
151 return 1000;
4ae092965c27 AVL tree
michael
parents:
diff changeset
152 if(t->state>1 || t->state<-1)
4ae092965c27 AVL tree
michael
parents:
diff changeset
153 return 1000;
4ae092965c27 AVL tree
michael
parents:
diff changeset
154 return FFMAX(left, right)+1;
4ae092965c27 AVL tree
michael
parents:
diff changeset
155 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
156 return 0;
4ae092965c27 AVL tree
michael
parents:
diff changeset
157 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
158
4ae092965c27 AVL tree
michael
parents:
diff changeset
159 static void print(AVTreeNode *t, int depth){
4ae092965c27 AVL tree
michael
parents:
diff changeset
160 int i;
4ae092965c27 AVL tree
michael
parents:
diff changeset
161 for(i=0; i<depth*4; i++) av_log(NULL, AV_LOG_ERROR, " ");
4ae092965c27 AVL tree
michael
parents:
diff changeset
162 if(t){
4ae092965c27 AVL tree
michael
parents:
diff changeset
163 av_log(NULL, AV_LOG_ERROR, "Node %p %2d %4d\n", t, t->state, t->elem);
4ae092965c27 AVL tree
michael
parents:
diff changeset
164 print(t->child[0], depth+1);
4ae092965c27 AVL tree
michael
parents:
diff changeset
165 print(t->child[1], depth+1);
4ae092965c27 AVL tree
michael
parents:
diff changeset
166 }else
4ae092965c27 AVL tree
michael
parents:
diff changeset
167 av_log(NULL, AV_LOG_ERROR, "NULL\n");
4ae092965c27 AVL tree
michael
parents:
diff changeset
168 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
169
4ae092965c27 AVL tree
michael
parents:
diff changeset
170 int cmp(const void *a, const void *b){
4ae092965c27 AVL tree
michael
parents:
diff changeset
171 return a-b;
4ae092965c27 AVL tree
michael
parents:
diff changeset
172 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
173
404
f9a4c04ebb0e main() --> main(void)
diego
parents: 141
diff changeset
174 int main(void){
425
344948d71978 Remove unused variable j.
diego
parents: 419
diff changeset
175 int i,k;
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
176 AVTreeNode *root= NULL, *node=NULL;
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
177
4ae092965c27 AVL tree
michael
parents:
diff changeset
178 for(i=0; i<10000; i++){
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
179 int j= (random()%86294);
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
180 if(check(root) > 999){
4ae092965c27 AVL tree
michael
parents:
diff changeset
181 av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
4ae092965c27 AVL tree
michael
parents:
diff changeset
182 print(root, 0);
4ae092965c27 AVL tree
michael
parents:
diff changeset
183 return -1;
4ae092965c27 AVL tree
michael
parents:
diff changeset
184 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
185 av_log(NULL, AV_LOG_ERROR, "inserting %4d\n", j);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
186 if(!node)
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
187 node= av_mallocz(av_tree_node_size);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
188 av_tree_insert(&root, (void*)(j+1), cmp, &node);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
189
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
190 j= (random()%86294);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
191 k= av_tree_find(root, (void*)(j+1), cmp, NULL);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
192 if(k){
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
193 AVTreeNode *node2=NULL;
430
42011b593830 Print removing of nodes in the test code.
michael
parents: 429
diff changeset
194 av_log(NULL, AV_LOG_ERROR, "removing %4d\n", j);
414
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
195 av_tree_insert(&root, (void*)(j+1), cmp, &node2);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
196 k= av_tree_find(root, (void*)(j+1), cmp, NULL);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
197 if(k)
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
198 av_log(NULL, AV_LOG_ERROR, "removial failure %d\n", i);
a30cad55db8b Support removing elements.
michael
parents: 413
diff changeset
199 }
136
4ae092965c27 AVL tree
michael
parents:
diff changeset
200 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
201 return 0;
4ae092965c27 AVL tree
michael
parents:
diff changeset
202 }
4ae092965c27 AVL tree
michael
parents:
diff changeset
203 #endif