mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			281 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Copyright (C) 2000 MySQL AB
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation; either version 2 of the License, or
 | 
						|
   (at your option) any later version.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 | 
						|
 | 
						|
/* Handling of arrays that can grow dynamicly. */
 | 
						|
 | 
						|
#if defined(WIN32) || defined(__WIN__)
 | 
						|
#undef SAFEMALLOC				/* Problems with threads */
 | 
						|
#endif
 | 
						|
 | 
						|
#include "mysys_priv.h"
 | 
						|
#include "m_string.h"
 | 
						|
 | 
						|
/*
 | 
						|
  Initiate dynamic array
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    init_dynamic_array()
 | 
						|
      array		Pointer to an array
 | 
						|
      element_size	Size of element
 | 
						|
      init_alloc	Number of initial elements
 | 
						|
      alloc_increment	Increment for adding new elements
 | 
						|
 | 
						|
  DESCRIPTION
 | 
						|
    init_dynamic_array() initiates array and allocate space for 
 | 
						|
    init_alloc eilements. 
 | 
						|
    Array is usable even if space allocation failed.
 | 
						|
 | 
						|
  RETURN VALUE
 | 
						|
    TRUE	my_malloc_ci() failed
 | 
						|
    FALSE	Ok
 | 
						|
*/
 | 
						|
 | 
						|
my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
 | 
						|
			    uint init_alloc,
 | 
						|
			    uint alloc_increment CALLER_INFO_PROTO)
 | 
						|
{
 | 
						|
  DBUG_ENTER("init_dynamic_array");
 | 
						|
  if (!alloc_increment)
 | 
						|
  {
 | 
						|
    alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16);
 | 
						|
    if (init_alloc > 8 && alloc_increment > init_alloc * 2)
 | 
						|
      alloc_increment=init_alloc*2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!init_alloc)
 | 
						|
    init_alloc=alloc_increment;
 | 
						|
  array->elements=0;
 | 
						|
  array->max_element=init_alloc;
 | 
						|
  array->alloc_increment=alloc_increment;
 | 
						|
  array->size_of_element=element_size;
 | 
						|
  if (!(array->buffer=(char*) my_malloc_ci(element_size*init_alloc,MYF(MY_WME))))
 | 
						|
  {
 | 
						|
    array->max_element=0;
 | 
						|
    DBUG_RETURN(TRUE);
 | 
						|
  }
 | 
						|
  DBUG_RETURN(FALSE);
 | 
						|
} 
 | 
						|
 | 
						|
/*
 | 
						|
  Insert element at the end of array. Allocate memory if needed.
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    insert_dynamic()
 | 
						|
      array
 | 
						|
      element
 | 
						|
 | 
						|
  RETURN VALUE
 | 
						|
    TRUE	Insert failed
 | 
						|
    FALSE	Ok
 | 
						|
*/
 | 
						|
 | 
						|
