| 1 | #ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP | 
|---|
| 2 | #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP | 
|---|
| 3 |  | 
|---|
| 4 | // MS compatible compilers support #pragma once | 
|---|
| 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) | 
|---|
| 6 | # pragma once | 
|---|
| 7 | #pragma inline_depth(511) | 
|---|
| 8 | #pragma inline_recursion(on) | 
|---|
| 9 | #endif | 
|---|
| 10 |  | 
|---|
| 11 | #if defined(__MWERKS__) | 
|---|
| 12 | #pragma inline_depth(511) | 
|---|
| 13 | #endif | 
|---|
| 14 |  | 
|---|
| 15 | /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 | 
|---|
| 16 | // iserializer.hpp: interface for serialization system. | 
|---|
| 17 |  | 
|---|
| 18 | // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .  | 
|---|
| 19 | // Use, modification and distribution is subject to the Boost Software | 
|---|
| 20 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | 
|---|
| 21 | // http://www.boost.org/LICENSE_1_0.txt) | 
|---|
| 22 |  | 
|---|
| 23 | //  See http://www.boost.org for updates, documentation, and revision history. | 
|---|
| 24 |  | 
|---|
| 25 | #include <new>     // for placement new | 
|---|
| 26 | #include <memory>  // for auto_ptr | 
|---|
| 27 | #include <cstddef> // size_t | 
|---|
| 28 |  | 
|---|
| 29 | #include <boost/config.hpp> | 
|---|
| 30 | #include <boost/detail/workaround.hpp> | 
|---|
| 31 | #if defined(BOOST_NO_STDC_NAMESPACE) | 
|---|
| 32 | namespace std{  | 
|---|
| 33 |     using ::size_t;  | 
|---|
| 34 | } // namespace std | 
|---|
| 35 | #endif | 
|---|
| 36 | #include <boost/throw_exception.hpp> | 
|---|
| 37 | #include <boost/smart_cast.hpp> | 
|---|
| 38 | #include <boost/static_assert.hpp> | 
|---|
| 39 | #include <boost/static_warning.hpp> | 
|---|
| 40 | #include <boost/detail/no_exceptions_support.hpp> | 
|---|
| 41 |  | 
|---|
| 42 | #include <boost/type_traits/is_pointer.hpp> | 
|---|
| 43 | #include <boost/type_traits/is_fundamental.hpp> | 
|---|
| 44 | #include <boost/type_traits/is_enum.hpp> | 
|---|
| 45 | #include <boost/type_traits/is_same.hpp> | 
|---|
| 46 | #include <boost/type_traits/is_const.hpp> | 
|---|
| 47 | #include <boost/type_traits/remove_const.hpp> | 
|---|
| 48 | #include <boost/serialization/is_abstract.hpp> | 
|---|
| 49 |  | 
|---|
| 50 | #include <boost/mpl/eval_if.hpp> | 
|---|
| 51 | #include <boost/mpl/if.hpp> | 
|---|
| 52 | #include <boost/mpl/identity.hpp> | 
|---|
| 53 | #include <boost/mpl/or.hpp> | 
|---|
| 54 | #include <boost/mpl/and.hpp> | 
|---|
| 55 | #include <boost/mpl/less.hpp> | 
|---|
| 56 | #include <boost/mpl/greater_equal.hpp> | 
|---|
| 57 | #include <boost/mpl/int.hpp> | 
|---|
| 58 | #include <boost/mpl/list.hpp> | 
|---|
| 59 | #include <boost/mpl/empty.hpp> | 
|---|
| 60 | #include <boost/mpl/not.hpp> | 
|---|
| 61 |  | 
|---|
| 62 | #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO | 
|---|
| 63 |     #include <boost/serialization/extended_type_info_typeid.hpp> | 
|---|
| 64 | #endif | 
|---|
| 65 |  | 
|---|
| 66 | // the following is need only for dynamic cast of polymorphic pointers | 
|---|
| 67 | #include <boost/archive/detail/basic_iarchive.hpp> | 
|---|
| 68 | #include <boost/archive/detail/basic_iserializer.hpp> | 
|---|
| 69 | #include <boost/archive/detail/archive_pointer_iserializer.hpp> | 
|---|
| 70 | #include <boost/archive/archive_exception.hpp> | 
|---|
| 71 |  | 
|---|
| 72 | #include <boost/serialization/force_include.hpp> | 
|---|
| 73 | #include <boost/serialization/serialization.hpp> | 
|---|
| 74 | #include <boost/serialization/version.hpp> | 
|---|
| 75 | #include <boost/serialization/level.hpp> | 
|---|
| 76 | #include <boost/serialization/tracking.hpp> | 
|---|
| 77 | #include <boost/serialization/type_info_implementation.hpp> | 
|---|
| 78 | #include <boost/serialization/nvp.hpp> | 
|---|
| 79 | #include <boost/serialization/binary_object.hpp> | 
|---|
| 80 | #include <boost/serialization/void_cast.hpp> | 
|---|
| 81 |  | 
|---|
| 82 | namespace boost { | 
|---|
| 83 |  | 
|---|
| 84 | namespace serialization { | 
|---|
| 85 |     class extended_type_info; | 
|---|
| 86 | } // namespace serialization | 
|---|
| 87 |  | 
|---|
| 88 | namespace archive { | 
|---|
| 89 |  | 
|---|
| 90 | // an accessor to permit friend access to archives.  Needed because | 
|---|
| 91 | // some compilers don't handle friend templates completely | 
|---|
| 92 | class load_access { | 
|---|
| 93 | public: | 
|---|
| 94 |     template<class Archive, class T> | 
|---|
| 95 |     static void load_primitive(Archive &ar, T &t){ | 
|---|
| 96 |         ar.load(t); | 
|---|
| 97 |     } | 
|---|
| 98 | }; | 
|---|
| 99 |  | 
|---|
| 100 | namespace detail { | 
|---|
| 101 |  | 
|---|
| 102 | template<class Archive, class T> | 
|---|
| 103 | class iserializer : public basic_iserializer | 
|---|
| 104 | { | 
|---|
| 105 | private: | 
|---|
| 106 |     virtual void destroy(/*const*/ void *address) const { | 
|---|
| 107 |         boost::serialization::access::destroy(static_cast<T *>(address)); | 
|---|
| 108 |     } | 
|---|
| 109 |     // private constructor to inhibit any existence other than the  | 
|---|
| 110 |     // static one | 
|---|
| 111 |     explicit iserializer() : | 
|---|
| 112 |         basic_iserializer( | 
|---|
| 113 |             * boost::serialization::type_info_implementation<T>::type::get_instance() | 
|---|
| 114 |         ) | 
|---|
| 115 |     {} | 
|---|
| 116 | public: | 
|---|
| 117 |     virtual BOOST_DLLEXPORT void load_object_data( | 
|---|
| 118 |         basic_iarchive & ar, | 
|---|
| 119 |         void *x,  | 
|---|
| 120 |         const unsigned int file_version | 
|---|
| 121 |     ) const BOOST_USED ; | 
|---|
| 122 |     virtual bool class_info() const { | 
|---|
| 123 |         return boost::serialization::implementation_level<T>::value  | 
|---|
| 124 |             >= boost::serialization::object_class_info; | 
|---|
| 125 |     } | 
|---|
| 126 |     virtual bool tracking(const unsigned int flags) const { | 
|---|
| 127 | //        if(0 != (flags & no_tracking)) | 
|---|
| 128 | //            return false; | 
|---|
| 129 |         return boost::serialization::tracking_level<T>::value  | 
|---|
| 130 |                 == boost::serialization::track_always | 
|---|
| 131 |             || boost::serialization::tracking_level<T>::value  | 
|---|
| 132 |                 == boost::serialization::track_selectivly | 
|---|
| 133 |             && serialized_as_pointer(); | 
|---|
| 134 |     } | 
|---|
| 135 |     virtual unsigned int version() const { | 
|---|
| 136 |         return ::boost::serialization::version<T>::value; | 
|---|
| 137 |     } | 
|---|
| 138 |     virtual bool is_polymorphic() const { | 
|---|
| 139 |         typedef BOOST_DEDUCED_TYPENAME  | 
|---|
| 140 |             boost::serialization::type_info_implementation< | 
|---|
| 141 |                 T | 
|---|
| 142 |             >::type::is_polymorphic::type typex; | 
|---|
| 143 |         return typex::value; | 
|---|
| 144 |     } | 
|---|
| 145 |     static iserializer & instantiate(){ | 
|---|
| 146 |         static iserializer instance; | 
|---|
| 147 |         return instance; | 
|---|
| 148 |     } | 
|---|
| 149 |     virtual ~iserializer(){}; | 
|---|
| 150 | }; | 
|---|
| 151 |  | 
|---|
| 152 | template<class Archive, class T> | 
|---|
| 153 | BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data( | 
|---|
| 154 |     basic_iarchive & ar, | 
|---|
| 155 |     void *x,  | 
|---|
| 156 |     const unsigned int file_version | 
|---|
| 157 | ) const { | 
|---|
| 158 |     // make sure call is routed through the higest interface that might | 
|---|
| 159 |     // be specialized by the user. | 
|---|
| 160 |     boost::serialization::serialize_adl( | 
|---|
| 161 |         boost::smart_cast_reference<Archive &>(ar), | 
|---|
| 162 |         * static_cast<T *>(x),  | 
|---|
| 163 |         file_version | 
|---|
| 164 |     ); | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 | // instantiation of this template creates a static object.  Note inversion of | 
|---|
| 168 | // normal argument order to workaround bizarre error in MSVC 6.0 which only | 
|---|
| 169 | // manifests iftself during compiler time. | 
|---|
| 170 | template<class T, class Archive> | 
|---|
| 171 | class pointer_iserializer : public archive_pointer_iserializer<Archive>  | 
|---|
| 172 | { | 
|---|
| 173 | private: | 
|---|
| 174 |     virtual const basic_iserializer & get_basic_serializer() const { | 
|---|
| 175 |         return iserializer<Archive, T>::instantiate(); | 
|---|
| 176 |     } | 
|---|
| 177 |     virtual BOOST_DLLEXPORT void load_object_ptr( | 
|---|
| 178 |         basic_iarchive & ar,  | 
|---|
| 179 |         void * & x, | 
|---|
| 180 |         const unsigned int file_version | 
|---|
| 181 |     ) const BOOST_USED; | 
|---|
| 182 | #if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) ) | 
|---|
| 183 | public: | 
|---|
| 184 | #endif | 
|---|
| 185 |     // private constructor to inhibit any existence other than the  | 
|---|
| 186 |     // static one.  Note GCC doesn't permit constructor to be private | 
|---|
| 187 |     explicit BOOST_DLLEXPORT pointer_iserializer() BOOST_USED; | 
|---|
| 188 |     static const pointer_iserializer instance; | 
|---|
| 189 | public: | 
|---|
| 190 |     // at least one compiler (CW) seems to require that serialize_adl | 
|---|
| 191 |     // be explicitly instantiated. Still under investigation.  | 
|---|
| 192 |     #if !defined(__BORLANDC__) | 
|---|
| 193 |     void (* const m)(Archive &, T &, const unsigned); | 
|---|
| 194 |     boost::serialization::extended_type_info * (* e)(); | 
|---|
| 195 |     #endif | 
|---|
| 196 |     static BOOST_DLLEXPORT const pointer_iserializer & instantiate() BOOST_USED; | 
|---|
| 197 |     virtual ~pointer_iserializer(){}; | 
|---|
| 198 | }; | 
|---|
| 199 |  | 
|---|
| 200 | template<class T, class Archive> | 
|---|
| 201 | BOOST_DLLEXPORT const pointer_iserializer<T, Archive> &  | 
|---|
| 202 | pointer_iserializer<T, Archive>::instantiate() { | 
|---|
| 203 |     return instance; | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 | // note: instances of this template to be constructed before the main | 
|---|
| 207 | // is called in order for things to be initialized properly.  For this | 
|---|
| 208 | // reason, hiding the instance in a static function as was done above | 
|---|
| 209 | // won't work here so we created a free instance here. | 
|---|
| 210 | template<class T, class Archive> | 
|---|
| 211 | const pointer_iserializer<T, Archive> pointer_iserializer<T, Archive>::instance; | 
|---|
| 212 |  | 
|---|
| 213 | // note trick to be sure that operator new is using class specific | 
|---|
| 214 | // version if such exists. Due to Peter Dimov. | 
|---|
| 215 | // note: the following fails if T has no default constructor. | 
|---|
| 216 | // otherwise it would have been ideal | 
|---|
| 217 | //struct heap_allocator : public T  | 
|---|
| 218 | //{ | 
|---|
| 219 | //    T * invoke(){ | 
|---|
| 220 | //        return ::new(sizeof(T)); | 
|---|
| 221 | //    } | 
|---|
| 222 | //} | 
|---|
| 223 |  | 
|---|
| 224 | // note: this should really be a member of the load_ptr function | 
|---|
| 225 | // below but some compilers still complain about this. | 
|---|
| 226 | template<class T> | 
|---|
| 227 | struct heap_allocator | 
|---|
| 228 | { | 
|---|
| 229 |     #if 0 | 
|---|
| 230 |         // note: this fails on msvc 7.0 and gcc 3.2 | 
|---|
| 231 |         template <class U, U x> struct test; | 
|---|
| 232 |         typedef char* yes; | 
|---|
| 233 |         typedef int* no; | 
|---|
| 234 |         template <class U> | 
|---|
| 235 |         yes has_op_new(U*, test<void* (*)(std::size_t), &U::operator new>* = 0); | 
|---|
| 236 |         no has_op_new(...); | 
|---|
| 237 |  | 
|---|
| 238 |         template<class U> | 
|---|
| 239 |         T * new_operator(U); | 
|---|
| 240 |  | 
|---|
| 241 |         T * new_operator(yes){ | 
|---|
| 242 |             return (T::operator new)(sizeof(T)); | 
|---|
| 243 |         } | 
|---|
| 244 |         T * new_operator(no){ | 
|---|
| 245 |             return static_cast<T *>(operator new(sizeof(T))); | 
|---|
| 246 |         } | 
|---|
| 247 |         static T * invoke(){ | 
|---|
| 248 |             return new_operator(has_op_new(static_cast<T *>(NULL))); | 
|---|
| 249 |         } | 
|---|
| 250 |     #else | 
|---|
| 251 |         // while this doesn't handle operator new overload for class T | 
|---|
| 252 |         static T * invoke(){ | 
|---|
| 253 |             return static_cast<T *>(operator new(sizeof(T))); | 
|---|
| 254 |         } | 
|---|
| 255 |     #endif | 
|---|
| 256 | }; | 
|---|
| 257 |  | 
|---|
| 258 | // due to Martin Ecker | 
|---|
| 259 | template <typename T> | 
|---|
| 260 | class auto_ptr_with_deleter | 
|---|
| 261 | { | 
|---|
| 262 | public: | 
|---|
| 263 |     explicit auto_ptr_with_deleter(T* p) : | 
|---|
| 264 |         m_p(p) | 
|---|
| 265 |     {} | 
|---|
| 266 |     ~auto_ptr_with_deleter(){ | 
|---|
| 267 |         if (m_p) | 
|---|
| 268 |             boost::serialization::access::destroy(m_p); | 
|---|
| 269 |     } | 
|---|
| 270 |     T* get() const { | 
|---|
| 271 |         return m_p; | 
|---|
| 272 |     } | 
|---|
| 273 |  | 
|---|
| 274 |     T* release() { | 
|---|
| 275 |         T* p = m_p; | 
|---|
| 276 |         m_p = NULL; | 
|---|
| 277 |         return p; | 
|---|
| 278 |     } | 
|---|
| 279 | private: | 
|---|
| 280 |     T* m_p; | 
|---|
| 281 | }; | 
|---|
| 282 |  | 
|---|
| 283 | template<class T, class Archive> | 
|---|
| 284 | BOOST_DLLEXPORT void pointer_iserializer<T, Archive>::load_object_ptr( | 
|---|
| 285 |     basic_iarchive & ar,  | 
|---|
| 286 |     void * & x, | 
|---|
| 287 |     const unsigned int file_version | 
|---|
| 288 | ) const { | 
|---|
| 289 |     Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar); | 
|---|
| 290 |  | 
|---|
| 291 | //    if(0 != (ar.get_flags() & no_object_creation)){ | 
|---|
| 292 | //        ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(x)); | 
|---|
| 293 | //        return; | 
|---|
| 294 | //    } | 
|---|
| 295 |  | 
|---|
| 296 |     auto_ptr_with_deleter<T> ap(heap_allocator<T>::invoke()); | 
|---|
| 297 |     if(NULL == ap.get()) | 
|---|
| 298 |         boost::throw_exception(std::bad_alloc()) ; | 
|---|
| 299 |  | 
|---|
| 300 |     T * t = ap.get(); | 
|---|
| 301 |     x = t; | 
|---|
| 302 |  | 
|---|
| 303 |     // catch exception during load_construct_data so that we don't | 
|---|
| 304 |     // automatically delete the t which is most likely not fully | 
|---|
| 305 |     // constructed | 
|---|
| 306 |     BOOST_TRY { | 
|---|
| 307 |         // this addresses an obscure situtation that occurs when  | 
|---|
| 308 |         // load_constructor de-serializes something through a pointer. | 
|---|
| 309 |         ar.next_object_pointer(t); | 
|---|
| 310 |         boost::serialization::load_construct_data_adl<Archive, T>( | 
|---|
| 311 |             ar_impl, | 
|---|
| 312 |             t,  | 
|---|
| 313 |             file_version | 
|---|
| 314 |         ); | 
|---|
| 315 |     } | 
|---|
| 316 |     BOOST_CATCH(...){ | 
|---|
| 317 |         BOOST_RETHROW; | 
|---|
| 318 |     } | 
|---|
| 319 |     BOOST_CATCH_END | 
|---|
| 320 |  | 
|---|
| 321 |     ar_impl >> boost::serialization::make_nvp(NULL, * t); | 
|---|
| 322 |     ap.release(); | 
|---|
| 323 | } | 
|---|
| 324 |  | 
|---|
| 325 | template<class T, class Archive> | 
|---|
| 326 | #if !defined(__BORLANDC__) | 
|---|
| 327 | BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() : | 
|---|
| 328 |     archive_pointer_iserializer<Archive>( | 
|---|
| 329 |         * boost::serialization::type_info_implementation<T>::type::get_instance() | 
|---|
| 330 |     ), | 
|---|
| 331 |     m(boost::serialization::serialize_adl<Archive, T>), | 
|---|
| 332 |     e(boost::serialization::type_info_implementation<T>::type::get_instance) | 
|---|
| 333 | #else | 
|---|
| 334 | BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() : | 
|---|
| 335 |     archive_pointer_iserializer<Archive>( | 
|---|
| 336 |         * boost::serialization::type_info_implementation<T>::type::get_instance() | 
|---|
| 337 |     ) | 
|---|
| 338 | #endif | 
|---|
| 339 | { | 
|---|
| 340 |     iserializer<Archive, T> & bis = iserializer<Archive, T>::instantiate(); | 
|---|
| 341 |     bis.set_bpis(this); | 
|---|
| 342 | } | 
|---|
| 343 |  | 
|---|
| 344 | template<class Archive, class T> | 
|---|
| 345 | struct load_non_pointer_type { | 
|---|
| 346 |     // note this bounces the call right back to the archive | 
|---|
| 347 |     // with no runtime overhead | 
|---|
| 348 |     struct load_primitive { | 
|---|
| 349 |         static void invoke(Archive & ar, T & t){ | 
|---|
| 350 |             load_access::load_primitive(ar, t); | 
|---|
| 351 |         } | 
|---|
| 352 |     }; | 
|---|
| 353 |     // note this bounces the call right back to the archive | 
|---|
| 354 |     // with no runtime overhead | 
|---|
| 355 |     struct load_only { | 
|---|
| 356 |         static void invoke(Archive & ar, T & t){ | 
|---|
| 357 |             // short cut to user's serializer | 
|---|
| 358 |             // make sure call is routed through the higest interface that might | 
|---|
| 359 |             // be specialized by the user. | 
|---|
| 360 |             boost::serialization::serialize_adl( | 
|---|
| 361 |                 ar, t, boost::serialization::version<T>::value | 
|---|
| 362 |             ); | 
|---|
| 363 |         } | 
|---|
| 364 |     }; | 
|---|
| 365 |  | 
|---|
| 366 |     // note this save class information including version | 
|---|
| 367 |     // and serialization level to the archive | 
|---|
| 368 |     struct load_standard { | 
|---|
| 369 |         static void invoke(Archive &ar, T &t){ | 
|---|
| 370 |             //BOOST_STATIC_ASSERT(! boost::is_const<T>::value); | 
|---|
| 371 |             // borland - for some reason T is const here - even though | 
|---|
| 372 |             // its not called that way - so fix it her | 
|---|
| 373 |             typedef BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type typex; | 
|---|
| 374 |             void * x = & const_cast<typex &>(t); | 
|---|
| 375 |             ar.load_object(x, iserializer<Archive, T>::instantiate()); | 
|---|
| 376 |         } | 
|---|
| 377 |     }; | 
|---|
| 378 |  | 
|---|
| 379 |     struct load_conditional { | 
|---|
| 380 |         static void invoke(Archive &ar, T &t){ | 
|---|
| 381 |             //if(0 == (ar.get_flags() & no_tracking)) | 
|---|
| 382 |                 load_standard::invoke(ar, t); | 
|---|
| 383 |             //else | 
|---|
| 384 |             //    load_only::invoke(ar, t); | 
|---|
| 385 |         } | 
|---|
| 386 |     }; | 
|---|
| 387 |  | 
|---|
| 388 |     typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 389 |             // if its primitive | 
|---|
| 390 |             mpl::equal_to< | 
|---|
| 391 |                 boost::serialization::implementation_level<T>, | 
|---|
| 392 |                 mpl::int_<boost::serialization::primitive_type> | 
|---|
| 393 |             >, | 
|---|
| 394 |             mpl::identity<load_primitive>, | 
|---|
| 395 |         // else | 
|---|
| 396 |         BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 397 |         // class info / version | 
|---|
| 398 |         mpl::greater_equal< | 
|---|
| 399 |                     boost::serialization::implementation_level<T>, | 
|---|
| 400 |                     mpl::int_<boost::serialization::object_class_info> | 
|---|
| 401 |                 >, | 
|---|
| 402 |         // do standard load | 
|---|
| 403 |         mpl::identity<load_standard>, | 
|---|
| 404 |     // else | 
|---|
| 405 |     BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 406 |         // no tracking | 
|---|
| 407 |                 mpl::equal_to< | 
|---|
| 408 |                     boost::serialization::tracking_level<T>, | 
|---|
| 409 |                     mpl::int_<boost::serialization::track_never> | 
|---|
| 410 |             >, | 
|---|
| 411 |             // do a fast load | 
|---|
| 412 |             mpl::identity<load_only>, | 
|---|
| 413 |         // else | 
|---|
| 414 |         // do a fast load only tracking is turned off | 
|---|
| 415 |         mpl::identity<load_conditional> | 
|---|
| 416 |     > > >::type typex; | 
|---|
| 417 |  | 
|---|
| 418 |     static void invoke(Archive & ar, T &t){ | 
|---|
| 419 |         BOOST_STATIC_ASSERT(( | 
|---|
| 420 |             mpl::greater_equal< | 
|---|
| 421 |                 boost::serialization::implementation_level<T>,  | 
|---|
| 422 |                 mpl::int_<boost::serialization::primitive_type> | 
|---|
| 423 |             >::value | 
|---|
| 424 |         )); | 
|---|
| 425 |         typex::invoke(ar, t); | 
|---|
| 426 |     } | 
|---|
| 427 | }; | 
|---|
| 428 |  | 
|---|
| 429 | template<class Archive, class Tptr> | 
|---|
| 430 | struct load_pointer_type { | 
|---|
| 431 |     template<class T> | 
|---|
| 432 |     struct abstract | 
|---|
| 433 |     { | 
|---|
| 434 |         static const basic_pointer_iserializer * register_type(Archive & /* ar */){ | 
|---|
| 435 |             #if ! defined(__BORLANDC__) | 
|---|
| 436 |             typedef BOOST_DEDUCED_TYPENAME  | 
|---|
| 437 |                 boost::serialization::type_info_implementation<T>::type::is_polymorphic typex; | 
|---|
| 438 |             // it has? to be polymorphic | 
|---|
| 439 |             BOOST_STATIC_ASSERT(typex::value); | 
|---|
| 440 |             #endif | 
|---|
| 441 |             return static_cast<basic_pointer_iserializer *>(NULL); | 
|---|
| 442 |          } | 
|---|
| 443 |     }; | 
|---|
| 444 |  | 
|---|
| 445 |     template<class T> | 
|---|
| 446 |     struct non_abstract | 
|---|
| 447 |     { | 
|---|
| 448 |         static const basic_pointer_iserializer * register_type(Archive & ar){ | 
|---|
| 449 |             return ar.register_type(static_cast<T *>(NULL)); | 
|---|
| 450 |         } | 
|---|
| 451 |     }; | 
|---|
| 452 |  | 
|---|
| 453 |     template<class T> | 
|---|
| 454 |     static const basic_pointer_iserializer * register_type(Archive &ar, T & /*t*/){ | 
|---|
| 455 |         // there should never be any need to load an abstract polymorphic  | 
|---|
| 456 |         // class pointer.  Inhibiting code generation for this | 
|---|
| 457 |         // permits abstract base classes to be used - note: exception | 
|---|
| 458 |         // virtual serialize functions used for plug-ins | 
|---|
| 459 |         typedef BOOST_DEDUCED_TYPENAME | 
|---|
| 460 |             mpl::eval_if< | 
|---|
| 461 |                 serialization::is_abstract<T>, | 
|---|
| 462 |                 mpl::identity<abstract<T> >, | 
|---|
| 463 |                 mpl::identity<non_abstract<T> >     | 
|---|
| 464 |             >::type typex; | 
|---|
| 465 |         return typex::register_type(ar); | 
|---|
| 466 |     } | 
|---|
| 467 |  | 
|---|
| 468 |     template<class T> | 
|---|
| 469 |     static T * pointer_tweak( | 
|---|
| 470 |         const boost::serialization::extended_type_info & eti, | 
|---|
| 471 |         void * t, | 
|---|
| 472 |         T & | 
|---|
| 473 |     ) { | 
|---|
| 474 |         // tweak the pointer back to the base class | 
|---|
| 475 |         return static_cast<T *>( | 
|---|
| 476 |             boost::serialization::void_upcast( | 
|---|
| 477 |                 eti, | 
|---|
| 478 |                 * boost::serialization::type_info_implementation<T>::type::get_instance(), | 
|---|
| 479 |                 t | 
|---|
| 480 |             ) | 
|---|
| 481 |         ); | 
|---|
| 482 |     } | 
|---|
| 483 |  | 
|---|
| 484 |     static void invoke(Archive & ar, Tptr & t){ | 
|---|
| 485 |         const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t); | 
|---|
| 486 |         const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer( | 
|---|
| 487 |             * reinterpret_cast<void **>(&t), | 
|---|
| 488 |             bpis_ptr, | 
|---|
| 489 |             archive_pointer_iserializer<Archive>::find | 
|---|
| 490 |         ); | 
|---|
| 491 |         // if the pointer isn't that of the base class | 
|---|
| 492 |         if(newbpis_ptr != bpis_ptr){ | 
|---|
| 493 |             t = pointer_tweak(newbpis_ptr->get_eti(), t, *t); | 
|---|
| 494 |         } | 
|---|
| 495 |     } | 
|---|
| 496 | }; | 
|---|
| 497 |  | 
|---|
| 498 | template<class Archive, class T> | 
|---|
| 499 | struct load_enum_type { | 
|---|
| 500 |     static void invoke(Archive &ar, T &t){ | 
|---|
| 501 |         // convert integers to correct enum to load | 
|---|
| 502 |         int i; | 
|---|
| 503 |         ar >> boost::serialization::make_nvp(NULL, i); | 
|---|
| 504 |         t = static_cast<T>(i); | 
|---|
| 505 |     } | 
|---|
| 506 | }; | 
|---|
| 507 |  | 
|---|
| 508 | template<class Archive, class T> | 
|---|
| 509 | struct load_array_type { | 
|---|
| 510 |     static void invoke(Archive &ar, T &t){ | 
|---|
| 511 |         // convert integers to correct enum to load | 
|---|
| 512 |         int current_count = sizeof(t) / ( | 
|---|
| 513 |             static_cast<char *>(static_cast<void *>(&t[1]))  | 
|---|
| 514 |             - static_cast<char *>(static_cast<void *>(&t[0])) | 
|---|
| 515 |         ); | 
|---|
| 516 |         int count; | 
|---|
| 517 |         ar >> BOOST_SERIALIZATION_NVP(count); | 
|---|
| 518 |         if(count > current_count) | 
|---|
| 519 |             boost::throw_exception(archive::archive_exception( | 
|---|
| 520 |                 boost::archive::archive_exception::array_size_too_short | 
|---|
| 521 |             )); | 
|---|
| 522 |         int i; | 
|---|
| 523 |         for(i = 0; i < count; ++i) | 
|---|
| 524 |             ar >> boost::serialization::make_nvp("item", t[i]); | 
|---|
| 525 |     } | 
|---|
| 526 | }; | 
|---|
| 527 |  | 
|---|
| 528 | // note bogus arguments to workaround msvc 6 silent runtime failure | 
|---|
| 529 | template<class Archive, class T> | 
|---|
| 530 | BOOST_DLLEXPORT  | 
|---|
| 531 | inline const basic_pointer_iserializer & | 
|---|
| 532 | instantiate_pointer_iserializer( | 
|---|
| 533 |     Archive * /* ar = NULL */, | 
|---|
| 534 |     T * /* t = NULL */ | 
|---|
| 535 | ) BOOST_USED; | 
|---|
| 536 |  | 
|---|
| 537 | template<class Archive, class T> | 
|---|
| 538 | BOOST_DLLEXPORT  | 
|---|
| 539 | inline const basic_pointer_iserializer & | 
|---|
| 540 | instantiate_pointer_iserializer( | 
|---|
| 541 |     Archive * /* ar = NULL */, | 
|---|
| 542 |     T * /* t = NULL */ | 
|---|
| 543 | ){ | 
|---|
| 544 |     // note: reversal of order of arguments to work around msvc 6.0 bug | 
|---|
| 545 |     // that manifests itself while trying to link. | 
|---|
| 546 |     return pointer_iserializer<T, Archive>::instantiate(); | 
|---|
| 547 | } | 
|---|
| 548 |  | 
|---|
| 549 | } // detail | 
|---|
| 550 |  | 
|---|
| 551 | template<class Archive, class T> | 
|---|
| 552 | inline void load(Archive &ar, T &t){ | 
|---|
| 553 |     // if this assertion trips. It means we're trying to load a | 
|---|
| 554 |     // const object with a compiler that doesn't have correct | 
|---|
| 555 |     // funtion template ordering.  On other compilers, this is | 
|---|
| 556 |     // handled below. | 
|---|
| 557 |     BOOST_STATIC_ASSERT(! boost::is_const<T>::value); | 
|---|
| 558 |     typedef | 
|---|
| 559 |         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>, | 
|---|
| 560 |             mpl::identity<detail::load_pointer_type<Archive, T> > | 
|---|
| 561 |         ,//else | 
|---|
| 562 |         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>, | 
|---|
| 563 |             mpl::identity<detail::load_array_type<Archive, T> > | 
|---|
| 564 |         ,//else | 
|---|
| 565 |         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>, | 
|---|
| 566 |             mpl::identity<detail::load_enum_type<Archive, T> > | 
|---|
| 567 |         ,//else | 
|---|
| 568 |             mpl::identity<detail::load_non_pointer_type<Archive, T> > | 
|---|
| 569 |         > | 
|---|
| 570 |         > | 
|---|
| 571 |         >::type typex; | 
|---|
| 572 |     typex::invoke(ar, t); | 
|---|
| 573 | } | 
|---|
| 574 |  | 
|---|
| 575 | // BORLAND | 
|---|
| 576 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) | 
|---|
| 577 | // borland has a couple fo problems | 
|---|
| 578 | // a) if function is partiall specialized - see below | 
|---|
| 579 | // const paramters are transformed to non-const ones | 
|---|
| 580 | // b) implementation of base_object can't be made to work | 
|---|
| 581 | // correctly which results in all base_object s being const. | 
|---|
| 582 | // So, strip off the const for borland.  This breaks the trap | 
|---|
| 583 | // for loading const objects - but I see no alternative | 
|---|
| 584 | template<class Archive, class T> | 
|---|
| 585 | inline void load(Archive &ar, const T & t){ | 
|---|
| 586 |         load(ar, const_cast<T &>(t)); | 
|---|
| 587 | } | 
|---|
| 588 | #endif | 
|---|
| 589 |  | 
|---|
| 590 | // let wrappers through.  (Someday implement is_wrapper) | 
|---|
| 591 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING | 
|---|
| 592 | template<class Archive, class T> | 
|---|
| 593 | inline void load(Archive &ar, const serialization::nvp<T> &t){ | 
|---|
| 594 |         boost::archive::load(ar, const_cast<serialization::nvp<T> &>(t)); | 
|---|
| 595 | } | 
|---|
| 596 | template<class Archive> | 
|---|
| 597 | inline void load(Archive &ar, const serialization::binary_object &t){ | 
|---|
| 598 |         boost::archive::load(ar, const_cast<serialization::binary_object &>(t)); | 
|---|
| 599 | } | 
|---|
| 600 |  | 
|---|
| 601 | //template<class Archive, class T> | 
|---|
| 602 | //inline void load(Archive &ar, const serialization::binary_object &t){ | 
|---|
| 603 | //      load(ar, const_cast<binary_object &>(t)); | 
|---|
| 604 | //} | 
|---|
| 605 | #endif | 
|---|
| 606 |  | 
|---|
| 607 | } // namespace archive | 
|---|
| 608 | } // namespace boost | 
|---|
| 609 |  | 
|---|
| 610 | #endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP | 
|---|