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 + -
显示快捷键?