mirror of
https://github.com/MariaDB/server.git
synced 2025-01-23 23:34:34 +01:00
7cb8a33b1a
into sergbook.mysql.com:/usr/home/serg/Abk/mysql-5.1-wl2936 client/mysql.cc: Auto merged include/my_global.h: Auto merged include/my_sys.h: Auto merged include/mysql.h: Auto merged mysql-test/r/im_utils.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/ndb_dd_basic.test: Auto merged mysql-test/t/partition_innodb.test: Auto merged mysql-test/t/variables.test: Auto merged mysys/array.c: Auto merged mysys/typelib.c: Auto merged sql/event_queue.cc: Auto merged sql/ha_partition.cc: Auto merged sql/ha_partition.h: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item_func.cc: Auto merged sql/item_sum.cc: Auto merged sql/log.cc: Auto merged sql/mysql_priv.h: Auto merged sql/set_var.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_delete.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_partition.cc: Auto merged sql/sql_plugin.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/table.cc: Auto merged sql/table.h: Auto merged storage/example/ha_example.cc: Auto merged storage/federated/ha_federated.cc: Auto merged storage/heap/ha_heap.cc: Auto merged storage/innobase/include/trx0trx.h: Auto merged storage/myisam/ha_myisam.cc: Auto merged storage/myisammrg/ha_myisammrg.cc: Auto merged storage/ndb/src/mgmsrv/InitConfigFileParser.cpp: Auto merged include/typelib.h: merged mysql-test/mysql-test-run.pl: merged mysql-test/r/flush2.result: merged mysql-test/r/ndb_dd_basic.result: merged mysql-test/r/partition_innodb.result: merged mysql-test/r/ps_1general.result: merged mysql-test/t/ps_1general.test: merged sql/ha_ndbcluster.cc: merged sql/item_create.cc: merged sql/mysqld.cc: merged sql/rpl_utility.h: merged sql/set_var.cc: merged sql/sql_class.cc: merged sql/sql_yacc.yy: merged storage/innobase/handler/ha_innodb.cc: merged storage/innobase/handler/ha_innodb.h: merged
356 lines
8.4 KiB
C
356 lines
8.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; version 2 of the License.
|
|
|
|
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. */
|
|
|
|
#include "mysys_priv.h"
|
|
#include "m_string.h"
|
|
|
|
/*
|
|
Initiate dynamic array
|
|
|
|
SYNOPSIS
|
|
init_dynamic_array2()
|
|
array Pointer to an array
|
|
element_size Size of element
|
|
init_buffer Initial buffer pointer
|
|
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.
|
|
Static buffers must begin immediately after the array structure.
|
|
|
|
RETURN VALUE
|
|
TRUE my_malloc_ci() failed
|
|
FALSE Ok
|
|
*/
|
|
|
|
my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
|
|
void *init_buffer, 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;
|
|
init_buffer= 0;
|
|
}
|
|
array->elements=0;
|
|
array->max_element=init_alloc;
|
|
array->alloc_increment=alloc_increment;
|
|
array->size_of_element=element_size;
|
|
if ((array->buffer= init_buffer))
|
|
DBUG_RETURN(FALSE);
|
|
if (!(array->buffer=(char*) my_malloc_ci(element_size*init_alloc,MYF(MY_WME))))
|
|
{
|
|
array->max_element=0;
|
|
DBUG_RETURN(TRUE);
|
|
}
|
|
DBUG_RETURN(FALSE);
|
|
}
|
|
|
|
my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
|
|
uint init_alloc,
|
|
uint alloc_increment CALLER_INFO_PROTO)
|
|
{
|
|
/* placeholder to preserve ABI */
|
|
return my_init_dynamic_array_ci(array, element_size, init_alloc,
|
|
alloc_increment);
|
|
}
|
|
/*
|
|
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 (array->buffer == (char *)(array + 1))
|
|
{
|
|
/*
|
|
In this senerio, the buffer is statically preallocated,
|
|
so we have to create an all-new malloc since we overflowed
|
|
*/
|
|
if (!(new_ptr= (char *) my_malloc((array->max_element+
|
|
array->alloc_increment) *
|
|
array->size_of_element,
|
|
MYF(MY_WME))))
|
|
return 0;
|
|
memcpy(new_ptr, array->buffer,
|
|
array->elements * array->size_of_element);
|
|
}
|
|
else
|
|
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 (array->buffer == (char *)(array + 1))
|
|
{
|
|
/*
|
|
In this senerio, the buffer is statically preallocated,
|
|
so we have to create an all-new malloc since we overflowed
|
|
*/
|
|
if (!(new_ptr= (char *) my_malloc(size *
|
|
array->size_of_element,
|
|
MYF(MY_WME))))
|
|
return 0;
|
|
memcpy(new_ptr, array->buffer,
|
|
array->elements * array->size_of_element);
|
|
}
|
|
else
|
|
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)
|
|
{
|
|
/*
|
|
Just mark as empty if we are using a static buffer
|
|
*/
|
|
if (array->buffer == (char *)(array + 1))
|
|
array->elements= 0;
|
|
else
|
|
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);
|
|
|
|
/*
|
|
Do nothing if we are using a static buffer
|
|
*/
|
|
if (array->buffer == (char *)(array + 1))
|
|
return;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Get the index of a dynamic element
|
|
|
|
SYNOPSIS
|
|
get_index_dynamic()
|
|
array Array
|
|
element Whose element index
|
|
|
|
*/
|
|
|
|
int get_index_dynamic(DYNAMIC_ARRAY *array, gptr element)
|
|
{
|
|
uint ret;
|
|
if (array->buffer > element)
|
|
return -1;
|
|
|
|
ret= (element - array->buffer) / array->size_of_element;
|
|
if (ret > array->elements)
|
|
return -1;
|
|
|
|
return ret;
|
|
|
|
}
|