Skip to content

Instantly share code, notes, and snippets.

@huiliu
Last active August 20, 2017 08:37
Show Gist options
  • Save huiliu/ee210e31776fa1d2fe96d1214579f5e8 to your computer and use it in GitHub Desktop.
Save huiliu/ee210e31776fa1d2fe96d1214579f5e8 to your computer and use it in GitHub Desktop.
RingBuffer.cpp
#include "stdafx.h"
#include <iostream>
#include <cassert>
#include <memory>
#include <tuple>
typedef char* CharSPtr;
class RingBuffer
{
public:
RingBuffer::RingBuffer(int capacity)
: m_capacity(capacity)
, m_head(0)
, m_tail(0)
, m_pBuffer(new char[capacity + 1])
{
assert(nullptr != m_pBuffer);
}
RingBuffer::~RingBuffer()
{
delete[] m_pBuffer;
}
void Print()
{
std::cout << "Capacity : " << m_capacity << "\t"
<< "size : " << Size() << "\t"
<< "head : " << m_head << "\t"
<< "tail : " << m_tail << "\t"
<< std::endl;
}
public:
int Capacity() const
{
return m_capacity;
}
bool IsEmpty() const
{
return Size() == 0;
}
bool IsFull() const
{
return Size() == m_capacity;
}
int Append(char* buff, int sz)
{
if (m_tail >= m_head)
{
return AppendWrap(buff, sz);
}
else
{
return AppendDirect(buff, sz);
}
}
std::tuple<CharSPtr, int> Read(int sz)
{
if (m_tail >= m_head)
{
return ReadDirect(sz);
}
else
{
return ReadWrap(sz);
}
}
// 当前Buffer中缓存数据量
int Size() const
{
if (m_tail >= m_head)
{
return m_tail - m_head;
}
else
{
return m_capacity + 1 - (m_head - m_tail);
}
}
private:
// 返回已写入数据
// ------head#############tail--------
int AppendWrap(char* buff, int sz)
{
assert(m_tail >= m_head);
if (sz < m_capacity + 1 - m_tail)
{
// m_tail - capacity 有足够容量
std::memcpy(m_pBuffer + m_tail, buff, sz);
m_tail += sz;
return sz;
}
else if (sz == m_capacity + 1 - m_tail)
{
std::memcpy(m_pBuffer + m_tail, buff, sz);
m_tail = 0;
return sz;
}
else
{
int tailCount = m_capacity + 1 - m_tail;
std::memcpy(m_pBuffer + m_tail, buff, tailCount);
int remaind = sz - tailCount;
if (remaind < m_head - 1)
{
std::memcpy(m_pBuffer, buff + tailCount, remaind);
m_tail = remaind;
return sz;
}
else
{
std::memcpy(m_pBuffer, buff + tailCount, m_head - 1);
m_tail = m_head - 1;
return remaind - (m_head - 1);
}
}
assert(false);
}
// #####tail---------head#######
int AppendDirect(char* buff, int sz)
{
assert(m_head > m_tail);
int writeSize = sz;
if (writeSize >= m_head - m_tail)
{
writeSize = m_head - m_tail - 1;
}
std::memcpy(m_pBuffer + m_tail, buff, writeSize);
m_tail += writeSize;
return writeSize;
}
std::tuple<CharSPtr, int> ReadDirect(int sz)
{
assert(m_tail >= m_head);
int actualSize = sz;
if (sz > Size())
{
actualSize = Size();
}
CharSPtr b = new char[actualSize+1];
std::memcpy(b, m_pBuffer + m_head, actualSize);
b[actualSize] = '\0';
m_head += actualSize;
return std::tuple<CharSPtr, int>(b, actualSize);
}
std::tuple<CharSPtr, int> ReadWrap(int sz)
{
assert(m_head > m_tail);
if (sz <= m_capacity - m_head)
{
CharSPtr b = new char[sz+1];
std::memcpy(b, m_pBuffer + m_head, sz);
b[sz] = '\0';
m_head += sz;
return std::tuple<CharSPtr, int>(b, sz);
}
else
{
int actualSize = sz;
if (sz > Size())
{
actualSize = Size();
}
CharSPtr b = new char[actualSize + 1];
std::memcpy(b, m_pBuffer + m_head, m_capacity + 1 - m_head);
std::memcpy(b + m_capacity + 1 - m_head, m_pBuffer, actualSize - (m_capacity + 1 - m_head));
b[actualSize] = '\0';
m_head = actualSize - (m_capacity + 1 - m_head);
return std::tuple<CharSPtr, int>(b, actualSize);
}
}
private:
int m_capacity;
int m_head;
int m_tail;
CharSPtr m_pBuffer;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment