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/serialization/void_cast_fwd.hpp> |
31 | |
32 | #include <boost/serialization/config.hpp> |
33 | #include <boost/config/abi_prefix.hpp> // must be the last header |
34 | |
35 | #ifdef BOOST_MSVC |
36 | # pragma warning(push) |
37 | # pragma warning(disable : 4251 4231 4660 4275) |
38 | #endif |
39 | |
40 | namespace boost { |
41 | namespace serialization { |
42 | |
43 | class extended_type_info; |
44 | |
45 | // Given a void *, assume that it really points to an instance of one type |
46 | // and alter it so that it would point to an instance of a related type. |
47 | // Return the altered pointer. If there exists no sequence of casts that |
48 | // can transform from_type to to_type, return a NULL. |
49 | |
50 | BOOST_SERIALIZATION_DECL void const * |
51 | void_upcast( |
52 | extended_type_info const & derived, |
53 | extended_type_info const & base, |
54 | void const * const t |
55 | ); |
56 | |
57 | inline void * |
58 | void_upcast( |
59 | extended_type_info const & derived, |
60 | extended_type_info const & base, |
61 | void * const t |
62 | ){ |
63 | return const_cast<void*>(void_upcast( |
64 | derived, |
65 | base, |
66 | t: const_cast<void const *>(t) |
67 | )); |
68 | } |
69 | |
70 | BOOST_SERIALIZATION_DECL void const * |
71 | void_downcast( |
72 | extended_type_info const & derived, |
73 | extended_type_info const & base, |
74 | void const * const t |
75 | ); |
76 | |
77 | inline void * |
78 | void_downcast( |
79 | extended_type_info const & derived, |
80 | extended_type_info const & base, |
81 | void * const t |
82 | ){ |
83 | return const_cast<void*>(void_downcast( |
84 | derived, |
85 | base, |
86 | t: const_cast<void const *>(t) |
87 | )); |
88 | } |
89 | |
90 | namespace void_cast_detail { |
91 | |
92 | class BOOST_SYMBOL_VISIBLE void_caster : |
93 | private boost::noncopyable |
94 | { |
95 | friend |
96 | BOOST_SERIALIZATION_DECL void const * |
97 | boost::serialization::void_upcast( |
98 | extended_type_info const & derived, |
99 | extended_type_info const & base, |
100 | void const * const |
101 | ); |
102 | friend |
103 | BOOST_SERIALIZATION_DECL void const * |
104 | boost::serialization::void_downcast( |
105 | extended_type_info const & derived, |
106 | extended_type_info const & base, |
107 | void const * const |
108 | ); |
109 | protected: |
110 | BOOST_SERIALIZATION_DECL void recursive_register(bool includes_virtual_base = false) const; |
111 | BOOST_SERIALIZATION_DECL void recursive_unregister() const; |
112 | virtual bool has_virtual_base() const = 0; |
113 | public: |
114 | // Data members |
115 | const extended_type_info * m_derived; |
116 | const extended_type_info * m_base; |
117 | /*const*/ std::ptrdiff_t m_difference; |
118 | void_caster const * const m_parent; |
119 | |
120 | // note that void_casters are keyed on value of |
121 | // member extended type info records - NOT their |
122 | // addresses. This is necessary in order for the |
123 | // void cast operations to work across dll and exe |
124 | // module boundries. |
125 | bool operator<(const void_caster & rhs) const; |
126 | |
127 | const void_caster & operator*(){ |
128 | return *this; |
129 | } |
130 | // each derived class must re-implement these; |
131 | virtual void const * upcast(void const * const t) const = 0; |
132 | virtual void const * downcast(void const * const t) const = 0; |
133 | // Constructor |
134 | void_caster( |
135 | extended_type_info const * derived, |
136 | extended_type_info const * base, |
137 | std::ptrdiff_t difference = 0, |
138 | void_caster const * const parent = 0 |
139 | ) : |
140 | m_derived(derived), |
141 | m_base(base), |
142 | m_difference(difference), |
143 | m_parent(parent) |
144 | {} |
145 | virtual ~void_caster(){} |
146 | }; |
147 | |
148 | #ifdef BOOST_MSVC |
149 | # pragma warning(push) |
150 | # pragma warning(disable : 4251 4231 4660 4275 4511 4512) |
151 | #endif |
152 | |
153 | template <class Derived, class Base> |
154 | class BOOST_SYMBOL_VISIBLE void_caster_primitive : |
155 | public void_caster |
156 | { |
157 | virtual void const * downcast(void const * const t) const { |
158 | const Derived * d = |
159 | boost::serialization::smart_cast<const Derived *, const Base *>( |
160 | static_cast<const Base *>(t) |
161 | ); |
162 | return d; |
163 | } |
164 | virtual void const * upcast(void const * const t) const { |
165 | const Base * b = |
166 | boost::serialization::smart_cast<const Base *, const Derived *>( |
167 | static_cast<const Derived *>(t) |
168 | ); |
169 | return b; |
170 | } |
171 | virtual bool has_virtual_base() const { |
172 | return false; |
173 | } |
174 | public: |
175 | void_caster_primitive(); |
176 | virtual ~void_caster_primitive(); |
177 | }; |
178 | |
179 | template <class Derived, class Base> |
180 | void_caster_primitive<Derived, Base>::void_caster_primitive() : |
181 | void_caster( |
182 | & type_info_implementation<Derived>::type::get_const_instance(), |
183 | & type_info_implementation<Base>::type::get_const_instance(), |
184 | // note:I wanted to displace from 0 here, but at least one compiler |
185 | // treated 0 by not shifting it at all. |
186 | reinterpret_cast<std::ptrdiff_t>( |
187 | static_cast<Derived *>( |
188 | reinterpret_cast<Base *>(8) |
189 | ) |
190 | ) - 8 |
191 | ) |
192 | { |
193 | recursive_register(); |
194 | } |
195 | |
196 | template <class Derived, class Base> |
197 | void_caster_primitive<Derived, Base>::~void_caster_primitive(){ |
198 | recursive_unregister(); |
199 | } |
200 | |
201 | template <class Derived, class Base> |
202 | class BOOST_SYMBOL_VISIBLE void_caster_virtual_base : |
203 | public void_caster |
204 | { |
205 | virtual bool has_virtual_base() const { |
206 | return true; |
207 | } |
208 | public: |
209 | virtual void const * downcast(void const * const t) const { |
210 | const Derived * d = |
211 | dynamic_cast<const Derived *>( |
212 | static_cast<const Base *>(t) |
213 | ); |
214 | return d; |
215 | } |
216 | virtual void const * upcast(void const * const t) const { |
217 | const Base * b = |
218 | dynamic_cast<const Base *>( |
219 | static_cast<const Derived *>(t) |
220 | ); |
221 | return b; |
222 | } |
223 | void_caster_virtual_base(); |
224 | virtual ~void_caster_virtual_base(); |
225 | }; |
226 | |
227 | #ifdef BOOST_MSVC |
228 | #pragma warning(pop) |
229 | #endif |
230 | |
231 | template <class Derived, class Base> |
232 | void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() : |
233 | void_caster( |
234 | & (type_info_implementation<Derived>::type::get_const_instance()), |
235 | & (type_info_implementation<Base>::type::get_const_instance()) |
236 | ) |
237 | { |
238 | recursive_register(includes_virtual_base: true); |
239 | } |
240 | |
241 | template <class Derived, class Base> |
242 | void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){ |
243 | recursive_unregister(); |
244 | } |
245 | |
246 | template <class Derived, class Base> |
247 | struct BOOST_SYMBOL_VISIBLE void_caster_base : |
248 | public void_caster |
249 | { |
250 | typedef |
251 | typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>, |
252 | mpl::identity< |
253 | void_cast_detail::void_caster_virtual_base<Derived, Base> |
254 | > |
255 | ,// else |
256 | mpl::identity< |
257 | void_cast_detail::void_caster_primitive<Derived, Base> |
258 | > |
259 | >::type type; |
260 | }; |
261 | |
262 | } // void_cast_detail |
263 | |
264 | template<class Derived, class Base> |
265 | BOOST_DLLEXPORT |
266 | inline const void_cast_detail::void_caster & void_cast_register( |
267 | Derived const * /* dnull = NULL */, |
268 | Base const * /* bnull = NULL */ |
269 | ){ |
270 | typedef |
271 | typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>, |
272 | mpl::identity< |
273 | void_cast_detail::void_caster_virtual_base<Derived, Base> |
274 | > |
275 | ,// else |
276 | mpl::identity< |
277 | void_cast_detail::void_caster_primitive<Derived, Base> |
278 | > |
279 | >::type typex; |
280 | return singleton<typex>::get_const_instance(); |
281 | } |
282 | |
283 | template<class Derived, class Base> |
284 | class BOOST_SYMBOL_VISIBLE void_caster : |
285 | public void_cast_detail::void_caster_base<Derived, Base>::type |
286 | { |
287 | }; |
288 | |
289 | } // namespace serialization |
290 | } // namespace boost |
291 | |
292 | #ifdef BOOST_MSVC |
293 | # pragma warning(pop) |
294 | #endif |
295 | |
296 | #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas |
297 | |
298 | #endif // BOOST_SERIALIZATION_VOID_CAST_HPP |
299 | |