c++ 消息字節流數據讀和寫

#ifndef _CELL_STREAM_HPP_
#define _CELL_STREAM_HPP_


#include <cstdint>
class CELLStream
{
public:
    //創建數據塊 (寫消息)
    CELLStream(int nSize = 1024)
    {
        _nSize = nSize;
        _pBuff = new char[_nSize];
        _bDelete = true;
    }
    //已有數據塊解析(讀消息)
    CELLStream(char* pData, int nSize = 1024, bool bDelete = false)
    {
        _nSize = nSize;
        _pBuff = pData;
        _bDelete = bDelete;
    }

    ~CELLStream()
    {
        if (_pBuff)
        {
            delete[] _pBuff;
            _pBuff = nullptr;
        }
    }

    //read
private:
    template<typename T>
    bool Read(T& n, bool isOffset = true)
    {
        //計算讀取數據的字節長度
        auto nLen = sizeof(T);
        //判斷能不能讀
        if ( _nReadPos + nLen <= _nSize)
        {
            memcpy(&n, _pBuff + _nReadPos, nLen);
            //計算已讀數據位置
            if(isOffset)
                _nReadPos += nLen;
            return true;
        }
        return false;
    }
    
public:

    /*bool canRead()
    {
        return false;
    }*/

    template<typename T>
    bool onlyRead(T& n = 0)
    {
        return Read(n, false);
    }
    int8_t ReadInt8(int8_t def = 0)
    {
        Read<int8_t>(def);
        return def;
    }
    int16_t ReadInt16(int16_t def = 0)
    {
        Read<int16_t>(def);
        return def;
    }
    int32_t ReadInt32(int32_t def = 0)
    {
        Read<int32_t>(def);
        return def;
    }
    float ReadFloat(float def = 0)
    {
        Read<float>(def);
        return def;
    }
    double ReadDouble(double def = 0)
    {
        Read<double>(def);
        return def;
    }

    template<typename T>
    bool ReadArrary(T* pData, uint32_t len)
    {
        //讀取數組的元素個數
        /*
        防止讀取數組的個數的時候能讀取數據的長度,但是裏面真實數據不能讀出來,所以爲了確保緩衝區不被破壞 暫時不偏移讀取位置的光標<_nReadPos>
        */
        int32_t len1 = 0;
        Read<int32_t>(len1, false);
        //判斷緩衝區數據能否放下
        if (len1 < len)
        {
            //計算讀取數據的數據大小
            auto nLen = sizeof(T)*len1;
                //s
                if (_nReadPos + nLen + sizeof(int32_t) <= _nSize)
                {
                    _nReadPos += sizeof(int32_t);
                    memcpy(pData, _pBuff + _nReadPos, nLen);
                    _nReadPos += nLen;
                    return len1;
                }
        }
       
        return len1;
    }
    
private:
    //write
    template<typename T>
    bool Write(T& n)
    {
        //寫入數據的大小長度
        size_t nLen = sizeof(T);
        //判斷能不能寫入
        if ( _nWritePos + nLen <= _nSize )
        {
            //將要寫入的數據 拷貝到緩衝區尾部
            memcpy(_pBuff + _nWritePos, &n, nLen);
            //計算已寫數據位置
            _nWritePos += nLen;
            return true;
        }
        return false;
    }

public:
    bool WriteInt8(int8_t n)
    {
        return Write<int8_t>(n);
    }
    bool WriteInt16(int16_t n)
    {
        return Write<int16_t>(n);
    }
    bool WriteInt32(int32_t n)
    {
        return Write<int32_t>(n);
    }
    bool WriteFloat(float n)
    {
        return Write<float>(n);
    }
    bool WriteDouble(double n)
    {
        return Write<double>(n);
    }

    /*
    數組寫入
    */
    template<typename T>
    bool WriteArray(T* pData, uint32_t len)
    {
        //計算寫入數據的大小
        //由於寫入數據的大小 讀取的時候不知道讀取的長度 故加個寫入數據大小長度一個字節頭
        auto nLen = sizeof(T)* len;
        //判斷能不能寫入
        if (_nWritePos + nLen + sizeof(uint32_t) <= _nSize)
        {
            //先寫入數組的長度
            WriteInt32(len);
            //將要寫入的數據 拷貝到緩衝區尾部
            memcpy(_pBuff + _nWritePos, pData, nLen);
            //計算數據尾部位置
            _nWritePos += nLen;
            return true;
        }
        return false;
    }
protected:
private:
    //數據緩衝區
    char* _pBuff = nullptr;
    //緩衝區總空間大小,字節長度
    int _nSize = 0;
    //寫入數據的尾部位置,已寫入數據長度
    int _nWritePos = 0;
    //已讀數據的尾部位置,已讀取的數據的長度
    int _nReadPos = 0;
    //_pBuff是外部傳入的數據塊是否應該被釋放
    bool _bDelete = true;

};

#endif
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章