]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/include/boost/archive/detail/oserializer.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / serialization / include / boost / archive / detail / oserializer.hpp
1 #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
2 #define BOOST_ARCHIVE_OSERIALIZER_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 // oserializer.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 <boost/assert.hpp>
26 #include <cstddef> // NULL
27
28 #include <boost/config.hpp>
29 #include <boost/static_assert.hpp>
30 #include <boost/detail/workaround.hpp>
31
32 #include <boost/mpl/eval_if.hpp>
33 #include <boost/mpl/equal_to.hpp>
34 #include <boost/mpl/greater_equal.hpp>
35 #include <boost/mpl/identity.hpp>
36 #include <boost/mpl/bool_fwd.hpp>
37
38 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
39 #include <boost/serialization/extended_type_info_typeid.hpp>
40 #endif
41 #include <boost/serialization/throw_exception.hpp>
42 #include <boost/serialization/smart_cast.hpp>
43 #include <boost/serialization/assume_abstract.hpp>
44 #include <boost/serialization/static_warning.hpp>
45
46 #include <boost/type_traits/is_pointer.hpp>
47 #include <boost/type_traits/is_enum.hpp>
48 #include <boost/type_traits/is_const.hpp>
49 #include <boost/type_traits/is_polymorphic.hpp>
50 #include <boost/type_traits/remove_extent.hpp>
51
52 #include <boost/serialization/serialization.hpp>
53 #include <boost/serialization/version.hpp>
54 #include <boost/serialization/level.hpp>
55 #include <boost/serialization/tracking.hpp>
56 #include <boost/serialization/type_info_implementation.hpp>
57 #include <boost/serialization/nvp.hpp>
58 #include <boost/serialization/void_cast.hpp>
59 #include <boost/serialization/array.hpp>
60 #include <boost/serialization/collection_size_type.hpp>
61 #include <boost/serialization/singleton.hpp>
62
63 #include <boost/archive/archive_exception.hpp>
64 #include <boost/archive/detail/basic_oarchive.hpp>
65 #include <boost/archive/detail/basic_oserializer.hpp>
66 #include <boost/archive/detail/basic_pointer_oserializer.hpp>
67 #include <boost/archive/detail/archive_serializer_map.hpp>
68 #include <boost/archive/detail/check.hpp>
69
70 namespace boost {
71
72 namespace serialization {
73 class extended_type_info;
74 } // namespace serialization
75
76 namespace archive {
77
78 // an accessor to permit friend access to archives. Needed because
79 // some compilers don't handle friend templates completely
80 class save_access {
81 public:
82 template<class Archive>
83 static void end_preamble(Archive & ar){
84 ar.end_preamble();
85 }
86 template<class Archive, class T>
87 static void save_primitive(Archive & ar, const T & t){
88 ar.end_preamble();
89 ar.save(t);
90 }
91 };
92
93 namespace detail {
94
95 #ifdef BOOST_MSVC
96 # pragma warning(push)
97 # pragma warning(disable : 4511 4512)
98 #endif
99
100 template<class Archive, class T>
101 class oserializer : public basic_oserializer
102 {
103 private:
104 // private constructor to inhibit any existence other than the
105 // static one
106 public:
107 explicit BOOST_DLLEXPORT oserializer() :
108 basic_oserializer(
109 boost::serialization::singleton<
110 typename
111 boost::serialization::type_info_implementation< T >::type
112 >::get_const_instance()
113 )
114 {}
115 virtual BOOST_DLLEXPORT void save_object_data(
116 basic_oarchive & ar,
117 const void *x
118 ) const BOOST_USED;
119 virtual bool class_info() const {
120 return boost::serialization::implementation_level< T >::value
121 >= boost::serialization::object_class_info;
122 }
123 virtual bool tracking(const unsigned int /* flags */) const {
124 return boost::serialization::tracking_level< T >::value == boost::serialization::track_always
125 || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively
126 && serialized_as_pointer());
127 }
128 virtual version_type version() const {
129 return version_type(::boost::serialization::version< T >::value);
130 }
131 virtual bool is_polymorphic() const {
132 return boost::is_polymorphic< T >::value;
133 }
134 virtual ~oserializer(){}
135 };
136
137 #ifdef BOOST_MSVC
138 # pragma warning(pop)
139 #endif
140
141 template<class Archive, class T>
142 BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
143 basic_oarchive & ar,
144 const void *x
145 ) const {
146 // make sure call is routed through the highest interface that might
147 // be specialized by the user.
148 BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
149 boost::serialization::serialize_adl(
150 boost::serialization::smart_cast_reference<Archive &>(ar),
151 * static_cast<T *>(const_cast<void *>(x)),
152 version()
153 );
154 }
155
156 #ifdef BOOST_MSVC
157 # pragma warning(push)
158 # pragma warning(disable : 4511 4512)
159 #endif
160
161 template<class Archive, class T>
162 class pointer_oserializer :
163 public basic_pointer_oserializer
164 {
165 private:
166 const basic_oserializer &
167 get_basic_serializer() const {
168 return boost::serialization::singleton<
169 oserializer<Archive, T>
170 >::get_const_instance();
171 }
172 virtual BOOST_DLLEXPORT void save_object_ptr(
173 basic_oarchive & ar,
174 const void * x
175 ) const BOOST_USED;
176 public:
177 pointer_oserializer();
178 ~pointer_oserializer();
179 };
180
181 #ifdef BOOST_MSVC
182 # pragma warning(pop)
183 #endif
184
185 template<class Archive, class T>
186 BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(
187 basic_oarchive & ar,
188 const void * x
189 ) const {
190 BOOST_ASSERT(NULL != x);
191 // make sure call is routed through the highest interface that might
192 // be specialized by the user.
193 T * t = static_cast<T *>(const_cast<void *>(x));
194 const unsigned int file_version = boost::serialization::version< T >::value;
195 Archive & ar_impl
196 = boost::serialization::smart_cast_reference<Archive &>(ar);
197 boost::serialization::save_construct_data_adl<Archive, T>(
198 ar_impl,
199 t,
200 file_version
201 );
202 ar_impl << boost::serialization::make_nvp(NULL, * t);
203 }
204
205 template<class Archive, class T>
206 pointer_oserializer<Archive, T>::pointer_oserializer() :
207 basic_pointer_oserializer(
208 boost::serialization::singleton<
209 typename
210 boost::serialization::type_info_implementation< T >::type
211 >::get_const_instance()
212 )
213 {
214 // make sure appropriate member function is instantiated
215 boost::serialization::singleton<
216 oserializer<Archive, T>
217 >::get_mutable_instance().set_bpos(this);
218 archive_serializer_map<Archive>::insert(this);
219 }
220
221 template<class Archive, class T>
222 pointer_oserializer<Archive, T>::~pointer_oserializer(){
223 archive_serializer_map<Archive>::erase(this);
224 }
225
226 template<class Archive>
227 struct save_non_pointer_type {
228 // note this bounces the call right back to the archive
229 // with no runtime overhead
230 struct save_primitive {
231 template<class T>
232 static void invoke(Archive & ar, const T & t){
233 save_access::save_primitive(ar, t);
234 }
235 };
236 // same as above but passes through serialization
237 struct save_only {
238 template<class T>
239 static void invoke(Archive & ar, const T & t){
240 // make sure call is routed through the highest interface that might
241 // be specialized by the user.
242 boost::serialization::serialize_adl(
243 ar,
244 const_cast<T &>(t),
245 ::boost::serialization::version< T >::value
246 );
247 }
248 };
249 // adds class information to the archive. This includes
250 // serialization level and class version
251 struct save_standard {
252 template<class T>
253 static void invoke(Archive &ar, const T & t){
254 ar.save_object(
255 & t,
256 boost::serialization::singleton<
257 oserializer<Archive, T>
258 >::get_const_instance()
259 );
260 }
261 };
262
263 // adds class information to the archive. This includes
264 // serialization level and class version
265 struct save_conditional {
266 template<class T>
267 static void invoke(Archive &ar, const T &t){
268 //if(0 == (ar.get_flags() & no_tracking))
269 save_standard::invoke(ar, t);
270 //else
271 // save_only::invoke(ar, t);
272 }
273 };
274
275
276 template<class T>
277 static void invoke(Archive & ar, const T & t){
278 typedef
279 typename mpl::eval_if<
280 // if its primitive
281 mpl::equal_to<
282 boost::serialization::implementation_level< T >,
283 mpl::int_<boost::serialization::primitive_type>
284 >,
285 mpl::identity<save_primitive>,
286 // else
287 typename mpl::eval_if<
288 // class info / version
289 mpl::greater_equal<
290 boost::serialization::implementation_level< T >,
291 mpl::int_<boost::serialization::object_class_info>
292 >,
293 // do standard save
294 mpl::identity<save_standard>,
295 // else
296 typename mpl::eval_if<
297 // no tracking
298 mpl::equal_to<
299 boost::serialization::tracking_level< T >,
300 mpl::int_<boost::serialization::track_never>
301 >,
302 // do a fast save
303 mpl::identity<save_only>,
304 // else
305 // do a fast save only tracking is turned off
306 mpl::identity<save_conditional>
307 > > >::type typex;
308 check_object_versioning< T >();
309 typex::invoke(ar, t);
310 }
311 template<class T>
312 static void invoke(Archive & ar, T & t){
313 check_object_level< T >();
314 check_object_tracking< T >();
315 invoke(ar, const_cast<const T &>(t));
316 }
317 };
318
319 template<class Archive>
320 struct save_pointer_type {
321 struct abstract
322 {
323 template<class T>
324 static const basic_pointer_oserializer * register_type(Archive & /* ar */){
325 // it has? to be polymorphic
326 BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
327 return NULL;
328 }
329 };
330
331 struct non_abstract
332 {
333 template<class T>
334 static const basic_pointer_oserializer * register_type(Archive & ar){
335 return ar.register_type(static_cast<T *>(NULL));
336 }
337 };
338
339 template<class T>
340 static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
341 // there should never be any need to save an abstract polymorphic
342 // class pointer. Inhibiting code generation for this
343 // permits abstract base classes to be used - note: exception
344 // virtual serialize functions used for plug-ins
345 typedef
346 typename mpl::eval_if<
347 boost::serialization::is_abstract< T >,
348 mpl::identity<abstract>,
349 mpl::identity<non_abstract>
350 >::type typex;
351 return typex::template register_type< T >(ar);
352 }
353
354 struct non_polymorphic
355 {
356 template<class T>
357 static void save(
358 Archive &ar,
359 T & t
360 ){
361 const basic_pointer_oserializer & bpos =
362 boost::serialization::singleton<
363 pointer_oserializer<Archive, T>
364 >::get_const_instance();
365 // save the requested pointer type
366 ar.save_pointer(& t, & bpos);
367 }
368 };
369
370 struct polymorphic
371 {
372 template<class T>
373 static void save(
374 Archive &ar,
375 T & t
376 ){
377 typename
378 boost::serialization::type_info_implementation< T >::type const
379 & i = boost::serialization::singleton<
380 typename
381 boost::serialization::type_info_implementation< T >::type
382 >::get_const_instance();
383
384 boost::serialization::extended_type_info const * const this_type = & i;
385
386 // retrieve the true type of the object pointed to
387 // if this assertion fails its an error in this library
388 BOOST_ASSERT(NULL != this_type);
389
390 const boost::serialization::extended_type_info * true_type =
391 i.get_derived_extended_type_info(t);
392
393 // note:if this exception is thrown, be sure that derived pointer
394 // is either registered or exported.
395 if(NULL == true_type){
396 boost::serialization::throw_exception(
397 archive_exception(
398 archive_exception::unregistered_class,
399 "derived class not registered or exported"
400 )
401 );
402 }
403
404 // if its not a pointer to a more derived type
405 const void *vp = static_cast<const void *>(&t);
406 if(*this_type == *true_type){
407 const basic_pointer_oserializer * bpos = register_type(ar, t);
408 ar.save_pointer(vp, bpos);
409 return;
410 }
411 // convert pointer to more derived type. if this is thrown
412 // it means that the base/derived relationship hasn't be registered
413 vp = serialization::void_downcast(
414 *true_type,
415 *this_type,
416 static_cast<const void *>(&t)
417 );
418 if(NULL == vp){
419 boost::serialization::throw_exception(
420 archive_exception(
421 archive_exception::unregistered_cast,
422 true_type->get_debug_info(),
423 this_type->get_debug_info()
424 )
425 );
426 }
427
428 // since true_type is valid, and this only gets made if the
429 // pointer oserializer object has been created, this should never
430 // fail
431 const basic_pointer_oserializer * bpos
432 = static_cast<const basic_pointer_oserializer *>(
433 boost::serialization::singleton<
434 archive_serializer_map<Archive>
435 >::get_const_instance().find(*true_type)
436 );
437 BOOST_ASSERT(NULL != bpos);
438 if(NULL == bpos)
439 boost::serialization::throw_exception(
440 archive_exception(
441 archive_exception::unregistered_class,
442 "derived class not registered or exported"
443 )
444 );
445 ar.save_pointer(vp, bpos);
446 }
447 };
448
449 template<class T>
450 static void save(
451 Archive & ar,
452 const T & t
453 ){
454 check_pointer_level< T >();
455 check_pointer_tracking< T >();
456 typedef typename mpl::eval_if<
457 is_polymorphic< T >,
458 mpl::identity<polymorphic>,
459 mpl::identity<non_polymorphic>
460 >::type type;
461 type::save(ar, const_cast<T &>(t));
462 }
463
464 template<class TPtr>
465 static void invoke(Archive &ar, const TPtr t){
466 register_type(ar, * t);
467 if(NULL == t){
468 basic_oarchive & boa
469 = boost::serialization::smart_cast_reference<basic_oarchive &>(ar);
470 boa.save_null_pointer();
471 save_access::end_preamble(ar);
472 return;
473 }
474 save(ar, * t);
475 }
476 };
477
478 template<class Archive>
479 struct save_enum_type
480 {
481 template<class T>
482 static void invoke(Archive &ar, const T &t){
483 // convert enum to integers on save
484 const int i = static_cast<int>(t);
485 ar << boost::serialization::make_nvp(NULL, i);
486 }
487 };
488
489 template<class Archive>
490 struct save_array_type
491 {
492 template<class T>
493 static void invoke(Archive &ar, const T &t){
494 typedef typename boost::remove_extent< T >::type value_type;
495
496 save_access::end_preamble(ar);
497 // consider alignment
498 std::size_t c = sizeof(t) / (
499 static_cast<const char *>(static_cast<const void *>(&t[1]))
500 - static_cast<const char *>(static_cast<const void *>(&t[0]))
501 );
502 boost::serialization::collection_size_type count(c);
503 ar << BOOST_SERIALIZATION_NVP(count);
504 ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count);
505 }
506 };
507
508 } // detail
509
510 template<class Archive, class T>
511 inline void save(Archive & ar, /*const*/ T &t){
512 typedef
513 typename mpl::eval_if<is_pointer< T >,
514 mpl::identity<detail::save_pointer_type<Archive> >,
515 //else
516 typename mpl::eval_if<is_enum< T >,
517 mpl::identity<detail::save_enum_type<Archive> >,
518 //else
519 typename mpl::eval_if<is_array< T >,
520 mpl::identity<detail::save_array_type<Archive> >,
521 //else
522 mpl::identity<detail::save_non_pointer_type<Archive> >
523 >
524 >
525 >::type typex;
526 typex::invoke(ar, t);
527 }
528
529 } // namespace archive
530 } // namespace boost
531
532 #endif // BOOST_ARCHIVE_OSERIALIZER_HPP