File indexing completed on 2025-01-18 09:28:27
0001 #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
0002 #define BOOST_ARCHIVE_OSERIALIZER_HPP
0003
0004
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
0018
0019
0020
0021
0022
0023
0024
0025
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 }
0081
0082 namespace archive {
0083
0084
0085
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
0111
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 ) 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
0153
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
0198
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
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
0235
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
0243 struct save_only {
0244 template<class T>
0245 static void invoke(Archive & ar, const T & t){
0246
0247
0248 boost::serialization::serialize_adl(
0249 ar,
0250 const_cast<T &>(t),
0251 ::boost::serialization::version< T >::value
0252 );
0253 }
0254 };
0255
0256
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
0272
0273 struct save_conditional {
0274 template<class T>
0275 static void invoke(Archive &ar, const T &t){
0276
0277 save_standard::invoke(ar, t);
0278
0279
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
0289 mpl::equal_to<
0290 boost::serialization::implementation_level< T >,
0291 mpl::int_<boost::serialization::primitive_type>
0292 >,
0293 mpl::identity<save_primitive>,
0294
0295 typename mpl::eval_if<
0296
0297 mpl::greater_equal<
0298 boost::serialization::implementation_level< T >,
0299 mpl::int_<boost::serialization::object_class_info>
0300 >,
0301
0302 mpl::identity<save_standard>,
0303
0304 typename mpl::eval_if<
0305
0306 mpl::equal_to<
0307 boost::serialization::tracking_level< T >,
0308 mpl::int_<boost::serialization::track_never>
0309 >,
0310
0311 mpl::identity<save_only>,
0312
0313
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 & ){
0333
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 ){
0349
0350
0351
0352
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
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
0395
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
0402
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
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
0420
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
0437
0438
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
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
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
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 }
0524
0525 template<class Archive, class T>
0526 inline void save(Archive & ar, T &t){
0527 typedef
0528 typename mpl::eval_if<is_pointer< T >,
0529 mpl::identity<detail::save_pointer_type<Archive> >,
0530
0531 typename mpl::eval_if<is_enum< T >,
0532 mpl::identity<detail::save_enum_type<Archive> >,
0533
0534 typename mpl::eval_if<is_array< T >,
0535 mpl::identity<detail::save_array_type<Archive> >,
0536
0537 mpl::identity<detail::save_non_pointer_type<Archive> >
0538 >
0539 >
0540 >::type typex;
0541 typex::invoke(ar, t);
0542 }
0543
0544 }
0545 }
0546
0547 #endif