diff --git a/README.md b/README.md index 4a2191f..1e8c9e3 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,6 @@ void* iter_next(); // 迭代器下一个元素 // -------------------- 扩展功能 -------------------- // 元素相关操作 bool append(const void* obj); // 追加元素 一般用于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); // 删除元素 +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 diff --git a/include/darray.h b/include/darray.h new file mode 100644 index 0000000..25bdd24 --- /dev/null +++ b/include/darray.h @@ -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 diff --git a/include/linklist.h b/include/linklist.h new file mode 100644 index 0000000..d4be439 --- /dev/null +++ b/include/linklist.h @@ -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 diff --git a/include/unicstl.h b/include/unicstl.h index 8fe81e4..55403d4 100644 --- a/include/unicstl.h +++ b/include/unicstl.h @@ -18,6 +18,9 @@ #include "unicstl_internal.h" +#include "darray.h" +#include "linklist.h" + #include "list.h" #include "stack.h" #include "queue.h" diff --git a/include/unicstl_config.h b/include/unicstl_config.h index 122ca65..667b972 100644 --- a/include/unicstl_config.h +++ b/include/unicstl_config.h @@ -40,4 +40,10 @@ #define UNICSTL_DEBUG_GRAPH #endif +/** + * @brief use malloc + * + */ +#define UNICSTL_MALLOC + #endif \ No newline at end of file diff --git a/include/unicstl_internal.h b/include/unicstl_internal.h index fc33722..bdb71ac 100644 --- a/include/unicstl_internal.h +++ b/include/unicstl_internal.h @@ -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_ diff --git a/src/darray.c b/src/darray.c new file mode 100644 index 0000000..22fe401 --- /dev/null +++ b/src/darray.c @@ -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; + } +} diff --git a/test/test.c b/test/test.c index 846e1e2..8a87612 100644 --- a/test/test.c +++ b/test/test.c @@ -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); diff --git a/test/test.h b/test/test.h index 2286e55..da69ff3 100644 --- a/test/test.h +++ b/test/test.h @@ -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); diff --git a/test/test_darray.c b/test/test_darray.c new file mode 100644 index 0000000..7cfd81c --- /dev/null +++ b/test/test_darray.c @@ -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); +}