通用动态数组(二)——接口实现

/*----------------------------------------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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值