/* $Id: dynarray.c 1462 2005-08-21 08:52:06Z mipsator $ */
/*
* Copyright (c) 2003-2005 Damien Couderc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* - Neither the name of the copyright holder(s) nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Credits for patches :
* - Ted Unangst
*/
/*******************************************************************
* *
* Dynamic Array *
* *
* Simulate an array of string with a variable size. *
* *
*******************************************************************/
#include <stdlib.h>
#include "compat/pmk_stdio.h"
#include "compat/pmk_string.h"
#include "dynarray.h"
/*****************
* da_init_adv() *
***********************************************************************
DESCR
Initialise dynamic array and provide specific free function
IN
freefunc : free function
OUT
returns pointer of dynamic array
***********************************************************************/
dynary *da_init_adv(void (*freefunc)(void *)) {
dynary *da = NULL;
da = (dynary *)malloc(sizeof(dynary));
if (da != NULL) {
da->nbcell = 0;
da->nextidx = 0;
da->pary = malloc(DYNARY_AUTO_GROW * sizeof(void *));
if (freefunc != NULL) {
da->freeobj = freefunc;
} else {
da->freeobj = free;
}
}
return(da);
}
/*************
* da_init() *
***********************************************************************
DESCR
Initialise dynamic array
IN
NONE
OUT
returns pointer of dynamic array
***********************************************************************/
dynary *da_init(void) {
return(da_init_adv(NULL));
}
/****************
* da_destroy() *
***********************************************************************
DESCR
destroy dynamic array
IN
da : dynamic array to destroy
OUT
NONE
***********************************************************************/
void da_destroy(dynary *da) {
int i;
if (da != NULL) {
for (i = 0 ; i < da->nextidx ; i++) {
da->freeobj(da->pary[i]);
}
free(da->pary);
free(da);
}
}
/***************
* da_resize() *
***********************************************************************
DESCR
Resize the array to the given size
IN
da : array to resize
nsize : new size
OUT
return : boolean
***********************************************************************/
bool da_resize(dynary *da, size_t nsize) {
void **tary;
if (da == NULL)
return(false);
tary = realloc(da->pary, nsize * sizeof(void *));
if (tary != NULL) {
da->pary = tary;
da->nbcell = nsize;
return(true);
} else {
return(false);
}
}
/*************
* da_size() *
***********************************************************************
DESCR
Get the size of the array
IN
NONE
OUT
returns number of cell of the array
***********************************************************************/
size_t da_size(dynary *da) {
if (da == NULL)
abort(); /* shouldn't happen */
return((size_t) da->nbcell);
}
/**************
* da_usize() *
***********************************************************************
DESCR
Get the 'used' size of the array
IN
NONE
OUT
returns the number of 'used' cells
***********************************************************************/
size_t da_usize(dynary *da) {
if (da == NULL)
abort(); /* shouldn't happen */
return((size_t) da->nextidx);
}
/*************
* da_push() *
***********************************************************************
DESCR
Add a new value at the end of the array
IN
da : dynamic array
pval : string to append
OUT
return : boolean
***********************************************************************/
bool da_push(dynary *da, void *pval) {
size_t gsize;
if (da == NULL)
return(false);
if (da->nbcell == da->nextidx) {
/* compute growing size */
gsize = (da->nbcell + DYNARY_AUTO_GROW);
if (da_resize(da, gsize) == false) {
/* cannot resize dynary */
return(false);
}
}
/* insert in last place */
da->pary[da->nextidx] = pval;
da->nextidx++;
return(true);
}
/************
* da_pop() *
***********************************************************************
DESCR
Pop the last value of the array
IN
da : dynamic array
OUT
return : the last element or NULL
***********************************************************************/
void *da_pop(dynary *da) {
void *p;
size_t gsize;
if (da == NULL)
return(NULL);
if (da->nextidx == 0) {
/* empty */
return(NULL);
}
da->nextidx--;
p = da->pary[da->nextidx];
da->pary[da->nextidx] = NULL;
/* resize if allocated space is too big */
if ((da->nbcell - da->nextidx) > DYNARY_AUTO_GROW) {
gsize = da->nbcell - DYNARY_AUTO_GROW;
if (da_resize(da, gsize) == false) {
/* cannot resize dynary */
return (NULL);
}
}
return(p);
}
/**************
* da_shift() *
***********************************************************************
DESCR
Pop the first value and shift the array
IN
da : dynamic array
OUT
return : the first cell
***********************************************************************/
void *da_shift(dynary *da) {
void *p;
int i;
size_t gsize;
if (da == NULL)
return(NULL);
if (da->nextidx == 0) {
/* empty */
return(NULL);
}
p = da->pary[0];
da->nextidx--;
/* shift remaining values */
for (i = 0 ; i < da->nextidx ; i++) {
da->pary[i] = da->pary[i+1];
}
/* clear previous latest element */
da->pary[da->nextidx] = NULL;
/* resize if allocated space is too big */
if ((da->nbcell - da->nextidx) > DYNARY_AUTO_GROW) {
gsize = da->nbcell - DYNARY_AUTO_GROW;
if (da_resize(da, gsize) == false) {
/* cannot resize dynary */
return (NULL);
}
}
return(p);
}
/************
* da_idx() *
***********************************************************************
DESCR
Get a value
IN
da : dynamic array
idx : index of the wanted value
OUT
returns value or NULL
***********************************************************************/
void *da_idx(dynary *da, int idx) {
if (da == NULL)
return(NULL);
if (idx >= da->nextidx) {
return(NULL);
}
return(da->pary[idx]);
}
/*************
* da_find() *
***********************************************************************
DESCR
try to find an element in the given dynary
IN
da : dynary structure
str : string to find
OUT
boolean relative to the result of the search
NOTE : this only work with dynaries intialised with da_init()
***********************************************************************/
bool da_find(dynary *da, char *str) {
bool rslt = false;
size_t i,
s;
/* compute size of string including the delimiter */
s = strlen(str) + 1;
/* for each item of the dynary */
for (i = 0 ; i < da_usize(da) ; i++) {
/* check if equal to the string */
if (strncmp(str, da_idx(da, i), s) == 0) {
/* and set the flag if true */
rslt = true;
break;
}
}
return(rslt);
}
/*************
* da_sort() *
***********************************************************************
DESCR
sort the dynary
IN
da : dynary structure
OUT
NONE
NOTE : this only work with dynaries intialised with da_init()
***********************************************************************/
static int da_strcmp(const void *a, const void *b) {
return(strcmp(*(char * const *)a, *(char * const *) b));
}
void da_sort(dynary *da) {
qsort((void *) da->pary, da->nextidx, sizeof(char *), da_strcmp);
}
syntax highlighted by Code2HTML, v. 0.9.1