利用Cista实现文本行到结构体的转换
文章目录
1. Cista概况
Cista 官方介绍
|
|
简单来说,就是提供的结构体提供序列化和反序列支持,跟 Thrift | Protobuf | Arrow 等产品或工具类似。Cista也提供一定的反射能力,能够与实现类成员变量的读写。
1.1 安装
安装Cista有两种方式:
|
|
对于大型的工程,作者建议通过CMake的方式,通过submoduel的方式,链接到编译系统中去。
|
|
2. 基本使用
从官方的示例来看,其实很详细,如下是自己总结的一些用法。
2.1 遍历
|
|
如上打印输出是通过 fmt 来实现,fmt 能够很好地通过 {} 来达到占位。
type_name 来源于Stack Overflow 的问题,当然cista 中也有实现。
2.2 序列化和反序列化
|
|
2.3 反射
利用反射接口实现的宏,能够很方便的实现结构体的打印
|
|
CISTA_PRINTABLE 宏自动生成对象的 结构体String类型,与dbg配合能够很方便的Debug,减少重复代码量。
|
|
其基本的思路是通过 上述例子中提到的 reflection 接口完成的。
同列 CISTA_COMPARABLE 宏,可以生成 比较函数
|
|
3. 应用
通过如上的熟悉,我们知道了其基本用法,尝试利用Cista接口完成如下场景:
有一个明文文本文件,其格式为按照 \t 分割的域
|
|
在服务加载时,需要转为HashMap的形式,其中Key为第一个字段,Value为如下的 Struct 结构体。
|
|
随着业务的发展,可能遇到如下两个问题
- Value字段越来越多,每次有些硬编码完成类型的相关转换
- 文件越来越大,插入HashMap的时间过长,导致服务上线或故障恢复难
本文尝试解决第一个问题,第二个问题在后续的文章中体现。
3.1 接口设计
任务的核心其实是将各个字符串的域转换为结构体,设计接口上,我们可以把行转换为StringTokenizer对象保存起来,然后将各个域与Struct的域类型映射起来,用到两个技术
- 模板
- 反射
核心的代码示例如下所示
|
|
3.2 类型匹配
dump_field 的实现可以通过标准库函数提供的 is_same 来进行判断,支持一些基础的类型,暂时不支持嵌套类型(但很容易嵌套),具体实现如下
|
|
3.3 完整封装
我们抽象下接口,如下具体的实现将第0个域作为了key,value为其它域。
|
|
3.4 支持有限层级的嵌套
上述方案仅仅对基础的build-in类型及String支持,如果在 struct 中嵌套struct呢?限于笔者对Cista的了解,下面只提供一些实现的思路。
在3.2中的类型判断中,我们可以把struct归为else之类。这时,我们只需要将对应的字符串域看作一个新的需要dump 的Struct域即可,但此时需要与首层不同的分隔符切分,递归的调用ReflectionDumpField 即可。
4. 总结
本文通过利用Cista中对结构体的反射,实现了行文本到基础类型的映射,避免了业务的硬编码,减少了出错的可能,具有一定的创新性。
实现的代价为支持有限的POD类型,能够有限地扩展到嵌套struct,在dump时有if判断,可能会影响效率。
文章作者 Rayan
上次更新 2020-04-30