00001 /*! \file list.c 00002 This code implements linked lists. 00003 */ 00004 00005 00006 #include <stdlib.h> 00007 #include <string.h> 00008 #include "list.h" 00009 00010 /*! \brief Initialize the linked list. This function should be called first. 00011 \param liste Pointer to a linked list structure (that will be initialized). 00012 \param detruire Pointer to a function that will be called to free the memory used to store one link of the list. Please note that: 00013 <UL> 00014 <li>This function depends on the type of data stored into the linked list. 00015 <li><i>detruire</i> could be a NULL pointer (if user's data are not dtnamically allocated). 00016 </UL> 00017 \param corresp Pointer to a function that will be called to compare to elements. Please note that this function depends on the type 00018 of data stored into the linked list. The function must returns 1 if the elements' datas are identical; 0 otherwise. 00019 */ 00020 00021 void list_init(List *liste, void (*detruire)(void *donnee), int (*corresp)(const void *val1, const void *val2)) 00022 { 00023 liste->taille = 0; 00024 liste->detruire = detruire; 00025 liste->corresp = corresp; 00026 liste->tete = NULL; 00027 liste->queue = NULL; 00028 00029 return; 00030 } 00031 00032 /*! \example test_list.c 00033 This file shows how to use the function list_init(). 00034 */ 00035 00036 /*! \brief Destroy the linked list. This function free all allocated memory used by the list. 00037 \param liste Pointer to a linked list structure (that you need to destroy). 00038 */ 00039 00040 void list_destroy(List *liste) 00041 { 00042 void *donnee; 00043 00044 while (list_size(liste) > 0) 00045 { 00046 if ((list_rem_next(liste, NULL, (void **)&donnee) == 0) && (liste->detruire != NULL)) 00047 { liste->detruire(donnee); } 00048 } 00049 00050 memset(liste, 0, sizeof(List)); 00051 00052 return; 00053 } 00054 00055 /*! \example test_list.c 00056 This file shows how to use the function list_destroy(). 00057 */ 00058 00059 /*! \brief Insert a new element into the linked list. 00060 \param liste Pointer to a linked list structure. 00061 \param element Pointer to an (existing) element of the linked list. The new element will be inserted <B>AFTER</B> the element pointed 00062 by <i>element</i>. 00063 \param donnee Pointer to the data to insert. Please note that the data is <B>NOT</B> copied into the linked list. 00064 \return Upon successful completion the function return the value 0. Otherwise the function returns -1. 00065 \warning The inserted data is <B>NOT</B> copied into the linked list! Therefore you should not free it unless you know exactly what you 00066 are doing. 00067 */ 00068 00069 int list_ins_next(List *liste, ListElmt *element, const void *donnee) 00070 { 00071 ListElmt *nouv_element; 00072 00073 /* --------------------------------------------------- */ 00074 /* Allocate memory for the new element */ 00075 /* --------------------------------------------------- */ 00076 00077 if ((nouv_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) { return -1; } 00078 00079 /* --------------------------------------------------- */ 00080 /* Set new element's data */ 00081 /* --------------------------------------------------- */ 00082 00083 nouv_element->donnee = (void *)donnee; 00084 00085 if (element == NULL) 00086 { 00087 /* ------------------------------------------------- */ 00088 /* Insert to the beginning of the list */ 00089 /* - in this case there is no previous element. */ 00090 /* - the new element becomes the head of the list */ 00091 /* ------------------------------------------------- */ 00092 00093 if (list_size(liste) == 0) { liste->queue = nouv_element; } 00094 00095 nouv_element->suivant = liste->tete; 00096 00097 #ifdef DOUBLE_LINK 00098 nouv_element->precedent = NULL; 00099 #endif 00100 00101 liste->tete = nouv_element; 00102 } 00103 else 00104 { 00105 /* ------------------------------------------------- */ 00106 /* Somewhere into the list, but not the beginning */ 00107 /* ------------------------------------------------- */ 00108 00109 if (element->suivant == NULL) { liste->queue = nouv_element; } 00110 00111 nouv_element->suivant = element->suivant; 00112 00113 #ifdef DOUBLE_LINK 00114 nouv_element->precedent = element; 00115 #endif 00116 00117 element->suivant = nouv_element; 00118 } 00119 00120 /* --------------------------------------------------- */ 00121 /* increment the number of elements of the list */ 00122 /* --------------------------------------------------- */ 00123 00124 liste->taille++; 00125 00126 return 0; 00127 } 00128 00129 /*! \example test_list.c 00130 This file shows how to use the function list_ins_next(). 00131 */ 00132 00133 00134 /*! \brief Remove an element from the linked list. 00135 \param liste Pointer to a linked list structure. 00136 \param element Pointer to an (existing) element of the linked list. The element to delete is the element <B>AFTER</B> the element 00137 pointed by <i>element</i>. If you want to remove the first element of the list, then you must specify NULL as second 00138 argument for the function list_rem_next(). 00139 \param donnee Pointer that vill point to the data stored by the removed element. 00140 \return Upon successful completion the function return the value 0. Otherwise the function returns -1. 00141 \warning This function does <B>NOT</B> free the element's data (it only frees the element's structure). Therefore you should use 00142 <i>donnee</i> to free the element's data yourself. 00143 */ 00144 00145 int list_rem_next(List *liste, ListElmt *element, void **donnee) 00146 { 00147 ListElmt *ancien_element; 00148 00149 /* --------------------------------------------------- */ 00150 /* Make sure that the list is not empty */ 00151 /* --------------------------------------------------- */ 00152 00153 if (list_size(liste) == 0) { return -1; } 00154 00155 /* --------------------------------------------------- */ 00156 /* Removing the element */ 00157 /* --------------------------------------------------- */ 00158 00159 if (element == NULL) 00160 { 00161 /* ------------------------------------------------- */ 00162 /* Removing at the beginning of the list */ 00163 /* - The second element becomes the first (which */ 00164 /* has no previous element now). */ 00165 /* ------------------------------------------------- */ 00166 00167 *donnee = liste->tete->donnee; 00168 ancien_element = liste->tete; 00169 liste->tete = liste->tete->suivant; 00170 00171 if (list_size(liste) == 1) { liste->queue = NULL; } 00172 00173 #ifdef DOUBLE_LINK 00174 else { liste->tete->precedent = NULL; } 00175 #endif 00176 } 00177 else 00178 { 00179 /* ------------------------------------------------- */ 00180 /* Somewhere into the list, but not the beginning */ 00181 /* (And not at the end of the list of course). */ 00182 /* ------------------------------------------------- */ 00183 00184 if (element->suivant == NULL) { return -1; } 00185 00186 *donnee = element->suivant->donnee; 00187 ancien_element = element->suivant; 00188 element->suivant = element->suivant->suivant; 00189 00190 if (element->suivant == NULL) { liste->queue = element; } 00191 00192 #ifdef DOUBLE_LINK 00193 else { element->suivant->precedent = element; } 00194 #endif 00195 } 00196 00197 /* --------------------------------------------------- */ 00198 /* Free the allocated memory (for the element) */ 00199 /* --------------------------------------------------- */ 00200 00201 free(ancien_element); 00202 00203 /* --------------------------------------------------- */ 00204 /* Decrement the number of element of the list */ 00205 /* --------------------------------------------------- */ 00206 00207 liste->taille--; 00208 00209 return 0; 00210 } 00211 00212 /*! \example test_list.c 00213 This file shows how to use the function list_rem_next(). 00214 */ 00215 00216 00217 /*! \brief Search an element into the linked list. 00218 \param liste Pointer to the linked list structure. 00219 \param from Pointer to the linked list's element where the search begins. If 'point' in NULL, then the search begins at the beginning 00220 of the linked list. 00221 \param data Pointer to a data a user defined structure that contains the data to search for. 00222 \param prec Pointer to a pointer that will receive the address of the element before the found element. 00223 \return <UL> 00224 <li>If the function finds an element that matches <i>data</i>, then it returns a pointer to this element. In this case, 00225 <i>prec</i> points to the previous element (unless the found element was the first element in the linked list ... in this 00226 the value of <i>prec</i> is NULL). 00227 <li>If there is no element that matches <i>data</i>, then the function returns NULL. 00228 </UL> 00229 */ 00230 00231 ListElmt* list_find (List *liste, ListElmt *from, void* data, ListElmt **prec) 00232 { 00233 *prec = NULL; 00234 00235 /* --------------------------------------------------- */ 00236 /* If 'from' is NULL pointer, then start the search */ 00237 /* from the beginning of the linked list. */ 00238 /* --------------------------------------------------- */ 00239 00240 if (from == NULL) { from = list_head(liste); } 00241 00242 /* --------------------------------------------------- */ 00243 /* Compare each element with 'data' */ 00244 /* --------------------------------------------------- */ 00245 00246 while (from != NULL) 00247 { 00248 if (liste->corresp(data, list_data(from))) { return from; } 00249 *prec = from; 00250 from = list_next(from); 00251 } 00252 00253 return NULL; 00254 } 00255 00256 /*! \example test_list.c 00257 This file shows how to use the function list_find(). 00258 */ 00259 00260