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 ...
随机推荐
- 6.css3定位--position
⑴Static默认值,没有定位. ⑵Absolute绝对定位.后面的元素会补上原来偏移的位置. ⑶Relative相对定位.后面的元素不会补上原来偏移的位置. ⑷Fixed绝对定位.相对于浏览器窗口固 ...
- 伟大的GIL
GIL 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代 ...
- GUI学习之十二——QTextEdit学习总结
在学习了QFrame和QAbstractScrollArea两个父类后,接下来是一个重头戏:QTextEdit. 一.QTextEdit特性 QTextEdit是一个高级的WYSIWYG(What Y ...
- systemd 相关及服务启动失败原因
1 查看启用的units systemctl list-unit-files | grep enabled 2 查看指定服务的日志 按服务单元过滤 journalctl -u j 查看j.serv ...
- linear_func
''' class torch.nn.Linear(in_features,out_features,bias = True )[来源] 参数: in_features - 每个输入样本的大小out_ ...
- Flutter-常用插件庫
alibaba/flutter_boost:路由 install_plugin 2.0.0#app下载更新插件 audio_recorder: any #录音.播放 flutter_sound: ^1 ...
- 配置apache运行cgi程序
配置apache运行cgi程序 文章目录 [隐藏] ScriptAlias目录的CGI ScriptAlias目录以外的CGI 配置apache运行cgi程序可分为两种情况,一是ScriptAlias ...
- 过采样算法之SMOTE
SMOTE(Synthetic Minority Oversampling Technique),合成少数类过采样技术.它是基于随机过采样算法的一种改进方案,由于随机过采样采取简单复制样本的策略来增加 ...
- SpringCloud学习系列-SpringCloud
SpringCloud是什么? SpringCloud=分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶 SpringCloud,基于SpringBoot提供了一 ...
- LeetCode--139--单词拆分(python)
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可以重复使用字典中的单词.你可以假设字典中没有重复的 ...