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