You've already forked pg_probackup
							
							
				mirror of
				https://github.com/postgrespro/pg_probackup.git
				synced 2025-10-31 00:17:52 +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);
 | |
| }
 |