1/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
2// void_cast.cpp: implementation of run-time casting of void pointers
3
4// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
5// Use, modification and distribution is subject to the Boost Software
6// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8// <gennadiy.rozental@tfn.com>
9
10// See http://www.boost.org for updates, documentation, and revision history.
11
12#if (defined _MSC_VER) && (_MSC_VER == 1200)
13# pragma warning (disable : 4786) // too long name, harmless warning
14#endif
15
16// STL
17#include <set>
18#include <functional>
19#include <algorithm>
20#include <cstddef> // NULL
21#ifdef BOOST_SERIALIZATION_LOG
22#include <iostream>
23#endif
24
25// BOOST
26#include <boost/config.hpp>
27#include <boost/assert.hpp>
28
29#define BOOST_SERIALIZATION_SOURCE
30#include <boost/serialization/config.hpp>
31// it marks our code with proper attributes as being exported when
32// we're compiling it while marking it import when just the headers
33// is being included.
34#include <boost/serialization/singleton.hpp>
35#include <boost/serialization/extended_type_info.hpp>
36#include <boost/serialization/void_cast.hpp>
37
38namespace boost {
39namespace serialization {
40namespace void_cast_detail {
41
42// note that void_casters are keyed on value of
43// member extended type info records - NOT their
44// addresses. This is necessary in order for the
45// void cast operations to work across dll and exe
46// module boundaries.
47bool void_caster::operator<(const void_caster & rhs) const {
48 // include short cut to save time and eliminate
49 // problems when when base class aren't virtual
50 if(m_derived != rhs.m_derived){
51 if(*m_derived < *rhs.m_derived)
52 return true;
53 if(*rhs.m_derived < *m_derived)
54 return false;
55 }
56 // m_derived == rhs.m_derived
57 if(m_base != rhs.m_base)
58 return *m_base < *rhs.m_base;
59 else
60 return false;
61}
62
63struct void_caster_compare {
64 bool operator()(const void_caster * lhs, const void_caster * rhs) const {
65 return *lhs < *rhs;
66 }
67};
68
69typedef std::set<const void_caster *, void_caster_compare> set_type;
70typedef boost::serialization::singleton<set_type> void_caster_registry;
71
72#ifdef BOOST_MSVC
73# pragma warning(push)
74# pragma warning(disable : 4511 4512)
75#endif
76
77// implementation of shortcut void caster
78class void_caster_shortcut : public void_caster
79{
80 bool m_includes_virtual_base;
81
82 void const *
83 vbc_upcast(
84 void const * const t
85 ) const;
86 void const *
87 vbc_downcast(
88 void const * const t
89 ) const;
90 void const *
91 upcast(void const * const t) const BOOST_OVERRIDE {
92 if(m_includes_virtual_base)
93 return vbc_upcast(t);
94 return static_cast<const char *> ( t ) - m_difference;
95 }
96 void const *
97 downcast(void const * const t) const BOOST_OVERRIDE {
98 if(m_includes_virtual_base)
99 return vbc_downcast(t);
100 return static_cast<const char *> ( t ) + m_difference;
101 }
102 virtual bool is_shortcut() const {
103 return true;
104 }
105 bool has_virtual_base() const BOOST_OVERRIDE {
106 return m_includes_virtual_base;
107 }
108public:
109 void_caster_shortcut(
110 extended_type_info const * derived,
111 extended_type_info const * base,
112 std::ptrdiff_t difference,
113 bool includes_virtual_base,
114 void_caster const * const parent
115 ) :
116 void_caster(derived, base, difference, parent),
117 m_includes_virtual_base(includes_virtual_base)
118 {
119 recursive_register(includes_virtual_base);
120 }
121 ~void_caster_shortcut() BOOST_OVERRIDE {
122 recursive_unregister();
123 }
124};
125
126#ifdef BOOST_MSVC
127# pragma warning(pop)
128#endif
129
130void const *
131void_caster_shortcut::vbc_downcast(
132 void const * const t
133) const {
134 // try to find a chain that gives us what we want
135 const void_cast_detail::set_type & s
136 = void_cast_detail::void_caster_registry::get_const_instance();
137 void_cast_detail::set_type::const_iterator it;
138 for(it = s.begin(); it != s.end(); ++it){
139 // if the current candidate casts to the desired target type
140 if ((*it)->m_derived == m_derived){
141 // and if it's not us
142 if ((*it)->m_base != m_base){
143 // try to cast from the candidate base to our base
144 const void * t_new;
145 t_new = void_downcast(derived: *(*it)->m_base, base: *m_base, t);
146 // if we were successful
147 if(NULL != t_new){
148 // recast to our derived
149 const void_caster * vc = *it;
150 return vc->downcast(t: t_new);
151 }
152 }
153 }
154 }
155 return NULL;
156}
157
158void const *
159void_caster_shortcut::vbc_upcast(
160 void const * const t
161) const {
162 // try to find a chain that gives us what we want
163 const void_cast_detail::set_type & s
164 = void_cast_detail::void_caster_registry::get_const_instance();
165 void_cast_detail::set_type::const_iterator it;
166 for(it = s.begin(); it != s.end(); ++it){
167 // if the current candidate casts from the desired base type
168 if((*it)->m_base == m_base){
169 // and if it's not us
170 if ((*it)->m_derived != m_derived){
171 // try to cast from the candidate derived to our our derived
172 const void * t_new;
173 t_new = void_upcast(derived: *m_derived, base: *(*it)->m_derived, t);
174 if(NULL != t_new)
175 return (*it)->upcast(t: t_new);
176 }
177 }
178 }
179 return NULL;
180}
181
182#ifdef BOOST_MSVC
183# pragma warning(push)
184# pragma warning(disable : 4511 4512)
185#endif
186
187// just used as a search key
188class void_caster_argument : public void_caster
189{
190 void const *
191 upcast(void const * const /*t*/) const BOOST_OVERRIDE {
192 BOOST_ASSERT(false);
193 return NULL;
194 }
195 void const *
196 downcast( void const * const /*t*/) const BOOST_OVERRIDE {
197 BOOST_ASSERT(false);
198 return NULL;
199 }
200 bool has_virtual_base() const BOOST_OVERRIDE {
201 BOOST_ASSERT(false);
202 return false;
203 }
204public:
205 void_caster_argument(
206 extended_type_info const * derived,
207 extended_type_info const * base
208 ) :
209 void_caster(derived, base)
210 {}
211 ~void_caster_argument() BOOST_OVERRIDE {}
212};
213
214#ifdef BOOST_MSVC
215# pragma warning(pop)
216#endif
217
218// implementation of void caster base class
219BOOST_SERIALIZATION_DECL void
220void_caster::recursive_register(bool includes_virtual_base) const {
221 void_cast_detail::set_type & s
222 = void_cast_detail::void_caster_registry::get_mutable_instance();
223
224 #ifdef BOOST_SERIALIZATION_LOG
225 std::clog << "recursive_register\n";
226 std::clog << m_derived->get_debug_info();
227 std::clog << "<-";
228 std::clog << m_base->get_debug_info();
229 std::clog << "\n";
230 #endif
231
232 std::pair<void_cast_detail::set_type::const_iterator, bool> result;
233 // comment this out for now.
234 result = s.insert(x: this);
235 //assert(result.second);
236
237 // generate all implied void_casts.
238 void_cast_detail::set_type::const_iterator it;
239 for(it = s.begin(); it != s.end(); ++it){
240 if(* m_derived == * (*it)->m_base){
241 const void_caster_argument vca(
242 (*it)->m_derived,
243 m_base
244 );
245 void_cast_detail::set_type::const_iterator i;
246 i = s.find(x: & vca);
247 if(i == s.end()){
248 new void_caster_shortcut(
249 (*it)->m_derived,
250 m_base,
251 m_difference + (*it)->m_difference,
252 (*it)->has_virtual_base() || includes_virtual_base,
253 this
254 );
255 }
256 }
257 if(* (*it)->m_derived == * m_base){
258 const void_caster_argument vca(
259 m_derived,
260 (*it)->m_base
261 );
262 void_cast_detail::set_type::const_iterator i;
263 i = s.find(x: & vca);
264 if(i == s.end()){
265 new void_caster_shortcut(
266 m_derived,
267 (*it)->m_base,
268 m_difference + (*it)->m_difference,
269 (*it)->has_virtual_base() || includes_virtual_base,
270 this
271 );
272 }
273 }
274 }
275}
276
277BOOST_SERIALIZATION_DECL void
278void_caster::recursive_unregister() const {
279 // note: it's been discovered that at least one platform is not guaranteed
280 // to destroy singletons reverse order of construction. So we can't
281 // use a runtime assert here. Leave this in a reminder not to do this!
282 // BOOST_ASSERT(! void_caster_registry::is_destroyed());
283 if(void_caster_registry::is_destroyed())
284 return;
285
286 #ifdef BOOST_SERIALIZATION_LOG
287 std::clog << "recursive_unregister\n";
288 std::clog << m_derived->get_debug_info();
289 std::clog << "<-";
290 std::clog << m_base->get_debug_info();
291 std::clog << "\n";
292 #endif
293
294 void_cast_detail::set_type & s
295 = void_caster_registry::get_mutable_instance();
296
297 // delete all shortcuts which use this primitive
298 void_cast_detail::set_type::iterator it;
299 for(it = s.begin(); it != s.end();){
300 const void_caster * vc = *it;
301 if(vc == this){
302 s.erase(position: it++);
303 }
304 else
305 if(vc->m_parent == this){
306 s.erase(position: it);
307 delete vc;
308 it = s.begin();
309 }
310 else
311 it++;
312 }
313}
314
315} // namespace void_cast_detail
316
317BOOST_SYMBOL_VISIBLE void const *
318void_upcast(
319 extended_type_info const & derived,
320 extended_type_info const & base,
321 void const * const t
322);
323
324// Given a void *, assume that it really points to an instance of one type
325// and alter it so that it would point to an instance of a related type.
326// Return the altered pointer. If there exists no sequence of casts that
327// can transform from_type to to_type, return a NULL.
328BOOST_SERIALIZATION_DECL void const *
329void_upcast(
330 extended_type_info const & derived,
331 extended_type_info const & base,
332 void const * const t
333){
334 // same types - trivial case
335 if (derived == base)
336 return t;
337
338 // check to see if base/derived pair is found in the registry
339 const void_cast_detail::set_type & s
340 = void_cast_detail::void_caster_registry::get_const_instance();
341 const void_cast_detail::void_caster_argument ca(& derived, & base);
342
343 void_cast_detail::set_type::const_iterator it;
344 it = s.find(x: & ca);
345 if (s.end() != it)
346 return (*it)->upcast(t);
347
348 return NULL;
349}
350
351BOOST_SYMBOL_VISIBLE void const *
352void_downcast(
353 extended_type_info const & derived,
354 extended_type_info const & base,
355 void const * const t
356);
357
358BOOST_SERIALIZATION_DECL void const *
359void_downcast(
360 extended_type_info const & derived,
361 extended_type_info const & base,
362 void const * const t
363){
364 // same types - trivial case
365 if (derived == base)
366 return t;
367
368 // check to see if base/derived pair is found in the registry
369 const void_cast_detail::set_type & s
370 = void_cast_detail::void_caster_registry::get_const_instance();
371 const void_cast_detail::void_caster_argument ca(& derived, & base);
372
373 void_cast_detail::set_type::const_iterator it;
374 it = s.find(x: &ca);
375 if (s.end() != it)
376 return(*it)->downcast(t);
377
378 return NULL;
379}
380
381} // namespace serialization
382} // namespace boost
383

source code of boost/libs/serialization/src/void_cast.cpp