Created
September 9, 2016 05:09
-
-
Save ecnelises/cdf1ffc4a9f8b88c32fa1b0826f927cc to your computer and use it in GitHub Desktop.
简易的C++二进制序列化类,模仿boost::serialization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Serialize.hpp | |
// 简易的C++二进制序列化类,模仿boost::serialization | |
// 邱超凡 2016.9.9 | |
#ifndef CPP_SERIALIZE_HPP | |
#define CPP_SERIALIZE_HPP | |
#include <fstream> | |
#include <algorithm> | |
#include <type_traits> | |
#include <cassert> | |
// 序列化写入工具,以文件流初始化 | |
// 使用方式类似于: | |
// std::ofstream out('out.file', std::ios::binary); | |
// SerializeWriter sw(out); | |
// int k = 10; | |
// sw << k; | |
class SerializeWriter { | |
public: | |
SerializeWriter(std::ofstream& file) : dest(file) {} | |
template<typename T> | |
SerializeWriter& operator << (const T& obj); | |
template<typename T> | |
SerializeWriter& operator << (T& obj); | |
template<typename T> | |
void directBinaryData(const T& obj); | |
private: | |
std::ofstream& dest; | |
}; | |
// 序列化读取工具 | |
class SerializeReader { | |
public: | |
SerializeReader(std::ifstream& file) : src(file) {} | |
template<typename T> | |
SerializeReader& operator >> (T& obj); | |
template<typename T> | |
SerializeReader& operator << (T& obj); | |
template<typename T> | |
void directBinaryData(T& obj); | |
private: | |
std::ifstream& src; | |
}; | |
// 辅助判断是否存在serialize成员函数的类 | |
// 序列化类有定义好的规则 | |
// 首先,会寻找是否有签名为`void serialize(S&, T&)`的函数,S为模版类型 | |
// 其次,会寻找要序列化的类型T是否有成员函数`void serialize(S&)` | |
// 如果二者都不存在,则会调用自带的序列化方法 | |
template<typename TestType, typename Serializer> | |
class HasSpecificSerializeFunction { | |
private: | |
template<typename U, void (U::*)(Serializer&)> | |
struct FuncMatchHelper; | |
template<typename U> | |
static char test(FuncMatchHelper<U, &U::serialize>*); | |
template<typename U> | |
static int test(...); | |
public: | |
static const bool value = sizeof(test<TestType>(0)) == sizeof(char); | |
}; | |
template<typename Serializer, typename DataType> | |
void serialize(Serializer& s, DataType& d, typename std::enable_if< | |
HasSpecificSerializeFunction<DataType, Serializer>::value | |
>::type* ph = nullptr) | |
{ | |
d.serialize(s); | |
} | |
template<typename Serializer, typename DataType> | |
void serialize(Serializer& s, const DataType& d, typename std::enable_if< | |
HasSpecificSerializeFunction<DataType, Serializer>::value | |
>::type* ph = nullptr) | |
{ | |
d.serialize(s); | |
} | |
// 自定义的序列化方法会判别参数是否是指针类型 | |
// 如果不是,就直接以二进制方式读入输出 | |
// 如果是,先判断指针是否为空,为空就输出零 | |
// 否则,输出0x0F0F0F0F,然后紧跟指针实际指向的对象 | |
template<typename DataType> | |
void serialize(SerializeReader& sr, DataType& d, | |
typename std::enable_if<!HasSpecificSerializeFunction<DataType, SerializeReader>::value>::type* ph = nullptr, | |
typename std::enable_if<std::is_pointer<DataType>::value>::type* ph2 = nullptr) | |
{ | |
int ptstatustmp; | |
sr.directBinaryData(ptstatustmp); | |
if (ptstatustmp == 0) { | |
return; | |
} else if (ptstatustmp == 0x0F0F0F0F) { | |
d = new typename std::remove_pointer<DataType>::type; | |
sr.directBinaryData(*d); | |
} else { | |
assert(0); | |
} | |
} | |
template<typename DataType> | |
void serialize(SerializeWriter& sw, const DataType& d, | |
typename std::enable_if<!HasSpecificSerializeFunction<DataType, SerializeWriter>::value>::type* ph = nullptr, | |
typename std::enable_if<std::is_pointer<DataType>::value>::type* ph2 = nullptr) | |
{ | |
if (d == nullptr) { | |
sw.directBinaryData(0); | |
} else { | |
sw.directBinaryData(0x0F0F0F0F); | |
sw.directBinaryData(*d); | |
} | |
} | |
template<typename Serializer, typename DataType> | |
void serialize(Serializer& s, DataType& d, | |
typename std::enable_if<!HasSpecificSerializeFunction<DataType, Serializer>::value>::type* ph = nullptr, | |
typename std::enable_if<!std::is_pointer<DataType>::value>::type* ph2 = nullptr) | |
{ | |
s.directBinaryData(d); | |
} | |
template<typename Serializer, typename DataType> | |
void serialize(Serializer& s, const DataType& d, | |
typename std::enable_if<!HasSpecificSerializeFunction<DataType, Serializer>::value>::type* ph = nullptr, | |
typename std::enable_if<!std::is_pointer<DataType>::value>::type* ph2 = nullptr) | |
{ | |
s.directBinaryData(d); | |
} | |
// 序列化类会自动根据serialize函数实现反序列化效果 | |
// 如果不需要反序列化,可以自由地加上const | |
template<typename T> | |
SerializeWriter& SerializeWriter::operator << (const T& obj) | |
{ | |
serialize(*this, obj); | |
return *this; | |
} | |
template<typename T> | |
SerializeWriter& SerializeWriter::operator << (T& obj) | |
{ | |
serialize(*this, obj); | |
return *this; | |
} | |
template<typename T> | |
void SerializeWriter::directBinaryData(const T& obj) | |
{ | |
dest.write(reinterpret_cast<const char*>(&obj), sizeof(T)); | |
} | |
template<typename T> | |
SerializeReader& SerializeReader::operator >> (T& obj) | |
{ | |
serialize(*this, obj); | |
return *this; | |
} | |
template<typename T> | |
SerializeReader& SerializeReader::operator << (T& obj) | |
{ | |
return (*this >> obj); | |
} | |
template<typename T> | |
void SerializeReader::directBinaryData(T& obj) | |
{ | |
char *tmp = new char[sizeof(T)]; | |
src.read(tmp, sizeof(T)); | |
std::copy(tmp, tmp + sizeof(T), reinterpret_cast<char*>(&obj)); | |
delete[] tmp; | |
} | |
#endif // CPP_SERIALIZE_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment