1 /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2                  2016 MariaDB Corporation AB
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public
15    License along with this library; if not, write to the Free
16    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17    MA 02111-1301, USA */
18 
19 /* Handling of arrays that can grow dynamically. */
20 
21 #undef SAFEMALLOC /* Problems with threads */
22 
23 #include <ma_global.h>
24 #include <ma_sys.h>
25 #include "ma_string.h"
26 #include <memory.h>
27 
28 /*
29   Initiate array and alloc space for init_alloc elements. Array is usable
30   even if space allocation failed
31 */
32 
ma_init_dynamic_array(DYNAMIC_ARRAY * array,uint element_size,uint init_alloc,uint alloc_increment CALLER_INFO_PROTO)33 my_bool ma_init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
34                               uint init_alloc, uint alloc_increment CALLER_INFO_PROTO)
35 {
36   if (!alloc_increment)
37   {
38     alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16);
39     if (init_alloc > 8 && alloc_increment > init_alloc * 2)
40       alloc_increment=init_alloc*2;
41   }
42 
43   if (!init_alloc)
44     init_alloc=alloc_increment;
45   array->elements=0;
46   array->max_element=init_alloc;
47   array->alloc_increment=alloc_increment;
48   array->size_of_element=element_size;
49   if (!(array->buffer=(char*) malloc(element_size*init_alloc)))
50   {
51     array->max_element=0;
52     return(TRUE);
53   }
54   return(FALSE);
55 }
56 
57 
ma_insert_dynamic(DYNAMIC_ARRAY * array,void * element)58 my_bool ma_insert_dynamic(DYNAMIC_ARRAY *array, void *element)
59 {
60   void *buffer;
61   if (array->elements == array->max_element)
62   {						/* Call only when necessary */
63     if (!(buffer=ma_alloc_dynamic(array)))
64       return TRUE;
65   }
66   else
67   {
68     buffer=array->buffer+(array->elements * array->size_of_element);
69     array->elements++;
70   }
71   memcpy(buffer,element,(size_t) array->size_of_element);
72   return FALSE;
73 }
74 
75 
76 	/* Alloc room for one element */
77 
ma_alloc_dynamic(DYNAMIC_ARRAY * array)78 unsigned char *ma_alloc_dynamic(DYNAMIC_ARRAY *array)
79 {
80   if (array->elements == array->max_element)
81   {
82     char *new_ptr;
83     if (!(new_ptr=(char*) realloc(array->buffer,(array->max_element+
84 			          array->alloc_increment)*
85 				   array->size_of_element)))
86       return 0;
87     array->buffer=new_ptr;
88     array->max_element+=array->alloc_increment;
89   }
90   return (unsigned char *)array->buffer+(array->elements++ * array->size_of_element);
91 }
92 
93 
94 	/* remove last element from array and return it */
95 
ma_pop_dynamic(DYNAMIC_ARRAY * array)96 unsigned char *ma_pop_dynamic(DYNAMIC_ARRAY *array)
97 {
98   if (array->elements)
99     return (unsigned char *)array->buffer+(--array->elements * array->size_of_element);
100   return 0;
101 }
102 
103 
ma_set_dynamic(DYNAMIC_ARRAY * array,void * element,uint idx)104 my_bool ma_set_dynamic(DYNAMIC_ARRAY *array, void * element, uint idx)
105 {
106   if (idx >= array->elements)
107   {
108     if (idx >= array->max_element)
109     {
110       uint size;
111       char *new_ptr;
112       size=(idx+array->alloc_increment)/array->alloc_increment;
113       size*= array->alloc_increment;
114       if (!(new_ptr=(char*) realloc(array->buffer,size*
115 			            array->size_of_element)))
116 	return TRUE;
117       array->buffer=new_ptr;
118       array->max_element=size;
119     }
120     memset((array->buffer+array->elements*array->size_of_element), 0,
121 	  (idx - array->elements)*array->size_of_element);
122     array->elements=idx+1;
123   }
124   memcpy(array->buffer+(idx * array->size_of_element),element,
125 	 (size_t) array->size_of_element);
126   return FALSE;
127 }
128 
129 
ma_get_dynamic(DYNAMIC_ARRAY * array,void * element,uint idx)130 void ma_get_dynamic(DYNAMIC_ARRAY *array, void * element, uint idx)
131 {
132   if (idx >= array->elements)
133   {
134     memset(element, 0, array->size_of_element);
135     return;
136   }
137   memcpy(element,array->buffer+idx*array->size_of_element,
138 	 (size_t) array->size_of_element);
139 }
140 
141 
ma_delete_dynamic(DYNAMIC_ARRAY * array)142 void ma_delete_dynamic(DYNAMIC_ARRAY *array)
143 {
144   if (array->buffer)
145   {
146     free(array->buffer);
147     array->buffer=0;
148     array->elements=array->max_element=0;
149   }
150 }
151 
152 
ma_delete_dynamic_element(DYNAMIC_ARRAY * array,uint idx)153 void ma_delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
154 {
155   char *ptr=array->buffer+array->size_of_element*idx;
156   array->elements--;
157   memmove(ptr,ptr+array->size_of_element,
158 	  (array->elements-idx)*array->size_of_element);
159 }
160 
161 
ma_freeze_size(DYNAMIC_ARRAY * array)162 void ma_freeze_size(DYNAMIC_ARRAY *array)
163 {
164   uint elements=max(array->elements,1);
165 
166   if (array->buffer && array->max_element != elements)
167   {
168     array->buffer=(char*) realloc(array->buffer,
169 			          elements*array->size_of_element);
170     array->max_element=elements;
171   }
172 }
173