需求
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;
}