实现一组buffer以便使用

内存的使用是c++中最频繁的,记录一下,方便以后使用。

由于时间原因,未经过太仔细的测试。仅供参考。

头文件:

#include <Windows.h>


#pragma pack(push,1) //开始定义数据包, 采用字节对齐方式
/*----------------------包头---------------------*/
typedef struct tagPACKAGEHEAD
{
    BYTE Version;
    WORD Command;
    WORD nDataLen;//包体的长度
}PACKAGE_HEAD;
#pragma pack(pop) //结束定义数据包, 恢复原来对齐方式


class InterLock
{
public:
    void Lock()
    {
        while (true == InterlockedExchange((LONG*)&m_bLockRec, true))
        {
            Sleep(0);
        }
    }


    void Unlock()
    {
        InterlockedExchange((LONG*)&m_bLockRec, false);
    }


private:
    bool m_bLockRec;
};


class MutexImpl
{
public:
    MutexImpl(){::InitializeCriticalSection(&m_oMutex);}
    ~MutexImpl(){::DeleteCriticalSection(&m_oMutex);}
public:
    void Lock()
    {
        ::EnterCriticalSection(&m_oMutex);
    }
    void Unlock()
    {
        ::LeaveCriticalSection(&m_oMutex);
    }
private:
    CRITICAL_SECTION m_oMutex;
};


class CDataBufferPool
{
public:
    CDataBufferPool() : m_pBuff(0),m_nSize(0),m_nOffset(0),m_PacketHeadLen(0)
    {};
    ~CDataBufferPool()
    {}


public:
    bool InitBuffer(unsigned int iMaxLen, int ipaglen);
    BOOL AddBuff( char *pBuff, int nLen );    
    int GetFullPacket( char *Buf, int& nLen );
protected:
    int GetFreeSize();
private:
    char* m_pBuff;
    unsigned int m_nSize;
    unsigned int m_nOffset;


    unsigned int m_PacketHeadLen;
    MutexImpl m_cs;
};


bool CDataBufferPool::InitBuffer(unsigned int iMaxLen, int ipaglen)
{
    m_nSize = iMaxLen;
    m_nOffset = 0;
    m_pBuff = (char*)malloc(m_nSize);
    m_PacketHeadLen = ipaglen;
    if (0 != m_pBuff)
    {
        return true;
    }
    return false;
}


int CDataBufferPool::GetFreeSize()
{
    return m_nSize-m_nOffset;
}


/*****************************************************************************
Description:添加数据到缓存
Input:pBuff[in]-待添加的数据;nLen[in]-待添加数据长度
Return: 如果当前缓冲区没有足够的空间存放pBuff则返回FALSE;否则返回TRUE。
******************************************************************************/
BOOL CDataBufferPool::AddBuff( char *pBuff, int nLen )
{
    m_cs.Lock();///临界区锁


    if ( nLen <= 0 )
    {
        m_cs.Unlock();
        return FALSE;
    }


    if ( nLen <= GetFreeSize() )///判断剩余空间是否足够存放nLen长的数据
    {
        memcpy(m_pBuff + m_nOffset, pBuff, nLen);
        m_nOffset += nLen;
    }
    else///若不够则扩充原有的空间
    { 
        m_nSize = m_nSize+m_nSize;
        char *pnew_buffer = 0;
        if (0 != m_pBuff)
        {
            pnew_buffer = (char*)realloc(m_pBuff,m_nSize);
        }
        else
        {
            pnew_buffer = (char*)malloc(m_nSize);
        }


        if (0 == pnew_buffer)
        {
            return false;
        }
        
        memcpy(m_pBuff + m_nOffset, pBuff, nLen);
        m_nOffset += nLen;
        return true;


        //
        //char *p = m_pBuff;
        //m_nSize += nLen*2;//每次增长2*nLen
        //m_pBuff = new char[m_nSize];
        //memcpy(m_pBuff,p,m_nOffset);
        //delete []p;
        //memcpy(m_pBuff + m_nOffset, pBuff, nLen);
        //m_nOffset += nLen;
        //m_cs.Unlock();
        //return FALSE;
    }


    m_cs.Unlock();
    return TRUE;
}






/*****************************************************************************
Description:获取一个完整的包
Input:Buf[out]-获取到的数据;nLen[out]-获取到的数据长度
Return: 1、当前缓冲区不够一个包头的数据 2、当前缓冲区不够一个包体的数据
******************************************************************************/


int CDataBufferPool::GetFullPacket( char *Buf, int& nLen )
{
    m_cs.Lock();


    if ( m_nOffset < m_PacketHeadLen )//当前缓冲区不够一个包头的数据
    {
        m_cs.Unlock();
        return 1;
    }
    PACKAGE_HEAD *p = (PACKAGE_HEAD *)m_pBuff;
    if( (m_nOffset-m_PacketHeadLen) < (int)p->nDataLen )//当前缓冲区不够一个包体的数据
    {
        m_cs.Unlock();
        return 2;
    }
    //判断包的合法性
    /* int IsIntegrallity = ValidatePackIntegrality(p);
    if( IsIntegrallity != 0 )
    {
    m_cs.Unlock();
    return IsIntegrallity;
    }
    */
    nLen = m_PacketHeadLen+p->nDataLen;
    memcpy( Buf, m_pBuff, nLen );
    m_nOffset -= nLen;
    memcpy( m_pBuff, m_pBuff+nLen, m_nOffset );


    m_cs.Unlock();
    return 0;
}




//
class CCircularBufferPool
{
public:
    CCircularBufferPool() : m_pBuffer(0), m_iBufSize(0), m_iHeadPos(0), m_iTailPos(0), m_PacketHeadLen(0),m_iOldBufferSize(0)
    {};
    ~CCircularBufferPool(){}


public:
    bool InitBuffer(unsigned int iMaxLen, int ipaglen);
    BOOL AddBuff(char *pBuff, int nLen);
    int GetFullPacket( char *Buf, int& nLen );


protected:
    void GetData(char *pData, int len, bool Delete);
    bool IsOverFlowCondition(int ilen);
    bool BufferResize(int ilen);
    bool IsIndexOverFlow(int nLen);
    unsigned int GetValidCount();
private:
    char *m_pBuffer;
    unsigned int m_iBufSize;
    unsigned int m_iHeadPos;
    unsigned int m_iTailPos;
    unsigned int m_PacketHeadLen;
    unsigned int m_iOldBufferSize;


    MutexImpl m_cs;
};


bool CCircularBufferPool::InitBuffer(unsigned int iMaxLen, int ipaglen)
{
    m_iBufSize = iMaxLen;
    m_iOldBufferSize = m_iBufSize;
    m_iHeadPos = 0;
    m_iTailPos = 0;
    m_pBuffer = (char*)malloc(m_iBufSize);
    m_PacketHeadLen = ipaglen;
    if (0 != m_pBuffer)
    {
        return true;
    }
    return false;
}


bool CCircularBufferPool::IsOverFlowCondition(int ilen)
{
    if (m_iTailPos >= m_iHeadPos)
        return (ilen > (m_iBufSize - (m_iTailPos-m_iHeadPos)));
    else if (m_iTailPos < m_iHeadPos)
    {
        return m_iHeadPos - m_iTailPos;
    }
}


bool CCircularBufferPool::BufferResize(int ilen)
{
    m_cs.Lock();
    m_iBufSize = m_iBufSize+m_iBufSize+ilen;
    char *pnew_buffer = 0;
    if (0 != m_pBuffer)
    {
        pnew_buffer = (char*)realloc(m_pBuffer,m_iBufSize);
    }
    else
    {
        pnew_buffer = (char*)malloc(m_iBufSize);
    }


    if (0 == pnew_buffer)
    {
        m_cs.Unlock();
        return false;
    }


    memcpy(m_pBuffer+m_iOldBufferSize, m_pBuffer, m_iTailPos);
    m_iTailPos = m_iOldBufferSize+m_iTailPos;
    m_iOldBufferSize = m_iBufSize;
    m_cs.Unlock();
    return true;
}


bool CCircularBufferPool::IsIndexOverFlow(int nLen)
{
    return m_iTailPos+nLen > m_iBufSize;
}


unsigned int CCircularBufferPool::GetValidCount()
{
    if (m_iTailPos >= m_iHeadPos)
    {
        return m_iTailPos - m_iHeadPos;
    }
    else
    {
        return m_iBufSize -(m_iHeadPos-m_iTailPos);
    }
}


BOOL CCircularBufferPool::AddBuff(char *pBuff, int nLen)
{
    if( nLen <= 0 ) 
        return 1;


    m_cs.Lock();
    while (IsOverFlowCondition(nLen))///判断缓冲区剩余空间是否够存放len长的数据
    {
        BufferResize(nLen);///若不够,则扩充缓冲区.
    }


    if (IsIndexOverFlow(nLen))///判断"尾"指针的位置.
    {
        int FirstCopyLen = m_iBufSize-m_iTailPos;
        int SecondCopyLen = nLen - FirstCopyLen;
        CopyMemory(m_pBuffer+m_iTailPos, pBuff, FirstCopyLen);
        if (SecondCopyLen)
        {
            CopyMemory(m_pBuffer, pBuff+FirstCopyLen, SecondCopyLen);
            m_iTailPos = SecondCopyLen;
        }
        else 
            m_iTailPos = 0;
    }
    else
    {
        CopyMemory(m_pBuffer+m_iTailPos, pBuff, nLen);
        m_iTailPos += nLen;
    }


    m_cs.Unlock();
    return 0;




}




