📄 basic_iarchive.cpp
字号:
/////////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 + -