| 1 | #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP | 
|---|
| 2 | #define BOOST_ARCHIVE_OSERIALIZER_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 | // oserializer.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 <cassert> | 
|---|
| 26 |  | 
|---|
| 27 | #include <boost/config.hpp> | 
|---|
| 28 | #include <boost/detail/workaround.hpp> | 
|---|
| 29 | #include <boost/throw_exception.hpp> | 
|---|
| 30 | #include <boost/smart_cast.hpp> | 
|---|
| 31 | #include <boost/static_assert.hpp> | 
|---|
| 32 | #include <boost/static_warning.hpp> | 
|---|
| 33 |  | 
|---|
| 34 | #include <boost/type_traits/is_pointer.hpp> | 
|---|
| 35 | #include <boost/type_traits/is_fundamental.hpp> | 
|---|
| 36 | #include <boost/type_traits/is_enum.hpp> | 
|---|
| 37 | #include <boost/type_traits/is_volatile.hpp> | 
|---|
| 38 | #include <boost/type_traits/is_const.hpp> | 
|---|
| 39 | #include <boost/type_traits/is_same.hpp> | 
|---|
| 40 | #include <boost/serialization/is_abstract.hpp> | 
|---|
| 41 |  | 
|---|
| 42 | #include <boost/mpl/eval_if.hpp> | 
|---|
| 43 | #include <boost/mpl/and.hpp> | 
|---|
| 44 | #include <boost/mpl/less.hpp> | 
|---|
| 45 | #include <boost/mpl/greater_equal.hpp> | 
|---|
| 46 | #include <boost/mpl/equal_to.hpp> | 
|---|
| 47 | #include <boost/mpl/int.hpp> | 
|---|
| 48 | #include <boost/mpl/identity.hpp> | 
|---|
| 49 | #include <boost/mpl/list.hpp> | 
|---|
| 50 | #include <boost/mpl/empty.hpp> | 
|---|
| 51 | #include <boost/mpl/not.hpp> | 
|---|
| 52 |  | 
|---|
| 53 | #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO | 
|---|
| 54 |     #include <boost/serialization/extended_type_info_typeid.hpp> | 
|---|
| 55 | #endif | 
|---|
| 56 |  | 
|---|
| 57 | // the following is need only for dynamic cast of polymorphic pointers | 
|---|
| 58 | #include <boost/archive/detail/basic_oarchive.hpp> | 
|---|
| 59 | #include <boost/archive/detail/basic_oserializer.hpp> | 
|---|
| 60 | #include <boost/archive/detail/archive_pointer_oserializer.hpp> | 
|---|
| 61 |  | 
|---|
| 62 | #include <boost/serialization/force_include.hpp> | 
|---|
| 63 | #include <boost/serialization/serialization.hpp> | 
|---|
| 64 | #include <boost/serialization/version.hpp> | 
|---|
| 65 | #include <boost/serialization/level.hpp> | 
|---|
| 66 | #include <boost/serialization/tracking.hpp> | 
|---|
| 67 | #include <boost/serialization/type_info_implementation.hpp> | 
|---|
| 68 | #include <boost/serialization/nvp.hpp> | 
|---|
| 69 | #include <boost/serialization/void_cast.hpp> | 
|---|
| 70 |  | 
|---|
| 71 | #include <boost/archive/archive_exception.hpp> | 
|---|
| 72 |  | 
|---|
| 73 | namespace boost { | 
|---|
| 74 |  | 
|---|
| 75 | namespace serialization { | 
|---|
| 76 |     class extended_type_info; | 
|---|
| 77 | } // namespace serialization | 
|---|
| 78 |  | 
|---|
| 79 | namespace archive { | 
|---|
| 80 |  | 
|---|
| 81 | // an accessor to permit friend access to archives.  Needed because | 
|---|
| 82 | // some compilers don't handle friend templates completely | 
|---|
| 83 | class save_access { | 
|---|
| 84 | public: | 
|---|
| 85 |     template<class Archive> | 
|---|
| 86 |     static void end_preamble(Archive & ar){ | 
|---|
| 87 |         ar.end_preamble(); | 
|---|
| 88 |     } | 
|---|
| 89 |     template<class Archive, class T> | 
|---|
| 90 |     static void save_primitive(Archive & ar, const  T & t){ | 
|---|
| 91 |         ar.end_preamble(); | 
|---|
| 92 |         ar.save(t); | 
|---|
| 93 |     } | 
|---|
| 94 | }; | 
|---|
| 95 |  | 
|---|
| 96 | namespace detail { | 
|---|
| 97 |  | 
|---|
| 98 | template<class Archive, class T> | 
|---|
| 99 | class oserializer : public basic_oserializer | 
|---|
| 100 | { | 
|---|
| 101 | private: | 
|---|
| 102 |     // private constructor to inhibit any existence other than the  | 
|---|
| 103 |     // static one | 
|---|
| 104 |     explicit oserializer() : | 
|---|
| 105 |         basic_oserializer( | 
|---|
| 106 |             * boost::serialization::type_info_implementation<T>::type::get_instance() | 
|---|
| 107 |         ) | 
|---|
| 108 |     {} | 
|---|
| 109 | public: | 
|---|
| 110 |     virtual BOOST_DLLEXPORT void save_object_data( | 
|---|
| 111 |         basic_oarchive & ar,     | 
|---|
| 112 |         const void *x | 
|---|
| 113 |     ) const BOOST_USED ; | 
|---|
| 114 |     virtual bool class_info() const { | 
|---|
| 115 |         return boost::serialization::implementation_level<T>::value  | 
|---|
| 116 |             >= boost::serialization::object_class_info; | 
|---|
| 117 |     } | 
|---|
| 118 |     virtual bool tracking(const unsigned int flags) const { | 
|---|
| 119 | //        if(0 != (flags &  no_tracking)) | 
|---|
| 120 | //            return false; | 
|---|
| 121 |         return boost::serialization::tracking_level<T>::value == boost::serialization::track_always | 
|---|
| 122 |             || boost::serialization::tracking_level<T>::value == boost::serialization::track_selectivly | 
|---|
| 123 |             && serialized_as_pointer(); | 
|---|
| 124 |     } | 
|---|
| 125 |     virtual unsigned int version() const { | 
|---|
| 126 |         return ::boost::serialization::version<T>::value; | 
|---|
| 127 |     } | 
|---|
| 128 |     virtual bool is_polymorphic() const { | 
|---|
| 129 |         typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation< | 
|---|
| 130 |             T | 
|---|
| 131 |         >::type::is_polymorphic::type typex; | 
|---|
| 132 |         return typex::value; | 
|---|
| 133 |     } | 
|---|
| 134 |     static oserializer & instantiate(){ | 
|---|
| 135 |         static oserializer instance; | 
|---|
| 136 |         return instance; | 
|---|
| 137 |     } | 
|---|
| 138 |     virtual ~oserializer(){} | 
|---|
| 139 | }; | 
|---|
| 140 |  | 
|---|
| 141 | template<class Archive, class T> | 
|---|
| 142 | BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data( | 
|---|
| 143 |     basic_oarchive & ar,     | 
|---|
| 144 |     const void *x | 
|---|
| 145 | ) const { | 
|---|
| 146 |     // make sure call is routed through the highest interface that might | 
|---|
| 147 |     // be specialized by the user. | 
|---|
| 148 |     boost::serialization::serialize_adl( | 
|---|
| 149 |         boost::smart_cast_reference<Archive &>(ar), | 
|---|
| 150 |         * static_cast<T *>(const_cast<void *>(x)), | 
|---|
| 151 |         version() | 
|---|
| 152 |     ); | 
|---|
| 153 | } | 
|---|
| 154 |  | 
|---|
| 155 | // instantiation of this template creates a static object.  Note inversion of | 
|---|
| 156 | // normal argument order to workaround bizarre error in MSVC 6.0 which only | 
|---|
| 157 | // manifests iftself during compiler time. | 
|---|
| 158 | template<class T, class Archive> | 
|---|
| 159 | class pointer_oserializer : public archive_pointer_oserializer<Archive>  | 
|---|
| 160 | { | 
|---|
| 161 | private: | 
|---|
| 162 |     virtual const basic_oserializer & get_basic_serializer() const { | 
|---|
| 163 |         return oserializer<Archive, T>::instantiate(); | 
|---|
| 164 |     } | 
|---|
| 165 |     virtual BOOST_DLLEXPORT void save_object_ptr( | 
|---|
| 166 |         basic_oarchive & ar, | 
|---|
| 167 |         const void * x | 
|---|
| 168 |     ) const BOOST_USED ; | 
|---|
| 169 | #if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) ) | 
|---|
| 170 | public: | 
|---|
| 171 | #endif | 
|---|
| 172 |     // private constructor to inhibit any existence other than the  | 
|---|
| 173 |     // static one.  Note GCC doesn't permit constructor to be private | 
|---|
| 174 |     explicit BOOST_DLLEXPORT pointer_oserializer() BOOST_USED; | 
|---|
| 175 |     static const pointer_oserializer instance; | 
|---|
| 176 | public: | 
|---|
| 177 |     #if !defined(__BORLANDC__) | 
|---|
| 178 |     // at least one compiler (CW) seems to require that serialize_adl | 
|---|
| 179 |     // be explicitly instantiated. Still under investigation.  | 
|---|
| 180 |     void (* const m)(Archive &, T &, const unsigned); | 
|---|
| 181 |     boost::serialization::extended_type_info * (* e)(); | 
|---|
| 182 |     #endif | 
|---|
| 183 |     static BOOST_DLLEXPORT const pointer_oserializer & instantiate() BOOST_USED; | 
|---|
| 184 |     virtual ~pointer_oserializer(){} | 
|---|
| 185 | }; | 
|---|
| 186 |  | 
|---|
| 187 | template<class T, class Archive> | 
|---|
| 188 | BOOST_DLLEXPORT const pointer_oserializer<T, Archive> &  | 
|---|
| 189 | pointer_oserializer<T, Archive>::instantiate(){ | 
|---|
| 190 |     return instance; | 
|---|
| 191 | } | 
|---|
| 192 |  | 
|---|
| 193 | // note: instances of this template to be constructed before the main | 
|---|
| 194 | // is called in order for things to be initialized properly.  For this | 
|---|
| 195 | // reason, hiding the instance in a static function as was done above | 
|---|
| 196 | // won't work here so we created a free instance here. | 
|---|
| 197 | template<class T, class Archive> | 
|---|
| 198 | const pointer_oserializer<T, Archive> pointer_oserializer<T, Archive>::instance; | 
|---|
| 199 |  | 
|---|
| 200 | template<class T, class Archive> | 
|---|
| 201 | BOOST_DLLEXPORT void pointer_oserializer<T, Archive>::save_object_ptr( | 
|---|
| 202 |     basic_oarchive & ar, | 
|---|
| 203 |     const void * x | 
|---|
| 204 | ) const { | 
|---|
| 205 |     assert(NULL != x); | 
|---|
| 206 |     // make sure call is routed through the highest interface that might | 
|---|
| 207 |     // be specialized by the user. | 
|---|
| 208 |     T * t = static_cast<T *>(const_cast<void *>(x)); | 
|---|
| 209 |     const unsigned int file_version = boost::serialization::version<T>::value; | 
|---|
| 210 |     Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar); | 
|---|
| 211 |     boost::serialization::save_construct_data_adl<Archive, T>( | 
|---|
| 212 |         ar_impl,  | 
|---|
| 213 |         t,  | 
|---|
| 214 |         file_version | 
|---|
| 215 |     ); | 
|---|
| 216 |     ar_impl << boost::serialization::make_nvp(NULL, * t); | 
|---|
| 217 | } | 
|---|
| 218 |  | 
|---|
| 219 | template<class T, class Archive> | 
|---|
| 220 | #if !defined(__BORLANDC__) | 
|---|
| 221 | BOOST_DLLEXPORT pointer_oserializer<T, Archive>::pointer_oserializer() : | 
|---|
| 222 |     archive_pointer_oserializer<Archive>( | 
|---|
| 223 |         * boost::serialization::type_info_implementation<T>::type::get_instance() | 
|---|
| 224 |     ), | 
|---|
| 225 |     m(boost::serialization::serialize_adl<Archive, T>), | 
|---|
| 226 |     e(boost::serialization::type_info_implementation<T>::type::get_instance) | 
|---|
| 227 | #else | 
|---|
| 228 | BOOST_DLLEXPORT pointer_oserializer<T, Archive>::pointer_oserializer() : | 
|---|
| 229 |     archive_pointer_oserializer<Archive>( | 
|---|
| 230 |         * boost::serialization::type_info_implementation<T>::type::get_instance() | 
|---|
| 231 |     ) | 
|---|
| 232 | #endif | 
|---|
| 233 | { | 
|---|
| 234 |     // make sure appropriate member function is instantiated | 
|---|
| 235 |     oserializer<Archive, T> & bos = oserializer<Archive, T>::instantiate(); | 
|---|
| 236 |     bos.set_bpos(this); | 
|---|
| 237 | } | 
|---|
| 238 |  | 
|---|
| 239 | template<class Archive, class T> | 
|---|
| 240 | struct save_non_pointer_type { | 
|---|
| 241 |     // note this bounces the call right back to the archive | 
|---|
| 242 |     // with no runtime overhead | 
|---|
| 243 |     struct save_primitive { | 
|---|
| 244 |         static void invoke(Archive & ar, const T & t){ | 
|---|
| 245 |             save_access::save_primitive(ar, t); | 
|---|
| 246 |         } | 
|---|
| 247 |     }; | 
|---|
| 248 |     // same as above but passes through serialization | 
|---|
| 249 |     struct save_only { | 
|---|
| 250 |         static void invoke(Archive & ar, const T & t){ | 
|---|
| 251 |             // make sure call is routed through the highest interface that might | 
|---|
| 252 |             // be specialized by the user. | 
|---|
| 253 |             boost::serialization::serialize_adl( | 
|---|
| 254 |                 ar,  | 
|---|
| 255 |                 const_cast<T &>(t),  | 
|---|
| 256 |                 ::boost::serialization::version<T>::value | 
|---|
| 257 |             ); | 
|---|
| 258 |         } | 
|---|
| 259 |     }; | 
|---|
| 260 |     // adds class information to the archive. This includes | 
|---|
| 261 |     // serialization level and class version | 
|---|
| 262 |     struct save_standard { | 
|---|
| 263 |         static void invoke(Archive &ar, const T & t){ | 
|---|
| 264 |             ar.save_object(& t, oserializer<Archive, T>::instantiate()); | 
|---|
| 265 |         } | 
|---|
| 266 |     }; | 
|---|
| 267 |  | 
|---|
| 268 |     // adds class information to the archive. This includes | 
|---|
| 269 |     // serialization level and class version | 
|---|
| 270 |     struct save_conditional { | 
|---|
| 271 |         static void invoke(Archive &ar, const T &t){ | 
|---|
| 272 |             //if(0 == (ar.get_flags() & no_tracking)) | 
|---|
| 273 |                 save_standard::invoke(ar, t); | 
|---|
| 274 |             //else | 
|---|
| 275 |             //   save_only::invoke(ar, t); | 
|---|
| 276 |         } | 
|---|
| 277 |     }; | 
|---|
| 278 |  | 
|---|
| 279 |     typedef  | 
|---|
| 280 |         BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 281 |         // if its primitive | 
|---|
| 282 |             mpl::equal_to< | 
|---|
| 283 |                 boost::serialization::implementation_level<T>, | 
|---|
| 284 |                 mpl::int_<boost::serialization::primitive_type> | 
|---|
| 285 |             >, | 
|---|
| 286 |             mpl::identity<save_primitive>, | 
|---|
| 287 |         // else | 
|---|
| 288 |         BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 289 |             // class info / version | 
|---|
| 290 |             mpl::greater_equal< | 
|---|
| 291 |                 boost::serialization::implementation_level<T>, | 
|---|
| 292 |                 mpl::int_<boost::serialization::object_class_info> | 
|---|
| 293 |             >, | 
|---|
| 294 |             // do standard save | 
|---|
| 295 |             mpl::identity<save_standard>, | 
|---|
| 296 |         // else | 
|---|
| 297 |         BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 298 |                 // no tracking | 
|---|
| 299 |             mpl::equal_to< | 
|---|
| 300 |                 boost::serialization::tracking_level<T>, | 
|---|
| 301 |                 mpl::int_<boost::serialization::track_never> | 
|---|
| 302 |             >, | 
|---|
| 303 |             // do a fast save | 
|---|
| 304 |             mpl::identity<save_only>, | 
|---|
| 305 |         // else | 
|---|
| 306 |             // do a fast save only tracking is turned off | 
|---|
| 307 |             mpl::identity<save_conditional> | 
|---|
| 308 |     > > >::type typex;  | 
|---|
| 309 |  | 
|---|
| 310 |     static void invoke(Archive & ar, const T & t){ | 
|---|
| 311 |         // check that we're not trying to serialize something that | 
|---|
| 312 |         // has been marked not to be serialized.  If this your program | 
|---|
| 313 |         // traps here, you've tried to serialize a class whose trait | 
|---|
| 314 |         // has been marked "non-serializable". Either reset the trait | 
|---|
| 315 |         // (see level.hpp) or change program not to serialize items of this class | 
|---|
| 316 |         BOOST_STATIC_ASSERT(( | 
|---|
| 317 |             mpl::greater_equal< | 
|---|
| 318 |                 boost::serialization::implementation_level<T>,  | 
|---|
| 319 |                 mpl::int_<boost::serialization::primitive_type> | 
|---|
| 320 |             >::value | 
|---|
| 321 |         )); | 
|---|
| 322 |         typex::invoke(ar, t); | 
|---|
| 323 |     }; | 
|---|
| 324 | }; | 
|---|
| 325 |  | 
|---|
| 326 | template<class Archive, class TPtr> | 
|---|
| 327 | struct save_pointer_type { | 
|---|
| 328 |     template<class T> | 
|---|
| 329 |     struct abstract | 
|---|
| 330 |     { | 
|---|
| 331 |         static const basic_pointer_oserializer * register_type(Archive & /* ar */){ | 
|---|
| 332 |             // it has? to be polymorphic | 
|---|
| 333 |             BOOST_STATIC_ASSERT( | 
|---|
| 334 |                 boost::serialization::type_info_implementation<T>::type::is_polymorphic::value | 
|---|
| 335 |             ); | 
|---|
| 336 |             return static_cast<const basic_pointer_oserializer *>(NULL); | 
|---|
| 337 |         } | 
|---|
| 338 |     }; | 
|---|
| 339 |  | 
|---|
| 340 |     template<class T> | 
|---|
| 341 |     struct non_abstract | 
|---|
| 342 |     { | 
|---|
| 343 |         static const basic_pointer_oserializer * register_type(Archive & ar){ | 
|---|
| 344 |             return ar.register_type(static_cast<T *>(NULL)); | 
|---|
| 345 |         } | 
|---|
| 346 |     }; | 
|---|
| 347 |  | 
|---|
| 348 |     template<class T> | 
|---|
| 349 |     static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){ | 
|---|
| 350 |         // there should never be any need to save an abstract polymorphic  | 
|---|
| 351 |         // class pointer.  Inhibiting code generation for this | 
|---|
| 352 |         // permits abstract base classes to be used - note: exception | 
|---|
| 353 |         // virtual serialize functions used for plug-ins | 
|---|
| 354 |         typedef  | 
|---|
| 355 |             BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 356 |                 serialization::is_abstract<T>, | 
|---|
| 357 |                 mpl::identity<abstract<T> >, | 
|---|
| 358 |                 mpl::identity<non_abstract<T> >        | 
|---|
| 359 |             >::type typex; | 
|---|
| 360 |         return typex::register_type(ar); | 
|---|
| 361 |     } | 
|---|
| 362 |  | 
|---|
| 363 |     template<class T> | 
|---|
| 364 |     struct non_polymorphic | 
|---|
| 365 |     { | 
|---|
| 366 |         static void save( | 
|---|
| 367 |             Archive &ar,  | 
|---|
| 368 |             const T & t,  | 
|---|
| 369 |             const basic_pointer_oserializer * bpos_ptr | 
|---|
| 370 |         ){ | 
|---|
| 371 |             // save the requested pointer type | 
|---|
| 372 |             ar.save_pointer(& t, bpos_ptr); | 
|---|
| 373 |         } | 
|---|
| 374 |     }; | 
|---|
| 375 |  | 
|---|
| 376 |     template<class T> | 
|---|
| 377 |     struct polymorphic | 
|---|
| 378 |     { | 
|---|
| 379 |         static void save( | 
|---|
| 380 |             Archive &ar,  | 
|---|
| 381 |             const T & t,  | 
|---|
| 382 |             const basic_pointer_oserializer * bpos_ptr | 
|---|
| 383 |         ){ | 
|---|
| 384 |             const boost::serialization::extended_type_info * this_type | 
|---|
| 385 |                 = boost::serialization::type_info_implementation<T>::type::get_instance(); | 
|---|
| 386 |             // retrieve the true type of the object pointed to | 
|---|
| 387 |             // if this assertion fails its an error in this library | 
|---|
| 388 |             assert(NULL != this_type); | 
|---|
| 389 |             const boost::serialization::extended_type_info * true_type  | 
|---|
| 390 |                 = boost::serialization::type_info_implementation<T>::type::get_derived_extended_type_info(t); | 
|---|
| 391 |             // note:if this exception is thrown, be sure that derived pointer | 
|---|
| 392 |             // is either regsitered or exported. | 
|---|
| 393 |             if(NULL == true_type){ | 
|---|
| 394 |                 boost::throw_exception( | 
|---|
| 395 |                     archive_exception(archive_exception::unregistered_class) | 
|---|
| 396 |                 ); | 
|---|
| 397 |             } | 
|---|
| 398 |  | 
|---|
| 399 |             // if its not a pointer to a more derived type | 
|---|
| 400 |             const void *vp = static_cast<const void *>(&t); | 
|---|
| 401 |             if(*this_type == *true_type){ | 
|---|
| 402 |                 ar.save_pointer(vp, bpos_ptr); | 
|---|
| 403 |                 return; | 
|---|
| 404 |             } | 
|---|
| 405 |             // convert pointer to more derived type. if this is thrown | 
|---|
| 406 |             // it means that the base/derived relationship hasn't be registered | 
|---|
| 407 |             vp = serialization::void_downcast(*true_type, *this_type, &t); | 
|---|
| 408 |             if(NULL == vp){ | 
|---|
| 409 |                 boost::throw_exception( | 
|---|
| 410 |                     archive_exception(archive_exception::unregistered_cast) | 
|---|
| 411 |                 ); | 
|---|
| 412 |             } | 
|---|
| 413 |  | 
|---|
| 414 |             // sice true_type is valid, and this only gets made if the  | 
|---|
| 415 |             // pointer oserializer object has been created, this should never | 
|---|
| 416 |             // fail | 
|---|
| 417 |             bpos_ptr = archive_pointer_oserializer<Archive>::find(* true_type); | 
|---|
| 418 |             assert(NULL != bpos_ptr); | 
|---|
| 419 |             if(NULL == bpos_ptr) | 
|---|
| 420 |                 boost::throw_exception( | 
|---|
| 421 |                     archive_exception(archive_exception::unregistered_class) | 
|---|
| 422 |                 ); | 
|---|
| 423 |             ar.save_pointer(vp, bpos_ptr); | 
|---|
| 424 |         } | 
|---|
| 425 |     }; | 
|---|
| 426 |  | 
|---|
| 427 |     template<class T> | 
|---|
| 428 |     static void save( | 
|---|
| 429 |         Archive & ar,  | 
|---|
| 430 |         const T &t, | 
|---|
| 431 |         const basic_pointer_oserializer * bpos_ptr | 
|---|
| 432 |     ){ | 
|---|
| 433 |         typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< | 
|---|
| 434 |             BOOST_DEDUCED_TYPENAME boost::serialization:: | 
|---|
| 435 |                 type_info_implementation<T>::type::is_polymorphic, | 
|---|
| 436 |             mpl::identity<polymorphic<T> >, | 
|---|
| 437 |             mpl::identity<non_polymorphic<T> > | 
|---|
| 438 |         >::type typey; | 
|---|
| 439 |         typey::save(ar, const_cast<T &>(t), bpos_ptr); | 
|---|
| 440 |     } | 
|---|
| 441 |  | 
|---|
| 442 |     template<class T> | 
|---|
| 443 |     static void const_check(T & t){ | 
|---|
| 444 |         BOOST_STATIC_ASSERT(! boost::is_const<T>::value); | 
|---|
| 445 |     } | 
|---|
| 446 |  | 
|---|
| 447 |     static void invoke(Archive &ar, const TPtr t){ | 
|---|
| 448 |         #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | 
|---|
| 449 |             // if your program traps here, its because you tried to do | 
|---|
| 450 |             // something like ar << t where t is a pointer to a const value | 
|---|
| 451 |             // void f3(A const* a, text_oarchive& oa) | 
|---|
| 452 |             // { | 
|---|
| 453 |             //     oa << a; | 
|---|
| 454 |             // } | 
|---|
| 455 |             // with a compiler which doesn't support remove_const | 
|---|
| 456 |             // const_check(* t); | 
|---|
| 457 |         #else | 
|---|
| 458 |             // otherwise remove the const | 
|---|
| 459 |         #endif | 
|---|
| 460 |         const basic_pointer_oserializer * bpos_ptr =  register_type(ar, * t); | 
|---|
| 461 |         if(NULL == t){ | 
|---|
| 462 |             basic_oarchive & boa = boost::smart_cast_reference<basic_oarchive &>(ar); | 
|---|
| 463 |             boa.save_null_pointer(); | 
|---|
| 464 |             save_access::end_preamble(ar); | 
|---|
| 465 |             return; | 
|---|
| 466 |         } | 
|---|
| 467 |         save(ar, * t, bpos_ptr); | 
|---|
| 468 |     }; | 
|---|
| 469 | }; | 
|---|
| 470 |  | 
|---|
| 471 | template<class Archive, class T> | 
|---|
| 472 | struct save_enum_type | 
|---|
| 473 | { | 
|---|
| 474 |     static void invoke(Archive &ar, const T &t){ | 
|---|
| 475 |         // convert enum to integers on save | 
|---|
| 476 |         const int i = static_cast<int>(t); | 
|---|
| 477 |         ar << boost::serialization::make_nvp(NULL, i); | 
|---|
| 478 |     } | 
|---|
| 479 | }; | 
|---|
| 480 |  | 
|---|
| 481 | template<class Archive, class T> | 
|---|
| 482 | struct save_array_type | 
|---|
| 483 | { | 
|---|
| 484 |     static void invoke(Archive &ar, const T &t){ | 
|---|
| 485 |         save_access::end_preamble(ar); | 
|---|
| 486 |         // consider alignment | 
|---|
| 487 |         int count = sizeof(t) / ( | 
|---|
| 488 |             static_cast<const char *>(static_cast<const void *>(&t[1]))  | 
|---|
| 489 |             - static_cast<const char *>(static_cast<const void *>(&t[0])) | 
|---|
| 490 |         ); | 
|---|
| 491 |         ar << BOOST_SERIALIZATION_NVP(count); | 
|---|
| 492 |         int i; | 
|---|
| 493 |         for(i = 0; i < count; ++i) | 
|---|
| 494 |             ar << boost::serialization::make_nvp("item", t[i]); | 
|---|
| 495 |     } | 
|---|
| 496 | }; | 
|---|
| 497 |  | 
|---|
| 498 | // note bogus arguments to workaround msvc 6 silent runtime failure | 
|---|
| 499 | // declaration to satisfy gcc | 
|---|
| 500 | template<class Archive, class T> | 
|---|
| 501 | BOOST_DLLEXPORT const basic_pointer_oserializer & | 
|---|
| 502 | instantiate_pointer_oserializer( | 
|---|
| 503 |     Archive * /* ar = NULL */, | 
|---|
| 504 |     T * /* t = NULL */ | 
|---|
| 505 | ) BOOST_USED ; | 
|---|
| 506 | // definition | 
|---|
| 507 | template<class Archive, class T> | 
|---|
| 508 | BOOST_DLLEXPORT const basic_pointer_oserializer & | 
|---|
| 509 | instantiate_pointer_oserializer( | 
|---|
| 510 |     Archive * /* ar = NULL */, | 
|---|
| 511 |     T * /* t = NULL */ | 
|---|
| 512 | ){ | 
|---|
| 513 |     // note: reversal of order of arguments to work around msvc 6.0 bug | 
|---|
| 514 |     // that manifests itself while trying to link. | 
|---|
| 515 |     return pointer_oserializer<T, Archive>::instantiate(); | 
|---|
| 516 | } | 
|---|
| 517 |  | 
|---|
| 518 | } // detail | 
|---|
| 519 |  | 
|---|
| 520 | template<class Archive, class T> | 
|---|
| 521 | inline void save(Archive & ar, const T &t){ | 
|---|
| 522 |     typedef  | 
|---|
| 523 |         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>, | 
|---|
| 524 |             mpl::identity<detail::save_pointer_type<Archive, T> >, | 
|---|
| 525 |         //else | 
|---|
| 526 |         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>, | 
|---|
| 527 |             mpl::identity<detail::save_enum_type<Archive, T> >, | 
|---|
| 528 |         //else | 
|---|
| 529 |         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>, | 
|---|
| 530 |             mpl::identity<detail::save_array_type<Archive, T> >, | 
|---|
| 531 |         //else | 
|---|
| 532 |             mpl::identity<detail::save_non_pointer_type<Archive, T> > | 
|---|
| 533 |         > | 
|---|
| 534 |         > | 
|---|
| 535 |         >::type typex; | 
|---|
| 536 |     typex::invoke(ar, t); | 
|---|
| 537 | } | 
|---|
| 538 |  | 
|---|
| 539 | #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING | 
|---|
| 540 |  | 
|---|
| 541 | template<class T> | 
|---|
| 542 | struct check_tracking { | 
|---|
| 543 |     typedef BOOST_DEDUCED_TYPENAME mpl::if_< | 
|---|
| 544 |         // if its never tracked. | 
|---|
| 545 |         BOOST_DEDUCED_TYPENAME mpl::equal_to< | 
|---|
| 546 |             serialization::tracking_level<T>, | 
|---|
| 547 |             mpl::int_<serialization::track_never> | 
|---|
| 548 |         >, | 
|---|
| 549 |         // it better not be a pointer | 
|---|
| 550 |         mpl::not_<is_pointer<T> >, | 
|---|
| 551 |     //else | 
|---|
| 552 |         // otherwise if it might be tracked.  So there shouldn't | 
|---|
| 553 |         // be any problem making a const | 
|---|
| 554 |         is_const<T> | 
|---|
| 555 |     >::type typex; | 
|---|
| 556 |     BOOST_STATIC_CONSTANT(bool, value = typex::value); | 
|---|
| 557 | }; | 
|---|
| 558 |  | 
|---|
| 559 | template<class Archive, class T> | 
|---|
| 560 | inline void save(Archive & ar, T &t){ | 
|---|
| 561 |     // if your program traps here, it indicates taht your doing one of the following: | 
|---|
| 562 |     // a) serializing an object of a type marked "track_never" through a pointer. | 
|---|
| 563 |     // b) saving an non-const object of a type not markd "track_never) | 
|---|
| 564 |     // Either of these conditions may be an indicator of an error usage of the | 
|---|
| 565 |     // serialization library and should be double checked.  See documentation on | 
|---|
| 566 |     // object tracking. | 
|---|
| 567 |     BOOST_STATIC_ASSERT(check_tracking<T>::value); | 
|---|
| 568 |         save(ar, const_cast<const T &>(t)); | 
|---|
| 569 | } | 
|---|
| 570 | #endif | 
|---|
| 571 |  | 
|---|
| 572 | } // namespace archive | 
|---|
| 573 | } // namespace boost | 
|---|
| 574 |  | 
|---|
| 575 | #endif // BOOST_ARCHIVE_OSERIALIZER_HPP | 
|---|