void CCircularBufferPool::GetData(char *pData, int len, bool Delete)
{
    if (len < m_iBufSize-m_iHeadPos)
    {
        CopyMemory(pData, m_pBuffer+m_iHeadPos, len);
        if(Delete==true)
            m_iHeadPos += len;
    }
    else
    {
        int fc, sc;
        fc = m_iBufSize-m_iHeadPos;
        sc = len - fc;
        CopyMemory(pData, m_pBuffer+m_iHeadPos, fc);
        if (sc) CopyMemory(pData+fc, m_pBuffer, sc);
        if(Delete==true)
            m_iHeadPos = sc;
        if(m_iHeadPos >= m_iBufSize)
            m_iHeadPos = 0;


    }
}


//
//进行自定义包的解析
//
int CCircularBufferPool::GetFullPacket( char *Buf, int &nLen )
{
    m_cs.Lock();
    if( GetValidCount() < m_PacketHeadLen )//当前缓冲区不够一个包头的数据
    {
        m_cs.Unlock();
        return 1;
    }


    GetData(Buf,m_PacketHeadLen,false);
    PACKAGE_HEAD *p = (PACKAGE_HEAD *)Buf;
    if( (GetValidCount()-m_PacketHeadLen) < (int)p->nDataLen )//当前缓冲区不够一个包体的数据
    {
        m_cs.Unlock();
        return 2;
    }


    //判断包的合法性
    //int IsIntegrallity = ValidatePackIntegrality(p);
    //if( IsIntegrallity != 0 )
    //{
    //    m_cs.Unlock();
    //    return IsIntegrallity;
    //}


    GetData(Buf,m_PacketHeadLen+p->nDataLen,true);
    nLen = m_PacketHeadLen+p->nDataLen;


    m_cs.Unlock();




    return 0;
}




template<class BUFFER>
class TplBuffer
{
public:
    bool InitBuffer(unsigned int iMaxLen, int ipaglen);
    BOOL AddBuff( char *pBuff, int nLen );    
    int GetFullPacket( char *Buf, int& nLen );
private:
    BUFFER m_buffer;
};


template<class BUFFER>
bool TplBuffer<BUFFER>::InitBuffer(unsigned int iMaxLen, int ipaglen)
{
    return m_buffer.InitBuffer(iMaxLen, ipaglen);
}


template<class BUFFER>
BOOL TplBuffer<BUFFER>::AddBuff( char *pBuff, int nLen )
{
    return m_buffer.AddBuff(pBuff, nLen);
}


template<class BUFFER>
int TplBuffer<BUFFER>::GetFullPacket( char *Buf, int& nLen )
{
    return m_buffer.GetFullPacket(Buf, nLen);
}

例子:

     TplBuffer<CDataBufferPool> tplDataBuff;
    TplBuffer<CCircularBufferPool> tplCirBuff;


    int isize = sizeof(PACKAGE_HEAD);
    tplDataBuff.InitBuffer(1024*1024, sizeof(PACKAGE_HEAD));
    tplCirBuff.InitBuffer(1024*1024, sizeof(PACKAGE_HEAD));


    PACKAGE_HEAD pheader1, pheader2;
    std::string strtest1("012345"), strTest2("0567890");
    pheader1.Version = 10;
    pheader1.Command = 100;
    pheader1.nDataLen = strtest1.length();


    pheader2.Version = 20;
    pheader2.Command = 200;
    pheader2.nDataLen = strTest2.length();


    tplDataBuff.AddBuff((char*)(&pheader1), isize);
    tplDataBuff.AddBuff((char*)strtest1.c_str(), strtest1.length());


    tplCirBuff.AddBuff((char*)(&pheader2), isize);
    tplCirBuff.AddBuff((char*)strTest2.c_str(), strTest2.length());


    char*pch1 = new char[512], *pch2 = new char[512];
    memset(pch1, 0, 512);
    memset(pch2, 0, 512);
    int ireallen1 = isize + strtest1.length();
    int ireallen2 = isize + strTest2.length();
    int iret1 = tplDataBuff.GetFullPacket(pch1,ireallen1);
    int iret2 = tplCirBuff.GetFullPacket(pch2, ireallen2);


    PACKAGE_HEAD *ph1 = (PACKAGE_HEAD*)pch1;
    PACKAGE_HEAD *ph2 = (PACKAGE_HEAD*)pch2;
    std::string strph1(pch1 + isize);
    std::string strph2(pch2 + isize);

 

也可以在这里看。

http://download.csdn.net/detail/flyingleo1981/6703163

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值