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