1
#ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
2
#define BOOST_ARCHIVE_OSERIALIZER_HPP
4
// MS compatible compilers support #pragma once
5
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
7
#pragma inline_depth(511)
8
#pragma inline_recursion(on)
11
#if defined(__MWERKS__)
12
#pragma inline_depth(511)
15
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
16
// oserializer.hpp: interface for serialization system.
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)
23
// See http://www.boost.org for updates, documentation, and revision history.
25
#include <boost/assert.hpp>
26
#include <cstddef> // NULL
28
#include <boost/config.hpp>
29
#include <boost/static_assert.hpp>
30
#include <boost/detail/workaround.hpp>
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>
37
#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
38
#include <boost/serialization/extended_type_info_typeid.hpp>
40
#include <boost/serialization/throw_exception.hpp>
41
#include <boost/serialization/smart_cast.hpp>
42
#include <boost/serialization/assume_abstract.hpp>
43
#include <boost/serialization/static_warning.hpp>
45
#include <boost/type_traits/is_pointer.hpp>
46
#include <boost/type_traits/is_enum.hpp>
47
#include <boost/type_traits/is_const.hpp>
48
#include <boost/type_traits/is_polymorphic.hpp>
49
#include <boost/type_traits/remove_extent.hpp>
51
#include <boost/serialization/serialization.hpp>
52
#include <boost/serialization/version.hpp>
53
#include <boost/serialization/level.hpp>
54
#include <boost/serialization/tracking.hpp>
55
#include <boost/serialization/type_info_implementation.hpp>
56
#include <boost/serialization/nvp.hpp>
57
#include <boost/serialization/void_cast.hpp>
58
#include <boost/serialization/array.hpp>
59
#include <boost/serialization/collection_size_type.hpp>
60
#include <boost/serialization/singleton.hpp>
62
#include <boost/archive/archive_exception.hpp>
63
#include <boost/archive/detail/basic_oarchive.hpp>
64
#include <boost/archive/detail/basic_oserializer.hpp>
65
#include <boost/archive/detail/basic_pointer_oserializer.hpp>
66
#include <boost/archive/detail/archive_serializer_map.hpp>
67
#include <boost/archive/detail/check.hpp>
71
namespace serialization {
72
class extended_type_info;
73
} // namespace serialization
77
// an accessor to permit friend access to archives. Needed because
78
// some compilers don't handle friend templates completely
81
template<class Archive>
82
static void end_preamble(Archive & ar){
85
template<class Archive, class T>
86
static void save_primitive(Archive & ar, const T & t){
95
# pragma warning(push)
96
# pragma warning(disable : 4511 4512)
99
template<class Archive, class T>
100
class oserializer : public basic_oserializer
103
// private constructor to inhibit any existence other than the
106
explicit BOOST_DLLEXPORT oserializer() :
108
boost::serialization::singleton<
109
BOOST_DEDUCED_TYPENAME
110
boost::serialization::type_info_implementation< T >::type
111
>::get_const_instance()
114
virtual BOOST_DLLEXPORT void save_object_data(
118
virtual bool class_info() const {
119
return boost::serialization::implementation_level< T >::value
120
>= boost::serialization::object_class_info;
122
virtual bool tracking(const unsigned int /* flags */) const {
123
return boost::serialization::tracking_level< T >::value == boost::serialization::track_always
124
|| (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively
125
&& serialized_as_pointer());
127
virtual version_type version() const {
128
return version_type(::boost::serialization::version< T >::value);
130
virtual bool is_polymorphic() const {
131
return boost::is_polymorphic< T >::value;
133
virtual ~oserializer(){}
137
# pragma warning(pop)
140
template<class Archive, class T>
141
BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
145
// make sure call is routed through the highest interface that might
146
// be specialized by the user.
147
BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
148
boost::serialization::serialize_adl(
149
boost::serialization::smart_cast_reference<Archive &>(ar),
150
* static_cast<T *>(const_cast<void *>(x)),
156
# pragma warning(push)
157
# pragma warning(disable : 4511 4512)
160
template<class Archive, class T>
161
class pointer_oserializer :
162
public basic_pointer_oserializer
165
const basic_oserializer &
166
get_basic_serializer() const {
167
return boost::serialization::singleton<
168
oserializer<Archive, T>
169
>::get_const_instance();
171
virtual BOOST_DLLEXPORT void save_object_ptr(
176
pointer_oserializer();
177
~pointer_oserializer();
181
# pragma warning(pop)
184
template<class Archive, class T>
185
BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(
189
BOOST_ASSERT(NULL != x);
190
// make sure call is routed through the highest interface that might
191
// be specialized by the user.
192
T * t = static_cast<T *>(const_cast<void *>(x));
193
const unsigned int file_version = boost::serialization::version< T >::value;
195
= boost::serialization::smart_cast_reference<Archive &>(ar);
196
boost::serialization::save_construct_data_adl<Archive, T>(
201
ar_impl << boost::serialization::make_nvp(NULL, * t);
204
template<class Archive, class T>
205
pointer_oserializer<Archive, T>::pointer_oserializer() :
206
basic_pointer_oserializer(
207
boost::serialization::singleton<
208
BOOST_DEDUCED_TYPENAME
209
boost::serialization::type_info_implementation< T >::type
210
>::get_const_instance()
213
// make sure appropriate member function is instantiated
214
boost::serialization::singleton<
215
oserializer<Archive, T>
216
>::get_mutable_instance().set_bpos(this);
217
archive_serializer_map<Archive>::insert(this);
220
template<class Archive, class T>
221
pointer_oserializer<Archive, T>::~pointer_oserializer(){
222
archive_serializer_map<Archive>::erase(this);
225
template<class Archive>
226
struct save_non_pointer_type {
227
// note this bounces the call right back to the archive
228
// with no runtime overhead
229
struct save_primitive {
231
static void invoke(Archive & ar, const T & t){
232
save_access::save_primitive(ar, t);
235
// same as above but passes through serialization
238
static void invoke(Archive & ar, const T & t){
239
// make sure call is routed through the highest interface that might
240
// be specialized by the user.
241
boost::serialization::serialize_adl(
244
::boost::serialization::version< T >::value
248
// adds class information to the archive. This includes
249
// serialization level and class version
250
struct save_standard {
252
static void invoke(Archive &ar, const T & t){
255
boost::serialization::singleton<
256
oserializer<Archive, T>
257
>::get_const_instance()
262
// adds class information to the archive. This includes
263
// serialization level and class version
264
struct save_conditional {
266
static void invoke(Archive &ar, const T &t){
267
//if(0 == (ar.get_flags() & no_tracking))
268
save_standard::invoke(ar, t);
270
// save_only::invoke(ar, t);
276
static void invoke(Archive & ar, const T & t){
278
BOOST_DEDUCED_TYPENAME mpl::eval_if<
281
boost::serialization::implementation_level< T >,
282
mpl::int_<boost::serialization::primitive_type>
284
mpl::identity<save_primitive>,
286
BOOST_DEDUCED_TYPENAME mpl::eval_if<
287
// class info / version
289
boost::serialization::implementation_level< T >,
290
mpl::int_<boost::serialization::object_class_info>
293
mpl::identity<save_standard>,
295
BOOST_DEDUCED_TYPENAME mpl::eval_if<
298
boost::serialization::tracking_level< T >,
299
mpl::int_<boost::serialization::track_never>
302
mpl::identity<save_only>,
304
// do a fast save only tracking is turned off
305
mpl::identity<save_conditional>
307
check_object_versioning< T >();
308
typex::invoke(ar, t);
311
static void invoke(Archive & ar, T & t){
312
check_object_level< T >();
313
check_object_tracking< T >();
314
invoke(ar, const_cast<const T &>(t));
318
template<class Archive>
319
struct save_pointer_type {
323
static const basic_pointer_oserializer * register_type(Archive & /* ar */){
324
// it has? to be polymorphic
325
BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
333
static const basic_pointer_oserializer * register_type(Archive & ar){
334
return ar.register_type(static_cast<T *>(NULL));
339
static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
340
// there should never be any need to save an abstract polymorphic
341
// class pointer. Inhibiting code generation for this
342
// permits abstract base classes to be used - note: exception
343
// virtual serialize functions used for plug-ins
345
BOOST_DEDUCED_TYPENAME mpl::eval_if<
346
boost::serialization::is_abstract< T >,
347
mpl::identity<abstract>,
348
mpl::identity<non_abstract>
350
return typex::template register_type< T >(ar);
353
struct non_polymorphic
360
const basic_pointer_oserializer & bpos =
361
boost::serialization::singleton<
362
pointer_oserializer<Archive, T>
363
>::get_const_instance();
364
// save the requested pointer type
365
ar.save_pointer(& t, & bpos);
376
BOOST_DEDUCED_TYPENAME
377
boost::serialization::type_info_implementation< T >::type const
378
& i = boost::serialization::singleton<
379
BOOST_DEDUCED_TYPENAME
380
boost::serialization::type_info_implementation< T >::type
381
>::get_const_instance();
383
boost::serialization::extended_type_info const * const this_type = & i;
385
// retrieve the true type of the object pointed to
386
// if this assertion fails its an error in this library
387
BOOST_ASSERT(NULL != this_type);
389
const boost::serialization::extended_type_info * true_type =
390
i.get_derived_extended_type_info(t);
392
// note:if this exception is thrown, be sure that derived pointer
393
// is either registered or exported.
394
if(NULL == true_type){
395
boost::serialization::throw_exception(
397
archive_exception::unregistered_class,
398
"derived class not registered or exported"
403
// if its not a pointer to a more derived type
404
const void *vp = static_cast<const void *>(&t);
405
if(*this_type == *true_type){
406
const basic_pointer_oserializer * bpos = register_type(ar, t);
407
ar.save_pointer(vp, bpos);
410
// convert pointer to more derived type. if this is thrown
411
// it means that the base/derived relationship hasn't be registered
412
vp = serialization::void_downcast(
415
static_cast<const void *>(&t)
418
boost::serialization::throw_exception(
420
archive_exception::unregistered_cast,
421
true_type->get_debug_info(),
422
this_type->get_debug_info()
427
// since true_type is valid, and this only gets made if the
428
// pointer oserializer object has been created, this should never
430
const basic_pointer_oserializer * bpos
431
= static_cast<const basic_pointer_oserializer *>(
432
boost::serialization::singleton<
433
archive_serializer_map<Archive>
434
>::get_const_instance().find(*true_type)
436
BOOST_ASSERT(NULL != bpos);
438
boost::serialization::throw_exception(
440
archive_exception::unregistered_class,
441
"derived class not registered or exported"
444
ar.save_pointer(vp, bpos);
453
check_pointer_level< T >();
454
check_pointer_tracking< T >();
455
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
457
mpl::identity<polymorphic>,
458
mpl::identity<non_polymorphic>
460
type::save(ar, const_cast<T &>(t));
464
static void invoke(Archive &ar, const TPtr t){
465
register_type(ar, * t);
468
= boost::serialization::smart_cast_reference<basic_oarchive &>(ar);
469
boa.save_null_pointer();
470
save_access::end_preamble(ar);
477
template<class Archive>
478
struct save_enum_type
481
static void invoke(Archive &ar, const T &t){
482
// convert enum to integers on save
483
const int i = static_cast<int>(t);
484
ar << boost::serialization::make_nvp(NULL, i);
488
template<class Archive>
489
struct save_array_type
492
static void invoke(Archive &ar, const T &t){
493
typedef BOOST_DEDUCED_TYPENAME boost::remove_extent< T >::type value_type;
495
save_access::end_preamble(ar);
496
// consider alignment
497
std::size_t c = sizeof(t) / (
498
static_cast<const char *>(static_cast<const void *>(&t[1]))
499
- static_cast<const char *>(static_cast<const void *>(&t[0]))
501
boost::serialization::collection_size_type count(c);
502
ar << BOOST_SERIALIZATION_NVP(count);
503
ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count);
509
template<class Archive, class T>
510
inline void save(Archive & ar, /*const*/ T &t){
512
BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
513
mpl::identity<detail::save_pointer_type<Archive> >,
515
BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
516
mpl::identity<detail::save_enum_type<Archive> >,
518
BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
519
mpl::identity<detail::save_array_type<Archive> >,
521
mpl::identity<detail::save_non_pointer_type<Archive> >
525
typex::invoke(ar, t);
528
} // namespace archive
531
#endif // BOOST_ARCHIVE_OSERIALIZER_HPP