cpp内存二进制数据流读写类、支持不同字节序

需求

win、vs、cpp开发环境,读写内存二进制数据流、支持不同字节序

代码

memorybinarystream.h

#ifndef _MEMORY_BINARY_STREAM_H_
#define _MEMORY_BINARY_STREAM_H_

#if defined _MSC_VER && _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <memory.h>
#include <fstream>

#ifndef int8
#define int8 char
#endif

#ifndef uint8
#define uint8 unsigned char
#endif

#ifndef int16
#define int16 short
#endif

#ifndef uint16
#define uint16 unsigned short
#endif

#ifndef int32
#define int32 int
#endif

#ifndef uint32
#define uint32 unsigned int
#endif

#ifndef xint64
#define xint64 __int64
#endif

#ifndef uint64
#define uint64 unsigned __int64
#endif

#ifndef NULL
#define NULL (0)
#endif

#define InitBufferSize (1024)
#define DefaultAlignSize (4)
#define DefaultFillValue (0)

/** @brief 类型强转宏*/
#define REINTERPRET_CAST(to_type,x) (*(reinterpret_cast<to_type*>(&x)))

//#define AsUint16(a) REINTERPRET_CAST(uint16,a)
//#define AsUint32(a) REINTERPRET_CAST(uint32,a)
//#define AsUint64(a) REINTERPRET_CAST(uint64,a)
#define AsUint16(a) a
#define AsUint32(a) a
#define AsUint64(a) a

//float用SWAP32处理,double用SWAP64处理
/** @brief 位交换宏*/
#define SWAP16(a) ( ((AsUint16(a)&0xFF00)>>8)\
                  | ((AsUint16(a)&0x00FF)<<8) )
#define SWAP32(a) ( ((AsUint32(a)&0xFF000000)>>24)\
                  | ((AsUint32(a)&0x00FF0000)>>8)\
                  | ((AsUint32(a)&0x0000FF00)<<8)\
                  | ((AsUint32(a)&0x000000FF)<<24) )
#define SWAP64(a) ( ((AsUint64(a)&0xFF00000000000000)>>56)\
                  | ((AsUint64(a)&0x00FF000000000000)>>40)\
                  | ((AsUint64(a)&0x0000FF0000000000)>>24)\
                  | ((AsUint64(a)&0x000000FF00000000)>>8)\
                  | ((AsUint64(a)&0x00000000FF000000)<<8)\
                  | ((AsUint64(a)&0x0000000000FF0000)<<24)\
                  | ((AsUint64(a)&0x000000000000FF00)<<40)\
                  | ((AsUint64(a)&0x00000000000000FF)<<56) )

class MemoryBinaryStream
{
public:
    enum EnumEndianType
    {
        EnumUnkownEndian = 0,   /**< 未知字节序*/
        EnumBigEndian,          /**< 大端,eg:MIPS、ARM,JAVA、NET*/
        EnumLittleEndian        /**< 小端,eg:x86*/
    };

    enum EnumMemoryBinaryStreamState{
        EMBSS_Unkown = 0,       /**< 未知状态*/
        EMBSS_OK,               /**< 正常*/
        EMBSS_MemoryOut,        /**< 内存不足*/
        EMBSS_ReadOut,          /**< 读数据时超界*/
        EMBSS_ReadFileError,    /**< 读文件出错,数据无效*/
        EMBSS_WriteFileError,   /**< 写文件出错*/
    };
public:
    MemoryBinaryStream();
    ~MemoryBinaryStream()
    {
        Clear();
    }
public:
    bool LoadFile(const std::string &file_name);

    bool SaveFile(const std::string &file_name);
private:
    inline bool TestRead(const int size_prepare_to_read)
    {
        return pos_ + size_prepare_to_read <= data_size_; //必须在有效数据内读
    }
public:
    inline int GetIntAlign(const int i, const unsigned int align_size = DefaultAlignSize)
    {
        if (align_size == 0)
        {
            return i;
        }
        int remainder = i % align_size;//求余
        if (remainder == 0)
        {
            return i;
        }
        int fill_size = align_size - remainder;//填充长度
        return (i + fill_size);
    }
    //读对齐
    bool ReadAlign(const int align_size = DefaultAlignSize);
    bool ReadAddPos(const int offset_size);
    inline bool Read(uint8 *ptr, const int arr_size)
    {
        if (TestRead(arr_size))
        {
            memcpy(ptr, data_ + pos_, arr_size);//此处小对象可以根据arr_size大小判断为赋值,不调用memcpy
            pos_ += arr_size;
            return true;
        }
        pos_ = data_size_;  //读超界,将指针放在有效数据尾部
        state_ = EMBSS_ReadOut; //读超界
        return false;
    }

