Drizzled Public API Documentation

dynamic_array.cc
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /* Handling of arrays that can grow dynamicly. */
17 
18 #include <config.h>
19 #include <algorithm>
20 #include <drizzled/dynamic_array.h>
21 #include <drizzled/internal/my_sys.h>
22 
23 using namespace std;
24 
25 namespace drizzled {
26 
27 /*
28  Initiate dynamic array
29 
30  SYNOPSIS
31  init_dynamic_array2()
32  array Pointer to an array
33  element_size Size of element
34  init_buffer Initial buffer pointer
35  init_alloc Number of initial elements
36  alloc_increment Increment for adding new elements
37 
38  DESCRIPTION
39  init_dynamic_array() initiates array and allocate space for
40  init_alloc eilements.
41  Array is usable even if space allocation failed.
42  Static buffers must begin immediately after the array structure.
43 
44  RETURN VALUE
45  true malloc() failed
46  false Ok
47 */
48 
49 static void init_dynamic_array2(DYNAMIC_ARRAY* array, uint32_t element_size, uint32_t init_alloc, uint32_t alloc_increment)
50 {
51  if (!alloc_increment)
52  {
53  alloc_increment= max((8192 - MALLOC_OVERHEAD) / element_size, 16U);
54  if (init_alloc > 8 && alloc_increment > init_alloc * 2)
55  alloc_increment= init_alloc * 2;
56  }
57  if (not init_alloc)
58  init_alloc= alloc_increment;
59  array->set_size(0);
60  array->max_element= init_alloc;
61  array->alloc_increment= alloc_increment;
62  array->size_of_element= element_size;
63  array->buffer= (unsigned char*) malloc(element_size * init_alloc);
64 }
65 
66 void DYNAMIC_ARRAY::init(uint32_t element_size, uint32_t init_alloc, uint32_t alloc_increment0)
67 {
68  init_dynamic_array2(this, element_size, init_alloc, alloc_increment0);
69 }
70 
71 /*
72  Insert element at the end of array. Allocate memory if needed.
73 
74  SYNOPSIS
75  insert_dynamic()
76  array
77  element
78 
79  RETURN VALUE
80  true Insert failed
81  false Ok
82 */
83 
84 static void insert_dynamic(DYNAMIC_ARRAY* array, void* element)
85 {
86  unsigned char* buffer;
87  if (array->size() == array->max_element)
88  buffer= array->alloc();
89  else
90  {
91  buffer= array->buffer+(array->size() * array->size_of_element);
92  array->set_size(array->size() + 1);
93  }
94  memcpy(buffer,element, array->size_of_element);
95 }
96 
97 void DYNAMIC_ARRAY::push_back(void* v)
98 {
99  insert_dynamic(this, v);
100 }
101 
102 
103 /*
104  Alloc space for next element(s)
105 
106  SYNOPSIS
107  alloc_dynamic()
108  array
109 
110  DESCRIPTION
111  alloc_dynamic() checks if there is empty space for at least
112  one element if not tries to allocate space for alloc_increment
113  elements at the end of array.
114 
115  RETURN VALUE
116  pointer Pointer to empty space for element
117  0 Error
118 */
119 
120 static unsigned char* alloc_dynamic(DYNAMIC_ARRAY* array)
121 {
122  if (array->size() == array->max_element)
123  {
124  char* new_ptr;
125  if (array->buffer == (unsigned char*)(array + 1))
126  {
127  /*
128  In this senerio, the buffer is statically preallocated,
129  so we have to create an all-new malloc since we overflowed
130  */
131  new_ptr= (char*) malloc((array->max_element + array->alloc_increment) * array->size_of_element);
132  memcpy(new_ptr, array->buffer, array->size() * array->size_of_element);
133  }
134  else
135  new_ptr= (char*) realloc(array->buffer, (array->max_element + array->alloc_increment) * array->size_of_element);
136  array->buffer= (unsigned char*) new_ptr;
137  array->max_element+=array->alloc_increment;
138  }
139  array->set_size(array->size() + 1);
140  return array->buffer + ((array->size() - 1) * array->size_of_element);
141 }
142 
143 unsigned char* DYNAMIC_ARRAY::alloc()
144 {
145  return alloc_dynamic(this);
146 }
147 
148 /*
149  Empty array by freeing all memory
150 
151  SYNOPSIS
152  delete_dynamic()
153  array Array to be deleted
154 */
155 
156 static void delete_dynamic(DYNAMIC_ARRAY* array)
157 {
158  /*
159  Just mark as empty if we are using a static buffer
160  */
161  if (array->buffer == (unsigned char*)(array + 1))
162  array->set_size(0);
163  else if (array->buffer)
164  {
165  free(array->buffer);
166  array->buffer=0;
167  array->set_size(array->max_element=0);
168  }
169 }
170 
171 void DYNAMIC_ARRAY::free()
172 {
173  delete_dynamic(this);
174 }
175 
176 } /* namespace drizzled */