darray实现

This commit is contained in:
建峰 2026-05-11 15:16:42 +08:00
parent 803f489ee7
commit 1532d3716c
10 changed files with 594 additions and 3 deletions

View File

@ -85,7 +85,6 @@ void* iter_next(); // 迭代器下一个元素
// -------------------- 扩展功能 --------------------
// 元素相关操作
bool append(const void* obj); // 追加元素 <push_back> 一般用于list
// bool remove(const void *obj); // 删除元素 <暂不使用该命名>
bool find(const void* obj); // 查找元素 <返回值bool/uint32_t/void*待定>
bool contains(const void* obj); // 判断元素是否存在 <返回bool>
uint32_t count(const void* obj); // 统计元素obj的个数
@ -93,7 +92,8 @@ uint32_t count(const void* obj); // 统计元素obj的个数
// 索引相关操作
uint32_t index(void *obj); // 获取元素索引
bool insert(uint32_t index, const void* obj); // 插入元素 <非树>
bool delete(uint32_t index, void* obj); // 删除元素
// bool delete(uint32_t index, void* obj); // 删除元素 <!!!废弃防止项目用于C++,关键字冲突>
bool remove(const void *obj); // 删除元素 <推荐>
// bool erase(uint32_t index); // 删除元素<暂时不用该命名>
bool set(uint32_t index, const void* obj); // 设置元素
bool get(uint32_t index, void* obj); // 获取元素
@ -147,6 +147,7 @@ bool get(uint32_t index, void* obj); // 获取元素
```
### 工程命名
`工程名(_功能)_v版本号_日期(_时间)(-其他信息)`
> 括号内表示可选项
@ -163,8 +164,23 @@ unicstl_stack_v1.2.5_20240717-a0.zip
# 带a或者b后缀表示当前版本发布前的测试版。如果发布后则直接更新版本号了
```
### 分支命名
|命名 |说明 | 示例
|:----: |:----: | ----
| master | 主分支 | master
| dev | 开发分支 | dev-stack
| test | 测试分支| test-tree
| release | 发布分支 | release-v1.2.5或v1.2.5
| feature | 新功能分支 | feature-tree
| bugfix | bug修复分支 | bugfix-map
| refactor | 重构分支| refactor-darray
## 修改日志
### Unicstl 0.0.10 (2025-12-31)
- refactor:
- darray & list, old list(list python list) -> arraylist
### Unicstl 0.0.02 (2025-05-06)
- new features
- graph add function: add/del/find vertex/edge
@ -179,7 +195,6 @@ unicstl_stack_v1.2.5_20240717-a0.zip
- others:
- none
### Unicstl 0.0.01 (2025-04-24)
- new features
- add stack

73
include/darray.h Normal file
View File

@ -0,0 +1,73 @@
/**
* @file darray.h
* @author wenjf (orig5826@163.com)
* @brief
* @version 0.1
* @date 2026-05-11
*
* @copyright Copyright (c) 2026
*
*/
#ifndef _DARRAY_H_
#define _DARRAY_H_
#include "unicstl_internal.h"
#include "iterator.h"
struct _darray
{
// -------------------- private --------------------
void *obj;
uint32_t _obj_size;
uint32_t _size;
uint32_t _capacity;
uint32_t _ratio;
uint32_t _cur;
struct _iterator _iter;
void (*_destory)(struct _darray *self);
// -------------------- public --------------------
// kernel
bool (*resize)(struct _darray *self, uint32_t capacity);
bool (*append)(struct _darray *self, void *obj);
bool (*pop)(struct _darray *self, void *obj);
bool (*insert)(struct _darray *self, int index, void *obj);
bool (*remove)(struct _darray *self, int index, void *obj);
bool (*get)(struct _darray *self, int index, void *obj);
bool (*set)(struct _darray *self, int index, void *obj);
int (*index)(struct _darray *self, void *obj); // retval -1 if not found
bool (*contains)(struct _darray *self, void *obj);
// base
uint32_t (*size)(struct _darray *self);
uint32_t (*capacity)(struct _darray *self);
bool (*empty)(struct _darray *self);
bool (*full)(struct _darray *self);
bool (*clear)(struct _darray *self);
void (*dynamic_enable)(struct _darray *self, bool enable);
bool (*dynamic)(struct _darray *self);
// iter
iterator_t (*iter)(struct _darray *self);
// config
compare_fun_t compare; // !!! you have to implement this function
// -------------------- debug --------------------
void (*print)(struct _darray *self);
void (*print_obj)(void *obj);
};
typedef struct _darray *darray_t;
darray_t darray_new(uint32_t obj_size, uint32_t capacity);
void darray_free(darray_t *darray);
#endif

