Revolver源码解析之——协议对象的序列化与反序列化

1、基本原理。

序列化:将对象转化为字节序列的过程。

反序列化:从字节序列中恢复对象的过程。

小端模式:低地址上存放低字节,在高地址上存放高字节。

大端模式:低地址上存放高字节,在高地址上存放低字节。

网络字节序采用大端模式。

参考:

[1].https://blog.csdn.net/qqliyunpeng/article/details/68484497;

[2].https://www.cnblogs.com/fuchongjundream/p/3914770.html;

[3].https://blog.csdn.net/qq_27093465/article/details/78544505;

2、实现。

.h

/*************************************************************************************
*filename:	base_bin_stream.h
*
*to do:		实现协议对象的二进制打包流对象,网络字节序模式流
*Create on: 2012-04
			2012-11 增加 =号重载、bin_to_string两个函数,主要实现对STRING的相互转换
*Author:	zerok
*check list:
*************************************************************************************/
#ifndef __BASE_BIN_STREAM_H
#define __BASE_BIN_STREAM_H

#include "revolver/base_namespace.h"
#include "revolver/base_typedef.h"
#include "revolver/base_hex_string.h"
#include <assert.h>
#include <string.h>
#include <string>

#define MAX_STREAM_STIRNG_SIZE 10485760 //10M

using namespace std;

BASE_NAMESPACE_BEGIN_DECL

//1K的默认大小
#define DEFAULT_PACKET_SIZE	 1024

#define ENCODE(data, type) \
	int32_t type_size = sizeof(type);\
	resize(used_ + type_size);\
	uint8_t* pos = (uint8_t*)&data;\
	if(big_endian) \
	{\
		::memcpy(wptr_, pos, type_size);\
	}\
	else\
	{\
		pos = pos + type_size - 1;\
		for(int32_t i = 0; i < type_size; ++i)\
		{\
			wptr_[i] = *pos;\
			-- pos;\
		}\
	}\
	used_ += type_size;\
	wptr_ += type_size;\


#define DECODE(data, type)\
	int32_t type_size = sizeof(type);\
	if(used_ >= rsize_ + type_size)\
	{\
		uint8_t* pos = (uint8_t*)&data;\
		if(big_endian)\
		{\
			::memcpy(pos ,rptr_, type_size);\
		}\
		else\
		{\
			pos = pos + type_size - 1;\
			for(int32_t i = 0; i < type_size; ++i)\
			{\
				*pos = rptr_[i];\
				 -- pos; \
			}\
		}\
		rsize_ += type_size;\
		rptr_ += type_size;\
	}\
	else \
	{\
		memset(&data, 0x00, type_size);\
	}

template<class Elem, uint32_t CAPACITY>
class BinStream_T
{
public:
	typedef BinStream_T<Elem, CAPACITY> _MyBint;

	BinStream_T();
	virtual ~BinStream_T();

	//复位
	void		rewind(bool reset = false);
	void		resize(uint32_t new_size);
	//瘦身,只有在闲置状态下调用
	void		reduce();
	void		set_used_size(uint32_t used)
	{
		used_ = used;
    }

	const Elem* get_data_ptr() const
	{
		return data_;
    }

	uint8_t*	get_wptr()
	{
		return wptr_;
    }

	const uint8_t* get_rptr() const
	{
		return rptr_;
    }

	//获取缓冲区的大小
	uint32_t	size() const
	{
		return size_;
    }
	//获取数据填充区的大小
	uint32_t	data_size() const
	{
		return used_;
    }

	_MyBint& operator<<(bool val)
	{
		ENCODE(val, bool);
		return (*this);
    }

	_MyBint& operator>>(bool& val)
	{
		DECODE(val, bool);
		return (*this);
    }

	_MyBint& operator<<(int8_t val)
	{
		ENCODE(val, int8_t);
		return (*this);
    }

	_MyBint& operator>>(int8_t& val)
	{
		DECODE(val, int8_t);
		return (*this);
    }

	_MyBint& operator<<(int16_t val)
	{
		ENCODE(val, int16_t);
		return (*this);
    }

	_MyBint& operator>>(int16_t& val)
	{
		DECODE(val, int16_t);
		return (*this);
    }

	_MyBint& operator<<(int32_t val)
	{
		ENCODE(val, int32_t);
		return (*this);
    }
	_MyBint& operator>>(int32_t& val)
	{
		DECODE(val, int32_t);
		return (*this);
    }

	_MyBint& operator<<(int64_t val)
	{
		ENCODE(val, int64_t);
		return (*this);
    }

	_MyBint& operator>>(int64_t& val)
	{
		DECODE(val, int64_t);
		return (*this);
    }

	_MyBint& operator<<(uint8_t val)
	{
		ENCODE(val, uint8_t);
		return (*this);
    }

	_MyBint& operator>>(uint8_t& val)
	{
		DECODE(val, uint8_t);
		return (*this);
    }

	_MyBint& operator<<(uint16_t val)
	{
		ENCODE(val, uint16_t);
		return (*this);
    }

	_MyBint& operator>>(uint16_t& val)
	{
		DECODE(val, uint16_t);
		return (*this);
    }

	_MyBint& operator<<(uint32_t val)
	{
		ENCODE(val, uint32_t);
		return (*this);
    }

	_MyBint& operator>>(uint32_t& val)
	{
		DECODE(val, uint32_t);
		return (*this);
    }

	_MyBint& operator<<(uint64_t val)
	{
		ENCODE(val, uint64_t);
		return (*this);
    }

