589 lines
10 KiB
C
589 lines
10 KiB
C
![]() |
#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);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|