]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/serialization/include/boost/archive/detail/iserializer.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / serialization / include / boost / archive / detail / iserializer.hpp
CommitLineData
7c673cae
FG
1#ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
2#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
3
4// MS compatible compilers support #pragma once
5#if defined(_MSC_VER)
6# pragma once
7#pragma inline_depth(511)
8#pragma inline_recursion(on)
9#endif
10
11#if defined(__MWERKS__)
12#pragma inline_depth(511)
13#endif
14
15/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
16// iserializer.hpp: interface for serialization system.
17
18// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
19// Use, modification and distribution is subject to the Boost Software
20// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
21// http://www.boost.org/LICENSE_1_0.txt)
22
23// See http://www.boost.org for updates, documentation, and revision history.
24
25#include <new> // for placement new
26#include <cstddef> // size_t, NULL
27
28#include <boost/config.hpp>
29#include <boost/detail/workaround.hpp>
30#if defined(BOOST_NO_STDC_NAMESPACE)
31namespace std{
32 using ::size_t;
33} // namespace std
34#endif
35
36#include <boost/static_assert.hpp>
37
38#include <boost/mpl/eval_if.hpp>
39#include <boost/mpl/identity.hpp>
40#include <boost/mpl/greater_equal.hpp>
41#include <boost/mpl/equal_to.hpp>
42#include <boost/core/no_exceptions_support.hpp>
43
44#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
45 #include <boost/serialization/extended_type_info_typeid.hpp>
46#endif
47#include <boost/serialization/throw_exception.hpp>
48#include <boost/serialization/smart_cast.hpp>
49#include <boost/serialization/static_warning.hpp>
50
51#include <boost/type_traits/is_pointer.hpp>
52#include <boost/type_traits/is_enum.hpp>
53#include <boost/type_traits/is_const.hpp>
54#include <boost/type_traits/remove_const.hpp>
55#include <boost/type_traits/remove_extent.hpp>
56#include <boost/type_traits/is_polymorphic.hpp>
57
58#include <boost/serialization/assume_abstract.hpp>
59
60#ifndef BOOST_MSVC
61 #define DONT_USE_HAS_NEW_OPERATOR ( \
62 BOOST_WORKAROUND(__IBMCPP__, < 1210) \
63 || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \
64 )
65#else
66 #define DONT_USE_HAS_NEW_OPERATOR 0
67#endif
68
69#if ! DONT_USE_HAS_NEW_OPERATOR
70#include <boost/type_traits/has_new_operator.hpp>
71#endif
72
73#include <boost/serialization/serialization.hpp>
74#include <boost/serialization/version.hpp>
75#include <boost/serialization/level.hpp>
76#include <boost/serialization/tracking.hpp>
77#include <boost/serialization/type_info_implementation.hpp>
78#include <boost/serialization/nvp.hpp>
79#include <boost/serialization/void_cast.hpp>
80#include <boost/serialization/array.hpp>
81#include <boost/serialization/collection_size_type.hpp>
82#include <boost/serialization/singleton.hpp>
83#include <boost/serialization/wrapper.hpp>
84
85// the following is need only for dynamic cast of polymorphic pointers
86#include <boost/archive/archive_exception.hpp>
87#include <boost/archive/detail/basic_iarchive.hpp>
88#include <boost/archive/detail/basic_iserializer.hpp>
89#include <boost/archive/detail/basic_pointer_iserializer.hpp>
90#include <boost/archive/detail/archive_serializer_map.hpp>
91#include <boost/archive/detail/check.hpp>
92
93namespace boost {
94
95namespace serialization {
96 class extended_type_info;
97} // namespace serialization
98
99namespace archive {
100
101// an accessor to permit friend access to archives. Needed because
102// some compilers don't handle friend templates completely
103class load_access {
104public:
105 template<class Archive, class T>
106 static void load_primitive(Archive &ar, T &t){
107 ar.load(t);
108 }
109};
110
111namespace detail {
112
113#ifdef BOOST_MSVC
114# pragma warning(push)
115# pragma warning(disable : 4511 4512)
116#endif
117
118template<class Archive, class T>
119class iserializer : public basic_iserializer
120{
121private:
122 virtual void destroy(/*const*/ void *address) const {
123 boost::serialization::access::destroy(static_cast<T *>(address));
124 }
125protected:
126 // protected constructor since it's always created by singleton
127 explicit iserializer() :
128 basic_iserializer(
129 boost::serialization::singleton<
130 typename
131 boost::serialization::type_info_implementation< T >::type
132 >::get_const_instance()
133 )
134 {}
135public:
136 virtual BOOST_DLLEXPORT void load_object_data(
137 basic_iarchive & ar,
138 void *x,
139 const unsigned int file_version
140 ) const BOOST_USED;
141 virtual bool class_info() const {
142 return boost::serialization::implementation_level< T >::value
143 >= boost::serialization::object_class_info;
144 }
145 virtual bool tracking(const unsigned int /* flags */) const {
146 return boost::serialization::tracking_level< T >::value
147 == boost::serialization::track_always
148 || ( boost::serialization::tracking_level< T >::value
149 == boost::serialization::track_selectively
150 && serialized_as_pointer());
151 }
152 virtual version_type version() const {
153 return version_type(::boost::serialization::version< T >::value);
154 }
155 virtual bool is_polymorphic() const {
156 return boost::is_polymorphic< T >::value;
157 }
158 virtual ~iserializer(){};
159};
160
161#ifdef BOOST_MSVC
162# pragma warning(pop)
163#endif
164
165template<class Archive, class T>
166BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
167 basic_iarchive & ar,
168 void *x,
169 const unsigned int file_version
170) const {
171 // note: we now comment this out. Before we permited archive
172 // version # to be very large. Now we don't. To permit
173 // readers of these old archives, we have to suppress this
174 // code. Perhaps in the future we might re-enable it but
175 // permit its suppression with a runtime switch.
176 #if 0
177 // trap case where the program cannot handle the current version
178 if(file_version > static_cast<const unsigned int>(version()))
179 boost::serialization::throw_exception(
180 archive::archive_exception(
181 boost::archive::archive_exception::unsupported_class_version,
182 get_debug_info()
183 )
184 );
185 #endif
186 // make sure call is routed through the higest interface that might
187 // be specialized by the user.
188 boost::serialization::serialize_adl(
189 boost::serialization::smart_cast_reference<Archive &>(ar),
190 * static_cast<T *>(x),
191 file_version
192 );
193}
194
195#ifdef BOOST_MSVC
196# pragma warning(push)
197# pragma warning(disable : 4511 4512)
198#endif
199
200// the purpose of this code is to allocate memory for an object
201// without requiring the constructor to be called. Presumably
202// the allocated object will be subsequently initialized with
203// "placement new".
204// note: we have the boost type trait has_new_operator but we
205// have no corresponding has_delete_operator. So we presume
206// that the former being true would imply that the a delete
207// operator is also defined for the class T.
208
209template<class T>
210struct heap_allocation {
211 // boost::has_new_operator< T > doesn't work on these compilers
212 #if DONT_USE_HAS_NEW_OPERATOR
213 // This doesn't handle operator new overload for class T
214 static T * invoke_new(){
215 return static_cast<T *>(operator new(sizeof(T)));
216 }
217 static void invoke_delete(T *t){
218 (operator delete(t));
219 }
220 #else
221 // note: we presume that a true value for has_new_operator
222 // implies the existence of a class specific delete operator as well
223 // as a class specific new operator.
224 struct has_new_operator {
225 static T * invoke_new() {
226 return static_cast<T *>((T::operator new)(sizeof(T)));
227 }
228 static void invoke_delete(T * t) {
229 // if compilation fails here, the likely cause that the class
230 // T has a class specific new operator but no class specific
231 // delete operator which matches the following signature.
232 // note that this solution addresses the issue that two
233 // possible signatures. But it doesn't address the possibility
234 // that the class might have class specific new with NO
235 // class specific delete at all. Patches (compatible with
236 // C++03) welcome!
237 delete 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 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 }
284private:
285 T* m_p;
286};
287
288template<class Archive, class T>
289class pointer_iserializer :
290 public basic_pointer_iserializer
291{
292private:
293 virtual void * heap_allocation() const {
294 detail::heap_allocation<T> h;
295 T * t = h.get();
296 h.release();
297 return t;
298 }
299 virtual const basic_iserializer & get_basic_serializer() const {
300 return boost::serialization::singleton<
301 iserializer<Archive, T>
302 >::get_const_instance();
303 }
304 BOOST_DLLEXPORT virtual void load_object_ptr(
305 basic_iarchive & ar,
306 void * x,
307 const unsigned int file_version
308 ) const BOOST_USED;
309protected:
310 // this should alway be a singleton so make the constructor protected
311 pointer_iserializer();
312 ~pointer_iserializer();
313};
314
315#ifdef BOOST_MSVC
316# pragma warning(pop)
317#endif
318
319// note: BOOST_DLLEXPORT is so that code for polymorphic class
320// serialized only through base class won't get optimized out
321template<class Archive, class T>
322BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
323 basic_iarchive & ar,
324 void * t,
325 const unsigned int file_version
326) const
327{
328 Archive & ar_impl =
329 boost::serialization::smart_cast_reference<Archive &>(ar);
330
331 // note that the above will throw std::bad_alloc if the allocation
332 // fails so we don't have to address this contingency here.
333
334 // catch exception during load_construct_data so that we don't
335 // automatically delete the t which is most likely not fully
336 // constructed
337 BOOST_TRY {
338 // this addresses an obscure situation that occurs when
339 // load_constructor de-serializes something through a pointer.
340 ar.next_object_pointer(t);
341 boost::serialization::load_construct_data_adl<Archive, T>(
342 ar_impl,
343 static_cast<T *>(t),
344 file_version
345 );
346 }
347 BOOST_CATCH(...){
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.
351 BOOST_RETHROW;
352 }
353 BOOST_CATCH_END
354
355 ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t));
356}
357
358template<class Archive, class T>
359pointer_iserializer<Archive, T>::pointer_iserializer() :
360 basic_pointer_iserializer(
361 boost::serialization::singleton<
362 typename
363 boost::serialization::type_info_implementation< T >::type
364 >::get_const_instance()
365 )
366{
367 boost::serialization::singleton<
368 iserializer<Archive, T>
369 >::get_mutable_instance().set_bpis(this);
370 archive_serializer_map<Archive>::insert(this);
371}
372
373template<class Archive, class T>
374pointer_iserializer<Archive, T>::~pointer_iserializer(){
375 archive_serializer_map<Archive>::erase(this);
376}
377
378template<class Archive>
379struct load_non_pointer_type {
380 // note this bounces the call right back to the archive
381 // with no runtime overhead
382 struct load_primitive {
383 template<class T>
384 static void invoke(Archive & ar, T & t){
385 load_access::load_primitive(ar, t);
386 }
387 };
388 // note this bounces the call right back to the archive
389 // with no runtime overhead
390 struct load_only {
391 template<class T>
392 static void invoke(Archive & ar, const T & t){
393 // short cut to user's serializer
394 // make sure call is routed through the higest interface that might
395 // be specialized by the user.
396 boost::serialization::serialize_adl(
397 ar,
398 const_cast<T &>(t),
399 boost::serialization::version< T >::value
400 );
401 }
402 };
403
404 // note this save class information including version
405 // and serialization level to the archive
406 struct load_standard {
407 template<class T>
408 static void invoke(Archive &ar, const T & t){
409 void * x = & const_cast<T &>(t);
410 ar.load_object(
411 x,
412 boost::serialization::singleton<
413 iserializer<Archive, T>
414 >::get_const_instance()
415 );
416 }
417 };
418
419 struct load_conditional {
420 template<class T>
421 static void invoke(Archive &ar, T &t){
422 //if(0 == (ar.get_flags() & no_tracking))
423 load_standard::invoke(ar, t);
424 //else
425 // load_only::invoke(ar, t);
426 }
427 };
428
429 template<class T>
430 static void invoke(Archive & ar, T &t){
431 typedef typename mpl::eval_if<
432 // if its primitive
433 mpl::equal_to<
434 boost::serialization::implementation_level< T >,
435 mpl::int_<boost::serialization::primitive_type>
436 >,
437 mpl::identity<load_primitive>,
438 // else
439 typename mpl::eval_if<
440 // class info / version
441 mpl::greater_equal<
442 boost::serialization::implementation_level< T >,
443 mpl::int_<boost::serialization::object_class_info>
444 >,
445 // do standard load
446 mpl::identity<load_standard>,
447 // else
448 typename mpl::eval_if<
449 // no tracking
450 mpl::equal_to<
451 boost::serialization::tracking_level< T >,
452 mpl::int_<boost::serialization::track_never>
453 >,
454 // do a fast load
455 mpl::identity<load_only>,
456 // else
457 // do a fast load only tracking is turned off
458 mpl::identity<load_conditional>
459 > > >::type typex;
460 check_object_versioning< T >();
461 check_object_level< T >();
462 typex::invoke(ar, t);
463 }
464};
465
466template<class Archive>
467struct load_pointer_type {
468 struct abstract
469 {
470 template<class T>
471 static const basic_pointer_iserializer * register_type(Archive & /* ar */){
472 // it has? to be polymorphic
473 BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
474 return static_cast<basic_pointer_iserializer *>(NULL);
475 }
476 };
477
478 struct non_abstract
479 {
480 template<class T>
481 static const basic_pointer_iserializer * register_type(Archive & ar){
482 return ar.register_type(static_cast<T *>(NULL));
483 }
484 };
485
486 template<class T>
487 static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){
488 // there should never be any need to load an abstract polymorphic
489 // class pointer. Inhibiting code generation for this
490 // permits abstract base classes to be used - note: exception
491 // virtual serialize functions used for plug-ins
492 typedef typename
493 mpl::eval_if<
494 boost::serialization::is_abstract<const T>,
495 boost::mpl::identity<abstract>,
496 boost::mpl::identity<non_abstract>
497 >::type typex;
498 return typex::template register_type< T >(ar);
499 }
500
501 template<class T>
502 static T * pointer_tweak(
503 const boost::serialization::extended_type_info & eti,
504 void const * const t,
505 const T &
506 ) {
507 // tweak the pointer back to the base class
508 void * upcast = const_cast<void *>(
509 boost::serialization::void_upcast(
510 eti,
511 boost::serialization::singleton<
512 typename
513 boost::serialization::type_info_implementation< T >::type
514 >::get_const_instance(),
515 t
516 )
517 );
518 if(NULL == upcast)
519 boost::serialization::throw_exception(
520 archive_exception(archive_exception::unregistered_class)
521 );
522 return static_cast<T *>(upcast);
523 }
524
525 template<class T>
526 static void check_load(T & /* t */){
527 check_pointer_level< T >();
528 check_pointer_tracking< T >();
529 }
530
531 static const basic_pointer_iserializer *
532 find(const boost::serialization::extended_type_info & type){
533 return static_cast<const basic_pointer_iserializer *>(
534 archive_serializer_map<Archive>::find(type)
535 );
536 }
537
538 template<class Tptr>
539 static void invoke(Archive & ar, Tptr & t){
540 check_load(*t);
541 const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
542 const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
543 // note major hack here !!!
544 // I tried every way to convert Tptr &t (where Tptr might
545 // include const) to void * &. This is the only way
546 // I could make it work. RR
547 (void * & )t,
548 bpis_ptr,
549 find
550 );
551 // if the pointer isn't that of the base class
552 if(newbpis_ptr != bpis_ptr){
553 t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
554 }
555 }
556};
557
558template<class Archive>
559struct load_enum_type {
560 template<class T>
561 static void invoke(Archive &ar, T &t){
562 // convert integers to correct enum to load
563 int i;
564 ar >> boost::serialization::make_nvp(NULL, i);
565 t = static_cast< T >(i);
566 }
567};
568
569template<class Archive>
570struct load_array_type {
571 template<class T>
572 static void invoke(Archive &ar, T &t){
573 typedef typename remove_extent< T >::type value_type;
574
575 // convert integers to correct enum to load
576 // determine number of elements in the array. Consider the
577 // fact that some machines will align elements on boundries
578 // other than characters.
579 std::size_t current_count = sizeof(t) / (
580 static_cast<char *>(static_cast<void *>(&t[1]))
581 - static_cast<char *>(static_cast<void *>(&t[0]))
582 );
583 boost::serialization::collection_size_type count;
584 ar >> BOOST_SERIALIZATION_NVP(count);
585 if(static_cast<std::size_t>(count) > current_count)
586 boost::serialization::throw_exception(
587 archive::archive_exception(
588 boost::archive::archive_exception::array_size_too_short
589 )
590 );
591 ar >> serialization::make_array(static_cast<value_type*>(&t[0]),count);
592 }
593};
594
595} // detail
596
597template<class Archive, class T>
598inline void load(Archive & ar, T &t){
599 // if this assertion trips. It means we're trying to load a
600 // const object with a compiler that doesn't have correct
601 // funtion template ordering. On other compilers, this is
602 // handled below.
603 detail::check_const_loading< T >();
604 typedef
605 typename mpl::eval_if<is_pointer< T >,
606 mpl::identity<detail::load_pointer_type<Archive> >
607 ,//else
608 typename mpl::eval_if<is_array< T >,
609 mpl::identity<detail::load_array_type<Archive> >
610 ,//else
611 typename mpl::eval_if<is_enum< T >,
612 mpl::identity<detail::load_enum_type<Archive> >
613 ,//else
614 mpl::identity<detail::load_non_pointer_type<Archive> >
615 >
616 >
617 >::type typex;
618 typex::invoke(ar, t);
619}
620
621} // namespace archive
622} // namespace boost
623
624#endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP