aboutsummaryrefslogtreecommitdiff
path: root/mysql/mysys/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysql/mysys/array.c')
-rw-r--r--mysql/mysys/array.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/mysql/mysys/array.c b/mysql/mysys/array.c
new file mode 100644
index 0000000..cf54304
--- /dev/null
+++ b/mysql/mysys/array.c
@@ -0,0 +1,281 @@
+/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ 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 */
+
+/* Handling of arrays that can grow dynamicly. */
+
+#include "mysys_priv.h"
+#include "m_string.h"
+#include "my_sys.h"
+
+/*
+ Initiate dynamic array
+
+ SYNOPSIS
+ my_init_dynamic_array()
+ 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
+
+ DESCRIPTION
+ init_dynamic_array() initiates array and allocate space for
+ 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 my_init_dynamic_array(DYNAMIC_ARRAY *array,
+ PSI_memory_key psi_key,
+ uint element_size,
+ void *init_buffer,
+ uint init_alloc,
+ uint alloc_increment)
+{
+ DBUG_ENTER("init_dynamic_array");
+ if (!alloc_increment)
+ {
+ alloc_increment=MY_MAX((8192-MALLOC_OVERHEAD)/element_size,16);
+ if (init_alloc > 8 && alloc_increment > init_alloc * 2)
+ alloc_increment=init_alloc*2;
+ }
+
+ 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;
+ array->m_psi_key= psi_key;
+ 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= (uchar*) my_malloc(psi_key,
+ 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)
+{
+ /* placeholder to preserve ABI */
+ return my_init_dynamic_array(array,
+ PSI_INSTRUMENT_ME,
+ element_size,
+ NULL, /* init_buffer */
+ init_alloc,
+ alloc_increment);
+}
+/*
+ Insert element at the end of array. Allocate memory if needed.
+
+ SYNOPSIS
+ insert_dynamic()
+ array
+ element
+
+ RETURN VALUE
+ TRUE Insert failed
+ FALSE Ok
+*/
+
+my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void *element)
+{
+ uchar* buffer;
+ if (array->elements == array->max_element)
+ { /* Call only when nessesary */
+ if (!(buffer=alloc_dynamic(array)))
+ return TRUE;
+ }
+ else
+ {
+ buffer=array->buffer+(array->elements * array->size_of_element);
+ array->elements++;
+ }
+ memcpy(buffer,element,(size_t) array->size_of_element);
+ return FALSE;
+}
+
+
+/*
+ Alloc space for next element(s)
+
+ SYNOPSIS
+ alloc_dynamic()
+ array
+
+ DESCRIPTION
+ alloc_dynamic() checks if there is empty space for at least
+ one element if not tries to allocate space for alloc_increment
+ elements at the end of array.
+
+ RETURN VALUE
+ pointer Pointer to empty space for element
+ 0 Error
+*/
+
+void *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->m_psi_key,
+ (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->m_psi_key,
+ array->buffer,(array->max_element+
+ array->alloc_increment)*
+ array->size_of_element,
+ MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
+ return 0;
+ array->buffer= (uchar*) new_ptr;
+ array->max_element+=array->alloc_increment;
+ }
+ return array->buffer+(array->elements++ * array->size_of_element);
+}
+
+
+/*
+ Pop last element from array.
+
+ SYNOPSIS
+ pop_dynamic()
+ array
+
+ RETURN VALUE
+ pointer Ok
+ 0 Array is empty
+*/
+
+void *pop_dynamic(DYNAMIC_ARRAY *array)
+{
+ if (array->elements)
+ return array->buffer+(--array->elements * array->size_of_element);
+ return 0;
+}
+
+
+/*
+ Get an element from array by given index
+
+ SYNOPSIS
+ get_dynamic()
+ array
+ uchar* Element to be returned. If idx > elements contain zeroes.
+ idx Index of element wanted.
+*/
+
+void get_dynamic(DYNAMIC_ARRAY *array, void *element, uint idx)
+{
+ if (idx >= array->elements)
+ {
+ DBUG_PRINT("warning",("To big array idx: %d, array size is %d",
+ idx,array->elements));
+ memset(element, 0, array->size_of_element);
+ return;
+ }
+ memcpy(element,array->buffer+idx*array->size_of_element,
+ (size_t) array->size_of_element);
+}
+
+void claim_dynamic(DYNAMIC_ARRAY *array)
+{
+ /*
+ Check for a static buffer
+ */
+ if (array->buffer == (uchar *)(array + 1))
+ return;
+
+ my_claim(array->buffer);
+}
+
+
+/*
+ Empty array by freeing all memory
+
+ SYNOPSIS
+ delete_dynamic()
+ array Array to be deleted
+*/
+
+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);
+ array->buffer=0;
+ array->elements=array->max_element=0;
+ }
+}
+
+
+/*
+ Free unused memory
+
+ SYNOPSIS
+ freeze_size()
+ array Array to be freed
+
+*/
+
+void freeze_size(DYNAMIC_ARRAY *array)
+{
+ uint elements=MY_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=(uchar*) my_realloc(array->m_psi_key,
+ array->buffer,
+ elements*array->size_of_element,
+ MYF(MY_WME));
+ array->max_element=elements;
+ }
+}