mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2024-11-28 09:33:54 +02:00
197 lines
3.8 KiB
C
197 lines
3.8 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* parray.c: pointer array collection.
|
|
*
|
|
* Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "pg_probackup.h"
|
|
|
|
/* members of struct parray are hidden from client. */
|
|
struct parray
|
|
{
|
|
void **data; /* poiter array, expanded if necessary */
|
|
size_t alloced; /* number of elements allocated */
|
|
size_t used; /* number of elements in use */
|
|
};
|
|
|
|
/*
|
|
* Create new parray object.
|
|
* Never returns NULL.
|
|
*/
|
|
parray *
|
|
parray_new(void)
|
|
{
|
|
parray *a = pgut_new(parray);
|
|
|
|
a->data = NULL;
|
|
a->used = 0;
|
|
a->alloced = 0;
|
|
|
|
parray_expand(a, 1024);
|
|
|
|
return a;
|
|
}
|
|
|
|
/*
|
|
* Expand array pointed by data to newsize.
|
|
* Elements in expanded area are initialized to NULL.
|
|
* Note: never returns NULL.
|
|
*/
|
|
void
|
|
parray_expand(parray *array, size_t newsize)
|
|
{
|
|
void **p;
|
|
|
|
/* already allocated */
|
|
if (newsize <= array->alloced)
|
|
return;
|
|
|
|
p = pgut_realloc(array->data, sizeof(void *) * newsize);
|
|
|
|
/* initialize expanded area to NULL */
|
|
memset(p + array->alloced, 0, (newsize - array->alloced) * sizeof(void *));
|
|
|
|
array->alloced = newsize;
|
|
array->data = p;
|
|
}
|
|
|
|
void
|
|
parray_free(parray *array)
|
|
{
|
|
if (array == NULL)
|
|
return;
|
|
free(array->data);
|
|
free(array);
|
|
}
|
|
|
|
void
|
|
parray_append(parray *array, void *elem)
|
|
{
|
|
if (array->used + 1 > array->alloced)
|
|
parray_expand(array, array->alloced * 2);
|
|
|
|
array->data[array->used++] = elem;
|
|
}
|
|
|
|
void
|
|
parray_insert(parray *array, size_t index, void *elem)
|
|
{
|
|
if (array->used + 1 > array->alloced)
|
|
parray_expand(array, array->alloced * 2);
|
|
|
|
memmove(array->data + index + 1, array->data + index,
|
|
(array->alloced - index - 1) * sizeof(void *));
|
|
array->data[index] = elem;
|
|
|
|
/* adjust used count */
|
|
if (array->used < index + 1)
|
|
array->used = index + 1;
|
|
else
|
|
array->used++;
|
|
}
|
|
|
|
/*
|
|
* Concatinate two parray.
|
|
* parray_concat() appends the copy of the content of src to the end of dest.
|
|
*/
|
|
parray *
|
|
parray_concat(parray *dest, const parray *src)
|
|
{
|
|
/* expand head array */
|
|
parray_expand(dest, dest->used + src->used);
|
|
|
|
/* copy content of src after content of dest */
|
|
memcpy(dest->data + dest->used, src->data, src->used * sizeof(void *));
|
|
dest->used += parray_num(src);
|
|
|
|
return dest;
|
|
}
|
|
|
|
void
|
|
parray_set(parray *array, size_t index, void *elem)
|
|
{
|
|
if (index > array->alloced - 1)
|
|
parray_expand(array, index + 1);
|
|
|
|
array->data[index] = elem;
|
|
|
|
/* adjust used count */
|
|
if (array->used < index + 1)
|
|
array->used = index + 1;
|
|
}
|
|
|
|
void *
|
|
parray_get(const parray *array, size_t index)
|
|
{
|
|
if (index > array->alloced - 1)
|
|
return NULL;
|
|
return array->data[index];
|
|
}
|
|
|
|
void *
|
|
parray_remove(parray *array, size_t index)
|
|
{
|
|
void *val;
|
|
|
|
/* removing unused element */
|
|
if (index > array->used)
|
|
return NULL;
|
|
|
|
val = array->data[index];
|
|
|
|
/* Do not move if the last element was removed. */
|
|
if (index < array->alloced - 1)
|
|
memmove(array->data + index, array->data + index + 1,
|
|
(array->alloced - index - 1) * sizeof(void *));
|
|
|
|
/* adjust used count */
|
|
array->used--;
|
|
|
|
return val;
|
|
}
|
|
|
|
bool
|
|
parray_rm(parray *array, const void *key, int(*compare)(const void *, const void *))
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < array->used; i++)
|
|
{
|
|
if (compare(&key, &array->data[i]) == 0)
|
|
{
|
|
parray_remove(array, i);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
size_t
|
|
parray_num(const parray *array)
|
|
{
|
|
return array->used;
|
|
}
|
|
|
|
void
|
|
parray_qsort(parray *array, int(*compare)(const void *, const void *))
|
|
{
|
|
qsort(array->data, array->used, sizeof(void *), compare);
|
|
}
|
|
|
|
void
|
|
parray_walk(parray *array, void (*action)(void *))
|
|
{
|
|
int i;
|
|
for (i = 0; i < array->used; i++)
|
|
action(array->data[i]);
|
|
}
|
|
|
|
void *
|
|
parray_bsearch(parray *array, const void *key, int(*compare)(const void *, const void *))
|
|
{
|
|
return bsearch(&key, array->data, array->used, sizeof(void *), compare);
|
|
}
|