67
include/linklist.h Normal file
View File

@ -0,0 +1,67 @@
/**
* @file linklist.h
* @author wenjf (orig5826@163.com)
* @brief
* @version 0.1
* @date 2026-05-11
*
* @copyright Copyright (c) 2026
*
*/
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include "unicstl_internal.h"
#include "iterator.h"
struct _linklist_node
{
void* obj;
struct _linklist_node* next;
};
struct _linklist
{
// -------------------- private --------------------
struct _linklist_node* _head;
struct _linklist_node* _tail;
uint32_t _obj_size;
uint32_t _size;
// uint32_t _capacity;
// uint32_t _ratio;
struct _iterator _iter;
void (*_destory)(struct _linklist* self);
// -------------------- public --------------------
// kernel
bool (*push_back)(struct _linklist* self, void* obj);
bool (*push_front)(struct _linklist* self, void* obj);
bool (*pop_back)(struct _linklist* self, void* obj);
bool (*pop_front)(struct _linklist* self, void* obj);
bool (*back)(struct _linklist* self, void* obj);
bool (*front)(struct _linklist* self, void* obj);
// base
uint32_t(*size)(struct _linklist* self);
bool (*clear)(struct _linklist* self);
bool (*empty)(struct _linklist* self);
// iter
iterator_t (*iter)(struct _linklist* self);
// -------------------- debug --------------------
void (*print)(struct _linklist* self);
void (*print_obj)(void* obj);
};
typedef struct _linklist* linklist_t;
// create and free deque
linklist_t linklist_new(uint32_t obj_size);
void linklist_free(linklist_t* deque);
#endif

View File

@ -18,6 +18,9 @@
#include "unicstl_internal.h"
#include "darray.h"
#include "linklist.h"
#include "list.h"
#include "stack.h"
#include "queue.h"

View File

@ -40,4 +40,10 @@
#define UNICSTL_DEBUG_GRAPH
#endif
/**
* @brief use malloc
*
*/
#define UNICSTL_MALLOC
#endif

View File