    inline bool Read(std::string &str, const int max_length)
    {
        if (max_length + 1 <= 512)
        {
            char ctemp[512];
            memset(ctemp, 0, max_length + 1);
            if (Read(reinterpret_cast<uint8*>(ctemp), max_length))
            {
                str = ctemp;
                return true;
            }
            else
            {
                str = "";
                return false;
            }
        }
        else
        {
            char *ptr = new char[max_length + 1];//频繁申请释放是不合适的,有空改为栈内数组
            memset(ptr, 0, max_length + 1);
            if (Read(reinterpret_cast<uint8*>(ptr), max_length))
            {
                str = ptr;
                delete[] ptr;
                ptr = NULL;
                return true;
            }
            else
            {
                str = "";
                delete[] ptr;
                ptr = NULL;
                return false;
            }
        }
    }

    template<class T>
    inline bool Read(T &t)
    {
        return Read(reinterpret_cast<T*>(&t), sizeof(T));
    }

    inline bool Read(uint16 &t)
    {
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(uint16));
        if (flag_swap_)
        {
            t = SWAP16(t);
        }
        return b;
    }

    inline bool Read(uint32 &t)
    {
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(uint32));
        if (flag_swap_)
        {
            t = SWAP32(t);
        }
        return b;
    }

    inline bool Read(uint64 &t)
    {
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(uint64));
        if (flag_swap_)
        {
            t = SWAP64(t);
        }
        return b;
    }

    inline bool Read(int16 &t)
    {
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(int16));
        if (flag_swap_)
        {
            t = SWAP16(t);
        }
        return b;
    }

    inline bool Read(int32 &t)
    {
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(int32));
        if (flag_swap_)
        {
            t = SWAP32(t);
        }
        return b;
    }

    inline bool Read(xint64 &t)
    {
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(xint64));
        if (flag_swap_)
        {
            t = SWAP64(t);
        }
        return b;
    }

    inline bool Read(float &f)
    {
        uint32 t = 0;
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(float));
        if (flag_swap_)
        {
            t = SWAP32(t);
        }
        f = REINTERPRET_CAST(float, t);
        return b;
    }

    inline bool Read(double &f)
    {
        uint64 t = 0;
        bool b = Read(reinterpret_cast<uint8*>(&t), sizeof(double));
        if (flag_swap_)
        {
            t = SWAP64(t);
        }
        f = REINTERPRET_CAST(double, t);
        return b;
    }
private:
    inline bool TestWrite(const int size_prepare_to_write)
    {
        return pos_ + size_prepare_to_write <= tatal_size_; //可以在全数据范围内写
    }
