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 *----------------------------------------------------------------------------
33 * Implementación de un buffer ordenado. Al obtener un dato del buffer, se
34 * obtiene de forma ordenada.
44 /** Crea un nuevo nodo, se guarda una copia del dato en el nodo. */
45 static BUFFORD_NODE* bufford_node_new(void* data, size_t reg_size);
47 /** Borra un nodo, liberando la memoria propia pero no la del dato. */
48 static void bufford_node_delete(BUFFORD_NODE* node);
50 /** Borra un nodo del buffer recursivamente, borrando sus hijos también. */
51 static void bufford_clear_node_recursive(BUFFORD_NODE* node);
53 /** Inserta un nodo en el buffer sin modificar el tamaño. */
54 static void bufford_insert_node(BUFFORD* buff, BUFFORD_NODE* new_node);
56 BUFFORD_NODE* bufford_node_new(void* data, size_t reg_size)
58 BUFFORD_NODE* n = malloc(sizeof(BUFFORD_NODE));
61 /* hago una copia del dato */
62 n->data = malloc(reg_size);
64 memcpy(n->data, data, reg_size);
74 void bufford_node_delete(BUFFORD_NODE* node)
80 void bufford_clear_node_recursive(BUFFORD_NODE* node)
84 if (node->left) bufford_clear_node_recursive(node->left);
85 if (node->right) bufford_clear_node_recursive(node->right);
87 bufford_node_delete(node);
90 void bufford_insert_node(BUFFORD* buff, BUFFORD_NODE* new_node)
94 if (buff->root) { /* no está vacío */
95 BUFFORD_NODE* curr = buff->root;
98 if (LT(buff, new_node->data, curr->data)) {
99 if (curr->left) { /* hay más, paso al próximo */
103 /* no hay más, lo inserto */
104 curr->left = new_node;
107 if (GT(buff, new_node->data, curr->data)) {
108 if (curr->right) { /* hay más, paso al próximo */
112 /* no hay más, lo inserto */
113 curr->right = new_node;
116 /* es igual! => error */
117 assert(NE(buff, new_node->data, curr->data));
122 buff->root = new_node;
125 BUFFORD* bufford_new(size_t size, size_t reg_size, CMP_FUNC cmp)
127 BUFFORD* b = malloc(sizeof(BUFFORD));
131 assert(reg_size > 0);
136 b->reg_size = reg_size;
140 BUFFORD* bufford_new_bytes_size(size_t size, size_t reg_size, CMP_FUNC cmp)
142 BUFFORD* b = malloc(sizeof(BUFFORD));
145 assert(reg_size > 0);
146 assert(size > (reg_size + sizeof(BUFFORD_NODE)));
150 b->max_size = size / (reg_size + sizeof(BUFFORD_NODE));
151 b->reg_size = reg_size;
155 void bufford_delete(BUFFORD* buff)
162 void bufford_clear(BUFFORD* buff)
165 if (buff->root) bufford_clear_node_recursive(buff->root);
169 int bufford_full(BUFFORD* buff)
172 return buff->size == buff->max_size;
175 int bufford_empty(BUFFORD* buff)
178 return buff->size == 0;
181 int bufford_push(BUFFORD* buff, void* data)
183 BUFFORD_NODE* new_node;
186 if (buff->size == buff->max_size) return 0; /* ERROR, está lleno */
187 new_node = bufford_node_new(data, buff->reg_size);
188 if (!new_node) return 0; /* ERROR, no hay memoria */
189 if (buff->root) { /* no está vacío */
190 BUFFORD_NODE* curr = buff->root;
193 if (LT(buff, data, curr->data)) {
194 if (curr->left) { /* hay más, paso al próximo */
198 /* no hay más, lo inserto */
199 curr->left = new_node;
203 if (GT(buff, data, curr->data)) {
204 if (curr->right) { /* hay más, paso al próximo */
208 /* no hay más, lo inserto */
209 curr->right = new_node;
213 /* es igual! => error */
215 assert(NE(buff, data, curr->data));
216 return 0; /* ERROR, dato duplicado */
220 buff->root = new_node;
225 void* bufford_pop_min(BUFFORD* buff)
228 BUFFORD_NODE* curr = buff->root;
229 /* nodo previo al iterador */
230 BUFFORD_NODE* prev = 0;
231 /* valor mínimo encontrado, si se encontró */
234 if (!curr) return 0; /* si no hay nodos, no hay nada que hacer */
235 /* buscamos el mínimo nodo */
240 /* lo sacamos del árbol */
241 if (prev) { /* si tiene padre (no es el raíz) */
242 /* le cuelgo de la izquierda el hijo de la derecha, sabemos que a
243 * izquierda no tiene nada.*/
244 prev->left = curr->right;
245 } else { /* si es el raíz */
246 buff->root = curr->right; /* ponemos el nuevo raíz */
248 min_found = curr->data;
249 bufford_node_delete(curr);
254 void* bufford_pop_next(BUFFORD* buff, void* min)
257 BUFFORD_NODE* curr = buff->root;
258 /* nodo previo al iterador */
259 BUFFORD_NODE* prev = 0;
260 /* nodo con el dato más pequeño encontrado hasta ahora */
261 BUFFORD_NODE* curr_min = 0;
262 /* padre del nodo con el dato más pequeño encontrado hasta ahora */
263 BUFFORD_NODE* padre = 0;
264 /* valor mínimo encontrado, si se encontró */
268 /* buscamos el mínimo nodo mayor que 'min' */
270 if (GT(buff, curr->data, min)) { /* actual mayor que buscado */
271 /* guardo y paso al de la izquierda */
276 } else { /* actual no es mayor que buscado, paso a derecha */
281 /* si encontramos uno, lo sacamos del árbol */
283 BUFFORD_NODE* link; /* nodo al cual enganchar con el padre */
284 BUFFORD_NODE* orphan = 0; /* nodo huerfano */
285 if (curr_min->left) {
286 link = curr_min->left;
287 orphan = curr_min->right;
289 link = curr_min->right;
291 if (padre) { /* si tiene padre (no es el raíz) */
292 if (padre->left == curr_min) { /* si es el de la izq */
293 padre->left = link; /* enganchamos */
294 } else { /* si no, es el de la derecha */
295 padre->right = link; /* enganchamos */
297 } else { /* si es el raíz */
298 buff->root = link; /* ponemos el nuevo raíz */
300 if (orphan) { /* si quedó un huerfano, lo insertamos */
301 bufford_insert_node(buff, orphan);
303 min_found = curr_min->data;
304 bufford_node_delete(curr_min);
310 void* bufford_get_min(BUFFORD* buff)
313 BUFFORD_NODE* curr = buff->root;
315 if (!curr) return 0; /* si no hay nodos, no hay nada que hacer */
316 /* buscamos el mínimo nodo */
317 while (curr->left) curr = curr->left;
321 void* bufford_get_next(BUFFORD* buff, void* min)
324 BUFFORD_NODE* curr = buff->root;
325 /* nodo con el dato más pequeño encontrado hasta ahora */
326 BUFFORD_NODE* curr_min = 0;
329 /* buscamos el mínimo nodo mayor que 'min' */
331 if (GT(buff, curr->data, min)) { /* actual mayor que buscado */
332 /* guardo y paso al de la izquierda */
335 } else curr = curr->right; /* paso a la derecha */
337 if (curr_min) return curr_min->data;