/* * CCycleBuffer.h * * Created on: 2013-5-27 * Author: shiguang */#ifndef __test__CCycleBuffer__#define __test__CCycleBuffer__#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>class CCycleBuffer{public:bool isFull();bool isEmpty();void Empty();int GetLength();CCycleBuffer(int size);virtual ~CCycleBuffer();int Write(char* buf, int count);int Read(char* buf, int count);private:bool m_bEmpty, m_bFull;char * m_pBuf;int m_nBufSize;int m_nReadPos;int m_nWritePos;public:int GetReadPos(){return m_nReadPos;}int GetWritePos(){return m_nWritePos;}};#endif /* defined(__test__CCycleBuffer__) */
/* * CCycleBuffer.cpp * * Created on: 2013-5-27 * Author: shiguang */#include "CCycleBuffer.h"// 定義CCycleBuffer::CCycleBuffer(int size){m_nBufSize = size;m_nReadPos = 0;m_nWritePos = 0;m_pBuf = new char[m_nBufSize];m_bEmpty = true;m_bFull = false;}CCycleBuffer::~CCycleBuffer(){delete[] m_pBuf;}/************************************************************************//* 向緩衝區寫入資料,返回實際寫入的位元組數 *//************************************************************************/int CCycleBuffer::Write(char* buf, int count){if (count <= 0)return 0;m_bEmpty = false;// 緩衝區已滿,不能繼續寫入if (m_bFull){return 0;}else if (m_nReadPos == m_nWritePos) // 緩衝區為空白時{/* == 記憶體模型 == (empty) m_nReadPos (empty) |----------------------------------|-----------------------------------------| m_nWritePos m_nBufSize */int leftcount = m_nBufSize - m_nWritePos;if (leftcount > count){memcpy(m_pBuf + m_nWritePos, buf, count);m_nWritePos += count;m_bFull = (m_nWritePos == m_nReadPos);return count;}else{memcpy(m_pBuf + m_nWritePos, buf, leftcount);m_nWritePos =(m_nReadPos > count - leftcount) ?count - leftcount : m_nReadPos; // 計算未寫入資料大小memcpy(m_pBuf, buf + leftcount, m_nWritePos);m_bFull = (m_nWritePos == m_nReadPos);return leftcount + m_nWritePos;}}else if (m_nReadPos < m_nWritePos) // 有剩餘空間可寫入{/* == 記憶體模型 == (empty) (data) (empty) |-------------------|----------------------------|---------------------------| m_nReadPos m_nWritePos (leftcount) */// 剩餘緩衝區大小(從寫入位置到緩衝區尾)int leftcount = m_nBufSize - m_nWritePos;if (leftcount > count) // 有足夠的剩餘空間存放{memcpy(m_pBuf + m_nWritePos, buf, count);m_nWritePos += count;m_bFull = (m_nReadPos == m_nWritePos);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return count;}else // 剩餘空間不足{// 先填充滿剩餘空間,再回頭找空間存放memcpy(m_pBuf + m_nWritePos, buf, leftcount);m_nWritePos =(m_nReadPos >= count - leftcount) ?count - leftcount : m_nReadPos;memcpy(m_pBuf, buf + leftcount, m_nWritePos);m_bFull = (m_nReadPos == m_nWritePos);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return leftcount + m_nWritePos;}}else{/* == 記憶體模型 == (unread) (read) (unread) |-------------------|----------------------------|---------------------------| m_nWritePos (leftcount) m_nReadPos */int leftcount = m_nReadPos - m_nWritePos;if (leftcount > count){// 有足夠的剩餘空間存放memcpy(m_pBuf + m_nWritePos, buf, count);m_nWritePos += count;m_bFull = (m_nReadPos == m_nWritePos);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return count;}else{// 剩餘空間不足時要丟棄後面的資料memcpy(m_pBuf + m_nWritePos, buf, leftcount);m_nWritePos += leftcount;m_bFull = (m_nReadPos == m_nWritePos);assert(m_bFull);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return leftcount;}}}/************************************************************************//* 從緩衝區讀資料,返回實際讀取的位元組數 *//************************************************************************/int CCycleBuffer::Read(char* buf, int count){if (count <= 0)return 0;m_bFull = false;if (m_bEmpty) // 緩衝區空,不能繼續讀取資料{return 0;}else if (m_nReadPos == m_nWritePos) // 緩衝區滿時{/* == 記憶體模型 == (data) m_nReadPos (data) |--------------------------------|--------------------------------------------| m_nWritePos m_nBufSize */int leftcount = m_nBufSize - m_nReadPos;if (leftcount > count){memcpy(buf, m_pBuf + m_nReadPos, count);m_nReadPos += count;m_bEmpty = (m_nReadPos == m_nWritePos);return count;}else{memcpy(buf, m_pBuf + m_nReadPos, leftcount);m_nReadPos =(m_nWritePos > count - leftcount) ?count - leftcount : m_nWritePos;memcpy(buf + leftcount, m_pBuf, m_nReadPos);m_bEmpty = (m_nReadPos == m_nWritePos);return leftcount + m_nReadPos;}}else if (m_nReadPos < m_nWritePos) // 寫指標在前(未讀資料是串連的){/* == 記憶體模型 == (read) (unread) (read) |-------------------|----------------------------|---------------------------| m_nReadPos m_nWritePos m_nBufSize */int leftcount = m_nWritePos - m_nReadPos;int c = (leftcount > count) ? count : leftcount;memcpy(buf, m_pBuf + m_nReadPos, c);m_nReadPos += c;m_bEmpty = (m_nReadPos == m_nWritePos);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return c;}else // 讀指標在前(未讀資料可能是不串連的){/* == 記憶體模型 == (unread) (read) (unread) |-------------------|----------------------------|---------------------------| m_nWritePos m_nReadPos m_nBufSize */int leftcount = m_nBufSize - m_nReadPos;if (leftcount > count) // 未讀緩衝區夠大,直接讀取資料{memcpy(buf, m_pBuf + m_nReadPos, count);m_nReadPos += count;m_bEmpty = (m_nReadPos == m_nWritePos);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return count;}else // 未讀緩衝區不足,需回到緩衝區頭開始讀{memcpy(buf, m_pBuf + m_nReadPos, leftcount);m_nReadPos =(m_nWritePos >= count - leftcount) ?count - leftcount : m_nWritePos; // 計算剩餘未讀資料大小memcpy(buf + leftcount, m_pBuf, m_nReadPos); // 注意目的指標位置m_bEmpty = (m_nReadPos == m_nWritePos);assert(m_nReadPos <= m_nBufSize);assert(m_nWritePos <= m_nBufSize);return leftcount + m_nReadPos;}}}/************************************************************************//* 擷取緩衝區有效資料長度 *//************************************************************************/int CCycleBuffer::GetLength(){if (m_bEmpty){return 0;}else if (m_bFull){return m_nBufSize;}else if (m_nReadPos < m_nWritePos){return m_nWritePos - m_nReadPos;}else{return m_nBufSize - m_nReadPos + m_nWritePos;}}void CCycleBuffer::Empty(){m_nReadPos = 0;m_nWritePos = 0;m_bEmpty = true;m_bFull = false;}bool CCycleBuffer::isEmpty(){return m_bEmpty;}bool CCycleBuffer::isFull(){return m_bFull;}
/* * main.cpp * * Created on: 2013-5-27 * Author: shiguang */#include "CCycleBuffer.h"int main(){CCycleBuffer buffer(100);char* datachar = new char[40];char* reschar = new char[100];int res = 0;for (int i = 0; i < 40; ++i){datachar[i] = i + 1;}res = buffer.Write(datachar, 40);printf("寫入資料個數:%d\n", res);res = buffer.Write(datachar, 40);printf("寫入資料個數:%d\n", res);res = buffer.Write(datachar, 40);printf("寫入資料個數:%d\n", res);res = buffer.Write(datachar, 40);printf("寫入資料個數:%d\n", res);res = buffer.Read(reschar, 100);printf("讀取資料個數:%d\n", res);for (int i = 0; i < 100; ++i){if (i % 10 == 0){printf("\n");}printf("%2d ", reschar[i]);}return 0;}
輸出結果:
寫入資料個數:40寫入資料個數:40寫入資料個數:20寫入資料個數:0讀取資料個數:100 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
來源程式來自網路資料!