]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/src/void_cast.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / serialization / src / void_cast.cpp
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
38 namespace boost {
39 namespace serialization {
40 namespace 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 boundries.
47 bool 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
63 struct void_caster_compare {
64 bool operator()(const void_caster * lhs, const void_caster * rhs) const {
65 return *lhs < *rhs;
66 }
67 };
68
69 typedef std::set<const void_caster *, void_caster_compare> set_type;
70 typedef 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
78 class 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 virtual void const *
91 upcast(void const * const t) const{
92 if(m_includes_virtual_base)
93 return vbc_upcast(t);
94 return static_cast<const char *> ( t ) - m_difference;
95 }
96 virtual void const *
97 downcast(void const * const t) const{
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 virtual bool has_virtual_base() const {
106 return m_includes_virtual_base;
107 }
108 public:
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 virtual ~void_caster_shortcut(){
122 recursive_unregister();
123 }
124 };
125
126 #ifdef BOOST_MSVC
127 # pragma warning(pop)
128 #endif
129
130 void const *
131 void_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(*(*it)->m_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_new);
151 }
152 }
153 }
154 }
155 return NULL;
156 }
157
158 void const *
159 void_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(*m_derived, *(*it)->m_derived, t);
174 if(NULL != t_new)
175 return (*it)->upcast(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
188 class void_caster_argument : public void_caster
189 {
190 virtual void const *
191 upcast(void const * const /*t*/) const {
192 BOOST_ASSERT(false);
193 return NULL;
194 }
195 virtual void const *
196 downcast( void const * const /*t*/) const {
197 BOOST_ASSERT(false);
198 return NULL;
199 }
200 virtual bool has_virtual_base() const {
201 BOOST_ASSERT(false);
202 return false;
203 }
204 public:
205 void_caster_argument(
206 extended_type_info const * derived,
207 extended_type_info const * base
208 ) :
209 void_caster(derived, base)
210 {}
211 virtual ~void_caster_argument(){};
212 };
213
214 #ifdef BOOST_MSVC
215 # pragma warning(pop)
216 #endif
217
218 // implementation of void caster base class
219 BOOST_SERIALIZATION_DECL void
220 void_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(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(& 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(& 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
277 BOOST_SERIALIZATION_DECL void
278 void_caster::recursive_unregister() const {
279 if(void_caster_registry::is_destroyed())
280 return;
281
282 #ifdef BOOST_SERIALIZATION_LOG
283 std::clog << "recursive_unregister\n";
284 std::clog << m_derived->get_debug_info();
285 std::clog << "<-";
286 std::clog << m_base->get_debug_info();
287 std::clog << "\n";
288 #endif
289
290 void_cast_detail::set_type & s
291 = void_caster_registry::get_mutable_instance();
292
293 // delete all shortcuts which use this primitive
294 void_cast_detail::set_type::iterator it;
295 for(it = s.begin(); it != s.end();){
296 const void_caster * vc = *it;
297 if(vc == this){
298 s.erase(it++);
299 }
300 else
301 if(vc->m_parent == this){
302 s.erase(it);
303 delete vc;
304 it = s.begin();
305 }
306 else
307 it++;
308 }
309 }
310
311 } // namespace void_cast_detail
312
313 BOOST_SYMBOL_VISIBLE void const *
314 void_upcast(
315 extended_type_info const & derived,
316 extended_type_info const & base,
317 void const * const t
318 );
319
320 // Given a void *, assume that it really points to an instance of one type
321 // and alter it so that it would point to an instance of a related type.
322 // Return the altered pointer. If there exists no sequence of casts that
323 // can transform from_type to to_type, return a NULL.
324 BOOST_SERIALIZATION_DECL void const *
325 void_upcast(
326 extended_type_info const & derived,
327 extended_type_info const & base,
328 void const * const t
329 ){
330 // same types - trivial case
331 if (derived == base)
332 return t;
333
334 // check to see if base/derived pair is found in the registry
335 const void_cast_detail::set_type & s
336 = void_cast_detail::void_caster_registry::get_const_instance();
337 const void_cast_detail::void_caster_argument ca(& derived, & base);
338
339 void_cast_detail::set_type::const_iterator it;
340 it = s.find(& ca);
341 if (s.end() != it)
342 return (*it)->upcast(t);
343
344 return NULL;
345 }
346
347 BOOST_SYMBOL_VISIBLE void const *
348 void_downcast(
349 extended_type_info const & derived,
350 extended_type_info const & base,
351 void const * const t
352 );
353
354 BOOST_SERIALIZATION_DECL void const *
355 void_downcast(
356 extended_type_info const & derived,
357 extended_type_info const & base,
358 void const * const t
359 ){
360 // same types - trivial case
361 if (derived == base)
362 return t;
363
364 // check to see if base/derived pair is found in the registry
365 const void_cast_detail::set_type & s
366 = void_cast_detail::void_caster_registry::get_const_instance();
367 const void_cast_detail::void_caster_argument ca(& derived, & base);
368
369 void_cast_detail::set_type::const_iterator it;
370 it = s.find(&ca);
371 if (s.end() != it)
372 return(*it)->downcast(t);
373
374 return NULL;
375 }
376
377 } // namespace serialization
378 } // namespace boost