comparison DEPENDENCIES/generic/include/boost/archive/detail/iserializer.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
comparison
equal deleted inserted replaced
100:793467b5e61c 101:c530137014c0
1 #ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP 1 #ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
2 #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP 2 #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
3 3
4 // MS compatible compilers support #pragma once 4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER) && (_MSC_VER >= 1020) 5 #if defined(_MSC_VER)
6 # pragma once 6 # pragma once
7 #pragma inline_depth(511) 7 #pragma inline_depth(511)
8 #pragma inline_recursion(on) 8 #pragma inline_recursion(on)
9 #endif 9 #endif
10 10
21 // http://www.boost.org/LICENSE_1_0.txt) 21 // http://www.boost.org/LICENSE_1_0.txt)
22 22
23 // See http://www.boost.org for updates, documentation, and revision history. 23 // See http://www.boost.org for updates, documentation, and revision history.
24 24
25 #include <new> // for placement new 25 #include <new> // for placement new
26 #include <memory> // for auto_ptr
27 #include <cstddef> // size_t, NULL 26 #include <cstddef> // size_t, NULL
28 27
29 #include <boost/config.hpp> 28 #include <boost/config.hpp>
30 #include <boost/detail/workaround.hpp> 29 #include <boost/detail/workaround.hpp>
31 #if defined(BOOST_NO_STDC_NAMESPACE) 30 #if defined(BOOST_NO_STDC_NAMESPACE)
39 #include <boost/mpl/eval_if.hpp> 38 #include <boost/mpl/eval_if.hpp>
40 #include <boost/mpl/identity.hpp> 39 #include <boost/mpl/identity.hpp>
41 #include <boost/mpl/greater_equal.hpp> 40 #include <boost/mpl/greater_equal.hpp>
42 #include <boost/mpl/equal_to.hpp> 41 #include <boost/mpl/equal_to.hpp>
43 #include <boost/mpl/bool.hpp> 42 #include <boost/mpl/bool.hpp>
44 #include <boost/detail/no_exceptions_support.hpp> 43 #include <boost/core/no_exceptions_support.hpp>
45 44
46 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO 45 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
47 #include <boost/serialization/extended_type_info_typeid.hpp> 46 #include <boost/serialization/extended_type_info_typeid.hpp>
48 #endif 47 #endif
49 #include <boost/serialization/throw_exception.hpp> 48 #include <boost/serialization/throw_exception.hpp>
56 #include <boost/type_traits/remove_const.hpp> 55 #include <boost/type_traits/remove_const.hpp>
57 #include <boost/type_traits/remove_extent.hpp> 56 #include <boost/type_traits/remove_extent.hpp>
58 #include <boost/type_traits/is_polymorphic.hpp> 57 #include <boost/type_traits/is_polymorphic.hpp>
59 58
60 #include <boost/serialization/assume_abstract.hpp> 59 #include <boost/serialization/assume_abstract.hpp>
61
62 #define DONT_USE_HAS_NEW_OPERATOR ( \ 60 #define DONT_USE_HAS_NEW_OPERATOR ( \
63 defined(__BORLANDC__) \ 61 defined(__BORLANDC__) \
64 || BOOST_WORKAROUND(__IBMCPP__, < 1210) \ 62 || BOOST_WORKAROUND(__IBMCPP__, < 1210) \
65 || defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) \
66 || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \ 63 || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \
67 ) 64 )
68
69 #if ! DONT_USE_HAS_NEW_OPERATOR 65 #if ! DONT_USE_HAS_NEW_OPERATOR
70 #include <boost/type_traits/has_new_operator.hpp> 66 #include <boost/type_traits/has_new_operator.hpp>
71 #endif 67 #endif
72 68
73 #include <boost/serialization/serialization.hpp> 69 #include <boost/serialization/serialization.hpp>
125 protected: 121 protected:
126 // protected constructor since it's always created by singleton 122 // protected constructor since it's always created by singleton
127 explicit iserializer() : 123 explicit iserializer() :
128 basic_iserializer( 124 basic_iserializer(
129 boost::serialization::singleton< 125 boost::serialization::singleton<
130 BOOST_DEDUCED_TYPENAME 126 typename
131 boost::serialization::type_info_implementation< T >::type 127 boost::serialization::type_info_implementation< T >::type
132 >::get_const_instance() 128 >::get_const_instance()
133 ) 129 )
134 {} 130 {}
135 public: 131 public:
195 #ifdef BOOST_MSVC 191 #ifdef BOOST_MSVC
196 # pragma warning(push) 192 # pragma warning(push)
197 # pragma warning(disable : 4511 4512) 193 # pragma warning(disable : 4511 4512)
198 #endif 194 #endif
199 195
196 // the purpose of this code is to allocate memory for an object
197 // without requiring the constructor to be called. Presumably
198 // the allocated object will be subsequently initialized with
199 // "placement new".
200 // note: we have the boost type trait has_new_operator but we
201 // have no corresponding has_delete_operator. So we presume
202 // that the former being true would imply that the a delete
203 // operator is also defined for the class T.
204
205 template<class T>
206 struct heap_allocation {
207 // boost::has_new_operator< T > doesn't work on these compilers
208 #if DONT_USE_HAS_NEW_OPERATOR
209 // This doesn't handle operator new overload for class T
210 static T * invoke_new(){
211 return static_cast<T *>(operator new(sizeof(T)));
212 }
213 static void invoke_delete(T *t){
214 (operator delete(t));
215 }
216 #else
217 // note: we presume that a true value for has_new_operator
218 // implies the existence of a class specific delete operator as well
219 // as a class specific new operator.
220 struct has_new_operator {
221 static T * invoke_new() {
222 return static_cast<T *>((T::operator new)(sizeof(T)));
223 }
224 static void invoke_delete(T * t) {
225 // if compilation fails here, the likely cause that the class
226 // T has a class specific new operator but no class specific
227 // delete operator which matches the following signature. Fix
228 // your program to have this. Note that adding operator delete
229 // with only one parameter doesn't seem correct to me since
230 // the standard(3.7.4.2) says "
231 // "If a class T has a member deallocation function named
232 // 'operator delete' with exactly one parameter, then that function
233 // is a usual (non-placement) deallocation function" which I take
234 // to mean that it will call the destructor of type T which we don't
235 // want to do here.
236 // Note: reliance upon automatic conversion from T * to void * here
237 (T::operator delete)(t, sizeof(T));
238 }
239 };
240 struct doesnt_have_new_operator {
241 static T* invoke_new() {
242 return static_cast<T *>(operator new(sizeof(T)));
243 }
244 static void invoke_delete(T * t) {
245 // Note: I'm reliance upon automatic conversion from T * to void * here
246 (operator delete)(t);
247 }
248 };
249 static T * invoke_new() {
250 typedef typename
251 mpl::eval_if<
252 boost::has_new_operator< T >,
253 mpl::identity<has_new_operator >,
254 mpl::identity<doesnt_have_new_operator >
255 >::type typex;
256 return typex::invoke_new();
257 }
258 static void invoke_delete(T *t) {
259 typedef typename
260 mpl::eval_if<
261 boost::has_new_operator< T >,
262 mpl::identity<has_new_operator >,
263 mpl::identity<doesnt_have_new_operator >
264 >::type typex;
265 typex::invoke_delete(t);
266 }
267 #endif
268 explicit heap_allocation(){
269 m_p = invoke_new();
270 }
271 ~heap_allocation(){
272 if (0 != m_p)
273 invoke_delete(m_p);
274 }
275 T* get() const {
276 return m_p;
277 }
278
279 T* release() {
280 T* p = m_p;
281 m_p = 0;
282 return p;
283 }
284 private:
285 T* m_p;
286 };
287
200 template<class Archive, class T> 288 template<class Archive, class T>
201 class pointer_iserializer : 289 class pointer_iserializer :
202 public basic_pointer_iserializer 290 public basic_pointer_iserializer
203 { 291 {
204 private: 292 private:
293 virtual void * heap_allocation() const {
294 detail::heap_allocation<T> h;
295 T * t = h.get();
296 h.release();
297 return t;
298 }
205 virtual const basic_iserializer & get_basic_serializer() const { 299 virtual const basic_iserializer & get_basic_serializer() const {
206 return boost::serialization::singleton< 300 return boost::serialization::singleton<
207 iserializer<Archive, T> 301 iserializer<Archive, T>
208 >::get_const_instance(); 302 >::get_const_instance();
209 } 303 }
210 BOOST_DLLEXPORT virtual void load_object_ptr( 304 BOOST_DLLEXPORT virtual void load_object_ptr(
211 basic_iarchive & ar, 305 basic_iarchive & ar,
212 void * & x, 306 void * x,
213 const unsigned int file_version 307 const unsigned int file_version
214 ) const BOOST_USED; 308 ) const BOOST_USED;
215 protected: 309 protected:
216 // this should alway be a singleton so make the constructor protected 310 // this should alway be a singleton so make the constructor protected
217 pointer_iserializer(); 311 pointer_iserializer();
220 314
221 #ifdef BOOST_MSVC 315 #ifdef BOOST_MSVC
222 # pragma warning(pop) 316 # pragma warning(pop)
223 #endif 317 #endif
224 318
225 // note trick to be sure that operator new is using class specific
226 // version if such exists. Due to Peter Dimov.
227 // note: the following fails if T has no default constructor.
228 // otherwise it would have been ideal
229 //struct heap_allocator : public T
230 //{
231 // T * invoke(){
232 // return ::new(sizeof(T));
233 // }
234 //}
235
236 template<class T>
237 struct heap_allocator
238 {
239 // boost::has_new_operator< T > doesn't work on these compilers
240 #if DONT_USE_HAS_NEW_OPERATOR
241 // This doesn't handle operator new overload for class T
242 static T * invoke(){
243 return static_cast<T *>(operator new(sizeof(T)));
244 }
245 #else
246 struct has_new_operator {
247 static T* invoke() {
248 return static_cast<T *>((T::operator new)(sizeof(T)));
249 }
250 };
251 struct doesnt_have_new_operator {
252 static T* invoke() {
253 return static_cast<T *>(operator new(sizeof(T)));
254 }
255 };
256 static T * invoke() {
257 typedef BOOST_DEDUCED_TYPENAME
258 mpl::eval_if<
259 boost::has_new_operator< T >,
260 mpl::identity<has_new_operator >,
261 mpl::identity<doesnt_have_new_operator >
262 >::type typex;
263 return typex::invoke();
264 }
265 #endif
266 };
267
268 // due to Martin Ecker
269 template <typename T>
270 class auto_ptr_with_deleter
271 {
272 public:
273 explicit auto_ptr_with_deleter(T* p) :
274 m_p(p)
275 {}
276 ~auto_ptr_with_deleter(){
277 if (m_p)
278 boost::serialization::access::destroy(m_p);
279 }
280 T* get() const {
281 return m_p;
282 }
283
284 T* release() {
285 T* p = m_p;
286 m_p = NULL;
287 return p;
288 }
289 private:
290 T* m_p;
291 };
292
293 // note: BOOST_DLLEXPORT is so that code for polymorphic class 319 // note: BOOST_DLLEXPORT is so that code for polymorphic class
294 // serialized only through base class won't get optimized out 320 // serialized only through base class won't get optimized out
295 template<class Archive, class T> 321 template<class Archive, class T>
296 BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr( 322 BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
297 basic_iarchive & ar, 323 basic_iarchive & ar,
298 void * & x, 324 void * t,
299 const unsigned int file_version 325 const unsigned int file_version
300 ) const 326 ) const
301 { 327 {
302 Archive & ar_impl = 328 Archive & ar_impl =
303 boost::serialization::smart_cast_reference<Archive &>(ar); 329 boost::serialization::smart_cast_reference<Archive &>(ar);
304 330
305 auto_ptr_with_deleter< T > ap(heap_allocator< T >::invoke()); 331 // note that the above will throw std::bad_alloc if the allocation
306 if(NULL == ap.get()) 332 // fails so we don't have to address this contingency here.
307 boost::serialization::throw_exception(std::bad_alloc()) ;
308
309 T * t = ap.get();
310 x = t;
311 333
312 // catch exception during load_construct_data so that we don't 334 // catch exception during load_construct_data so that we don't
313 // automatically delete the t which is most likely not fully 335 // automatically delete the t which is most likely not fully
314 // constructed 336 // constructed
315 BOOST_TRY { 337 BOOST_TRY {
316 // this addresses an obscure situtation that occurs when 338 // this addresses an obscure situation that occurs when
317 // load_constructor de-serializes something through a pointer. 339 // load_constructor de-serializes something through a pointer.
318 ar.next_object_pointer(t); 340 ar.next_object_pointer(t);
319 boost::serialization::load_construct_data_adl<Archive, T>( 341 boost::serialization::load_construct_data_adl<Archive, T>(
320 ar_impl, 342 ar_impl,
321 t, 343 static_cast<T *>(t),
322 file_version 344 file_version
323 ); 345 );
324 } 346 }
325 BOOST_CATCH(...){ 347 BOOST_CATCH(...){
326 ap.release(); 348 // if we get here the load_construct failed. The heap_allocation
349 // will be automatically deleted so we don't have to do anything
350 // special here.
327 BOOST_RETHROW; 351 BOOST_RETHROW;
328 } 352 }
329 BOOST_CATCH_END 353 BOOST_CATCH_END
330 354
331 ar_impl >> boost::serialization::make_nvp(NULL, * t); 355 ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t));
332 ap.release();
333 } 356 }
334 357
335 template<class Archive, class T> 358 template<class Archive, class T>
336 pointer_iserializer<Archive, T>::pointer_iserializer() : 359 pointer_iserializer<Archive, T>::pointer_iserializer() :
337 basic_pointer_iserializer( 360 basic_pointer_iserializer(
338 boost::serialization::singleton< 361 boost::serialization::singleton<
339 BOOST_DEDUCED_TYPENAME 362 typename
340 boost::serialization::type_info_implementation< T >::type 363 boost::serialization::type_info_implementation< T >::type
341 >::get_const_instance() 364 >::get_const_instance()
342 ) 365 )
343 { 366 {
344 boost::serialization::singleton< 367 boost::serialization::singleton<
403 } 426 }
404 }; 427 };
405 428
406 template<class T> 429 template<class T>
407 static void invoke(Archive & ar, T &t){ 430 static void invoke(Archive & ar, T &t){
408 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< 431 typedef typename mpl::eval_if<
409 // if its primitive 432 // if its primitive
410 mpl::equal_to< 433 mpl::equal_to<
411 boost::serialization::implementation_level< T >, 434 boost::serialization::implementation_level< T >,
412 mpl::int_<boost::serialization::primitive_type> 435 mpl::int_<boost::serialization::primitive_type>
413 >, 436 >,
414 mpl::identity<load_primitive>, 437 mpl::identity<load_primitive>,
415 // else 438 // else
416 BOOST_DEDUCED_TYPENAME mpl::eval_if< 439 typename mpl::eval_if<
417 // class info / version 440 // class info / version
418 mpl::greater_equal< 441 mpl::greater_equal<
419 boost::serialization::implementation_level< T >, 442 boost::serialization::implementation_level< T >,
420 mpl::int_<boost::serialization::object_class_info> 443 mpl::int_<boost::serialization::object_class_info>
421 >, 444 >,
422 // do standard load 445 // do standard load
423 mpl::identity<load_standard>, 446 mpl::identity<load_standard>,
424 // else 447 // else
425 BOOST_DEDUCED_TYPENAME mpl::eval_if< 448 typename mpl::eval_if<
426 // no tracking 449 // no tracking
427 mpl::equal_to< 450 mpl::equal_to<
428 boost::serialization::tracking_level< T >, 451 boost::serialization::tracking_level< T >,
429 mpl::int_<boost::serialization::track_never> 452 mpl::int_<boost::serialization::track_never>
430 >, 453 >,
464 static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){ 487 static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){
465 // there should never be any need to load an abstract polymorphic 488 // there should never be any need to load an abstract polymorphic
466 // class pointer. Inhibiting code generation for this 489 // class pointer. Inhibiting code generation for this
467 // permits abstract base classes to be used - note: exception 490 // permits abstract base classes to be used - note: exception
468 // virtual serialize functions used for plug-ins 491 // virtual serialize functions used for plug-ins
469 typedef BOOST_DEDUCED_TYPENAME 492 typedef typename
470 mpl::eval_if< 493 mpl::eval_if<
471 boost::serialization::is_abstract<const T>, 494 boost::serialization::is_abstract<const T>,
472 boost::mpl::identity<abstract>, 495 boost::mpl::identity<abstract>,
473 boost::mpl::identity<non_abstract> 496 boost::mpl::identity<non_abstract>
474 >::type typex; 497 >::type typex;
480 const boost::serialization::extended_type_info & eti, 503 const boost::serialization::extended_type_info & eti,
481 void const * const t, 504 void const * const t,
482 const T & 505 const T &
483 ) { 506 ) {
484 // tweak the pointer back to the base class 507 // tweak the pointer back to the base class
485 return static_cast<T *>( 508 void * upcast = const_cast<void *>(
486 const_cast<void *>( 509 boost::serialization::void_upcast(
487 boost::serialization::void_upcast( 510 eti,
488 eti, 511 boost::serialization::singleton<
489 boost::serialization::singleton< 512 typename
490 BOOST_DEDUCED_TYPENAME 513 boost::serialization::type_info_implementation< T >::type
491 boost::serialization::type_info_implementation< T >::type 514 >::get_const_instance(),
492 >::get_const_instance(), 515 t
493 t
494 )
495 ) 516 )
496 ); 517 );
518 if(NULL == upcast)
519 boost::serialization::throw_exception(
520 archive_exception(archive_exception::unregistered_class)
521 );
522 return static_cast<T *>(upcast);
497 } 523 }
498 524
499 template<class T> 525 template<class T>
500 static void check_load(T & /* t */){ 526 static void check_load(T & /* t */){
501 check_pointer_level< T >(); 527 check_pointer_level< T >();
542 568
543 template<class Archive> 569 template<class Archive>
544 struct load_array_type { 570 struct load_array_type {
545 template<class T> 571 template<class T>
546 static void invoke(Archive &ar, T &t){ 572 static void invoke(Archive &ar, T &t){
547 typedef BOOST_DEDUCED_TYPENAME remove_extent< T >::type value_type; 573 typedef typename remove_extent< T >::type value_type;
548 574
549 // convert integers to correct enum to load 575 // convert integers to correct enum to load
550 // determine number of elements in the array. Consider the 576 // determine number of elements in the array. Consider the
551 // fact that some machines will align elements on boundries 577 // fact that some machines will align elements on boundries
552 // other than characters. 578 // other than characters.
574 // const object with a compiler that doesn't have correct 600 // const object with a compiler that doesn't have correct
575 // funtion template ordering. On other compilers, this is 601 // funtion template ordering. On other compilers, this is
576 // handled below. 602 // handled below.
577 detail::check_const_loading< T >(); 603 detail::check_const_loading< T >();
578 typedef 604 typedef
579 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >, 605 typename mpl::eval_if<is_pointer< T >,
580 mpl::identity<detail::load_pointer_type<Archive> > 606 mpl::identity<detail::load_pointer_type<Archive> >
581 ,//else 607 ,//else
582 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >, 608 typename mpl::eval_if<is_array< T >,
583 mpl::identity<detail::load_array_type<Archive> > 609 mpl::identity<detail::load_array_type<Archive> >
584 ,//else 610 ,//else
585 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >, 611 typename mpl::eval_if<is_enum< T >,
586 mpl::identity<detail::load_enum_type<Archive> > 612 mpl::identity<detail::load_enum_type<Archive> >
587 ,//else 613 ,//else
588 mpl::identity<detail::load_non_pointer_type<Archive> > 614 mpl::identity<detail::load_non_pointer_type<Archive> >
589 > 615 >
590 > 616 >