环形队列实现异步传输数据间的缓存

//**********************************************************************************************
//  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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值