my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element)
 | 
						|
{
 | 
						|
  gptr buffer;
 | 
						|
  if (array->elements == array->max_element)
 | 
						|
  {						/* Call only when nessesary */
 | 
						|
    if (!(buffer=alloc_dynamic(array)))
 | 
						|
      return TRUE;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    buffer=array->buffer+(array->elements * array->size_of_element);
 | 
						|
    array->elements++;
 | 
						|
  }
 | 
						|
  memcpy(buffer,element,(size_t) array->size_of_element);
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Alloc space for next element(s) 
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    alloc_dynamic()
 | 
						|
      array
 | 
						|
 | 
						|
  DESCRIPTION
 | 
						|
    alloc_dynamic() checks if there is empty space for at least
 | 
						|
    one element if not tries to allocate space for alloc_increment
 | 
						|
    elements at the end of array.
 | 
						|
 | 
						|
  RETURN VALUE
 | 
						|
    pointer	Pointer to empty space for element
 | 
						|
    0		Error
 | 
						|
*/
 | 
						|
 | 
						|
byte *alloc_dynamic(DYNAMIC_ARRAY *array)
 | 
						|
{
 | 
						|
  if (array->elements == array->max_element)
 | 
						|
  {
 | 
						|
    char *new_ptr;
 | 
						|
    if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+
 | 
						|
				     array->alloc_increment)*
 | 
						|
				     array->size_of_element,
 | 
						|
				     MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
 | 
						|
      return 0;
 | 
						|
    array->buffer=new_ptr;
 | 
						|
    array->max_element+=array->alloc_increment;
 | 
						|
  }
 | 
						|
  return array->buffer+(array->elements++ * array->size_of_element);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Pop last element from array.
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    pop_dynamic()
 | 
						|
      array
 | 
						|
  
 | 
						|
  RETURN VALUE    
 | 
						|
    pointer	Ok
 | 
						|
    0		Array is empty
 | 
						|
*/
 | 
						|
 | 
						|
byte *pop_dynamic(DYNAMIC_ARRAY *array)
 | 
						|
{
 | 
						|
  if (array->elements)
 | 
						|
    return array->buffer+(--array->elements * array->size_of_element);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Replace elemnent in array with given element and index
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    set_dynamic()
 | 
						|
      array
 | 
						|
      element	Element to be inserted
 | 
						|
      idx	Index where element is to be inserted
 | 
						|
 | 
						|
  DESCRIPTION
 | 
						|
    set_dynamic() replaces element in array. 
 | 
						|
    If idx > max_element insert new element. Allocate memory if needed. 
 | 
						|
 
 | 
						|
  RETURN VALUE
 | 
						|
    TRUE	Idx was out of range and allocation of new memory failed
 | 
						|
    FALSE	Ok
 | 
						|
*/
 | 
						|
 | 
						|
my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx)
 | 
						|
{
 | 
						|
  if (idx >= array->elements)
 | 
						|
  {
 | 
						|
    if (idx >= array->max_element)
 | 
						|
    {
 | 
						|
      uint size;
 | 
						|
      char *new_ptr;
 | 
						|
      size=(idx+array->alloc_increment)/array->alloc_increment;
 | 
						|
      size*= array->alloc_increment;
 | 
						|
      if (!(new_ptr=(char*) my_realloc(array->buffer,size*
 | 
						|
				       array->size_of_element,
 | 
						|
				       MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
 | 
						|
	return TRUE;
 | 
						|
      array->buffer=new_ptr;
 | 
						|
      array->max_element=size;
 | 
						|
    }
 | 
						|
    bzero((gptr) (array->buffer+array->elements*array->size_of_element),
 | 
						|
	  (idx - array->elements)*array->size_of_element);
 | 
						|
    array->elements=idx+1;
 | 
						|
  }
 | 
						|
  memcpy(array->buffer+(idx * array->size_of_element),element,
 | 
						|
	 (size_t) array->size_of_element);
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Get an element from array by given index
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    get_dynamic()
 | 
						|
      array	
 | 
						|
      gptr	Element to be returned. If idx > elements contain zeroes.
 | 
						|
      idx	Index of element wanted. 
 | 
						|
*/
 | 
						|
 | 
						|
void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx)
 | 
						|
{
 | 
						|
  if (idx >= array->elements)
 | 
						|
  {
 | 
						|
    DBUG_PRINT("warning",("To big array idx: %d, array size is %d",
 | 
						|
			  idx,array->elements));
 | 
						|
    bzero(element,array->size_of_element);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  memcpy(element,array->buffer+idx*array->size_of_element,
 | 
						|
	 (size_t) array->size_of_element);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Empty array by freeing all memory
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    delete_dynamic()
 | 
						|
      array	Array to be deleted
 | 
						|
*/
 | 
						|
 | 
						|
void delete_dynamic(DYNAMIC_ARRAY *array)
 | 
						|
{
 | 
						|
  if (array->buffer)
 | 
						|
  {
 | 
						|
    my_free(array->buffer,MYF(MY_WME));
 | 
						|
    array->buffer=0;
 | 
						|
    array->elements=array->max_element=0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
  Delete element by given index
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    delete_dynamic_element()
 | 
						|
      array
 | 
						|
      idx	Index of element to be deleted
 | 
						|
*/
 | 
						|
 | 
						|
void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
 | 
						|
{
 | 
						|
  char *ptr=array->buffer+array->size_of_element*idx;
 | 
						|
  array->elements--;
 | 
						|
  memmove(ptr,ptr+array->size_of_element,
 | 
						|
	  (array->elements-idx)*array->size_of_element);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Free unused memory
 | 
						|
 | 
						|
  SYNOPSIS
 | 
						|
    freeze_size()
 | 
						|
      array	Array to be freed
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
void freeze_size(DYNAMIC_ARRAY *array)
 | 
						|
{
 | 
						|
  uint elements=max(array->elements,1);
 | 
						|
 | 
						|
  if (array->buffer && array->max_element != elements)
 | 
						|
  {
 | 
						|
    array->buffer=(char*) my_realloc(array->buffer,
 | 
						|
				     elements*array->size_of_element,
 | 
						|
				     MYF(MY_WME));
 | 
						|
    array->max_element=elements;
 | 
						|
  }
 | 
						|
}
 |