一个简单循环队列的实现
在线验证链接:https://onlinegdb.com/gpGlm4BV0
/******************************************************************************* @Brief A simple circle fifo* @Data 23/12/07* @Author zxk* @File name z_fifo.c
*******************************************************************************/
#include <stdio.h>
#include <string.h>typedef unsigned char u8;
typedef signed char s8;typedef struct {u8 size; // 单个元素占用空间u8 num; // 元素个数u8 w_ind; // 写入索引u8 r_ind; // 读出索引u8 * p; // 缓存池首地址
} z_fifo_t;#define Z_FIFO_NUM 8 /* must be 4, 8, 16, 32 ... else need to change "zzz" lines */
#define Z_FIFO_SIZE 32 unsigned char fifo_pool_buff[Z_FIFO_NUM*Z_FIFO_SIZE] = {0};z_fifo_t test_fifo = {.size = Z_FIFO_SIZE,.num = Z_FIFO_NUM, .w_ind = 0,.r_ind = 0,.p = fifo_pool_buff,
};void z_fifo_init(z_fifo_t *f, u8 size, u8 num, u8 *p_buff)
{f->size = size;f->num = num;f->w_ind = 0;f->r_ind = 0;f->p = p_buff;
}/*** @brief 恢复队列到初始状态*/
void z_fifo_rst(z_fifo_t * f)
{f->w_ind = 0;f->r_ind = 0;
}/*** @brief 获取队列未使用元素个数*/
u8 get_fifo_remain_num(z_fifo_t *f)
{return f->num - (f->w_ind - f->r_ind);
}/*** @brief 如果队列未满则入队列* @ret 0: succ, -1: fifo is full, -2: parameter err.*/
s8 z_fifo_push(z_fifo_t *f, u8 *push_data, u8 push_len)
{// count offsetu8 * p_wr = f->p + (f->w_ind & (f->num - 1)) * f->size; // zzz // fifo is full if(f->w_ind - f->r_ind >= f->num){return -1;}// data's point is NULLif(push_data == NULL){return -2;}// exceed cell's sizeif(push_len > f->size){return -2;}// copy push_datamemcpy(p_wr, push_data, push_len);// updata write indexf->w_ind++;return 0;
}/*** @brief 队列没满 正常入队列等同于z_fifo_push, 队列已满则弹出当前队列第一个元素* @ret 0: succ, -1: parameter err.*/
s8 z_fifo_pop_push(z_fifo_t *f, u8 *push_data, u8 push_len)
{u8 *p_wr = f->p;// data's point is NULLif(push_data == NULL){return -2;}// exceed cell sizeif(push_len > f->size){return -2;}p_wr += (f->w_ind & (f->num - 1)) * f->size; // zzz// Processing when the fifo is already full.if(f->w_ind - f->r_ind >= f->num){f->r_ind = f->w_ind - f->num + 1;}memcpy(p_wr, push_data, push_len);f->w_ind++;return 0;
}/*** @brief pop one cell from the fifo* @ret 0 fifo is not empty, -1 fifo is empty -2 err sta*/
s8 z_fifo_pop(z_fifo_t *f)
{if((f->w_ind - f->r_ind) > f->num){// It's not supposed to run here.f->r_ind = f->w_ind - f->num + 1; // err sta: make it equal to last indexreturn -2;}else if(f->w_ind == f->r_ind){return -1;}else{f->r_ind ++;return 0;}
}/*** @brief get the last cell from the fifo* @ret 0 fifo empty else fifo data's point*/
u8 *z_fifo_get(z_fifo_t *f)
{if(f->r_ind != f->w_ind){u8 *p = f->p + (f->r_ind & (f->num - 1)) * f->size; // zzzreturn p;}return 0;
}int main(void)
{/* 元素个数8 单个元素占用空间32 */z_fifo_t *p_fifo = &test_fifo;u8 ii = 0;s8 ret = 0;u8 buff_set[16] = {0};u8 *buff_get = NULL;printf("!!! z_fifo test start ...... \n");for(ii = 0; ii < 9; ii++){memset(buff_set,ii,sizeof(buff_set));ret = z_fifo_push(p_fifo, buff_set, sizeof(buff_set));printf("push fifo ind:%d ret = %d\n",ii,ret);buff_get = z_fifo_get(p_fifo);if(buff_get != NULL){printf("[%02d] get fifo data:%02d,%02d,%02d,%02d, %02d,%02d,%02d,%02d\n",ii,buff_get[0],buff_get[1],buff_get[2],buff_get[3], buff_get[4],buff_get[5],buff_get[6],buff_get[7]);z_fifo_pop(p_fifo);}else{printf("\nfifo is empty.\n");}}printf("------------- 1 ----------------\n\n");for(ii = 0; ii < p_fifo->num*2 ; ii++){memset(buff_set,ii,sizeof(buff_set));z_fifo_pop_push(p_fifo, buff_set, sizeof(buff_set));buff_get = z_fifo_get(p_fifo);if(buff_get != NULL){printf("[%02d] remain num:%d,get fifo data:%02d,%02d,%02d,%02d, %02d,%02d,%02d,%02d\n", ii,get_fifo_remain_num(p_fifo),buff_get[0],buff_get[1],buff_get[2],buff_get[3], buff_get[4],buff_get[5],buff_get[6],buff_get[7]);// @test not pop z_fifo_pop(p_fifo);}else{printf("\nfifo is empty.\n");}}printf("------------- 2 ----------------\n\n");if(get_fifo_remain_num(p_fifo) == 0){printf("fifo is full.\n");}for(ii = 0; ii < p_fifo->num; ii ++){ret = z_fifo_pop(p_fifo);if(0 == ret){buff_get = z_fifo_get(p_fifo);if(buff_get != NULL){printf("[%02d] get fifo data:%02d,%02d,%02d,%02d, %02d,%02d,%02d,%02d\n", ii,buff_get[0],buff_get[1],buff_get[2],buff_get[3], buff_get[4],buff_get[5],buff_get[6],buff_get[7]);}else{printf("\nfifo is empty.\n");}}else if(-1 == ret){ printf("the fifo to be poped is empty.\n");}else if(-2 == ret){printf("pop fifo err.\n");}}printf("------------- 3 ----------------\n\n");printf("\n!!! z_fifo test over.\n");return 0;
}