/***************************************************************************** * Copyright (c) 2005 Daniel Lerch Hostalot * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "list.h" #include /* ------------------------------------------------------------------------- */ void* list_new () { list_t* obj; obj = malloc(sizeof(list_t)); if(!obj) { perror("list_new()"); exit(EXIT_FAILURE); } obj->head = NULL; obj->tail = NULL; obj->iterator = obj->head; obj->size = 0; obj->cmpfunc = NULL; return obj; } /* ------------------------------------------------------------------------- */ void list_free (list_t* obj, void (*freefunc)(void*)) { void* elm; if (obj->size>0) { list_begin(obj); while (list_next(obj)) { elm = list_remove_first(obj); if (freefunc) freefunc(elm); } } free(obj); } /* ------------------------------------------------------------------------- */ void list_add (list_t* obj, void* element, unsigned int index) { int i; list_node_t *node_ptr; list_node_t *node_before; list_node_t *node_after; list_node_t* new_node = malloc(sizeof(list_node_t)); if(!new_node) { perror("list_add()"); exit(EXIT_FAILURE); } new_node->element = element; new_node->next = NULL; if (index > obj->size) { fprintf(stderr, "list_add(): ERROR indice fuera de los limites.\n"); exit(EXIT_FAILURE); } obj->size++; if (!((obj->tail)&&(obj->head))) { obj->tail = new_node; obj->head = new_node; return; } i=0; for (node_ptr=obj->head; node_ptr; node_ptr=node_ptr->next) { if (i==index) { if (i==0) { node_after = obj->head; obj->head = new_node; obj->head->next = node_after; break; } else if (i==obj->size) { node_before = node_ptr; node_before->next = new_node; new_node->next = NULL; obj->tail = new_node; break; } } else if (i+1==index) { node_before = node_ptr; node_after = node_ptr->next; node_before->next = new_node; new_node->next = node_after; break; } i++; } } /* ------------------------------------------------------------------------- */ void list_add_first (list_t* obj, void* element) { list_add (obj, element, 0); } /* ------------------------------------------------------------------------- */ void list_add_last (list_t* obj, void* element) { list_add (obj, element, obj->size); } /* ------------------------------------------------------------------------- */ int list_contains (list_t* obj, void *element) { list_node_t* node_ptr; for (node_ptr=obj->head; node_ptr; node_ptr=node_ptr->next) { if (obj->cmpfunc) { if (obj->cmpfunc(element, node_ptr->element)==0) return 1; } else if (element==node_ptr->element) return 1; } return 0; } /* ------------------------------------------------------------------------- */ void* list_get (list_t* obj, unsigned int index) { int i; list_node_t *node_ptr; if (index > obj->size) { fprintf(stderr, "list_get(): ERROR indice fuera de los limites.\n"); exit(EXIT_FAILURE); } i=0; for (node_ptr=obj->head; node_ptr; node_ptr=node_ptr->next) { if (i==index) return node_ptr->element; i++; } /* No deberia llegar aqui */ return NULL; } /* ------------------------------------------------------------------------- */ void* list_get_first (list_t* obj) { return list_get (obj, 0); } /* ------------------------------------------------------------------------- */ void* list_get_last (list_t* obj) { if (obj->size>0) return list_get (obj, obj->size-1); else return NULL; } /* ------------------------------------------------------------------------- */ int list_index_of (list_t* obj, void* element) { int i=0; list_node_t* node_ptr; for (node_ptr=obj->head; node_ptr; node_ptr=node_ptr->next) if (element==node_ptr->element) return i; else i++; return -1; } /* ------------------------------------------------------------------------- */ void* list_remove (list_t* obj, unsigned int index) { int i; list_node_t *node_ptr; list_node_t *node_before; void* element_ptr; if (index > obj->size) { fprintf(stderr, "list_remove(): ERROR indice fuera de los limites.\n"); exit(EXIT_FAILURE); } i=0; node_before=obj->head; for (node_ptr=obj->head; node_ptr; node_ptr=node_ptr->next) { if (i==index) { if (i==0) obj->head=node_ptr->next; if (i==obj->size-1) obj->tail=node_before; else node_before->next=node_ptr->next; element_ptr = node_ptr->element; free(node_ptr); obj->size--; return element_ptr; } i++; node_before=node_ptr; } return NULL; } /* ------------------------------------------------------------------------- */ void* list_remove_first (list_t* obj) { return list_remove (obj, 0); } /* ------------------------------------------------------------------------- */ void* list_remove_last (list_t* obj) { if (obj->size>0) return list_remove (obj, obj->size-1); else return NULL; } /* ------------------------------------------------------------------------- */ void* list_set (list_t* obj, void* element, unsigned int index) { list_node_t* node_ptr; void* old_element; int i=0; for (node_ptr=obj->head; node_ptr; node_ptr=node_ptr->next) if (i++ == index) break; old_element = node_ptr->element; node_ptr->element = element; return old_element; } /* ------------------------------------------------------------------------- */ int list_size (list_t* obj) { return obj->size; } /* ------------------------------------------------------------------------- */ void list_begin (list_t* obj) { obj->iterator = obj->head; } /* ------------------------------------------------------------------------- */ void *list_next (list_t* obj) { void *element; if (!obj->iterator) return NULL; element = obj->iterator->element; obj->iterator = obj->iterator->next; return element; } /* ------------------------------------------------------------------------- */ void list_sort (list_t* obj, int desc) { int i,j, cmp; void* tmp; if (!obj->cmpfunc) { fprintf(stderr, "list_sort(): ERROR no se ha establecido cmpfunc()\n"); exit(0); } /* Ordenacion del list poco eficiente: O(n^2)*/ for (i=0;isize;i++) { for (j=0;jsize;j++) { cmp = obj->cmpfunc(list_get(obj, i), list_get(obj, j)); if ((cmp<0)&&(!desc)) cmp=1; else if ((cmp>0)&&(!desc)) cmp=-1; if (cmp>0) { tmp = list_get (obj, i); list_set (obj, list_set (obj, tmp, j), i); } } } } /* ------------------------------------------------------------------------- */ void list_set_cmpfunc (list_t* obj, int (*cmpfunc)(void*, void*)) { obj->cmpfunc=cmpfunc; }