refactor(segarray): 段使用rawbuf而不是darray,先按照最简单的方式调试通push和pop等操作

This commit is contained in:
建峰 2026-05-15 19:01:37 +08:00
parent 0236e6e315
commit 0dd45ed7dd
7 changed files with 298 additions and 154 deletions

3
.gitignore vendored
View File

@ -1,4 +1,7 @@
# log/txt
*.log
# cmake
build/
release/

View File

@ -40,4 +40,4 @@ void rawbuf_free(rawbuf_t *rawbuf);
bool rawbuf_init(struct _rawbuf *self, size_t obj_size, size_t capacity, void *mem_base);
#endif
#endif
#endif // _RAWBUF_H_

View File

@ -12,8 +12,8 @@
#define _SEGARRAY_H_
#include "unicstl_internal.h"
#include "darray.h"
#include "ringbuf.h"
#include "rawbuf.h"
enum _segarray_order
{
@ -21,12 +21,6 @@ enum _segarray_order
SEGARRAY_REVERSE,
};
struct _obj_pos
{
size_t map;
size_t seg;
};
struct _segarray
{
// -------------------- private --------------------
@ -36,11 +30,13 @@ struct _segarray
size_t _size;
size_t _capacity;
bool _dynamic;
size_t _segsize;
ringbuf_t _map;
struct _obj_pos _head;
struct _obj_pos _tail;
size_t _maphead;
size_t _maptail;
size_t _seghead;
size_t _segtail;
struct _iterator _iter;
void (*_destory)(struct _segarray* self);

View File

@ -10,7 +10,7 @@
*/
#ifndef _UNICSTL_CONFIG_H_
#define NDEBUG // release mode if define NDEBUG
// #define NDEBUG // release mode if define NDEBUG
/**
* @brief unicstl contains which module
@ -66,7 +66,7 @@
* 0. simple
* 1. detail
*/
#define LOG_DEBUG_DETAIL 1
#define LOG_DEBUG_DETAIL 0
#endif // UNICSTL_DEBUG
#endif

View File

@ -1,87 +1,86 @@
/**
* @file segarray.c
* @author wenjf (Orig5826@163.com)
* @brief
* @brief
* @version 0.1
* @date 2026-05-15
*
*
* @copyright Copyright (c) 2026
*
*
*/
#include "segarray.h"
static inline size_t clac_start_index(size_t capacity)
{
return capacity <= 2 ? 0 : (capacity - 1)/ 2;
return capacity <= 2 ? 0 : (capacity - 1) / 2;
}
static inline const darray_t get_seg(struct _segarray *self, struct _obj_pos pos)
static inline size_t segarray_map_full(struct _segarray *self, size_t capacity)
{
return (const darray_t)self->_map->at(self->_map, pos.map);
}
static inline void * get_obj(struct _segarray *self, struct _obj_pos pos, void *obj)
{
darray_t darray = get_seg(self, pos);
return (void *)darray->at(darray, pos.seg);
return 0;
}
static inline void print_pos(struct _segarray *self)
{
printf("head[%d][%d], tail[%d][%d]\n", self->_head.map, self->_head.seg,
self->_tail.map, self->_tail.seg);
LOG_DEBUG("head[%d][%d], tail[%d][%d]\n",
self->_maphead,
self->_seghead,
self->_maptail - 1,
self->_segtail);
}
static bool segarray_push_back(struct _segarray *self, const void *obj)
{
unicstl_assert(self != NULL);
if(self->obj == NULL || obj == NULL)
if (self->obj == NULL || obj == NULL)
{
return false;
}
ringbuf_t map = self->_map;
if (self->_segtail == self->_segsize)
{
if (map->full(map))
{
LOG_WARN("map->full");
return false;
// size_t new_capacity = unicstl_new_capacity(self->capacity(self));
// if (!map->resize(map, new_capacity))
// {
// LOG_ERROR("map->resize(map, new_capacity) failed!");
// return false;
// }
}
rawbuf_t seg = rawbuf_new(self->_obj_size, self->_capacity);
if (seg == NULL)
{
LOG_ERROR("rawbuf_new failed!");
return false;
}
map->push_back(map, &seg);
self->_maptail = self->_maptail + 1;
self->_segtail = 0;
}
print_pos(self);
if (self->_tail.seg == self->_capacity - 1)
rawbuf_t seg;
if (!map->back(map, &seg))
{
if(map->full(map))
{
size_t new_capacity = unicstl_new_capacity(self->capacity(self));
if (!map->resize(map, new_capacity))
{
printf("map->resize(map, new_capacity) failed!");
return false;
}
}
else
{
darray_t seg = darray_new(self->_obj_size, self->_capacity);
if(seg == NULL)
{
printf("darray_new failed!");
return false;
}
map->push_back(map, &seg);
}
}
darray_t seg;
if(!map->back(map, &seg))
{
printf("map->back failed!");
LOG_ERROR("map->back failed!");
return false;
}
size_t index = self->_tail.seg;
printf("index = %d\n", index);
if(!seg->set(seg, index, obj))
size_t index = self->_segtail;
if (!seg->set(seg, index, obj))
{
printf("seg->set failed!");
LOG_ERROR("seg->set failed!");
return false;
}
self->_tail.seg = ring_index_next(self->_tail.seg, self->_capacity);
self->_segtail = index + 1;
LOG_INFO("push_back success!");
self->_size++;
return true;
}
@ -89,39 +88,56 @@ static bool segarray_push_back(struct _segarray *self, const void *obj)
static bool segarray_push_front(struct _segarray *self, const void *obj)
{
unicstl_assert(self != NULL);
if(self->obj == NULL || obj == NULL)
if (self->obj == NULL || obj == NULL)
{
return false;
}
if (self->full(self))
ringbuf_t map = self->_map;
if (self->_seghead == 0)
{
if(self->_dynamic != true)
{
return false;
}
size_t new_capacity = unicstl_new_capacity(self->capacity(self));
if (self->resize(self, new_capacity) == false)
LOG_DEBUG("map->size = %d\n", map->size(map));
if (map->full(map))
{
LOG_WARN("map->full");
return false;
// size_t new_capacity = unicstl_new_capacity(self->capacity(self));
// if (!map->resize(map, new_capacity))
// {
// LOG_ERROR("map->resize(map, new_capacity) failed!");
// return false;
// }
}
rawbuf_t seg = rawbuf_new(self->_obj_size, self->_capacity);
if (seg == NULL)
{
LOG_ERROR("rawbuf_new failed!");
return false;
}
map->push_front(map, &seg);
self->_maphead = self->_maphead - 1;
self->_seghead = self->_segsize;
}
// const darray_t seg = (const darray_t)self->_map->at(self->_map, self->_head.map);
// if(seg == NULL)
// {
// return false;
// }
// self->obj = seg->at(seg, self->_head.seg);
// if(self->obj == NULL)
// {
// return false;
// }
// size_t index = ring_index_prev(self->_head.seg, self->_capacity);
// obj_set(self->obj, index, obj, self->_obj_size);
// self->_head.seg = index;
print_pos(self);
rawbuf_t seg;
if (!map->front(map, &seg))
{
LOG_ERROR("map->back failed!");
return false;
}
size_t index = self->_seghead - 1;
if (!seg->set(seg, index, obj))
{
LOG_ERROR("seg->set failed!");
return false;
}
self->_seghead = index;
LOG_INFO("push_front success!");
self->_size++;
return true;
}
@ -129,18 +145,41 @@ static bool segarray_push_front(struct _segarray *self, const void *obj)
static bool segarray_pop_back(struct _segarray *self, void *obj)
{
unicstl_assert(self != NULL);
if(self->obj == NULL || self->empty(self))
if (self->obj == NULL || self->empty(self))
{
return false;
}
// size_t index = ring_index_prev(self->_tail.seg, self->_capacity);
// if(obj != NULL)
// {
// obj_get(self->obj, index, obj, self->_obj_size);
// }
// self->_tail = index;
print_pos(self);
ringbuf_t map = self->_map;
rawbuf_t seg;
size_t index = self->_segtail - 1;
if(obj != NULL)
{
if (!map->back(map, &seg))
{
LOG_ERROR("map->back failed!");
return false;
}
if (!seg->get(seg, index, obj))
{
LOG_ERROR("seg->set failed!");
return false;
}
}
self->_segtail = index;
if(self->_segtail == 0)
{
self->_segtail = self->_segsize;
self->_maptail = self->_maptail - 1;
map->pop_back(map, &seg);
rawbuf_free(&seg);
}
LOG_INFO("pop_back success!");
self->_size--;
return true;
}
@ -148,7 +187,7 @@ static bool segarray_pop_back(struct _segarray *self, void *obj)
static bool segarray_pop_front(struct _segarray *self, void *obj)
{
unicstl_assert(self != NULL);
if(self->obj == NULL || self->empty(self))
if (self->obj == NULL || self->empty(self))
{
return false;
}
@ -158,6 +197,36 @@ static bool segarray_pop_front(struct _segarray *self, void *obj)
return false;
}
print_pos(self);
ringbuf_t map = self->_map;
size_t index = self->_seghead;
if(obj != NULL)
{
rawbuf_t seg;
if (!map->front(map, &seg))
{
LOG_ERROR("map->back failed!");
return false;
}
if (!seg->get(seg, index, obj))
{
LOG_ERROR("seg->set failed!");
return false;
}
}
self->_seghead = index + 1;
if(self->_seghead == self->_segsize)
{
self->_seghead = 0;
self->_maphead = self->_maphead + 1;
rawbuf_t seg;
map->pop_front(map, &seg);
rawbuf_free(&seg);
}
LOG_INFO("pop_front success!");
self->_size--;
return true;
}
@ -165,25 +234,37 @@ static bool segarray_pop_front(struct _segarray *self, void *obj)
static bool segarray_back(struct _segarray *self, void *obj)
{
unicstl_assert(self != NULL);
if(self->obj == NULL || obj == NULL|| self->empty(self))
if (self->obj == NULL || obj == NULL || self->empty(self))
{
return false;
}
return true;
ringbuf_t map = self->_map;
rawbuf_t seg;
if (!map->back(map, &seg))
{
return false;
}
size_t index = self->_segtail - 1;
return seg->get(seg, index, obj);
}
static bool segarray_front(struct _segarray *self, void *obj)
{
unicstl_assert(self != NULL);
if(self->obj == NULL || obj == NULL|| self->empty(self))
if (self->obj == NULL || obj == NULL || self->empty(self))
{
return false;
}
return true;
ringbuf_t map = self->_map;
rawbuf_t seg;
if (!map->front(map, &seg))
{
return false;
}
size_t index = self->_seghead;
return seg->get(seg, index, obj);
}
static bool segarray_resize(struct _segarray *self, size_t capacity)
@ -194,6 +275,11 @@ static bool segarray_resize(struct _segarray *self, size_t capacity)
return false;
}
if(capacity < self->_capacity)
{
return false;
}
return true;
}
@ -206,8 +292,7 @@ static size_t segarray_size(struct _segarray *self)
static size_t segarray_capacity(struct _segarray *self)
{
unicstl_assert(self != NULL);
// return self->_capacity;
return self->_capacity * self->_map->size(self->_map);
return self->_capacity;
}
static bool segarray_empty(struct _segarray *self)
@ -219,32 +304,38 @@ static bool segarray_empty(struct _segarray *self)
static bool segarray_full(struct _segarray *self)
{
unicstl_assert(self != NULL);
size_t map_cap = self->_map->size(self->_map);
size_t map_size = self->_map->size(self->_map);
return (self->_head.map == 0 && self->_head.seg == 0) ||
( self->_tail.map == map_cap - 1 && self->_head.seg == self->_capacity - 1);
return (self->_maphead == 0 && self->_seghead == 0) ||
(self->_maptail == map_size - 1 && self->_segtail == self->_segsize - 1);
}
static bool segarray_clear(struct _segarray *self)
{
unicstl_assert(self != NULL);
self->_size = 0;
self->_head.map = clac_start_index(self->_map->capacity(self->_map));
self->_tail.map = self->_head.map;
self->_head.seg = clac_start_index(self->capacity(self));
self->_tail.seg = self->_head.seg;
self->_seghead = clac_start_index(self->_segsize);
self->_segtail = self->_seghead;
self->_maptail = self->_maphead;
return true;
}
static void segarray_destory(struct _segarray *self)
{
unicstl_assert(self != NULL);
if (self->obj != NULL && self->_dynamic == true)
ringbuf_t map = self->_map;
if (self->_dynamic)
{
free(self->obj);
self->obj = NULL;
rawbuf_t seg = NULL;
while(map->empty(map))
{
if (map->pop_back(map, &seg))
{
rawbuf_free(&seg);
}
}
ringbuf_free(&map);
}
}
@ -267,11 +358,17 @@ bool segarray_iter_hasnext(struct _iterator *iter)
if (iter->_order == SEGARRAY_FORWARD)
{
if (iter->_index >= self->size(self))
{
return false;
}
}
else
{
if (iter->_index == 0)
{
return false;
}
}
return true;
}
@ -283,17 +380,58 @@ const void *segarray_iter_next(struct _iterator *iter)
segarray_t self = (segarray_t)iter->_container;
const void *obj = NULL;
size_t index = iter->_index;
if (iter->_order == SEGARRAY_FORWARD)
ringbuf_t map = self->_map;
rawbuf_t seg = NULL;
size_t map_index;
size_t seg_index;
if (iter->_order == SEGARRAY_REVERSE)
{
//iter->_index = index_next(index, self->_capacity);
LOG_DEBUG("index:%ld", index);
index = self->size(self) + 1 - index;
LOG_DEBUG("reverse-index:%ld", index);
}
size_t seg1_left = self->_segsize - self->_seghead;
if(index < seg1_left)
{
map_index = 0;
seg_index = self->_seghead + index;
}
else
{
//iter->_index = index_prev(index, self->_capacity);
size_t index_left = index - seg1_left;
map_index = index_left / self->_segsize + 1;
seg_index = index_left % self->_segsize;
}
LOG_DEBUG("index:%ld, sethead:%ld", index, seg_index);
LOG_DEBUG("map_index:%ld, seg_index:%ld", map_index, seg_index);
if (map->get(map, map_index, &seg))
{
obj = seg->at(seg, seg_index);
if(obj == NULL)
{
return NULL;
}
}
else
{
return NULL;
}
return obj_at(self->obj, index, self->_obj_size);
if (iter->_order == SEGARRAY_FORWARD)
{
iter->_index++;
}
else
{
iter->_index--;
}
return obj;
}
iterator_t segarray_iter(struct _segarray *self, enum _segarray_order order)
@ -306,6 +444,14 @@ iterator_t segarray_iter(struct _segarray *self, enum _segarray_order order)
iter->_order = order;
//..
if (iter->_order == SEGARRAY_FORWARD)
{
iter->_index = 0;
}
else
{
iter->_index = self->_map->size(self->_map);
}
iter->hasnext = segarray_iter_hasnext;
iter->next = segarray_iter_next;
@ -330,7 +476,8 @@ bool segarray_init(struct _segarray *self, size_t obj_size, size_t capacity, voi
// -------------------- private --------------------
self->_obj_size = obj_size;
self->_size = 0;
self->_capacity = capacity + 1;
self->_capacity = capacity;
self->_segsize = capacity;
if (mem_pool != NULL)
{
@ -341,25 +488,25 @@ bool segarray_init(struct _segarray *self, size_t obj_size, size_t capacity, voi
{
self->_dynamic = true;
self->_map = ringbuf_new(sizeof(darray_t), 8);
if(self->_map == NULL)
self->_map = ringbuf_new(sizeof(rawbuf_t), 8);
if (self->_map == NULL)
{
return false;
}
darray_t seg = darray_new(obj_size, capacity);
if(seg == NULL)
rawbuf_t seg = rawbuf_new(obj_size, self->_segsize);
if (seg == NULL)
{
ringbuf_free(&self->_map);
return false;
}
// config first obj index in seg array
self->_head.seg = clac_start_index(self->_capacity);
self->_tail.seg = self->_head.seg;
self->_seghead = clac_start_index(self->_segsize);
self->_segtail = self->_seghead;
// add first seg array to map
self->_head.map = 0;
self->_tail.map = 0;
self->_maphead = 0;
self->_maptail = 1;
self->_map->push_back(self->_map, &seg);
}

View File

@ -96,7 +96,7 @@ int main(int argc, char const *argv[])
TEST_ADD(test_graph);
TEST_ADD(test_rawbuf);
// TEST_ADD(test_segarray);
TEST_ADD(test_segarray);
return UNITY_END();
}

View File

@ -103,7 +103,6 @@ static void test_segarray_push_back_invalid(void)
segarray_free(&segarray);
}
#if 0
static void test_segarray_push_front(void)
{
size_t i = 0;
@ -196,7 +195,6 @@ static void test_segarray_pop_back(void)
segarray_free(&segarray);
}
static void test_segarray_pop_front(void)
{
size_t i = 0;
@ -374,7 +372,7 @@ static void test_segarray_front_invalid(void)
segarray_free(&segarray);
}
#if 0
static void test_segarray_set(void)
{
int temp = 0;
@ -477,6 +475,7 @@ static void test_segarray_at(void)
segarray_free(&segarray);
}
#endif
static void test_segarray_iter(void)
{
@ -492,32 +491,38 @@ static void test_segarray_iter(void)
{
segarray->push_back(segarray, &data[i]);
}
TEST_ASSERT_EQUAL_INT(len, segarray->size(segarray));
iterator_t iter = segarray->iter(segarray, RINGBUF_FORWARD);
i = 0;
TEST_ASSERT_TRUE(iter->hasnext(iter));
while(iter->hasnext(iter))
{
LOG_DEBUG("iter-test: i=%d\n", i);
temp = *(int *)iter->next(iter);
TEST_ASSERT_EQUAL_INT(data[i], temp);
i++;
}
TEST_ASSERT_EQUAL_INT(len, i);
LOG_INFO("iter-forward cuccess!");
iter = segarray->iter(segarray, RINGBUF_REVERSE);
i = len - 1;
TEST_ASSERT_TRUE(iter->hasnext(iter));
while(iter->hasnext(iter))
{
LOG_DEBUG("iter-test: i=%d\n", i);
temp = *(int *)iter->next(iter);
TEST_ASSERT_EQUAL_INT(data[i], temp);
i--;
}
TEST_ASSERT_EQUAL_INT(0, i);
LOG_INFO("iter-reverse cuccess!");
segarray_free(&segarray);
}
#if 0
static void test_segarray_resize(void)
{
int temp = 0;
@ -662,6 +667,7 @@ static void test_segarray_dynamic(void)
segarray_free(&segarray);
}
#endif
static void test_segarray_status(void)
{
@ -687,7 +693,7 @@ static void test_segarray_status(void)
TEST_ASSERT_FALSE(segarray->full(segarray));
}
TEST_ASSERT_TRUE(segarray->push_back(segarray, &data[i]));
TEST_ASSERT_TRUE(segarray->full(segarray));
// TEST_ASSERT_TRUE(segarray->full(segarray));
TEST_ASSERT_TRUE(segarray->push_back(segarray, &data[i]));
TEST_ASSERT_TRUE(segarray->clear(segarray));
@ -816,18 +822,10 @@ static void test_segarray_struct(void)
TEST_ASSERT_TRUE(segarray->push_front(segarray, &data[i]));
}
#if 0
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(segarray->get(segarray, i, &temp));
}
#endif
segarray_free(&segarray);
TEST_ASSERT_NULL(segarray);
}
#endif // 0
void test_segarray(void)
{
@ -841,29 +839,29 @@ void test_segarray(void)
// RUN_TEST(test_segarray_init);
// #endif
// RUN_TEST(test_segarray_push_back);
// RUN_TEST(test_segarray_push_back_invalid);
RUN_TEST(test_segarray_push_back);
RUN_TEST(test_segarray_push_back_invalid);
// RUN_TEST(test_segarray_push_front);
// RUN_TEST(test_segarray_push_front_invalid);
RUN_TEST(test_segarray_push_front);
RUN_TEST(test_segarray_push_front_invalid);
// RUN_TEST(test_segarray_pop_back);
// RUN_TEST(test_segarray_pop_front);
RUN_TEST(test_segarray_pop_back);
RUN_TEST(test_segarray_pop_front);
// RUN_TEST(test_segarray_back);
// RUN_TEST(test_segarray_back_invalid);
RUN_TEST(test_segarray_back);
RUN_TEST(test_segarray_back_invalid);
// RUN_TEST(test_segarray_front);
// RUN_TEST(test_segarray_front_invalid);
RUN_TEST(test_segarray_front);
RUN_TEST(test_segarray_front_invalid);
// // ---------- random access ----------
// ---------- random access ----------
// RUN_TEST(test_segarray_set);
// RUN_TEST(test_segarray_set_invalid);
// RUN_TEST(test_segarray_at);
// // ---------- base ----------
// RUN_TEST(test_segarray_iter);
// ---------- base ----------
// RUN_TEST(test_segarray_iter);
// RUN_TEST(test_segarray_resize);
// RUN_TEST(test_segarray_resize_invalid);
@ -871,8 +869,8 @@ void test_segarray(void)
// RUN_TEST(test_segarray_dynamic);
// RUN_TEST(test_segarray_status);
// RUN_TEST(test_segarray_status);
// // ---------- ext ----------
// RUN_TEST(test_segarray_struct);
// ---------- ext ----------
// RUN_TEST(test_segarray_struct);
}