一、简介
利用C++模板元编程实现简单的序列化和反序列化,支持的数据类型如下:
- 基本类型:char、short、int、long、float、double以及无符号整数;
- 字符串:std::string;
- 向量:std::vector,支持vector<基本类型>和vector<字符串>;
- 支持嵌套;
二、实现
// serialization.h
/* 序列化说明
* 1.包组成:
* -----------------------
* | 包长度 | 数据 |
* |-----------------------|
* | int | char[] |
* -----------------------
* 2.数据组成
* -----------------------------------------------------------------------------------
* | 类型 | 符号表示 | 排列方式,其中len(x)的类型为unsigned short |
* |-----------------------------------------------------------------------------------|
* | 普通类型 | T | T |
* | 字符串 | S | len(S) + S |
* | 普通向量 | V<T> | len(V) + T1 + T2 + T3 + ... + Tn |
* | 字符串向量 | V<S> | len(V) + len(S1) + S1 + len(S2) + S2 + ... + len(Sn) + Sn |
* -----------------------------------------------------------------------------------
*/
#ifndef SERIALLIZATION_H_
#define SERIALLIZATION_H_
#include <string>
#include <vector>
#define DEFINE_PACK(...) \
public: \
size_t packSize() const { \
return sizeof(int) + Ser::all_size(__VA_ARGS__); \
} \
std::string toString() const{ \
const size_t& _count = sizeof(int) + Ser::all_size(__VA_ARGS__); \
std::string _result; \
_result.reserve(_count); \
Ser::push(_result, (int)_count); \
Ser::pack(_result, __VA_ARGS__); \
return _result; \
} \
bool fromString(const char* const _buf, const int & _len) { \
if (_len < sizeof(int)) return false; \
const char* _ptr = _buf; \
int _count = 0; \
Ser::take(_count, _ptr); \
if (_count != _len) return false; \
Ser::unpack(_ptr, __VA_ARGS__); \
return true; \
} \
bool fromString(const std::string _buf) { \
return fromString(_buf.data(), _buf.size()); \
}
namespace Ser {
template<bool cond, typename T>
class IF {
public:
static inline size_t _val_size(const T& val) {
return val.packSize();
}
static inline void _push(std::string& buf, const T& val) {
buf.append(val.toString());
}
static inline void _take(T& val, const char*& buf) {
const int count = *(reinterpret_cast<const int*>(buf));
val.fromString(buf, count);
buf += count;
}
};
template<typename T>
class IF<false, T> {
public:
static inline size_t _val_size(const T& val) {
return sizeof(T);
}
static inline void _push(std::string& buf, const T& val) {
const char* ptr = reinterpret_cast<const char*>(&val);
buf.append(ptr, sizeof(T));
}
static inline void _take(T& val, const char*& buf) {
val = *(reinterpret_cast<const T*>(buf));
buf += sizeof(T);
}
};
/* 计算单个元素序列化后的长度 */
template<typename T>
inline size_t valsize(const T& val) {
return IF<std::is_class_v<T>, T>::_val_size(val);
}
template<>
inline size_t valsize<std::string>(const std::string& val) {
return sizeof(unsigned short) + val.size();
}
template<typename T>
size_t valsize(const std::vector<T>& val) {
size_t len = sizeof(unsigned short);
for (size_t i = 0; i < val.size(); ++i) {
len += valsize(val[i]);
}
return len;
}
/* 序列化单个元素 */
template<typename T>
inline void push(std::string& buf, const T& val) {
IF<std::is_class_v<T>, T>::_push(buf, val);
}
template<>
inline void push<std::string>(std::string& buf, const std::string& val) {
const unsigned short& len = static_cast<unsigned short>(val.size());
buf.append(reinterpret_cast<const char*>(&len), sizeof(unsigned short));
buf.append(val);
}
template<typename T>
void push(std::string& buf, const std::vector<T>& val) {
const unsigned short& len = static_cast<unsigned short>(val.size());
push(buf, len);
for (size_t i = 0; i < len; ++i) {
push(buf, val[i]);
}
}
/* 反序列化单个元素 */
template<typename T>
inline void take(T& val, const char*& buf) {
IF<std::is_class_v<T>, T>::_take(val, buf);
}
template<>
inline void take<std::string>(std::string& val, const char*& buf) {
unsigned short len = 0;
take(len, buf);
val.clear();
val.append(buf, len);
buf += len;
}
template<typename T>
void take(std::vector<T>& val, const char*& buf) {
unsigned short len = 0;
take(len, buf);
val.resize(len);
for (int i = 0; i < len; ++i) {
take(val[i], buf);
}
}
/* 计算不定参序列化后总长度 */
template<typename T>
size_t all_size(const T& elem) {
return valsize(elem);
}
template<typename T, typename... Args>
size_t all_size(const T& elem, const Args&... args) {
return valsize(elem) + all_size(args...);
}
/* 不定参序列化 */
template<typename T>
void pack(std::string& buf, const T& elem) {
push(buf, elem);
}
template<typename T, typename... Args>
void pack(std::string& buf, const T& elem, const Args&... args) {
push(buf, elem);
pack(buf, args...);
}
/* 不定参反序列化 */
template<typename T>
void unpack(const char*& buf, T& elem) {
take(elem, buf);
}
template<typename T, typename... Args>
void unpack(const char*& buf, T& elem, Args&... args) {
take(elem, buf);
unpack(buf, args...);
}
}
#endif /* SERIALLIZATION_H_ */
三、使用示例
3.1基本使用
#include "serialization.h"
class Message {
public:
std::string type; //类型
std::string msg; //内容
int priority; //优先级
long long id; //序号
std::string srcip; //IP
public:
DEFINE_PACK(type, msg, priority, id, srcip)
};
int main()
{
Message m = { "type", "test", 2, 56, "192.168.0.2" };
//序列化
std::string buf = m.toString();
//反序列化
Message res;
res.fromString(buf);
return 0;
}
3.2嵌套使用
#include "serialization.h"
class A {
public:
int a;
std::vector<double> b;
DEFINE_PACK(a, b)
};
class B {
A t1;
float t2;
DEFINE_PACK(t1, t2)
};
int main()
{
B m;
//序列化
std::string buf = m.toString();
//反序列化
B res;
res.fromString(buf);
return 0;
}