~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
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
33
    init_dynamic_array() initiates array and allocate space for
34
    init_alloc eilements.
1 by brian
clean slate
35
    Array is usable even if space allocation failed.
36
    Static buffers must begin immediately after the array structure.
37
38
  RETURN VALUE
656.3.2 by Monty Taylor
Removed my_nosys and my_quick. /me shudders.
39
    true	malloc() failed
163 by Brian Aker
Merge Monty's code.
40
    false	Ok
1 by brian
clean slate
41
*/
42
482 by Brian Aker
Remove uint.
43
bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint32_t element_size,
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
44
                            void *init_buffer, uint32_t init_alloc,
575.1.6 by Monty Taylor
Cleaned up some headers for PCH.
45
                            uint32_t alloc_increment)
1 by brian
clean slate
46
{
47
  if (!alloc_increment)
48
  {
398.1.4 by Monty Taylor
Renamed max/min.
49
    alloc_increment=cmax((8192-MALLOC_OVERHEAD)/element_size,16);
1 by brian
clean slate
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;
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
63
  if ((array->buffer= (unsigned char*) init_buffer))
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
64
    return(false);
656.3.2 by Monty Taylor
Removed my_nosys and my_quick. /me shudders.
65
  if (!(array->buffer=(unsigned char*) malloc(element_size*init_alloc)))
1 by brian
clean slate
66
  {
67
    array->max_element=0;
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
68
    return(true);
1 by brian
clean slate
69
  }
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
70
  return(false);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
71
}
1 by brian
clean slate
72
482 by Brian Aker
Remove uint.
73
bool init_dynamic_array(DYNAMIC_ARRAY *array, uint32_t element_size,
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
74
                           uint32_t init_alloc,
575.1.6 by Monty Taylor
Cleaned up some headers for PCH.
75
                           uint32_t alloc_increment)
1 by brian
clean slate
76
{
77
  /* placeholder to preserve ABI */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
78
  return my_init_dynamic_array_ci(array, element_size, init_alloc,
1 by brian
clean slate
79
                                  alloc_increment);
80
}
81
/*
82
  Insert element at the end of array. Allocate memory if needed.
83
84
  SYNOPSIS
85
    insert_dynamic()
86
      array
87
      element
88
89
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
90
    true	Insert failed
91
    false	Ok
1 by brian
clean slate
92
*/
93
481 by Brian Aker
Remove all of uchar.
94
bool insert_dynamic(DYNAMIC_ARRAY *array, unsigned char* element)
1 by brian
clean slate
95
{
481 by Brian Aker
Remove all of uchar.
96
  unsigned char* buffer;
1 by brian
clean slate
97
  if (array->elements == array->max_element)
98
  {						/* Call only when nessesary */
99
    if (!(buffer=alloc_dynamic(array)))
163 by Brian Aker
Merge Monty's code.
100
      return true;
1 by brian
clean slate
101
  }
102
  else
103
  {
104
    buffer=array->buffer+(array->elements * array->size_of_element);
105
    array->elements++;
106
  }
107
  memcpy(buffer,element,(size_t) array->size_of_element);
163 by Brian Aker
Merge Monty's code.
108
  return false;
1 by brian
clean slate
109
}
110
111
112
/*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
113
  Alloc space for next element(s)
1 by brian
clean slate
114
115
  SYNOPSIS
116
    alloc_dynamic()
117
      array
118
119
  DESCRIPTION
120
    alloc_dynamic() checks if there is empty space for at least
121
    one element if not tries to allocate space for alloc_increment
122
    elements at the end of array.
123
124
  RETURN VALUE
125
    pointer	Pointer to empty space for element
126
    0		Error
127
*/
128
481 by Brian Aker
Remove all of uchar.
129
unsigned char *alloc_dynamic(DYNAMIC_ARRAY *array)
1 by brian
clean slate
130
{
131
  if (array->elements == array->max_element)
132
  {
133
    char *new_ptr;
481 by Brian Aker
Remove all of uchar.
134
    if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
135
    {
136
      /*
137
        In this senerio, the buffer is statically preallocated,
138
        so we have to create an all-new malloc since we overflowed
139
      */
140
      if (!(new_ptr= (char *) my_malloc((array->max_element+
141
                                         array->alloc_increment) *
142
                                        array->size_of_element,
143
                                        MYF(MY_WME))))
144
        return 0;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
145
      memcpy(new_ptr, array->buffer,
1 by brian
clean slate
146
             array->elements * array->size_of_element);
147
    }
148
    else
149
    if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+
150
                                     array->alloc_increment)*
151
                                     array->size_of_element,
152
                                     MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
153
      return 0;
481 by Brian Aker
Remove all of uchar.
154
    array->buffer= (unsigned char*) new_ptr;
1 by brian
clean slate
155
    array->max_element+=array->alloc_increment;
156
  }
157
  return array->buffer+(array->elements++ * array->size_of_element);
158
}
159
160
161
/*
162
  Pop last element from array.
163
164
  SYNOPSIS
165
    pop_dynamic()
166
      array
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
167
168
  RETURN VALUE
1 by brian
clean slate
169
    pointer	Ok
170
    0		Array is empty
171
*/
172
481 by Brian Aker
Remove all of uchar.
173
unsigned char *pop_dynamic(DYNAMIC_ARRAY *array)
1 by brian
clean slate
174
{
175
  if (array->elements)
176
    return array->buffer+(--array->elements * array->size_of_element);
177
  return 0;
178
}
179
180
/*
181
  Replace element in array with given element and index
182
183
  SYNOPSIS
184
    set_dynamic()
185
      array
186
      element	Element to be inserted
187
      idx	Index where element is to be inserted
188
189
  DESCRIPTION
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
190
    set_dynamic() replaces element in array.
191
    If idx > max_element insert new element. Allocate memory if needed.
192
1 by brian
clean slate
193
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
194
    true	Idx was out of range and allocation of new memory failed
195
    false	Ok
1 by brian
clean slate
196
*/
197
482 by Brian Aker
Remove uint.
198
bool set_dynamic(DYNAMIC_ARRAY *array, unsigned char* element, uint32_t idx)
1 by brian
clean slate
199
{
200
  if (idx >= array->elements)
201
  {
202
    if (idx >= array->max_element && allocate_dynamic(array, idx))
163 by Brian Aker
Merge Monty's code.
203
      return true;
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
204
    memset(array->buffer+array->elements*array->size_of_element, 0,
205
           (idx - array->elements)*array->size_of_element);
1 by brian
clean slate
206
    array->elements=idx+1;
207
  }
208
  memcpy(array->buffer+(idx * array->size_of_element),element,
209
	 (size_t) array->size_of_element);
163 by Brian Aker
Merge Monty's code.
210
  return false;
1 by brian
clean slate
211
}
212
213
214
/*
215
  Ensure that dynamic array has enough elements
216
217
  SYNOPSIS
218
    allocate_dynamic()
219
    array
220
    max_elements        Numbers of elements that is needed
221
222
  NOTES
223
   Any new allocated element are NOT initialized
224
225
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
226
    false	Ok
227
    true	Allocation of new memory failed
1 by brian
clean slate
228
*/
229
482 by Brian Aker
Remove uint.
230
bool allocate_dynamic(DYNAMIC_ARRAY *array, uint32_t max_elements)
1 by brian
clean slate
231
{
232
  if (max_elements >= array->max_element)
233
  {
482 by Brian Aker
Remove uint.
234
    uint32_t size;
481 by Brian Aker
Remove all of uchar.
235
    unsigned char *new_ptr;
1 by brian
clean slate
236
    size= (max_elements + array->alloc_increment)/array->alloc_increment;
237
    size*= array->alloc_increment;
481 by Brian Aker
Remove all of uchar.
238
    if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
239
    {
240
       /*
241
         In this senerio, the buffer is statically preallocated,
242
         so we have to create an all-new malloc since we overflowed
243
       */
481 by Brian Aker
Remove all of uchar.
244
       if (!(new_ptr= (unsigned char *) my_malloc(size *
1 by brian
clean slate
245
                                         array->size_of_element,
246
                                         MYF(MY_WME))))
247
         return 0;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
248
       memcpy(new_ptr, array->buffer,
1 by brian
clean slate
249
              array->elements * array->size_of_element);
250
     }
251
     else
252
253
481 by Brian Aker
Remove all of uchar.
254
    if (!(new_ptr= (unsigned char*) my_realloc(array->buffer,size*
1 by brian
clean slate
255
                                       array->size_of_element,
256
                                       MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
163 by Brian Aker
Merge Monty's code.
257
      return true;
1 by brian
clean slate
258
    array->buffer= new_ptr;
259
    array->max_element= size;
260
  }
163 by Brian Aker
Merge Monty's code.
261
  return false;
1 by brian
clean slate
262
}
263
264
265
/*
266
  Get an element from array by given index
267
268
  SYNOPSIS
269
    get_dynamic()
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
270
      array
481 by Brian Aker
Remove all of uchar.
271
      unsigned char*	Element to be returned. If idx > elements contain zeroes.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
272
      idx	Index of element wanted.
1 by brian
clean slate
273
*/
274
482 by Brian Aker
Remove uint.
275
void get_dynamic(DYNAMIC_ARRAY *array, unsigned char* element, uint32_t idx)
1 by brian
clean slate
276
{
277
  if (idx >= array->elements)
278
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
279
    memset(element, 0, array->size_of_element);
1 by brian
clean slate
280
    return;
281
  }
282
  memcpy(element,array->buffer+idx*array->size_of_element,
283
         (size_t) array->size_of_element);
284
}
285
286
287
/*
288
  Empty array by freeing all memory
289
290
  SYNOPSIS
291
    delete_dynamic()
292
      array	Array to be deleted
293
*/
294
295
void delete_dynamic(DYNAMIC_ARRAY *array)
296
{
297
  /*
298
    Just mark as empty if we are using a static buffer
299
  */
481 by Brian Aker
Remove all of uchar.
300
  if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
301
    array->elements= 0;
302
  else
303
  if (array->buffer)
304
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
305
    free(array->buffer);
1 by brian
clean slate
306
    array->buffer=0;
307
    array->elements=array->max_element=0;
308
  }
309
}
310
311
/*
312
  Delete element by given index
313
314
  SYNOPSIS
315
    delete_dynamic_element()
316
      array
317
      idx        Index of element to be deleted
318
*/
319
482 by Brian Aker
Remove uint.
320
void delete_dynamic_element(DYNAMIC_ARRAY *array, uint32_t idx)
1 by brian
clean slate
321
{
322
  char *ptr= (char*) array->buffer+array->size_of_element*idx;
323
  array->elements--;
324
  memmove(ptr,ptr+array->size_of_element,
325
          (array->elements-idx)*array->size_of_element);
326
}
327
328
329
/*
330
  Free unused memory
331
332
  SYNOPSIS
333
    freeze_size()
334
      array	Array to be freed
335
336
*/
337
338
void freeze_size(DYNAMIC_ARRAY *array)
339
{
482 by Brian Aker
Remove uint.
340
  uint32_t elements=cmax(array->elements,1);
1 by brian
clean slate
341
342
  /*
343
    Do nothing if we are using a static buffer
344
  */
481 by Brian Aker
Remove all of uchar.
345
  if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
346
    return;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
347
1 by brian
clean slate
348
  if (array->buffer && array->max_element != elements)
349
  {
481 by Brian Aker
Remove all of uchar.
350
    array->buffer=(unsigned char*) my_realloc(array->buffer,
1 by brian
clean slate
351
                                     elements*array->size_of_element,
352
                                     MYF(MY_WME));
353
    array->max_element=elements;
354
  }
355
}
356
357
358
/*
359
  Get the index of a dynamic element
360
361
  SYNOPSIS
362
    get_index_dynamic()
363
     array	Array
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
364
     element Whose element index
1 by brian
clean slate
365
366
*/
367
481 by Brian Aker
Remove all of uchar.
368
int get_index_dynamic(DYNAMIC_ARRAY *array, unsigned char* element)
1 by brian
clean slate
369
{
482 by Brian Aker
Remove uint.
370
  uint32_t ret;
1 by brian
clean slate
371
  if (array->buffer > element)
372
    return -1;
373
374
  ret= (element - array->buffer) /  array->size_of_element;
375
  if (ret > array->elements)
376
    return -1;
377
378
  return ret;
379
380
}