1 #ifndef BOOST_SERIALIZATION_VOID_CAST_HPP
2 #define BOOST_SERIALIZATION_VOID_CAST_HPP
3 
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER)
6 # pragma once
7 #endif
8 
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10 // void_cast.hpp:   interface for run-time casting of void pointers.
11 
12 // (C) Copyright 2002-2009 Robert Ramey - http://www.rrsd.com .
13 // Use, modification and distribution is subject to the Boost Software
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
16 // gennadiy.rozental@tfn.com
17 
18 //  See http://www.boost.org for updates, documentation, and revision history.
19 
20 #include <cstddef> // for ptrdiff_t
21 #include <boost/config.hpp>
22 #include <boost/noncopyable.hpp>
23 
24 #include <boost/serialization/smart_cast.hpp>
25 #include <boost/serialization/singleton.hpp>
26 #include <boost/serialization/force_include.hpp>
27 #include <boost/serialization/type_info_implementation.hpp>
28 #include <boost/serialization/extended_type_info.hpp>
29 #include <boost/type_traits/is_virtual_base_of.hpp>
30 #include <boost/type_traits/aligned_storage.hpp>
31 #include <boost/serialization/void_cast_fwd.hpp>
32 
33 #include <boost/serialization/config.hpp>
34 #include <boost/config/abi_prefix.hpp> // must be the last header
35 
36 #ifdef BOOST_MSVC
37 #  pragma warning(push)
38 #  pragma warning(disable : 4251 4231 4660 4275)
39 #endif
40 
41 namespace boost {
42 namespace serialization {
43 
44 class extended_type_info;
45 
46 // Given a void *, assume that it really points to an instance of one type
47 // and alter it so that it would point to an instance of a related type.
48 // Return the altered pointer. If there exists no sequence of casts that
49 // can transform from_type to to_type, return a NULL.
50 
51 BOOST_SERIALIZATION_DECL void const *
52 void_upcast(
53     extended_type_info const & derived,
54     extended_type_info const & base,
55     void const * const t
56 );
57 
58 inline void *
void_upcast(extended_type_info const & derived,extended_type_info const & base,void * const t)59 void_upcast(
60     extended_type_info const & derived,
61     extended_type_info const & base,
62     void * const t
63 ){
64     return const_cast<void*>(void_upcast(
65         derived,
66         base,
67         const_cast<void const *>(t)
68     ));
69 }
70 
71 BOOST_SERIALIZATION_DECL void const *
72 void_downcast(
73     extended_type_info const & derived,
74     extended_type_info const & base,
75     void const * const t
76 );
77 
78 inline void *
void_downcast(extended_type_info const & derived,extended_type_info const & base,void * const t)79 void_downcast(
80     extended_type_info const & derived,
81     extended_type_info const & base,
82     void * const t
83 ){
84     return const_cast<void*>(void_downcast(
85         derived,
86         base,
87         const_cast<void const *>(t)
88     ));
89 }
90 
91 namespace void_cast_detail {
92 
93 class BOOST_SYMBOL_VISIBLE void_caster :
94     private boost::noncopyable
95 {
96     friend
97     BOOST_SERIALIZATION_DECL void const *
98     boost::serialization::void_upcast(
99         extended_type_info const & derived,
100         extended_type_info const & base,
101         void const * const
102     );
103     friend
104     BOOST_SERIALIZATION_DECL void const *
105     boost::serialization::void_downcast(
106         extended_type_info const & derived,
107         extended_type_info const & base,
108         void const * const
109     );
110 protected:
111     BOOST_SERIALIZATION_DECL void recursive_register(bool includes_virtual_base = false) const;
112     BOOST_SERIALIZATION_DECL void recursive_unregister() const;
113     virtual bool has_virtual_base() const = 0;
114 public:
115     // Data members
116     const extended_type_info * m_derived;
117     const extended_type_info * m_base;
118     /*const*/ std::ptrdiff_t m_difference;
119     void_caster const * const m_parent;
120 
121     // note that void_casters are keyed on value of
122     // member extended type info records - NOT their
123     // addresses.  This is necessary in order for the
124     // void cast operations to work across dll and exe
125     // module boundaries.
126     bool operator<(const void_caster & rhs) const;
127 
operator *()128     const void_caster & operator*(){
129         return *this;
130     }
131     // each derived class must re-implement these;
132     virtual void const * upcast(void const * const t) const = 0;
133     virtual void const * downcast(void const * const t) const = 0;
134     // Constructor
void_caster(extended_type_info const * derived,extended_type_info const * base,std::ptrdiff_t difference=0,void_caster const * const parent=0)135     void_caster(
136         extended_type_info const * derived,
137         extended_type_info const * base,
138         std::ptrdiff_t difference = 0,
139         void_caster const * const parent = 0
140     ) :
141         m_derived(derived),
142         m_base(base),
143         m_difference(difference),
144         m_parent(parent)
145     {}
~void_caster()146     virtual ~void_caster(){}
147 };
148 
149 #ifdef BOOST_MSVC
150 #  pragma warning(push)
151 #  pragma warning(disable : 4251 4231 4660 4275 4511 4512)
152 #endif
153 
154 template <class Derived, class Base>
155 class BOOST_SYMBOL_VISIBLE void_caster_primitive :
156     public void_caster
157 {
downcast(void const * const t) const158     void const * downcast(void const * const t) const BOOST_OVERRIDE {
159         const Derived * d =
160             boost::serialization::smart_cast<const Derived *, const Base *>(
161                 static_cast<const Base *>(t)
162             );
163         return d;
164     }
upcast(void const * const t) const165     void const * upcast(void const * const t) const BOOST_OVERRIDE {
166         const Base * b =
167             boost::serialization::smart_cast<const Base *, const Derived *>(
168                 static_cast<const Derived *>(t)
169             );
170         return b;
171     }
has_virtual_base() const172     bool has_virtual_base() const BOOST_OVERRIDE {
173         return false;
174     }
175 public:
176     void_caster_primitive();
177     ~void_caster_primitive() BOOST_OVERRIDE;
178 
179 private:
base_offset()180     static std::ptrdiff_t base_offset() {
181         typename boost::aligned_storage<sizeof(Derived)>::type data;
182         return reinterpret_cast<char*>(&data)
183              - reinterpret_cast<char*>(
184                    static_cast<Base*>(
185                        reinterpret_cast<Derived*>(&data)));
186     }
187 };
188 
189 template <class Derived, class Base>
void_caster_primitive()190 void_caster_primitive<Derived, Base>::void_caster_primitive() :
191     void_caster(
192         & type_info_implementation<Derived>::type::get_const_instance(),
193         & type_info_implementation<Base>::type::get_const_instance(),
194         base_offset()
195     )
196 {
197     recursive_register();
198 }
199 
200 template <class Derived, class Base>
~void_caster_primitive()201 void_caster_primitive<Derived, Base>::~void_caster_primitive(){
202     recursive_unregister();
203 }
204 
205 template <class Derived, class Base>
206 class BOOST_SYMBOL_VISIBLE void_caster_virtual_base :
207     public void_caster
208 {
has_virtual_base() const209     bool has_virtual_base() const BOOST_OVERRIDE {
210         return true;
211     }
212 public:
downcast(void const * const t) const213     void const * downcast(void const * const t) const BOOST_OVERRIDE {
214         const Derived * d =
215             dynamic_cast<const Derived *>(
216                 static_cast<const Base *>(t)
217             );
218         return d;
219     }
upcast(void const * const t) const220     void const * upcast(void const * const t) const BOOST_OVERRIDE {
221         const Base * b =
222             dynamic_cast<const Base *>(
223                 static_cast<const Derived *>(t)
224             );
225         return b;
226     }
227     void_caster_virtual_base();
228     ~void_caster_virtual_base() BOOST_OVERRIDE;
229 };
230 
231 #ifdef BOOST_MSVC
232 #pragma warning(pop)
233 #endif
234 
235 template <class Derived, class Base>
void_caster_virtual_base()236 void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() :
237     void_caster(
238         & (type_info_implementation<Derived>::type::get_const_instance()),
239         & (type_info_implementation<Base>::type::get_const_instance())
240     )
241 {
242     recursive_register(true);
243 }
244 
245 template <class Derived, class Base>
~void_caster_virtual_base()246 void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){
247     recursive_unregister();
248 }
249 
250 template <class Derived, class Base>
251 struct BOOST_SYMBOL_VISIBLE void_caster_base :
252     public void_caster
253 {
254     typedef
255         typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
256             mpl::identity<
257                 void_cast_detail::void_caster_virtual_base<Derived, Base>
258             >
259         ,// else
260             mpl::identity<
261                 void_cast_detail::void_caster_primitive<Derived, Base>
262             >
263         >::type type;
264 };
265 
266 } // void_cast_detail
267 
268 template<class Derived, class Base>
269 BOOST_DLLEXPORT
void_cast_register(Derived const *,Base const *)270 inline const void_cast_detail::void_caster & void_cast_register(
271     Derived const * /* dnull = NULL */,
272     Base const * /* bnull = NULL */
273 ){
274     typedef
275         typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
276             mpl::identity<
277                 void_cast_detail::void_caster_virtual_base<Derived, Base>
278             >
279         ,// else
280             mpl::identity<
281                 void_cast_detail::void_caster_primitive<Derived, Base>
282             >
283         >::type typex;
284     return singleton<typex>::get_const_instance();
285 }
286 
287 template<class Derived, class Base>
288 class BOOST_SYMBOL_VISIBLE void_caster :
289     public void_cast_detail::void_caster_base<Derived, Base>::type
290 {
291 };
292 
293 } // namespace serialization
294 } // namespace boost
295 
296 #ifdef BOOST_MSVC
297 #  pragma warning(pop)
298 #endif
299 
300 #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
301 
302 #endif // BOOST_SERIALIZATION_VOID_CAST_HPP
303