Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / archive / detail / iserializer.hpp
index 46033fd..42d00a3 100644 (file)
@@ -2,7 +2,7 @@
 #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
 
 // MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#if defined(_MSC_VER)
 # pragma once
 #pragma inline_depth(511)
 #pragma inline_recursion(on)
@@ -23,7 +23,6 @@
 //  See http://www.boost.org for updates, documentation, and revision history.
 
 #include <new>     // for placement new
-#include <memory>  // for auto_ptr
 #include <cstddef> // size_t, NULL
 
 #include <boost/config.hpp>
@@ -58,14 +57,11 @@ namespace std{
 #include <boost/type_traits/is_polymorphic.hpp>
 
 #include <boost/serialization/assume_abstract.hpp>
-
 #define DONT_USE_HAS_NEW_OPERATOR (                    \
     defined(__BORLANDC__)                              \
-    || defined(__IBMCPP__)                             \
-    || defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)     \
+    || BOOST_WORKAROUND(__IBMCPP__, < 1210)            \
     || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590)   \
 )
-
 #if ! DONT_USE_HAS_NEW_OPERATOR
 #include <boost/type_traits/has_new_operator.hpp>
 #endif
@@ -127,7 +123,7 @@ protected:
     explicit iserializer() :
         basic_iserializer(
             boost::serialization::singleton<
-                BOOST_DEDUCED_TYPENAME 
+                typename 
                 boost::serialization::type_info_implementation< T >::type
             >::get_const_instance()
         )
@@ -197,85 +193,84 @@ BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
 #  pragma warning(disable : 4511 4512)
 #endif
 
-template<class Archive, class T>
-class pointer_iserializer :
-    public basic_pointer_iserializer
-{
-private:
-    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 trick to be sure that operator new is using class specific
-// version if such exists. Due to Peter Dimov.
-// note: the following fails if T has no default constructor.
-// otherwise it would have been ideal
-//struct heap_allocator : public T 
-//{
-//    T * invoke(){
-//        return ::new(sizeof(T));
-//    }
-//}
+// 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_allocator
-{
+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(){
+        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() {
+            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.  Fix
+                // your program to have this.  Note that adding operator delete
+                // with only one parameter doesn't seem correct to me since 
+                // the standard(3.7.4.2) says "
+                // "If a class T has a member deallocation function named
+                // 'operator delete' with exactly one parameter, then that function 
+                // is a usual (non-placement) deallocation function" which I take
+                // to mean that it will call the destructor of type T which we don't
+                // want to do here.
+                // Note: reliance upon automatic conversion from T * to void * here
+                (T::operator delete)(t, sizeof(T));
+            }
         };
         struct doesnt_have_new_operator {
-            static T* invoke() {
+            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
+                (operator delete)(t);
+            }
         };
-        static T * invoke() {
-            typedef BOOST_DEDUCED_TYPENAME
+        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;
-            return typex::invoke();
+            typex::invoke_delete(t);
         }
     #endif
-};
-
-// due to Martin Ecker
-template <typename T>
-class auto_ptr_with_deleter
-{
-public:
-    explicit auto_ptr_with_deleter(T* p) :
-        m_p(p)
-    {}
-    ~auto_ptr_with_deleter(){
-        if (m_p)
-            boost::serialization::access::destroy(m_p);
+    explicit heap_allocation(){
+        m_p = invoke_new();
+    }
+    ~heap_allocation(){
+        if (0 != m_p)
+            invoke_delete(m_p);
     }
     T* get() const {
         return m_p;
@@ -283,60 +278,88 @@ public:
 
     T* release() {
         T* p = m_p;
-        m_p = NULL;
+        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 * & x,
+    void * t,
     const unsigned int file_version
 ) const
 {
     Archive & ar_impl = 
         boost::serialization::smart_cast_reference<Archive &>(ar);
 
-    auto_ptr_with_deleter< T > ap(heap_allocator< T >::invoke());
-    if(NULL == ap.get())
-        boost::serialization::throw_exception(std::bad_alloc()) ;
-
-    T * t = ap.get();
-    x = t;
+    // 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 situtation that occurs when 
+        // 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,
-            t, 
+            static_cast<T *>(t),
             file_version
         );
     }
     BOOST_CATCH(...){
-        ap.release();
+        // 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, * t);
-    ap.release();
+    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<
-            BOOST_DEDUCED_TYPENAME 
+            typename 
             boost::serialization::type_info_implementation< T >::type
         >::get_const_instance()
     )
@@ -405,7 +428,7 @@ struct load_non_pointer_type {
 
     template<class T>
     static void invoke(Archive & ar, T &t){
-        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+        typedef typename mpl::eval_if<
                 // if its primitive
                 mpl::equal_to<
                     boost::serialization::implementation_level< T >,
@@ -413,7 +436,7 @@ struct load_non_pointer_type {
                 >,
                 mpl::identity<load_primitive>,
             // else
-            BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            typename mpl::eval_if<
             // class info / version
             mpl::greater_equal<
                         boost::serialization::implementation_level< T >,
@@ -422,7 +445,7 @@ struct load_non_pointer_type {
             // do standard load
             mpl::identity<load_standard>,
         // else
-        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+        typename mpl::eval_if<
             // no tracking
                     mpl::equal_to<
                         boost::serialization::tracking_level< T >,
@@ -466,7 +489,7 @@ struct load_pointer_type {
         // class pointer.  Inhibiting code generation for this
         // permits abstract base classes to be used - note: exception
         // virtual serialize functions used for plug-ins
-        typedef BOOST_DEDUCED_TYPENAME
+        typedef typename
             mpl::eval_if<
                 boost::serialization::is_abstract<const T>,
                 boost::mpl::identity<abstract>,
@@ -482,18 +505,21 @@ struct load_pointer_type {
         const T &
     ) {
         // tweak the pointer back to the base class
-        return static_cast<T *>(
-            const_cast<void *>(
-                boost::serialization::void_upcast(
-                    eti,
-                    boost::serialization::singleton<
-                        BOOST_DEDUCED_TYPENAME 
-                        boost::serialization::type_info_implementation< T >::type
-                    >::get_const_instance(),
-                    t
-                )
+        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>
@@ -544,7 +570,7 @@ template<class Archive>
 struct load_array_type {
     template<class T>
     static void invoke(Archive &ar, T &t){
-        typedef BOOST_DEDUCED_TYPENAME remove_extent< T >::type value_type;
+        typedef typename remove_extent< T >::type value_type;
         
         // convert integers to correct enum to load
         // determine number of elements in the array. Consider the
@@ -576,13 +602,13 @@ inline void load(Archive & ar, T &t){
     // handled below.
     detail::check_const_loading< T >();
     typedef
-        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
+        typename mpl::eval_if<is_pointer< T >,
             mpl::identity<detail::load_pointer_type<Archive> >
         ,//else
-        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
+        typename mpl::eval_if<is_array< T >,
             mpl::identity<detail::load_array_type<Archive> >
         ,//else
-        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
+        typename mpl::eval_if<is_enum< T >,
             mpl::identity<detail::load_enum_type<Archive> >
         ,//else
             mpl::identity<detail::load_non_pointer_type<Archive> >