当前,应用最广泛的C语言json解析库当属cJSON,但是,使用cJSON读json进行序列化和反序列化,需要根据key一个一个进行处理,会导致代码冗余,逻辑性不强。
java语言可以用gson,能够直接将json映射成对象。而在C语言中,也有CSON,不过感觉CSON有点不太好用,虽然使用的时候效率高,但是定义的时候挺麻烦的,所以想自己造个轮子,看看能不能解决。
三种想法,
1,在定义结构体的时候,同时定义结构体的描述,也就是CSON,不考虑了。
2,自动化脚本,将.h文件中特定的结构体批量自动生成 描述,或者是在运行的时候,调用类似nm命令去获取结构体描述,其实也是类似CSON,只不过想自动化实现,难度不大,但是限制太多。
3,使用宏的方法,在定义结构体的时候定义一个字符串,通过解析字符串来解析结构体。现在想做的就是方法3。
/*批量转换结构体字节序.
不支持结构体嵌套定义。
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include <arpa/inet.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
#define STR_MSG(A) #A
#define TP_ST(MSG, NM) const char *NM = STR_MSG(MSG); MSG;
/**********msg struct define***************/
#define MSG_HEAD typedef struct \
{\
u32 length;\
u16 msg_type;\
u16 trans_id;\
u8 version;\
u8 reserv1;\
u16 reserv2;\
} __attribute__ ((__packed__))tag_msg_head_t;
TP_ST(MSG_HEAD, MSG_HEAD_STR);
u16 htons(u16 input)
{
u16 ret = 0;
ret = (input & 0xff) << 8;
ret += (input & 0xff00) >> 8;
return ret;
}
u32 htonl(u32 input)
{
u32 ret = 0;
ret = (input & 0xff) << 24;
ret += (input & 0xff00) << 8;
ret += (input & 0xff0000) >> 8;
ret += (input & 0xff000000) >> 24;
return ret;
}
int convert_msg(char *pdata, const char *pmsg_str)
{
char *pch;
printf("%s\n", pmsg_str);
pch = strstr(pmsg_str, "{");
if(pch == NULL)
return 0;
pch++;
while(pch != NULL && *pch != '\0'&& *pch != '}')
{
while(*pch == ' ' || *pch == '\t')pch++;
if (strncmp(pch, "u32", 3) == 0)
{
*(u32*)pdata = htonl(*(u32 *)pdata);
pdata += sizeof(u32);
pch += 3;
}
else if(strncmp(pch, "u16", 3) == 0)
{
*(u16*)pdata = htons(*(u16 *)pdata);
pdata += sizeof(u16);
pch += 3;
}
else if(strncmp(pch, "u8", 2) == 0)
{
pdata++;
pch += 2;
}
pch = strstr(pch, ";");
pch++;
}
return 0;
}
int main()
{
tag_msg_head_t val;
val.length = 0x123456;
val.msg_type = 0xabcd;
val.version = 1;
convert_msg((char*)&val, MSG_HEAD_STR);
printf("val.length=0x%0x\n", val.length);
printf("val.msg_type=0x%0x\n", val.msg_type);
printf("val.version=0x%0x\n", val.version);
}