mirror of
https://gitee.com/apaki/unicstl.git
synced 2026-05-28 22:54:19 +08:00
ringbuf: add random access
This commit is contained in:
parent
dcce634326
commit
d6a6bacbb0
@ -39,13 +39,13 @@ struct _darray
|
|||||||
bool (*append)(struct _darray *self, const void *obj); // O(1)
|
bool (*append)(struct _darray *self, const void *obj); // O(1)
|
||||||
bool (*pop)(struct _darray *self, void *obj); // O(1)
|
bool (*pop)(struct _darray *self, void *obj); // O(1)
|
||||||
|
|
||||||
bool (*insert)(struct _darray *self, size_t index, const void *obj); // O(n)
|
bool (*insert)(struct _darray *self, size_t index, const void *obj); // O(n)
|
||||||
bool (*remove)(struct _darray *self, size_t index, void *obj); // O(n)
|
bool (*remove)(struct _darray *self, size_t index, void *obj); // O(n)
|
||||||
|
|
||||||
bool (*set)(struct _darray *self, size_t index, const void *obj); // O(1)
|
// -------------------- random access --------------------
|
||||||
bool (*get)(struct _darray *self, size_t index, void *obj); // O(1)
|
bool (*set)(struct _darray *self, size_t index, const void *obj); // O(1)
|
||||||
|
bool (*get)(struct _darray *self, size_t index, void *obj); // O(1)
|
||||||
const void* (*at)(struct _darray *self, size_t index); // O(1)
|
const void* (*at)(struct _darray *self, size_t index); // O(1)
|
||||||
|
|
||||||
// base
|
// base
|
||||||
bool (*resize)(struct _darray *self, size_t capacity);
|
bool (*resize)(struct _darray *self, size_t capacity);
|
||||||
|
|||||||
@ -43,6 +43,11 @@ struct _ringbuf
|
|||||||
bool (*pop_front)(struct _ringbuf* self, void* obj);
|
bool (*pop_front)(struct _ringbuf* self, void* obj);
|
||||||
bool (*back)(struct _ringbuf* self, void* obj);
|
bool (*back)(struct _ringbuf* self, void* obj);
|
||||||
bool (*front)(struct _ringbuf* self, void* obj);
|
bool (*front)(struct _ringbuf* self, void* obj);
|
||||||
|
|
||||||
|
// -------------------- random access --------------------
|
||||||
|
bool (*set)(struct _ringbuf *self, size_t index, const void *obj); // O(1)
|
||||||
|
bool (*get)(struct _ringbuf *self, size_t index, void *obj); // O(1)
|
||||||
|
const void* (*at)(struct _ringbuf *self, size_t index); // O(1)
|
||||||
|
|
||||||
// base
|
// base
|
||||||
bool (*resize)(struct _ringbuf *self, size_t capacity);
|
bool (*resize)(struct _ringbuf *self, size_t capacity);
|
||||||
|
|||||||
@ -20,6 +20,11 @@ static inline size_t index_prev(size_t index, size_t capacity)
|
|||||||
return index == 0 ? (capacity - 1) : index - 1;
|
return index == 0 ? (capacity - 1) : index - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t ring_index(size_t head, size_t index, size_t capacity)
|
||||||
|
{
|
||||||
|
return (head + index) % capacity;
|
||||||
|
}
|
||||||
|
|
||||||
static bool ringbuf_push_back(struct _ringbuf *self, const void *obj)
|
static bool ringbuf_push_back(struct _ringbuf *self, const void *obj)
|
||||||
{
|
{
|
||||||
unicstl_assert(self != NULL);
|
unicstl_assert(self != NULL);
|
||||||
@ -143,6 +148,47 @@ static bool ringbuf_front(struct _ringbuf *self, void *obj)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ringbuf_set(struct _ringbuf *self, size_t index, const void *obj)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
if (index >= self->size(self) || obj == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
index = ring_index(self->_head, index, self->_capacity);
|
||||||
|
|
||||||
|
size_t offset = index * self->_obj_size;
|
||||||
|
memmove((char *)self->obj + offset, obj, self->_obj_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ringbuf_get(struct _ringbuf *self, size_t index, void *obj)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
if (index >= self->size(self) || obj == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
index = ring_index(self->_head, index, self->_capacity);
|
||||||
|
|
||||||
|
size_t offset = index * self->_obj_size;
|
||||||
|
memmove(obj, (char *)self->obj + offset, self->_obj_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const void* ringbuf_at(struct _ringbuf *self, size_t index)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
if (index >= self->size(self))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
index = ring_index(self->_head, index, self->_capacity);
|
||||||
|
|
||||||
|
size_t offset = index * self->_obj_size;
|
||||||
|
return (const char *)self->obj + offset;
|
||||||
|
}
|
||||||
|
|
||||||
static bool ringbuf_resize(struct _ringbuf *self, size_t capacity)
|
static bool ringbuf_resize(struct _ringbuf *self, size_t capacity)
|
||||||
{
|
{
|
||||||
unicstl_assert(self != NULL);
|
unicstl_assert(self != NULL);
|
||||||
@ -374,6 +420,11 @@ bool ringbuf_init(struct _ringbuf *self, size_t obj_size, size_t capacity, void
|
|||||||
self->back = ringbuf_back;
|
self->back = ringbuf_back;
|
||||||
self->front = ringbuf_front;
|
self->front = ringbuf_front;
|
||||||
|
|
||||||
|
// random access
|
||||||
|
self->get = ringbuf_get;
|
||||||
|
self->set = ringbuf_set;
|
||||||
|
self->at = ringbuf_at;
|
||||||
|
|
||||||
// base
|
// base
|
||||||
self->resize = ringbuf_resize;
|
self->resize = ringbuf_resize;
|
||||||
self->size = ringbuf_size;
|
self->size = ringbuf_size;
|
||||||
|
|||||||
@ -280,6 +280,47 @@ static void test_darray_set_invalid(void)
|
|||||||
darray_free(&darray);
|
darray_free(&darray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_darray_at(void)
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
|
||||||
|
size_t len = sizeof(data) / sizeof(data[0]);
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
darray_t darray = darray_new(sizeof(int), len);
|
||||||
|
darray->compare = compare_num;
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
darray->append(darray, &data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *p_int = NULL;
|
||||||
|
p_int = darray->at(darray, 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, *p_int);
|
||||||
|
|
||||||
|
p_int = darray->at(darray, 4);
|
||||||
|
TEST_ASSERT_EQUAL_INT(5, *p_int);
|
||||||
|
|
||||||
|
p_int = darray->at(darray, 9);
|
||||||
|
TEST_ASSERT_EQUAL_INT(10, *p_int);
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(darray->at(darray, 10));
|
||||||
|
TEST_ASSERT_NULL(darray->at(darray, -1));
|
||||||
|
|
||||||
|
|
||||||
|
// warning: initialization discards 'const' qualifier from pointer target type
|
||||||
|
// int *p_int_warring = darray->at(darray, 0);
|
||||||
|
|
||||||
|
// !!! you should not do this.
|
||||||
|
int *p_int_warring = (int *)darray->at(darray, 0);
|
||||||
|
*p_int_warring = 100;
|
||||||
|
|
||||||
|
darray->get(darray, 0, &temp);
|
||||||
|
TEST_ASSERT_EQUAL_INT(100, temp);
|
||||||
|
|
||||||
|
darray_free(&darray);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_darray_resize(void)
|
static void test_darray_resize(void)
|
||||||
{
|
{
|
||||||
int temp = 0;
|
int temp = 0;
|
||||||
@ -397,48 +438,6 @@ static void test_darray_index_invalid(void)
|
|||||||
darray_free(&darray);
|
darray_free(&darray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void test_darray_at(void)
|
|
||||||
{
|
|
||||||
int temp = 0;
|
|
||||||
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
|
|
||||||
size_t len = sizeof(data) / sizeof(data[0]);
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
darray_t darray = darray_new(sizeof(int), len);
|
|
||||||
darray->compare = compare_num;
|
|
||||||
for(i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
darray->append(darray, &data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int *p_int = NULL;
|
|
||||||
p_int = darray->at(darray, 0);
|
|
||||||
TEST_ASSERT_EQUAL_INT(1, *p_int);
|
|
||||||
|
|
||||||
p_int = darray->at(darray, 4);
|
|
||||||
TEST_ASSERT_EQUAL_INT(5, *p_int);
|
|
||||||
|
|
||||||
p_int = darray->at(darray, 9);
|
|
||||||
TEST_ASSERT_EQUAL_INT(10, *p_int);
|
|
||||||
|
|
||||||
TEST_ASSERT_NULL(darray->at(darray, 10));
|
|
||||||
TEST_ASSERT_NULL(darray->at(darray, -1));
|
|
||||||
|
|
||||||
|
|
||||||
// warning: initialization discards 'const' qualifier from pointer target type
|
|
||||||
// int *p_int_warring = darray->at(darray, 0);
|
|
||||||
|
|
||||||
// !!! you should not do this.
|
|
||||||
int *p_int_warring = (int *)darray->at(darray, 0);
|
|
||||||
*p_int_warring = 100;
|
|
||||||
|
|
||||||
darray->get(darray, 0, &temp);
|
|
||||||
TEST_ASSERT_EQUAL_INT(100, temp);
|
|
||||||
|
|
||||||
darray_free(&darray);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_darray_dynamic(void)
|
static void test_darray_dynamic(void)
|
||||||
{
|
{
|
||||||
int temp = 0;
|
int temp = 0;
|
||||||
@ -688,14 +687,14 @@ void test_darray(void)
|
|||||||
RUN_TEST(test_darray_set);
|
RUN_TEST(test_darray_set);
|
||||||
RUN_TEST(test_darray_set_invalid);
|
RUN_TEST(test_darray_set_invalid);
|
||||||
|
|
||||||
|
RUN_TEST(test_darray_at);
|
||||||
|
|
||||||
RUN_TEST(test_darray_resize);
|
RUN_TEST(test_darray_resize);
|
||||||
RUN_TEST(test_darray_resize_invalid);
|
RUN_TEST(test_darray_resize_invalid);
|
||||||
|
|
||||||
RUN_TEST(test_darray_index); // index, search, contains
|
RUN_TEST(test_darray_index); // index, search, contains
|
||||||
RUN_TEST(test_darray_index_invalid);
|
RUN_TEST(test_darray_index_invalid);
|
||||||
|
|
||||||
RUN_TEST(test_darray_at);
|
|
||||||
|
|
||||||
RUN_TEST(test_darray_dynamic);
|
RUN_TEST(test_darray_dynamic);
|
||||||
|
|
||||||
RUN_TEST(test_darray_iter);
|
RUN_TEST(test_darray_iter);
|
||||||
|
|||||||
@ -373,6 +373,110 @@ static void test_ringbuf_front_invalid(void)
|
|||||||
ringbuf_free(&ringbuf);
|
ringbuf_free(&ringbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_ringbuf_set(void)
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
|
||||||
|
size_t len = sizeof(data) / sizeof(data[0]);
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
ringbuf_t ringbuf = ringbuf_new(sizeof(int), len);
|
||||||
|
// ringbuf->compare = compare_num;
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->push_back(ringbuf, &data[i]));
|
||||||
|
TEST_ASSERT_EQUAL_INT(i + 1, ringbuf->size(ringbuf));
|
||||||
|
|
||||||
|
size_t index = ringbuf->size(ringbuf) - 1;
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->get(ringbuf, index, &temp));
|
||||||
|
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = 0x11;
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->set(ringbuf, 0, &temp));
|
||||||
|
temp = 0x22;
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->set(ringbuf, 5, &temp));
|
||||||
|
temp = 0x33;
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->set(ringbuf, 9, &temp));
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->get(ringbuf, 0, &temp));
|
||||||
|
TEST_ASSERT_EQUAL_INT(0x11, temp);
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->get(ringbuf, 5, &temp));
|
||||||
|
TEST_ASSERT_EQUAL_INT(0x22, temp);
|
||||||
|
TEST_ASSERT_TRUE(ringbuf->get(ringbuf, 9, &temp));
|
||||||
|
TEST_ASSERT_EQUAL_INT(0x33, temp);
|
||||||
|
|
||||||
|
ringbuf_free(&ringbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ringbuf_set_invalid(void)
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
|
||||||
|
size_t len = sizeof(data) / sizeof(data[0]);
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
ringbuf_t ringbuf = ringbuf_new(sizeof(int), len);
|
||||||
|
// ringbuf->compare = compare_num;
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
ringbuf->push_back(ringbuf, &data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- invalid index ----------
|
||||||
|
temp = 0x11;
|
||||||
|
TEST_ASSERT_FALSE(ringbuf->set(ringbuf, -1, &temp));
|
||||||
|
TEST_ASSERT_FALSE(ringbuf->set(ringbuf, len, &temp));
|
||||||
|
TEST_ASSERT_FALSE(ringbuf->set(ringbuf, 999, &temp));
|
||||||
|
|
||||||
|
TEST_ASSERT_FALSE(ringbuf->set(ringbuf, 0, NULL));
|
||||||
|
|
||||||
|
ringbuf_free(&ringbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ringbuf_at(void)
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
|
||||||
|
size_t len = sizeof(data) / sizeof(data[0]);
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
ringbuf_t ringbuf = ringbuf_new(sizeof(int), len);
|
||||||
|
// ringbuf->compare = compare_num;
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
ringbuf->push_back(ringbuf, &data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *p_int = NULL;
|
||||||
|
p_int = ringbuf->at(ringbuf, 0);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, *p_int);
|
||||||
|
|
||||||
|
p_int = ringbuf->at(ringbuf, 4);
|
||||||
|
TEST_ASSERT_EQUAL_INT(5, *p_int);
|
||||||
|
|
||||||
|
p_int = ringbuf->at(ringbuf, 9);
|
||||||
|
TEST_ASSERT_EQUAL_INT(10, *p_int);
|
||||||
|
|
||||||
|
TEST_ASSERT_NULL(ringbuf->at(ringbuf, 10));
|
||||||
|
TEST_ASSERT_NULL(ringbuf->at(ringbuf, -1));
|
||||||
|
|
||||||
|
// warning: initialization discards 'const' qualifier from pointer target type
|
||||||
|
// int *p_int_warring = ringbuf->at(ringbuf, 0);
|
||||||
|
|
||||||
|
// !!! you should not do this.
|
||||||
|
int *p_int_warring = (int *)ringbuf->at(ringbuf, 0);
|
||||||
|
*p_int_warring = 100;
|
||||||
|
|
||||||
|
ringbuf->get(ringbuf, 0, &temp);
|
||||||
|
TEST_ASSERT_EQUAL_INT(100, temp);
|
||||||
|
|
||||||
|
ringbuf_free(&ringbuf);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_ringbuf_iter(void)
|
static void test_ringbuf_iter(void)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@ -750,6 +854,13 @@ void test_ringbuf(void)
|
|||||||
RUN_TEST(test_ringbuf_front);
|
RUN_TEST(test_ringbuf_front);
|
||||||
RUN_TEST(test_ringbuf_front_invalid);
|
RUN_TEST(test_ringbuf_front_invalid);
|
||||||
|
|
||||||
|
// ---------- random access ----------
|
||||||
|
RUN_TEST(test_ringbuf_set);
|
||||||
|
RUN_TEST(test_ringbuf_set_invalid);
|
||||||
|
|
||||||
|
RUN_TEST(test_ringbuf_at);
|
||||||
|
|
||||||
|
// ---------- base ----------
|
||||||
RUN_TEST(test_ringbuf_iter);
|
RUN_TEST(test_ringbuf_iter);
|
||||||
|
|
||||||
RUN_TEST(test_ringbuf_resize);
|
RUN_TEST(test_ringbuf_resize);
|
||||||
@ -758,9 +869,8 @@ void test_ringbuf(void)
|
|||||||
|
|
||||||
RUN_TEST(test_ringbuf_dynamic);
|
RUN_TEST(test_ringbuf_dynamic);
|
||||||
|
|
||||||
// ---------- base ----------
|
|
||||||
RUN_TEST(test_ringbuf_status);
|
RUN_TEST(test_ringbuf_status);
|
||||||
|
|
||||||
// ---------- ext ----------
|
// ---------- ext ----------
|
||||||
RUN_TEST(test_ringbuf_struct);
|
RUN_TEST(test_ringbuf_struct);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user