/*----------------------------------------darray.c-------------------------*/
#include "darray.h"
#define ARRAY_HEAD 0
#define ARRAY_TAIL -1
#define MIN_PRE_ALLOCATE_NR 10
struct _DArray
{
void** data;
size_t size;
size_t alloc_size;
void* data_destroy_ctx;
DataDestroyFunc data_destroy;
};
DArray* darray_create(DataDestroyFunc data_destroy, void* ctx)
{
DArray* this = (DArray*)malloc(sizeof(DArray));
if(NULL == this)
{
return NULL;
}
this->data = NULL;
this->size = 0;
this->alloc_size = 0;
this->data_destroy = data_destroy;
this->data_destroy_ctx = ctx;
return this;
}
static Ret darray_expand(DArray* this, size_t need)
{
return_val_if_fail(this != NULL, RET_INVALID_PARAMETER);
if(this->size + need > this->alloc_size)
{
size_t alloc_size = this->alloc_size + (this->alloc_size >> 1)
+ MIN_PRE_ALLOCATE_NR;
void** data = (void **)realloc(this->data, sizeof(void*) * alloc_size);
if(NULL != data)
{
this->data = data;
this->alloc_size = alloc_size;
}
}
return ((this->size + need) <= this->alloc_size) ? RET_OK : RET_FAIL;
}
Ret darray_insert(DArray* this, size_t index, void* data)
{
Ret ret = RET_OOM;
size_t cursor = index;
return_val_if_fail(this != NULL, RET_INVALID_PARAMETER);
cursor = (cursor < this->size) ? cursor : this->size;
if(darray_expand(this, 1) == RET_OK)
{
size_t i = 0;
for(i = this->size; i > cursor; i--)
{
this->data[i] = this->data[i-1];
}
this->data[cursor] = data;
this->size++;
ret = RET_OK;
}
return ret;
}
Ret darray_prepend(DArray* this, void* data)
{
return (RET_OK == darray_insert(this, ARRAY_HEAD, data)) ? RET_OK : RET_FAIL;
}
Ret darray_append(DArray* this, void* data)
{
return (RET_OK == darray_insert(this, ARRAY_TAIL, data)) ? RET_OK : RET_FAIL;
}
static void darray_destroy_data(DArray* this, void* data)
{
if(this->data_destroy != NULL)
{
this->data_destroy(this->data_destroy_ctx, data);
}
return;
}
static Ret darray_shrink(DArray* this)
{
Ret ret = RET_OK;
return_val_if_fail(this != NULL, RET_INVALID_PARAMETER);
if((this->size < (this->alloc_size >> 1)) && (this->size > MIN_PRE_ALLOCATE_NR))
{
size_t alloc_size = this->size + (this->size >> 1);
void** data = (void ** )realloc(this->data, sizeof(void *) * alloc_size);
if(data != NULL)
{
this->data = data;
this->alloc_size = alloc_size;
}
else
{
ret = RET_OOM;
}
}
return ret;
}
Ret darray_delete(DArray* this, size_t index)
{
size_t i = 0;
Ret ret = RET_OK;
return_val_if_fail(this != NULL && this->size > index, RET_INVALID_PARAMETER);
darray_destroy_data(this, this->data[index]);
for(i = index; (i+1) < this->size; i++)
{
this->data[i] = this->data[i+1];
}
this->size--;
ret = darray_shrink(this);
return ret;
}
Ret darray_get_by_index(DArray* this, size_t index, void** data)
{
return_val_if_fail(this != NULL && this->size > index, RET_INVALID_PARAMETER);
*data = this->data[index];
return RET_OK;
}
Ret darray_set_by_index(DArray* this, size_t index, void* data)
{
return_val_if_fail(this != NULL && this->size > index, RET_INVALID_PARAMETER);
this->data[index] = data;
return RET_OK;
}
int darray_find(DArray* this, DataCompareFunc cmp, void* ctx)
{
size_t i = 0;
return_val_if_fail(this != NULL, RET_INVALID_PARAMETER);
for(; i < this->size; i++)
{
if(0 == cmp(ctx, this->data[i]))
{
return i;
}
}
return -1;
}
size_t darray_length(DArray* this)
{
return this->size;
}
Ret darray_foreach(DArray* this, DataVisitFunc visit, void* ctx)
{
size_t i = 0;
return_val_if_fail(this != NULL, RET_INVALID_PARAMETER);
for(i = 0; i < this->size; i++)
{
visit(ctx, this->data[i]);
}
return RET_OK;
}
Ret darray_sort(DArray* this, DataSortFunc sort, DataCompareFunc cmp)
{
return_val_if_fail(this != NULL, RET_INVALID_PARAMETER);
return(sort(this->data, this->size, cmp));
}
void darray_destroy(DArray* this)
{
return_void_if_fail(this != NULL);
if(this->data_destroy != NULL)
{
size_t i = 0;
for(; i < this->size; i++)
{
if(this->data[i] != NULL)
{
this->data_destroy(this->data_destroy_ctx, this->data[i]);
this->data[i] = NULL;
}
}
}
free(this);
}
转载于:https://my.oschina.net/mavericsoung/blog/217825