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 bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint32_t element_size,
00050                             void *init_buffer, uint32_t init_alloc,
00051                             uint32_t alloc_increment)
00052 {
00053   if (!alloc_increment)
00054   {
00055     alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16U);
00056     if (init_alloc > 8 && alloc_increment > init_alloc * 2)
00057       alloc_increment=init_alloc*2;
00058   }
00059 
00060   if (!init_alloc)
00061   {
00062     init_alloc=alloc_increment;
00063     init_buffer= 0;
00064   }
00065   array->set_size(0);
00066   array->max_element=init_alloc;
00067   array->alloc_increment=alloc_increment;
00068   array->size_of_element=element_size;
00069   if ((array->buffer= (unsigned char*) init_buffer))
00070     return(false);
00071   if (!(array->buffer=(unsigned char*) malloc(element_size*init_alloc)))
00072   {
00073     array->max_element=0;
00074     return(true);
00075   }
00076   return(false);
00077 }
00078 
00079 /*
00080   Insert element at the end of array. Allocate memory if needed.
00081 
00082   SYNOPSIS
00083     insert_dynamic()
00084       array
00085       element
00086 
00087   RETURN VALUE
00088     true  Insert failed
00089     false Ok
00090 */
00091 
00092 static void insert_dynamic(DYNAMIC_ARRAY *array, void* element)
00093 {
00094   unsigned char* buffer;
00095   if (array->size() == array->max_element)
00096     buffer= alloc_dynamic(array);
00097   else
00098   {
00099     buffer= array->buffer+(array->size() * array->size_of_element);
00100     array->set_size(array->size() + 1);
00101   }
00102   memcpy(buffer,element, array->size_of_element);
00103 }
00104 
00105 void DYNAMIC_ARRAY::push_back(void* v)
00106 {
00107   insert_dynamic(this, v);
00108 }
00109 
00110 
00111 /*
00112   Alloc space for next element(s)
00113 
00114   SYNOPSIS
00115     alloc_dynamic()
00116       array
00117 
00118   DESCRIPTION
00119     alloc_dynamic() checks if there is empty space for at least
00120     one element if not tries to allocate space for alloc_increment
00121     elements at the end of array.
00122 
00123   RETURN VALUE
00124     pointer Pointer to empty space for element
00125     0   Error
00126 */
00127 
00128 unsigned char *alloc_dynamic(DYNAMIC_ARRAY *array)
00129 {
00130   if (array->size() == array->max_element)
00131   {
00132     char *new_ptr;
00133     if (array->buffer == (unsigned char *)(array + 1))
00134     {
00135       /*
00136         In this senerio, the buffer is statically preallocated,
00137         so we have to create an all-new malloc since we overflowed
00138       */
00139       if (!(new_ptr= (char *) malloc((array->max_element+
00140                                      array->alloc_increment) *
00141                                      array->size_of_element)))
00142         return 0;
00143       memcpy(new_ptr, array->buffer,
00144              array->size() * array->size_of_element);
00145     }
00146     else if (!(new_ptr= (char*) realloc(array->buffer,
00147                                         (array->max_element+
00148                                          array->alloc_increment)*
00149                                         array->size_of_element)))
00150       return 0;
00151     array->buffer= (unsigned char*) new_ptr;
00152     array->max_element+=array->alloc_increment;
00153   }
00154   array->set_size(array->size() + 1);
00155   return array->buffer + ((array->size() - 1) * array->size_of_element);
00156 }
00157 
00158 
00159 /*
00160   Pop last element from array.
00161 
00162   SYNOPSIS
00163     pop_dynamic()
00164       array
00165 
00166   RETURN VALUE
00167     pointer Ok
00168     0   Array is empty
00169 */
00170 
00171 unsigned char *pop_dynamic(DYNAMIC_ARRAY *array)
00172 {
00173   if (!array->size())
00174     return 0;
00175   array->set_size(array->size() - 1);
00176   return array->buffer+(array->size() * array->size_of_element);
00177 }
00178 
00179 /*
00180   Empty array by freeing all memory
00181 
00182   SYNOPSIS
00183     delete_dynamic()
00184       array Array to be deleted
00185 */
00186 
00187 void delete_dynamic(DYNAMIC_ARRAY *array)
00188 {
00189   /*
00190     Just mark as empty if we are using a static buffer
00191   */
00192   if (array->buffer == (unsigned char *)(array + 1))
00193     array->set_size(0);
00194   else
00195   if (array->buffer)
00196   {
00197     free(array->buffer);
00198     array->buffer=0;
00199     array->set_size(array->max_element=0);
00200   }
00201 }
00202 
00203 } /* namespace drizzled */