nlib
exi/serializer/serializer.cpp

簡単なXMLシリアライザを定義してオブジェクトをシリアライズします。

boostのserializationライブラリのように、関数テンプレートを作成して& 演算子を用いてシリアライズしたいデータメンバを指定することでクラスオブジェクトのシリアライズが可能です。

template<class Archive>
void Coordinate::serialize(Archive& ar) {
ar & latitude;
ar & longitude;
}

バイナリXMLを用いた場合、シリアライズした結果は、テキストのXMLよりはコンパクトで、バイナリとはいえXMLなのでテキストのXMLに変換すれば読めるようになるという利点があります。

サンプルのシリアライザには以下のような制約があります。

以下がサンプルのソースコードになります。

#include <map>
#include <string>
#include <vector>
#include "./def_serializer.h"
using nlib_ns::exi::ExiAllocator;
struct Coordinate {
float latitude;
float longitude;
template <class Archive>
void serialize(Archive& ar); // NOLINT
Coordinate(float arg_latitude, float arg_longitude) {
latitude = arg_latitude;
longitude = arg_longitude;
}
Coordinate() : latitude(0.f), longitude(0.f) {}
};
class CityInfo {
StdString name;
StdString url;
StdString governor;
int population;
Coordinate coordinate;
public:
template <class Archive>
void serialize(Archive& ar); // NOLINT
CityInfo(const ExiChar* arg_name, const ExiChar* arg_url, const ExiChar* arg_governor,
int arg_population, const Coordinate& arg_coordinate)
: name(arg_name),
url(arg_url),
governor(arg_governor),
population(arg_population),
coordinate(arg_coordinate) {}
CityInfo() : population(0) {}
void Print() {
ConsoleOutputStream out_;
TextWriter out;
out.Init();
out.Open(&out_);
out.WriteFormat("name: %s\n", M(name.c_str()));
out.WriteFormat("\turl: %s\n", M(url.c_str()));
out.WriteFormat("\tgovernor: %s\n", M(governor.c_str()));
out.WriteFormat("\tpopulation: %d\n", population);
out.WriteFormat("\tcoord: (%f, %f)\n\n", coordinate.latitude, coordinate.longitude);
}
};
template <class Archive>
void Coordinate::serialize(Archive& ar) { // NOLINT
ar& latitude;
ar& longitude;
}
template <class Archive>
void CityInfo::serialize(Archive& ar) { // NOLINT
// You can describe serialization and deserialization of the data by operator &().
// Archive is instantiated by SimpleSerializer in serialization,
// by SimpleDeserializer in deserialization.
ar& name;
ar& url;
ar& governor;
ar& population;
ar& coordinate;
}
typedef std::map<StdString, CityInfo> CityDB;
const int BUF_SIZE = 1024 * 128;
unsigned char g_Buf[BUF_SIZE];
struct AllocFinalizer {
~AllocFinalizer() {
ExiAllocator::Finalize();
}
};
bool SampleExec() {
ReallocOutputStream os;
{
SimpleSerializer ser(&os);
CityDB sendData;
CityInfo tokyo(N("Tokyo"), N("http://www.metro.tokyo.jp/"), N("Shintaro Ishihara"),
13186835, Coordinate(35.6894875f, 139.6917064f));
CityInfo kyoto(N("Kyoto"), N("http://www.pref.kyoto.jp/"), N("Keiji Yamada"), 2633795,
Coordinate(35.0212466f, 135.7555968f));
sendData[N("Tokyo")] = tokyo;
sendData[N("Kyoto")] = kyoto;
// Serializes sendData into binary XML.
ser << sendData;
if (!ser.IsSuccess()) {
return false;
}
nlib_printf("%" PRIuS " bytes written\n\n", os.Pos());
}
// You have to reset the allocator after parsing.
ExiAllocator::Reset();
ReallocOutputStream::UniquePtrType data;
size_t data_size = os.Release(&data);
MemoryInputStream is(&data[0], data_size);
{
// Restore the CityDB object from the serialized data.
// You can also restore the object at a distant place.
SimpleDeserializer deser(&is);
CityDB receiveData;
// Restore receiveData by deserializing the binary XML for it.
deser >> receiveData;
if (!deser.IsSuccess()) {
return false;
}
CityDB::iterator it;
for (it = receiveData.begin(); it != receiveData.end(); ++it) {
it->second.Print();
}
}
return true;
}
bool SampleMain(int, char**) {
if (ExiAllocator::Init(g_Buf, BUF_SIZE) != 0) {
nlib_printf("ExiAllocator::Initialize failed\n");
return false;
}
bool rval = SampleExec();
ExiAllocator::Finalize();
return rval;
}
NLIB_MAINFUNC