Last active
August 20, 2017 08:37
-
-
Save huiliu/ee210e31776fa1d2fe96d1214579f5e8 to your computer and use it in GitHub Desktop.
RingBuffer.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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