Compare commits

...

10 Commits

6 changed files with 572 additions and 9 deletions

View File

@ -27,6 +27,8 @@
"unicstl_config.h": "c", "unicstl_config.h": "c",
"iter.h": "c", "iter.h": "c",
"iterator.h": "c", "iterator.h": "c",
"assert.h": "c" "assert.h": "c",
"limits.h": "c",
"cstdint": "c"
} }
} }

View File

@ -39,4 +39,9 @@
*/ */
typedef int (*compare_fun_t)(void* obj, void* obj2); typedef int (*compare_fun_t)(void* obj, void* obj2);
// default function
int default_compare(void* obj1, void* obj2);
void default_print_obj(void* obj);
#endif // _COMMON_H_ #endif // _COMMON_H_

View File

@ -18,6 +18,8 @@
#include "common.h" #include "common.h"
#include "iterator.h" #include "iterator.h"
#define LIST_UNLIMITED INT32_MAX
struct _list struct _list
{ {
// -------------------- private -------------------- // -------------------- private --------------------
@ -56,13 +58,13 @@ struct _list
// iter // iter
iterator_t (*iter)(struct _list *self); iterator_t (*iter)(struct _list *self);
// config // others
compare_fun_t compare; // !!! you have to implement this function
// copy
struct _list* (*slice)(struct _list *self, int start, int end, int step); struct _list* (*slice)(struct _list *self, int start, int end, int step);
// struct _list* (*copy)(struct _list *self); // struct _list* (*copy)(struct _list *self);
// config
compare_fun_t compare; // !!! you have to implement this function
// -------------------- debug -------------------- // -------------------- debug --------------------
void (*print)(struct _list *self); void (*print)(struct _list *self);
void (*print_obj)(void *obj); void (*print_obj)(void *obj);

View File

@ -189,6 +189,142 @@ static void list_print(struct _list* self)
} }
} }
/**
* @brief list slice
* if index < 0, from the end of list. for example:
* list[-1] is the last element in list.
*
* @param self
* @param start start index
* @param end end index
* @param step step, if step < 0, return a reverse list.
* @return struct _list*
* a copy of the list, from start to end, step by step.
* if step < 0, return a reverse list.
* if step > 0, return a forward list.
* if step == 0, return NULL.
*/
struct _list* list_slice(struct _list *self, int start, int end, int step)
{
assert(self != NULL);
int i = 0;
bool unlimited = false;
if(step == 0)
{
return NULL;
}
if(step > 0)
{
if(start == LIST_UNLIMITED)
{
start = 0;
}
if(end == LIST_UNLIMITED)
{
end = self->size(self);
}
}
else
{
if(start == LIST_UNLIMITED)
{
start = self->size(self) - 1;
unlimited = true;
}
if(end == LIST_UNLIMITED)
{
end = 0;
unlimited = true;
}
}
if(start < 0)
{
if(start < -self->size(self))
{
start = -self->size(self);
}
start += self->size(self);
}
if(end < 0)
{
if(end < -self->size(self))
{
end = -self->size(self);
}
end += self->size(self);
}
// printf("start = %d\n", start);
// printf("end = %d\n", end);
uint32_t capicity = (end - start == 0) ? 1 : abs(end - start);
list_t list = list_new2(self->_obj_size, capicity);
if(list == NULL)
{
return NULL;
}
list->compare = self->compare;
list->print_obj = self->print_obj;
if(capicity == 0 || start > self->size(self) || end > self->size(self))
{
goto done;
}
if(step > 0)
{
if(start > end)
{
goto done;
}
if(unlimited != true)
{
for(i = start; i < end; i += step)
{
list->append(list, (char*)self->obj + i * self->_obj_size);
}
}
else
{
for(i = start; i <= end; i += step)
{
list->append(list, (char*)self->obj + i * self->_obj_size);
}
}
}
else /*if(step < 0)*/
{
if(start < end)
{
goto done;
}
if(unlimited != true)
{
for(i = start; i > end; i += step)
{
list->append(list, (char*)self->obj + i * self->_obj_size);
}
}
else
{
for(i = start; i >= end; i += step)
{
list->append(list, (char*)self->obj + i * self->_obj_size);
}
}
}
done:
return list;
}
static bool list_iter_hasnext(struct _iterator* iter) static bool list_iter_hasnext(struct _iterator* iter)
{ {
list_t self = (list_t)iter->_container; list_t self = (list_t)iter->_container;
@ -270,7 +406,13 @@ static bool list_init2(struct _list* list, uint32_t obj_size, uint32_t capacity)
// iter // iter
list->iter = list_iter; list->iter = list_iter;
// -------------------- debug -------------------- // others
list->slice = list_slice;
// config
list->compare = default_compare;
// -------------------- debug --------------------
list->print_obj = default_print_obj;
list->print = list_print; list->print = list_print;
return true; return true;

23
src/unicstl_internal.c Normal file
View File

@ -0,0 +1,23 @@
/**
* @file unicstl_internal.c
* @author wenjf (Orig5826@163.com)
* @brief
* @version 0.1
* @date 2025-04-29
*
* @copyright Copyright (c) 2025
*
*/
#include "common.h"
int default_compare(void* obj1, void* obj2)
{
printf("compare is not implemented!\n");
assert(0);
}
void default_print_obj(void* obj)
{
printf("print_obj is not implemented!\n");
assert(0);
}

View File

@ -26,7 +26,6 @@ static void test_list_new(void)
TEST_ASSERT_NULL(list_new2(sizeof(int), 0)); TEST_ASSERT_NULL(list_new2(sizeof(int), 0));
} }
static void test_list_append(void) static void test_list_append(void)
{ {
int temp = 0; int temp = 0;
@ -62,7 +61,6 @@ static void test_list_append(void)
list_free(&list); list_free(&list);
} }
static void test_list_pop(void) static void test_list_pop(void)
{ {
int temp = 0; int temp = 0;
@ -87,6 +85,78 @@ static void test_list_pop(void)
list_free(&list); list_free(&list);
} }
static void test_list_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;
list_t list = NULL;
// ------------------------------
list = list_new2(sizeof(int), len);
list->print_obj = print_num;
TEST_ASSERT_TRUE(list->empty(list));
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(list->insert(list, i, &data[i]));
TEST_ASSERT_EQUAL_INT(i + 1, list->size(list));
TEST_ASSERT_TRUE(list->get(list, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
// list->print(list);
// printf("\n");
}
list->clear(list);
TEST_ASSERT_TRUE(list->empty(list));
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(list->insert(list, 0, &data[i]));
TEST_ASSERT_EQUAL_INT(i + 1, list->size(list));
TEST_ASSERT_TRUE(list->get(list, 0, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
// list->print(list);
// printf("\n");
}
TEST_ASSERT_FALSE(list->empty(list));
list_free(&list);
}
static void test_list_delete(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;
list_t list = NULL;
// ------------------------------
list = list_new2(sizeof(int), len);
for (i = 0; i < len; i++)
{
list->append(list, &data[i]);
}
TEST_ASSERT_TRUE(list->delete(list, len - 1, &temp));
TEST_ASSERT_EQUAL_INT(data[len - 1], temp);
for (i = 0; i < len - 1; i++)
{
TEST_ASSERT_TRUE(list->delete(list, 0, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
}
TEST_ASSERT_TRUE(list->empty(list));
TEST_ASSERT_FALSE(list->pop(list, &temp));
list_free(&list);
}
static void test_list_clear(void) static void test_list_clear(void)
{ {
@ -322,7 +392,6 @@ void test_list_iter(void)
list_free(&list); list_free(&list);
} }
static void test_list_index(void) static void test_list_index(void)
{ {
int temp = 0; int temp = 0;
@ -350,13 +419,328 @@ static void test_list_index(void)
list_free(&list); list_free(&list);
} }
static void test_list_slice_empty(void)
{
int temp = 0;
int data[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
uint32_t len = sizeof(data) / sizeof(data[0]);
uint32_t i = 0;
list_t list = NULL;
list_t list2 = NULL;
// ------------------------------
list = list_new2(sizeof(int), len);
list->compare = compare_num;
list->print_obj = print_num;
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(list->append(list, &data[i]));
}
// -------------------- NULL --------------------
// python: list[0:] -> []
list2 = list->slice(list, 1, 5, 0); // if step == 0
TEST_ASSERT_NULL(list2);
// list_free(&list2);
// -------------------- empty --------------------
list2 = list->slice(list, 0, 0, 1); // if start == end
TEST_ASSERT_NOT_NULL(list2);
TEST_ASSERT_TRUE(list2->empty(list2));
list_free(&list2);
list2 = list->slice(list, 1, 5, -1); // if start < end && step < 0
TEST_ASSERT_NOT_NULL(list2);
TEST_ASSERT_TRUE(list2->empty(list2));
list_free(&list2);
list2 = list->slice(list, 5, 1, 1); // if start > end && step > 0
TEST_ASSERT_NOT_NULL(list2);
TEST_ASSERT_TRUE(list2->empty(list2));
list_free(&list2);
list2 = list->slice(list, -1, -5, 1); // if start < end && step < 0
TEST_ASSERT_NOT_NULL(list2);
TEST_ASSERT_TRUE(list2->empty(list2));
list_free(&list2);
list2 = list->slice(list, -5, -1, -1); // if start > end && step > 0
TEST_ASSERT_NOT_NULL(list2);
TEST_ASSERT_TRUE(list2->empty(list2));
list_free(&list2);
list_free(&list);
}
static void test_list_slice_positive(void)
{
int temp = 0;
int data[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
uint32_t len = sizeof(data) / sizeof(data[0]);
uint32_t i = 0;
list_t list = NULL;
list_t list2 = NULL;
// ------------------------------
list = list_new2(sizeof(int), len);
list->compare = compare_num;
list->print_obj = print_num;
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(list->append(list, &data[i]));
}
// -------------------- elements --------------------
// python: list[0:]
list2 = list->slice(list, 0, len, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(len, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
}
list_free(&list2);
// python: list[-6:8] or list[-6:-2] or list[4:8]
list2 = list->slice(list, 4, 8, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(4, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[len - 6 + i], temp);
}
list_free(&list2);
// python: list[4:0:-1]
list2 = list->slice(list, 4, 0, -1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(4, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[list2->size(list2) - i], temp);
}
list_free(&list2);
// python: list[::2]
list2 = list->slice(list, 0, len, 2);
TEST_ASSERT_NOT_NULL(list2);
// list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(5, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i * 2], temp);
}
list_free(&list2);
list_free(&list);
}
static void test_list_slice_negative(void)
{
int temp = 0;
int data[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
uint32_t len = sizeof(data) / sizeof(data[0]);
uint32_t i = 0;
list_t list = NULL;
list_t list2 = NULL;
// ------------------------------
list = list_new2(sizeof(int), len);
list->compare = compare_num;
list->print_obj = print_num;
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(list->append(list, &data[i]));
}
// -------------------- elements --------------------
// python: list[:-1]
list2 = list->slice(list, 0, -1, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(len - 1, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
}
list_free(&list2);
// python: list[:-1]
list2 = list->slice(list, -1, len, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(1, list2->size(list2));
TEST_ASSERT_TRUE(list2->get(list2, 0, &temp));
TEST_ASSERT_EQUAL_INT(data[len - 1], temp);
list_free(&list2);
// python: list[-6:8] or list[-6:-2]
// list2 = list->slice(list, -6, 8, 1); // It can be executed, but it's not intuitive
list2 = list->slice(list, -6, -2, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(4, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[len - 6 + i], temp);
}
list_free(&list2);
// -------------------- step == 2 --------------------
// python: list[::-2]
list2 = list->slice(list, len-1, 0, -2);
TEST_ASSERT_NOT_NULL(list2);
// list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(5, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[9 - i * 2], temp);
}
list_free(&list2);
// -------------------- step == 2 --------------------
// list[-30:-1]
list2 = list->slice(list, -30, -1, 1);
TEST_ASSERT_NOT_NULL(list2);
// list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(len - 1, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
}
list_free(&list2);
// list[-30:-10]
list2 = list->slice(list, -30, -10, 1);
TEST_ASSERT_NOT_NULL(list2);
TEST_ASSERT_TRUE(list2->empty(list2));
list_free(&list2);
list_free(&list);
}
static void test_list_slice_unlimited(void)
{
int temp = 0;
int data[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
uint32_t len = sizeof(data) / sizeof(data[0]);
uint32_t i = 0;
list_t list = NULL;
list_t list2 = NULL;
// ------------------------------
list = list_new2(sizeof(int), len);
list->compare = compare_num;
list->print_obj = print_num;
for (i = 0; i < len; i++)
{
TEST_ASSERT_TRUE(list->append(list, &data[i]));
}
// -------------------- umlimited --------------------
// python: list[0:]
list2 = list->slice(list, 0, LIST_UNLIMITED, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(len, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
}
list_free(&list2);
// python: list[4::-1]
list2 = list->slice(list, 4, LIST_UNLIMITED, -1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(5, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[list2->size(list2) - 1 - i], temp);
}
list_free(&list2);
list2 = list->slice(list, LIST_UNLIMITED, LIST_UNLIMITED, 1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(len, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i], temp);
}
list_free(&list2);
list2 = list->slice(list, LIST_UNLIMITED, LIST_UNLIMITED, -1);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(len, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[list2->size(list2) - 1 - i], temp);
}
list_free(&list2);
// -------------------- step == 2 --------------------
list2 = list->slice(list, LIST_UNLIMITED, LIST_UNLIMITED, 2);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(5, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[i * 2], temp);
}
list_free(&list2);
list2 = list->slice(list, LIST_UNLIMITED, LIST_UNLIMITED, -2);
TEST_ASSERT_NOT_NULL(list2);
//list2->print(list2); printf("\n");
TEST_ASSERT_EQUAL_INT(5, list2->size(list2));
for(i = 0; i < list2->size(list2); i++)
{
TEST_ASSERT_TRUE(list2->get(list2, i, &temp));
TEST_ASSERT_EQUAL_INT(data[9 - i*2], temp);
}
list_free(&list2);
list_free(&list);
}
void test_list(void) void test_list(void)
{ {
UnitySetTestFile(__FILE__); UnitySetTestFile(__FILE__);
RUN_TEST(test_list_new); RUN_TEST(test_list_new);
RUN_TEST(test_list_append); RUN_TEST(test_list_append);
RUN_TEST(test_list_pop); RUN_TEST(test_list_pop);
RUN_TEST(test_list_insert);
RUN_TEST(test_list_delete);
RUN_TEST(test_list_clear); RUN_TEST(test_list_clear);
RUN_TEST(test_list_num); RUN_TEST(test_list_num);
@ -365,4 +749,9 @@ void test_list(void)
RUN_TEST(test_list_iter); RUN_TEST(test_list_iter);
RUN_TEST(test_list_index); RUN_TEST(test_list_index);
RUN_TEST(test_list_slice_empty);
RUN_TEST(test_list_slice_positive);
RUN_TEST(test_list_slice_negative);
RUN_TEST(test_list_slice_unlimited);
} }