源码赏析: 数据结构转换工具 configor (一)
2023-12-14 19:28:16
一、configor
先贴地址 configor,先看configor的特性:
- Header-only & STL-like
- Custom type conversion & serialization
- Complete Unicode support
- ASCII & Wide-character support
说白了,这个工具用于自定义类型的转换和序列化/反序列化。目前作者已经实现了任何自定义数据类型转换为流式数据,并可将流式数据转换为json,按照作者的plan,或许会增加ini、xml等格式转换。
二、使用代码示例
struct User
{
std::string name;
int age;
// bind custom type to configor
CONFIGOR_BIND(json::value, User, REQUIRED(name), OPTIONAL(age))
};
// User -> json
json::value j = User{"John", 18};
// json -> User
User u = json::object{{"name", "John"}, {"age", 18}};
// User -> string
std::string str = json::dump(User{"John", 18});
// string -> User
User u = json::parse("{\"name\": \"John\", \"age\": 18}");
// User -> stream
std::cout << json::wrap(User{"John", 18});
// stream -> User
User u;
std::cin >> json::wrap(u);
三、珠玉撷取
到不至于说这个工具非常强大,同类型的开源项目还有一些,如xpack
、msgpack
,这两个开源项目我们再后面会分享。不过,在框架设计和代码实现上,configor
绝对是顶级的,值得好好学习的。精读高级武学功法,勤奋精进,有助于我们彻底打开任督二脉,在c++编码世界里笑傲江湖。
我们关注自定义结构里面这样一个宏:
CONFIGOR_BIND(json::value, User, REQUIRED(name), OPTIONAL(age))
CONFIGOR_BIND
宏函数定义如下:
// Bind custom type to configor value
// e.g.
// CONFIGOR_BIND(json, myclass, REQUIRED(field1), REQUIRED(field2, "field2 name"))
// CONFIGOR_BIND(json, myclass, OPTIONAL(field1), OPTIONAL(field2, "field2 name"))
#define CONFIGOR_BIND(value_type, custom_type, ...) \
friend void to_value(value_type& c, const custom_type& v) \
{ \
__CONFIGOR_EXPAND(__CONFIGOR_PASTE(__CONFIGOR_COMBINE_PASTE1, __CONFIGOR_TO_CONF_CALL_OVERLOAD, __VA_ARGS__)) \
} \
friend void from_value(const value_type& c, custom_type& v) \
{ \
__CONFIGOR_EXPAND( \
__CONFIGOR_PASTE(__CONFIGOR_COMBINE_PASTE1, __CONFIGOR_FROM_CONF_CALL_OVERLOAD, __VA_ARGS__)) \
}
粗略一看,实际上就是实现了to_value
和from_value
实现 value_type
与 自定义类型 custom_type
之间的转换(序列化与反序列化)。
#define __CONFIGOR_EXPAND(x) x
#define __CONFIGOR_PASTE(parse1, func, ...) \
__CONFIGOR_EXPAND(__CONFIGOR_GET_ARG_MAX50( \
__VA_ARGS__, __CONFIGOR_PASTE50, __CONFIGOR_PASTE49, __CONFIGOR_PASTE48, __CONFIGOR_PASTE47, \
__CONFIGOR_PASTE46, __CONFIGOR_PASTE45, __CONFIGOR_PASTE44, __CONFIGOR_PASTE43, __CONFIGOR_PASTE42, \
__CONFIGOR_PASTE41, __CONFIGOR_PASTE40, __CONFIGOR_PASTE39, __CONFIGOR_PASTE38, __CONFIGOR_PASTE37, \
__CONFIGOR_PASTE36, __CONFIGOR_PASTE35, __CONFIGOR_PASTE34, __CONFIGOR_PASTE33, __CONFIGOR_PASTE32, \
__CONFIGOR_PASTE31, __CONFIGOR_PASTE30, __CONFIGOR_PASTE29, __CONFIGOR_PASTE28, __CONFIGOR_PASTE27, \
__CONFIGOR_PASTE26, __CONFIGOR_PASTE25, __CONFIGOR_PASTE24, __CONFIGOR_PASTE23, __CONFIGOR_PASTE22, \
__CONFIGOR_PASTE21, __CONFIGOR_PASTE20, __CONFIGOR_PASTE19, __CONFIGOR_PASTE18, __CONFIGOR_PASTE17, \
__CONFIGOR_PASTE16, __CONFIGOR_PASTE15, __CONFIGOR_PASTE14, __CONFIGOR_PASTE13, __CONFIGOR_PASTE12, \
__CONFIGOR_PASTE11, __CONFIGOR_PASTE10, __CONFIGOR_PASTE9, __CONFIGOR_PASTE8, __CONFIGOR_PASTE7, \
__CONFIGOR_PASTE6, __CONFIGOR_PASTE5, __CONFIGOR_PASTE4, __CONFIGOR_PASTE3, __CONFIGOR_PASTE2, \
parse1)(parse1, func, __VA_ARGS__))
真吓人啊,别怕。我们心里要始终坚持一点,宏千变万化,本质也是字符串的替换。
#define __CONFIGOR_GET_ARG_MAX50(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, \
_37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, ARG, ...) \
ARG
#define __CONFIGOR_COUNT_ARGS_MAX50(...) \
__CONFIGOR_EXPAND(__CONFIGOR_GET_ARG_MAX50(__VA_ARGS__, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, \
36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
这是一个宏参数计数器,用于统计传入参数的个数。
先下班,后面再续上~~😂
文章来源:https://blog.csdn.net/weixin_39568531/article/details/134991602
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!