~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
      */
656.1.26 by Monty Taylor
Finally removed all of the my_malloc stuff.
140
      if (!(new_ptr= (char *) malloc((array->max_element+
141
                                     array->alloc_increment) *
142
                                     array->size_of_element)))
1 by brian
clean slate
143
        return 0;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
144
      memcpy(new_ptr, array->buffer,
1 by brian
clean slate
145
             array->elements * array->size_of_element);
146
    }
656.1.47 by Monty Taylor
More malloc return check fixes.
147
    else if (!(new_ptr= (char*) realloc(array->buffer,
148
                                        (array->max_element+
149
                                         array->alloc_increment)*
150
                                        array->size_of_element)))
1 by brian
clean slate
151
      return 0;
481 by Brian Aker
Remove all of uchar.
152
    array->buffer= (unsigned char*) new_ptr;
1 by brian
clean slate
153
    array->max_element+=array->alloc_increment;
154
  }
155
  return array->buffer+(array->elements++ * array->size_of_element);
156
}
157
158
159
/*
160
  Pop last element from array.
161
162
  SYNOPSIS
163
    pop_dynamic()
164
      array
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
165
166
  RETURN VALUE
1 by brian
clean slate
167
    pointer	Ok
168
    0		Array is empty
169
*/
170
481 by Brian Aker
Remove all of uchar.
171
unsigned char *pop_dynamic(DYNAMIC_ARRAY *array)
1 by brian
clean slate
172
{
173
  if (array->elements)
174
    return array->buffer+(--array->elements * array->size_of_element);
175
  return 0;
176
}
177
178
/*
179
  Replace element in array with given element and index
180
181
  SYNOPSIS
182
    set_dynamic()
183
      array
184
      element	Element to be inserted
185
      idx	Index where element is to be inserted
186
187
  DESCRIPTION
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
188
    set_dynamic() replaces element in array.
189
    If idx > max_element insert new element. Allocate memory if needed.
190
1 by brian
clean slate
191
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
192
    true	Idx was out of range and allocation of new memory failed
193
    false	Ok
1 by brian
clean slate
194
*/
195
482 by Brian Aker
Remove uint.
196
bool set_dynamic(DYNAMIC_ARRAY *array, unsigned char* element, uint32_t idx)
1 by brian
clean slate
197
{
198
  if (idx >= array->elements)
199
  {
200
    if (idx >= array->max_element && allocate_dynamic(array, idx))
163 by Brian Aker
Merge Monty's code.
201
      return true;
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
202
    memset(array->buffer+array->elements*array->size_of_element, 0,
203
           (idx - array->elements)*array->size_of_element);
1 by brian
clean slate
204
    array->elements=idx+1;
205
  }
206
  memcpy(array->buffer+(idx * array->size_of_element),element,
207
	 (size_t) array->size_of_element);
163 by Brian Aker
Merge Monty's code.
208
  return false;
1 by brian
clean slate
209
}
210
211
212
/*
213
  Ensure that dynamic array has enough elements
214
215
  SYNOPSIS
216
    allocate_dynamic()
217
    array
218
    max_elements        Numbers of elements that is needed
219
220
  NOTES
221
   Any new allocated element are NOT initialized
222
223
  RETURN VALUE
163 by Brian Aker
Merge Monty's code.
224
    false	Ok
225
    true	Allocation of new memory failed
1 by brian
clean slate
226
*/
227
482 by Brian Aker
Remove uint.
228
bool allocate_dynamic(DYNAMIC_ARRAY *array, uint32_t max_elements)
1 by brian
clean slate
229
{
230
  if (max_elements >= array->max_element)
231
  {
482 by Brian Aker
Remove uint.
232
    uint32_t size;
481 by Brian Aker
Remove all of uchar.
233
    unsigned char *new_ptr;
1 by brian
clean slate
234
    size= (max_elements + array->alloc_increment)/array->alloc_increment;
235
    size*= array->alloc_increment;
481 by Brian Aker
Remove all of uchar.
236
    if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
237
    {
238
       /*
239
         In this senerio, the buffer is statically preallocated,
240
         so we have to create an all-new malloc since we overflowed
241
       */
656.1.26 by Monty Taylor
Finally removed all of the my_malloc stuff.
242
       if (!(new_ptr= (unsigned char *) malloc(size *
243
                                               array->size_of_element)))
1 by brian
clean slate
244
         return 0;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
245
       memcpy(new_ptr, array->buffer,
1 by brian
clean slate
246
              array->elements * array->size_of_element);
247
     }
248
     else
249
250
656.1.47 by Monty Taylor
More malloc return check fixes.
251
    if (!(new_ptr=(unsigned char*) realloc(array->buffer,
252
                                        size* array->size_of_element)))
163 by Brian Aker
Merge Monty's code.
253
      return true;
1 by brian
clean slate
254
    array->buffer= new_ptr;
255
    array->max_element= size;
256
  }
163 by Brian Aker
Merge Monty's code.
257
  return false;
1 by brian
clean slate
258
}
259
260
261
/*
262
  Get an element from array by given index
263
264
  SYNOPSIS
265
    get_dynamic()
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
266
      array
481 by Brian Aker
Remove all of uchar.
267
      unsigned char*	Element to be returned. If idx > elements contain zeroes.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
268
      idx	Index of element wanted.
1 by brian
clean slate
269
*/
270
482 by Brian Aker
Remove uint.
271
void get_dynamic(DYNAMIC_ARRAY *array, unsigned char* element, uint32_t idx)
1 by brian
clean slate
272
{
273
  if (idx >= array->elements)
274
  {
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
275
    memset(element, 0, array->size_of_element);
1 by brian
clean slate
276
    return;
277
  }
278
  memcpy(element,array->buffer+idx*array->size_of_element,
279
         (size_t) array->size_of_element);
280
}
281
282
283
/*
284
  Empty array by freeing all memory
285
286
  SYNOPSIS
287
    delete_dynamic()
288
      array	Array to be deleted
289
*/
290
291
void delete_dynamic(DYNAMIC_ARRAY *array)
292
{
293
  /*
294
    Just mark as empty if we are using a static buffer
295
  */
481 by Brian Aker
Remove all of uchar.
296
  if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
297
    array->elements= 0;
298
  else
299
  if (array->buffer)
300
  {
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.
301
    free(array->buffer);
1 by brian
clean slate
302
    array->buffer=0;
303
    array->elements=array->max_element=0;
304
  }
305
}
306
307
/*
308
  Delete element by given index
309
310
  SYNOPSIS
311
    delete_dynamic_element()
312
      array
313
      idx        Index of element to be deleted
314
*/
315
482 by Brian Aker
Remove uint.
316
void delete_dynamic_element(DYNAMIC_ARRAY *array, uint32_t idx)
1 by brian
clean slate
317
{
318
  char *ptr= (char*) array->buffer+array->size_of_element*idx;
319
  array->elements--;
320
  memmove(ptr,ptr+array->size_of_element,
321
          (array->elements-idx)*array->size_of_element);
322
}
323
324
325
/*
326
  Free unused memory
327
328
  SYNOPSIS
329
    freeze_size()
330
      array	Array to be freed
331
332
*/
333
334
void freeze_size(DYNAMIC_ARRAY *array)
335
{
482 by Brian Aker
Remove uint.
336
  uint32_t elements=cmax(array->elements,1);
1 by brian
clean slate
337
338
  /*
339
    Do nothing if we are using a static buffer
340
  */
481 by Brian Aker
Remove all of uchar.
341
  if (array->buffer == (unsigned char *)(array + 1))
1 by brian
clean slate
342
    return;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
343
1 by brian
clean slate
344
  if (array->buffer && array->max_element != elements)
345
  {
656.1.26 by Monty Taylor
Finally removed all of the my_malloc stuff.
346
    array->buffer=(unsigned char*) realloc(array->buffer,
347
                                     elements*array->size_of_element);
1 by brian
clean slate
348
    array->max_element=elements;
349
  }
350
}
351
352
353
/*
354
  Get the index of a dynamic element
355
356
  SYNOPSIS
357
    get_index_dynamic()
358
     array	Array
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
359
     element Whose element index
1 by brian
clean slate
360
361
*/
362
481 by Brian Aker
Remove all of uchar.
363
int get_index_dynamic(DYNAMIC_ARRAY *array, unsigned char* element)
1 by brian
clean slate
364
{
482 by Brian Aker
Remove uint.
365
  uint32_t ret;
1 by brian
clean slate
366
  if (array->buffer > element)
367
    return -1;
368
369
  ret= (element - array->buffer) /  array->size_of_element;
370
  if (ret > array->elements)
371
    return -1;
372
373
  return ret;
374
375
}