openmv中用到很多结构体list_t,通过对于这个结构体的实现,可以方便对于数据的处理。
在collections.h中定义的相关结构体和功能函数声明。
//
// list //
//
typedef struct list_lnk
{
struct list_lnk *next_ptr, *prev_ptr;
char data[];
}
__attribute__((aligned(8)))list_lnk_t;
typedef struct list
{
list_lnk_t *head_ptr, *tail_ptr;
size_t size, data_len;
}
__attribute__((aligned(8)))list_t;
void list_init(list_t *ptr, size_t data_len);
void list_copy(list_t *dst, list_t *src);
void list_free(list_t *ptr);
void list_clear(list_t *ptr);
size_t list_size(list_t *ptr);
void list_push_front(list_t *ptr, void *data);
void list_push_back(list_t *ptr, void *data);
void list_pop_front(list_t *ptr, void *data);
void list_pop_back(list_t *ptr, void *data);
void list_get_front(list_t *ptr, void *data);
void list_get_back(list_t *ptr, void *data);
void list_set_front(list_t *ptr, void *data);
void list_set_back(list_t *ptr, void *data);
void list_insert(list_t *ptr, void *data, size_t index);
void list_remove(list_t *ptr, void *data, size_t index);
void list_get(list_t *ptr, void *data, size_t index);
void list_set(list_t *ptr, void *data, size_t index);
结构体list_t是头结点。这样就可以容纳不同的数据类型。通过连接list_lnk_t。所以所有函数用list_t充当形参。
这里的链表是一个双向循环的链表,这里要注意头结点指向的第一个节点没有指向头结点。
1、void list_init(list_t *ptr, size_t data_len)
void list_init(list_t *ptr, size_t data_len)
{
ptr->head_ptr = NULL;
ptr->tail_ptr = NULL;
ptr->size = 0;
ptr->data_len = data_len;
}
这个函数主要是初始化list_t 的结构体。其中关于其中的参数data_len用于指示后续的节点的数据的内存申请长度。
2、void list_copy(list_t *dst, list_t *src);
void list_copy(list_t *dst, list_t *src)
{
memcpy(dst, src, sizeof(list_t));
}
这里就是利用memcpy做简单的内存复制。
3、void list_free(list_t *ptr)
void list_free(list_t *ptr)
{
for (list_lnk_t *i = ptr->head_ptr; i; )//获取到ptr的头结点
{
list_lnk_t *j = i->next_ptr; //获取当前节点的下一个节点
xfree(i); //释放当前节点
i = j; //更新当前节点
}
}
这个函数就如函数里面的注释,主要就是遍寻一遍链表,释放节点内存。
<