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
33my_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
58my_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
78unsigned 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
96unsigned 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
104my_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
130void 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
142void 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
153void 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
162void 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