~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* Handling of arrays that can grow dynamicly. */
17
18
#include "mysys_priv.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
19
#include <mystrings/m_string.h>
1 by brian
clean slate
20
21
/*
22
  Initiate dynamic array
23
24
  SYNOPSIS
25
    init_dynamic_array2()
26
      array		Pointer to an array
27
      element_size	Size of element
28
      init_buffer       Initial buffer pointer
29
      init_alloc	Number of initial elements
30
      alloc_increment	Increment for adding new elements
31
32
  DESCRIPTION
33
    init_dynamic_array() initiates array and allocate space for 
34
    init_alloc eilements. 
35
    Array is usable even if space allocation failed.
36
    Static buffers must begin immediately after the array structure.
37
38
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
39
    true	my_malloc_ci() failed
40
    false	Ok
1 by brian
clean slate
41
*/
42
146 by Brian Aker
my_bool cleanup.
43
bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
1 by brian
clean slate
44
                            void *init_buffer, uint init_alloc, 
45
                            uint alloc_increment CALLER_INFO_PROTO)
46
{
47
  if (!alloc_increment)
48
  {
49
    alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16);
50
    if (init_alloc > 8 && alloc_increment > init_alloc * 2)
51
      alloc_increment=init_alloc*2;
52
  }
53
54
  if (!init_alloc)
55
  {
56
    init_alloc=alloc_increment;
57
    init_buffer= 0;
58
  }
59
  array->elements=0;
60
  array->max_element=init_alloc;
61
  array->alloc_increment=alloc_increment;
62
  array->size_of_element=element_size;
63
  if ((array->buffer= init_buffer))
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
64
    return(false);
1 by brian
clean slate
65
  if (!(array->buffer=(uchar*) my_malloc_ci(element_size*init_alloc,
66
                                            MYF(MY_WME))))
67
  {
68
    array->max_element=0;
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
69
    return(true);
1 by brian
clean slate
70
  }
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
71
  return(false);
1 by brian
clean slate
72
} 
73
146 by Brian Aker
my_bool cleanup.
74
bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
1 by brian
clean slate
75
                           uint init_alloc, 
76
                           uint alloc_increment CALLER_INFO_PROTO)
77
{
78
  /* placeholder to preserve ABI */
79
  return my_init_dynamic_array_ci(array, element_size, init_alloc, 
80
                                  alloc_increment);
81
}
82
/*
83
  Insert element at the end of array. Allocate memory if needed.
84
85
  SYNOPSIS
86
    insert_dynamic()
87
      array
88
      element
89
90
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
91
    true	Insert failed
92
    false	Ok
1 by brian
clean slate
93
*/
94
146 by Brian Aker
my_bool cleanup.
95
bool insert_dynamic(DYNAMIC_ARRAY *array, uchar* element)
1 by brian
clean slate
96
{
97
  uchar* buffer;
98
  if (array->elements == array->max_element)
99
  {						/* Call only when nessesary */
100
    if (!(buffer=alloc_dynamic(array)))
163 by Brian Aker
Merge Monty's code.
101
      return true;
1 by brian
clean slate
102
  }
103
  else
104
  {
105
    buffer=array->buffer+(array->elements * array->size_of_element);
106
    array->elements++;
107
  }
108
  memcpy(buffer,element,(size_t) array->size_of_element);
163 by Brian Aker
Merge Monty's code.
109
  return false;
1 by brian
clean slate
110
}
111
112
113
/*
114
  Alloc space for next element(s) 
115
116
  SYNOPSIS
117
    alloc_dynamic()
118
      array
119
120
  DESCRIPTION
121
    alloc_dynamic() checks if there is empty space for at least
122
    one element if not tries to allocate space for alloc_increment
123
    elements at the end of array.
124
125
  RETURN VALUE
126
    pointer	Pointer to empty space for element
127
    0		Error
128
*/
129
130
uchar *alloc_dynamic(DYNAMIC_ARRAY *array)
131
{
132
  if (array->elements == array->max_element)
133
  {
134
    char *new_ptr;
135
    if (array->buffer == (uchar *)(array + 1))
136
    {
137
      /*
138
        In this senerio, the buffer is statically preallocated,
139
        so we have to create an all-new malloc since we overflowed
140
      */
141
      if (!(new_ptr= (char *) my_malloc((array->max_element+
142
                                         array->alloc_increment) *
143
                                        array->size_of_element,
144
                                        MYF(MY_WME))))
145
        return 0;
146
      memcpy(new_ptr, array->buffer, 
147
             array->elements * array->size_of_element);
148
    }
149
    else
150
    if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+
151
                                     array->alloc_increment)*
152
                                     array->size_of_element,
153
                                     MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
154
      return 0;
155
    array->buffer= (uchar*) new_ptr;
156
    array->max_element+=array->alloc_increment;
157
  }
158
  return array->buffer+(array->elements++ * array->size_of_element);