	_MyBint& operator>>(uint64_t& val)
	{
		DECODE(val, uint64_t);
		return (*this);
    }
	
	_MyBint& operator<<(const string& val)
	{
		uint32_t val_size = val.size();
		ENCODE(val_size, uint32_t);
	
		resize(used_ + val_size);
		::memcpy((void *)wptr_, (const void *)val.data(), (size_t)val_size);
		wptr_ += val_size;
		used_ += val_size;

		return (*this);
    }

	_MyBint& operator>>(string& val)
	{
		uint32_t val_size = 0;
		DECODE(val_size, uint32_t);

		if(val_size + rsize_ > used_) //防止越界访问
		{			
			throw 0;
		}
		else if(val_size == 0)
		{
			val = "";
		}
		else 
		{
			val.assign((char *)rptr_, val_size);

			rptr_ += val_size;
			rsize_ += val_size;
		}

		return (*this);
    }

	_MyBint& operator=(const _MyBint& strm)
	{
		resize(strm.size_);
		::memcpy(data_, strm.data_, strm.size_);
		used_ = strm.used_;
		rsize_ = strm.rsize_;
		rptr_ = data_ + rsize_;
		wptr_ = data_ + used_;

		return *this;
	}

	_MyBint& operator=(const string& data)
	{
		rewind(true);
		resize(data.size());
		set_used_size(data.size());

		::memcpy(get_wptr(), data.data(), data.size());
		wptr_ = data_ + used_;

		return *this;
	}

	void push_data(const uint8_t *data, uint32_t data_len)
	{
		ENCODE(data_len, uint32_t);

		resize(used_ + data_len);
		::memcpy((void *)wptr_, (const void *)data, (size_t)data_len);
		wptr_ += data_len;
		used_ += data_len;
	}

	uint32_t pop_data(uint8_t *data, uint32_t data_len)
	{
		uint32_t ret = 0;
		DECODE(ret, uint32_t);

		if (ret > data_len || ret > used_ - rsize_)
			throw 0;

		memcpy(data, get_rptr(), ret);
		rptr_ += ret;
		rsize_ += ret;

		return ret;
	}

	void bin_to_string(string& data)
	{
		data.clear();
		data.assign((char*)rptr_, data_size());
	}

	const string to_string()
	{
		string text;
		return bin2asc((uint8_t *)data_, used_);
	}

protected:
	Elem*		data_;	//数据缓冲区
	uint8_t*	rptr_;	//当前读位置指针
	uint8_t*	wptr_;	//当前写位置指针

	size_t		size_;	//最大缓冲区尺寸
	size_t		used_;	//已经使用的缓冲区尺寸
	size_t		rsize_;	//读取的字节数

	bool		big_endian;//系统字节序标志
};

typedef BinStream_T<uint8_t, DEFAULT_PACKET_SIZE> BinStream;

BASE_NAMESPACE_END_DECL

#include "base_bin_stream.inl"

#endif

/************************************************************************************/



.inl

#include "revolver/base_bin_stream.h"
#include <stdlib.h>

BASE_NAMESPACE_BEGIN_DECL

template<class Elem, uint32_t CAPACITY>
BinStream_T<Elem, CAPACITY>::BinStream_T()
{
	//判断字节序
	union 
	{
		uint16_t	s16;
		uint8_t		s8[2];
	}un;
	un.s16 = 0x010a;
	big_endian = (un.s8[0] == 0x01);

	//开辟Binstream对象缓冲区
	size_ = sizeof(Elem) * CAPACITY;
	data_ = (Elem *)malloc(size_);

	rptr_ = (uint8_t *)data_;
	wptr_ = (uint8_t *)data_;

	used_ = 0;
	rsize_ = 0;
}

template<class Elem, uint32_t CAPACITY>
BinStream_T<Elem, CAPACITY>::~BinStream_T()
{
	if(data_ != NULL)
	{
		free(data_);
		data_ = NULL;

		rptr_ = NULL;
		wptr_ = NULL;

		size_ = 0;

		used_ = 0;
		rsize_ = 0;
	}
} 

template<class Elem, uint32_t CAPACITY>
void BinStream_T<Elem, CAPACITY>::rewind(bool reset)
{
	if(reset)
	{
		wptr_ = (uint8_t *)data_;
		used_ = 0;
	}

	rptr_ = (uint8_t *)data_;
	rsize_ = 0;
}
//重新设置内存大小
template<class Elem, uint32_t CAPACITY>
void BinStream_T<Elem, CAPACITY>::resize(uint32_t new_size)
{
	if(new_size <= size_)
		return ;

	uint32_t alloc_size  = size_;
	while(new_size >= alloc_size)
		alloc_size *= 2;

	data_ = (Elem *)realloc(data_, alloc_size);
	size_ = alloc_size;
	wptr_ = (uint8_t *)data_ + used_;
	rptr_ = (uint8_t *)data_ + 	rsize_;
}
//复位内存占用
template<class Elem, uint32_t CAPACITY>
void BinStream_T<Elem, CAPACITY>::reduce()
{
	if(size_ > 4096) //4KB
	{
		free(data_);

		size_ = sizeof(Elem) * CAPACITY;
		data_ = (Elem *)malloc(size_);

		rptr_ = (uint8_t *)data_;
		wptr_ = (uint8_t *)data_;

		used_ = 0;
		rsize_ = 0;
	}
}

BASE_NAMESPACE_END_DECL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值