summaryrefslogtreecommitdiff
path: root/mysys/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/array.c')
-rw-r--r--mysys/array.c192
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;
+
+}