/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 2016 MariaDB Corporation AB This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA */ /* Handling of arrays that can grow dynamically. */ #undef SAFEMALLOC /* Problems with threads */ #include #include #include "ma_string.h" #include /* Initiate array and alloc space for init_alloc elements. Array is usable even if space allocation failed */ my_bool ma_init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, uint init_alloc, uint alloc_increment CALLER_INFO_PROTO) { if (!alloc_increment) { alloc_increment=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; array->elements=0; array->max_element=init_alloc; array->alloc_increment=alloc_increment; array->size_of_element=element_size; if (!(array->buffer=(char*) malloc(element_size*init_alloc))) { array->max_element=0; return(TRUE); } return(FALSE); } my_bool ma_insert_dynamic(DYNAMIC_ARRAY *array, void *element) { void *buffer; if (array->elements == array->max_element) { /* Call only when necessary */ if (!(buffer=ma_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 room for one element */ unsigned char *ma_alloc_dynamic(DYNAMIC_ARRAY *array) { if (array->elements == array->max_element) { char *new_ptr; if (!(new_ptr=(char*) realloc(array->buffer,(array->max_element+ array->alloc_increment)* array->size_of_element))) return 0; array->buffer=new_ptr; array->max_element+=array->alloc_increment; } return (unsigned char *)array->buffer+(array->elements++ * array->size_of_element); } /* remove last element from array and return it */ unsigned char *ma_pop_dynamic(DYNAMIC_ARRAY *array) { if (array->elements) return (unsigned char *)array->buffer+(--array->elements * array->size_of_element); return 0; } my_bool ma_set_dynamic(DYNAMIC_ARRAY *array, void * 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*) realloc(array->buffer,size* array->size_of_element))) return TRUE; array->buffer=new_ptr; array->max_element=size; } memset((array->buffer+array->elements*array->size_of_element), 0, (idx - array->elements)*array->size_of_element); array->elements=idx+1; } memcpy(array->buffer+(idx * array->size_of_element),element, (size_t) array->size_of_element); return FALSE; } void ma_get_dynamic(DYNAMIC_ARRAY *array, void * element, uint idx) { if (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 ma_delete_dynamic(DYNAMIC_ARRAY *array) { if (array->buffer) { free(array->buffer); array->buffer=0; array->elements=array->max_element=0; } } void ma_delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) { char *ptr=array->buffer+array->size_of_element*idx; array->elements--; memmove(ptr,ptr+array->size_of_element, (array->elements-idx)*array->size_of_element); } void ma_freeze_size(DYNAMIC_ARRAY *array) { uint elements=max(array->elements,1); if (array->buffer && array->max_element != elements) { array->buffer=(char*) realloc(array->buffer, elements*array->size_of_element); array->max_element=elements; } }