boost serialization
От: limax Россия http://mem.ee
Дата: 05.07.03 18:59
Оценка:
Недавно наткнулся у себя на винте на boost serialization library, которая проходила проверку в прошлом году, однако я так и не понял, почему она не была принята и на какой стадии она сейчас — информацию на сайте boost хрен найдёшь, нужно лезть в архивы рассылки, а это дело весьма утомительное. На Wiki вообще про serialization не слова.

Прошлогодняя версия здесь.

Неплохая либа, вот только не люблю я дублировать все записи/чтения для save/load отдельно. Поэтому накарябал маленький адаптер, чтобы совместить save/load в одной шаблонной функции.

//-----------------------------------------------------------------------------
//    serializer_simple.h
//    Initial coding: 2003/07/05   18:14
//    Purpose:    boost::serialization wrapper, to make save/load simplier
//-----------------------------------------------------------------------------
#pragma once

#include <boost/serialization.hpp>

//-----------------------------------------------------------------------------

namespace lim_internal {
struct Load
    {
    boost::basic_iarchive& _ar;
    boost::version_type _ver;
    bool _process;
    Load(boost::basic_iarchive& ar, boost::version_type ver, bool process=true)
        : _ar(ar), _ver(ver), _process(process)
        {}
    template<class T> Load& operator,(const T& t)
        {
        if (_process)
            _ar>>(T&)t;
        return *this;
        }
    Load operator!()
        { return Load(_ar,_ver,!_process); }
    Load operator()(boost::version_type min_ver)
        { return Load(_ar,_ver, (min_ver<=_ver)?true:false); }
    Load operator()(boost::version_type min_ver, boost::version_type max_ver)
        { return Load(_ar,_ver, ((min_ver<=_ver)&&(max_ver>=_ver))?true:false); }
    };

struct Save
    {
    boost::basic_oarchive& _ar;
    boost::version_type _ver;
    bool _process;
    Save(boost::basic_oarchive& ar, boost::version_type ver, bool process=true)
        : _ar(ar), _ver(ver), _process(process)
        {}
    template<class T> Save& operator,(const T& t)
        {
        if (_process)
            _ar<<t;
        return *this;
        }
    Save operator!()
        { return Save(_ar,_ver,!_process); }
    Save operator()(boost::version_type min_ver)
        { return Save(_ar,_ver, (min_ver<=_ver)?true:false); }
    Save operator()(boost::version_type min_ver, boost::version_type max_ver)
        { return Save(_ar,_ver, ((min_ver<=_ver)&&(max_ver>=_ver))?true:false); }
    };
}
//-----------------------------------------------------------------------------

//по-умолчанию переадресация в метод класса.
template <class T, class Serializer> inline void serializer(const T& t, Serializer& s)
    { t.serializer(s); }

// Переадресация boost::serialization в наш адаптер.
// Определять после определения вашей специализации шаблона сериализатора.
#define SERIALIZER(Type,ver) \
    inline void serialization<Type>::save(boost::basic_oarchive &ar, const Type &t) \
    { return serializer(t,lim_internal::Save(ar,ver)); } \
    inline void serialization<Type>::load(boost::basic_iarchive &ar, Type &t, boost::version_type saved_version) \
    { return serializer(t,lim_internal::Load(ar,saved_version)); } \
    inline boost::version_type serialization<Type>::version(const Type &t) \
    { return ver; }


Использовать так:
// test_serialization.cpp : Defines the entry point for the console application.
//

#include "serializer_simple.h"
#include <iostream>
#include <fstream>
using namespace std;

struct MapTile
    { char tile,obj,unit,force,vis; }; //vis добавлен позднее.

//! external serialization of MapTile
template<class Serializer> void serializer(const MapTile& t, Serializer& s)
    {
    s, t.tile, t.obj, t.unit, t.force; //для всех версий
    s(2), t.vis; //только в версии 2 и более поздних
    }
SERIALIZER(MapTile,2); //если поставить версию 0 или 1, то не будет сериализован t.vis


//возможно определение serializer-а внутри класса.
//! with internal serialization
struct MapTile2
    {
    char tile,obj,unit,force,vis;
    template<class Serializer> void serializer(Serializer& s) const
        {
        s, tile, obj, unit, force; //для всех версий
        s(2), vis; //только в версии 2 и более поздних
        }
    };
