1 /* vim: set noexpandtab tabstop=4 shiftwidth=4 wrap:
2 *----------------------------------------------------------------------------
4 *----------------------------------------------------------------------------
5 * This file is part of emufs.
7 * emufs is free software; you can redistribute it and/or modify it under the
8 * terms of the GNU General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option) any later
12 * emufs is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along
18 * with emufs; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
20 *----------------------------------------------------------------------------
21 * Creado: mié may 26 19:46:31 ART 2004
22 * Autores: Leandro Lucarella <llucare@fi.uba.ar>
23 *----------------------------------------------------------------------------
25 * $Id: tipo1.c 548 2004-05-28 22:44:27Z llucare $
33 * Implementación de un buffer ordenado. Al obtener un dato del buffer, se
34 * obtiene de forma ordenada.
43 /** Prueba si \c x es menor que \c y usando la función de comparación. */
44 #define LT(b, x, y) (b->cmp(x, y) < 0)
45 /** Prueba si \c x es mayor que \c y usando la función de comparación. */
46 #define GT(b, x, y) (b->cmp(x, y) > 0)
47 /** Prueba si \c x es igual a \c y usando la función de comparación. */
48 #define EQ(b, x, y) (b->cmp(x, y) == 0)
49 /** Prueba si \c x es distinto a \c y usando la función de comparación. */
50 #define NE(b, x, y) (b->cmp(x, y) != 0)
51 /** Prueba si \c x es menor o igual a \c y usando la función de comparación. */
52 #define LE(b, x, y) (b->cmp(x, y) <= 0)
53 /** Prueba si \c x es mayor o igual a \c y usando la función de comparación. */
54 #define GE(b, x, y) (b->cmp(x, y) >= 0)
56 /** Crea un nuevo nodo, se guarda una copia del dato en el nodo. */
57 static BUFFORD_NODE* bufford_node_new(void* data, size_t reg_size);
59 /** Borra un nodo, liberando la memoria propia pero no la del dato. */
60 static void bufford_node_delete(BUFFORD_NODE* node);
62 /** Borra un nodo del buffer recursivamente, borrando sus hijos también. */
63 static void bufford_clear_node_recursive(BUFFORD_NODE* node);
65 /** Inserta un nodo en el buffer sin modificar el tamaño. */
66 static void bufford_insert_node(BUFFORD* buff, BUFFORD_NODE* new_node);
68 BUFFORD_NODE* bufford_node_new(void* data, size_t reg_size)
70 BUFFORD_NODE* n = malloc(sizeof(BUFFORD_NODE));
73 /* hago una copia del dato */
74 n->data = malloc(reg_size);
76 memcpy(n->data, data, reg_size);
86 void bufford_node_delete(BUFFORD_NODE* node)
92 void bufford_clear_node_recursive(BUFFORD_NODE* node)
96 if (node->left) bufford_clear_node_recursive(node->left);
97 if (node->right) bufford_clear_node_recursive(node->right);
99 bufford_node_delete(node);
102 void bufford_insert_node(BUFFORD* buff, BUFFORD_NODE* new_node)
106 if (buff->root) { /* no está vacío */
107 BUFFORD_NODE* curr = buff->root;
110 if (LT(buff, new_node->data, curr->data)) {
111 if (curr->left) { /* hay más, paso al próximo */
115 /* no hay más, lo inserto */
116 curr->left = new_node;
119 if (GT(buff, new_node->data, curr->data)) {
120 if (curr->right) { /* hay más, paso al próximo */
124 /* no hay más, lo inserto */
125 curr->right = new_node;
128 /* es igual! => error */
129 assert(NE(buff, new_node->data, curr->data));
134 buff->root = new_node;
137 BUFFORD* bufford_new(size_t size, size_t reg_size, CMP_FUNC cmp)
139 BUFFORD* b = malloc(sizeof(BUFFORD));
142 assert(reg_size > 0);
143 assert(size > reg_size);
147 b->max_size = size / reg_size;
148 b->reg_size = reg_size;
152 void bufford_delete(BUFFORD* buff)
159 void bufford_clear(BUFFORD* buff)
162 if (buff->root) bufford_clear_node_recursive(buff->root);
166 int bufford_full(BUFFORD* buff)
169 return buff->size == buff->max_size;
172 int bufford_empty(BUFFORD* buff)
175 return buff->size == 0;
178 int bufford_push(BUFFORD* buff, void* data)
180 BUFFORD_NODE* new_node;
183 if (buff->size == buff->max_size) return 0; /* ERROR, está lleno */
184 new_node = bufford_node_new(data, buff->reg_size);
185 if (!new_node) return 0; /* ERROR, no hay memoria */
186 if (buff->root) { /* no está vacío */
187 BUFFORD_NODE* curr = buff->root;
190 if (LT(buff, data, curr->data)) {
191 if (curr->left) { /* hay más, paso al próximo */
195 /* no hay más, lo inserto */
196 curr->left = new_node;
200 if (GT(buff, data, curr->data)) {
201 if (curr->right) { /* hay más, paso al próximo */
205 /* no hay más, lo inserto */
206 curr->right = new_node;
210 /* es igual! => error */
212 assert(NE(buff, data, curr->data));
213 return 0; /* ERROR, dato duplicado */
217 buff->root = new_node;
222 void* bufford_pop_min(BUFFORD* buff)
225 BUFFORD_NODE* curr = buff->root;
226 /* nodo previo al iterador */
227 BUFFORD_NODE* prev = 0;
228 /* valor mínimo encontrado, si se encontró */
231 if (!curr) return 0; /* si no hay nodos, no hay nada que hacer */
232 /* buscamos el mínimo nodo */
237 /* lo sacamos del árbol */
238 if (prev) { /* si tiene padre (no es el raíz) */
239 /* le cuelgo de la izquierda el hijo de la derecha, sabemos que a
240 * izquierda no tiene nada.*/
241 prev->left = curr->right;
242 } else { /* si es el raíz */
243 buff->root = curr->right; /* ponemos el nuevo raíz */
245 min_found = curr->data;
246 bufford_node_delete(curr);
251 void* bufford_pop_next(BUFFORD* buff, void* min)
254 BUFFORD_NODE* curr = buff->root;
255 /* nodo previo al iterador */
256 BUFFORD_NODE* prev = 0;
257 /* nodo con el dato más pequeño encontrado hasta ahora */
258 BUFFORD_NODE* curr_min = 0;
259 /* padre del nodo con el dato más pequeño encontrado hasta ahora */
260 BUFFORD_NODE* padre = 0;
261 /* valor mínimo encontrado, si se encontró */
265 /* buscamos el mínimo nodo mayor que 'min' */
267 if (GT(buff, curr->data, min)) { /* actual mayor que buscado */
268 /* guardo y paso al de la izquierda */
273 } else { /* actual no es mayor que buscado, paso a derecha */
278 /* si encontramos uno, lo sacamos del árbol */
280 BUFFORD_NODE* link; /* nodo al cual enganchar con el padre */
281 BUFFORD_NODE* orphan = 0; /* nodo huerfano */
282 if (curr_min->left) {
283 link = curr_min->left;
284 orphan = curr_min->right;
286 link = curr_min->right;
288 if (padre) { /* si tiene padre (no es el raíz) */
289 if (padre->left == curr_min) { /* si es el de la izq */
290 padre->left = link; /* enganchamos */
291 } else { /* si no, es el de la derecha */
292 padre->right = link; /* enganchamos */
294 } else { /* si es el raíz */
295 buff->root = link; /* ponemos el nuevo raíz */
297 if (orphan) { /* si quedó un huerfano, lo insertamos */
298 bufford_insert_node(buff, orphan);
300 min_found = curr_min->data;
301 bufford_node_delete(curr_min);
307 void* bufford_get_min(BUFFORD* buff)
310 BUFFORD_NODE* curr = buff->root;
312 if (!curr) return 0; /* si no hay nodos, no hay nada que hacer */
313 /* buscamos el mínimo nodo */
314 while (curr->left) curr = curr->left;
318 void* bufford_get_next(BUFFORD* buff, void* min)
321 BUFFORD_NODE* curr = buff->root;
322 /* nodo con el dato más pequeño encontrado hasta ahora */
323 BUFFORD_NODE* curr_min = 0;
326 /* buscamos el mínimo nodo mayor que 'min' */
328 if (GT(buff, curr->data, min)) { /* actual mayor que buscado */
329 /* guardo y paso al de la izquierda */
332 } else curr = curr->right; /* paso a la derecha */
334 if (curr_min) return curr_min->data;