C++模板元实现序列化

一、简介

利用C++模板元编程实现简单的序列化和反序列化,支持的数据类型如下:

  1. 基本类型:char、short、int、long、float、double以及无符号整数;
  2. 字符串:std::string;
  3. 向量:std::vector,支持vector<基本类型>和vector<字符串>;
  4. 支持嵌套;

二、实现

// 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;
}

猜你喜欢

转载自blog.csdn.net/kpengk/article/details/118070178