625 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			625 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								#ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// MS compatible compilers support #pragma once
							 | 
						||
| 
								 | 
							
								#if defined(_MSC_VER)
							 | 
						||
| 
								 | 
							
								# pragma once
							 | 
						||
| 
								 | 
							
								#pragma inline_depth(511)
							 | 
						||
| 
								 | 
							
								#pragma inline_recursion(on)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(__MWERKS__)
							 | 
						||
| 
								 | 
							
								#pragma inline_depth(511)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
							 | 
						||
| 
								 | 
							
								// iserializer.hpp: interface for serialization system.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// (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 <new>     // for placement new
							 | 
						||
| 
								 | 
							
								#include <cstddef> // size_t, NULL
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/config.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/detail/workaround.hpp>
							 | 
						||
| 
								 | 
							
								#if defined(BOOST_NO_STDC_NAMESPACE)
							 | 
						||
| 
								 | 
							
								namespace std{ 
							 | 
						||
| 
								 | 
							
								    using ::size_t; 
							 | 
						||
| 
								 | 
							
								} // namespace std
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/static_assert.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/eval_if.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/identity.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/greater_equal.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/equal_to.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/core/no_exceptions_support.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
							 | 
						||
| 
								 | 
							
								    #include <boost/serialization/extended_type_info_typeid.hpp>   
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/throw_exception.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/smart_cast.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/static_warning.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_pointer.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_enum.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_const.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/remove_const.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/remove_extent.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/is_polymorphic.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/assume_abstract.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								    #define DONT_USE_HAS_NEW_OPERATOR (                    \
							 | 
						||
| 
								 | 
							
								           BOOST_WORKAROUND(__IBMCPP__, < 1210)            \
							 | 
						||
| 
								 | 
							
								        || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590)   \
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    #define DONT_USE_HAS_NEW_OPERATOR 0
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if ! DONT_USE_HAS_NEW_OPERATOR
							 | 
						||
| 
								 | 
							
								#include <boost/type_traits/has_new_operator.hpp>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/serialization.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/version.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/level.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/tracking.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/type_info_implementation.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/nvp.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/void_cast.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/array.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/collection_size_type.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/singleton.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/serialization/wrapper.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// the following is need only for dynamic cast of polymorphic pointers
							 | 
						||
| 
								 | 
							
								#include <boost/archive/archive_exception.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/archive/detail/basic_iarchive.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/archive/detail/basic_iserializer.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/archive/detail/basic_pointer_iserializer.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/archive/detail/archive_serializer_map.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/archive/detail/check.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace serialization {
							 | 
						||
| 
								 | 
							
								    class extended_type_info;
							 | 
						||
