|
- /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License, version 2.0,
- as published by the Free Software Foundation.
-
- This program is also distributed with certain software (including
- but not limited to OpenSSL) that is licensed under separate terms,
- as designated in a particular file or component or in included license
- documentation. The authors of MySQL hereby grant you an additional
- permission to link the program and your derivative works with the
- separately licensed software that they have included with MySQL.
-
- Without limiting anything contained in the foregoing, this file,
- which is part of C Driver for MySQL (Connector/C), is also subject to the
- Universal FOSS Exception, version 1.0, a copy of which can be found at
- http://oss.oracle.com/licenses/universal-foss-exception.
-
- 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, version 2.0, 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;
- }
- }
|