00001 /*! \file array.c 00002 This file implements basic array manipulation tools. 00003 */ 00004 00005 00006 #include "array.h" 00007 #include "sort.h" 00008 00009 /*! \brief Initialize an array handler. 00010 \param array Pointer to the array handler to initialize. 00011 \param first_element pointer to the first element of the array. 00012 \param size Size of the array (that is: the maximum number of elements in the array). 00013 \param copy_data User defined function used to copy data from/to the array. 00014 Upon successful completion the function returns 0, otherwise it returns 1. 00015 See the description of <i>struct s_array</i> for a complete description. 00016 <FONT COLOR="#FF0000"><B>WARNING:</B></FONT> The function copy_data <B>MUST</B> take care off memory 00017 allocation/desallocation (if required). 00018 \param remove_data User defined function used to remove an element from the array. 00019 Upon successful completion the function returns 0, otherwise it returns 1. 00020 See the description of <i>struct s_array</i> for a complete description. 00021 <i>remove_data</i> can be a NULL pointer if no special operation is required to remove an element. 00022 \param compare User defined function used to compare two elements of the array. 00023 The function must return: 00024 <UL> 00025 <li>-1 if <i>d1 < d2</i> 00026 <li>0 if <i>d1 = d2</i> 00027 <li>+1 if <i>d1 > d2</i> 00028 <li>-2 if an error occured. 00029 </UL> 00030 See the description of <i>struct s_array</i> for a complete description. 00031 \param index User defined function that returns a pointer to the element which index is <i>idx</i>. 00032 See the description of <i>struct s_array</i> for a complete description. 00033 \param init_data User defined function used to initialize data. You can specify a NULL pointer if initialization is not required. 00034 See the description of <i>struct s_array</i> for a complete description. 00035 \return Upon successful completion the function returns 0, otherwise it returns -1. 00036 */ 00037 00038 int array_init ( 00039 Array *array, 00040 void *first_element, 00041 int size, 00042 int (*copy_data)(void *src, void *dest), 00043 int (*remove_data)(void *target), 00044 int (*compare)(void *d1, void *d2), 00045 void* (*index)(void *start, int idx), 00046 int (*init_data)(void *data) 00047 ) 00048 { 00049 array->first_element = first_element; 00050 array->array_size = size; 00051 array->number_of_elements = 0; 00052 array->copy_data = copy_data; 00053 array->remove_data = remove_data; 00054 array->compare = compare; 00055 array->index = index; 00056 array->init_data = init_data; 00057 array->element_to_remove = 0; 00058 array->to_remove = (int*)malloc(array->array_size * sizeof(int)); 00059 00060 if (array->to_remove == NULL) { return -1; } 00061 00062 return 0; 00063 } 00064 00065 /*! \example test_array.c 00066 This program shows how to use the array API 00067 */ 00068 00069 /*! \brief Free all memory allocated for the array structure. 00070 \warning This function <B>DOES NOT</B> free memory allocated for the user's data (this is the responsability of the user). 00071 */ 00072 00073 void array_free (Array *array) { free(array->to_remove); return; } 00074 00075 /*! \example test_array.c 00076 This program shows how to use the array API 00077 */ 00078 00079 /*! \brief Schedule an element of the array for removing. 00080 \param array Pointer to an array data structure. 00081 \param idx Index of the element to remove. 00082 \return Upon successful completion the function returns 0, otherwise it returns -1. 00083 */ 00084 00085 int array_schedule_for_rem (Array *array, int idx) 00086 { 00087 int i; 00088 00089 /* ------------------------------------------------- */ 00090 /* First make sure that this index is not already */ 00091 /* scheduled. */ 00092 /* ------------------------------------------------- */ 00093 00094 for (i=0; i<array->element_to_remove; i++) 00095 { if (array->to_remove[i] == idx) { return 0; } } 00096 00097 /* ------------------------------------------------- */ 00098 /* Then, make sure that we can add an element to */ 00099 /* the list of elements to remove. */ 00100 /* ------------------------------------------------- */ 00101 00102 if (array->element_to_remove >= array->array_size) { return -1; } 00103 00104 /* ------------------------------------------------- */ 00105 /* Add the index to the list of index to remove */ 00106 /* ------------------------------------------------- */ 00107 00108 array->to_remove[array->element_to_remove] = idx; 00109 00110 /* ------------------------------------------------- */ 00111 /* Increment the number of index to remove and exit */ 00112 /* ------------------------------------------------- */ 00113 00114 array->element_to_remove += 1; 00115 00116 return 0; 00117 } 00118 00119 /*! \example test_array.c 00120 This program shows how to use the array API 00121 */ 00122 00123 00124 /* ------------------------------------------------------------ */ 00125 /* Compare two integers -- Not part of public API */ 00126 /* ------------------------------------------------------------ */ 00127 00128 static int compare_int(const void *int1, const void *int2) 00129 { 00130 if (*(const int *)int1 > *(const int *)int2) { return 1; } 00131 if (*(const int *)int1 < *(const int *)int2) { return -1; } 00132 return 0; 00133 } 00134 00135 /*! \brief Remove a list of previouly scheduled element. 00136 \param array Pointer to an array data structure. 00137 \return Upon successful completion the function returns 0, otherwise it returns -1. 00138 */ 00139 00140 int array_rem_all (Array *array) 00141 { 00142 int i; 00143 00144 /* ------------------------------------------------- */ 00145 /* Is there something to remove ? */ 00146 /* ------------------------------------------------- */ 00147 00148 if (array->element_to_remove == 0) { return 0; } 00149 00150 /* ------------------------------------------------- */ 00151 /* Sort the idexes of the elements to remove */ 00152 /* ------------------------------------------------- */ 00153 00154 issort((void*)array->to_remove, array->element_to_remove, sizeof(int), compare_int); 00155 00156 /* ------------------------------------------------- */ 00157 /* Modify indexes, so we take care of the left shift */ 00158 /* ------------------------------------------------- */ 00159 00160 for (i=0; i<array->element_to_remove; i++) { array->to_remove[i] -= i; } 00161 00162 /* ------------------------------------------------- */ 00163 /* Now remove the elements */ 00164 /* ------------------------------------------------- */ 00165 00166 for (i=0; i<array->element_to_remove; i++) 00167 { if (array_rem(array, array->to_remove[i]) == -1) { return -1; } } 00168 00169 /* ------------------------------------------------- */ 00170 /* Reset the number of element to remove */ 00171 /* ------------------------------------------------- */ 00172 00173 array->element_to_remove = 0; 00174 00175 return 0; 00176 } 00177 00178 /*! \brief Initialize all elements of an array. 00179 \param array Pointer to an array data structure. 00180 \return Upon successful completion the function returns 0, otherwise it returns -1. 00181 \warning Depending on what you put in the function <i>init_data()</i>, you may call this function one or more times. 00182 */ 00183 00184 int array_init_element (Array *array) 00185 { 00186 void *location; 00187 int i; 00188 00189 for (i=0; i<array->array_size; i++) 00190 { 00191 location = array->index(array->first_element, i); 00192 if (array->init_data(location) == 1) { return -1; } 00193 } 00194 00195 return 0; 00196 } 00197 00198 /*! \example test_array.c 00199 This program shows how to use the array API 00200 */ 00201 00202 /*! \brief Add an element to the array (the element id added after the last element). 00203 \param array Pointer to the array handler to initialize. 00204 \param element Pointer to the element to add to the array. 00205 \return Upon successful completion the function returns 0, otherwise it returns -1. 00206 */ 00207 00208 int array_add ( 00209 Array *array, 00210 void *element 00211 ) 00212 { 00213 void *location; 00214 00215 /* ------------------------------------------------- */ 00216 /* First, make sure that we can add an element */ 00217 /* ------------------------------------------------- */ 00218 00219 if (array->number_of_elements >= array->array_size) { return -1; } 00220 00221 /* ------------------------------------------------- */ 00222 /* Get a pointer to the first available location */ 00223 /* (That is, the end of the array) */ 00224 /* Indexes start at 0. The index of the Nth element */ 00225 /* is N-1. */ 00226 /* ------------------------------------------------- */ 00227 00228 location = array->index(array->first_element, array->number_of_elements); 00229 00230 /* ------------------------------------------------- */ 00231 /* Copy the element to the available location */ 00232 /* ------------------------------------------------- */ 00233 00234 if (array->copy_data (element, location) == 1) { return -1; } 00235 00236 /* ------------------------------------------------- */ 00237 /* Increment the number of elements and exit */ 00238 /* ------------------------------------------------- */ 00239 00240 array->number_of_elements += 1; 00241 00242 return 0; 00243 00244 } 00245 00246 /*! \example test_array.c 00247 This program shows how to use the array API 00248 */ 00249 00250 /*! \brief Remove an element from an array. The elements next to the one removed are shifted to the left (so there is no gaps, and the 00251 elements' order does not change). 00252 \param array Pointer to the array handler to initialize. 00253 \param idx Index of the element to remove. 00254 \return Upon successful completion the function returns 0, otherwise it returns -1. 00255 */ 00256 00257 int array_rem ( 00258 Array *array, 00259 int idx 00260 ) 00261 { 00262 void *location, *src, *dst; 00263 int i; 00264 00265 /* ------------------------------------------------- */ 00266 /* First, make sure that 'idx' is not out of the */ 00267 /* array. Indexes start at 0. The index of the Nth */ 00268 /* element is N-1 */ 00269 /* ------------------------------------------------- */ 00270 00271 if (idx > array->number_of_elements-1) { return -1; } 00272 00273 /* ------------------------------------------------- */ 00274 /* Get a pointer to the location pointed by 'idx' */ 00275 /* ------------------------------------------------- */ 00276 00277 location = array->index(array->first_element, idx); 00278 00279 /* ------------------------------------------------- */ 00280 /* Remove the element and shift the next elements */ 00281 /* ------------------------------------------------- */ 00282 00283 if (array->remove_data != NULL) 00284 { if (array->remove_data(location) == 1) { return -1; } } 00285 00286 /* ------------------------------------------------- */ 00287 /* Now, the difficult part: shift all the elements */ 00288 /* ------------------------------------------------- */ 00289 00290 for (i=idx; i<array->number_of_elements-1; i++) 00291 { 00292 dst = array->index(array->first_element, i); 00293 src = array->index(array->first_element, i+1); 00294 00295 if (array->copy_data (src, dst) == 1) { return -1; } 00296 } 00297 00298 /* ------------------------------------------------- */ 00299 /* Remove the last element. Keep in mind that the */ 00300 /* function 'copy_data' doest not remove the source */ 00301 /* ------------------------------------------------- */ 00302 00303 if (array->remove_data != NULL) 00304 { 00305 location = array->index(array->first_element, array->number_of_elements-1); 00306 if (array->remove_data(location) == 1) { return -1; } 00307 } 00308 00309 /* ------------------------------------------------- */ 00310 /* Decrement the number of element in the array and */ 00311 /* exit */ 00312 /* ------------------------------------------------- */ 00313 00314 array->number_of_elements -= 1; 00315 00316 return 0; 00317 } 00318 00319 /*! \example test_array.c 00320 This program shows how to use the array API 00321 */ 00322 00323 /*! \brief Insert an element in an array. 00324 \param array Pointer to an array data structure. 00325 \param idx Index in the array where to insert the new elememt. 00326 \param data Pointer to a user defined data (that represents the content of the new element). 00327 \return Upon successful completion the function returns 0, otherwise it returns -1. 00328 */ 00329 00330 int array_insert ( 00331 Array *array, 00332 int idx, 00333 void *data 00334 ) 00335 { 00336 00337 void *src, *dst, *location; 00338 int i; 00339 00340 /* ------------------------------------------------- */ 00341 /* First, make sure that we can add an element */ 00342 /* ------------------------------------------------- */ 00343 00344 if (array->number_of_elements >= array->array_size) { return -1; } 00345 00346 /* ------------------------------------------------- */ 00347 /* The make shure that 'idx' is a valid position */ 00348 /* Note: the index of the last element is */ 00349 /* (array->number_of_elements - 1) */ 00350 /* ------------------------------------------------- */ 00351 00352 if (idx >= array->number_of_elements) { return -1; } 00353 00354 /* ------------------------------------------------- */ 00355 /* Shift all elements which index is greater that */ 00356 /* 'idx' to the right. */ 00357 /* ------------------------------------------------- */ 00358 00359 for (i=array->number_of_elements; i>idx; i--) 00360 { 00361 src = array->index(array->first_element, i-1); 00362 dst = array->index(array->first_element, i); 00363 00364 if (array->copy_data (src, dst) == 1) { return -1; } 00365 } 00366 00367 /* ------------------------------------------------- */ 00368 /* Now copy 'data' at index 'idx'. */ 00369 /* ------------------------------------------------- */ 00370 00371 location = array->index(array->first_element, idx); 00372 if (array->copy_data (data, location) == 1) { return -1; } 00373 00374 /* ------------------------------------------------- */ 00375 /* Increment the number of elements and exit */ 00376 /* ------------------------------------------------- */ 00377 00378 array->number_of_elements += 1; 00379 00380 return 0; 00381 } 00382 00383 /*! \example test_array.c 00384 This program shows how to use the array API 00385 */ 00386 00387 /*! \brief Find an given element in the array. 00388 \param array Pointer to the array data structure. 00389 \param data Pointer to the user defined element to find. 00390 \return If the element is found, then the function returns the index of the element. Otherwise the function 00391 returns -1. 00392 */ 00393 00394 int array_find ( 00395 Array *array, 00396 void *data 00397 ) 00398 { 00399 int idx; 00400 void *location; 00401 00402 for (idx=0; idx<array->number_of_elements; idx++) 00403 { 00404 location = array->index(array->first_element, idx); 00405 if (array->compare(location, data) == 0) { return idx; } 00406 } 00407 00408 return -1; 00409 } 00410 00411 /*! \example test_array.c 00412 This program shows how to use the array API 00413 */ 00414 00415