| 
								 | 
							
								} // namespace serialization
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace archive {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// an accessor to permit friend access to archives.  Needed because
							 | 
						||
| 
								 | 
							
								// some compilers don't handle friend templates completely
							 | 
						||
| 
								 | 
							
								class load_access {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								    static void load_primitive(Archive &ar, T &t){
							 | 
						||
| 
								 | 
							
								        ar.load(t);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace detail {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#  pragma warning(push)
							 | 
						||
| 
								 | 
							
								#  pragma warning(disable : 4511 4512)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								class iserializer : public basic_iserializer
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    virtual void destroy(/*const*/ void *address) const {
							 | 
						||
| 
								 | 
							
								        boost::serialization::access::destroy(static_cast<T *>(address));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								    // protected constructor since it's always created by singleton
							 | 
						||
| 
								 | 
							
								    explicit iserializer() :
							 | 
						||
| 
								 | 
							
								        basic_iserializer(
							 | 
						||
| 
								 | 
							
								            boost::serialization::singleton<
							 | 
						||
| 
								 | 
							
								                typename 
							 | 
						||
| 
								 | 
							
								                boost::serialization::type_info_implementation< T >::type
							 | 
						||
| 
								 | 
							
								            >::get_const_instance()
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								    {}
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    virtual BOOST_DLLEXPORT void load_object_data(
							 | 
						||
| 
								 | 
							
								        basic_iarchive & ar,
							 | 
						||
| 
								 | 
							
								        void *x, 
							 | 
						||
| 
								 | 
							
								        const unsigned int file_version
							 | 
						||
| 
								 | 
							
								    ) const BOOST_USED;
							 | 
						||
| 
								 | 
							
								    virtual bool class_info() const {
							 | 
						||
| 
								 | 
							
								        return boost::serialization::implementation_level< T >::value 
							 | 
						||
| 
								 | 
							
								            >= boost::serialization::object_class_info;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    virtual bool tracking(const unsigned int /* flags */) const {
							 | 
						||
| 
								 | 
							
								        return boost::serialization::tracking_level< T >::value 
							 | 
						||
| 
								 | 
							
								                == boost::serialization::track_always
							 | 
						||
| 
								 | 
							
								            || ( boost::serialization::tracking_level< T >::value 
							 | 
						||
| 
								 | 
							
								                == boost::serialization::track_selectively
							 | 
						||
| 
								 | 
							
								                && serialized_as_pointer());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    virtual version_type version() const {
							 | 
						||
| 
								 | 
							
								        return version_type(::boost::serialization::version< T >::value);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    virtual bool is_polymorphic() const {
							 | 
						||
| 
								 | 
							
								        return boost::is_polymorphic< T >::value;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    virtual ~iserializer(){};
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#  pragma warning(pop)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
							 | 
						||
| 
								 | 
							
								    basic_iarchive & ar,
							 | 
						||
| 
								 | 
							
								    void *x, 
							 | 
						||
| 
								 | 
							
								    const unsigned int file_version
							 | 
						||
| 
								 | 
							
								) const {
							 | 
						||
| 
								 | 
							
								    // note: we now comment this out. Before we permited archive
							 | 
						||
| 
								 | 
							
								    // version # to be very large.  Now we don't.  To permit
							 | 
						||
| 
								 | 
							
								    // readers of these old archives, we have to suppress this 
							 | 
						||
| 
								 | 
							
								    // code.  Perhaps in the future we might re-enable it but
							 | 
						||
| 
								 | 
							
								    // permit its suppression with a runtime switch.
							 | 
						||
| 
								 | 
							
								    #if 0
							 | 
						||
| 
								 | 
							
								    // trap case where the program cannot handle the current version
							 | 
						||
| 
								 | 
							
								    if(file_version > static_cast<const unsigned int>(version()))
							 | 
						||
| 
								 | 
							
								        boost::serialization::throw_exception(
							 | 
						||
| 
								 | 
							
								            archive::archive_exception(
							 | 
						||
| 
								 | 
							
								                boost::archive::archive_exception::unsupported_class_version,
							 | 
						||
| 
								 | 
							
								                get_debug_info()
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								    // make sure call is routed through the higest interface that might
							 | 
						||
| 
								 | 
							
								    // be specialized by the user.
							 | 
						||
| 
								 | 
							
								    boost::serialization::serialize_adl(
							 | 
						||
| 
								 | 
							
								        boost::serialization::smart_cast_reference<Archive &>(ar),
							 | 
						||
| 
								 | 
							
								        * static_cast<T *>(x), 
							 | 
						||
| 
								 | 
							
								        file_version
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#  pragma warning(push)
							 | 
						||
| 
								 | 
							
								#  pragma warning(disable : 4511 4512)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// the purpose of this code is to allocate memory for an object
							 | 
						||
| 
								 | 
							
								// without requiring the constructor to be called.  Presumably
							 | 
						||
| 
								 | 
							
								// the allocated object will be subsequently initialized with
							 | 
						||
| 
								 | 
							
								// "placement new". 
							 | 
						||
| 
								 | 
							
								// note: we have the boost type trait has_new_operator but we
							 | 
						||
| 
								 | 
							
								// have no corresponding has_delete_operator.  So we presume
							 | 
						||
| 
								 | 
							
								// that the former being true would imply that the a delete
							 | 
						||
| 
								 | 
							
								// operator is also defined for the class T.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class T>
							 | 
						||
| 
								 | 
							
								struct heap_allocation {
							 | 
						||
| 
								 | 
							
								    // boost::has_new_operator< T > doesn't work on these compilers
							 | 
						||
| 
								 | 
							
								    #if DONT_USE_HAS_NEW_OPERATOR
							 | 
						||
| 
								 | 
							
								        // This doesn't handle operator new overload for class T
							 | 
						||
| 
								 | 
							
								        static T * invoke_new(){
							 | 
						||
| 
								 | 
							
								            return static_cast<T *>(operator new(sizeof(T)));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        static void invoke_delete(T *t){
							 | 
						||
| 
								 | 
							
								            (operator delete(t));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    #else
							 | 
						||
| 
								 | 
							
								        // note: we presume that a true value for has_new_operator
							 | 
						||
| 
								 | 
							
								        // implies the existence of a class specific delete operator as well
							 | 
						||
| 
								 | 
							
								        // as a class specific new operator.
							 | 
						||
| 
								 | 
							
								        struct has_new_operator {
							 | 
						||
| 
								 | 
							
								            static T * invoke_new() {
							 | 
						||
| 
								 | 
							
								                return static_cast<T *>((T::operator new)(sizeof(T)));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            static void invoke_delete(T * t) {
							 | 
						||
| 
								 | 
							
								                // if compilation fails here, the likely cause that the class
							 | 
						||
| 
								 | 
							
								                // T has a class specific new operator but no class specific
							 | 
						||
| 
								 | 
							
								                // delete operator which matches the following signature.
							 | 
						||
| 
								 | 
							
								                // note that this solution addresses the issue that two
							 | 
						||
| 
								 | 
							
								                // possible signatures.  But it doesn't address the possibility
							 | 
						||
| 
								 | 
							
								                // that the class might have class specific new with NO
							 | 
						||
| 
								 | 
							
								                // class specific delete at all.  Patches (compatible with
							 | 
						||
| 
								 | 
							
								                // C++03) welcome!
							 | 
						||
| 
								 | 
							
								                delete t;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        struct doesnt_have_new_operator {
							 | 
						||
| 
								 | 
							
								            static T* invoke_new() {
							 | 
						||
| 
								 | 
							
								                return static_cast<T *>(operator new(sizeof(T)));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            static void invoke_delete(T * t) {
							 | 
						||
| 
								 | 
							
								                // Note: I'm reliance upon automatic conversion from T * to void * here
							 | 
						||
| 
								 | 
							
								                delete t;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        static T * invoke_new() {
							 | 
						||
| 
								 | 
							
								            typedef typename
							 | 
						||
| 
								 | 
							
								                mpl::eval_if<
							 | 
						||
| 
								 | 
							
								                    boost::has_new_operator< T >,
							 | 
						||
| 
								 | 
							
								                    mpl::identity<has_new_operator >,
							 | 
						||
| 
								 | 
							
								                    mpl::identity<doesnt_have_new_operator >    
							 | 
						||
| 
								 | 
							
								                >::type typex;
							 | 
						||
| 
								 | 
							
								            return typex::invoke_new();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        static void invoke_delete(T *t) {
							 | 
						||
| 
								 | 
							
								            typedef typename
							 | 
						||
| 
								 | 
							
								                mpl::eval_if<
							 | 
						||
| 
								 | 
							
								                    boost::has_new_operator< T >,
							 | 
						||
| 
								 | 
							
								                    mpl::identity<has_new_operator >,
							 | 
						||
| 
								 | 
							
								                    mpl::identity<doesnt_have_new_operator >    
							 | 
						||
| 
								 | 
							
								                >::type typex;
							 | 
						||
| 
								 | 
							
								            typex::invoke_delete(t);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    #endif
							 | 
						||
| 
								 | 
							
								    explicit heap_allocation(){
							 | 
						||
| 
								 | 
							
								        m_p = invoke_new();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ~heap_allocation(){
							 | 
						||
| 
								 | 
							
								        if (0 != m_p)
							 | 
						||
| 
								 | 
							
								            invoke_delete(m_p);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    T* get() const {
							 | 
						||
| 
								 | 
							
								        return m_p;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    T* release() {
							 | 
						||
| 
								 | 
							
								        T* p = m_p;
							 | 
						||
| 
								 | 
							
								        m_p = 0;
							 | 
						||
| 
								 | 
							
								        return p;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    T* m_p;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								class pointer_iserializer :
							 | 
						||
| 
								 | 
							
								    public basic_pointer_iserializer
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    virtual void * heap_allocation() const {
							 | 
						||
| 
								 | 
							
								        detail::heap_allocation<T> h;
							 | 
						||
| 
								 | 
							
								        T * t = h.get();
							 | 
						||
| 
								 | 
							
								        h.release();
							 | 
						||
| 
								 | 
							
								        return t;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    virtual const basic_iserializer & get_basic_serializer() const {
							 | 
						||
| 
								 | 
							
								        return boost::serialization::singleton<
							 | 
						||
| 
								 | 
							
								            iserializer<Archive, T>
							 | 
						||
| 
								 | 
							
								        >::get_const_instance();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    BOOST_DLLEXPORT virtual void load_object_ptr(
							 | 
						||
| 
								 | 
							
								        basic_iarchive & ar, 
							 | 
						||
| 
								 | 
							
								        void * x,
							 | 
						||
| 
								 | 
							
								        const unsigned int file_version
							 | 
						||
| 
								 | 
							
								    ) const BOOST_USED;
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								    // this should alway be a singleton so make the constructor protected
							 | 
						||
| 
								 | 
							
								    pointer_iserializer();
							 | 
						||
| 
								 | 
							
								    ~pointer_iserializer();
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#  pragma warning(pop)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// note: BOOST_DLLEXPORT is so that code for polymorphic class
							 | 
						||
| 
								 | 
							
								// serialized only through base class won't get optimized out
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
							 | 
						||
| 
								 | 
							
								    basic_iarchive & ar, 
							 | 
						||
| 
								 | 
							
								    void * t,
							 | 
						||
| 
								 | 
							
								    const unsigned int file_version
							 | 
						||
| 
								 | 
							
								) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    Archive & ar_impl = 
							 | 
						||
| 
								 | 
							
								        boost::serialization::smart_cast_reference<Archive &>(ar);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // note that the above will throw std::bad_alloc if the allocation
							 | 
						||
| 
								 | 
							
								    // fails so we don't have to address this contingency here.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // catch exception during load_construct_data so that we don't
							 | 
						||
| 
								 | 
							
								    // automatically delete the t which is most likely not fully
							 | 
						||
| 
								 | 
							
								    // constructed
							 | 
						||
| 
								 | 
							
								    BOOST_TRY {
							 | 
						||
| 
								 | 
							
								        // this addresses an obscure situation that occurs when 
							 | 
						||
| 
								 | 
							
								        // load_constructor de-serializes something through a pointer.
							 | 
						||
| 
								 | 
							
								        ar.next_object_pointer(t);
							 | 
						||
| 
								 | 
							
								        boost::serialization::load_construct_data_adl<Archive, T>(
							 | 
						||
| 
								 | 
							
								            ar_impl,
							 | 
						||
| 
								 | 
							
								            static_cast<T *>(t),
							 | 
						||
| 
								 | 
							
								            file_version
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    BOOST_CATCH(...){
							 | 
						||
| 
								 | 
							
								        // if we get here the load_construct failed.  The heap_allocation
							 | 
						||
| 
								 | 
							
								        // will be automatically deleted so we don't have to do anything
							 | 
						||
| 
								 | 
							
								        // special here.
							 | 
						||
| 
								 | 
							
								        BOOST_RETHROW;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    BOOST_CATCH_END
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								pointer_iserializer<Archive, T>::pointer_iserializer() :
							 | 
						||
| 
								 | 
							
								    basic_pointer_iserializer(
							 | 
						||
| 
								 | 
							
								        boost::serialization::singleton<
							 | 
						||
| 
								 | 
							
								            typename 
							 | 
						||
| 
								 | 
							
								            boost::serialization::type_info_implementation< T >::type
							 | 
						||
| 
								 | 
							
								        >::get_const_instance()
							 | 
						||
| 
								 | 
							
								    )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    boost::serialization::singleton<
							 | 
						||
| 
								 | 
							
								        iserializer<Archive, T>
							 | 
						||
| 
								 | 
							
								    >::get_mutable_instance().set_bpis(this);
							 | 
						||
| 
								 | 
							
								    archive_serializer_map<Archive>::insert(this);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								pointer_iserializer<Archive, T>::~pointer_iserializer(){
							 | 
						||
| 
								 | 
							
								    archive_serializer_map<Archive>::erase(this);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive>
							 | 
						||
| 
								 | 
							
								struct load_non_pointer_type {
							 | 
						||
| 
								 | 
							
								    // note this bounces the call right back to the archive
							 | 
						||
| 
								 | 
							
								    // with no runtime overhead
							 | 
						||
| 
								 | 
							
								    struct load_primitive {
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        static void invoke(Archive & ar, T & t){
							 | 
						||
| 
								 | 
							
								            load_access::load_primitive(ar, t);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    // note this bounces the call right back to the archive
							 | 
						||
| 
								 | 
							
								    // with no runtime overhead
							 | 
						||
| 
								 | 
							
								    struct load_only {
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        static void invoke(Archive & ar, const T & t){
							 | 
						||
| 
								 | 
							
								            // short cut to user's serializer
							 | 
						||
| 
								 | 
							
								            // make sure call is routed through the higest interface that might
							 | 
						||
| 
								 | 
							
								            // be specialized by the user.
							 | 
						||
| 
								 | 
							
								            boost::serialization::serialize_adl(
							 | 
						||
| 
								 | 
							
								                ar, 
							 | 
						||
| 
								 | 
							
								                const_cast<T &>(t), 
							 | 
						||
| 
								 | 
							
								                boost::serialization::version< T >::value
							 | 
						||
| 
								 | 
							
								            );
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // note this save class information including version
							 | 
						||
| 
								 | 
							
								    // and serialization level to the archive
							 | 
						||
| 
								 | 
							
								    struct load_standard {
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        static void invoke(Archive &ar, const T & t){
							 | 
						||
| 
								 | 
							
								            void * x = & const_cast<T &>(t);
							 | 
						||
| 
								 | 
							
								            ar.load_object(
							 | 
						||
| 
								 | 
							
								                x, 
							 | 
						||
| 
								 | 
							
								                boost::serialization::singleton<
							 | 
						||
| 
								 | 
							
								                    iserializer<Archive, T>
							 | 
						||
| 
								 | 
							
								                >::get_const_instance()
							 | 
						||
| 
								 | 
							
								            );
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    struct load_conditional {
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        static void invoke(Archive &ar, T &t){
							 | 
						||
| 
								 | 
							
								            //if(0 == (ar.get_flags() & no_tracking))
							 | 
						||
| 
								 | 
							
								                load_standard::invoke(ar, t);
							 | 
						||
| 
								 | 
							
								            //else
							 | 
						||
| 
								 | 
							
								            //    load_only::invoke(ar, t);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    static void invoke(Archive & ar, T &t){
							 | 
						||
| 
								 | 
							
								        typedef typename mpl::eval_if<
							 | 
						||
| 
								 | 
							
								                // if its primitive
							 | 
						||
| 
								 | 
							
								                mpl::equal_to<
							 | 
						||
| 
								 | 
							
								                    boost::serialization::implementation_level< T >,
							 | 
						||
| 
								 | 
							
								                    mpl::int_<boost::serialization::primitive_type>
							 | 
						||
| 
								 | 
							
								                >,
							 | 
						||
| 
								 | 
							
								                mpl::identity<load_primitive>,
							 | 
						||
| 
								 | 
							
								            // else
							 | 
						||
| 
								 | 
							
								            typename mpl::eval_if<
							 | 
						||
| 
								 | 
							
								            // class info / version
							 | 
						||
| 
								 | 
							
								            mpl::greater_equal<
							 | 
						||
| 
								 | 
							
								                        boost::serialization::implementation_level< T >,
							 | 
						||
| 
								 | 
							
								                        mpl::int_<boost::serialization::object_class_info>
							 | 
						||
| 
								 | 
							
								                    >,
							 | 
						||
| 
								 | 
							
								            // do standard load
							 | 
						||
| 
								 | 
							
								            mpl::identity<load_standard>,
							 | 
						||
| 
								 | 
							
								        // else
							 | 
						||
| 
								 | 
							
								        typename mpl::eval_if<
							 | 
						||
| 
								 | 
							
								            // no tracking
							 | 
						||
| 
								 | 
							
								                    mpl::equal_to<
							 | 
						||
| 
								 | 
							
								                        boost::serialization::tracking_level< T >,
							 | 
						||
| 
								 | 
							
								                        mpl::int_<boost::serialization::track_never>
							 | 
						||
| 
								 | 
							
								                >,
							 | 
						||
| 
								 | 
							
								                // do a fast load
							 | 
						||
| 
								 | 
							
								                mpl::identity<load_only>,
							 | 
						||
| 
								 | 
							
								            // else
							 | 
						||
| 
								 | 
							
								            // do a fast load only tracking is turned off
							 | 
						||
| 
								 | 
							
								            mpl::identity<load_conditional>
							 | 
						||
| 
								 | 
							
								        > > >::type typex;
							 | 
						||
| 
								 | 
							
								        check_object_versioning< T >();
							 | 
						||
| 
								 | 
							
								        check_object_level< T >();
							 | 
						||
| 
								 | 
							
								        typex::invoke(ar, t);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive>
							 | 
						||
| 
								 | 
							
								struct load_pointer_type {
							 | 
						||
| 
								 | 
							
								    struct abstract
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        static const basic_pointer_iserializer * register_type(Archive & /* ar */){
							 | 
						||
| 
								 | 
							
								            // it has? to be polymorphic
							 | 
						||
| 
								 | 
							
								            BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
							 | 
						||
| 
								 | 
							
								            return static_cast<basic_pointer_iserializer *>(NULL);
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    struct non_abstract
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        template<class T>
							 | 
						||
| 
								 | 
							
								        static const basic_pointer_iserializer * register_type(Archive & ar){
							 | 
						||
| 
								 | 
							
								            return ar.register_type(static_cast<T *>(NULL));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){
							 | 
						||
| 
								 | 
							
								        // there should never be any need to load an abstract polymorphic 
							 | 
						||
| 
								 | 
							
								        // class pointer.  Inhibiting code generation for this
							 | 
						||
| 
								 | 
							
								        // permits abstract base classes to be used - note: exception
							 | 
						||
| 
								 | 
							
								        // virtual serialize functions used for plug-ins
							 | 
						||
| 
								 | 
							
								        typedef typename
							 | 
						||
| 
								 | 
							
								            mpl::eval_if<
							 | 
						||
| 
								 | 
							
								                boost::serialization::is_abstract<const T>,
							 | 
						||
| 
								 | 
							
								                boost::mpl::identity<abstract>,
							 | 
						||
| 
								 | 
							
								                boost::mpl::identity<non_abstract>  
							 | 
						||
| 
								 | 
							
								            >::type typex;
							 | 
						||
| 
								 | 
							
								        return typex::template register_type< T >(ar);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    static T * pointer_tweak(
							 | 
						||
| 
								 | 
							
								        const boost::serialization::extended_type_info & eti,
							 | 
						||
| 
								 | 
							
								        void const * const t,
							 | 
						||
| 
								 | 
							
								        const T &
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								        // tweak the pointer back to the base class
							 | 
						||
| 
								 | 
							
								        void * upcast = const_cast<void *>(
							 | 
						||
| 
								 | 
							
								            boost::serialization::void_upcast(
							 | 
						||
| 
								 | 
							
								                eti,
							 | 
						||
| 
								 | 
							
								                boost::serialization::singleton<
							 | 
						||
| 
								 | 
							
								                    typename 
							 | 
						||
| 
								 | 
							
								                    boost::serialization::type_info_implementation< T >::type
							 | 
						||
| 
								 | 
							
								                >::get_const_instance(),
							 | 
						||
| 
								 | 
							
								                t
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        if(NULL == upcast)
							 | 
						||
| 
								 | 
							
								            boost::serialization::throw_exception(
							 | 
						||
| 
								 | 
							
								                archive_exception(archive_exception::unregistered_class)
							 | 
						||
| 
								 | 
							
								            );
							 | 
						||
| 
								 | 
							
								        return static_cast<T *>(upcast);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    static void check_load(T & /* t */){
							 | 
						||
| 
								 | 
							
								        check_pointer_level< T >();
							 | 
						||
| 
								 | 
							
								        check_pointer_tracking< T >();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static const basic_pointer_iserializer *
							 | 
						||
| 
								 | 
							
								    find(const boost::serialization::extended_type_info & type){
							 | 
						||
| 
								 | 
							
								        return static_cast<const basic_pointer_iserializer *>(
							 | 
						||
| 
								 | 
							
								            archive_serializer_map<Archive>::find(type)
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    template<class Tptr>
							 | 
						||
| 
								 | 
							
								    static void invoke(Archive & ar, Tptr & t){
							 | 
						||
| 
								 | 
							
								        check_load(*t);
							 | 
						||
| 
								 | 
							
								        const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
							 | 
						||
| 
								 | 
							
								        const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
							 | 
						||
| 
								 | 
							
								            // note major hack here !!!
							 | 
						||
| 
								 | 
							
								            // I tried every way to convert Tptr &t (where Tptr might
							 | 
						||
| 
								 | 
							
								            // include const) to void * &.  This is the only way
							 | 
						||
| 
								 | 
							
								            // I could make it work. RR
							 | 
						||
| 
								 | 
							
								            (void * & )t,
							 | 
						||
| 
								 | 
							
								            bpis_ptr,
							 | 
						||
| 
								 | 
							
								            find
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        // if the pointer isn't that of the base class
							 | 
						||
| 
								 | 
							
								        if(newbpis_ptr != bpis_ptr){
							 | 
						||
| 
								 | 
							
								            t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive>
							 | 
						||
| 
								 | 
							
								struct load_enum_type {
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    static void invoke(Archive &ar, T &t){
							 | 
						||
| 
								 | 
							
								        // convert integers to correct enum to load
							 | 
						||
| 
								 | 
							
								        int i;
							 | 
						||
| 
								 | 
							
								        ar >> boost::serialization::make_nvp(NULL, i);
							 | 
						||
| 
								 | 
							
								        t = static_cast< T >(i);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive>
							 | 
						||
| 
								 | 
							
								struct load_array_type {
							 | 
						||
| 
								 | 
							
								    template<class T>
							 | 
						||
| 
								 | 
							
								    static void invoke(Archive &ar, T &t){
							 | 
						||
| 
								 | 
							
								        typedef typename remove_extent< T >::type value_type;
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        // convert integers to correct enum to load
							 | 
						||
| 
								 | 
							
								        // determine number of elements in the array. Consider the
							 | 
						||
| 
								 | 
							
								        // fact that some machines will align elements on boundries
							 | 
						||
| 
								 | 
							
								        // other than characters.
							 | 
						||
| 
								 | 
							
								        std::size_t current_count = sizeof(t) / (
							 | 
						||
| 
								 | 
							
								            static_cast<char *>(static_cast<void *>(&t[1])) 
							 | 
						||
| 
								 | 
							
								            - static_cast<char *>(static_cast<void *>(&t[0]))
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        boost::serialization::collection_size_type count;
							 | 
						||
| 
								 | 
							
								        ar >> BOOST_SERIALIZATION_NVP(count);
							 | 
						||
| 
								 | 
							
								        if(static_cast<std::size_t>(count) > current_count)
							 | 
						||
| 
								 | 
							
								            boost::serialization::throw_exception(
							 | 
						||
| 
								 | 
							
								                archive::archive_exception(
							 | 
						||
| 
								 | 
							
								                    boost::archive::archive_exception::array_size_too_short
							 | 
						||
| 
								 | 
							
								                )
							 | 
						||
| 
								 | 
							
								            );
							 | 
						||
| 
								 | 
							
								        ar >> serialization::make_array(static_cast<value_type*>(&t[0]),count);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // detail
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class Archive, class T>
							 | 
						||
| 
								 | 
							
								inline void load(Archive & ar, T &t){
							 | 
						||
| 
								 | 
							
								    // if this assertion trips. It means we're trying to load a
							 | 
						||
| 
								 | 
							
								    // const object with a compiler that doesn't have correct
							 | 
						||
| 
								 | 
							
								    // funtion template ordering.  On other compilers, this is
							 | 
						||
| 
								 | 
							
								    // handled below.
							 | 
						||
| 
								 | 
							
								    detail::check_const_loading< T >();
							 | 
						||
| 
								 | 
							
								    typedef
							 | 
						||
| 
								 | 
							
								        typename mpl::eval_if<is_pointer< T >,
							 | 
						||
| 
								 | 
							
								            mpl::identity<detail::load_pointer_type<Archive> >
							 | 
						||
| 
								 | 
							
								        ,//else
							 | 
						||
| 
								 | 
							
								        typename mpl::eval_if<is_array< T >,
							 | 
						||
| 
								 | 
							
								            mpl::identity<detail::load_array_type<Archive> >
							 | 
						||
| 
								 | 
							
								        ,//else
							 | 
						||
| 
								 | 
							
								        typename mpl::eval_if<is_enum< T >,
							 | 
						||
| 
								 | 
							
								            mpl::identity<detail::load_enum_type<Archive> >
							 | 
						||
| 
								 | 
							
								        ,//else
							 | 
						||
| 
								 | 
							
								            mpl::identity<detail::load_non_pointer_type<Archive> >
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								        >::type typex;
							 | 
						||
| 
								 | 
							
								    typex::invoke(ar, t);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace archive
							 | 
						||
| 
								 | 
							
								} // namespace boost
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
							 |