mirror of
https://gitee.com/apaki/unicstl.git
synced 2026-05-28 22:54:19 +08:00
feat(segarray): 实现随机访问,优化迭代器和头尾访问实现逻辑,并与ringbuf对比不同应用场景下的优劣
This commit is contained in:
parent
115646ecd4
commit
8a65218105
@ -139,6 +139,14 @@ equeue ..> ringbuf : 依赖
|
||||
| equeue | 队列 | 外部缓存
|
||||
|
||||
|
||||
## 性能对比
|
||||
|应用场合 |ringbuf |segarray | 说明
|
||||
|----------|---------|---------|--------------
|
||||
|不扩容 |内存优势 | 内存浪费| 嵌入式无堆内存
|
||||
|小对象扩容|尚可 | 优秀 | 开销低,后者无拷贝更丝滑
|
||||
|大对象扩容|性能较差 | 极致优秀| 前者整体搬移,后者分段扩容
|
||||
|
||||
|
||||
## 接口函数原型
|
||||
```c
|
||||
// -------------------- 初始化 --------------------
|
||||
|
||||
11
doc/log.md
11
doc/log.md
@ -1,11 +0,0 @@
|
||||
|
||||
# 日志
|
||||
|
||||
### 2026-05-16
|
||||
|
||||
### 2026-05-15
|
||||
1. ringbuffer,resize扩容,截断的处理代码简化了。
|
||||
|
||||
### 2026-05-14
|
||||
1. darray模块,insert传参obj没有判断NULL,导致crash
|
||||
2. darray模块,reseze没有处理当realloc之后,size > capacity 的情况
|
||||
55
doc/notes.md
55
doc/notes.md
@ -33,3 +33,58 @@ $$ memory = 2 * mapcap * sizeof(pointer) + objs:capacity $$
|
||||
|
||||
### 5. based on scheme 4, limited to 512 bytes
|
||||
> obj_size < 512 ? segsize=512 : segsize=1
|
||||
|
||||
## ringbuf
|
||||
|
||||
对于嵌入式场景下(没有malloc,也即不扩容的场景),需要用到的estack和equeue,只选择ringbuf即可。而不使用segarray。
|
||||
```c
|
||||
bool ringbuf_init(struct _ringbuf *self, size_t obj_size, size_t capacity, void *mem_base);|
|
||||
```
|
||||
|
||||
### 不扩容场景
|
||||
ringbuf比segarray更节省内存。ringbuf只多一个obj_size的空间。
|
||||
|
||||
$$
|
||||
membase:size = objsize * (capacity + 1)
|
||||
$$
|
||||
|
||||
而segarray是不确定的,所以segarray就得按照可能的最大空间分配。比如方案4的情况下:
|
||||
seghead默认是放中间的,方便不需要库容的时候,push_back和push_front一开始不用分配内存。
|
||||
则为了保证push_back和push_front都能够用,至少需要三个空间。
|
||||
|
||||
$$
|
||||
mem_base_size = obj_size * (capacity * 3)
|
||||
$$
|
||||
|
||||
当然了,若非要将segarray用于嵌入式场景。也可以将seghead初始放在首段开头,那么需要的总内存为:
|
||||
|
||||
$$
|
||||
mem_base_size = obj_size * (capacity * 2)
|
||||
$$
|
||||
|
||||
**因此,若嵌入式不扩容场景下,ringbuf更节省内存。**
|
||||
这可能也是Rust的底层VecDeque选择使用ringbuf的原因。
|
||||
|
||||
### 小文件库容
|
||||
|
||||
对于小文件,ringbuf库容全内存搬移,还尚可以接受。
|
||||
segarray扩容,开新segment,然后指向新的segment,性能也不差。
|
||||
|
||||
### 大文件扩容
|
||||
但对于大文件,ringbuf库容全内存搬移,代价太大。
|
||||
|
||||
而segarray库容,不会触发大量数据搬移,而是新建一个segment,然后指向新的segment。
|
||||
|
||||
**因此,对于大文件扩容场景下,segarray远胜于ringbuf**
|
||||
|
||||
|
||||
|
||||
## 经典问题
|
||||
|
||||
### 2026-05-15
|
||||
1. ringbuffer,resize扩容,截断的处理代码简化了。
|
||||
|
||||
### 2026-05-14
|
||||
> 这就是单元测试的魅力
|
||||
1. darray模块,insert传参obj没有判断NULL,导致crash
|
||||
2. darray模块,resize没有处理当realloc之后,size > capacity 的情况
|
||||
|
||||
@ -70,6 +70,7 @@ ringbuf_t ringbuf_new(size_t obj_size, size_t capacity);
|
||||
void ringbuf_free(ringbuf_t* ringbuf);
|
||||
|
||||
#ifdef UNICSTL_STATIC_MEMORY
|
||||
// mem_base_size = obj_size * (capacity + 1)
|
||||
bool ringbuf_init(struct _ringbuf *self, size_t obj_size, size_t capacity, void *mem_base);
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,8 +33,7 @@ struct _segarray
|
||||
size_t _segsize;
|
||||
|
||||
ringbuf_t _map;
|
||||
size_t _maphead;
|
||||
size_t _maptail;
|
||||
ringbuf_t _mapfree;
|
||||
size_t _seghead;
|
||||
size_t _segtail;
|
||||
|
||||
@ -50,6 +49,11 @@ struct _segarray
|
||||
bool (*back)(struct _segarray* self, void* obj);
|
||||
bool (*front)(struct _segarray* self, void* obj);
|
||||
|
||||
// -------------------- random access --------------------
|
||||
bool (*set)(struct _segarray *self, size_t index, const void *obj); // O(1)
|
||||
bool (*get)(struct _segarray *self, size_t index, void *obj); // O(1)
|
||||
const void* (*at)(struct _segarray *self, size_t index); // O(1)
|
||||
|
||||
// base
|
||||
bool (*resize)(struct _segarray *self, size_t capacity);
|
||||
size_t (*size)(struct _segarray* self);
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
/**
|
||||
* @file unicstl_config.h
|
||||
* @author wenjf (Orig5826@163.com)
|
||||
* @brief
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2025-04-22
|
||||
*
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef _UNICSTL_CONFIG_H_
|
||||
#define _UNICSTL_CONFIG_H_
|
||||
// clang-format off
|
||||
|
||||
// #define NDEBUG // release mode if define
|
||||
#ifndef NDEBUG
|
||||
@ -84,4 +85,5 @@
|
||||
|
||||
#endif // UNICSTL_DEBUG
|
||||
|
||||
#endif // _UNICSTL_CONFIG_H_
|
||||
// clang-format on
|
||||
#endif // _UNICSTL_CONFIG_H_
|
||||
|
||||
@ -28,37 +28,40 @@
|
||||
#include "iterator.h"
|
||||
#include "logger.h"
|
||||
|
||||
#define UNICSTL_VERSION_MAJOR 0
|
||||
#define UNICSTL_VERSION_MINOR 0
|
||||
#define UNICSTL_VERSION_MICRO 10
|
||||
#define UNICSTL_VERSION ((UNICSTL_VERSION_MAJOR << 16) | (UNICSTL_VERSION_MINOR << 8) | UNICSTL_VERSION_MICRO)
|
||||
|
||||
#define UNICSTL_TOSTRING_(x) #x
|
||||
#define UNICSTL_TOSTRING(x) UNICSTL_TOSTRING_(x)
|
||||
#define UNICSTL_VERSION_STRING UNICSTL_TOSTRING(UNICSTL_VERSION_MAJOR) "." UNICSTL_TOSTRING(UNICSTL_VERSION_MINOR) "." UNICSTL_TOSTRING(UNICSTL_VERSION_MICRO)
|
||||
|
||||
#define UNICSTL_UNUSED(x) (void)(x)
|
||||
// clang-format off
|
||||
#define UNICSTL_VERSION_MAJOR 0
|
||||
#define UNICSTL_VERSION_MINOR 0
|
||||
#define UNICSTL_VERSION_MICRO 10
|
||||
#define UNICSTL_VERSION ((UNICSTL_VERSION_MAJOR << 16) | (UNICSTL_VERSION_MINOR << 8) | UNICSTL_VERSION_MICRO)
|
||||
|
||||
#define UNICSTL_TOSTRING_(x) #x
|
||||
#define UNICSTL_TOSTRING(x) UNICSTL_TOSTRING_(x)
|
||||
#define UNICSTL_VERSION_STRING UNICSTL_TOSTRING(UNICSTL_VERSION_MAJOR) "." \
|
||||
UNICSTL_TOSTRING(UNICSTL_VERSION_MINOR) "." \
|
||||
UNICSTL_TOSTRING(UNICSTL_VERSION_MICRO)
|
||||
/**
|
||||
* @brief default capacity and ratio
|
||||
*
|
||||
*/
|
||||
#ifndef UNICSTL_CAPACITY_INIT
|
||||
#define UNICSTL_CAPACITY_INIT 8 // 若capacity参数为0时,自动分配默认初始容量
|
||||
#define UNICSTL_CAPACITY_INIT 8 // 若capacity参数为0时,自动分配默认初始容量
|
||||
#endif
|
||||
|
||||
#ifndef UNICSTL_CAPACITY_MAX
|
||||
#define UNICSTL_CAPACITY_MAX 8192 // 最大容量
|
||||
#define UNICSTL_CAPACITY_MAX 8192 // 最大容量
|
||||
#endif
|
||||
|
||||
#ifndef UNICSTL_OBJSIZE_MAX
|
||||
#define UNICSTL_OBJSIZE_MAX 8192 // 最大对象大小
|
||||
#define UNICSTL_OBJSIZE_MAX 8192 // 最大对象大小
|
||||
#endif
|
||||
|
||||
#ifndef UNICSTL_STATIC_MEMORY
|
||||
#define UNICSTL_STATIC_MEMORY
|
||||
#endif
|
||||
|
||||
#define UNICSTL_UNUSED(x) (void)(x)
|
||||
// clang-format on
|
||||
|
||||
/**
|
||||
* @brief assert function
|
||||
*
|
||||
@ -78,7 +81,8 @@ extern void _unicstl_assert(const char *expr, const char *file, int line);
|
||||
|
||||
#else
|
||||
#define unicstl_assert(expr) // assert(expr)
|
||||
#endif // UNICSTL_ASSERT_ENABLE
|
||||
|
||||
#endif // UNICSTL_ASSERT_ENABLE
|
||||
|
||||
/**
|
||||
* @brief malloc and free function
|
||||
@ -115,7 +119,7 @@ extern void unicstl_free(void *ptr);
|
||||
static inline void *unicstl_malloc(size_t size) { return NULL; }
|
||||
static inline void *unicstl_calloc(size_t num, size_t size) { return NULL; }
|
||||
static inline void *unicstl_realloc(void *ptr, size_t size) { return NULL; }
|
||||
static inline void unicstl_free(void *ptr) { }
|
||||
static inline void unicstl_free(void *ptr) {}
|
||||
#endif // UNICSTL_MALLOC_ENABLE
|
||||
|
||||
static inline const void *obj_at(const void *objs, size_t index, size_t obj_size)
|
||||
|
||||
321
src/segarray.c
321
src/segarray.c
@ -20,15 +20,6 @@ static inline size_t segarray_map_full(struct _segarray *self, size_t capacity)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void print_pos(struct _segarray *self)
|
||||
{
|
||||
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);
|
||||
@ -38,34 +29,47 @@ static bool segarray_push_back(struct _segarray *self, const void *obj)
|
||||
}
|
||||
|
||||
ringbuf_t map = self->_map;
|
||||
ringbuf_t mapfree = self->_mapfree;
|
||||
|
||||
if (self->_segtail == self->_segsize)
|
||||
{
|
||||
if (map->full(map))
|
||||
if(self->_mapfree->empty(mapfree))
|
||||
{
|
||||
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;
|
||||
// }
|
||||
if (map->full(map))
|
||||
{
|
||||
// need resize
|
||||
log_error("next, you need to realize it");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
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->_segtail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rawbuf_t seg = rawbuf_new(self->_obj_size, self->_capacity);
|
||||
if (seg == NULL)
|
||||
else
|
||||
{
|
||||
log_error("rawbuf_new failed!");
|
||||
return false;
|
||||
rawbuf_t seg;
|
||||
if (!mapfree->pop_back(mapfree, &seg))
|
||||
{
|
||||
log_error("mapfree->pop_back failed!");
|
||||
return false;
|
||||
}
|
||||
if (!map->push_back(map, &seg))
|
||||
{
|
||||
log_error("map->push_back failed!");
|
||||
return false;
|
||||
}
|
||||
self->_seghead = 0;
|
||||
}
|
||||
map->push_back(map, &seg);
|
||||
|
||||
self->_maptail = self->_maptail + 1;
|
||||
self->_segtail = 0;
|
||||
}
|
||||
|
||||
print_pos(self);
|
||||
|
||||
rawbuf_t seg;
|
||||
if (!map->back(map, &seg))
|
||||
{
|
||||
@ -94,35 +98,47 @@ static bool segarray_push_front(struct _segarray *self, const void *obj)
|
||||
}
|
||||
|
||||
ringbuf_t map = self->_map;
|
||||
ringbuf_t mapfree = self->_mapfree;
|
||||
|
||||
if (self->_seghead == 0)
|
||||
{
|
||||
log_debug("map->size = %d\n", map->size(map));
|
||||
if (map->full(map))
|
||||
if(self->_mapfree->empty(mapfree))
|
||||
{
|
||||
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;
|
||||
// }
|
||||
if (map->full(map))
|
||||
{
|
||||
// need resize
|
||||
log_error("next, you need to realize it");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
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->_seghead = self->_segsize;
|
||||
}
|
||||
}
|
||||
|
||||
rawbuf_t seg = rawbuf_new(self->_obj_size, self->_capacity);
|
||||
if (seg == NULL)
|
||||
else
|
||||
{
|
||||
log_error("rawbuf_new failed!");
|
||||
return false;
|
||||
rawbuf_t seg;
|
||||
if (!mapfree->pop_back(mapfree, &seg))
|
||||
{
|
||||
log_error("mapfree->pop_back failed!");
|
||||
return false;
|
||||
}
|
||||
if (!map->push_front(map, &seg))
|
||||
{
|
||||
log_error("map->push_back failed!");
|
||||
return false;
|
||||
}
|
||||
self->_seghead = self->_segsize;
|
||||
}
|
||||
map->push_front(map, &seg);
|
||||
|
||||
self->_maphead = self->_maphead - 1;
|
||||
self->_seghead = self->_segsize;
|
||||
}
|
||||
|
||||
print_pos(self);
|
||||
|
||||
rawbuf_t seg;
|
||||
if (!map->front(map, &seg))
|
||||
{
|
||||
@ -150,9 +166,8 @@ static bool segarray_pop_back(struct _segarray *self, void *obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
print_pos(self);
|
||||
|
||||
ringbuf_t map = self->_map;
|
||||
ringbuf_t mapfree = self->_mapfree;
|
||||
rawbuf_t seg;
|
||||
|
||||
size_t index = self->_segtail - 1;
|
||||
@ -173,10 +188,13 @@ static bool segarray_pop_back(struct _segarray *self, void *obj)
|
||||
if(self->_segtail == 0)
|
||||
{
|
||||
self->_segtail = self->_segsize;
|
||||
self->_maptail = self->_maptail - 1;
|
||||
|
||||
map->pop_back(map, &seg);
|
||||
rawbuf_free(&seg);
|
||||
if (!mapfree->push_back(mapfree, &seg))
|
||||
{
|
||||
log_error("mapfree->push_back failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("pop_back success!");
|
||||
@ -197,9 +215,9 @@ static bool segarray_pop_front(struct _segarray *self, void *obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
print_pos(self);
|
||||
|
||||
ringbuf_t map = self->_map;
|
||||
ringbuf_t mapfree = self->_mapfree;
|
||||
|
||||
size_t index = self->_seghead;
|
||||
if(obj != NULL)
|
||||
{
|
||||
@ -219,11 +237,15 @@ static bool segarray_pop_front(struct _segarray *self, void *obj)
|
||||
if(self->_seghead == self->_segsize)
|
||||
{
|
||||
self->_seghead = 0;
|
||||
self->_maphead = self->_maphead + 1;
|
||||
|
||||
rawbuf_t seg;
|
||||
map->pop_front(map, &seg);
|
||||
rawbuf_free(&seg);
|
||||
|
||||
if (!mapfree->push_back(mapfree, &seg))
|
||||
{
|
||||
log_error("mapfree->push_back failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
log_info("pop_front success!");
|
||||
@ -238,15 +260,7 @@ static bool segarray_back(struct _segarray *self, void *obj)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
return self->get(self, self->size(self) - 1, obj);
|
||||
}
|
||||
|
||||
static bool segarray_front(struct _segarray *self, void *obj)
|
||||
@ -256,15 +270,95 @@ static bool segarray_front(struct _segarray *self, void *obj)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return self->get(self, 0, obj);
|
||||
}
|
||||
|
||||
static bool segarray_calc_index(struct _segarray *self, size_t index, size_t *map_index, size_t *seg_index)
|
||||
{
|
||||
ringbuf_t map = self->_map;
|
||||
rawbuf_t seg;
|
||||
if (!map->front(map, &seg))
|
||||
rawbuf_t seg = NULL;
|
||||
size_t map_idx;
|
||||
size_t seg_idx;
|
||||
|
||||
size_t seg1_left = self->_segsize - self->_seghead;
|
||||
if(index < seg1_left)
|
||||
{
|
||||
map_idx = 0;
|
||||
seg_idx = self->_seghead + index;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t index_left = index - seg1_left;
|
||||
map_idx = index_left / self->_segsize + 1;
|
||||
seg_idx = index_left % self->_segsize;
|
||||
}
|
||||
*map_index = map_idx;
|
||||
*seg_index = seg_idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool segarray_set(struct _segarray *self, size_t index, const void *obj)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
if (index >= self->size(self) || obj == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
size_t index = self->_seghead;
|
||||
return seg->get(seg, index, obj);
|
||||
|
||||
ringbuf_t map = self->_map;
|
||||
rawbuf_t seg = NULL;
|
||||
size_t map_index;
|
||||
size_t seg_index;
|
||||
|
||||
segarray_calc_index(self, index, &map_index, &seg_index);
|
||||
|
||||
if (!map->get(map, map_index, &seg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return seg->set(seg, seg_index, obj);
|
||||
}
|
||||
|
||||
static bool segarray_get(struct _segarray *self, size_t index, void *obj)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
if (index >= self->size(self) || obj == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ringbuf_t map = self->_map;
|
||||
rawbuf_t seg = NULL;
|
||||
size_t map_index;
|
||||
size_t seg_index;
|
||||
|
||||
segarray_calc_index(self, index, &map_index, &seg_index);
|
||||
|
||||
if (!map->get(map, map_index, &seg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return seg->get(seg, seg_index, obj);
|
||||
}
|
||||
|
||||
static const void* segarray_at(struct _segarray *self, size_t index)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
if (index >= self->size(self))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ringbuf_t map = self->_map;
|
||||
rawbuf_t seg = NULL;
|
||||
size_t map_index;
|
||||
size_t seg_index;
|
||||
|
||||
segarray_calc_index(self, index, &map_index, &seg_index);
|
||||
|
||||
if (!map->get(map, map_index, &seg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return seg->at(seg, seg_index);
|
||||
}
|
||||
|
||||
static bool segarray_resize(struct _segarray *self, size_t capacity)
|
||||
@ -280,6 +374,7 @@ static bool segarray_resize(struct _segarray *self, size_t capacity)
|
||||
return false;
|
||||
}
|
||||
|
||||
log_error("you need to implement this function!");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -305,9 +400,14 @@ static bool segarray_full(struct _segarray *self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
size_t map_size = self->_map->size(self->_map);
|
||||
|
||||
return (self->_maphead == 0 && self->_seghead == 0) ||
|
||||
(self->_maptail == map_size - 1 && self->_segtail == self->_segsize - 1);
|
||||
if(self->_map->full(self->_map))
|
||||
{
|
||||
if(self->_seghead == 0 || self->_segtail == self->_segsize - 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool segarray_clear(struct _segarray *self)
|
||||
@ -317,7 +417,6 @@ static bool segarray_clear(struct _segarray *self)
|
||||
|
||||
self->_seghead = clac_start_index(self->_segsize);
|
||||
self->_segtail = self->_seghead;
|
||||
self->_maptail = self->_maphead;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -342,10 +441,17 @@ static void segarray_destory(struct _segarray *self)
|
||||
static void segarray_print(struct _segarray *self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
const void *obj = NULL;
|
||||
|
||||
for (size_t i = 0; i < self->size(self); i++)
|
||||
{
|
||||
self->print_obj(obj_at(self->obj, self->_obj_size, i));
|
||||
obj = self->at(self, i);
|
||||
if(obj == NULL)
|
||||
{
|
||||
log_error("objs[%ld] is NULL", i);
|
||||
return;
|
||||
}
|
||||
self->print_obj(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +459,6 @@ bool segarray_iter_hasnext(struct _iterator *iter)
|
||||
{
|
||||
unicstl_assert(iter != NULL);
|
||||
unicstl_assert(iter->_container != NULL);
|
||||
|
||||
segarray_t self = (segarray_t)iter->_container;
|
||||
|
||||
if (iter->_order == SEGARRAY_FORWARD)
|
||||
@ -377,52 +482,10 @@ const void *segarray_iter_next(struct _iterator *iter)
|
||||
{
|
||||
unicstl_assert(iter != NULL);
|
||||
unicstl_assert(iter->_container != NULL);
|
||||
|
||||
segarray_t self = (segarray_t)iter->_container;
|
||||
|
||||
const void *obj = NULL;
|
||||
size_t index = iter->_index;
|
||||
ringbuf_t map = self->_map;
|
||||
rawbuf_t seg = NULL;
|
||||
size_t map_index;
|
||||
size_t seg_index;
|
||||
|
||||
if (iter->_order == SEGARRAY_REVERSE)
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
obj = self->at(self, iter->_index);
|
||||
if (iter->_order == SEGARRAY_FORWARD)
|
||||
{
|
||||
iter->_index++;
|
||||
@ -443,14 +506,13 @@ iterator_t segarray_iter(struct _segarray *self, enum _segarray_order order)
|
||||
iter->_index = 0;
|
||||
iter->_order = order;
|
||||
|
||||
//..
|
||||
if (iter->_order == SEGARRAY_FORWARD)
|
||||
{
|
||||
iter->_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->_index = self->_map->size(self->_map);
|
||||
iter->_index = self->size(self) - 1;
|
||||
}
|
||||
|
||||
iter->hasnext = segarray_iter_hasnext;
|
||||
@ -494,10 +556,18 @@ bool segarray_init(struct _segarray *self, size_t obj_size, size_t capacity, voi
|
||||
return false;
|
||||
}
|
||||
|
||||
self->_mapfree = ringbuf_new(sizeof(rawbuf_t), 8);
|
||||
if (self->_mapfree == NULL)
|
||||
{
|
||||
ringbuf_free(&self->_map);
|
||||
return false;
|
||||
}
|
||||
|
||||
rawbuf_t seg = rawbuf_new(obj_size, self->_segsize);
|
||||
if (seg == NULL)
|
||||
{
|
||||
ringbuf_free(&self->_map);
|
||||
ringbuf_free(&self->_mapfree);
|
||||
return false;
|
||||
}
|
||||
// config first obj index in seg array
|
||||
@ -505,8 +575,6 @@ bool segarray_init(struct _segarray *self, size_t obj_size, size_t capacity, voi
|
||||
self->_segtail = self->_seghead;
|
||||
|
||||
// add first seg array to map
|
||||
self->_maphead = 0;
|
||||
self->_maptail = 1;
|
||||
self->_map->push_back(self->_map, &seg);
|
||||
}
|
||||
|
||||
@ -521,6 +589,11 @@ bool segarray_init(struct _segarray *self, size_t obj_size, size_t capacity, voi
|
||||
self->back = segarray_back;
|
||||
self->front = segarray_front;
|
||||
|
||||
// -------------------- random access --------------------
|
||||
self->set = segarray_set;
|
||||
self->get = segarray_get;
|
||||
self->at = segarray_at;
|
||||
|
||||
// base
|
||||
self->resize = segarray_resize;
|
||||
self->size = segarray_size;
|
||||
|
||||
@ -372,7 +372,6 @@ static void test_segarray_front_invalid(void)
|
||||
segarray_free(&segarray);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void test_segarray_set(void)
|
||||
{
|
||||
int temp = 0;
|
||||
@ -475,7 +474,6 @@ static void test_segarray_at(void)
|
||||
|
||||
segarray_free(&segarray);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_segarray_iter(void)
|
||||
{
|
||||
@ -767,11 +765,12 @@ static void test_segarray_struct(void)
|
||||
TEST_ASSERT_FALSE(segarray->back(segarray, &temp));
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_TRUE(segarray->empty(segarray));
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
TEST_ASSERT_TRUE(segarray->push_front(segarray, &data[i]));
|
||||
|
||||
|
||||
TEST_ASSERT_TRUE(segarray->front(segarray, &temp));
|
||||
TEST_ASSERT_EQUAL_INT(data[i].id, temp.id);
|
||||
TEST_ASSERT_EQUAL_STRING(data[i].name, temp.name);
|
||||
@ -855,13 +854,13 @@ void test_segarray(void)
|
||||
RUN_TEST(test_segarray_front_invalid);
|
||||
|
||||
// ---------- random access ----------
|
||||
// RUN_TEST(test_segarray_set);
|
||||
// RUN_TEST(test_segarray_set_invalid);
|
||||
RUN_TEST(test_segarray_set);
|
||||
RUN_TEST(test_segarray_set_invalid);
|
||||
|
||||
// RUN_TEST(test_segarray_at);
|
||||
RUN_TEST(test_segarray_at);
|
||||
|
||||
// ---------- base ----------
|
||||
// RUN_TEST(test_segarray_iter);
|
||||
RUN_TEST(test_segarray_iter);
|
||||
|
||||
// RUN_TEST(test_segarray_resize);
|
||||
// RUN_TEST(test_segarray_resize_invalid);
|
||||
@ -869,8 +868,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);
|
||||
RUN_TEST(test_segarray_struct);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user