欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言实现任意数据类型的Queue环形队列RingBuffer

程序员文章站 2022-03-14 15:07:27
...

头文件 fifo.h

#ifndef __QUEUE_H_
#define __QUEUE_H_

/*********************************************************************
 * @brief       Queue队列类型定义
 *********************************************************************/
typedef struct
{
    unsigned int            Depth;          // Queue深度
    volatile unsigned int   Head;           // Head为起始元素
    volatile unsigned int   Tail;           // Tail-1为最后一个元素
    volatile unsigned int   Counter;        // 元素个数
    unsigned int            ElementBytes;   // 每个元素的字节数
    void                    *Buff;          // 缓存区
}Queue_Type;
  
/*********************************************************************
 * @brief       Queue初始化
 * @param[in]   pQueue: Queue指针
 * @param[in]   pBuff: Queue中缓存
 * @param[in]   elementBytes:Queue每个元素的字节数
 * @param[in]   depth: Queue深度
 * @return      None
 *********************************************************************/
void Queue_Init(Queue_Type *pQueue, void *pBuff, unsigned int elementBytes, unsigned int depth);
  
/*********************************************************************
 * @brief       向Queue添加一个元素
 * @param[in]   pQueue: Queue指针
 * @param[in]   pValue: 要添加的元素
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char Queue_AddOne(Queue_Type *pQueue, void *pValue);
  
/*********************************************************************
 * @brief       向Queue添加多个元素
 * @param[in]   pQueue: Queue指针
 * @param[in]   pValues: 要添加的元素指针
 * @param[in]   bytesToAdd: 要添加元素的长度
 * @return      实际添加的元素个数
 *********************************************************************/
unsigned int Queue_Add(Queue_Type *pQueue, void *pValues, unsigned int bytesToAdd);
  
/*********************************************************************
 * @brief       从Queue读取一个元素
 * @param[in]   pQueue: Queue指针
 * @param[in]   pValue: 存放要读取的元素指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char Queue_GetOne(Queue_Type *pQueue, void *pValue);
  
/*********************************************************************
 * @brief       从Queue读取多个元素
 * @param[in]   pQueue: Queue指针
 * @param[out]  pValues: 存放要读取的元素指针
 * @param[in]   bytesToRead: 要读取的元素长度
 * @return      实际读取的元素个数
 *********************************************************************/
unsigned int Queue_Get(Queue_Type *pQueue, void *pValues, unsigned int bytesToRead);
  
  
/*********************************************************************
 * @brief       清空Queue
 * @param[in]   pQueue: Queue指针
 * @return      None
 *********************************************************************/
void Queue_Clear(Queue_Type *pQueue);
  
#endif

实体文件 fifo.c

#include <string.h>
#include "Queue.h"
  
/*********************************************************************
 * @brief       Queue初始化
 * @param[in]   pQueue: Queue指针
 * @param[in]   pBuff: Queue中缓存
 * @param[in]   elementBytes:Queue每个元素的字节数
 * @param[in]   depth: Queue深度
 * @return      None
 *********************************************************************/
void Queue_Init(Queue_Type *pQueue, void *pBuff, unsigned int elementBytes, unsigned int depth)
{
    pQueue->Buff = pBuff;
    pQueue->ElementBytes = elementBytes;
    pQueue->Depth = depth;
    pQueue->Head = 0;
    pQueue->Tail = 0;
    pQueue->Counter = 0;
}
  
/*********************************************************************
 * @brief       判断Queue是否为空
 * @param[in]   pQueue: Queue指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char Queue_IsEmpty(Queue_Type *pQueue)
{
    return (pQueue->Counter == 0);
}
  
/*********************************************************************
 * @brief       判断Queue是否已满
 * @param[in]   pQueue: Queue指针
 * @return      TRUE or FALSE
 *********************************************************************/
unsigned char Queue_IsFull(Queue_Type *pQueue)
{
    return (pQueue->Counter == pQueue->Depth);
}
  
/*********************************************************************
 * @brief       向Queue添加一个元素
 * @param[in]   pQueue: Queue指针
 * @param[in]   pValue: 要添加的元素
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char Queue_AddOne(Queue_Type *pQueue, void *pValue)
{
    unsigned char *p;
  
    if (Queue_IsFull(pQueue))
    {
        return 0;
    }
  
    p = (unsigned char *)pQueue->Buff;
    memcpy(p + pQueue->Tail * pQueue->ElementBytes, (unsigned char *)pValue, pQueue->ElementBytes);
     
    pQueue->Tail ++;
    if (pQueue->Tail >= pQueue->Depth)
    {
        pQueue->Tail = 0;
    }
    pQueue->Counter ++;
    return 1;
}
  
/*********************************************************************
 * @brief       向Queue添加多个元素
 * @param[in]   pQueue: Queue指针
 * @param[in]   pValues: 要添加的元素指针
 * @param[in]   bytesToAdd: 要添加元素的长度
 * @return      实际添加的元素个数
 *********************************************************************/
