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