- //---------------------------------------------------------------------------
- // 模块: 环形缓冲区类 TFengRingBuf
- // 版本号: V0.3
- // 编写人: Twicave(twicave@yahoo.com.cn)
- //
- // 简要说明: 实现了环形缓冲区(频繁的读取写入操作时,无需进行缓冲区的重整)
- // 主要用于通讯类的操作.代码用C++ template编写,可直接以源代码
- // 的方式包含进工程中使用.BC6.0测试通过.不含BC Local代码,可用
- // 于其他编译环境.
- //
- // !警告!: (对象数组的初始化)如果以数组的方式使用本类,那么缺省的尺
- // 寸是0。请特别注意。改变尺寸,请使用Resize()函数。
- // 备注:
- // 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);
- }
- else
- {
- memcpy(&buf[0], &_buf[_pRead], tryMove);
- memcpy(&buf[tryMove], &_buf[0], len-tryMove);
- }
- 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