这篇是CircularBuffer类
用途:
在Socket类中用做高级缓冲区,接收recv的数据,把指针通过OnRawData传给用户处理。
TcpSocket::OnWrite()函数还会把本缓冲区的数据发出去(send)。
所以用了它用户不需要太多的管理缓冲区了。
分析:
利用了几个size_t变量指示数据开始,结尾,长度,最大值,实现的数据的写入与读出。
由于类结构不太大,罗列如下:
/** Buffer class containing one read/write circular buffer.
\ingroup internal */
class CircularBuffer
{
public:
CircularBuffer(Socket& owner,size_t size);//size是缓冲区的初始大小
~CircularBuffer();
/** append l bytes from p to buffer */
bool Write(const char *p,size_t l);
/** copy l bytes from buffer to dest */
bool Read(char *dest,size_t l);
/** skip l bytes from buffer */
bool Remove(size_t l);
/** total buffer length */
size_t GetLength();
/** pointer to circular buffer beginning */
char *GetStart();
/** return number of bytes from circular buffer beginning to buffer physical end */
size_t GetL();
/** return free space in buffer, number of bytes until buffer overrun */
size_t Space();
/** return total number of bytes written to this buffer, ever */
unsigned long ByteCounter();
private:
Socket& GetOwner() const;
CircularBuffer(const CircularBuffer& s) : m_owner( s.GetOwner() ) {}
CircularBuffer& operator=(const CircularBuffer& ) { return *this; }
Socket& m_owner; /*缓冲区总是为Socket类准备的*/
char *buf; /*缓冲区指针*/
size_t m_max; /*数据最大值*/
size_t m_q; /*是数据的长度Length*/
size_t m_b; /*数据的开始位置*/
size_t m_t; /*数据的结束位置*/
unsigned long m_count; /*如果只调用Write,不调用read函数,返回所有写入的字节数,如果调用过read函数,返回所有写入的字节数,包括read函数中被删除的字节数*/
};
初始化:
CircularBuffer::CircularBuffer(Socket& owner,size_t size)
:m_owner(owner)
,buf(new char[size])
,m_max(size)
,m_q(0)
,m_b(0)
,m_t(0)
,m_count(0)
{
}
/*写入时只需要数据的结尾位置m_t和大小(l,m_q)一些信息,不需要知道数据的开始位置m_b,写入时不更改m_b变量,只更改m_t*/
bool CircularBuffer::Write(const char *s,size_t l) /**/
{
if (m_q + l > m_max) //在Read函数中改变m_q的机会多,而只有m_q为0才会m_t=m_q=0,所以
{
m_owner.Handler().LogError(&m_owner, "CircularBuffer::Write", -1, "write buffer overflow");
return false; // overflow
}
m_count += (unsigned long)l; /*总写入的字节计数器*/
if (m_t + l > m_max) // block crosses circular border 当read函数执行后会有可能
{
size_t l1 = m_max - m_t; // size left until circular border crossing
memcpy(buf + m_t, s, l1); //原型:extern void *memcpy(void *dest, void *src, unsigned int count);
memcpy(buf, s + l1, l - l1);
m_t = l - l1; /*赋值后m_t又历经一循环,回到了l-l1处.因为此时m_t+l已大于m_max*/
m_q += l;
}
else
{
memcpy(buf + m_t, s, l);
m_t += l;
if (m_t >= m_max) /*好象最多相等哦,不可能>么*/
m_t -= m_max; /*m_t=m_max时m_t归零*/
m_q += l; /*m_q一直相加,最多等于m_max*/
}
return true;
}
/*读出时只需要数据的开始位置m_b和要读的大小l和总数据长度m_q,不需要结尾位置m_t,如s为NULL,还可起到删除的作用*/
bool CircularBuffer::Read(char *s,size_t l) /* l代表要读的长度,读时只改变m_b,m_q不改变m_t*/
{
if (l > m_q)
{
m_owner.Handler().LogError(&m_owner, s ? "CircularBuffer::Read" : "CircularBuffer::Write", -1, "attempt to read beyond buffer");
return false; // not enough chars
}
if (m_b + l > m_max) // block crosses circular border . m_b是起点
{
size_t l1 = m_max - m_b; /* l1是后面的部分,l-l1是前面的部分*/
if (s)
{
memcpy(s, buf + m_b, l1); /*这儿用 l1 代替了l,因为只有这么多的有效数据,l大点没关系*/
memcpy(s + l1, buf, l - l1); /* l-l1 应该最多是m_b,因为l<=m_q */
}
m_b = l - l1; /*读完后清除被读的数据*/
m_q -= l; /*m_q是数据长度,也要减去已读的数据长度 */
}
else
{
if (s)
{
memcpy(s, buf + m_b, l);
}
m_b += l; /*这里是正常情况,没有循环写入*/
if (m_b >= m_max)
m_b -= m_max;
m_q -= l;
}
if (!m_q)
{
m_b = m_t = 0;
}
return true;
}
bool CircularBuffer::Remove(size_t l)
{
return Read(NULL, l);
}
size_t CircularBuffer::GetLength()
{
return m_q;
}
char *CircularBuffer::GetStart()
{
return buf + m_b;
}
size_t CircularBuffer::GetL()
{
return (m_b + m_q > m_max) ? m_max - m_b : m_q;
}
size_t CircularBuffer::Space()
{
return m_max - m_q;
}
unsigned long CircularBuffer::ByteCounter()
{
return m_count;
}
Socket& CircularBuffer::GetOwner() const
{
return m_owner;
}
怎么样,这个类不错吧,COPY一下洋为中用了。
阅读(2367) | 评论(0) | 转发(0) |