basic_iarchive.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 572 行 · 第 1/2 页

CPP
572
字号
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8// basic_archive.cpp:// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//  See http://www.boost.org for updates, documentation, and revision history.#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings#include <cassert>#include <set>#include <list>#include <vector>#include <cstddef> // size_t, NULL#include <boost/config.hpp>#if defined(BOOST_NO_STDC_NAMESPACE)namespace std{     using ::size_t; } // namespace std#endif#include <boost/limits.hpp>#include <boost/serialization/state_saver.hpp>#include <boost/serialization/throw_exception.hpp>#include <boost/serialization/tracking.hpp>#include <boost/archive/archive_exception.hpp>#define BOOST_ARCHIVE_SOURCE#define BOOST_SERIALIZATION_SOURCE#include <boost/archive/detail/decl.hpp>#include <boost/archive/basic_archive.hpp>#include <boost/archive/detail/basic_iserializer.hpp>#include <boost/archive/detail/basic_pointer_iserializer.hpp>#include <boost/archive/detail/basic_iarchive.hpp>#include <boost/archive/detail/auto_link_archive.hpp>using namespace boost::serialization;namespace boost {namespace archive {namespace detail {class basic_iarchive_impl {    friend class basic_iarchive;    version_type m_archive_library_version;    unsigned int m_flags;    //////////////////////////////////////////////////////////////////////    // information about each serialized object loaded    // indexed on object_id    struct aobject    {        void * address;        bool loaded_as_pointer;        class_id_type class_id;        aobject(            void *a,            class_id_type class_id_        ) :            address(a),            loaded_as_pointer(false),            class_id(class_id_)        {}        aobject() :             address(NULL),            loaded_as_pointer(false),            class_id(-2)         {}    };    typedef std::vector<aobject> object_id_vector_type;    object_id_vector_type object_id_vector;    //////////////////////////////////////////////////////////////////////    // used to implement the reset_object_address operation.    object_id_type moveable_objects_start;    object_id_type moveable_objects_end;    object_id_type moveable_objects_recent;    void reset_object_address(        const void * new_address,         const void *old_address    );    //////////////////////////////////////////////////////////////////////    // used by load object to look up class id given basic_serializer    struct cobject_type    {        const basic_iserializer * bis;        const class_id_type class_id;        cobject_type(            class_id_type class_id_,            const basic_iserializer & bis_        ) :             bis(& bis_),            class_id(class_id_)        {}        cobject_type(const cobject_type & rhs) :             bis(rhs.bis),            class_id(rhs.class_id)        {}        // the following cannot be defined because of the const        // member.  This will generate a link error if an attempt        // is made to assign.  This should never be necessary        cobject_type & operator=(const cobject_type & rhs);        bool operator<(const cobject_type &rhs) const        {            return *bis < *(rhs.bis);        }    };    typedef std::set<cobject_type> cobject_info_set_type;    cobject_info_set_type cobject_info_set;    //////////////////////////////////////////////////////////////////////    // information about each serialized class indexed on class_id    class cobject_id     {    public:        cobject_id & operator=(const cobject_id & rhs){            bis_ptr = rhs.bis_ptr;            bpis_ptr = rhs.bpis_ptr;            file_version = rhs.file_version;            tracking_level = rhs.tracking_level;            initialized = rhs.initialized;            return *this;        }        const basic_iserializer * bis_ptr;        const basic_pointer_iserializer * bpis_ptr;        version_type file_version;        tracking_type tracking_level;        bool initialized;        cobject_id(const basic_iserializer & bis_) :            bis_ptr(& bis_),            bpis_ptr(NULL),            file_version(0),            tracking_level(track_never),            initialized(false)        {}        cobject_id(const cobject_id &rhs):             bis_ptr(rhs.bis_ptr),            bpis_ptr(rhs.bpis_ptr),            file_version(rhs.file_version),            tracking_level(rhs.tracking_level),            initialized(rhs.initialized)        {}    };    typedef std::vector<cobject_id> cobject_id_vector_type;    cobject_id_vector_type cobject_id_vector;    //////////////////////////////////////////////////////////////////////    // address of the most recent object serialized as a poiner    // whose data itself is now pending serialization    void * pending_object;    const basic_iserializer * pending_bis;    version_type pending_version;    basic_iarchive_impl(unsigned int flags) :        m_archive_library_version(BOOST_ARCHIVE_VERSION()),        m_flags(flags),        moveable_objects_start(0),        moveable_objects_end(0),        moveable_objects_recent(0),        pending_object(NULL),        pending_bis(NULL),        pending_version(0)    {}    ~basic_iarchive_impl(){}    void set_library_version(unsigned int archive_library_version){        m_archive_library_version = archive_library_version;    }    bool    track(        basic_iarchive & ar,        void * & t    );    void    load_preamble(        basic_iarchive & ar,        cobject_id & co    );    class_id_type register_type(        const basic_iserializer & bis    );    // redirect through virtual functions to load functions for this archive    template<class T>    void load(basic_iarchive & ar, T & t){        ar.vload(t);    }//public:    void    next_object_pointer(void * t){        pending_object = t;    }    void delete_created_pointers();    class_id_type register_type(        const basic_pointer_iserializer & bpis    );    void load_object(        basic_iarchive & ar,        void * t,        const basic_iserializer & bis    );    const basic_pointer_iserializer * load_pointer(        basic_iarchive & ar,        void * & t,         const basic_pointer_iserializer * bpis,        const basic_pointer_iserializer * (*finder)(            const boost::serialization::extended_type_info & type        )    );};inline void basic_iarchive_impl::reset_object_address(    const void * new_address,     const void *old_address){    // this code handles a couple of situations.    // a) where reset_object_address is applied to an untracked object.    //    In such a case the call is really superfluous and its really an    //    an error.  But we don't have access to the types here so we can't    //    know that.  However, this code will effectively turn this situation    //    into a no-op and every thing will work fine - albeat with a small    //    execution time penalty.    // b) where the call to reset_object_address doesn't immediatly follow    //    the << operator to which it corresponds.  This would be a bad idea    //    but the code may work anyway.  Naturally, a bad practice on the part    //    of the programmer but we can't detect it - as above.  So maybe we    //    can save a few more people from themselves as above.    object_id_type i;    for(i = moveable_objects_recent; i < moveable_objects_end; ++i){        if(old_address == object_id_vector[i].address)            break;    }    for(; i < moveable_objects_end; ++i){        // calculate displacement from this level        // warning - pointer arithmetic on void * is in herently non-portable        // but expected to work on all platforms in current usage        if(object_id_vector[i].address > old_address){            std::size_t member_displacement                = reinterpret_cast<std::size_t>(object_id_vector[i].address)                 - reinterpret_cast<std::size_t>(old_address);            object_id_vector[i].address = reinterpret_cast<void *>(                reinterpret_cast<std::size_t>(new_address) + member_displacement            );        }        else{            std::size_t member_displacement                = reinterpret_cast<std::size_t>(old_address)                - reinterpret_cast<std::size_t>(object_id_vector[i].address);             object_id_vector[i].address = reinterpret_cast<void *>(                reinterpret_cast<std::size_t>(new_address) - member_displacement            );       }    }}inline void basic_iarchive_impl::delete_created_pointers(){    object_id_vector_type::iterator i;    for(        i = object_id_vector.begin();        i != object_id_vector.end();         ++i    ){        if(i->loaded_as_pointer){            // borland complains without this minor hack            const int j = i->class_id;            const cobject_id & co = cobject_id_vector[j];            //const cobject_id & co = cobject_id_vector[i->class_id];            // with the appropriate input serializer,             // delete the indicated object            co.bis_ptr->destroy(i->address);        }    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?