serialization.h

来源:互联网 发布:nginx 图片服务器配置 编辑:程序博客网 时间:2024/05/20 17:39

本人水平有限,又不对之处请见谅。

这是一个序列化的头文件,该文件声明了多个结构体,我会从这几个结构体来逐步分析来解析这个头文件。

源码

-源码246——250行 结构体 bool_

template <bool C_> struct bool_ {    static const bool value = C_;    typedef bool value_type;};

用模版的方式定义了一个结构体。

bool_<true> a;

a.value的值为true。

bool_<false> b;

b.value的值为false。

-源码253——255行 ArchiveBase

class ArchiveBase{public:    void* getObject() { return object_; }    void setObject(void* object) { object_ = object; }private:    void* object_;};

这是flann库的文档基类,主要用于对对象进行序列化,大家将到后面看到其如何使用。
其中 void* object_; 是指向文件的指针。

-源码266——281 InputArchiive

template<typename Archive>class InputArchive : public ArchiveBase{protected:    InputArchive() {};public:    typedef bool_<true> is_loading;    typedef bool_<false> is_saving;    template<typename T>    Archive& operator& (T& val)    {        Serializer<T>::load(*static_cast<Archive*>(this),val);        return *static_cast<Archive*>(this);    }};

该类继承于ArchiveBase,如其名字InputArchive,它的主要作用是加载对象,对于一个输入的文档,所以is_loading值为true,is_saving值为false,该类重载了一个操作符&。该类也是一个基类,并不适合实例化。

-源码284——299 OutputArchive

template<typename Archive>class OutputArchive : public ArchiveBase{protected:    OutputArchive() {};public:    typedef bool_<false> is_loading;    typedef bool_<true> is_saving;    template<typename T>    Archive& operator& (const T& val)    {        Serializer<T>::save(*static_cast<Archive*>(this),val);        return *static_cast<Archive*>(this);    }};

OutputArchive继承于ArchiveBase,不同于InputArchive的是。该类是用于save的,所以is_loading.value为false,is_saving.value值为true.用法同InputArchive。

注:这两个类都直接用,一般都作为基类。

-源码303——334 SizeArchive

class SizeArchive : public OutputArchive<SizeArchive>{    size_t size_;public:    SizeArchive() : size_(0)    {    }    template<typename T>    void save(const T& val)    {        size_ += sizeof(val);    }    template<typename T>    void save_binary(T* ptr, size_t size)    {        size_ += size;    }    void reset()    {        size_ = 0;    }    size_t size()    {        return size_;    }};

我暂且称其类为尺寸文档。它比OutputArchive多了一个存储size的功能,并针对size提供了一些操作。

-源码355——396

class SaveArchive : public OutputArchive<SaveArchive>{    FILE* stream_;    bool own_stream_;public:    SaveArchive(const char* filename)    {        stream_ = fopen(filename, "w");        own_stream_ = true;    }    SaveArchive(FILE* stream) : stream_(stream), own_stream_(false)    {    }    ~SaveArchive()    {        if (own_stream_) {            fclose(stream_);        }    }    template<typename T>    void save(const T& val)    {        fwrite(&val, sizeof(val), 1, stream_);    }    template<typename T>    void save(T* const& val)    {        // don't save pointers        //fwrite(&val, sizeof(val), 1, handle_);    }    template<typename T>    void save_binary(T* ptr, size_t size)    {        fwrite(ptr, size, 1, stream_);    }};

该类SaveArchive继承与OutputArchive,它提供并实现了对对象save的接口。
成员变量:FILE * stream; 指向存储的文件
bool own_stream_;指明该文件指针是否独享
方法: save(const T& val);
将值存储到指定文件中
save_binary(T *ptr, size_t size);
存储一个数据块,首地址为ptr,大小为size个字节。

class LoadArchive : public InputArchive<LoadArchive>{    FILE* stream_;    bool own_stream_;public:    LoadArchive(const char* filename)    {        stream_ = fopen(filename, "r");        own_stream_ = true;    }    LoadArchive(FILE* stream) : stream_(stream), own_stream_(false)    {    }    ~LoadArchive()    {        if (own_stream_) {            fclose(stream_);        }    }    template<typename T>    void load(T& val)    {        size_t ret = fread(&val, sizeof(val), 1, stream_);        if (ret!=1) {            throw FLANNException("Error loading from file");        }    }    template<typename T>    void load(T*& val)    {        // don't load pointers        //fread(&val, sizeof(val), 1, handle_);    }    template<typename T>    void load_binary(T* ptr, size_t size)    {        size_t ret = fread(ptr, size, 1, stream_);        if (ret!=1) {            throw FLANNException("Error loading from file");        }    }};

原理同SaveArchive不过LoadArchive执行的是加载操作。

回过头来,我们来看一看它是如何进行序列化操作的。
大家注意到,InputArchive,OutputArchive都重载了操作符&,所以我们可称为&为序列化操作符,它们执行时分别调用了Serializer中的静态成员函数load与save,下面我们来仔细看看这Serializer结构体,如何实现这两个函数。

作者是用模版的方式实现了Serializer

大家阅读源码前一部分会发现,除了对vector,Map这两个类型的Serializer,其他类型的Serializer直接调用了Archive类中的相关函数,所以大家理解之前Archive中的相关函数,就能很好的理解。

而对应vector,Map这两种类型需要对其每个元素进行序列化,所以才与原先的有所不同,我认为仔细读代码的人都能很清楚了理解Serilizer的句法,我这就不多赘述了,我是为了帮同我一样的新手来更容易理解serialization.h这个头文件才写的这篇博客。

0 0
原创粉丝点击