@ -29,6 +29,36 @@
#include "iterator.h"
#endif
/**
* @brief default capacity and ratio
*
*/
#define DEFAULT_CAPACITY 16
#define DEFAULT_RATIO 2
/**
* @brief malloc and free function
*
*/
#ifdef UNICSTL_MALLOC
static inline void * unicstl_malloc(size_t size) {
return malloc(size);
}
static inline void * unicstl_realloc(void * ptr, size_t size) {
return realloc(ptr, size);
}
static inline void unicstl_free(void * ptr) {
free(ptr);
}
#else
#error "UNICSTL_MALLOC not defined"
#endif
/**
* @brief obj compare with obj2
*
@ -44,4 +74,5 @@ typedef int (*compare_fun_t)(void* obj, void* obj2);
int default_compare(void* obj1, void* obj2);
void default_print_obj(void* obj);
#endif // _COMMON_H_

303
src/darray.c Normal file
View File

@ -0,0 +1,303 @@
/**
* @file darray.c
* @author wenjf (orig5826@163.com)
* @brief
* @version 0.1
* @date 2026-05-11
*
* @copyright Copyright (c) 2026
*
*/
#include "darray.h"
static uint32_t darray_size(struct _darray *self)
{
return self->_size;
}
static uint32_t darray_capacity(struct _darray *self)
{
return self->_capacity;
}
static bool darray_empty(struct _darray *self)
{
return self->_size == 0;
}
static bool darray_full(struct _darray *self)
{
return self->_size == self->_capacity;
}
static bool darray_clear(struct _darray *self)
{
self->_size = 0;
return true;
}
static void darray_destory(struct _darray *self)
{
assert(self != NULL);
if (self->obj != NULL)
{
free(self->obj);
}
}
static void darray_print(struct _darray *self)
{
assert(self != NULL);
if (self->obj == NULL)
{
return;
}
void *obj = NULL;
uint32_t offset = 0;
for (int i = self->size(self) - 1; i >= 0; i--)
{
offset = self->_obj_size * i;
obj = (char *)self->obj + offset;
self->print_obj(obj);
}
}
static void darray_dynamic_enable(struct _darray *self, bool enable)
{
assert(self != NULL);
if (enable)
{
self->_ratio = DEFAULT_RATIO;
}
else
{
self->_ratio = 1;
}
}
static bool darray_dynamic(struct _darray *self)
{
assert(self != NULL);
return self->_ratio == DEFAULT_RATIO ? true : false;
}
static bool darray_resize(struct _darray *self, uint32_t capacity)
{
assert(self != NULL);
void *new_obj = unicstl_realloc(self->obj, capacity * self->_obj_size);
if (new_obj == NULL)
{
return false;
}
self->obj = new_obj;
self->_capacity = capacity;
return true;
}
static bool darray_insert(struct _darray *self, int index, void *obj)
{
assert(self != NULL);
if (index < 0 || index > (int)self->size(self))
{
return false;
}
if (self->full(self))
{
if(self->dynamic(self) != true)
{
return false;
}
int new_capacity = self->_capacity * self->_ratio;
if (darray_resize(self, new_capacity) == false)
{
return false;
}
}
uint32_t offset = index * self->_obj_size;
if (index < self->size(self))
{
uint32_t offset1 = (index + 1) * self->_obj_size;
uint32_t count = self->size(self) - index;
// move data to right
memmove((char *)self->obj + offset1, (char *)self->obj + offset, count * self->_obj_size);
}
// copy new data
memmove((char *)self->obj + offset, obj, self->_obj_size);
self->_size += 1;
return true;
}
static bool darray_remove(struct _darray *self, int index, void *obj)
{
assert(self != NULL);
if (self->empty(self))
{
return false;
}
if (index < 0 || index >= (int)self->size(self))
{
return false;
}
uint32_t offset = index * self->_obj_size;
uint32_t offset1 = (index + 1) * self->_obj_size;
uint32_t count = self->size(self) - 1 - index;
if (obj != NULL)
{
memmove(obj, (char*)self->obj + offset, self->_obj_size);
}
memmove((char*)self->obj + offset, (char*)self->obj + offset1, count * self->_obj_size);
self->_size -= 1;
return true;
}
static bool darray_append(struct _darray *self, void *obj)
{
return darray_insert(self, self->size(self), obj);
}
static bool darray_pop(struct _darray *self, void *obj)
{
return darray_remove(self, self->size(self) - 1, obj);
}
static bool darray_get(struct _darray *self, int index, void *obj)
{
assert(self != NULL);
if(obj == NULL)
{
return false;
}
if (index < 0 || index >= self->size(self))
{
return false;
}
uint32_t offset = index * self->_obj_size;
memmove(obj, (char*)self->obj + offset, self->_obj_size);
return true;
}
static bool darray_set(struct _darray *self, int index, void *obj)
{
assert(self != NULL);
if(obj == NULL)
{
return false;
}
if (index < 0 || index >= self->size(self))
{
return false;
}
uint32_t offset = index * self->_obj_size;
memmove((char*)self->obj + offset, obj, self->_obj_size);
return true;
}
static int darray_index(struct _darray *self, void *obj)
{
assert(self != NULL);
if (obj == NULL)
{
return -1;
}
for (int i = 0; i < self->size(self); ++i)
{
if (self->compare((char*)self->obj + i * self->_obj_size, obj) == 0)
{
return i;
}
}
return -1;
}
static bool darray_contains(struct _darray *self, void *obj)
{
return darray_index(self, obj) != -1;
}
static bool darray_init(struct _darray *self, uint32_t obj_size, uint32_t capacity)
{
assert(self != NULL);
if (obj_size == 0 || capacity == 0)
{
return false;
}
// -------------------- private --------------------
self->_obj_size = obj_size;
self->_size = 0;
self->_capacity = capacity;
self->_ratio = 2;
self->obj = NULL;
self->_destory = darray_destory;
// -------------------- public --------------------
// kernel
self->resize = darray_resize;
self->insert = darray_insert;
self->remove = darray_remove;
self->append = darray_append;
self->pop = darray_pop;
self->get = darray_get;
self->set = darray_set;
self->index = darray_index;
self->contains = darray_contains;
self->empty = darray_empty;
self->full = darray_full;
self->dynamic_enable = darray_dynamic_enable;
self->dynamic = darray_dynamic;
self->size = darray_size;
self->capacity = darray_capacity;
self->clear = darray_clear;
// -------------------- default --------------------
self->print_obj = default_print_obj;
// -------------------- debug --------------------
self->print = darray_print;
// -------------------- init config --------------------
self->resize(self, capacity);
return true;
}
darray_t darray_new(uint32_t obj_size, uint32_t capacity)
{
struct _darray *darray = NULL;
darray = (struct _darray *)unicstl_malloc(sizeof(struct _darray));
if(darray == NULL)
{
return NULL;
}
if(darray_init(darray, obj_size, capacity) != true)
{
free(darray);
return NULL;
}
return darray;
}
void darray_free(darray_t *darray)
{
if(darray != NULL && *darray != NULL)
{
if((*darray)->_destory != NULL)
{
(*darray)->_destory((*darray));
}
free(*darray);
*darray = NULL;
}
}

