00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* Handling of arrays that can grow dynamicly. */ 00018 00019 #if defined(WIN32) || defined(__WIN__) 00020 #undef SAFEMALLOC /* Problems with threads */ 00021 #endif 00022 00023 #include "mysys_priv.h" 00024 #include "m_string.h" 00025 00026 /* 00027 Initiate dynamic array 00028 00029 SYNOPSIS 00030 init_dynamic_array() 00031 array Pointer to an array 00032 element_size Size of element 00033 init_alloc Number of initial elements 00034 alloc_increment Increment for adding new elements 00035 00036 DESCRIPTION 00037 init_dynamic_array() initiates array and allocate space for 00038 init_alloc eilements. 00039 Array is usable even if space allocation failed. 00040 00041 RETURN VALUE 00042 TRUE my_malloc_ci() failed 00043 FALSE Ok 00044 */ 00045 00046 my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, 00047 uint init_alloc, 00048 uint alloc_increment CALLER_INFO_PROTO) 00049 { 00050 DBUG_ENTER("init_dynamic_array"); 00051 if (!alloc_increment) 00052 { 00053 alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16); 00054 if (init_alloc > 8 && alloc_increment > init_alloc * 2) 00055 alloc_increment=init_alloc*2; 00056 } 00057 00058 if (!init_alloc) 00059 init_alloc=alloc_increment; 00060 array->elements=0; 00061 array->max_element=init_alloc; 00062 array->alloc_increment=alloc_increment; 00063 array->size_of_element=element_size; 00064 if (!(array->buffer=(char*) my_malloc_ci(element_size*init_alloc,MYF(MY_WME)))) 00065 { 00066 array->max_element=0; 00067 DBUG_RETURN(TRUE); 00068 } 00069 DBUG_RETURN(FALSE); 00070 } 00071 00072 /* 00073 Insert element at the end of array. Allocate memory if needed. 00074 00075 SYNOPSIS 00076 insert_dynamic() 00077 array 00078 element 00079 00080 RETURN VALUE 00081 TRUE Insert failed 00082 FALSE Ok 00083 */ 00084 00085 my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element) 00086 { 00087 gptr buffer; 00088 if (array->elements == array->max_element) 00089 { /* Call only when nessesary */ 00090 if (!(buffer=alloc_dynamic(array))) 00091 return TRUE; 00092 } 00093 else 00094 { 00095 buffer=array->buffer+(array->elements * array->size_of_element); 00096 array->elements++; 00097 } 00098 memcpy(buffer,element,(size_t) array->size_of_element); 00099 return FALSE; 00100 } 00101 00102 00103 /* 00104 Alloc space for next element(s) 00105 00106 SYNOPSIS 00107 alloc_dynamic() 00108 array 00109 00110 DESCRIPTION 00111 alloc_dynamic() checks if there is empty space for at least 00112 one element if not tries to allocate space for alloc_increment 00113 elements at the end of array. 00114 00115 RETURN VALUE 00116 pointer Pointer to empty space for element 00117 0 Error 00118 */ 00119 00120 byte *alloc_dynamic(DYNAMIC_ARRAY *array) 00121 { 00122 if (array->elements == array->max_element) 00123 { 00124 char *new_ptr; 00125 if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+ 00126 array->alloc_increment)* 00127 array->size_of_element, 00128 MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) 00129 return 0; 00130 array->buffer=new_ptr; 00131 array->max_element+=array->alloc_increment; 00132 } 00133 return array->buffer+(array->elements++ * array->size_of_element); 00134 } 00135 00136 00137 /* 00138 Pop last element from array. 00139 00140 SYNOPSIS 00141 pop_dynamic() 00142 array 00143 00144 RETURN VALUE 00145 pointer Ok 00146 0 Array is empty 00147 */ 00148 00149 byte *pop_dynamic(DYNAMIC_ARRAY *array) 00150 { 00151 if (array->elements) 00152 return array->buffer+(--array->elements * array->size_of_element); 00153 return 0; 00154 } 00155 00156 /* 00157 Replace elemnent in array with given element and index 00158 00159 SYNOPSIS 00160 set_dynamic() 00161 array 00162 element Element to be inserted 00163 idx Index where element is to be inserted 00164 00165 DESCRIPTION 00166 set_dynamic() replaces element in array. 00167 If idx > max_element insert new element. Allocate memory if needed. 00168 00169 RETURN VALUE 00170 TRUE Idx was out of range and allocation of new memory failed 00171 FALSE Ok 00172 */ 00173 00174 my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) 00175 { 00176 if (idx >= array->elements) 00177 { 00178 if (idx >= array->max_element) 00179 { 00180 uint size; 00181 char *new_ptr; 00182 size=(idx+array->alloc_increment)/array->alloc_increment; 00183 size*= array->alloc_increment; 00184 if (!(new_ptr=(char*) my_realloc(array->buffer,size* 00185 array->size_of_element, 00186 MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) 00187 return TRUE; 00188 array->buffer=new_ptr; 00189 array->max_element=size; 00190 } 00191 bzero((gptr) (array->buffer+array->elements*array->size_of_element), 00192 (idx - array->elements)*array->size_of_element); 00193 array->elements=idx+1; 00194 } 00195 memcpy(array->buffer+(idx * array->size_of_element),element, 00196 (size_t) array->size_of_element); 00197 return FALSE; 00198 } 00199 00200 /* 00201 Get an element from array by given index 00202 00203 SYNOPSIS 00204 get_dynamic() 00205 array 00206 gptr Element to be returned. If idx > elements contain zeroes. 00207 idx Index of element wanted. 00208 */ 00209 00210 void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) 00211 { 00212 if (idx >= array->elements) 00213 { 00214 DBUG_PRINT("warning",("To big array idx: %d, array size is %d", 00215 idx,array->elements)); 00216 bzero(element,array->size_of_element); 00217 return; 00218 } 00219 memcpy(element,array->buffer+idx*array->size_of_element, 00220 (size_t) array->size_of_element); 00221 } 00222 00223 00224 /* 00225 Empty array by freeing all memory 00226 00227 SYNOPSIS 00228 delete_dynamic() 00229 array Array to be deleted 00230 */ 00231 00232 void delete_dynamic(DYNAMIC_ARRAY *array) 00233 { 00234 if (array->buffer) 00235 { 00236 my_free(array->buffer,MYF(MY_WME)); 00237 array->buffer=0; 00238 array->elements=array->max_element=0; 00239 } 00240 } 00241 00242 /* 00243 Delete element by given index 00244 00245 SYNOPSIS 00246 delete_dynamic_element() 00247 array 00248 idx Index of element to be deleted 00249 */ 00250 00251 void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) 00252 { 00253 char *ptr=array->buffer+array->size_of_element*idx; 00254 array->elements--; 00255 memmove(ptr,ptr+array->size_of_element, 00256 (array->elements-idx)*array->size_of_element); 00257 } 00258 00259 00260 /* 00261 Free unused memory 00262 00263 SYNOPSIS 00264 freeze_size() 00265 array Array to be freed 00266 00267 */ 00268 00269 void freeze_size(DYNAMIC_ARRAY *array) 00270 { 00271 uint elements=max(array->elements,1); 00272 00273 if (array->buffer && array->max_element != elements) 00274 { 00275 array->buffer=(char*) my_realloc(array->buffer, 00276 elements*array->size_of_element, 00277 MYF(MY_WME)); 00278 array->max_element=elements; 00279 } 00280 } 00281 00282 00283 /* 00284 Get the index of a dynamic element 00285 00286 SYNOPSIS 00287 get_index_dynamic() 00288 array Array 00289 element Whose element index 00290 00291 */ 00292 00293 int get_index_dynamic(DYNAMIC_ARRAY *array, gptr element) 00294 { 00295 uint ret; 00296 if (array->buffer > element) 00297 return -1; 00298 00299 ret= (element - array->buffer) / array->size_of_element; 00300 if (ret > array->elements) 00301 return -1; 00302 00303 return ret; 00304 00305 }
1.4.7

