Drizzled Public API Documentation

dynamic_array.cc
00001 /* Copyright (C) 2000 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /* Handling of arrays that can grow dynamicly. */
00017 
00018 #include <config.h>
00019 #include <algorithm>
00020 #include <drizzled/dynamic_array.h>
00021 #include <drizzled/internal/my_sys.h>
00022 
00023 using namespace std;
00024 
00025 namespace drizzled {
00026 
00027 /*
00028   Initiate dynamic array
00029 
00030   SYNOPSIS
00031     init_dynamic_array2()
00032       array   Pointer to an array
00033       element_size  Size of element
00034       init_buffer       Initial buffer pointer
00035       init_alloc  Number of initial elements
00036       alloc_increment Increment for adding new elements
00037 
00038   DESCRIPTION
00039     init_dynamic_array() initiates array and allocate space for
00040     init_alloc eilements.
00041     Array is usable even if space allocation failed.
00042     Static buffers must begin immediately after the array structure.
00043 
00044   RETURN VALUE
00045     true  malloc() failed
00046     false Ok
00047 */
00048 
00049 static void init_dynamic_array2(DYNAMIC_ARRAY* array, uint32_t element_size, uint32_t init_alloc, uint32_t alloc_increment)
00050 {
00051   if (!alloc_increment)
00052   {
00053     alloc_increment= max((8192 - MALLOC_OVERHEAD) / element_size, 16U);
00054     if (init_alloc > 8 && alloc_increment > init_alloc * 2)
00055       alloc_increment= init_alloc * 2;
00056   }
00057   if (not init_alloc)
00058     init_alloc= alloc_increment;
00059   array->set_size(0);
00060   array->max_element= init_alloc;
00061   array->alloc_increment= alloc_increment;
00062   array->size_of_element= element_size;
00063   array->buffer= (unsigned char*) malloc(element_size * init_alloc);
00064 }
00065 
00066 void DYNAMIC_ARRAY::init(uint32_t element_size, uint32_t init_alloc, uint32_t alloc_increment0)
00067 {
00068   init_dynamic_array2(this, element_size, init_alloc, alloc_increment0);
00069 }
00070 
00071 /*
00072   Insert element at the end of array. Allocate memory if needed.
00073 
00074   SYNOPSIS
00075     insert_dynamic()
00076       array
00077       element
00078 
00079   RETURN VALUE
00080     true  Insert failed
00081     false Ok
00082 */
00083 
00084 static void insert_dynamic(DYNAMIC_ARRAY* array, void* element)
00085 {
00086   unsigned char* buffer;
00087   if (array->size() == array->max_element)
00088     buffer= array->alloc();
00089   else
00090   {
00091     buffer= array->buffer+(array->size() * array->size_of_element);
00092     array->set_size(array->size() + 1);
00093   }
00094   memcpy(buffer,element, array->size_of_element);
00095 }
00096 
00097 void DYNAMIC_ARRAY::push_back(void* v)
00098 {
00099   insert_dynamic(this, v);
00100 }
00101 
00102 
00103 /*
00104   Alloc space for next element(s)
00105 
00106   SYNOPSIS
00107     alloc_dynamic()
00108       array
00109 
00110   DESCRIPTION
00111     alloc_dynamic() checks if there is empty space for at least
00112     one element if not tries to allocate space for alloc_increment
00113     elements at the end of array.
00114 
00115   RETURN VALUE
00116     pointer Pointer to empty space for element
00117     0   Error
00118 */
00119 
00120 static unsigned char* alloc_dynamic(DYNAMIC_ARRAY* array)
00121 {
00122   if (array->size() == array->max_element)
00123   {
00124     char* new_ptr;
00125     if (array->buffer == (unsigned char*)(array + 1))
00126     {
00127       /*
00128         In this senerio, the buffer is statically preallocated,
00129         so we have to create an all-new malloc since we overflowed
00130       */
00131       new_ptr= (char*) malloc((array->max_element + array->alloc_increment) * array->size_of_element);
00132       memcpy(new_ptr, array->buffer, array->size() * array->size_of_element);
00133     }
00134     else 
00135       new_ptr= (char*) realloc(array->buffer, (array->max_element + array->alloc_increment) * array->size_of_element);
00136     array->buffer= (unsigned char*) new_ptr;
00137     array->max_element+=array->alloc_increment;
00138   }
00139   array->set_size(array->size() + 1);
00140   return array->buffer + ((array->size() - 1) * array->size_of_element);
00141 }
00142 
00143 unsigned char* DYNAMIC_ARRAY::alloc()
00144 {
00145   return alloc_dynamic(this);
00146 }
00147 
00148 /*
00149   Empty array by freeing all memory
00150 
00151   SYNOPSIS
00152     delete_dynamic()
00153       array Array to be deleted
00154 */
00155 
00156 static void delete_dynamic(DYNAMIC_ARRAY* array)
00157 {
00158   /*
00159     Just mark as empty if we are using a static buffer
00160   */
00161   if (array->buffer == (unsigned char*)(array + 1))
00162     array->set_size(0);
00163   else if (array->buffer)
00164   {
00165     free(array->buffer);
00166     array->buffer=0;
00167     array->set_size(array->max_element=0);
00168   }
00169 }
00170 
00171 void DYNAMIC_ARRAY::free()
00172 {
00173   delete_dynamic(this);
00174 }
00175 
00176 } /* namespace drizzled */