View File

@ -78,6 +78,8 @@ int main(int argc, char const *argv[])
printf("----- Unicstl Unit Test -----\n");
UNITY_BEGIN();
TEST_ADD(test_darray);
TEST_ADD(test_queue);
TEST_ADD(test_stack);
TEST_ADD(test_list);

View File

@ -42,6 +42,8 @@ void print_str(void* obj);
* @brief test function
*
*/
void test_darray(void);
void test_queue(void);
void test_stack(void);
void test_list(void);

89
test/test_darray.c Normal file
View File

@ -0,0 +1,89 @@
/**
* @file test_darray.c
* @author wenjf (orig5826@163.com)
* @brief
* @version 0.1
* @date 2026-05-11
*
* @copyright Copyright (c) 2026
*
*/
#include "test.h"
static void test_darray_new(void)
{
darray_t darray = darray_new(sizeof(int), 10);
TEST_ASSERT_NOT_NULL(darray);
darray_free(&darray);
TEST_ASSERT_NULL(darray_new(0, 0));
TEST_ASSERT_NULL(darray_new(0, 1));
TEST_ASSERT_NULL(darray_new(sizeof(int), 0));
// ------------------------------
TEST_ASSERT_NULL(darray);
darray_free(&darray);
}
static void test_darray_insert(void)
{
int temp = 0;
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
uint32_t len = sizeof(data) / sizeof(data[0]);
uint32_t i = 0;
darray_t darray = darray_new(sizeof(int), len);
darray->compare = compare_num;
TEST_ASSERT_TRUE(darray->empty(darray));
TEST_ASSERT_FALSE(darray->full(darray));
for(i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(darray->insert(darray, 0, &data[i]));
TEST_ASSERT_EQUAL_INT(i + 1, darray->size(darray));
TEST_ASSERT_TRUE(darray->get(darray, 0, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
TEST_ASSERT_FALSE(darray->empty(darray));
}
TEST_ASSERT_TRUE(darray->full(darray));
darray_free(&darray);
}
static void test_darray_append(void)
{
int temp = 0;
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
uint32_t len = sizeof(data) / sizeof(data[0]);
uint32_t i = 0;
darray_t darray = darray_new(sizeof(int), len);
darray->compare = compare_num;
TEST_ASSERT_TRUE(darray->empty(darray));
TEST_ASSERT_FALSE(darray->full(darray));
for(i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(darray->append(darray, &data[i]));
TEST_ASSERT_EQUAL_INT(i + 1, darray->size(darray));
uint32_t index = darray->size(darray) - 1;
TEST_ASSERT_TRUE(darray->get(darray, index, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
TEST_ASSERT_FALSE(darray->empty(darray));
}
TEST_ASSERT_TRUE(darray->full(darray));
darray_free(&darray);
}
void test_darray(void)
{
UnitySetTestFile(__FILE__);
RUN_TEST(test_darray_new);
RUN_TEST(test_darray_insert);
RUN_TEST(test_darray_append);
}