Chris@16: #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP Chris@16: #define BOOST_ARCHIVE_OSERIALIZER_HPP Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #pragma inline_depth(511) Chris@16: #pragma inline_recursion(on) Chris@16: #endif Chris@16: Chris@16: #if defined(__MWERKS__) Chris@16: #pragma inline_depth(511) Chris@16: #endif Chris@16: Chris@16: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 Chris@16: // oserializer.hpp: interface for serialization system. Chris@16: Chris@16: // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . Chris@16: // Use, modification and distribution is subject to the Boost Software Chris@16: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org for updates, documentation, and revision history. Chris@16: Chris@16: #include Chris@16: #include // NULL Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace serialization { Chris@16: class extended_type_info; Chris@16: } // namespace serialization Chris@16: Chris@16: namespace archive { Chris@16: Chris@16: // an accessor to permit friend access to archives. Needed because Chris@16: // some compilers don't handle friend templates completely Chris@16: class save_access { Chris@16: public: Chris@16: template Chris@16: static void end_preamble(Archive & ar){ Chris@16: ar.end_preamble(); Chris@16: } Chris@16: template Chris@16: static void save_primitive(Archive & ar, const T & t){ Chris@16: ar.end_preamble(); Chris@16: ar.save(t); Chris@16: } Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable : 4511 4512) Chris@16: #endif Chris@16: Chris@16: template Chris@16: class oserializer : public basic_oserializer Chris@16: { Chris@16: private: Chris@16: // private constructor to inhibit any existence other than the Chris@16: // static one Chris@16: public: Chris@16: explicit BOOST_DLLEXPORT oserializer() : Chris@16: basic_oserializer( Chris@16: boost::serialization::singleton< Chris@101: typename Chris@16: boost::serialization::type_info_implementation< T >::type Chris@16: >::get_const_instance() Chris@16: ) Chris@16: {} Chris@16: virtual BOOST_DLLEXPORT void save_object_data( Chris@16: basic_oarchive & ar, Chris@16: const void *x Chris@16: ) const BOOST_USED; Chris@16: virtual bool class_info() const { Chris@16: return boost::serialization::implementation_level< T >::value Chris@16: >= boost::serialization::object_class_info; Chris@16: } Chris@16: virtual bool tracking(const unsigned int /* flags */) const { Chris@16: return boost::serialization::tracking_level< T >::value == boost::serialization::track_always Chris@16: || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively Chris@16: && serialized_as_pointer()); Chris@16: } Chris@16: virtual version_type version() const { Chris@16: return version_type(::boost::serialization::version< T >::value); Chris@16: } Chris@16: virtual bool is_polymorphic() const { Chris@16: return boost::is_polymorphic< T >::value; Chris@16: } Chris@16: virtual ~oserializer(){} Chris@16: }; Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: template Chris@16: BOOST_DLLEXPORT void oserializer::save_object_data( Chris@16: basic_oarchive & ar, Chris@16: const void *x Chris@16: ) const { Chris@16: // make sure call is routed through the highest interface that might Chris@16: // be specialized by the user. Chris@16: BOOST_STATIC_ASSERT(boost::is_const< T >::value == false); Chris@16: boost::serialization::serialize_adl( Chris@16: boost::serialization::smart_cast_reference(ar), Chris@16: * static_cast(const_cast(x)), Chris@16: version() Chris@16: ); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable : 4511 4512) Chris@16: #endif Chris@16: Chris@16: template Chris@16: class pointer_oserializer : Chris@16: public basic_pointer_oserializer Chris@16: { Chris@16: private: Chris@16: const basic_oserializer & Chris@16: get_basic_serializer() const { Chris@16: return boost::serialization::singleton< Chris@16: oserializer Chris@16: >::get_const_instance(); Chris@16: } Chris@16: virtual BOOST_DLLEXPORT void save_object_ptr( Chris@16: basic_oarchive & ar, Chris@16: const void * x Chris@16: ) const BOOST_USED; Chris@16: public: Chris@16: pointer_oserializer(); Chris@16: ~pointer_oserializer(); Chris@16: }; Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: template Chris@16: BOOST_DLLEXPORT void pointer_oserializer::save_object_ptr( Chris@16: basic_oarchive & ar, Chris@16: const void * x Chris@16: ) const { Chris@16: BOOST_ASSERT(NULL != x); Chris@16: // make sure call is routed through the highest interface that might Chris@16: // be specialized by the user. Chris@16: T * t = static_cast(const_cast(x)); Chris@16: const unsigned int file_version = boost::serialization::version< T >::value; Chris@16: Archive & ar_impl Chris@16: = boost::serialization::smart_cast_reference(ar); Chris@16: boost::serialization::save_construct_data_adl( Chris@16: ar_impl, Chris@16: t, Chris@16: file_version Chris@16: ); Chris@16: ar_impl << boost::serialization::make_nvp(NULL, * t); Chris@16: } Chris@16: Chris@16: template Chris@16: pointer_oserializer::pointer_oserializer() : Chris@16: basic_pointer_oserializer( Chris@16: boost::serialization::singleton< Chris@101: typename Chris@16: boost::serialization::type_info_implementation< T >::type Chris@16: >::get_const_instance() Chris@16: ) Chris@16: { Chris@16: // make sure appropriate member function is instantiated Chris@16: boost::serialization::singleton< Chris@16: oserializer Chris@16: >::get_mutable_instance().set_bpos(this); Chris@16: archive_serializer_map::insert(this); Chris@16: } Chris@16: Chris@16: template Chris@16: pointer_oserializer::~pointer_oserializer(){ Chris@16: archive_serializer_map::erase(this); Chris@16: } Chris@16: Chris@16: template Chris@16: struct save_non_pointer_type { Chris@16: // note this bounces the call right back to the archive Chris@16: // with no runtime overhead Chris@16: struct save_primitive { Chris@16: template Chris@16: static void invoke(Archive & ar, const T & t){ Chris@16: save_access::save_primitive(ar, t); Chris@16: } Chris@16: }; Chris@16: // same as above but passes through serialization Chris@16: struct save_only { Chris@16: template Chris@16: static void invoke(Archive & ar, const T & t){ Chris@16: // make sure call is routed through the highest interface that might Chris@16: // be specialized by the user. Chris@16: boost::serialization::serialize_adl( Chris@16: ar, Chris@16: const_cast(t), Chris@16: ::boost::serialization::version< T >::value Chris@16: ); Chris@16: } Chris@16: }; Chris@16: // adds class information to the archive. This includes Chris@16: // serialization level and class version Chris@16: struct save_standard { Chris@16: template Chris@16: static void invoke(Archive &ar, const T & t){ Chris@16: ar.save_object( Chris@16: & t, Chris@16: boost::serialization::singleton< Chris@16: oserializer Chris@16: >::get_const_instance() Chris@16: ); Chris@16: } Chris@16: }; Chris@16: Chris@16: // adds class information to the archive. This includes Chris@16: // serialization level and class version Chris@16: struct save_conditional { Chris@16: template Chris@16: static void invoke(Archive &ar, const T &t){ Chris@16: //if(0 == (ar.get_flags() & no_tracking)) Chris@16: save_standard::invoke(ar, t); Chris@16: //else Chris@16: // save_only::invoke(ar, t); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: static void invoke(Archive & ar, const T & t){ Chris@16: typedef Chris@101: typename mpl::eval_if< Chris@16: // if its primitive Chris@16: mpl::equal_to< Chris@16: boost::serialization::implementation_level< T >, Chris@16: mpl::int_ Chris@16: >, Chris@16: mpl::identity, Chris@16: // else Chris@101: typename mpl::eval_if< Chris@16: // class info / version Chris@16: mpl::greater_equal< Chris@16: boost::serialization::implementation_level< T >, Chris@16: mpl::int_ Chris@16: >, Chris@16: // do standard save Chris@16: mpl::identity, Chris@16: // else Chris@101: typename mpl::eval_if< Chris@16: // no tracking Chris@16: mpl::equal_to< Chris@16: boost::serialization::tracking_level< T >, Chris@16: mpl::int_ Chris@16: >, Chris@16: // do a fast save Chris@16: mpl::identity, Chris@16: // else Chris@16: // do a fast save only tracking is turned off Chris@16: mpl::identity Chris@16: > > >::type typex; Chris@16: check_object_versioning< T >(); Chris@16: typex::invoke(ar, t); Chris@16: } Chris@16: template Chris@16: static void invoke(Archive & ar, T & t){ Chris@16: check_object_level< T >(); Chris@16: check_object_tracking< T >(); Chris@16: invoke(ar, const_cast(t)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct save_pointer_type { Chris@16: struct abstract Chris@16: { Chris@16: template Chris@16: static const basic_pointer_oserializer * register_type(Archive & /* ar */){ Chris@16: // it has? to be polymorphic Chris@16: BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value); Chris@16: return NULL; Chris@16: } Chris@16: }; Chris@16: Chris@16: struct non_abstract Chris@16: { Chris@16: template Chris@16: static const basic_pointer_oserializer * register_type(Archive & ar){ Chris@16: return ar.register_type(static_cast(NULL)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){ Chris@16: // there should never be any need to save an abstract polymorphic Chris@16: // class pointer. Inhibiting code generation for this Chris@16: // permits abstract base classes to be used - note: exception Chris@16: // virtual serialize functions used for plug-ins Chris@16: typedef Chris@101: typename mpl::eval_if< Chris@16: boost::serialization::is_abstract< T >, Chris@16: mpl::identity, Chris@16: mpl::identity Chris@16: >::type typex; Chris@16: return typex::template register_type< T >(ar); Chris@16: } Chris@16: Chris@16: struct non_polymorphic Chris@16: { Chris@16: template Chris@16: static void save( Chris@16: Archive &ar, Chris@16: T & t Chris@16: ){ Chris@16: const basic_pointer_oserializer & bpos = Chris@16: boost::serialization::singleton< Chris@16: pointer_oserializer Chris@16: >::get_const_instance(); Chris@16: // save the requested pointer type Chris@16: ar.save_pointer(& t, & bpos); Chris@16: } Chris@16: }; Chris@16: Chris@16: struct polymorphic Chris@16: { Chris@16: template Chris@16: static void save( Chris@16: Archive &ar, Chris@16: T & t Chris@16: ){ Chris@101: typename Chris@16: boost::serialization::type_info_implementation< T >::type const Chris@16: & i = boost::serialization::singleton< Chris@101: typename Chris@16: boost::serialization::type_info_implementation< T >::type Chris@16: >::get_const_instance(); Chris@16: Chris@16: boost::serialization::extended_type_info const * const this_type = & i; Chris@16: Chris@16: // retrieve the true type of the object pointed to Chris@16: // if this assertion fails its an error in this library Chris@16: BOOST_ASSERT(NULL != this_type); Chris@16: Chris@16: const boost::serialization::extended_type_info * true_type = Chris@16: i.get_derived_extended_type_info(t); Chris@16: Chris@16: // note:if this exception is thrown, be sure that derived pointer Chris@16: // is either registered or exported. Chris@16: if(NULL == true_type){ Chris@16: boost::serialization::throw_exception( Chris@16: archive_exception( Chris@16: archive_exception::unregistered_class, Chris@16: "derived class not registered or exported" Chris@16: ) Chris@16: ); Chris@16: } Chris@16: Chris@16: // if its not a pointer to a more derived type Chris@16: const void *vp = static_cast(&t); Chris@16: if(*this_type == *true_type){ Chris@16: const basic_pointer_oserializer * bpos = register_type(ar, t); Chris@16: ar.save_pointer(vp, bpos); Chris@16: return; Chris@16: } Chris@16: // convert pointer to more derived type. if this is thrown Chris@16: // it means that the base/derived relationship hasn't be registered Chris@16: vp = serialization::void_downcast( Chris@16: *true_type, Chris@16: *this_type, Chris@16: static_cast(&t) Chris@16: ); Chris@16: if(NULL == vp){ Chris@16: boost::serialization::throw_exception( Chris@16: archive_exception( Chris@16: archive_exception::unregistered_cast, Chris@16: true_type->get_debug_info(), Chris@16: this_type->get_debug_info() Chris@16: ) Chris@16: ); Chris@16: } Chris@16: Chris@16: // since true_type is valid, and this only gets made if the Chris@16: // pointer oserializer object has been created, this should never Chris@16: // fail Chris@16: const basic_pointer_oserializer * bpos Chris@16: = static_cast( Chris@16: boost::serialization::singleton< Chris@16: archive_serializer_map Chris@16: >::get_const_instance().find(*true_type) Chris@16: ); Chris@16: BOOST_ASSERT(NULL != bpos); Chris@16: if(NULL == bpos) Chris@16: boost::serialization::throw_exception( Chris@16: archive_exception( Chris@16: archive_exception::unregistered_class, Chris@16: "derived class not registered or exported" Chris@16: ) Chris@16: ); Chris@16: ar.save_pointer(vp, bpos); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: static void save( Chris@16: Archive & ar, Chris@16: const T & t Chris@16: ){ Chris@16: check_pointer_level< T >(); Chris@16: check_pointer_tracking< T >(); Chris@101: typedef typename mpl::eval_if< Chris@16: is_polymorphic< T >, Chris@16: mpl::identity, Chris@16: mpl::identity Chris@16: >::type type; Chris@16: type::save(ar, const_cast(t)); Chris@16: } Chris@16: Chris@16: template Chris@16: static void invoke(Archive &ar, const TPtr t){ Chris@16: register_type(ar, * t); Chris@16: if(NULL == t){ Chris@16: basic_oarchive & boa Chris@16: = boost::serialization::smart_cast_reference(ar); Chris@16: boa.save_null_pointer(); Chris@16: save_access::end_preamble(ar); Chris@16: return; Chris@16: } Chris@16: save(ar, * t); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct save_enum_type Chris@16: { Chris@16: template Chris@16: static void invoke(Archive &ar, const T &t){ Chris@16: // convert enum to integers on save Chris@16: const int i = static_cast(t); Chris@16: ar << boost::serialization::make_nvp(NULL, i); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct save_array_type Chris@16: { Chris@16: template Chris@16: static void invoke(Archive &ar, const T &t){ Chris@101: typedef typename boost::remove_extent< T >::type value_type; Chris@16: Chris@16: save_access::end_preamble(ar); Chris@16: // consider alignment Chris@16: std::size_t c = sizeof(t) / ( Chris@16: static_cast(static_cast(&t[1])) Chris@16: - static_cast(static_cast(&t[0])) Chris@16: ); Chris@16: boost::serialization::collection_size_type count(c); Chris@16: ar << BOOST_SERIALIZATION_NVP(count); Chris@16: ar << serialization::make_array(static_cast(&t[0]),count); Chris@16: } Chris@16: }; Chris@16: Chris@16: } // detail Chris@16: Chris@16: template Chris@16: inline void save(Archive & ar, /*const*/ T &t){ Chris@16: typedef Chris@101: typename mpl::eval_if, Chris@16: mpl::identity >, Chris@16: //else Chris@101: typename mpl::eval_if, Chris@16: mpl::identity >, Chris@16: //else Chris@101: typename mpl::eval_if, Chris@16: mpl::identity >, Chris@16: //else Chris@16: mpl::identity > Chris@16: > Chris@16: > Chris@16: >::type typex; Chris@16: typex::invoke(ar, t); Chris@16: } Chris@16: Chris@16: } // namespace archive Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_ARCHIVE_OSERIALIZER_HPP