Skip to content

Instantly share code, notes, and snippets.

@ecnelises
Created September 9, 2016 05:09
Show Gist options
  • Save ecnelises/cdf1ffc4a9f8b88c32fa1b0826f927cc to your computer and use it in GitHub Desktop.
Save ecnelises/cdf1ffc4a9f8b88c32fa1b0826f927cc to your computer and use it in GitHub Desktop.
简易的C++二进制序列化类,模仿boost::serialization
// 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