Publishing R3
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / common / boost / 1.64.0 / include / boost-1_64 / boost / archive / detail / iserializer.hpp
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)
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 <cstddef> // size_t, NULL
27
28 #include <boost/config.hpp>
29 #include <boost/detail/workaround.hpp>
30 #if defined(BOOST_NO_STDC_NAMESPACE)
31 namespace std{ 
32     using ::size_t; 
33 } // namespace std
34 #endif
35
36 #include <boost/static_assert.hpp>
37
38 #include <boost/mpl/eval_if.hpp>
39 #include <boost/mpl/identity.hpp>
40 #include <boost/mpl/greater_equal.hpp>
41 #include <boost/mpl/equal_to.hpp>
42 #include <boost/core/no_exceptions_support.hpp>
43
44 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
45     #include <boost/serialization/extended_type_info_typeid.hpp>   
46 #endif
47 #include <boost/serialization/throw_exception.hpp>
48 #include <boost/serialization/smart_cast.hpp>
49 #include <boost/serialization/static_warning.hpp>
50
51 #include <boost/type_traits/is_pointer.hpp>
52 #include <boost/type_traits/is_enum.hpp>
53 #include <boost/type_traits/is_const.hpp>
54 #include <boost/type_traits/remove_const.hpp>
55 #include <boost/type_traits/remove_extent.hpp>
56 #include <boost/type_traits/is_polymorphic.hpp>
57
58 #include <boost/serialization/assume_abstract.hpp>
59
60 #ifndef BOOST_MSVC
61     #define DONT_USE_HAS_NEW_OPERATOR (                    \
62            BOOST_WORKAROUND(__IBMCPP__, < 1210)            \
63         || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590)   \
64     )
65 #else
66     #define DONT_USE_HAS_NEW_OPERATOR 0
67 #endif
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/collection_size_type.hpp>
81 #include <boost/serialization/singleton.hpp>
82 #include <boost/serialization/wrapper.hpp>
83 #include <boost/serialization/array_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                 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 // the purpose of this code is to allocate memory for an object
201 // without requiring the constructor to be called.  Presumably
202 // the allocated object will be subsequently initialized with
203 // "placement new". 
204 // note: we have the boost type trait has_new_operator but we
205 // have no corresponding has_delete_operator.  So we presume
206 // that the former being true would imply that the a delete
207 // operator is also defined for the class T.
208
209 template<class T>
210 struct heap_allocation {
211     // boost::has_new_operator< T > doesn't work on these compilers
212     #if DONT_USE_HAS_NEW_OPERATOR
213         // This doesn't handle operator new overload for class T
214         static T * invoke_new(){
215             return static_cast<T *>(operator new(sizeof(T)));
216         }
217         static void invoke_delete(T *t){
218             (operator delete(t));
219         }
220     #else
221         // note: we presume that a true value for has_new_operator
222         // implies the existence of a class specific delete operator as well
223         // as a class specific new operator.
224         struct has_new_operator {
225             static T * invoke_new() {
226                 return static_cast<T *>((T::operator new)(sizeof(T)));
227             }
228             static void invoke_delete(T * t) {
229                 // if compilation fails here, the likely cause that the class
230                 // T has a class specific new operator but no class specific
231                 // delete operator which matches the following signature.
232                 // note that this solution addresses the issue that two
233                 // possible signatures.  But it doesn't address the possibility
234                 // that the class might have class specific new with NO
235                 // class specific delete at all.  Patches (compatible with
236                 // C++03) welcome!
237                 delete t;
238             }
239         };
240         struct doesnt_have_new_operator {
241             static T* invoke_new() {
242                 return static_cast<T *>(operator new(sizeof(T)));
243             }
244             static void invoke_delete(T * t) {
245                 // Note: I'm reliance upon automatic conversion from T * to void * here
246                 delete t;
247             }
248         };
249         static T * invoke_new() {
250             typedef typename
251                 mpl::eval_if<
252                     boost::has_new_operator< T >,
253                     mpl::identity<has_new_operator >,
254                     mpl::identity<doesnt_have_new_operator >    
255                 >::type typex;
256             return typex::invoke_new();
257         }
258         static void invoke_delete(T *t) {
259             typedef typename
260                 mpl::eval_if<
261                     boost::has_new_operator< T >,
262                     mpl::identity<has_new_operator >,
263                     mpl::identity<doesnt_have_new_operator >    
264                 >::type typex;
265             typex::invoke_delete(t);
266         }
267     #endif
268     explicit heap_allocation(){
269         m_p = invoke_new();
270     }
271     ~heap_allocation(){
272         if (0 != m_p)
273             invoke_delete(m_p);
274     }
275     T* get() const {
276         return m_p;
277     }
278
279     T* release() {
280         T* p = m_p;
281         m_p = 0;
282         return p;
283     }
284 private:
285     T* m_p;
286 };
287
288 template<class Archive, class T>
289 class pointer_iserializer :
290     public basic_pointer_iserializer
291 {
292 private:
293     virtual void * heap_allocation() const {
294         detail::heap_allocation<T> h;
295         T * t = h.get();
296         h.release();
297         return t;
298     }
299     virtual const basic_iserializer & get_basic_serializer() const {
300         return boost::serialization::singleton<
301             iserializer<Archive, T>
302         >::get_const_instance();
303     }
304     BOOST_DLLEXPORT virtual void load_object_ptr(
305         basic_iarchive & ar, 
306         void * x,
307         const unsigned int file_version
308     ) const BOOST_USED;
309 protected:
310     // this should alway be a singleton so make the constructor protected
311     pointer_iserializer();
312     ~pointer_iserializer();
313 };
314
315 #ifdef BOOST_MSVC
316 #  pragma warning(pop)
317 #endif
318
319 // note: BOOST_DLLEXPORT is so that code for polymorphic class
320 // serialized only through base class won't get optimized out
321 template<class Archive, class T>
322 BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
323     basic_iarchive & ar, 
324     void * t,
325     const unsigned int file_version
326 ) const
327 {
328     Archive & ar_impl = 
329         boost::serialization::smart_cast_reference<Archive &>(ar);
330
331     // note that the above will throw std::bad_alloc if the allocation
332     // fails so we don't have to address this contingency here.
333
334     // catch exception during load_construct_data so that we don't
335     // automatically delete the t which is most likely not fully
336     // constructed
337     BOOST_TRY {
338         // this addresses an obscure situation that occurs when 
339         // load_constructor de-serializes something through a pointer.
340         ar.next_object_pointer(t);
341         boost::serialization::load_construct_data_adl<Archive, T>(
342             ar_impl,
343             static_cast<T *>(t),
344             file_version
345         );
346     }
347     BOOST_CATCH(...){
348         // if we get here the load_construct failed.  The heap_allocation
349         // will be automatically deleted so we don't have to do anything
350         // special here.
351         BOOST_RETHROW;
352     }
353     BOOST_CATCH_END
354
355     ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t));
356 }
357
358 template<class Archive, class T>
359 pointer_iserializer<Archive, T>::pointer_iserializer() :
360     basic_pointer_iserializer(
361         boost::serialization::singleton<
362             typename 
363             boost::serialization::type_info_implementation< T >::type
364         >::get_const_instance()
365     )
366 {
367     boost::serialization::singleton<
368         iserializer<Archive, T>
369     >::get_mutable_instance().set_bpis(this);
370     archive_serializer_map<Archive>::insert(this);
371 }
372
373 template<class Archive, class T>
374 pointer_iserializer<Archive, T>::~pointer_iserializer(){
375     archive_serializer_map<Archive>::erase(this);
376 }
377
378 template<class Archive>
379 struct load_non_pointer_type {
380     // note this bounces the call right back to the archive
381     // with no runtime overhead
382     struct load_primitive {
383         template<class T>
384         static void invoke(Archive & ar, T & t){
385             load_access::load_primitive(ar, t);
386         }
387     };
388     // note this bounces the call right back to the archive
389     // with no runtime overhead
390     struct load_only {
391         template<class T>
392         static void invoke(Archive & ar, const T & t){
393             // short cut to user's serializer
394             // make sure call is routed through the higest interface that might
395             // be specialized by the user.
396             boost::serialization::serialize_adl(
397                 ar, 
398                 const_cast<T &>(t), 
399                 boost::serialization::version< T >::value
400             );
401         }
402     };
403
404     // note this save class information including version
405     // and serialization level to the archive
406     struct load_standard {
407         template<class T>
408         static void invoke(Archive &ar, const T & t){
409             void * x = & const_cast<T &>(t);
410             ar.load_object(
411                 x, 
412                 boost::serialization::singleton<
413                     iserializer<Archive, T>
414                 >::get_const_instance()
415             );
416         }
417     };
418
419     struct load_conditional {
420         template<class T>
421         static void invoke(Archive &ar, T &t){
422             //if(0 == (ar.get_flags() & no_tracking))
423                 load_standard::invoke(ar, t);
424             //else
425             //    load_only::invoke(ar, t);
426         }
427     };
428
429     template<class T>
430     static void invoke(Archive & ar, T &t){
431         typedef typename mpl::eval_if<
432                 // if its primitive
433                 mpl::equal_to<
434                     boost::serialization::implementation_level< T >,
435                     mpl::int_<boost::serialization::primitive_type>
436                 >,
437                 mpl::identity<load_primitive>,
438             // else
439             typename mpl::eval_if<
440             // class info / version
441             mpl::greater_equal<
442                         boost::serialization::implementation_level< T >,
443                         mpl::int_<boost::serialization::object_class_info>
444                     >,
445             // do standard load
446             mpl::identity<load_standard>,
447         // else
448         typename mpl::eval_if<
449             // no tracking
450                     mpl::equal_to<
451                         boost::serialization::tracking_level< T >,
452                         mpl::int_<boost::serialization::track_never>
453                 >,
454                 // do a fast load
455                 mpl::identity<load_only>,
456             // else
457             // do a fast load only tracking is turned off
458             mpl::identity<load_conditional>
459         > > >::type typex;
460         check_object_versioning< T >();
461         check_object_level< T >();
462         typex::invoke(ar, t);
463     }
464 };
465
466 template<class Archive>
467 struct load_pointer_type {
468     struct abstract
469     {
470         template<class T>
471         static const basic_pointer_iserializer * register_type(Archive & /* ar */){
472             // it has? to be polymorphic
473             BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
474             return static_cast<basic_pointer_iserializer *>(NULL);
475          }
476     };
477
478     struct non_abstract
479     {
480         template<class T>
481         static const basic_pointer_iserializer * register_type(Archive & ar){
482             return ar.register_type(static_cast<T *>(NULL));
483         }
484     };
485
486     template<class T>
487     static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){
488         // there should never be any need to load an abstract polymorphic 
489         // class pointer.  Inhibiting code generation for this
490         // permits abstract base classes to be used - note: exception
491         // virtual serialize functions used for plug-ins
492         typedef typename
493             mpl::eval_if<
494                 boost::serialization::is_abstract<const T>,
495                 boost::mpl::identity<abstract>,
496                 boost::mpl::identity<non_abstract>  
497             >::type typex;
498         return typex::template register_type< T >(ar);
499     }
500
501     template<class T>
502     static T * pointer_tweak(
503         const boost::serialization::extended_type_info & eti,
504         void const * const t,
505         const T &
506     ) {
507         // tweak the pointer back to the base class
508         void * upcast = const_cast<void *>(
509             boost::serialization::void_upcast(
510                 eti,
511                 boost::serialization::singleton<
512                     typename 
513                     boost::serialization::type_info_implementation< T >::type
514                 >::get_const_instance(),
515                 t
516             )
517         );
518         if(NULL == upcast)
519             boost::serialization::throw_exception(
520                 archive_exception(archive_exception::unregistered_class)
521             );
522         return static_cast<T *>(upcast);
523     }
524
525     template<class T>
526     static void check_load(T & /* t */){
527         check_pointer_level< T >();
528         check_pointer_tracking< T >();
529     }
530
531     static const basic_pointer_iserializer *
532     find(const boost::serialization::extended_type_info & type){
533         return static_cast<const basic_pointer_iserializer *>(
534             archive_serializer_map<Archive>::find(type)
535         );
536     }
537
538     template<class Tptr>
539     static void invoke(Archive & ar, Tptr & t){
540         check_load(*t);
541         const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
542         const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
543             // note major hack here !!!
544             // I tried every way to convert Tptr &t (where Tptr might
545             // include const) to void * &.  This is the only way
546             // I could make it work. RR
547             (void * & )t,
548             bpis_ptr,
549             find
550         );
551         // if the pointer isn't that of the base class
552         if(newbpis_ptr != bpis_ptr){
553             t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
554         }
555     }
556 };
557
558 template<class Archive>
559 struct load_enum_type {
560     template<class T>
561     static void invoke(Archive &ar, T &t){
562         // convert integers to correct enum to load
563         int i;
564         ar >> boost::serialization::make_nvp(NULL, i);
565         t = static_cast< T >(i);
566     }
567 };
568
569 template<class Archive>
570 struct load_array_type {
571     template<class T>
572     static void invoke(Archive &ar, T &t){
573         typedef typename remove_extent< T >::type value_type;
574         
575         // convert integers to correct enum to load
576         // determine number of elements in the array. Consider the
577         // fact that some machines will align elements on boundries
578         // other than characters.
579         std::size_t current_count = sizeof(t) / (
580             static_cast<char *>(static_cast<void *>(&t[1])) 
581             - static_cast<char *>(static_cast<void *>(&t[0]))
582         );
583         boost::serialization::collection_size_type count;
584         ar >> BOOST_SERIALIZATION_NVP(count);
585         if(static_cast<std::size_t>(count) > current_count)
586             boost::serialization::throw_exception(
587                 archive::archive_exception(
588                     boost::archive::archive_exception::array_size_too_short
589                 )
590             );
591         // explict template arguments to pass intel C++ compiler
592         ar >> serialization::make_array<
593             value_type,
594             boost::serialization::collection_size_type
595         >(
596             static_cast<value_type *>(&t[0]),
597             count
598         );
599     }
600 };
601
602 } // detail
603
604 template<class Archive, class T>
605 inline void load(Archive & ar, T &t){
606     // if this assertion trips. It means we're trying to load a
607     // const object with a compiler that doesn't have correct
608     // funtion template ordering.  On other compilers, this is
609     // handled below.
610     detail::check_const_loading< T >();
611     typedef
612         typename mpl::eval_if<is_pointer< T >,
613             mpl::identity<detail::load_pointer_type<Archive> >
614         ,//else
615         typename mpl::eval_if<is_array< T >,
616             mpl::identity<detail::load_array_type<Archive> >
617         ,//else
618         typename mpl::eval_if<is_enum< T >,
619             mpl::identity<detail::load_enum_type<Archive> >
620         ,//else
621             mpl::identity<detail::load_non_pointer_type<Archive> >
622         >
623         >
624         >::type typex;
625     typex::invoke(ar, t);
626 }
627
628 } // namespace archive
629 } // namespace boost
630
631 #endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP