File indexing completed on 2025-01-18 09:28:27
0001 #ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
0002 #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
0003
0004
0005 #if defined(BOOST_MSVC)
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 <new> // for placement new
0028 #include <cstddef> // size_t, NULL
0029
0030 #include <boost/config.hpp>
0031 #include <boost/detail/workaround.hpp>
0032 #if defined(BOOST_NO_STDC_NAMESPACE)
0033 namespace std{
0034 using ::size_t;
0035 }
0036 #endif
0037
0038 #include <boost/static_assert.hpp>
0039
0040 #include <boost/mpl/eval_if.hpp>
0041 #include <boost/mpl/identity.hpp>
0042 #include <boost/mpl/greater_equal.hpp>
0043 #include <boost/mpl/equal_to.hpp>
0044 #include <boost/core/no_exceptions_support.hpp>
0045
0046 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
0047 #include <boost/serialization/extended_type_info_typeid.hpp>
0048 #endif
0049 #include <boost/serialization/throw_exception.hpp>
0050 #include <boost/serialization/smart_cast.hpp>
0051 #include <boost/serialization/static_warning.hpp>
0052
0053 #include <boost/type_traits/is_pointer.hpp>
0054 #include <boost/type_traits/is_enum.hpp>
0055 #include <boost/type_traits/is_const.hpp>
0056 #include <boost/type_traits/remove_const.hpp>
0057 #include <boost/type_traits/remove_extent.hpp>
0058 #include <boost/type_traits/is_polymorphic.hpp>
0059
0060 #include <boost/serialization/assume_abstract.hpp>
0061
0062 #if !defined(BOOST_MSVC) && \
0063 (BOOST_WORKAROUND(__IBMCPP__, < 1210) || \
0064 defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590))
0065 #define BOOST_SERIALIZATION_DONT_USE_HAS_NEW_OPERATOR 1
0066 #else
0067 #define BOOST_SERIALIZATION_DONT_USE_HAS_NEW_OPERATOR 0
0068 #endif
0069
0070 #if ! BOOST_SERIALIZATION_DONT_USE_HAS_NEW_OPERATOR
0071 #include <boost/type_traits/has_new_operator.hpp>
0072 #endif
0073
0074 #include <boost/serialization/serialization.hpp>
0075 #include <boost/serialization/version.hpp>
0076 #include <boost/serialization/level.hpp>
0077 #include <boost/serialization/tracking.hpp>
0078 #include <boost/serialization/type_info_implementation.hpp>
0079 #include <boost/serialization/nvp.hpp>
0080 #include <boost/serialization/void_cast.hpp>
0081 #include <boost/serialization/collection_size_type.hpp>
0082 #include <boost/serialization/singleton.hpp>
0083 #include <boost/serialization/wrapper.hpp>
0084 #include <boost/serialization/array_wrapper.hpp>
0085
0086
0087 #include <boost/archive/archive_exception.hpp>
0088 #include <boost/archive/detail/basic_iarchive.hpp>
0089 #include <boost/archive/detail/basic_iserializer.hpp>
0090 #include <boost/archive/detail/basic_pointer_iserializer.hpp>
0091 #include <boost/archive/detail/archive_serializer_map.hpp>
0092 #include <boost/archive/detail/check.hpp>
0093
0094 #include <boost/core/addressof.hpp>
0095
0096 namespace boost {
0097
0098 namespace serialization {
0099 class extended_type_info;
0100 }
0101
0102 namespace archive {
0103
0104
0105
0106 class load_access {
0107 public:
0108 template<class Archive, class T>
0109 static void load_primitive(Archive &ar, T &t){
0110 ar.load(t);
0111 }
0112 };
0113
0114 namespace detail {
0115
0116 #ifdef BOOST_MSVC
0117 # pragma warning(push)
0118 # pragma warning(disable : 4511 4512)
0119 #endif
0120
0121 template<class Archive, class T>
0122 class iserializer : public basic_iserializer
0123 {
0124 private:
0125 void destroy( void *address) const BOOST_OVERRIDE {
0126 boost::serialization::access::destroy(static_cast<T *>(address));
0127 }
0128 public:
0129 explicit iserializer() :
0130 basic_iserializer(
0131 boost::serialization::singleton<
0132 typename
0133 boost::serialization::type_info_implementation< T >::type
0134 >::get_const_instance()
0135 )
0136 {}
0137 BOOST_DLLEXPORT void load_object_data(
0138 basic_iarchive & ar,
0139 void *x,
0140 const unsigned int file_version
0141 ) const BOOST_OVERRIDE BOOST_USED;
0142 bool class_info() const BOOST_OVERRIDE {
0143 return boost::serialization::implementation_level< T >::value
0144 >= boost::serialization::object_class_info;
0145 }
0146 bool tracking(const unsigned int ) const BOOST_OVERRIDE {
0147 return boost::serialization::tracking_level< T >::value
0148 == boost::serialization::track_always
0149 || ( boost::serialization::tracking_level< T >::value
0150 == boost::serialization::track_selectively
0151 && serialized_as_pointer());
0152 }
0153 version_type version() const BOOST_OVERRIDE {
0154 return version_type(::boost::serialization::version< T >::value);
0155 }
0156 bool is_polymorphic() const BOOST_OVERRIDE {
0157 return boost::is_polymorphic< T >::value;
0158 }
0159 ~iserializer() BOOST_OVERRIDE {}
0160 };
0161
0162 #ifdef BOOST_MSVC
0163 # pragma warning(pop)
0164 #endif
0165
0166 template<class Archive, class T>
0167 BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
0168 basic_iarchive & ar,
0169 void *x,
0170 const unsigned int file_version
0171 ) const {
0172
0173
0174
0175
0176
0177 #if 1
0178
0179 if(file_version > static_cast<const unsigned int>(version()))
0180 boost::serialization::throw_exception(
0181 archive::archive_exception(
0182 boost::archive::archive_exception::unsupported_class_version,
0183 get_debug_info()
0184 )
0185 );
0186 #endif
0187
0188
0189 boost::serialization::serialize_adl(
0190 boost::serialization::smart_cast_reference<Archive &>(ar),
0191 * static_cast<T *>(x),
0192 file_version
0193 );
0194 }
0195
0196 #ifdef BOOST_MSVC
0197 # pragma warning(push)
0198 # pragma warning(disable : 4511 4512)
0199 #endif
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 template<class T>
0211 struct heap_allocation {
0212
0213 #if BOOST_SERIALIZATION_DONT_USE_HAS_NEW_OPERATOR
0214
0215 static T * invoke_new(){
0216 return static_cast<T *>(operator new(sizeof(T)));
0217 }
0218 static void invoke_delete(T *t){
0219 (operator delete(t));
0220 }
0221 #else
0222
0223
0224
0225 struct has_new_operator {
0226 static T * invoke_new() {
0227 return static_cast<T *>((T::operator new)(sizeof(T)));
0228 }
0229 static void invoke_delete(T * t) {
0230
0231
0232
0233
0234
0235
0236
0237
0238 (operator delete)(t);
0239 }
0240 };
0241 struct doesnt_have_new_operator {
0242 static T* invoke_new() {
0243 return static_cast<T *>(operator new(sizeof(T)));
0244 }
0245 static void invoke_delete(T * t) {
0246
0247 (operator delete)(t);
0248 }
0249 };
0250 static T * invoke_new() {
0251 typedef typename
0252 mpl::eval_if<
0253 boost::has_new_operator< T >,
0254 mpl::identity<has_new_operator >,
0255 mpl::identity<doesnt_have_new_operator >
0256 >::type typex;
0257 return typex::invoke_new();
0258 }
0259 static void invoke_delete(T *t) {
0260 typedef typename
0261 mpl::eval_if<
0262 boost::has_new_operator< T >,
0263 mpl::identity<has_new_operator >,
0264 mpl::identity<doesnt_have_new_operator >
0265 >::type typex;
0266 typex::invoke_delete(t);
0267 }
0268 #endif
0269 explicit heap_allocation(){
0270 m_p = invoke_new();
0271 }
0272 ~heap_allocation(){
0273 if (0 != m_p)
0274 invoke_delete(m_p);
0275 }
0276 T* get() const {
0277 return m_p;
0278 }
0279
0280 T* release() {
0281 T* p = m_p;
0282 m_p = 0;
0283 return p;
0284 }
0285 private:
0286 T* m_p;
0287 };
0288
0289 template<class Archive, class T>
0290 class pointer_iserializer :
0291 public basic_pointer_iserializer
0292 {
0293 private:
0294 void * heap_allocation() const BOOST_OVERRIDE {
0295 detail::heap_allocation<T> h;
0296 T * t = h.get();
0297 h.release();
0298 return t;
0299 }
0300 const basic_iserializer & get_basic_serializer() const BOOST_OVERRIDE {
0301 return boost::serialization::singleton<
0302 iserializer<Archive, T>
0303 >::get_const_instance();
0304 }
0305 BOOST_DLLEXPORT void load_object_ptr(
0306 basic_iarchive & ar,
0307 void * x,
0308 const unsigned int file_version
0309 ) const BOOST_OVERRIDE BOOST_USED;
0310 public:
0311
0312 pointer_iserializer();
0313 ~pointer_iserializer() BOOST_OVERRIDE;
0314 };
0315
0316 #ifdef BOOST_MSVC
0317 # pragma warning(pop)
0318 #endif
0319
0320
0321
0322 template<class Archive, class T>
0323 BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
0324 basic_iarchive & ar,
0325 void * t,
0326 const unsigned int file_version
0327 ) const
0328 {
0329 Archive & ar_impl =
0330 boost::serialization::smart_cast_reference<Archive &>(ar);
0331
0332
0333
0334
0335
0336
0337
0338 BOOST_TRY {
0339
0340
0341 ar.next_object_pointer(t);
0342 boost::serialization::load_construct_data_adl<Archive, T>(
0343 ar_impl,
0344 static_cast<T *>(t),
0345 file_version
0346 );
0347 }
0348 BOOST_CATCH(...){
0349
0350
0351
0352 BOOST_RETHROW;
0353 }
0354 BOOST_CATCH_END
0355
0356 ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t));
0357 }
0358
0359 template<class Archive, class T>
0360 pointer_iserializer<Archive, T>::pointer_iserializer() :
0361 basic_pointer_iserializer(
0362 boost::serialization::singleton<
0363 typename
0364 boost::serialization::type_info_implementation< T >::type
0365 >::get_const_instance()
0366 )
0367 {
0368 boost::serialization::singleton<
0369 iserializer<Archive, T>
0370 >::get_mutable_instance().set_bpis(this);
0371 archive_serializer_map<Archive>::insert(this);
0372 }
0373
0374 template<class Archive, class T>
0375 pointer_iserializer<Archive, T>::~pointer_iserializer(){
0376 archive_serializer_map<Archive>::erase(this);
0377 }
0378
0379 template<class Archive>
0380 struct load_non_pointer_type {
0381
0382
0383 struct load_primitive {
0384 template<class T>
0385 static void invoke(Archive & ar, T & t){
0386 load_access::load_primitive(ar, t);
0387 }
0388 };
0389
0390
0391 struct load_only {
0392 template<class T>
0393 static void invoke(Archive & ar, const T & t){
0394
0395
0396
0397 boost::serialization::serialize_adl(
0398 ar,
0399 const_cast<T &>(t),
0400 boost::serialization::version< T >::value
0401 );
0402 }
0403 };
0404
0405
0406
0407 struct load_standard {
0408 template<class T>
0409 static void invoke(Archive &ar, const T & t){
0410 void * x = boost::addressof(const_cast<T &>(t));
0411 ar.load_object(
0412 x,
0413 boost::serialization::singleton<
0414 iserializer<Archive, T>
0415 >::get_const_instance()
0416 );
0417 }
0418 };
0419
0420 struct load_conditional {
0421 template<class T>
0422 static void invoke(Archive &ar, T &t){
0423
0424 load_standard::invoke(ar, t);
0425
0426
0427 }
0428 };
0429
0430 template<class T>
0431 static void invoke(Archive & ar, T &t){
0432 typedef typename mpl::eval_if<
0433
0434 mpl::equal_to<
0435 boost::serialization::implementation_level< T >,
0436 mpl::int_<boost::serialization::primitive_type>
0437 >,
0438 mpl::identity<load_primitive>,
0439
0440 typename mpl::eval_if<
0441
0442 mpl::greater_equal<
0443 boost::serialization::implementation_level< T >,
0444 mpl::int_<boost::serialization::object_class_info>
0445 >,
0446
0447 mpl::identity<load_standard>,
0448
0449 typename mpl::eval_if<
0450
0451 mpl::equal_to<
0452 boost::serialization::tracking_level< T >,
0453 mpl::int_<boost::serialization::track_never>
0454 >,
0455
0456 mpl::identity<load_only>,
0457
0458
0459 mpl::identity<load_conditional>
0460 > > >::type typex;
0461 check_object_versioning< T >();
0462 check_object_level< T >();
0463 typex::invoke(ar, t);
0464 }
0465 };
0466
0467 template<class Archive>
0468 struct load_pointer_type {
0469 struct abstract
0470 {
0471 template<class T>
0472 static const basic_pointer_iserializer * register_type(Archive & ){
0473
0474 BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
0475 return static_cast<basic_pointer_iserializer *>(NULL);
0476 }
0477 };
0478
0479 struct non_abstract
0480 {
0481 template<class T>
0482 static const basic_pointer_iserializer * register_type(Archive & ar){
0483 return ar.register_type(static_cast<T *>(NULL));
0484 }
0485 };
0486
0487 template<class T>
0488 static const basic_pointer_iserializer * register_type(Archive &ar, const T* const ){
0489
0490
0491
0492
0493 typedef typename
0494 mpl::eval_if<
0495 boost::serialization::is_abstract<const T>,
0496 boost::mpl::identity<abstract>,
0497 boost::mpl::identity<non_abstract>
0498 >::type typex;
0499 return typex::template register_type< T >(ar);
0500 }
0501
0502 template<class T>
0503 static T * pointer_tweak(
0504 const boost::serialization::extended_type_info & eti,
0505 void const * const t,
0506 const T &
0507 ) {
0508
0509 void * upcast = const_cast<void *>(
0510 boost::serialization::void_upcast(
0511 eti,
0512 boost::serialization::singleton<
0513 typename
0514 boost::serialization::type_info_implementation< T >::type
0515 >::get_const_instance(),
0516 t
0517 )
0518 );
0519 if(NULL == upcast)
0520 boost::serialization::throw_exception(
0521 archive_exception(archive_exception::unregistered_class)
0522 );
0523 return static_cast<T *>(upcast);
0524 }
0525
0526 template<class T>
0527 static void check_load(T * const ){
0528 check_pointer_level< T >();
0529 check_pointer_tracking< T >();
0530 }
0531
0532 static const basic_pointer_iserializer *
0533 find(const boost::serialization::extended_type_info & type){
0534 return static_cast<const basic_pointer_iserializer *>(
0535 archive_serializer_map<Archive>::find(type)
0536 );
0537 }
0538
0539 template<class Tptr>
0540 static void invoke(Archive & ar, Tptr & t){
0541 check_load(t);
0542 const basic_pointer_iserializer * bpis_ptr = register_type(ar, t);
0543 const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
0544
0545
0546
0547
0548 (void * & )t,
0549 bpis_ptr,
0550 find
0551 );
0552
0553 if(newbpis_ptr != bpis_ptr){
0554 t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
0555 }
0556 }
0557 };
0558
0559 template<class Archive>
0560 struct load_enum_type {
0561 template<class T>
0562 static void invoke(Archive &ar, T &t){
0563
0564 int i;
0565 ar >> boost::serialization::make_nvp(NULL, i);
0566 t = static_cast< T >(i);
0567 }
0568 };
0569
0570 template<class Archive>
0571 struct load_array_type {
0572 template<class T>
0573 static void invoke(Archive &ar, T &t){
0574 typedef typename remove_extent< T >::type value_type;
0575
0576
0577
0578
0579
0580 std::size_t current_count = sizeof(t) / (
0581 static_cast<char *>(static_cast<void *>(&t[1]))
0582 - static_cast<char *>(static_cast<void *>(&t[0]))
0583 );
0584 boost::serialization::collection_size_type count;
0585 ar >> BOOST_SERIALIZATION_NVP(count);
0586 if(static_cast<std::size_t>(count) > current_count)
0587 boost::serialization::throw_exception(
0588 archive::archive_exception(
0589 boost::archive::archive_exception::array_size_too_short
0590 )
0591 );
0592
0593 ar >> serialization::make_array<
0594 value_type,
0595 boost::serialization::collection_size_type
0596 >(
0597 static_cast<value_type *>(&t[0]),
0598 count
0599 );
0600 }
0601 };
0602
0603 }
0604
0605 template<class Archive, class T>
0606 inline void load(Archive & ar, T &t){
0607
0608
0609
0610
0611 detail::check_const_loading< T >();
0612 typedef
0613 typename mpl::eval_if<is_pointer< T >,
0614 mpl::identity<detail::load_pointer_type<Archive> >
0615 ,
0616 typename mpl::eval_if<is_array< T >,
0617 mpl::identity<detail::load_array_type<Archive> >
0618 ,
0619 typename mpl::eval_if<is_enum< T >,
0620 mpl::identity<detail::load_enum_type<Archive> >
0621 ,
0622 mpl::identity<detail::load_non_pointer_type<Archive> >
0623 >
0624 >
0625 >::type typex;
0626 typex::invoke(ar, t);
0627 }
0628
0629 }
0630 }
0631
0632 #endif