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 * |
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 | t: 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 * |
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 | t: 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 | |
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 |
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 | {} |
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 | { |
158 | 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 | } |
165 | 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 | } |
172 | 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: |
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> |
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> |
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 | { |
209 | bool has_virtual_base() const BOOST_OVERRIDE { |
210 | return true; |
211 | } |
212 | public: |
213 | 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 | } |
220 | 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> |
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(includes_virtual_base: true); |
243 | } |
244 | |
245 | template <class Derived, class 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 |
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 | |