Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:27

0001 #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
0002 #define BOOST_ARCHIVE_OSERIALIZER_HPP
0003 
0004 // MS compatible compilers support #pragma once
0005 #if defined(_MSC_VER)
0006 # pragma once
0007 #if !defined(__clang__)
0008 #pragma inline_depth(255)
0009 #pragma inline_recursion(on)
0010 #endif
0011 #endif
0012 
0013 #if defined(__MWERKS__)
0014 #pragma inline_depth(255)
0015 #endif
0016 
0017 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
0018 // oserializer.hpp: interface for serialization system.
0019 
0020 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
0021 // Use, modification and distribution is subject to the Boost Software
0022 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0023 // http://www.boost.org/LICENSE_1_0.txt)
0024 
0025 //  See http://www.boost.org for updates, documentation, and revision history.
0026 
0027 #include <boost/assert.hpp>
0028 #include <cstddef> // NULL
0029 
0030 #include <boost/config.hpp>
0031 
0032 #include <boost/static_assert.hpp>
0033 #include <boost/detail/workaround.hpp>
0034 
0035 #include <boost/mpl/eval_if.hpp>
0036 #include <boost/mpl/equal_to.hpp>
0037 #include <boost/mpl/greater_equal.hpp>
0038 #include <boost/mpl/identity.hpp>
0039 #include <boost/mpl/bool_fwd.hpp>
0040 
0041 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
0042     #include <boost/serialization/extended_type_info_typeid.hpp>
0043 #endif
0044 #include <boost/serialization/throw_exception.hpp>
0045 #include <boost/serialization/smart_cast.hpp>
0046 #include <boost/serialization/assume_abstract.hpp>
0047 #include <boost/serialization/static_warning.hpp>
0048 
0049 #include <boost/type_traits/is_pointer.hpp>
0050 #include <boost/type_traits/is_enum.hpp>
0051 #include <boost/type_traits/is_const.hpp>
0052 #include <boost/type_traits/is_polymorphic.hpp>
0053 #include <boost/type_traits/remove_extent.hpp>
0054 
0055 #include <boost/serialization/serialization.hpp>
0056 #include <boost/serialization/version.hpp>
0057 #include <boost/serialization/level.hpp>
0058 #include <boost/serialization/tracking.hpp>
0059 #include <boost/serialization/type_info_implementation.hpp>
0060 #include <boost/serialization/nvp.hpp>
0061 #include <boost/serialization/void_cast.hpp>
0062 #include <boost/serialization/collection_size_type.hpp>
0063 #include <boost/serialization/array_wrapper.hpp>
0064 
0065 #include <boost/serialization/singleton.hpp>
0066 
0067 #include <boost/archive/archive_exception.hpp>
0068 #include <boost/archive/detail/basic_oarchive.hpp>
0069 #include <boost/archive/detail/basic_oserializer.hpp>
0070 #include <boost/archive/detail/basic_pointer_oserializer.hpp>
0071 #include <boost/archive/detail/archive_serializer_map.hpp>
0072 #include <boost/archive/detail/check.hpp>
0073 
0074 #include <boost/core/addressof.hpp>
0075 
0076 namespace boost {
0077 
0078 namespace serialization {
0079     class extended_type_info;
0080 } // namespace serialization
0081 
0082 namespace archive {
0083 
0084 // an accessor to permit friend access to archives.  Needed because
0085 // some compilers don't handle friend templates completely
0086 class save_access {
0087 public:
0088     template<class Archive>
0089     static void end_preamble(Archive & ar){
0090         ar.end_preamble();
0091     }
0092     template<class Archive, class T>
0093     static void save_primitive(Archive & ar, const  T & t){
0094         ar.end_preamble();
0095         ar.save(t);
0096     }
0097 };
0098 
0099 namespace detail {
0100 
0101 #ifdef BOOST_MSVC
0102 #  pragma warning(push)
0103 #  pragma warning(disable : 4511 4512)
0104 #endif
0105 
0106 template<class Archive, class T>
0107 class oserializer : public basic_oserializer
0108 {
0109 private:
0110     // private constructor to inhibit any existence other than the
0111     // static one
0112 public:
0113     explicit BOOST_DLLEXPORT oserializer() :
0114         basic_oserializer(
0115             boost::serialization::singleton<
0116                 typename
0117                 boost::serialization::type_info_implementation< T >::type
0118             >::get_const_instance()
0119         )
0120     {}
0121     BOOST_DLLEXPORT void save_object_data(
0122         basic_oarchive & ar,
0123         const void *x
0124     ) const BOOST_OVERRIDE BOOST_USED;
0125     bool class_info() const BOOST_OVERRIDE {
0126         return boost::serialization::implementation_level< T >::value
0127             >= boost::serialization::object_class_info;
0128     }
0129     bool tracking(const unsigned int /* flags */) const BOOST_OVERRIDE {
0130         return boost::serialization::tracking_level< T >::value == boost::serialization::track_always
0131             || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively
0132                 && serialized_as_pointer());
0133     }
0134     version_type version() const BOOST_OVERRIDE {
0135         return version_type(::boost::serialization::version< T >::value);
0136     }
0137     bool is_polymorphic() const BOOST_OVERRIDE {
0138         return boost::is_polymorphic< T >::value;
0139     }
0140     ~oserializer() BOOST_OVERRIDE {}
0141 };
0142 
0143 #ifdef BOOST_MSVC
0144 #  pragma warning(pop)
0145 #endif
0146 
0147 template<class Archive, class T>
0148 BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
0149     basic_oarchive & ar,
0150     const void *x
0151 ) const {
0152     // make sure call is routed through the highest interface that might
0153     // be specialized by the user.
0154     BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
0155     boost::serialization::serialize_adl(
0156         boost::serialization::smart_cast_reference<Archive &>(ar),
0157         * static_cast<T *>(const_cast<void *>(x)),
0158         version()
0159     );
0160 }
0161 
0162 #ifdef BOOST_MSVC
0163 #  pragma warning(push)
0164 #  pragma warning(disable : 4511 4512)
0165 #endif
0166 
0167 template<class Archive, class T>
0168 class pointer_oserializer :
0169     public basic_pointer_oserializer
0170 {
0171 private:
0172     const basic_oserializer &
0173     get_basic_serializer() const BOOST_OVERRIDE {
0174         return boost::serialization::singleton<
0175             oserializer<Archive, T>
0176         >::get_const_instance();
0177     }
0178     BOOST_DLLEXPORT void save_object_ptr(
0179         basic_oarchive & ar,
0180         const void * x
0181     ) const BOOST_OVERRIDE BOOST_USED;
0182 public:
0183     pointer_oserializer();
0184     ~pointer_oserializer() BOOST_OVERRIDE;
0185 };
0186 
0187 #ifdef BOOST_MSVC
0188 #  pragma warning(pop)
0189 #endif
0190 
0191 template<class Archive, class T>
0192 BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(
0193     basic_oarchive & ar,
0194     const void * x
0195 ) const {
0196     BOOST_ASSERT(NULL != x);
0197     // make sure call is routed through the highest interface that might
0198     // be specialized by the user.
0199     T * t = static_cast<T *>(const_cast<void *>(x));
0200     const unsigned int file_version = boost::serialization::version< T >::value;
0201     Archive & ar_impl
0202         = boost::serialization::smart_cast_reference<Archive &>(ar);
0203     boost::serialization::save_construct_data_adl<Archive, T>(
0204         ar_impl,
0205         t,
0206         file_version
0207     );
0208     ar_impl << boost::serialization::make_nvp(NULL, * t);
0209 }
0210 
0211 template<class Archive, class T>
0212 pointer_oserializer<Archive, T>::pointer_oserializer() :
0213     basic_pointer_oserializer(
0214         boost::serialization::singleton<
0215             typename
0216             boost::serialization::type_info_implementation< T >::type
0217         >::get_const_instance()
0218     )
0219 {
0220     // make sure appropriate member function is instantiated
0221     boost::serialization::singleton<
0222         oserializer<Archive, T>
0223     >::get_mutable_instance().set_bpos(this);
0224     archive_serializer_map<Archive>::insert(this);
0225 }
0226 
0227 template<class Archive, class T>
0228 pointer_oserializer<Archive, T>::~pointer_oserializer(){
0229     archive_serializer_map<Archive>::erase(this);
0230 }
0231 
0232 template<class Archive>
0233 struct save_non_pointer_type {
0234     // note this bounces the call right back to the archive
0235     // with no runtime overhead
0236     struct save_primitive {
0237         template<class T>
0238         static void invoke(Archive & ar, const T & t){
0239             save_access::save_primitive(ar, t);
0240         }
0241     };
0242     // same as above but passes through serialization
0243     struct save_only {
0244         template<class T>
0245         static void invoke(Archive & ar, const T & t){
0246             // make sure call is routed through the highest interface that might
0247             // be specialized by the user.
0248             boost::serialization::serialize_adl(
0249                 ar,
0250                 const_cast<T &>(t),
0251                 ::boost::serialization::version< T >::value
0252             );
0253         }
0254     };
0255     // adds class information to the archive. This includes
0256     // serialization level and class version
0257     struct save_standard {
0258         template<class T>
0259         static void invoke(Archive &ar, const T & t){
0260             ar.save_object(
0261                 boost::addressof(t),
0262                 boost::serialization::singleton<
0263                     oserializer<Archive, T>
0264                 >::get_const_instance()
0265             );
0266         }
0267     };
0268 
0269 
0270 
0271     // adds class information to the archive. This includes
0272     // serialization level and class version
0273     struct save_conditional {
0274         template<class T>
0275         static void invoke(Archive &ar, const T &t){
0276             //if(0 == (ar.get_flags() & no_tracking))
0277                 save_standard::invoke(ar, t);
0278             //else
0279             //   save_only::invoke(ar, t);
0280         }
0281     };
0282 
0283 
0284     template<class T>
0285     static void invoke(Archive & ar, const T & t){
0286         typedef
0287             typename mpl::eval_if<
0288             // if its primitive
0289                 mpl::equal_to<
0290                     boost::serialization::implementation_level< T >,
0291                     mpl::int_<boost::serialization::primitive_type>
0292                 >,
0293                 mpl::identity<save_primitive>,
0294             // else
0295             typename mpl::eval_if<
0296                 // class info / version
0297                 mpl::greater_equal<
0298                     boost::serialization::implementation_level< T >,
0299                     mpl::int_<boost::serialization::object_class_info>
0300                 >,
0301                 // do standard save
0302                 mpl::identity<save_standard>,
0303             // else
0304             typename mpl::eval_if<
0305                     // no tracking
0306                 mpl::equal_to<
0307                     boost::serialization::tracking_level< T >,
0308                     mpl::int_<boost::serialization::track_never>
0309                 >,
0310                 // do a fast save
0311                 mpl::identity<save_only>,
0312             // else
0313                 // do a fast save only tracking is turned off
0314                 mpl::identity<save_conditional>
0315             > > >::type typex;
0316         check_object_versioning< T >();
0317         typex::invoke(ar, t);
0318     }
0319     template<class T>
0320     static void invoke(Archive & ar, T & t){
0321         check_object_level< T >();
0322         check_object_tracking< T >();
0323         invoke(ar, const_cast<const T &>(t));
0324     }
0325 };
0326 
0327 template<class Archive>
0328 struct save_pointer_type {
0329     struct abstract
0330     {
0331         template<class T>
0332         static const basic_pointer_oserializer * register_type(Archive & /* ar */){
0333             // it has? to be polymorphic
0334             BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
0335             return NULL;
0336         }
0337     };
0338 
0339     struct non_abstract
0340     {
0341         template<class T>
0342         static const basic_pointer_oserializer * register_type(Archive & ar){
0343             return ar.register_type(static_cast<T *>(NULL));
0344         }
0345     };
0346 
0347     template<class T>
0348     static const basic_pointer_oserializer * register_type(Archive &ar, T* const /*t*/){
0349         // there should never be any need to save an abstract polymorphic
0350         // class pointer.  Inhibiting code generation for this
0351         // permits abstract base classes to be used - note: exception
0352         // virtual serialize functions used for plug-ins
0353         typedef
0354             typename mpl::eval_if<
0355                 boost::serialization::is_abstract< T >,
0356                 mpl::identity<abstract>,
0357                 mpl::identity<non_abstract>
0358             >::type typex;
0359         return typex::template register_type< T >(ar);
0360     }
0361 
0362     struct non_polymorphic
0363     {
0364         template<class T>
0365         static void save(
0366             Archive &ar,
0367             T & t
0368         ){
0369             const basic_pointer_oserializer & bpos =
0370                 boost::serialization::singleton<
0371                     pointer_oserializer<Archive, T>
0372                 >::get_const_instance();
0373             // save the requested pointer type
0374             ar.save_pointer(& t, & bpos);
0375         }
0376     };
0377 
0378     struct polymorphic
0379     {
0380         template<class T>
0381         static void save(
0382             Archive &ar,
0383             T & t
0384         ){
0385             typename
0386             boost::serialization::type_info_implementation< T >::type const
0387             & i = boost::serialization::singleton<
0388                 typename
0389                 boost::serialization::type_info_implementation< T >::type
0390             >::get_const_instance();
0391 
0392             boost::serialization::extended_type_info const * const this_type = & i;
0393 
0394             // retrieve the true type of the object pointed to
0395             // if this assertion fails its an error in this library
0396             BOOST_ASSERT(NULL != this_type);
0397 
0398             const boost::serialization::extended_type_info * true_type =
0399                 i.get_derived_extended_type_info(t);
0400 
0401             // note:if this exception is thrown, be sure that derived pointer
0402             // is either registered or exported.
0403             if(NULL == true_type){
0404                 boost::serialization::throw_exception(
0405                     archive_exception(
0406                         archive_exception::unregistered_class,
0407                         "derived class not registered or exported"
0408                     )
0409                 );
0410             }
0411 
0412             // if its not a pointer to a more derived type
0413             const void *vp = static_cast<const void *>(&t);
0414             if(*this_type == *true_type){
0415                 const basic_pointer_oserializer * bpos = register_type(ar, &t);
0416                 ar.save_pointer(vp, bpos);
0417                 return;
0418             }
0419             // convert pointer to more derived type. if this is thrown
0420             // it means that the base/derived relationship hasn't be registered
0421             vp = serialization::void_downcast(
0422                 *true_type,
0423                 *this_type,
0424                 static_cast<const void *>(&t)
0425             );
0426             if(NULL == vp){
0427                 boost::serialization::throw_exception(
0428                     archive_exception(
0429                         archive_exception::unregistered_cast,
0430                         true_type->get_debug_info(),
0431                         this_type->get_debug_info()
0432                     )
0433                 );
0434             }
0435 
0436             // since true_type is valid, and this only gets made if the
0437             // pointer oserializer object has been created, this should never
0438             // fail
0439             const basic_pointer_oserializer * bpos
0440                 = static_cast<const basic_pointer_oserializer *>(
0441                     boost::serialization::singleton<
0442                         archive_serializer_map<Archive>
0443                     >::get_const_instance().find(*true_type)
0444                 );
0445             BOOST_ASSERT(NULL != bpos);
0446             if(NULL == bpos)
0447                 boost::serialization::throw_exception(
0448                     archive_exception(
0449                         archive_exception::unregistered_class,
0450                         "derived class not registered or exported"
0451                     )
0452                 );
0453             ar.save_pointer(vp, bpos);
0454         }
0455     };
0456 
0457     template<class T>
0458     static void save(
0459         Archive & ar,
0460         const T & t
0461     ){
0462         check_pointer_level< T >();
0463         check_pointer_tracking< T >();
0464         typedef typename mpl::eval_if<
0465             is_polymorphic< T >,
0466             mpl::identity<polymorphic>,
0467             mpl::identity<non_polymorphic>
0468         >::type type;
0469         type::save(ar, const_cast<T &>(t));
0470     }
0471 
0472     template<class TPtr>
0473     static void invoke(Archive &ar, const TPtr t){
0474         register_type(ar, t);
0475         if(NULL == t){
0476             basic_oarchive & boa
0477                 = boost::serialization::smart_cast_reference<basic_oarchive &>(ar);
0478             boa.save_null_pointer();
0479             save_access::end_preamble(ar);
0480             return;
0481         }
0482         save(ar, * t);
0483     }
0484 };
0485 
0486 template<class Archive>
0487 struct save_enum_type
0488 {
0489     template<class T>
0490     static void invoke(Archive &ar, const T &t){
0491         // convert enum to integers on save
0492         const int i = static_cast<int>(t);
0493         ar << boost::serialization::make_nvp(NULL, i);
0494     }
0495 };
0496 
0497 template<class Archive>
0498 struct save_array_type
0499 {
0500     template<class T>
0501     static void invoke(Archive &ar, const T &t){
0502         typedef typename boost::remove_extent< T >::type value_type;
0503 
0504         save_access::end_preamble(ar);
0505         // consider alignment
0506         std::size_t c = sizeof(t) / (
0507             static_cast<const char *>(static_cast<const void *>(&t[1]))
0508             - static_cast<const char *>(static_cast<const void *>(&t[0]))
0509         );
0510         boost::serialization::collection_size_type count(c);
0511         ar << BOOST_SERIALIZATION_NVP(count);
0512         // explicit template arguments to pass intel C++ compiler
0513         ar << serialization::make_array<
0514             const value_type,
0515             boost::serialization::collection_size_type
0516         >(
0517             static_cast<const value_type *>(&t[0]),
0518             count
0519         );
0520     }
0521 };
0522 
0523 } // detail
0524 
0525 template<class Archive, class T>
0526 inline void save(Archive & ar, /*const*/ T &t){
0527     typedef
0528         typename mpl::eval_if<is_pointer< T >,
0529             mpl::identity<detail::save_pointer_type<Archive> >,
0530         //else
0531         typename mpl::eval_if<is_enum< T >,
0532             mpl::identity<detail::save_enum_type<Archive> >,
0533         //else
0534         typename mpl::eval_if<is_array< T >,
0535             mpl::identity<detail::save_array_type<Archive> >,
0536         //else
0537             mpl::identity<detail::save_non_pointer_type<Archive> >
0538         >
0539         >
0540         >::type typex;
0541     typex::invoke(ar, t);
0542 }
0543 
0544 } // namespace archive
0545 } // namespace boost
0546 
0547 #endif // BOOST_ARCHIVE_OSERIALIZER_HPP