//首先是数据结构,size记录使用的空间,alloc_size记录分配的空间 data为指针的指针,为了灵活性,必须的。
struct _DArray
{
size_t size;
size_t alloc_size;
void** data;
};
typedef struct _DArray DArray;
//一些接口的定义。
DArray* darray_create(DataDestroyFunc data_destroy, void* ctx);
Ret darray_insert(DArray* thiz, size_t index, void* data);
Ret darray_prepend(DArray* thiz, void* data);
Ret darray_append(DArray* thiz, void* data);
Ret darray_delete(DArray* thiz, size_t index);
Ret darray_get_by_index(DArray* thiz, size_t index, void** data);
Ret darray_set_by_index(DArray* thiz, size_t index, void* data);
size_t darray_length(DArray* thiz);
int darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx);
Ret darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx);
void darray_destroy(DArray* thiz);
/*************************************
* 好的到了关键的地方了,在空间不足的时候,动态扩充容量,为了提高效率,
*一次扩充多个空间,在不够用的时候,一次扩充为原来的1.5倍,
*计算公式为alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR
*这样就可以避免一些环境中没有浮点运算,以及浮点运算可能造成的误差~~最后那个数,是为了防止到了一定时候,分配过于频繁
*
*
********************************************/
#define MIN_PRE_ALLOCATE_NR 10
static Ret darray_expand(DArray* thiz, size_t need)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
if((thiz->size + need) > thiz->alloc_size)
{
size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR ;
void** data = (void **)realloc(thiz->data,sizeof(void*) * alloc_size);
if(data != NULL)
{
thiz->data = data;
thiz->alloc_size = alloc_size;
}
}
return ((thiz->size + need) <= thiz->alloc_size) ? RET_OK : RET_FAIL;
}
//插入函数,在某个下标插入,最多也就在当前数组的末尾,会自动调整。
Ret darray_insert(DArray* thiz, size_t index, void* data)
{
Ret ret = RET_OOM;
size_t cursor = index;
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
cursor = cursor < thiz->size ? cursor : thiz->size;
if(darray_expand(thiz,1) == RET_OK)
{
size_t i = 0;
for(i = thiz->size; i > cursor; i--)
{
thiz->data[i] = thiz->data[i-1];
}
thiz->data[cursor] = data;
thiz->size++;
ret = RET_OK;
}
return ret;
}
/*************************************
* 压缩数组,在空闲的空间到了一定的数量的时候,就进行压缩,
*当使用空间小于分配的空间的一半的时候,就将当前的空间缩小为1.5倍已使用的空间。
*计算公式为alloc_size = (thiz->size >>1) +thiz->size ,
*这样就可以避免一些环境中没有浮点运算,以及浮点运算可能造成的误差~~thiz->alloc_size > MIN_PRE_ALLOCATE_NR
*是为了防止到了一定时候,压缩过于频繁
*
*
********************************************/
static Ret darray_shrink(DArray* thiz)
{
return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);
if((thiz->size < (thiz->alloc_size >> 1)) && (thiz->alloc_size > MIN_PRE_ALLOCATE_NR ))
{
size_t alloc_size = (thiz->size >>1) +thiz->size;
void** data = (void **)realloc(thiz->data,sizeof(void*)*alloc_size);
if(data != NULL)
{
thiz->alloc_size = alloc_size;
thiz->data =data;
}
}
return RET_OK;
}
//根据下标删除某个元素,先删,再定容。
Ret darray_delete(DArray* thiz, size_t index)
{
size_t i=0;
Ret ret = RET_OK;
return_val_if_fail(thiz != NULL && thiz->size > index, RET_INVALID_PARAM);
darray_destroy_data(thiz,thiz->data[index]);
for(i = index; (i+1) < thiz->data->size; ++i)
{
thiz->data[i] = thiz->data[i+1];
}
thiz->size--;
darray_shrink(thiz);
return RET_OK;
}