分析buttonrpc中的序列化
源码提供了StreamBuffer
类,该类继承自vector<char>
,用来存储数据。
// 此处省略实现...
class StreamBuffer : public vector<char>
{
};
并提供了Serializer
类,用来序列化数据。
// 此处省略部分实现...
class Serializer
{
public:
enum ByteOrder {
BigEndian,
LittleEndian
};
void byte_orser(char* in, int len);
template<typename T>
void output_type(T& t);
template<typename T>
void input_type(T t);
template<typename T>
Serializer &operator >> (T& i){
output_type(i);
return *this;
}
template<typename T>
Serializer &operator << (T i){
input_type(i);
return *this;
}
private:
int m_byteorder;
StreamBuffer m_iodevice;
};
其中,成员变量m_byteorder
定义了大小端模式,成员函数byte_orser(char* in, int len)
进行大小端转换。
好奇:byte_orser
函数名是不是写错了,应该是byte_order
吧?
inline void Serializer::byte_orser(char* in, int len)
{
if (m_byteorder == BigEndian)
{
reverse(in, in+len);
}
}
类中提供了流入函数operator << (T i)
和流出函数operator >> (T& i)
,具体实现由私有成员函数
input_type
和output_type
提供。流入操作实现如下:
好奇:operator << (T i)函数应该定义为operator << (const T &i)吧?
// 1、定义泛化版本
template<typename T>
inline void Serializer::input_type(T t)
{
int len = sizeof(T);
char* d = new char[len];
const char* p = reinterpret_cast<const char*>(&t);
memcpy(d, p, len);
byte_orser(d, len);
m_iodevice.input(d, len);
delete [] d;
}
// 2、定义特化版本:针对string类型进行特化处理
template<>
inline void Serializer::input_type(std::string in)
{
// 先存入字符串长度
uint16_t len = in.size();
char* p = reinterpret_cast< char*>(&len);
byte_orser(p, sizeof(uint16_t));
m_iodevice.input(p, sizeof(uint16_t));
// 存入字符串
if (len == 0) return;
char* d = new char[len];
memcpy(d, in.c_str(), len);
m_iodevice.input(d, len);
delete [] d;
}
// 3、定义特化版本:针对char *类型数据,转换为string类型进行处理
template<>
inline void Serializer::input_type(const char* in)
{
input_type<std::string>(std::string(in));
}
流出操作实现如下:
template<typename T>
inline void Serializer::output_type(T& t)
{
int len = sizeof(T);
char* d = new char[len];
if (!m_iodevice.is_eof()){
memcpy(d, m_iodevice.current(), len);
m_iodevice.offset(len);
byte_orser(d, len);
t = *reinterpret_cast<T*>(&d[0]);
}
delete [] d;
}
template<>
inline void Serializer::output_type(std::string& in)
{
int marklen = sizeof(uint16_t);
char* d = new char[marklen];
memcpy(d, m_iodevice.current(), marklen);
byte_orser(d, marklen);
int len = *reinterpret_cast<uint16_t*>(&d[0]);
m_iodevice.offset(marklen);
delete [] d;
if (len == 0) return;
in.insert(in.begin(), m_iodevice.current(), m_iodevice.current() + len);
m_iodevice.offset(len);
}