SERIALIZER(MapTile2,2);


//-----------------------------------------------------------------------------
ostream& operator<<(ostream& os, const MapTile& m)
    { return os<<m.tile<<m.obj<<m.unit<<m.force<<m.vis; }
ostream& operator<<(ostream& os, const MapTile2& m)
    { return os<<m.tile<<m.obj<<m.unit<<m.force<<m.vis; }

MapTile _map;

void load(const char* path)
    {
    cout<<"loading "<<path<<endl;
    std::ifstream ifs(path, std::ios::binary);
    boost::biarchive ia(ifs);
    ia>>_map;
    ifs.close();
    }

void save(const char* path)
    {
    cout<<"saving "<<path<<endl;
    std::ofstream ofs(path, std::ios::binary);
    boost::boarchive oa(ofs);
    oa<<_map;
    ofs.close();
    }

int main( ) 
    {
    _map.tile='t';
    _map.obj='o';
    _map.unit='u';
    _map.force='f';
    _map.vis='v';
    cout<<_map<<endl;
    save("test_map1.bin");
    cout<<"changing..."<<endl;
    _map.tile='-';
    _map.obj='-';
    _map.vis='-';
    cout<<_map<<endl;
    load("test_map1.bin");
    cout<<_map<<endl;
    return 0;
    }

Можно дальше поиграть с определением Load/Save.

Например !s(2,4),xxx вызовет сериализацию xxx для всех версий, кроме 2,3,4.
s(1,1),xxx — только версию 1, но ни 0, ни 2.
Можно свои операторы/методы добавить и т.п.
Have fun: Win+M, Ctrl+A, Enter
Re: boost serialization
От: limax Россия http://mem.ee
Дата: 05.07.03 19:09
Оценка:
Ага, наткнулся на сообщение автора:
http://aspn.activestate.com/ASPN/Mail/Message/boost/1643270
Have fun: Win+M, Ctrl+A, Enter
Re: [update] boost serialization
От: limax Россия http://mem.ee
Дата: 07.07.03 18:59
Оценка:
Обновление.
  • Базовый класс для Save/Load адаптеров, для общих фич, например выбор версии.
  • Более интуитивный выбор версий, например s>=3,a,b,c,d; или s<3,xxx;
  • Исправлена поддержка массивов. (Контейнеры и всё остальное и раньше работало)
  • SERIALIZER_MEMBER для объявления внутри класса.

    //-----------------------------------------------------------------------------
    //    serializer_simple.h
    //    Initial coding: 2003/07/05   18:14
    //    Purpose:    boost::serialization wrapper, to make save/load simplier
    //-----------------------------------------------------------------------------
    #pragma once
    
    #include <boost/serialization.hpp>
    
    //-----------------------------------------------------------------------------
    
    namespace lim_serialization 
        {
        //generic for both Save and Load
        template<class Serializer, class Arch> struct SerializerT
            {
            typedef SerializerT<Serializer,Arch> Base;
            typedef Arch Archive;
            typedef boost::version_type Version;
            Archive& _ar;
            Version _ver;
            bool _process;
            SerializerT(Archive& ar, Version ver, bool process=true)
                : _ar(ar), _ver(ver), _process(process)
                {}
            Serializer operator!()
                { return Serializer(_ar,_ver,!_process); }
            Serializer operator()(Version min_ver)
                { return Serializer(_ar,_ver, (min_ver<=_ver)?true:false); }
            Serializer operator()(Version min_ver, Version max_ver)
                { return Serializer(_ar,_ver, ((min_ver<=_ver)&&(max_ver>=_ver))?true:false); }
            Serializer operator<(Version min_ver)
                { return Serializer(_ar,_ver, (_ver<min_ver)?true:false); }
            Serializer operator>(Version min_ver)
                { return Serializer(_ar,_ver, (_ver>min_ver)?true:false); }
            Serializer operator<=(Version min_ver)
                { return Serializer(_ar,_ver, (_ver<=min_ver)?true:false); }
            Serializer operator>=(Version min_ver)
                { return Serializer(_ar,_ver, (_ver>=min_ver)?true:false); }
            Serializer operator==(Version min_ver)
                { return Serializer(_ar,_ver, (_ver==min_ver)?true:false); }
            Serializer operator!=(Version min_ver)
                { return Serializer(_ar,_ver, (_ver!=min_ver)?true:false); }
            };
    
        //Load adapter
        struct Load : SerializerT<Load,boost::basic_iarchive>
            {
            Load(Archive& ar, Version ver, bool process=true)
                : Base(ar,ver,process)
                {}
            template<class T, size_t N> Load& operator,(const T (&t)[N])
                {
                if (_process)
                    _ar>>(T (&)[N])t;
                return *this;
                }
            template<class T> Load& operator,(const T& t)
                {
                if (_process)
                    _ar>>(T&)t;
                return *this;
                }
            };
    
        //Save adapter
        struct Save : SerializerT<Save,boost::basic_oarchive>
            {
            Save(Archive& ar, Version ver, bool process=true)
                : Base(ar,ver,process)
                {}
            template<class T, size_t N> Save& operator,(const T (&t)[N])
                {
                if (_process)
                    _ar<<t;
                return *this;
                }
            template<class T> Save& operator,(const T& t)
                {
                if (_process)
                    _ar<<t;
                return *this;
                }
            };
        }
    //-----------------------------------------------------------------------------
    
    //redirect to member by default
    template <class T, class Serializer> inline void serializer(const T& t, Serializer& s)
        { t.serializer(s); }
    
    #define SERIALIZER_EXTERNAL(Type,ver) \
        inline void serialization<Type>::save(boost::basic_oarchive &ar, const Type &t) \
            { return ::serializer(t,lim_serialization::Save(ar,ver)); } \
        inline void serialization<Type>::load(boost::basic_iarchive &ar, Type &t, boost::version_type saved_version) \
            { return ::serializer(t,lim_serialization::Load(ar,saved_version)); } \
        inline boost::version_type serialization<Type>::version(const Type &t) \
            { return ver; }
    #define SERIALIZER SERIALIZER_EXTERNAL
    
    #define SERIALIZER_MEMBER(ver) \
        inline void save(boost::basic_oarchive &ar) const \
            { return ::serializer(*this,lim_serialization::Save(ar,ver)); } \
        inline void load(boost::basic_iarchive &ar, boost::version_type saved_version) \
            { return ::serializer(*this,lim_serialization::Load(ar,saved_version)); } \
        inline boost::version_type version() const \
            { return ver; }

    // test_serializer.cpp : Example of serialization
    
    #include "stdafx.h" //<iostram>, <fstream>, <vector>, "<serializer_simple.h"
    
    using namespace std;
    
    struct struct_t
        {
        char _arr[10];
        struct_t()
            { _arr[0]=0; }
        struct_t(char* str)
            { strncpy(_arr,str,10); }
        //internal serialization
        template<class Serializer> void serializer(Serializer& s) const
            { s,_arr; }
        SERIALIZER_MEMBER(0);
        };
    
    //-----------------------------------------------------------------------------
    
    // Output to cout
    inline ostream& operator<<(ostream& os, const struct_t& st)
        { return os<<st._arr; }
    template<class T> inline ostream& operator<<(ostream& os, const vector<T*>& t)
        {
        for(vector<T*>::const_iterator i=t.begin(); i!=t.end(); ++i)
            os<<**i<<endl;
        return os;
        }
    
    template<class T> void load(T& t, const char* path)
        {
        cout<<"loading "<<path<<endl;
        std::ifstream ifs(path, std::ios::binary);
        boost::biarchive ia(ifs);
        ia>>t;
        ifs.close();
        }
    
    template<class T> void save(const T& t, const char* path)
        {
        cout<<"saving "<<path<<endl;
        std::ofstream ofs(path, std::ios::binary);
        boost::boarchive oa(ofs);
        oa<<t;
        ofs.close();
        }
    
    int main( ) 
        {
        vector<struct_t*> vec;
        vec.push_back(new struct_t("struct1"));
        vec.push_back(new struct_t(" struct2"));
        vec.push_back(new struct_t("  struct3"));
        cout<<vec<<endl;
        save(vec,"map_test1.bin");
        while(!vec.empty())
            {
            delete vec.back();
            vec.pop_back();
            }
        cout<<vec<<endl;
        load(vec,"map_test1.bin");
        cout<<vec<<endl;
        return 0;
        }
  • Have fun: Win+M, Ctrl+A, Enter
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.