mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-05-18 03:51:35 +08:00
368 lines
7.6 KiB
C
368 lines
7.6 KiB
C
/**
|
|
* @file list.c
|
|
* @author wenjf (Orig5826@163.com)
|
|
* @brief
|
|
* @version 0.1
|
|
* @date 2024-06-23
|
|
*
|
|
* @copyright Copyright (c) 2024
|
|
*
|
|
*/
|
|
#include "list.h"
|
|
|
|
|
|
static bool list_insert(struct _list* self, int index, void* obj)
|
|
{
|
|
// assert(index >= 0 && index < (int)self->size(self));
|
|
// assert(index >= 0 && index <= (int)self->size(self));
|
|
if(index < 0 || index > (int)self->size(self))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (self->size(self) == self->_capacity)
|
|
{
|
|
int capacity = self->_capacity * self->_ratio;
|
|
void* obj_new = (void *)realloc(self->obj, capacity * self->_obj_size);
|
|
if (obj_new == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
self->obj = obj_new;
|
|
self->_capacity = capacity;
|
|
}
|
|
uint32_t offset = index * self->_obj_size;
|
|
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 list_delete(struct _list* self, int index, void* obj)
|
|
{
|
|
assert(self != NULL);
|
|
// assert(index >= (int)(0 - self->size(self)) && index < (int)self->size(self));
|
|
if(index < (int)(0 - self->size(self)) || index >= (int)self->size(self))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (self->empty(self))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (index < 0)
|
|
{
|
|
index += self->size(self);
|
|
}
|
|
|
|
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 list_append(struct _list* self, void* obj)
|
|
{
|
|
return self->insert(self, (int)self->size(self), obj);
|
|
}
|
|
|
|
static bool list_pop(struct _list* self, void* obj)
|
|
{
|
|
if (self->empty(self))
|
|
{
|
|
return false;
|
|
}
|
|
return self->delete(self, (int)self->size(self) - 1, obj);
|
|
}
|
|
|
|
static int list_index(struct _list* self, void* obj)
|
|
{
|
|
assert(self != NULL);
|
|
int index = 0;
|
|
if(obj == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
while(index < (int)self->size(self))
|
|
{
|
|
if(self->compare(self->obj + index * self->_obj_size, obj) == 0)
|
|
{
|
|
return index;
|
|
}
|
|
index++;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static bool list_clear(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
self->_size = 0;
|
|
return true;
|
|
}
|
|
|
|
static bool list_get(struct _list* self, int index, void* obj)
|
|
{
|
|
assert(self != NULL);
|
|
assert(obj != NULL);
|
|
assert(index >= (int)(0 - self->size(self)) && index < (int)self->size(self));
|
|
|
|
if (index < 0)
|
|
{
|
|
index += self->size(self);
|
|
}
|
|
uint32_t offset = index * self->_obj_size;
|
|
memmove(obj, (char*)self->obj + offset, self->_obj_size);
|
|
return true;
|
|
}
|
|
|
|
static bool list_set(struct _list* self, int index, void* obj)
|
|
{
|
|
assert(self != NULL);
|
|
assert(index >= (int)(0 - self->size(self)) && index < (int)self->size(self));
|
|
if (index < 0)
|
|
{
|
|
index += self->size(self);
|
|
}
|
|
uint32_t offset = index * self->_obj_size;
|
|
memmove((char*)self->obj + offset, obj, self->_obj_size);
|
|
return true;
|
|
}
|
|
|
|
static uint32_t list_size(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
return self->_size;
|
|
}
|
|
|
|
static uint32_t list_capacity(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
return self->_capacity;
|
|
}
|
|
|
|
static bool list_empty(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
return !self->size(self);
|
|
}
|
|
|
|
// free
|
|
static void list_destory(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
if (self->obj != NULL)
|
|
{
|
|
free(self->obj);
|
|
}
|
|
}
|
|
|
|
// print
|
|
static void list_print(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
|
|
if (!self->empty(self))
|
|
{
|
|
void* obj = NULL;
|
|
|
|
for (uint32_t i = 0; i < self->size(self); i++)
|
|
{
|
|
obj = (char*)self->obj + i * self->_obj_size;
|
|
self->print_obj(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct _list* list_slice(struct _list *self, int start, int end, int step)
|
|
{
|
|
assert(self != NULL);
|
|
if(step == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if(start < 0)
|
|
{
|
|
start += self->size(self);
|
|
}
|
|
|
|
if(end < 0)
|
|
{
|
|
end += self->size(self);
|
|
}
|
|
|
|
list_t list = list_new2(self->_obj_size, end - start);
|
|
if(list == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if(step > 0)
|
|
{
|
|
if(start >= end)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uint32_t temp = 0;
|
|
if(start <= end)
|
|
{
|
|
return NULL;
|
|
}
|
|
// start ^= end;
|
|
// end ^= start;
|
|
// start ^= end;
|
|
temp = start;
|
|
start = end;
|
|
end = temp;
|
|
step = -step;
|
|
}
|
|
|
|
for(int i = start; i < end; i += step)
|
|
{
|
|
if(i >= self->size(self))
|
|
{
|
|
break;
|
|
}
|
|
list->append(list, (char*)self->obj + i * self->_obj_size);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static bool list_iter_hasnext(struct _iterator* iter)
|
|
{
|
|
list_t self = (list_t)iter->_container;
|
|
|
|
if(iter->_index < self->size(self))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static const void* list_iter_next(struct _iterator* iter)
|
|
{
|
|
list_t self = (list_t)iter->_container;
|
|
void *obj = self->obj + iter->_index * self->_obj_size;
|
|
iter->_index += 1;
|
|
return obj;
|
|
}
|
|
|
|
iterator_t list_iter(struct _list* self)
|
|
{
|
|
assert(self != NULL);
|
|
iterator_t iter = &self->_iter;
|
|
|
|
iter->_container = self;
|
|
iter->_index = 0;
|
|
|
|
iter->hasnext = list_iter_hasnext;
|
|
iter->next = list_iter_next;
|
|
return iter;
|
|
}
|
|
|
|
static bool list_init2(struct _list* list, uint32_t obj_size, uint32_t capacity)
|
|
{
|
|
assert(list != NULL);
|
|
if(list == NULL || obj_size == 0 || capacity == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// -------------------- private --------------------
|
|
list->_obj_size = obj_size;
|
|
list->_size = 0;
|
|
list->_capacity = capacity;
|
|
list->_ratio = 2;
|
|
list->_cur = 0;
|
|
|
|
list->obj = (void*)malloc(list->_capacity * list->_obj_size);
|
|
if (list->obj == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
list->_iter.next = list_iter_next;
|
|
list->_iter.hasnext = list_iter_hasnext;
|
|
|
|
list->_destory = list_destory;
|
|
|
|
// -------------------- public --------------------
|
|
// kernel
|
|
list->append = list_append;
|
|
list->pop = list_pop;
|
|
|
|
list->insert = list_insert;
|
|
list->delete = list_delete;
|
|
|
|
list->get = list_get;
|
|
list->set = list_set;
|
|
|
|
list->index = list_index;
|
|
// list->contains = list_contains;
|
|
|
|
// base
|
|
list->clear = list_clear;
|
|
list->size = list_size;
|
|
list->empty = list_empty;
|
|
list->capacity = list_capacity;
|
|
|
|
// iter
|
|
list->iter = list_iter;
|
|
|
|
// -------------------- debug --------------------
|
|
list->print = list_print;
|
|
|
|
return true;
|
|
}
|
|
|
|
list_t list_new2(uint32_t obj_size, uint32_t capacity)
|
|
{
|
|
struct _list* list = NULL;
|
|
list = (struct _list*)calloc(1, sizeof(struct _list));
|
|
if(list == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if(list_init2(list, obj_size, capacity) != true)
|
|
{
|
|
free(list);
|
|
return NULL;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
void list_free(list_t* list)
|
|
{
|
|
assert(list != NULL);
|
|
if(list != NULL && *list != NULL)
|
|
{
|
|
if((*list)->_destory != NULL)
|
|
{
|
|
(*list)->_destory(*list);
|
|
}
|
|
free(*list);
|
|
*list = NULL;
|
|
}
|
|
}
|