C++中的通用结构定义,及相应的序列化、反序列化接口
一个通用的C++结构定义如下:
typedef struct tagCommonStruct {
long len;
void* buff;
}CommonStruct_st;
此接口对应的普通序列化、反序列化接口如下:
unsigned char* EncodeCommonStruct(const CommonStruct_st& CommonSt)
{
//分配内存
unsigned char* strBuff = (unsigned char*)malloc(CALC_COMMON_ST_LEN(&CommonSt));
if (NULL == strBuff)
{
return NULL;
} //填充内容
*(long*)strBuff = CommonSt.len;
if (CommonSt.len > ) {
memcpy(strBuff + sizeof(long), CommonSt.buff, CommonSt.len);
} return strBuff;
} BOOL DecodeCommonStruct(const unsigned char* strBuff, long len, CommonStruct_st& CommonSt)
{
long st_len;
if (NULL == strBuff)
{
return FALSE;
} //获取到当前长度
st_len = *(const long*)strBuff;
//校验BUFF内容合法性
if (st_len + sizeof(long) > len) {
return FALSE;
}
CommonSt.len = st_len;
CommonSt.buff = (void*)malloc(st_len);
memcpy(CommonSt.buff, strBuff + sizeof(long), st_len);
return TRUE;
} void EncodeCommonStruct_S(const CommonStruct_st& CommonSt, std::string& strOut)
{
//分配内存
strOut.resize(CALC_COMMON_ST_LEN(&CommonSt)); //填充内容
*(long*)&(strOut[]) = CommonSt.len;
if (CommonSt.len > ) {
memcpy(&(strOut[]) + sizeof(long), CommonSt.buff, CommonSt.len);
} return;
} BOOL DecodeCommonStruct_S(const unsigned char* strBuff, long len, CommonStruct_st& pCommonSt, std::string& strInnBuff)
{
long st_len;
if (NULL == strBuff)
{
return FALSE;
} //获取到当前长度
st_len = *(const long*)strBuff;
//校验BUFF内容合法性
if (st_len + sizeof(long) > len) {
return FALSE;
}
pCommonSt.len = st_len;
strInnBuff.resize(st_len);
//pCommonSt.buff = (void*)malloc(st_len);
pCommonSt.buff = &strInnBuff[];
memcpy(pCommonSt.buff, strBuff + sizeof(long), st_len);
return TRUE;
}
支持批量操作的序列化、反序列化接口:
#define MAX_COMMON_STRUCT_PARAM_NUMBER (16) void EncodeCommonStructV(std::string& strOut, int nStNum, ...)
{
int index = ;
int nBufLen;
unsigned char* strTemp;
//最多允许16个
va_list arg_ptr;
CommonStruct_st CommStructStArray[MAX_COMMON_STRUCT_PARAM_NUMBER]; //
if (nStNum > MAX_COMMON_STRUCT_PARAM_NUMBER) {
return;
} //依次取出相应的结构、指针位置
nBufLen = ;
va_start(arg_ptr, nStNum);
for(index = ; index < nStNum; index ++){
CommStructStArray[index].len = va_arg(arg_ptr, int);
CommStructStArray[index].buff = va_arg(arg_ptr, void*);
nBufLen += CALC_COMMON_ST_LEN(&CommStructStArray[index]);
}
va_end(arg_ptr); //计算总字符长度
strOut.resize(nBufLen, '\0');
strTemp = (unsigned char*)&strOut[]; //依次格式化
std::string strTmpBuf;
for(index = ; index < nStNum; index ++){
#if 0
EncodeCommonStruct_S(CommStructStArray[index], strTmpBuf);
memcpy(strTemp, strTmpBuf.c_str(), CALC_COMMON_ST_LEN(&CommStructStArray[index]);
#else
*(long*)strTemp = CommStructStArray[index].len;
if (CommStructStArray[index].len > ) {
memcpy(strTemp + sizeof(long), CommStructStArray[index].buff, CommStructStArray[index].len);
}
#endif strTemp += CALC_COMMON_ST_LEN(&CommStructStArray[index]);
}
}
BOOL DecodeCommonStructV(const unsigned char* strBuff, long len, ...)
{
va_list arg_ptr;
long leave_len, st_len;
CommonStruct_st *pstCommonStruct;
const unsigned char* strTemp;
if (NULL == strBuff)
{
return FALSE;
} leave_len = len;
strTemp = strBuff;
va_start(arg_ptr, len);
while(leave_len > ){
pstCommonStruct = va_arg(arg_ptr, CommonStruct_st *); //允许BUFF中的内容更长,但只取前面一部分
if (NULL == pstCommonStruct){
break;
} //获取到当前长度
st_len = *(const long*)strTemp;
//校验BUFF内容合法性
if (st_len + sizeof(long) > leave_len) {
return FALSE;
} //填充一块结构体的内容
pstCommonStruct->len = st_len;
memcpy(pstCommonStruct->buff, strTemp + sizeof(long), st_len); //偏移位置
strTemp += st_len + sizeof(long);
leave_len -= st_len + sizeof(long);
}
va_end(arg_ptr); return TRUE;
}
V2版本的 EncodeCommonStruct,不再限制传入参数的最多个数
void EncodeCommonStructV2(std::string& strOut, int nStNum, ...)
{
int index = ;
int nBufLen;
va_list arg_ptr;
unsigned char* strTemp;
CommonStruct_st stCommStruct; //依次取出相应的结构、指针位置
nBufLen = ;
va_start(arg_ptr, nStNum);
for(index = ; index < nStNum; index ++){
stCommStruct.len = va_arg(arg_ptr, int);
stCommStruct.buff = va_arg(arg_ptr, void*);
nBufLen += CALC_COMMON_ST_LEN(&stCommStruct);
}
va_end(arg_ptr); //计算总字符长度
strOut.resize(nBufLen, '\0');
strTemp = (unsigned char*)&strOut[]; //依次格式化
std::string strTmpBuf;
va_start(arg_ptr, nStNum);
for(index = ; index < nStNum; index ++){
stCommStruct.len = va_arg(arg_ptr, int);
stCommStruct.buff = va_arg(arg_ptr, void*);
*(long*)strTemp = stCommStruct.len;
if (stCommStruct.len > ) {
memcpy(strTemp + sizeof(long), stCommStruct.buff, stCommStruct.len);
} strTemp += CALC_COMMON_ST_LEN(&stCommStruct);
}
va_end(arg_ptr);
}
V2版本的 DecodeCommonStruct,不再限制传入参数的最多个数
BOOL DecodeCommonStructV2(const unsigned char* strBuff, std::string& strInnBuff, long len, ...)
{
va_list arg_ptr;
long leave_len, st_len, all_st_len;
CommonStruct_st *pstCommonStruct;
const unsigned char* strTemp;
unsigned char* strDest;
if (NULL == strBuff)
{
return FALSE;
} //计算strBuff中总共需要多少内存来存放
all_st_len = ;
leave_len = len;
strTemp = strBuff;
while (leave_len > ){
//获取到当前长度
st_len = *(const long*)strTemp;
//校验BUFF内容合法性
if (st_len + sizeof(long) > leave_len) {
return FALSE;
}
//每个都用\0隔开吧
all_st_len += st_len + ; strTemp += st_len + sizeof(long);
leave_len -= st_len + sizeof(long);
} //分配内存
strInnBuff.resize(all_st_len, '\0');
strDest = (unsigned char*)&strInnBuff[]; strTemp = strBuff;
leave_len = len;
va_start(arg_ptr, len);
while(leave_len > ){
pstCommonStruct = va_arg(arg_ptr, CommonStruct_st *); //允许BUFF中的内容更长,但只取前面一部分
if (NULL == pstCommonStruct){
break;
} //获取到当前长度
st_len = *(const long*)strTemp; //填充一块结构体的内容
pstCommonStruct->len = st_len;
pstCommonStruct->buff = strDest;
//拷贝至缓冲区中
memcpy(strDest, strTemp + sizeof(long), st_len); //偏移位置
strTemp += st_len + sizeof(long);
leave_len -= st_len + sizeof(long);
strDest += st_len + ;
}
va_end(arg_ptr); return TRUE;
}
C++中的通用结构定义,及相应的序列化、反序列化接口的更多相关文章
- ArcGIS中的坐标系统定义与投影转换【转】
ArcGIS中的坐标系统定义与投影转换 坐标系统是GIS数据重要的数学基础,用于表示地理要素.图像和观测结果的参照系统,坐标系统的定义能够保证地理数据在软件中正确的显示其位置.方向和距离,缺少坐标系统 ...
- 【转】+【举例】ArcGIS中的坐标系统定义与投影转换
背景知识: UTM (Universal Transverse Mercator)坐标系是由美国军方在1947提出的.虽然我们仍然将其看作与"高斯-克吕格"相似的坐标系统,但实际上 ...
- ArcGIS中的坐标系定义与转换 (转载)
原文:ArcGIS中的坐标系定义与转换 (转载) 1.基准面概念: GIS中的坐标系定义由基准面和地图投影两组参数确定,而基准面的定义则由特定椭球体及其对应的转换参数确定,因此欲正确定义GIS系统坐 ...
- C++中的一些定义
PS: 这篇博客用来记录一些一般的C++书中草草掠过的一些概念. 或者一些不太容易理解的概念的详细解释. 欢迎新手进入,欢迎高手指正! Orz . 引用: 为对象起了另外一个名字, 引用类型引用(re ...
- [C/C++]在头文件中使用static定义变量意味着什么
文章出处:http://www.cnblogs.com/zplutor/ 看到有一位同学在头文件中这么写: static const wchar_t* g_str1 = - static const ...
- switch的case中不能做定义
switch的case中不能做定义 只能给语句 error: a label can only be part of a statement and a declaration is not a st ...
- iOS 静态库中使用宏定义区分iPhone模拟器与真机---备用
问题描述 一般项目中,可以使用宏定义来判断模拟器还是真机,这无疑是有效的. #if TARGET_IPHONE_SIMULATOR #define SIMULATOR 1 #elif TARGET_O ...
- [转载]C++中声明与定义的区别
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...
- (转载)php的类中可以不定义成员变量,直接在构造方法中使用并赋值吗?
(转载)http://s.yanghao.org/program/viewdetail.php?i=184313 php的类中可以不定义成员变量,直接在构造方法中使用并赋值吗? class block ...
随机推荐
- java中的数据类型,基本数据类型及其包装类型
java中的8大基本类型及其包装类型 1,int--->Integer 2,byte--->Byte 3,short--->Short 4,long--->Long 5,cha ...
- WindowsForms使用Telerik Reporting
新建一个WindowsForms窗体项目 然后拖动ReportViewer这个控件到WindowsForms的窗体中 如上图所示,用来呈现报表的控件,这个控件可以打印报表,转换报表这类的功能 接下来我 ...
- Apache Allow 命令
用于设置哪些客户端可以访问 Apache,格式如下: Allow from [All /全域名/部分域名/IP 地址/网络地址/CIDR 地址] All:表示全部客户端 全域名:表示域名对应的客户端, ...
- STM32程序编写或调试犯过的错误
1.宏定义后加了分号: eg: define NOKEY_PRES 0; (❌) define NOKEY_PRES 0 (✔) 2.
- 020-VMware虚拟机作为OpenStack计算节点,上面的虚拟机无法启动问题解决
问题描述: VMware虚拟机作为OpenStack计算节点,如果安装的操作系统是CentOS7.3,则在此计算节点放置的虚拟机无法正常启动,报如下错误: 在创建计算节点时,为了能让 KVM 能创 ...
- Codeforces 907 矩阵编号不相邻构造 团操作状压DFS
A. #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #de ...
- 真正解决iframe高度自适应问题
1.前言 解决iframe高度自适应问题有两种方法1.pym2.手动设置iframe的高度 本文主要是总结第二种实现方式,因为第一种pym.js插件我没用懂 如果使用iframe时,遇到以下的需求: ...
- Python网络爬虫数据解析的三种方式
request实现数据爬取的流程: 指定url 基于request发起请求 获取响应的数据 数据解析 持久化存储 1.正则解析: 常用的正则回顾:https://www.cnblogs.com/wqz ...
- CSS颜色和长度单位
颜色 如果我们相给页面设置颜色可以采用多种方法进行设置: 一.命名颜色 假设在设置页面的颜色时觉得一部分很小的颜色集中就足够了,就可以直接给定颜色的名称.CSS称这些有名称的颜色为命名颜色. 命名颜色 ...
- 不同地区Android开发者使用哪些设备测试APP?
我们的团队密切关注着移动世界的趋势,以便可以提供所有有关变化的最紧密和最重要的信息.春天恰好是对app进行新一轮测试并检查其与不同Android设备兼容性如何的最佳时机.下面让我们一起来看看全世界范围 ...