public:
    //写对齐
    bool WriteAlign(const int align_size = DefaultAlignSize, const uint8 fill_value = DefaultFillValue);

    inline bool Write(const uint8 *ptr, const int arr_size)
    {
        bool b = TestWrite(arr_size);
        if (b == false)
        {
            b = ResetMemory(pos_ + arr_size);//如果为false,内部已设置错误状态
        }
        if (b == true)
        {
            memcpy(data_ + pos_, ptr, arr_size);
            pos_ += arr_size;
            return set_data_size(pos_);
        }
        return b;
    }

    inline bool Write(const std::string &str)
    {
        const char *ptr = str.c_str();
        int arr_size = str.length();
        return Write(reinterpret_cast<const uint8*>(ptr), arr_size);
    }

    template<class T>
    inline bool Write(const T &t)
    {
        return Write(reinterpret_cast<const uint8*>(&t), sizeof(T));
    }

    inline bool Write(uint16 t)
    {
        if (flag_swap_)
        {
            t = SWAP16(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(uint16));
    }

    inline bool Write(uint32 t)
    {
        if (flag_swap_)
        {
            t = SWAP32(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(uint32));
    }

    inline bool Write(uint64 t)
    {
        if (flag_swap_)
        {
            t = SWAP64(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(uint64));
    }

    inline bool Write(int16 t)
    {
        if (flag_swap_)
        {
            t = SWAP16(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(int16));
    }

    inline bool Write(int32 t)
    {
        if (flag_swap_)
        {
            t = SWAP32(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(int32));
    }

    inline bool Write(xint64 t)
    {
        if (flag_swap_)
        {
            t = SWAP64(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(xint64));
    }

    inline bool Write(float f)
    {
        uint32 t = REINTERPRET_CAST(uint32, f);
        if (flag_swap_)
        {
            t = SWAP32(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(uint32));
    }

    inline bool Write(double f)
    {
        uint64 t = REINTERPRET_CAST(uint64, f);
        if (flag_swap_)
        {
            t = SWAP64(t);
        }
        return Write(reinterpret_cast<uint8*>(&t), sizeof(uint64));
    }
public:
    inline void Clear()
    {
        if (data_)
        {
            delete[] data_;
            data_ = NULL;
        }
        tatal_size_ = 0;
        pos_ = 0;
        data_size_ = 0;
        state_ = EMBSS_OK;
    }
    inline void Init()
    {
        Clear();
        set_tatal_size(InitBufferSize);
    }
private:
    //内存不够时,每次倍增内存,直至能容纳size_temp个字节
    bool ResetMemory(const int size_temp);
public:
    inline uint8 *data()const
    {
        return data_;
    }

    inline int tatal_size()const
    {
        return tatal_size_;
    }

    bool set_tatal_size(const int size_temp);

    inline int data_size()const
    {
        return data_size_;
    }

    inline bool set_data_size(const int size_temp)
    {
        //设置有效数据大小
        if (size_temp < 0)
        {
            return false;
        }
        if (size_temp <= tatal_size_)
        {
            if (data_size_ < size_temp)
            {
                data_size_ = size_temp;//回写时,当前位置并不是有效数据尾部
            }
            return true;
        }
        //大于最大内存,不处理
        return false;//此处不自动增长缓存,test write时负责加缓存
    }

    inline int pos()const
    {
        return pos_;
    }

    bool set_pos(const int pos_temp);

    EnumMemoryBinaryStreamState state()const
    {
        return state_;
    }
private:
    uint8 *data_;       /**< 内存数据数组*/
    int tatal_size_;    /**< 内存数据大小,单位byte*/
    int data_size_;     /**< 有效数据大小,单位byte,eg:写数据时,只写了一部分*/
    int pos_;           /**< 当前读写指针的绝对位置,从data_的0位置开始,单位byte*/
    EnumMemoryBinaryStreamState state_; /**< 内存数据流的读写状态,非EMBSS_OK都是错误的*/

    //大端小端、大尾小尾、字节交换相关
public:
    EnumEndianType endian_type()
    {
        return endian_type_;
    }

    /** @brief 设置二进制数据流的字节对齐类型
    @param [in] t 字节对齐类型,大端或小端
    */
    void set_endian_type(const EnumEndianType t);
private:
    EnumEndianType current_system_endian_type_; /**< 当前系统的大端小端标志*/
    EnumEndianType endian_type_;    /**< 数据流的大端小端标志*/
    //bool flag_set_endian_;          /**< 是否已设置大端小端,一个对象只能设置一次,中途不可修改*/
    bool flag_swap_;                /**< 是否需要交换字节序*/
};

#endif //_MEMORY_BINARY_STREAM_H_

memorybinarystream.cpp代码

#include "common/language/memorybinarystream.h"

MemoryBinaryStream::MemoryBinaryStream()
    ://flag_set_endian_(false),
    endian_type_(EnumUnkownEndian),
    data_(NULL), tatal_size_(0), pos_(0), data_size_(0),
    flag_swap_(false),
    state_(EMBSS_OK)
{
    int i = 1;
    if ((reinterpret_cast<uint8 *>(&i))[0] == 1)
    {
        current_system_endian_type_ = EnumLittleEndian;
    }
    else
    {
        current_system_endian_type_ = EnumBigEndian;
    }
    set_endian_type(EnumBigEndian);//默认写大端数据
    Init();
}

bool MemoryBinaryStream::LoadFile(const std::string &file_name)
{
    std::ifstream file;
    file.open(file_name.c_str(), std::ios::binary);
    bool b = file.is_open();
    if (b)
    {
        uint64 file_size = file.seekg(0, std::ios::end).tellg();
        file.seekg(0);
        bool b = set_tatal_size(int(file_size));
        if (b)
        {
            file.read((char*)data_, file_size);
            data_size_ = int(file_size);
            pos_ = 0;
        }
    }
    else
    {
        state_ = EMBSS_ReadFileError;
    }
    file.close();
    return b;
}

bool MemoryBinaryStream::SaveFile(const std::string &file_name)
{
    std::ofstream file;
    /*bool b = */file.open(file_name.c_str(), std::ios::binary | std::ios::trunc);
    //if (b)
    //{
        /*uint64 write_size = */file.write((char*)data(), data_size());
        //if (write_size != data_size())
        //{
        //    b = false;
        //    state_ = EMBSS_WriteFileError;
        //}
    //}
    //else
    //{
    //    state_ = EMBSS_WriteFileError;
    //}
    file.close();
    return true;
}

void MemoryBinaryStream::set_endian_type(const EnumEndianType t)
{
    //if (!flag_set_endian_                       //当前对象未设置大端小端
    //    && t != EnumUnkownEndian)               //t为有效值
    //{
        endian_type_ = t;
        //flag_set_endian_ = true;
        //
        if (endian_type_ == current_system_endian_type_)
        {
            flag_swap_ = false;
        }
        else
        {
            flag_swap_ = true;  //字节序不同才需要交换
        }
    //}
}

bool MemoryBinaryStream::set_tatal_size(const int size_temp)
{
    if (size_temp <= tatal_size_)
    {
        return true;
    }
    uint8 *data_temp = new uint8[size_temp];
    if (data_temp != NULL)
    {
        memset(data_temp, 0, size_temp);    //初始化
        if (data_ != NULL)
        {
            memcpy(data_temp, data_, tatal_size_);   //拷贝原有数据
            delete[] data_;
        }
        data_ = data_temp;
        tatal_size_ = size_temp;
        return true;
    }
    state_ = EMBSS_MemoryOut;
    return false;
}

bool MemoryBinaryStream::ResetMemory(const int size_temp)
{
    if (size_temp < 0)  //负数约定清空内存
    {
        Clear();
        return true;
    }
    if (size_temp <= tatal_size_)//相等时标示数据尾,不能读写
    {
        return true;
    }
    int size_new = tatal_size_ * 2;//内存不够时,每次倍增内存
    while (size_new < size_temp)
    {
        size_new = size_new * 2;
    }
    return set_tatal_size(size_new);
}

bool MemoryBinaryStream::set_pos(const int pos_temp)
{
    if (pos_temp < 0)
    {
        return false;
    }
    if (pos_temp <= tatal_size_)//相等时标示数据尾,不能读写
    {
        pos_ = pos_temp;
        return true;
    }
    return false;
    //写空数据时要求可以任意移动到某位置。
    //写空数据调用此函数会返回false
    //int size_new = tatal_size_ * 2;//内存不够时,每次倍增内存
    //while (size_new < pos_temp)
    //{
    //    size_new = size_new * 2;
    //}
    //bool b = set_data_size(size_new);
    //if (b)
    //{
    //    pos_ = pos_temp;
    //    return true;
    //}
    //return false;
}

bool MemoryBinaryStream::ReadAddPos(const int offset_size){
    bool b = TestRead(offset_size);
    if (b == false)
    {
        return false;
    }
    return set_pos(pos_ + offset_size);
}

bool MemoryBinaryStream::ReadAlign(const int align_size)
{
    if (align_size == 0)
    {
        return true;
    }
    int remainder = pos_ % align_size;//求余
    if (remainder == 0)
    {
        return true;
    }
    int fill_size = align_size - remainder;//填充长度
    bool b = TestRead(fill_size);
    if (b == false)
    {
        return false;
    }
    return set_pos(pos_ + fill_size);
}

bool MemoryBinaryStream::WriteAlign(const int align_size, const uint8 fill_value)
{
    if (align_size == 0)
    {
        return true;
    }
    int remainder = pos_ % align_size;//求余
    if (remainder == 0)
    {
        return true;
    }
    int fill_size = align_size - remainder;//填充长度
    bool b = TestWrite(fill_size);
    if (b == false)
    {
        b = ResetMemory(pos_ + fill_size);//如果为false,内部已设置错误状态
    }
    if (b == true)
    {
        memset(data_ + pos_, fill_value, fill_size);
        pos_ += fill_size;
        return set_data_size(pos_);
    }
    return b;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值