//---------------------------------------------------------------------------
// 模块: 环形缓冲区类 TFengRingBuf
// 版本号: V0.31
// 编写人: Twicave(twicave@yahoo.com.cn)
//
// 简要说明: 实现了环形缓冲区(频繁的读取写入操作时,无需进行缓冲区的重整)
// 主要用于通讯类的操作.代码用C++ template编写,可直接以源代码
// 的方式包含进工程中使用.BC6.0测试通过.不含BC Local代码,可用
// 于其他编译环境.
//
// !警告!: (对象数组的初始化)如果以数组的方式使用本类,那么缺省的尺
// 寸是0。请特别注意。改变尺寸,请使用Resize()函数。
// 备注:
// Aug08,2008 v0.31
// 修改了取出缓冲区内容的一个bug.内部的内存拷贝没有考虑TYPE元
// 素的尺寸。
//
// Aug06,2008 V0.3
// 添加一条警告信息(关于对象数组的初始化),并完善缺省、拷贝
// 构造函数、赋值函数和相等、不等验证函数。
//
// Aug05,2008 V0.21
// 初步完成。支持接近手工编码的方案。需要解释一下"只读"的概念.
// 在尝试对环形缓冲区进行写入操作时,因为Context中的函数均是对
// 标准缓冲区进行操作的.此时涉及缓冲区的转换操作.这里采用的方案
// 是先用WriteBuf()取出一个缓冲区,这个缓冲区可能就位于原始缓冲
// 区内,也可能是因为接近边界处而生成的一个临时缓冲区.因为此时
// 可能已经对环形缓冲区的内容进行写入操作(在相当高的概率下),所
// 以后续的写入操作必须延迟(写入操作涉及Resize和Push).对于缓冲
// 区的察看,有类似的情形.一旦用户通过ReadBuf()注册了对缓冲区的
// 察看操作,则后续的对读指针的修改也必须挂起.否则可能导致正在读
// 取的内容被后续写入操作污染.
// 目前尚需要改进的地方有循环概念的实现.(目前一旦缓冲区满就不再
// 接受最新的输入了.)不过环形缓冲区 != 循环缓冲区.对不对?
// Bug修正: Reset()时CommitRead&WriteBuf.
//
// Aug04,2008 V0.2
// 发现最重要的工作是如何替换标准的缓冲区。性能必须要接近标准缓
// 冲区,否则就失去意义了。
//
// Aug02,2008 开始编码
//---------------------------------------------------------------------------
#ifndef FengRingBufH
#define FengRingBufH
#include <ctype.h> //for size_t定义
#include <assert.h> //for assert()
//---------------------------------------------------------------------------
template<class TYPE = unsigned char>
class TFengRingBuf
{
public:
//构造函数
TFengRingBuf(size_t size = 0);
//析构函数
virtual ~TFengRingBuf(void);
//拷贝构造函数
TFengRingBuf(const TFengRingBuf<TYPE>& rhs);
//赋值函数
TFengRingBuf<TYPE>& operator=(const TFengRingBuf<TYPE>& rhs);
//取容量
inline size_t Size(void) const;
//取长度
size_t Len(void) const;
//取元素
TYPE operator[](size_t pos);
//归零
inline void Reset(void);
//重设缓冲区尺寸
void Resize(size_t size);
//导入数据
size_t Push(TYPE *buf, size_t len);
//导入数据,用于缓冲区之间转移 (buf=>本地,buf相关指针不变)
size_t Push(const TFengRingBuf<TYPE>& buf, size_t len);
//缓冲区转换(用户负责对返回的数组析构)
TYPE* Get(size_t& len) const;
//读取数据
size_t Get(TYPE *buf, size_t len) const;
//取出数据(用户负责对返回的数组析构)
TYPE* Pop(size_t& len);
//取出数据
size_t Pop(TYPE *buf, size_t len);
//导出数据,用于缓冲区之间转移 (本地=>buf,本地相关指针改变)
size_t Pop(TFengRingBuf<TYPE>& buf, size_t& len);
//导出写入缓冲区(本操作执行以后无法对缓冲区进行写入操作)
TYPE* WriteBuf(size_t size = 0);
//写入缓冲区尺寸
inline size_t SizeOfWriteBuf(void);
//写入缓冲区长度
inline size_t& LenOfWriteBuf(void);
//导出的写入缓冲区提交(提交后恢复对缓冲区进行写入操作响应)
size_t CommitWriteBuf(size_t len);
//导出读取缓冲区(本操作执行以后不可对读指针进行移动,实际的缓冲区尺寸可能不足size,请查询SizeOfReadBuf())
TYPE* ReadBuf(size_t size = 0);
//读取缓冲区尺寸
inline size_t SizeOfReadBuf(void);
//读取缓冲区位置指针
inline size_t& PosOfReadBuf(void);
//导出的读取缓冲区提交(提交后恢复对对读指针移动的响应)
size_t CommitReadBuf(size_t len);
private:
TYPE *_buf; //缓冲区指针
size_t _pRead; //读指针
size_t _pWrite; //写指针
size_t _size; //尺寸
TYPE *_writeBuf; //写入缓冲区首地址
size_t _sizeWriteBuf; //写入缓冲区尺寸
size_t _lenWriteBuf; //写入缓冲区位置指针
bool _isWriteBufTemp; //写入缓冲区是否为临时缓冲区
TYPE *_readBuf; //读取缓冲区首地址
size_t _sizeReadBuf; //读取缓冲区尺寸
size_t _posReadBuf; //读取缓冲区读取指针
bool _isReadBufTemp; //读取缓冲区是否为临时缓冲区
};
template<class TYPE>
TFengRingBuf<TYPE>::TFengRingBuf(size_t size)
{
_pRead = _pWrite = 0;
_buf = new TYPE[size + 1];
assert(NULL != _buf);
_size = size;
_writeBuf = NULL;
_sizeWriteBuf = 0;
_lenWriteBuf = 0;
_isWriteBufTemp = false;
_readBuf = NULL;
_sizeReadBuf = 0;
_posReadBuf = 0;
_isReadBufTemp = false;
}
template<class TYPE>
TFengRingBuf<TYPE>::~TFengRingBuf(void)
{
if(0 != SizeOfWriteBuf()) CommitWriteBuf(0); //writeBuf只读处理
if(0 != SizeOfReadBuf()) CommitReadBuf(0); //readBuf只读处理
delete[] _buf;
}
template<class TYPE>
TFengRingBuf<TYPE>::TFengRingBuf(const TFengRingBuf<TYPE>& rhs)
{
_pRead = _pWrite = 0;
_buf = new TYPE[rhs.Size() + 1];
assert(NULL != _buf);
_size = rhs.Size();
_writeBuf = NULL;
_sizeWriteBuf = 0;
_lenWriteBuf = 0;
_isWriteBufTemp = false;
_readBuf = NULL;
_sizeReadBuf = 0;
_posReadBuf = 0;
_isReadBufTemp = false;
Push(rhs, rhs.Len());
}
template<class TYPE>
TFengRingBuf<TYPE>& TFengRingBuf<TYPE>::operator=(const TFengRingBuf<TYPE>& rhs)
{
Reset();
Push(rhs, rhs.Len());
return *this;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Size(void) const
{
return _size;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Len(void) const
{
return ((_pWrite+Size()+1) - _pRead) % (Size()+1);
}
template<class TYPE>
TYPE TFengRingBuf<TYPE>::operator[](size_t pos)
{
return _buf[(_pRead+pos)%(Size()+1)];
}
template<class TYPE>
void TFengRingBuf<TYPE>::Reset(void)
{
if(0 != SizeOfWriteBuf()) CommitWriteBuf(0); //writeBuf只读处理
if(0 != SizeOfReadBuf()) CommitReadBuf(0); //readBuf只读处理
_pRead = _pWrite = 0;
}
template<class TYPE>
void TFengRingBuf<TYPE>::Resize(size_t size)
{
if(0 != SizeOfWriteBuf()) return; //writeBuf只读处理
//取出所有数据,并删除原始数组
size_t len;
TYPE *buf = Get(len);
delete[] _buf;
Reset();
_buf = new TYPE[size + 1];
_size = size;
assert(NULL != _buf);
Push(buf, len);
delete[] buf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Push(TYPE *buf, size_t len)
{
if(0 != SizeOfWriteBuf()) return 0; //writeBuf只读处理
//传入数据溢出处理(仅移入尾部)
if(len > Size() - Len())
{
size_t oldLen = len;
len = Size() - Len();
buf += oldLen - len;
}
if(0 == len) return 0;
//尝试分两步拷贝
size_t tryMove = (0 == _pRead) ?
Size()+1-_pWrite-1 : Size()+1-_pWrite;
if( tryMove >= len)
{
memcpy(&_buf[_pWrite], buf, sizeof(TYPE)*len);
}
else
{
memcpy(&_buf[_pWrite], buf, sizeof(TYPE)*tryMove);
memcpy(&_buf[0], &buf[tryMove], sizeof(TYPE)*(len - tryMove));
}
//指针移动
_pWrite += len;
_pWrite %= Size() + 1;
return len;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Push(const TFengRingBuf<TYPE>& buf, size_t len)
{
if(0 != SizeOfWriteBuf()) return 0; //writeBuf只读处理
size_t ret, tempLen;
tempLen = len > buf.Len() ? buf.Len() : len;
TYPE *tempBuf = new TYPE[tempLen];
tempLen = buf.Get(tempBuf, tempLen);
ret = Push(tempBuf, tempLen);
delete[] tempBuf;
return ret;
}
template<class TYPE>
TYPE * TFengRingBuf<TYPE>::Get(size_t& len) const
{
TYPE *buf(NULL);
len = Len();
if(0 != len)
{
buf = new TYPE[Len()];
Get(buf, Len());
}
return buf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Get(TYPE *buf, size_t len) const
{
//传入参数合法化
if(len > Len())
{
len = Len();
}
//尝试分两步拷贝
size_t tryMove = (_pWrite > _pRead) ?
_pWrite - _pRead : (Size()+1 - _pRead);
if(len <= tryMove)
{
memcpy(buf, &_buf[_pRead], len*sizeof(TYPE));
}
else
{
memcpy(&buf[0], &_buf[_pRead], tryMove*sizeof(TYPE));
memcpy(&buf[tryMove], &_buf[0], (len-tryMove)*sizeof(TYPE));
}
return len;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Pop(TYPE *buf, size_t len)
{
if(0 != SizeOfReadBuf()) return 0; //readBuf只读处理
len = Get(buf, len);
_pRead += len;
_pRead %= Size() + 1;
return len;
}
template<class TYPE>
TYPE * TFengRingBuf<TYPE>::Pop(size_t& len)
{
len = 0;
if(0 != SizeOfReadBuf()) return NULL; //readBuf只读处理
TYPE *buf = Get(len);
_pRead += len;
_pRead %= Size() + 1;
return buf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::Pop(TFengRingBuf<TYPE>& buf, size_t& len)
{
if(0 != SizeOfReadBuf()) return 0; //readBuf只读处理
if(len > this->Len())
{
len = this->Len();
}
size_t ret = buf.Push(*this, len);
_pRead += len;
_pRead %= Size() + 1;
return ret;
}
template<class TYPE>
TYPE* TFengRingBuf<TYPE>::WriteBuf(size_t size)
{
if(0 == size) return _writeBuf;
if(0 != _sizeWriteBuf && 0 != size) return NULL; //writeBuf仅可取出一次,不支持多重导出
_sizeWriteBuf = size;
_lenWriteBuf = 0;
if(Size()+1 - _pWrite >= size)
{
_writeBuf = &_buf[_pWrite];
_isWriteBufTemp = false;
}
else
{
_writeBuf = new TYPE[size];
assert(NULL != _writeBuf);
_isWriteBufTemp = true;
}
return _writeBuf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::SizeOfWriteBuf(void)
{
return _sizeWriteBuf;
}
template<class TYPE>
size_t& TFengRingBuf<TYPE>::LenOfWriteBuf(void)
{
return _lenWriteBuf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::CommitWriteBuf(size_t len)
{
if(0 == _sizeWriteBuf) return 0;
if(len > _sizeWriteBuf) len = _sizeWriteBuf; //防止越界访问
TYPE *pOuterBuf = _writeBuf;
_writeBuf = NULL;
_sizeWriteBuf = 0; //首先脱离outerBuf状态,否则无法写入
if(_isWriteBufTemp)
{
len = Push(pOuterBuf, len);
delete[] pOuterBuf;
_isWriteBufTemp = false;
}
else
{
_pWrite += len; //无需处理指针回环
}
_lenWriteBuf = 0;
return len;
}
template<class TYPE>
TYPE* TFengRingBuf<TYPE>::ReadBuf(size_t size)
{
if(size > Len()) size = Len(); //防止越界访问
if(0 == size) return _readBuf; //注意与上条语句的顺序
if(0 != _sizeReadBuf && 0 != size) return NULL; //ReadBuf仅可取出一次,不支持多重导出
if(Size()+1 - _pRead >= size)
{
_readBuf = &_buf[_pRead];
_isReadBufTemp = false;
}
else
{
_readBuf = new TYPE[size];
assert(NULL != _readBuf);
Get(_readBuf, size);
_isReadBufTemp = true;
}
_sizeReadBuf = size;
_posReadBuf = 0;
return _readBuf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::SizeOfReadBuf(void)
{
return _sizeReadBuf;
}
template<class TYPE>
size_t& TFengRingBuf<TYPE>::PosOfReadBuf(void)
{
return _posReadBuf;
}
template<class TYPE>
size_t TFengRingBuf<TYPE>::CommitReadBuf(size_t len)
{
if(len > Len()) len = Len(); //防止越界访问
_pRead += len;
_pRead %= Size() + 1;
if(0 == _sizeReadBuf) return 0; //对于普通的读指针移动已经执行完毕
if(_isReadBufTemp)
{
delete[] _readBuf;
_isReadBufTemp = false;
}
_posReadBuf = 0;
_sizeReadBuf = 0;
_readBuf = NULL;
return len;
}
//---------------------------------------------------------------------------
//相等函数(仅判断尺寸是否一致)
template<class TYPE>
bool operator==(const TFengRingBuf<TYPE>& lhs, const TFengRingBuf<TYPE>& rhs)
{
return lhs.Size() == rhs.Size();
}
//不等函数(仅判断尺寸是否一致)
template<class TYPE>
bool operator!=(const TFengRingBuf<TYPE>& lhs, const TFengRingBuf<TYPE>& rhs)
{
return !(lhs == rhs);
}
#endif