Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/archive/detail/iserializer.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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) && (_MSC_VER >= 1020) | |
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 <memory> // for auto_ptr | |
27 #include <cstddef> // size_t, NULL | |
28 | |
29 #include <boost/config.hpp> | |
30 #include <boost/detail/workaround.hpp> | |
31 #if defined(BOOST_NO_STDC_NAMESPACE) | |
32 namespace std{ | |
33 using ::size_t; | |
34 } // namespace std | |
35 #endif | |
36 | |
37 #include <boost/static_assert.hpp> | |
38 | |
39 #include <boost/mpl/eval_if.hpp> | |
40 #include <boost/mpl/identity.hpp> | |
41 #include <boost/mpl/greater_equal.hpp> | |
42 #include <boost/mpl/equal_to.hpp> | |
43 #include <boost/mpl/bool.hpp> | |
44 #include <boost/detail/no_exceptions_support.hpp> | |
45 | |
46 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO | |
47 #include <boost/serialization/extended_type_info_typeid.hpp> | |
48 #endif | |
49 #include <boost/serialization/throw_exception.hpp> | |
50 #include <boost/serialization/smart_cast.hpp> | |
51 #include <boost/serialization/static_warning.hpp> | |
52 | |
53 #include <boost/type_traits/is_pointer.hpp> | |
54 #include <boost/type_traits/is_enum.hpp> | |
55 #include <boost/type_traits/is_const.hpp> | |
56 #include <boost/type_traits/remove_const.hpp> | |
57 #include <boost/type_traits/remove_extent.hpp> | |
58 #include <boost/type_traits/is_polymorphic.hpp> | |
59 | |
60 #include <boost/serialization/assume_abstract.hpp> | |
61 | |
62 #define DONT_USE_HAS_NEW_OPERATOR ( \ | |
63 defined(__BORLANDC__) \ | |
64 || BOOST_WORKAROUND(__IBMCPP__, < 1210) \ | |
65 || defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) \ | |
66 || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \ | |
67 ) | |
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 | |
93 namespace boost { | |
94 | |
95 namespace serialization { | |
96 class extended_type_info; | |
97 } // namespace serialization | |
98 | |
99 namespace archive { | |
100 | |
101 // an accessor to permit friend access to archives. Needed because | |
102 // some compilers don't handle friend templates completely | |
103 class load_access { | |
104 public: | |
105 template<class Archive, class T> | |
106 static void load_primitive(Archive &ar, T &t){ | |
107 ar.load(t); | |
108 } | |
109 }; | |
110 | |
111 namespace detail { | |
112 | |
113 #ifdef BOOST_MSVC | |
114 # pragma warning(push) | |
115 # pragma warning(disable : 4511 4512) | |
116 #endif | |
117 | |
118 template<class Archive, class T> | |
119 class iserializer : public basic_iserializer | |
120 { | |
121 private: | |
122 virtual void destroy(/*const*/ void *address) const { | |
123 boost::serialization::access::destroy(static_cast<T *>(address)); | |
124 } | |
125 protected: | |
126 // protected constructor since it's always created by singleton | |
127 explicit iserializer() : | |
128 basic_iserializer( | |
129 boost::serialization::singleton< | |
130 BOOST_DEDUCED_TYPENAME | |
131 boost::serialization::type_info_implementation< T >::type | |
132 >::get_const_instance() | |
133 ) | |
134 {} | |
135 public: | |
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 | |
165 template<class Archive, class T> | |
166 BOOST_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 template<class Archive, class T> | |
201 class pointer_iserializer : | |
202 public basic_pointer_iserializer | |
203 { | |
204 private: | |
205 virtual const basic_iserializer & get_basic_serializer() const { | |
206 return boost::serialization::singleton< | |
207 iserializer<Archive, T> | |
208 >::get_const_instance(); | |
209 } | |
210 BOOST_DLLEXPORT virtual void load_object_ptr( | |
211 basic_iarchive & ar, | |
212 void * & x, | |
213 const unsigned int file_version | |
214 ) const BOOST_USED; | |
215 protected: | |
216 // this should alway be a singleton so make the constructor protected | |
217 pointer_iserializer(); | |
218 ~pointer_iserializer(); | |
219 }; | |
220 | |
221 #ifdef BOOST_MSVC | |
222 # pragma warning(pop) | |
223 #endif | |
224 | |
225 // note trick to be sure that operator new is using class specific | |
226 // version if such exists. Due to Peter Dimov. | |
227 // note: the following fails if T has no default constructor. | |
228 // otherwise it would have been ideal | |
229 //struct heap_allocator : public T | |
230 //{ | |
231 // T * invoke(){ | |
232 // return ::new(sizeof(T)); | |
233 // } | |
234 //} | |
235 | |
236 template<class T> | |
237 struct heap_allocator | |
238 { | |
239 // boost::has_new_operator< T > doesn't work on these compilers | |
240 #if DONT_USE_HAS_NEW_OPERATOR | |
241 // This doesn't handle operator new overload for class T | |
242 static T * invoke(){ | |
243 return static_cast<T *>(operator new(sizeof(T))); | |
244 } | |
245 #else | |
246 struct has_new_operator { | |
247 static T* invoke() { | |
248 return static_cast<T *>((T::operator new)(sizeof(T))); | |
249 } | |
250 }; | |
251 struct doesnt_have_new_operator { | |
252 static T* invoke() { | |
253 return static_cast<T *>(operator new(sizeof(T))); | |
254 } | |
255 }; | |
256 static T * invoke() { | |
257 typedef BOOST_DEDUCED_TYPENAME | |
258 mpl::eval_if< | |
259 boost::has_new_operator< T >, | |
260 mpl::identity<has_new_operator >, | |
261 mpl::identity<doesnt_have_new_operator > | |
262 >::type typex; | |
263 return typex::invoke(); | |
264 } | |
265 #endif | |
266 }; | |
267 | |
268 // due to Martin Ecker | |
269 template <typename T> | |
270 class auto_ptr_with_deleter | |
271 { | |
272 public: | |
273 explicit auto_ptr_with_deleter(T* p) : | |
274 m_p(p) | |
275 {} | |
276 ~auto_ptr_with_deleter(){ | |
277 if (m_p) | |
278 boost::serialization::access::destroy(m_p); | |
279 } | |
280 T* get() const { | |
281 return m_p; | |
282 } | |
283 | |
284 T* release() { | |
285 T* p = m_p; | |
286 m_p = NULL; | |
287 return p; | |
288 } | |
289 private: | |
290 T* m_p; | |
291 }; | |
292 | |
293 // note: BOOST_DLLEXPORT is so that code for polymorphic class | |
294 // serialized only through base class won't get optimized out | |
295 template<class Archive, class T> | |
296 BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr( | |
297 basic_iarchive & ar, | |
298 void * & x, | |
299 const unsigned int file_version | |
300 ) const | |
301 { | |
302 Archive & ar_impl = | |
303 boost::serialization::smart_cast_reference<Archive &>(ar); | |
304 | |
305 auto_ptr_with_deleter< T > ap(heap_allocator< T >::invoke()); | |
306 if(NULL == ap.get()) | |
307 boost::serialization::throw_exception(std::bad_alloc()) ; | |
308 | |
309 T * t = ap.get(); | |
310 x = t; | |
311 | |
312 // catch exception during load_construct_data so that we don't | |
313 // automatically delete the t which is most likely not fully | |
314 // constructed | |
315 BOOST_TRY { | |
316 // this addresses an obscure situtation that occurs when | |
317 // load_constructor de-serializes something through a pointer. | |
318 ar.next_object_pointer(t); | |
319 boost::serialization::load_construct_data_adl<Archive, T>( | |
320 ar_impl, | |
321 t, | |
322 file_version | |
323 ); | |
324 } | |
325 BOOST_CATCH(...){ | |
326 ap.release(); | |
327 BOOST_RETHROW; | |
328 } | |
329 BOOST_CATCH_END | |
330 | |
331 ar_impl >> boost::serialization::make_nvp(NULL, * t); | |
332 ap.release(); | |
333 } | |
334 | |
335 template<class Archive, class T> | |
336 pointer_iserializer<Archive, T>::pointer_iserializer() : | |
337 basic_pointer_iserializer( | |
338 boost::serialization::singleton< | |
339 BOOST_DEDUCED_TYPENAME | |
340 boost::serialization::type_info_implementation< T >::type | |
341 >::get_const_instance() | |
342 ) | |
343 { | |
344 boost::serialization::singleton< | |
345 iserializer<Archive, T> | |
346 >::get_mutable_instance().set_bpis(this); | |
347 archive_serializer_map<Archive>::insert(this); | |
348 } | |
349 | |
350 template<class Archive, class T> | |
351 pointer_iserializer<Archive, T>::~pointer_iserializer(){ | |
352 archive_serializer_map<Archive>::erase(this); | |
353 } | |
354 | |
355 template<class Archive> | |
356 struct load_non_pointer_type { | |
357 // note this bounces the call right back to the archive | |
358 // with no runtime overhead | |
359 struct load_primitive { | |
360 template<class T> | |
361 static void invoke(Archive & ar, T & t){ | |
362 load_access::load_primitive(ar, t); | |
363 } | |
364 }; | |
365 // note this bounces the call right back to the archive | |
366 // with no runtime overhead | |
367 struct load_only { | |
368 template<class T> | |
369 static void invoke(Archive & ar, const T & t){ | |
370 // short cut to user's serializer | |
371 // make sure call is routed through the higest interface that might | |
372 // be specialized by the user. | |
373 boost::serialization::serialize_adl( | |
374 ar, | |
375 const_cast<T &>(t), | |
376 boost::serialization::version< T >::value | |
377 ); | |
378 } | |
379 }; | |
380 | |
381 // note this save class information including version | |
382 // and serialization level to the archive | |
383 struct load_standard { | |
384 template<class T> | |
385 static void invoke(Archive &ar, const T & t){ | |
386 void * x = & const_cast<T &>(t); | |
387 ar.load_object( | |
388 x, | |
389 boost::serialization::singleton< | |
390 iserializer<Archive, T> | |
391 >::get_const_instance() | |
392 ); | |
393 } | |
394 }; | |
395 | |
396 struct load_conditional { | |
397 template<class T> | |
398 static void invoke(Archive &ar, T &t){ | |
399 //if(0 == (ar.get_flags() & no_tracking)) | |
400 load_standard::invoke(ar, t); | |
401 //else | |
402 // load_only::invoke(ar, t); | |
403 } | |
404 }; | |
405 | |
406 template<class T> | |
407 static void invoke(Archive & ar, T &t){ | |
408 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< | |
409 // if its primitive | |
410 mpl::equal_to< | |
411 boost::serialization::implementation_level< T >, | |
412 mpl::int_<boost::serialization::primitive_type> | |
413 >, | |
414 mpl::identity<load_primitive>, | |
415 // else | |
416 BOOST_DEDUCED_TYPENAME mpl::eval_if< | |
417 // class info / version | |
418 mpl::greater_equal< | |
419 boost::serialization::implementation_level< T >, | |
420 mpl::int_<boost::serialization::object_class_info> | |
421 >, | |
422 // do standard load | |
423 mpl::identity<load_standard>, | |
424 // else | |
425 BOOST_DEDUCED_TYPENAME mpl::eval_if< | |
426 // no tracking | |
427 mpl::equal_to< | |
428 boost::serialization::tracking_level< T >, | |
429 mpl::int_<boost::serialization::track_never> | |
430 >, | |
431 // do a fast load | |
432 mpl::identity<load_only>, | |
433 // else | |
434 // do a fast load only tracking is turned off | |
435 mpl::identity<load_conditional> | |
436 > > >::type typex; | |
437 check_object_versioning< T >(); | |
438 check_object_level< T >(); | |
439 typex::invoke(ar, t); | |
440 } | |
441 }; | |
442 | |
443 template<class Archive> | |
444 struct load_pointer_type { | |
445 struct abstract | |
446 { | |
447 template<class T> | |
448 static const basic_pointer_iserializer * register_type(Archive & /* ar */){ | |
449 // it has? to be polymorphic | |
450 BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value); | |
451 return static_cast<basic_pointer_iserializer *>(NULL); | |
452 } | |
453 }; | |
454 | |
455 struct non_abstract | |
456 { | |
457 template<class T> | |
458 static const basic_pointer_iserializer * register_type(Archive & ar){ | |
459 return ar.register_type(static_cast<T *>(NULL)); | |
460 } | |
461 }; | |
462 | |
463 template<class T> | |
464 static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){ | |
465 // there should never be any need to load an abstract polymorphic | |
466 // class pointer. Inhibiting code generation for this | |
467 // permits abstract base classes to be used - note: exception | |
468 // virtual serialize functions used for plug-ins | |
469 typedef BOOST_DEDUCED_TYPENAME | |
470 mpl::eval_if< | |
471 boost::serialization::is_abstract<const T>, | |
472 boost::mpl::identity<abstract>, | |
473 boost::mpl::identity<non_abstract> | |
474 >::type typex; | |
475 return typex::template register_type< T >(ar); | |
476 } | |
477 | |
478 template<class T> | |
479 static T * pointer_tweak( | |
480 const boost::serialization::extended_type_info & eti, | |
481 void const * const t, | |
482 const T & | |
483 ) { | |
484 // tweak the pointer back to the base class | |
485 return static_cast<T *>( | |
486 const_cast<void *>( | |
487 boost::serialization::void_upcast( | |
488 eti, | |
489 boost::serialization::singleton< | |
490 BOOST_DEDUCED_TYPENAME | |
491 boost::serialization::type_info_implementation< T >::type | |
492 >::get_const_instance(), | |
493 t | |
494 ) | |
495 ) | |
496 ); | |
497 } | |
498 | |
499 template<class T> | |
500 static void check_load(T & /* t */){ | |
501 check_pointer_level< T >(); | |
502 check_pointer_tracking< T >(); | |
503 } | |
504 | |
505 static const basic_pointer_iserializer * | |
506 find(const boost::serialization::extended_type_info & type){ | |
507 return static_cast<const basic_pointer_iserializer *>( | |
508 archive_serializer_map<Archive>::find(type) | |
509 ); | |
510 } | |
511 | |
512 template<class Tptr> | |
513 static void invoke(Archive & ar, Tptr & t){ | |
514 check_load(*t); | |
515 const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t); | |
516 const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer( | |
517 // note major hack here !!! | |
518 // I tried every way to convert Tptr &t (where Tptr might | |
519 // include const) to void * &. This is the only way | |
520 // I could make it work. RR | |
521 (void * & )t, | |
522 bpis_ptr, | |
523 find | |
524 ); | |
525 // if the pointer isn't that of the base class | |
526 if(newbpis_ptr != bpis_ptr){ | |
527 t = pointer_tweak(newbpis_ptr->get_eti(), t, *t); | |
528 } | |
529 } | |
530 }; | |
531 | |
532 template<class Archive> | |
533 struct load_enum_type { | |
534 template<class T> | |
535 static void invoke(Archive &ar, T &t){ | |
536 // convert integers to correct enum to load | |
537 int i; | |
538 ar >> boost::serialization::make_nvp(NULL, i); | |
539 t = static_cast< T >(i); | |
540 } | |
541 }; | |
542 | |
543 template<class Archive> | |
544 struct load_array_type { | |
545 template<class T> | |
546 static void invoke(Archive &ar, T &t){ | |
547 typedef BOOST_DEDUCED_TYPENAME remove_extent< T >::type value_type; | |
548 | |
549 // convert integers to correct enum to load | |
550 // determine number of elements in the array. Consider the | |
551 // fact that some machines will align elements on boundries | |
552 // other than characters. | |
553 std::size_t current_count = sizeof(t) / ( | |
554 static_cast<char *>(static_cast<void *>(&t[1])) | |
555 - static_cast<char *>(static_cast<void *>(&t[0])) | |
556 ); | |
557 boost::serialization::collection_size_type count; | |
558 ar >> BOOST_SERIALIZATION_NVP(count); | |
559 if(static_cast<std::size_t>(count) > current_count) | |
560 boost::serialization::throw_exception( | |
561 archive::archive_exception( | |
562 boost::archive::archive_exception::array_size_too_short | |
563 ) | |
564 ); | |
565 ar >> serialization::make_array(static_cast<value_type*>(&t[0]),count); | |
566 } | |
567 }; | |
568 | |
569 } // detail | |
570 | |
571 template<class Archive, class T> | |
572 inline void load(Archive & ar, T &t){ | |
573 // if this assertion trips. It means we're trying to load a | |
574 // const object with a compiler that doesn't have correct | |
575 // funtion template ordering. On other compilers, this is | |
576 // handled below. | |
577 detail::check_const_loading< T >(); | |
578 typedef | |
579 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >, | |
580 mpl::identity<detail::load_pointer_type<Archive> > | |
581 ,//else | |
582 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >, | |
583 mpl::identity<detail::load_array_type<Archive> > | |
584 ,//else | |
585 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >, | |
586 mpl::identity<detail::load_enum_type<Archive> > | |
587 ,//else | |
588 mpl::identity<detail::load_non_pointer_type<Archive> > | |
589 > | |
590 > | |
591 >::type typex; | |
592 typex::invoke(ar, t); | |
593 } | |
594 | |
595 #if 0 | |
596 | |
597 // BORLAND | |
598 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) | |
599 // borland has a couple of problems | |
600 // a) if function is partially specialized - see below | |
601 // const paramters are transformed to non-const ones | |
602 // b) implementation of base_object can't be made to work | |
603 // correctly which results in all base_object s being const. | |
604 // So, strip off the const for borland. This breaks the trap | |
605 // for loading const objects - but I see no alternative | |
606 template<class Archive, class T> | |
607 inline void load(Archive &ar, const T & t){ | |
608 load(ar, const_cast<T &>(t)); | |
609 } | |
610 #endif | |
611 | |
612 // let wrappers through. | |
613 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING | |
614 template<class Archive, class T> | |
615 inline void load_wrapper(Archive &ar, const T&t, mpl::true_){ | |
616 boost::archive::load(ar, const_cast<T&>(t)); | |
617 } | |
618 | |
619 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) | |
620 template<class Archive, class T> | |
621 inline void load(Archive &ar, const T&t){ | |
622 load_wrapper(ar,t,serialization::is_wrapper< T >()); | |
623 } | |
624 #endif | |
625 #endif | |
626 | |
627 #endif | |
628 | |
629 } // namespace archive | |
630 } // namespace boost | |
631 | |
632 #endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP |