⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basic_iarchive.cpp

📁 C++的一个好库。。。现在很流行
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////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

#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{ 
    using ::size_t; 
} // namespace std
#endif

#define BOOST_ARCHIVE_SOURCE
#include <boost/archive/detail/auto_link_archive.hpp>

#include <boost/limits.hpp>
#include <boost/state_saver.hpp>
#include <boost/throw_exception.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/basic_archive_impl.hpp>
#include <boost/archive/archive_exception.hpp>

#include <boost/serialization/tracking.hpp>
#include <boost/serialization/extended_type_info.hpp>

using namespace boost::serialization;

namespace boost {
namespace archive {
namespace detail {

class basic_iserializer;
class basic_pointer_iserializer;

class basic_iarchive_impl :
    public basic_archive_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;
        class_id_type class_id;
        aobject(
            void *a,
            class_id_type class_id_
        ) :
            address(a),
            class_id(class_id_)
        {}
        aobject() : address(NULL), 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.
    // list of objects which might be moved. We use a vector for implemenation
    // in the hope the the truncation operation will be faster than either
    // with a list or stack adaptor
    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;

    //////////////////////////////////////////////////////////////////////
    // list of objects created by de-serialization.  Used to implement
    // clean up after exceptions.
    class created_pointer_type
    {
    public:
        created_pointer_type(
            class_id_type class_id_,
            void * address_
        ) :
            class_id(class_id_),
            address(address_)
        {}
        created_pointer_type(const created_pointer_type &rhs) :
            class_id(rhs.class_id),
            address(rhs.address)
        {}
        created_pointer_type & operator=(const created_pointer_type &){
            assert(false);
            return *this;
        }
        void * get_address() const {
            return address;
        }
        // object to which this item refers
        const class_id_type class_id;
    private:
        void * address;
    };

    std::list<created_pointer_type> created_pointers;

    //////////////////////////////////////////////////////////////////////
    // 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(ARCHIVE_VERSION()),
        m_flags(flags),
        moveable_objects_start(0),
        moveable_objects_end(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
){
    object_id_type i;
    // 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.
    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
            );
       }
        ++i;
    }
}

inline void 
basic_iarchive_impl::delete_created_pointers()
{
    while(created_pointers.size() > 0){
        const created_pointer_type & cp = created_pointers.front();

        // figure out the class of the object to be deleted

⌨️ 快捷键说明

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