不含stm32 底层的代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
MyStm32Code/libraries/file_list.c

663 lines
22 KiB

/**
* @file file_list.c
* @author Chen Jihang (embedded@eseaoptics.com)
* @brief 文件列表
* @version 1.0
* @date 2022-08-25
*
* @copyright ESEA (c) 2020
*
*/
#include "file_list.h"
/**
* @brief 从文件中读取链表头
*
* @param p_list file_list描述符
* @param p_head 链表头
* @return int 0:成功 非0:失败
*/
int file_list_get_head(struct file_list *p_list,struct file_list_head *p_head)
{
FRESULT ret;
UINT btr;
UINT br;
ret=f_lseek(&p_list->fp,0);
if(ret!=FR_OK){
return -1;
}
btr=sizeof(struct file_list_head);
ret=f_read(&p_list->fp,p_head,btr,&br);
if(ret!=FR_OK || btr!=br){
return -2;
}
return 0;
}
/**
* @brief 将链表头写入文件
*
* @param p_list file_list描述符
* @param p_head 链表头
* @return int 0:成功 非0:失败
*/
int file_list_put_head(struct file_list *p_list,struct file_list_head *p_head)
{
FRESULT ret;
UINT btw;
UINT bw;
ret=f_lseek(&p_list->fp,0);
if(ret!=FR_OK){
return -1;
}
btw=sizeof(struct file_list_head);
ret=f_write(&p_list->fp,p_head,btw,&bw);
if(ret!=FR_OK || btw!=bw){
return -2;
}
return 0;
}
/**
* @brief 从文件中获取链表节点
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @param file_pointer 文件指针
* @return int 0:成功 非0:失败
*/
int file_list_get_node(struct file_list *p_list,struct file_list_node *p_node,uint64_t file_pointer)
{
FRESULT ret;
UINT btr;
UINT br;
ret=f_lseek(&p_list->fp,file_pointer);
if(ret!=FR_OK){
return -1;
}
btr=sizeof(struct file_list_node);
ret=f_read(&p_list->fp,p_node,btr,&br);
if(ret!=FR_OK || btr!=br){
return -2;
}
return 0;
}
/**
* @brief 将链表节点写入文件
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @return int 0:成功 非0:失败
*/
int file_list_put_node(struct file_list *p_list,struct file_list_node *p_node)
{
FRESULT ret;
UINT btw;
UINT bw;
ret=f_lseek(&p_list->fp,p_node->file_pointer_this);
if(ret!=FR_OK){
return -1;
}
btw=sizeof(struct file_list_node);
ret=f_write(&p_list->fp,p_node,btw,&bw);
if(ret!=FR_OK || btw!=bw){
return -2;
}
return 0;
}
/**
* @brief 从指定链表节点中获取数据
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @param p_data 数据缓冲区
* @param base_addr 数据在链表节点中的基地址
* @param size 要获取的数据长度
* @return int 0:成功 非0:失败
*/
int file_list_get_data(struct file_list *p_list,struct file_list_node *p_node,uint8_t *p_data,uint64_t base_addr,uint64_t size)
{
FRESULT ret;
UINT btr;
UINT br;
ret=f_lseek(&p_list->fp,p_node->file_pointer_this+sizeof(struct file_list_node)+base_addr);
if(ret!=FR_OK){
return -1;
}
btr=size;
ret=f_read(&p_list->fp,p_data,btr,&br);
if(ret!=FR_OK || btr!=br){
return -2;
}
return 0;
}
/**
* @brief 将数据写入指定链表节点中
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @param p_data 要写入的数据
* @param base_addr 数据在链表节点中的基地址
* @param size 要写入的数据长度
* @return int 0:成功 非0:失败
*/
int file_list_put_data(struct file_list *p_list,struct file_list_node *p_node,uint8_t *p_data,uint64_t base_addr,uint64_t size)
{
FRESULT ret;
UINT btw;
UINT bw;
ret=f_lseek(&p_list->fp,p_node->file_pointer_this+sizeof(struct file_list_node)+base_addr);
if(ret!=FR_OK){
return -1;
}
btw=size;
ret=f_write(&p_list->fp,p_data,btw,&bw);
if(ret!=FR_OK || btw!=bw){
return -2;
}
return 0;
}
/**
* @brief 使用指定字符填充链表节点数据
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @param data_to_fill 要填充的字符
* @return int 0:成功 非0:失败
*/
int file_list_fill_data(struct file_list *p_list,struct file_list_node *p_node,uint8_t data_to_fill)
{
FRESULT ret;
UINT btw;
UINT bw;
uint64_t i;
ret=f_lseek(&p_list->fp,p_node->file_pointer_this+sizeof(struct file_list_node));
if(ret!=FR_OK){
return -1;
}
for(i=0;i<p_node->size;i++){
btw=1;
ret=f_write(&p_list->fp,&data_to_fill,btw,&bw);
if(ret!=FR_OK || btw!=bw){
return -2;
}
}
return 0;
}
/**
* @brief 使用指定文件路径创建链表
*
* @param p_list file_list描述符
* @param path 文件路径
* @return struct file_list* 成功:p_list 失败:NULL
*/
struct file_list *file_list_create(struct file_list *p_list,char *path)
{
FRESULT ret;
ret=f_open(&p_list->fp,path,FA_CREATE_ALWAYS|FA_READ|FA_WRITE);
if(ret!=FR_OK){
return NULL;
}
p_list->list_head.file_pointer_used_first=0;
p_list->list_head.file_pointer_used_last=0;
p_list->list_head.file_pointer_free_first=sizeof(struct file_list_head);
p_list->list_head.file_pointer_free_last=p_list->list_head.file_pointer_free_first;
p_list->free_node_now.file_pointer_last=0;
p_list->free_node_now.file_pointer_next=0;
p_list->free_node_now.file_pointer_this=p_list->list_head.file_pointer_free_last;
p_list->free_node_now.size=0xffffffffffffffff;
p_list->used_node_now.size_used=0;
p_list->used_node_now.file_pointer_last=0;
p_list->used_node_now.file_pointer_next=0;
p_list->used_node_now.file_pointer_this=0;
p_list->used_node_now.size=0;
p_list->used_node_now.size_used=0;
if(file_list_put_head(p_list,&p_list->list_head)!=0){
return NULL;
}
if(file_list_put_node(p_list,&p_list->free_node_now)!=0){
return NULL;
}
f_sync(&p_list->fp);
return p_list;
}
/**
* @brief 使用指定文件路径打开链表,若文件不存在则创建新的链表
*
* @param p_list file_list描述符
* @param path 文件路径
* @return struct file_list* 成功:p_list 失败:NULL
*/
struct file_list *file_list_open(struct file_list *p_list,char *path)
{
FRESULT ret;
ret=f_open(&p_list->fp,path,FA_READ|FA_WRITE);
if(ret!=FR_OK){
return file_list_create(p_list,path);
}
if(file_list_get_head(p_list,&p_list->list_head)!=0){
return NULL;
}
if(p_list->list_head.file_pointer_used_first!=0){
if(file_list_get_node(p_list,&p_list->used_node_now,p_list->list_head.file_pointer_used_first)!=0){
return NULL;
}
}
else{
p_list->used_node_now.file_pointer_last=0;
p_list->used_node_now.file_pointer_next=0;
p_list->used_node_now.file_pointer_this=0;
p_list->used_node_now.size=0;
}
if(file_list_get_node(p_list,&p_list->free_node_now,p_list->list_head.file_pointer_free_first)!=0){
return NULL;
}
f_sync(&p_list->fp);
return p_list;
}
/**
* @brief 关闭链表
*
* @param p_list file_list描述符
* @return int 0:成功 非0:失败
*/
int file_list_close(struct file_list *p_list)
{
FRESULT ret;
ret=f_sync(&p_list->fp);
if(ret!=FR_OK){
return -1;
}
ret=f_close(&p_list->fp);
if(ret!=FR_OK){
return -1;
}
return 0;
}
/**
* @brief 合并未使用的链表节点
*
* @param p_list file_list描述符
* @param p_free_node 未使用的链表节点
* @return int 0:成功 非0:失败
*/
int file_list_merge_free_node(struct file_list *p_list,struct file_list_node *p_free_node)
{
struct file_list_node last_free_node;
struct file_list_node next_free_node;
struct file_list_node this_free_node;
this_free_node.size=p_free_node->size;
this_free_node.file_pointer_last=p_free_node->file_pointer_last;
this_free_node.file_pointer_next=p_free_node->file_pointer_next;
this_free_node.file_pointer_this=p_free_node->file_pointer_this;
if(p_free_node->file_pointer_last!=0){
if(file_list_get_node(p_list,&last_free_node,p_free_node->file_pointer_last)!=0){
return -1;
}
if(last_free_node.file_pointer_this+last_free_node.size+sizeof(struct file_list_node)==last_free_node.file_pointer_next){
// printf("<Merge [%llX,%llX]-->%llX,Size [%llX,%llX]-->%llX\n",last_free_node.file_pointer_this,this_free_node.file_pointer_this,last_free_node.file_pointer_this,last_free_node.size,this_free_node.size,this_free_node.size+last_free_node.size+sizeof(struct file_list_node));
this_free_node.file_pointer_last=last_free_node.file_pointer_last;
this_free_node.file_pointer_this=last_free_node.file_pointer_this;
this_free_node.size+=last_free_node.size+sizeof(struct file_list_node);
}
}
if(p_free_node->file_pointer_next!=0){
if(file_list_get_node(p_list,&next_free_node,p_free_node->file_pointer_next)!=0){
return -1;
}
if(this_free_node.file_pointer_this+this_free_node.size+sizeof(struct file_list_node)==this_free_node.file_pointer_next){
// printf(">Merge [%llX,%llX]-->%llX,Size [%llX,%llX]-->%llX\n",this_free_node.file_pointer_this,next_free_node.file_pointer_this,this_free_node.file_pointer_this,this_free_node.size,next_free_node.size,this_free_node.size+next_free_node.size+sizeof(struct file_list_node));
this_free_node.file_pointer_next=next_free_node.file_pointer_next;
this_free_node.size+=next_free_node.size+sizeof(struct file_list_node);
if(this_free_node.file_pointer_next!=0){
if(file_list_get_node(p_list,&next_free_node,this_free_node.file_pointer_next)!=0){
return -1;
}
next_free_node.file_pointer_last=this_free_node.file_pointer_this;
if(file_list_put_node(p_list,&next_free_node)!=0){
return -1;
}
}
else{
p_list->list_head.file_pointer_free_last=this_free_node.file_pointer_this;
if(file_list_put_head(p_list,&p_list->list_head)!=0){
return -1;
}
}
}
else{
next_free_node.file_pointer_last=this_free_node.file_pointer_this;
}
}
if(file_list_put_node(p_list,&this_free_node)!=0){
return -1;
}
if(this_free_node.file_pointer_next!=0){
if(file_list_put_node(p_list,&next_free_node)!=0){
return -1;
}
}
p_list->free_node_now.file_pointer_last=this_free_node.file_pointer_last;
p_list->free_node_now.file_pointer_next=this_free_node.file_pointer_next;
p_list->free_node_now.file_pointer_this=this_free_node.file_pointer_this;
p_list->free_node_now.size=this_free_node.size;
return 0;
}
/**
* @brief 分配一个新的链表节点
*
* @param p_list file_list描述符
* @param size 要存储的数据大小
* @return struct file_list_node* 成功:新的链表节点 失败:NULL
*/
struct file_list_node *file_list_alloc(struct file_list *p_list,uint64_t size)
{
struct file_list_node last_free_node;
struct file_list_node this_free_node;
struct file_list_node next_free_node;
uint64_t file_pointer;
this_free_node.file_pointer_last=0;
this_free_node.file_pointer_next=0;
this_free_node.file_pointer_this=0;
this_free_node.size=0;
file_pointer=p_list->list_head.file_pointer_free_first;
do{
last_free_node.file_pointer_last=this_free_node.file_pointer_last;
last_free_node.file_pointer_next=this_free_node.file_pointer_next;
last_free_node.file_pointer_this=this_free_node.file_pointer_this;
last_free_node.size=this_free_node.size;
if(file_list_get_node(p_list,&this_free_node,file_pointer)!=0){
return NULL;
}
file_pointer=this_free_node.file_pointer_next;
}while(this_free_node.size<size);
p_list->used_node_now.size=this_free_node.size;
p_list->free_node_now.file_pointer_last=this_free_node.file_pointer_last;
p_list->free_node_now.file_pointer_next=this_free_node.file_pointer_next;
p_list->free_node_now.file_pointer_this=this_free_node.file_pointer_this;
p_list->free_node_now.size=this_free_node.size;
p_list->used_node_now.file_pointer_this=this_free_node.file_pointer_this;
p_list->used_node_now.file_pointer_next=0;
p_list->used_node_now.size_used=size;
if(this_free_node.file_pointer_last!=0){
if(file_list_get_node(p_list,&last_free_node,this_free_node.file_pointer_last)!=0){
return NULL;
}
if(this_free_node.size>=size+sizeof(struct file_list_node)){
p_list->free_node_now.file_pointer_last=last_free_node.file_pointer_this;
p_list->free_node_now.file_pointer_this=p_list->used_node_now.file_pointer_this+size+sizeof(struct file_list_node);
last_free_node.file_pointer_next=p_list->free_node_now.file_pointer_this;
}
else{
last_free_node.file_pointer_next=this_free_node.file_pointer_next;
}
if(file_list_put_node(p_list,&last_free_node)!=0){
return NULL;
}
}
else{
if(this_free_node.size>=size+sizeof(struct file_list_node)){
p_list->free_node_now.file_pointer_this=p_list->used_node_now.file_pointer_this+size+sizeof(struct file_list_node);
p_list->list_head.file_pointer_free_first=p_list->free_node_now.file_pointer_this;
}
else{
p_list->list_head.file_pointer_free_first=this_free_node.file_pointer_next;
}
}
if(this_free_node.file_pointer_next!=0){
if(file_list_get_node(p_list,&next_free_node,this_free_node.file_pointer_next)!=0){
return NULL;
}
if(this_free_node.size>=size+sizeof(struct file_list_node)){
p_list->free_node_now.file_pointer_this=p_list->used_node_now.file_pointer_this+size+sizeof(struct file_list_node);
p_list->free_node_now.file_pointer_next=next_free_node.file_pointer_this;
next_free_node.file_pointer_last=p_list->free_node_now.file_pointer_this;
}
else{
next_free_node.file_pointer_last=this_free_node.file_pointer_last;
}
if(file_list_put_node(p_list,&next_free_node)!=0){
return NULL;
}
}
else{
if(this_free_node.size>=size+sizeof(struct file_list_node)){
p_list->free_node_now.file_pointer_this=p_list->used_node_now.file_pointer_this+size+sizeof(struct file_list_node);
p_list->list_head.file_pointer_free_last=p_list->free_node_now.file_pointer_this;
}
else{
p_list->list_head.file_pointer_free_last=this_free_node.file_pointer_last;
}
}
if(this_free_node.size>=size+sizeof(struct file_list_node)){
p_list->used_node_now.size=size;
p_list->free_node_now.size-=size+sizeof(struct file_list_node);
if(file_list_put_node(p_list,&p_list->free_node_now)!=0){
return NULL;
}
}
if(file_list_put_head(p_list,&p_list->list_head)!=0){
return NULL;
}
return &p_list->used_node_now;
}
/**
* @brief 释放链表节点
*
* @param p_list file_list描述符
* @param p_node_to_free 要释放的链表节点
* @return int 0:成功 非0:失败
*/
int file_list_free_node(struct file_list *p_list,struct file_list_node *p_node_to_free)
{
struct file_list_node last_free_node;
struct file_list_node next_free_node;
uint64_t file_pointer;
next_free_node.file_pointer_this=0;
next_free_node.file_pointer_last=0;
next_free_node.size=0;
file_pointer=p_list->list_head.file_pointer_free_first;
do{
last_free_node.file_pointer_last=next_free_node.file_pointer_last;
last_free_node.file_pointer_this=next_free_node.file_pointer_this;
last_free_node.size=next_free_node.size;
if(file_list_get_node(p_list,&next_free_node,file_pointer)!=0){
return -1;
}
file_pointer=next_free_node.file_pointer_next;
}while(next_free_node.file_pointer_this<p_node_to_free->file_pointer_this);
if(last_free_node.file_pointer_this!=0){
last_free_node.file_pointer_next=p_node_to_free->file_pointer_this;
if(file_list_put_node(p_list,&last_free_node)!=0){
return -1;
}
}
else{
p_list->list_head.file_pointer_free_first=p_node_to_free->file_pointer_this;
}
next_free_node.file_pointer_last=p_node_to_free->file_pointer_this;
p_node_to_free->file_pointer_last=last_free_node.file_pointer_this;
p_node_to_free->file_pointer_next=next_free_node.file_pointer_this;
if(file_list_put_node(p_list,&next_free_node)!=0){
return -1;
}
if(file_list_put_node(p_list,p_node_to_free)!=0){
return -1;
}
return file_list_merge_free_node(p_list,p_node_to_free);
}
/**
* @brief 从链表中删除指定节点
*
* @param p_list file_list描述符
* @param p_used_node 要删除的节点
* @return int 0:成功 非0:失败
*/
int file_list_del_node(struct file_list *p_list,struct file_list_node *p_used_node)
{
struct file_list_node last_used_node;
struct file_list_node next_used_node;
if(p_used_node->file_pointer_last!=0){
if(file_list_get_node(p_list,&last_used_node,p_used_node->file_pointer_last)!=0){
return -1;
}
last_used_node.file_pointer_next=p_used_node->file_pointer_next;
if(file_list_put_node(p_list,&last_used_node)!=0){
return -1;
}
}
else{
p_list->list_head.file_pointer_used_first=p_used_node->file_pointer_next;
}
if(p_used_node->file_pointer_next!=0){
if(file_list_get_node(p_list,&next_used_node,p_used_node->file_pointer_next)!=0){
return -1;
}
next_used_node.file_pointer_last=p_used_node->file_pointer_last;
if(file_list_put_node(p_list,&next_used_node)!=0){
return -1;
}
}
else{
p_list->list_head.file_pointer_used_last=p_used_node->file_pointer_last;
}
if(file_list_put_head(p_list,&p_list->list_head)!=0){
return -1;
}
return file_list_free_node(p_list,p_used_node);
}
/**
* @brief 向链表最后插入新的节点
*
* @param p_list file_list描述符
* @param size 要存储的数据大小
* @return struct file_list_node* 成功:新的节点 失败:NULL
*/
struct file_list_node *file_list_add_node(struct file_list *p_list,uint64_t size)
{
struct file_list_node last_used_node;
struct file_list_node *pnode;
pnode=file_list_alloc(p_list,size);
if(pnode==NULL){
return NULL;
}
pnode->file_pointer_last=0;
pnode->file_pointer_next=0;
if(p_list->list_head.file_pointer_used_last!=0){
pnode->file_pointer_last=p_list->list_head.file_pointer_used_last;
if(file_list_get_node(p_list,&last_used_node,pnode->file_pointer_last)!=0){
return NULL;
}
last_used_node.file_pointer_next=pnode->file_pointer_this;
if(file_list_put_node(p_list,&last_used_node)!=0){
return NULL;
}
}
p_list->list_head.file_pointer_used_last=pnode->file_pointer_this;
if(p_list->list_head.file_pointer_used_first==0){
p_list->list_head.file_pointer_used_first=pnode->file_pointer_this;
}
if(file_list_put_head(p_list,&p_list->list_head)!=0){
return NULL;
}
if(file_list_put_node(p_list,pnode)!=0){
return NULL;
}
f_sync(&p_list->fp);
return pnode;
}
/**
* @brief 获取链表中第一个节点
*
* @param p_list file_list描述符
* @return struct file_list_node* 成功:第一个节点 失败:NULL
*/
struct file_list_node *file_list_get_first_node(struct file_list *p_list)
{
if(p_list->list_head.file_pointer_used_first==0){
return NULL;
}
if(file_list_get_node(p_list,&p_list->used_node_now,p_list->list_head.file_pointer_used_first)!=0){
return NULL;
}
return &p_list->used_node_now;
}
/**
* @brief 获取链表中下一个节点
*
* @param p_list file_list描述符
* @return struct file_list_node* 成功:下一个节点 失败:NULL
*/
struct file_list_node *file_list_get_next_node(struct file_list *p_list)
{
if(p_list->used_node_now.file_pointer_next==0){
return NULL;
}
if(file_list_get_node(p_list,&p_list->used_node_now,p_list->used_node_now.file_pointer_next)!=0){
return NULL;
}
return &p_list->used_node_now;
}
/**
* @brief 获取链表中最后一个节点
*
* @param p_list file_list描述符
* @return struct file_list_node* 成功:最后一个节点 失败:NULL
*/
struct file_list_node *file_list_get_last_node(struct file_list *p_list)
{
if(p_list->used_node_now.file_pointer_last==0){
return NULL;
}
if(file_list_get_node(p_list,&p_list->used_node_now,p_list->used_node_now.file_pointer_last)!=0){
return NULL;
}
return &p_list->used_node_now;
}
/**
* @brief 获取链表中数据大小
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @return uint64_t 改节点中的数据大小
*/
uint64_t file_list_get_node_size(struct file_list *p_list,struct file_list_node *p_node)
{
return p_node->size_used;
}
/**
* @brief 获取指定节点中的数据
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @param buf 数据缓冲区
* @param base_addr 要获取的数据在链表节点中的基地址
* @param size 要获取的数据大小
* @return uint64_t 实际获取的数据大小
*/
uint64_t file_list_get_node_data(struct file_list *p_list,struct file_list_node *p_node,void *buf,uint64_t base_addr,uint64_t size)
{
size=(base_addr+size>p_node->size_used)?p_node->size_used-base_addr:size;
if(file_list_get_data(p_list,p_node,buf,base_addr,size)!=0){
return 0;
}
return size;
}
/**
* @brief 向指定节点中写入数据
*
* @param p_list file_list描述符
* @param p_node 链表节点
* @param buf 要写入的数据
* @param base_addr 要写入的数据的基地址
* @param size 要写入的数据大小
* @return uint64_t 实际写入的数据大小
*/
uint64_t file_list_put_node_data(struct file_list *p_list,struct file_list_node *p_node,void *buf,uint64_t base_addr,uint64_t size)
{
size=(base_addr+size>p_node->size_used)?p_node->size_used-base_addr:size;
if(file_list_put_data(p_list,p_node,buf,base_addr,size)!=0){
return 0;
}
f_sync(&p_list->fp);
return size;
}