//**********************************************************************************************
// Copyright By BFSoft
// 20130419 By zhangwf
// 环形队列,在异步传递数据时用作缓存
//**********************************************************************************************
#ifndef __CIRCULAR_QUEUE_BFSOFT_H
#define __CIRCULAR_QUEUE_BFSOFT_H
#ifdef __cplusplus
extern "C" {
#endif
// 定义用到的数据类型
typedef unsigned long CQULONG;
typedef enum {CQ_FALSE=0, CQ_TRUE=1} CQBOOL;
typedef unsigned char CQBYTE;
//
// 取得队列大小,可以在.c文件中修改队列的大小
CQULONG CQUE_GetSize(void);
// 判断队列是否为空
CQBOOL CQUE_Empty(void);
// 判断队列是否为满
CQBOOL CQUE_Full(void);
// 取得当前队列中字节数量
CQULONG CQUE_GetDataByteCount(void);
// 取得当前队列中空位字节数量
CQULONG CQUE_GetEmptyByteCount(void);
// 追加一个字节到队列尾部
// 返回CQ_FALSE表示队列满
CQBOOL CQUE_PushByte(CQBYTE byteVal);
// 从队列头部取出一个字节的数据
// 返回CQ_FALSE表示队列为空
CQBOOL CQUE_PopByte(CQBYTE *pByteVal);
// 追加一段字节数据到队列尾部
// 返回CQ_FALSE表示队列剩余空间不够追加的数据字节数
// 此时仍然会追加数据,具体追加的字节数由plNumberOfBytesPushed输出
CQBOOL CQUE_PushBuf(
const CQBYTE *pBuf, // 待追加数据缓冲区
CQULONG lNumberOfBytesToPush, // 待追加数据字节数
CQULONG *plNumberOfBytesPushed // 输出实际追加的字节数
);
// 从队列头部取出一段字节数据
// 返回CQ_FALSE表示队列为空
// 否则plNumberOfBytesPoped输出实际取出的字节数
CQBOOL CQUE_PopBuf(
CQBYTE *pBuf, // 存放读取字节数据缓冲区
CQULONG lNumberOfBytesToPop, // 待读取数据字节数
CQULONG *plNumberOfBytesPoped // 输出实际读取的字节数
);
#ifdef __cplusplus
}
#endif
#endif
//**********************************************************************************************
// Copyright By BFSoft
// 20130419 By zhangwf
// 环形队列,在异步传递数据时用作缓存
//**********************************************************************************************
#include "circular_queue.h"
#include <string.h>
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
// 定义队列字节大小
#define CQUEUE_DATABYTE_SIZE 64
// 定义队列结构
typedef struct
{
CQULONG uHead; // 头
CQULONG uTail; // 尾
CQBOOL bEmpty; // 是否为空
CQBYTE DataBuf[CQUEUE_DATABYTE_SIZE]; // 数据区
}CQUEUEDATA;
// 定义静态循环队列,外部访问必须通过接口操作数据
static CQUEUEDATA CQING_Queue = {0, 0, CQ_TRUE, {0}};
// 取得队列大小,可以在.c文件中修改队列的大小
CQULONG CQUE_GetSize(void)
{
return CQUEUE_DATABYTE_SIZE;
}
// 判断队列是否为空
CQBOOL CQUE_Empty(void)
{
return ( CQING_Queue.uHead == CQING_Queue.uTail
&& CQING_Queue.bEmpty == CQ_TRUE
) ? CQ_TRUE : CQ_FALSE;
}
// 判断队列是否为满
CQBOOL CQUE_Full(void)
{
return ( CQING_Queue.uHead == CQING_Queue.uTail
&& CQING_Queue.bEmpty == CQ_FALSE
) ? CQ_TRUE : CQ_FALSE;
}
// 取得当前队列中字节数量
CQULONG CQUE_GetDataByteCount(void)
{
// 尾部在头部之后
if (CQING_Queue.uTail > CQING_Queue.uHead)
{
return (CQING_Queue.uTail - CQING_Queue.uHead);
}
// 头部在尾部之后
else if (CQING_Queue.uTail < CQING_Queue.uHead)
{
return (CQUEUE_DATABYTE_SIZE-CQING_Queue.uHead + CQING_Queue.uTail);
}
// 头部和尾部重合,此时或者空或者满
else
{
return (CQING_Queue.bEmpty == CQ_TRUE) ? 0 : CQUEUE_DATABYTE_SIZE;
}
}
// 取得当前队列中空位字节数量
CQULONG CQUE_GetEmptyByteCount(void)
{
return (CQUEUE_DATABYTE_SIZE - CQUE_GetDataByteCount());
}
// 追加一个字节到队列尾部
CQBOOL CQUE_PushByte(CQBYTE byteVal)
{
// 队列满直接返回
if (CQUE_Full() == CQ_TRUE)
{
return CQ_FALSE;
}
// 追加一个字节到队列尾
CQING_Queue.DataBuf[CQING_Queue.uTail] = byteVal;
CQING_Queue.uTail += 1;
if (CQING_Queue.uTail >= CQUEUE_DATABYTE_SIZE)
{
CQING_Queue.uTail = 0;
}
// 修改标记非空
if (CQING_Queue.bEmpty == CQ_TRUE)
{
CQING_Queue.bEmpty = CQ_FALSE;
}
// 追加数据成功
return CQ_TRUE;
}
// 从队列头部取出一个字节的数据
CQBOOL CQUE_PopByte(CQBYTE *pByteVal)
{
// 参数错误或队列为空
if ( pByteVal == NULL
|| CQUE_Empty() == CQ_TRUE
)
{
return CQ_FALSE;
}
// 取出头部字节
*pByteVal = CQING_Queue.DataBuf[CQING_Queue.uHead];
CQING_Queue.uHead += 1;
if (CQING_Queue.uHead >= CQUEUE_DATABYTE_SIZE)
{
CQING_Queue.uHead = 0;
}
// 修改是否为空标记
if (CQING_Queue.uHead == CQING_Queue.uTail)
{
CQING_Queue.bEmpty = CQ_TRUE;
}
// 返回取出字节成功
return CQ_TRUE;
}
// 追加一段字节数据到队列尾部
CQBOOL CQUE_PushBuf(
const CQBYTE *pBuf, // 待追加数据缓冲区
CQULONG lNumberOfBytesToPush, // 待追加数据字节数
CQULONG *plNumberOfBytesPushed // 输出实际追加的字节数
)
{
// 记录实际追加字节数
CQULONG lRemainEmptyBytes = CQUE_GetEmptyByteCount();
CQULONG lRealPushBytes = 0;
CQULONG lTailBytes = 0;
// 初始化输出参数
if (plNumberOfBytesPushed != NULL)
{
*plNumberOfBytesPushed = 0;
}
// 无空位或参数错误
if ( lRemainEmptyBytes == 0
|| pBuf == NULL
|| lNumberOfBytesToPush == 0
)
{
return CQ_FALSE;
}
// 计算可追加字节数
lRealPushBytes = (lRemainEmptyBytes>=lNumberOfBytesToPush) ? lNumberOfBytesToPush : lRemainEmptyBytes;
// 计算数组尾部字节数
lTailBytes = CQUEUE_DATABYTE_SIZE - CQING_Queue.uTail;
if (lTailBytes >= lRealPushBytes)
{
memcpy(CQING_Queue.DataBuf+CQING_Queue.uTail, pBuf, lRealPushBytes);
}
// 分段拷贝,先拷贝到数组尾部的,然后从数组头部开始拷贝
else
{
memcpy(CQING_Queue.DataBuf+CQING_Queue.uTail, pBuf, lTailBytes);
memcpy(CQING_Queue.DataBuf, pBuf+lTailBytes, lRealPushBytes-lTailBytes);
}
// 修改队列尾位置
CQING_Queue.uTail += lRealPushBytes;
CQING_Queue.uTail %= CQUEUE_DATABYTE_SIZE;
// 修改标记非空
if (CQING_Queue.bEmpty == CQ_TRUE)
{
CQING_Queue.bEmpty = CQ_FALSE;
}
// 输出实际追加字节数
if (plNumberOfBytesPushed != NULL)
{
*plNumberOfBytesPushed = lRealPushBytes;
}
// 返回是否追加数据成功
return (lRealPushBytes == lNumberOfBytesToPush) ? CQ_TRUE : CQ_FALSE;
}
// 从队列头部取出一段字节数据
CQBOOL CQUE_PopBuf(
CQBYTE *pBuf, // 存放读取字节数据缓冲区
CQULONG lNumberOfBytesToPop, // 待读取数据字节数
CQULONG *plNumberOfBytesPoped // 输出实际读取的字节数
)
{
// 记录实际读取字节数
CQULONG lCurrentDataBytes = CQUE_GetDataByteCount();
CQULONG lRealPopBytes = 0;
CQULONG lRearBytes = 0;
// 初始化输出参数
if (plNumberOfBytesPoped != NULL)
{
*plNumberOfBytesPoped = 0;
}
// 无数据或参数错误
if ( lCurrentDataBytes == 0
|| pBuf == NULL
|| lNumberOfBytesToPop == 0
)
{
return CQ_FALSE;
}
// 计算可读取字节数
lRealPopBytes = (lCurrentDataBytes>=lNumberOfBytesToPop) ? lNumberOfBytesToPop : lCurrentDataBytes;
// 计算数组尾部字节数并拷贝数据
lRearBytes = CQUEUE_DATABYTE_SIZE - CQING_Queue.uHead;
if (lRearBytes >= lRealPopBytes)
{
memcpy(pBuf, CQING_Queue.DataBuf+CQING_Queue.uHead, lRealPopBytes);
}
// 分段拷贝,先拷贝数组尾部的,然后从数组头部开始拷贝
else
{
memcpy(pBuf, CQING_Queue.DataBuf+CQING_Queue.uHead, lRearBytes);
memcpy(pBuf+lRearBytes, CQING_Queue.DataBuf, lRealPopBytes-lRearBytes);
}
// 修改队列头位置
CQING_Queue.uHead += lRealPopBytes;
CQING_Queue.uHead %= CQUEUE_DATABYTE_SIZE;
// 修改是否为空标记
if (CQING_Queue.uHead == CQING_Queue.uTail)
{
CQING_Queue.bEmpty = CQ_TRUE;
}
// 输出实际读取字节数
if (plNumberOfBytesPoped != NULL)
{
*plNumberOfBytesPoped = lRealPopBytes;
}
// 返回读取成功
return CQ_TRUE;
}