159
}
160
161
162
/*
163
  Pop last element from array.
164
165
  SYNOPSIS
166
    pop_dynamic()
167
      array
168
  
169
  RETURN VALUE    
170
    pointer	Ok
171
    0		Array is empty
172
*/
173
174
uchar *pop_dynamic(DYNAMIC_ARRAY *array)
175
{
176
  if (array->elements)
177
    return array->buffer+(--array->elements * array->size_of_element);
178
  return 0;
179
}
180
181
/*
182
  Replace element in array with given element and index
183
184
  SYNOPSIS
185
    set_dynamic()
186
      array
187
      element	Element to be inserted
188
      idx	Index where element is to be inserted
189
190
  DESCRIPTION
191
    set_dynamic() replaces element in array. 
192
    If idx > max_element insert new element. Allocate memory if needed. 
193
 
194
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
195
    true	Idx was out of range and allocation of new memory failed
196
    false	Ok
1 by brian
clean slate
197
*/
198
146 by Brian Aker
my_bool cleanup.
199
bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
1 by brian
clean slate
200
{
201
  if (idx >= array->elements)
202
  {
203
    if (idx >= array->max_element && allocate_dynamic(array, idx))
163 by Brian Aker
Merge Monty's code.
204
      return true;
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
205
    memset((uchar*) (array->buffer+array->elements*array->size_of_element), 0,
1 by brian
clean slate
206
	  (idx - array->elements)*array->size_of_element);
207
    array->elements=idx+1;
208
  }
209
  memcpy(array->buffer+(idx * array->size_of_element),element,
210
	 (size_t) array->size_of_element);
163 by Brian Aker
Merge Monty's code.
211
  return false;
1 by brian
clean slate
212
}
213
214
215
/*
216
  Ensure that dynamic array has enough elements
217
218
  SYNOPSIS
219
    allocate_dynamic()
220
    array
221
    max_elements        Numbers of elements that is needed
222
223
  NOTES
224
   Any new allocated element are NOT initialized
225
226
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
227
    false	Ok
228
    true	Allocation of new memory failed
1 by brian
clean slate
229
*/
230
146 by Brian Aker
my_bool cleanup.
231
bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements)
1 by brian
clean slate
232
{
233
  if (max_elements >= array->max_element)
234
  {
235
    uint size;
236
    uchar *new_ptr;
237
    size= (max_elements + array->alloc_increment)/array->alloc_increment;
238
    size*= array->alloc_increment;
239
    if (array->buffer == (uchar *)(array + 1))
240
    {
241
       /*
242
         In this senerio, the buffer is statically preallocated,
243
         so we have to create an all-new malloc since we overflowed
244
       */
245
       if (!(new_ptr= (uchar *) my_malloc(size *
246
                                         array->size_of_element,
247
                                         MYF(MY_WME))))
248
         return 0;
249
       memcpy(new_ptr, array->buffer, 
250
              array->elements * array->size_of_element);
251
     }
252
     else
253
254
255
    if (!(new_ptr= (uchar*) my_realloc(array->buffer,size*
256
                                       array->size_of_element,
257
                                       MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
163 by Brian Aker
Merge Monty's code.
258
      return true;
1 by brian
clean slate
259
    array->buffer= new_ptr;
260
    array->max_element= size;
261
  }
163 by Brian Aker
Merge Monty's code.
262
  return false;
1 by brian
clean slate
263
}
264
265
266
/*
267
  Get an element from array by given index
268
269
  SYNOPSIS
270
    get_dynamic()
271
      array	
272
      uchar*	Element to be returned. If idx > elements contain zeroes.
273
      idx	Index of element wanted. 
274
*/
275
276
void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
277
{
278
  if (idx >= array->elements)
279
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
280
    memset(element, 0, array->size_of_element);
1 by brian
clean slate
281
    return;
282
  }
283
  memcpy(element,array->buffer+idx*array->size_of_element,
284
         (size_t) array->size_of_element);
285
}
286
287
288
/*
289
  Empty array by freeing all memory
290
291
  SYNOPSIS
292
    delete_dynamic()
293
      array	Array to be deleted
294
*/
295
296
void delete_dynamic(DYNAMIC_ARRAY *array)
297
{
298
  /*
299
    Just mark as empty if we are using a static buffer
300
  */
301
  if (array->buffer == (uchar *)(array + 1))
302
    array->elements= 0;
303
  else
304
  if (array->buffer)
305
  {
306
    my_free(array->buffer,MYF(MY_WME));
307
    array->buffer=0;
308
    array->elements=array->max_element=0;
309
  }
310
}
311
312
/*
313
  Delete element by given index
314
315
  SYNOPSIS
316
    delete_dynamic_element()
317
      array
318
      idx        Index of element to be deleted
319
*/
320
321
void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
322
{
323
  char *ptr= (char*) array->buffer+array->size_of_element*idx;
324
  array->elements--;
325
  memmove(ptr,ptr+array->size_of_element,
326
          (array->elements-idx)*array->size_of_element);
327
}
328
329
330
/*
331
  Free unused memory
332
333
  SYNOPSIS
334
    freeze_size()
335
      array	Array to be freed
336
337
*/
338
339
void freeze_size(DYNAMIC_ARRAY *array)
340
{
341
  uint elements=max(array->elements,1);
342
343
  /*
344
    Do nothing if we are using a static buffer
345
  */
346
  if (array->buffer == (uchar *)(array + 1))
347
    return;
348
    
349
  if (array->buffer && array->max_element != elements)
350
  {
351
    array->buffer=(uchar*) my_realloc(array->buffer,
352
                                     elements*array->size_of_element,
353
                                     MYF(MY_WME));
354
    array->max_element=elements;
355
  }
356
}
357
358
359
/*
360
  Get the index of a dynamic element
361
362
  SYNOPSIS
363
    get_index_dynamic()
364
     array	Array
365
     element Whose element index 
366
367
*/
368
369
int get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element)
370
{
371
  uint ret;
372
  if (array->buffer > element)
373
    return -1;
374
375
  ret= (element - array->buffer) /  array->size_of_element;
376
  if (ret > array->elements)
377
    return -1;
378
379
  return ret;
380
381
}