/** * @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;isize;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("%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.sizeused_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_thisfile_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; }