Files
2023-06-10 11:52:00 +08:00

589 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "list.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "board.h"
#include "mystdlib.h"
#include "debug.h"
#include "bytearray.h"
#include "rtthread.h"
#define LIST_APPEND_SKIP 10
typedef struct{
int32_t next;
int32_t prev;
uint32_t data[0];
}list_node_def;
struct _list_def{
int32_t all;
int32_t used;
int32_t block_size;
int32_t block_size4;
rt_mutex_t mutex;
int32_t head;
int32_t tail;
sub_fun_def sub;
del_fun_def del;
str_fun_def str;
uint32_t data[0];
};
//#define list_enter_mutex(l)\
// rt_mutex_take((l)->mutex,RT_WAITING_FOREVER)
//
//#define list_exit_mutex(l)\
// rt_mutex_release((l)->mutex)
#define list_enter_mutex(l)
#define list_exit_mutex(l)
#define rt_mutex_create(...) 0
#define rt_mutex_delete(l)
list_def *list_creat(int block_size,sub_fun_def sub,del_fun_def del,str_fun_def str)
{
static uint16_t count=0;
char s1[16]={0};
sprintf(s1,"list_mut#%d",count);
int size=0;
int block_size4;
list_def *l;
size+=sizeof(list_def);
// 4字节对齐
block_size4=((block_size+3)/4)*4;
size+=(sizeof(list_node_def)+block_size4)*LIST_APPEND_SKIP;
l=malloc(size);
param_check(l);
l->all=LIST_APPEND_SKIP;
l->used=0;
l->block_size=block_size;
l->block_size4=block_size4;
l->mutex=rt_mutex_create(s1,RT_IPC_FLAG_FIFO);
l->head=-1;
l->tail=-1;
l->sub=sub;
l->del=del;
l->str=str;
// 初始化列表
list_node_def *node;
node=(list_node_def *)l->data;
for(int i=0;i<l->all;i++)
{
node->next=-1;
node->prev=-1;
node=(list_node_def *)((uint32_t)node+sizeof(list_node_def)+l->block_size4);
}
count++;
return l;
}
// 对于数据里有指针数据的成员,需要提供del函数
void _list_delete(list_def **l)
{
param_check(l);
param_check(*l);
list_enter_mutex(*l);
if((*l)->del)
{
for(int i=0;i<(*l)->used;i++)
{
(*l)->del(list_get(*l,i));
}
}
list_exit_mutex(*l);
rt_mutex_delete((*l)->mutex);
free(*l);
*l=0;
}
int list_block_size4(list_def *l)
{
param_check(l);
return l->block_size4;
}
//static void cpy4byte(uint32_t *dst,uint32_t *src,int num_4byte)
//{
// for(int i=0;i<num_4byte;i++)
// {
// dst[i]=src[i];
// }
//}
static list_def *list_expend(list_def *l)
{
int size=0;
int cpysize=0;
list_def *r;
size+=sizeof(list_def);
size+=(sizeof(list_node_def)+l->block_size4)*(l->all);
cpysize=size;
size+=(sizeof(list_node_def)+l->block_size4)*(LIST_APPEND_SKIP);
r=malloc(size);
param_check(r);
cpy4byte((uint32_t *)r,(uint32_t *)l,cpysize/4);
// 初始化列表
list_node_def *node;
node=(list_node_def *)((uint32_t)r->data+r->all*(sizeof(list_node_def)+r->block_size4));
for(int i=0;i<LIST_APPEND_SKIP;i++)
{
node->next=-1;
node->prev=-1;
node=(list_node_def *)((uint32_t)node+sizeof(list_node_def)+r->block_size4);
}
r->all+=LIST_APPEND_SKIP;
free(l);
return r;
}
// 查找一个未使用的节点
static list_node_def *list_unused_node(list_def *l,int *index)
{
list_node_def *node=0;
node=(list_node_def *)l->data;
for(int i=0;i<l->all;i++)
{
if((node->next==-1)&&(node->prev==-1)){
if(index) *index=i;
return node;
}
node=(list_node_def *)((uint32_t)node+sizeof(list_node_def)+l->block_size4);
}
return node;
}
// 取得指定序号的节点
static list_node_def *list_node(list_def *l,int index)
{
list_node_def *node;
param_check(index>=0&&index<l->all);
node=(list_node_def *)((uint32_t)l->data+index*(sizeof(list_node_def)+l->block_size4));
return node;
}
// 取得节点的物理索引
static int list_phy_index(list_def *l,list_node_def *n)
{
return ((uint32_t)n-(uint32_t)l->data)/(sizeof(list_node_def)+l->block_size4);
}
/*
// 改为统一使用insert函数
list_def *list_append(list_def **l,void *data)
{
param_check(l);
param_check(*l);
list_def *r=*l;
if((*l)->used>=(*l)->all)
{
r=list_expend(*l);
}
list_node_def *node;
int index;
node=list_unused_node(r,&index);
param_check(node);
memcpy(node->data,data,r->block_size);
if(r->head==-1&&r->tail==-1)
{
r->head=index;
r->tail=index;
node->next=index;
node->prev=index;
}
else if(r->head!=-1&&r->tail!=-1)
{
node->prev=r->tail;
node->next=list_node(r,r->tail)->next;
list_node(r,r->tail)->next=index;
r->tail=index;
list_node(r,r->head)->prev=index;
}
else
{
param_check(0);
}
r->used++;
*l=r;
return r;
}
*/
// 返回指定index的已使用节点
static list_node_def *list_used_node(list_def *l,int index)
{
list_node_def *node=0;
if(index>l->used/2)
{
index=l->used-1-index;
node=list_node(l,l->tail);
for(int i=0;i<index;i++)
{
node=list_node(l,node->prev);
}
}
else{
node=list_node(l,l->head);
for(int i=0;i<index;i++)
{
node=list_node(l,node->next);
}
}
return node;
}
// 获取第index项数据,不删除
// index支持负数-1表示最后一项
// 返回数据引用
void *list_get(list_def *l,int index)
{
param_check(l);
void *ret=0;
list_enter_mutex(l);
list_node_def *node;
if(index<0) index=l->used+index;
if((index>=0&&index<l->used)==0)
ret=0;
else{
node=list_used_node(l,index);
param_check(node);
ret=node->data;
}
list_exit_mutex(l);
return ret;
}
// 删除第index项数据
// index支持负数-1表示最后一项
void list_remove(list_def *l,int index)
{
param_check(l);
list_node_def *node;
int phy_index;
if(index<0) index=l->used+index;
list_enter_mutex(l);
if((index>=0&&index<l->used)){
node=list_used_node(l,index);
param_check(node);
phy_index=list_phy_index(l,node);
if(l->used==1)
{
l->head=-1;
l->tail=-1;
}
else
{
if(l->head==phy_index)
{
l->head=node->next;
}
if(l->tail==phy_index)
{
l->tail=node->prev;
}
list_node(l,node->prev)->next=node->next;
list_node(l,node->next)->prev=node->prev;
}
node->next=-1;
node->prev=-1;
if(l->del) l->del(node->data);
l->used--;
}
list_enter_mutex(l);
}
// 获取指定index的数据随后删除
// 返回数据的临时指针
// 对于存在动态指针的对象由于take之后会自动删除take操作会出现野指针
// 建议使用list_get + list_remove的方式代替list_take
void *list_take(list_def *l,int index)
{
param_check(l);
void *p;
p=list_get(l,index);
void *t=tmalloc(l->block_size);
param_check(t);
memcpy(t,p,l->block_size);
list_remove(l,index);
return t;
}
// 清空
void list_clear(list_def *l)
{
param_check(l);
list_enter_mutex(l);
while(l->used>0)
{
list_remove(l,0);
}
list_exit_mutex(l);
}
int list_length(list_def *l)
{
param_check(l);
return l->used;
}
// 在指定位置插入
// index为节点插入之后所在的位置
list_def *_list_insert(list_def **l,void *data,int index)
{
param_check(l);
param_check(*l);
list_enter_mutex(*l);
if(index<0) index=(*l)->used+index+1;
if((index>=0&&index<=(*l)->used)==0){
list_exit_mutex(*l);
return *l;
}
list_def *r=*l;
if((*l)->used>=(*l)->all)
{
r=list_expend(*l);
}
list_node_def *node;
int phy_index;
node=list_unused_node(r,&phy_index);
param_check(node);
memcpy(node->data,data,r->block_size);
if(r->head==-1&&r->tail==-1)
{
r->head=phy_index;
r->tail=phy_index;
node->next=phy_index;
node->prev=phy_index;
}
else if(r->head!=-1&&r->tail!=-1)
{
list_node_def *n;
int n_phy_index;
if(index<r->used)
{
n=list_used_node(r,index);
n_phy_index=list_phy_index(r,n);
list_node(r,n->prev)->next=phy_index;
node->prev=n->prev;
node->next=n_phy_index;
n->prev=phy_index;
if(index==0)
{
r->head=phy_index;
}
}
else
{
node->prev=r->tail;
node->next=list_node(r,r->tail)->next;
list_node(r,r->tail)->next=phy_index;
r->tail=index;
list_node(r,r->head)->prev=phy_index;
}
}
else
{
param_check(0);
}
r->used++;
*l=r;
list_exit_mutex(*l);
return r;
}
void list_sort(list_def *l)
{
param_check(l);
list_enter_mutex(l);
if(l->sub){
_list_sort(l,l->sub);
}
else{
DBG_WARN("obj->sub fun is null.");
}
list_exit_mutex(l);
}
// 在列表内返回1不在返回0
int list_contains(list_def *l,void *d)
{
param_check(l);
list_enter_mutex(l);
if(l->sub)
{
for(int i=0;i<list_length(l);i++)
{
if(l->sub(list_get(l,i),d)==0){
list_exit_mutex(l);
return 1;
}
}
}
else{
DBG_WARN("obj->sub fun is null.");
}
list_exit_mutex(l);
return 0;
}
// 交换两个位置
void list_swap(list_def *l,int index_a,int index_b)
{
param_check(l);
list_enter_mutex(l);
void *a_=list_get(l,index_a);
void *b_=list_get(l,index_b);
void *t_=0;
if(a_&&b_)
{
t_=calloc(1,sizeof(l->block_size4));
cpy4byte(t_,a_,l->block_size4/4);
cpy4byte(a_,b_,l->block_size4/4);
cpy4byte(b_,t_,l->block_size4/4);
free(t_);
}
list_exit_mutex(l);
}
// 向后循环移动
void list_shift(list_def *l)
{
param_check(l);
list_enter_mutex(l);
if(l->used>0){
l->head=list_node(l,l->head)->next;
l->tail=list_node(l,l->tail)->next;
}
list_exit_mutex(l);
}
// 输出打印字符串
char *list_string(list_def *l)
{
param_check(l);
list_enter_mutex(l);
array_def *d=arr_creat();
param_check(d);
int len=0;
char *s=0;
arr_append(d,'(');
if(l->str)
{
for(int i=0;i<list_length(l);i++)
{
s=l->str(list_get(l,i));
len=strlen(s);
arr_appends(d,s,len);
free(s);
arr_append(d,',');
arr_append(d,' ');
}
}
arr_append(d,')');
len=arr_length(d);
s=malloc(len+1);
param_check(s);
memcpy(s,arr_data(d),len);
arr_delete(d);
s[len]=0;
list_exit_mutex(l);
return s;
}
// int sub函数
int _list_int_sub(void *a,void *b)
{
return *(int *)a-*(int *)b;
}
// int 打印函数
char *_list_int_str(void *a)
{
char *s=malloc(20);
param_check(s);
sprintf(s,"%d",*(int *)a);
return s;
}
// str sub函数
int _list_str_sub(void *a,void *b)
{
char *a_=*(char **)a;
char *b_=*(char **)b;
return strcmp(a_,b_);
}
// str删除函数
int _list_str_del(void *d)
{
char **c=d;
if(*c) free(*c);
return 0;
}
// str 打印函数
char *_list_str_str(void *a)
{
char *a_=*(char **)a;
int len=strlen(a_);
char *s=malloc(len+1);
param_check(s);
memcpy(s,a_,len+1);
return s;
}
// 延迟删除,不需要修改指针
void _list_delete_later(list_def *l)
{
_list_delete(&l);
}