diff options
Diffstat (limited to 'mysys/array.c')
-rw-r--r-- | mysys/array.c | 192 |
1 files changed, 151 insertions, 41 deletions
diff --git a/mysys/array.c b/mysys/array.c index f1303f705ba..db219eb2430 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2002, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2002, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Handling of arrays that can grow dynamicly. */ @@ -23,9 +25,10 @@ Initiate dynamic array SYNOPSIS - init_dynamic_array() + init_dynamic_array2() array Pointer to an array element_size Size of element + init_buffer Initial buffer pointer init_alloc Number of initial elements alloc_increment Increment for adding new elements @@ -34,14 +37,15 @@ init_alloc eilements. Array is usable even if space allocation failed, hence, the function never returns TRUE. + Static buffers must begin immediately after the array structure. RETURN VALUE FALSE Ok */ -my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, - uint init_alloc, - uint alloc_increment CALLER_INFO_PROTO) +my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, + void *init_buffer, uint init_alloc, + uint alloc_increment CALLER_INFO_PROTO) { DBUG_ENTER("init_dynamic_array"); if (!alloc_increment) @@ -52,20 +56,33 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, } if (!init_alloc) + { init_alloc=alloc_increment; + init_buffer= 0; + } array->elements=0; array->max_element=init_alloc; array->alloc_increment=alloc_increment; array->size_of_element=element_size; + if ((array->buffer= init_buffer)) + DBUG_RETURN(FALSE); /* Since the dynamic array is usable even if allocation fails here malloc should not throw an error */ - if (!(array->buffer= (char*) my_malloc_ci(element_size*init_alloc, MYF(0)))) + if (!(array->buffer= (uchar*) my_malloc_ci(element_size*init_alloc, MYF(0)))) array->max_element=0; DBUG_RETURN(FALSE); } +my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, + uint init_alloc, + uint alloc_increment CALLER_INFO_PROTO) +{ + /* placeholder to preserve ABI */ + return my_init_dynamic_array_ci(array, element_size, init_alloc, + alloc_increment); +} /* Insert element at the end of array. Allocate memory if needed. @@ -79,9 +96,9 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, FALSE Ok */ -my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element) +my_bool insert_dynamic(DYNAMIC_ARRAY *array, uchar* element) { - gptr buffer; + uchar* buffer; if (array->elements == array->max_element) { /* Call only when nessesary */ if (!(buffer=alloc_dynamic(array))) @@ -114,17 +131,32 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element) 0 Error */ -byte *alloc_dynamic(DYNAMIC_ARRAY *array) +uchar *alloc_dynamic(DYNAMIC_ARRAY *array) { if (array->elements == array->max_element) { char *new_ptr; + if (array->buffer == (uchar *)(array + 1)) + { + /* + In this senerio, the buffer is statically preallocated, + so we have to create an all-new malloc since we overflowed + */ + if (!(new_ptr= (char *) my_malloc((array->max_element+ + array->alloc_increment) * + array->size_of_element, + MYF(MY_WME)))) + return 0; + memcpy(new_ptr, array->buffer, + array->elements * array->size_of_element); + } + else if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+ - array->alloc_increment)* - array->size_of_element, - MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) + array->alloc_increment)* + array->size_of_element, + MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) return 0; - array->buffer=new_ptr; + array->buffer= (uchar*) new_ptr; array->max_element+=array->alloc_increment; } return array->buffer+(array->elements++ * array->size_of_element); @@ -143,7 +175,7 @@ byte *alloc_dynamic(DYNAMIC_ARRAY *array) 0 Array is empty */ -byte *pop_dynamic(DYNAMIC_ARRAY *array) +uchar *pop_dynamic(DYNAMIC_ARRAY *array) { if (array->elements) return array->buffer+(--array->elements * array->size_of_element); @@ -151,7 +183,7 @@ byte *pop_dynamic(DYNAMIC_ARRAY *array) } /* - Replace elemnent in array with given element and index + Replace element in array with given element and index SYNOPSIS set_dynamic() @@ -168,24 +200,13 @@ byte *pop_dynamic(DYNAMIC_ARRAY *array) FALSE Ok */ -my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) +my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx) { if (idx >= array->elements) { - if (idx >= array->max_element) - { - uint size; - char *new_ptr; - size=(idx+array->alloc_increment)/array->alloc_increment; - size*= array->alloc_increment; - if (!(new_ptr=(char*) my_realloc(array->buffer,size* - array->size_of_element, - MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) - return TRUE; - array->buffer=new_ptr; - array->max_element=size; - } - bzero((gptr) (array->buffer+array->elements*array->size_of_element), + if (idx >= array->max_element && allocate_dynamic(array, idx)) + return TRUE; + bzero((uchar*) (array->buffer+array->elements*array->size_of_element), (idx - array->elements)*array->size_of_element); array->elements=idx+1; } @@ -194,27 +215,79 @@ my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) return FALSE; } + +/* + Ensure that dynamic array has enough elements + + SYNOPSIS + allocate_dynamic() + array + max_elements Numbers of elements that is needed + + NOTES + Any new allocated element are NOT initialized + + RETURN VALUE + FALSE Ok + TRUE Allocation of new memory failed +*/ + +my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements) +{ + if (max_elements >= array->max_element) + { + uint size; + uchar *new_ptr; + size= (max_elements + array->alloc_increment)/array->alloc_increment; + size*= array->alloc_increment; + if (array->buffer == (uchar *)(array + 1)) + { + /* + In this senerio, the buffer is statically preallocated, + so we have to create an all-new malloc since we overflowed + */ + if (!(new_ptr= (uchar *) my_malloc(size * + array->size_of_element, + MYF(MY_WME)))) + return 0; + memcpy(new_ptr, array->buffer, + array->elements * array->size_of_element); + } + else + + + if (!(new_ptr= (uchar*) my_realloc(array->buffer,size* + array->size_of_element, + MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) + return TRUE; + array->buffer= new_ptr; + array->max_element= size; + } + return FALSE; +} + + /* Get an element from array by given index SYNOPSIS get_dynamic() array - gptr Element to be returned. If idx > elements contain zeroes. + uchar* Element to be returned. If idx > elements contain zeroes. idx Index of element wanted. */ -void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) +void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx) { if (idx >= array->elements) { DBUG_PRINT("warning",("To big array idx: %d, array size is %d", - idx,array->elements)); + idx,array->elements)); bzero(element,array->size_of_element); return; } memcpy(element,array->buffer+idx*array->size_of_element, - (size_t) array->size_of_element); + (size_t) array->size_of_element); } @@ -228,6 +301,12 @@ void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) void delete_dynamic(DYNAMIC_ARRAY *array) { + /* + Just mark as empty if we are using a static buffer + */ + if (array->buffer == (uchar *)(array + 1)) + array->elements= 0; + else if (array->buffer) { my_free(array->buffer,MYF(MY_WME)); @@ -242,15 +321,15 @@ void delete_dynamic(DYNAMIC_ARRAY *array) SYNOPSIS delete_dynamic_element() array - idx Index of element to be deleted + idx Index of element to be deleted */ void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) { - char *ptr=array->buffer+array->size_of_element*idx; + char *ptr= (char*) array->buffer+array->size_of_element*idx; array->elements--; memmove(ptr,ptr+array->size_of_element, - (array->elements-idx)*array->size_of_element); + (array->elements-idx)*array->size_of_element); } @@ -267,11 +346,42 @@ void freeze_size(DYNAMIC_ARRAY *array) { uint elements=max(array->elements,1); + /* + Do nothing if we are using a static buffer + */ + if (array->buffer == (uchar *)(array + 1)) + return; + if (array->buffer && array->max_element != elements) { - array->buffer=(char*) my_realloc(array->buffer, - elements*array->size_of_element, - MYF(MY_WME)); + array->buffer=(uchar*) my_realloc(array->buffer, + elements*array->size_of_element, + MYF(MY_WME)); array->max_element=elements; } } + + +/* + Get the index of a dynamic element + + SYNOPSIS + get_index_dynamic() + array Array + element Whose element index + +*/ + +int get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element) +{ + size_t ret; + if (array->buffer > element) + return -1; + + ret= (element - array->buffer) / array->size_of_element; + if (ret > array->elements) + return -1; + + return ret; + +} |