unsigned int Queue_Add(Queue_Type *pQueue, void *pValues, unsigned int bytesToAdd)
{
    unsigned char *p;
    unsigned int cnt = 0;
  
    p = (unsigned char *)pValues;
    while(bytesToAdd --)
    {
        if (Queue_AddOne(pQueue, p))
        {
            p += pQueue->ElementBytes;
            cnt++;
        }
        else
        {
            break;
        }
    }
  
    return cnt;
}
  
/*********************************************************************
 * @brief       从Queue读取一个元素
 * @param[in]   pQueue: Queue指针
 * @param[in]   pValue: 存放要读取的元素指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char Queue_GetOne(Queue_Type *pQueue, void *pValue)
{
    unsigned char *p;
    if (Queue_IsEmpty(pQueue))
    {
        return 0;
    }
  
    p = (unsigned char *)pQueue->Buff;
    memcpy(pValue, p + pQueue->Head * pQueue->ElementBytes, pQueue->ElementBytes);
  
    pQueue->Head ++;
    if (pQueue->Head >= pQueue->Depth)
    {
        pQueue->Head = 0;
    }
    pQueue->Counter --;
  
    return 1;
}
  
/*********************************************************************
 * @brief       从Queue读取多个元素
 * @param[in]   pQueue: Queue指针
 * @param[out]  pValues: 存放要读取的元素指针
 * @param[in]   bytesToRead: 要读取的元素长度
 * @return      实际读取的元素个数
 *********************************************************************/
unsigned int Queue_Get(Queue_Type *pQueue, void *pValues, unsigned int bytesToRead)
{
    unsigned int cnt = 0;
    unsigned char *p;
  
    p = pValues;
    while(bytesToRead--)
    {
        if (Queue_GetOne(pQueue, p))
        {
            p += pQueue->ElementBytes;
            cnt++;
        }
        else
        {
            break;
        }
    }
  
    return cnt;
}
  
/*********************************************************************
 * @brief       清空Queue
 * @param[in]   pQueue: Queue指针
 * @return      None
 *********************************************************************/
void Queue_Clear(Queue_Type *pQueue)
{
    pQueue->Counter = 0;
    pQueue->Head = 0;
    pQueue->Tail = 0;
}

测试代码

void TestQueue(void)
{
    int i;
    Queue_Type   queue;
    Queue_Type   *pQueue;
    int         index;
    float       fArray[10];
    float       fValue;
  
    char        cArray[10];
    char        cValue;
  
    pQueue = &queue;
  
    printf("测试Queue元素为float型的数据\r\n");
    printf("初始化Queue值。\r\n");
    Queue_Init(pQueue, fArray, sizeof(float), 10);
    for (i = 0; i < 10; i++)
    {
        fValue = (100.0f+i*i);
        Queue_AddOne(pQueue, &fValue);
    }
    printf("当前元数个数:%d\r\n", pQueue->Counter);
    index = 0;
    while(Queue_GetOne(pQueue, &fValue))
    {
        index ++;
        printf("第%d个元素fValue = %0.3f\r\n",index, fValue);
        if (index == 5)
        {
            printf("插入3个值。\r\n");
            fValue = 1.23f;
            Queue_AddOne(pQueue, &fValue);
  
            fValue = 2.34f;
            Queue_AddOne(pQueue, &fValue);
  
            fValue = 3.45f;
            Queue_AddOne(pQueue, &fValue);
        }
    }
  
    printf("\r\n\r\n");
    printf("测试Queue元素为char型的数据\r\n");
    Queue_Init(pQueue, cArray, sizeof(char), 10);
    printf("初始化Queue值。\r\n");
    Queue_Add(pQueue, "ABCDEFGHIJ", 10);
    printf("当前元数个数:%d\r\n", pQueue->Counter);
    index = 0;
    while(Queue_GetOne(pQueue, &cValue))
    {
        index ++;
        printf("第%d个元素cValue = %c\r\n",index, cValue);
        if (index == 5)
        {
            printf("插入3个值。\r\n");
            cValue = 'X';
            Queue_AddOne(pQueue, &cValue);
  
            cValue = 'Y';
            Queue_AddOne(pQueue, &cValue);
  
            cValue = 'Z';
            Queue_AddOne(pQueue, &cValue);
        }
    }
}