]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/serialization/src/void_cast.cpp
update sources to v12.2.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 BOOST_ASSERT(! void_caster_registry::is_destroyed());
280 if(void_caster_registry::is_destroyed())
281 return;
282
283 #ifdef BOOST_SERIALIZATION_LOG
284 std::clog << "recursive_unregister\n";
285 std::clog << m_derived->get_debug_info();
286 std::clog << "<-";
287 std::clog << m_base->get_debug_info();
288 std::clog << "\n";
289 #endif
290
291 void_cast_detail::set_type & s
292 = void_caster_registry::get_mutable_instance();
293
294 // delete all shortcuts which use this primitive
295 void_cast_detail::set_type::iterator it;
296 for(it = s.begin(); it != s.end();){
297 const void_caster * vc = *it;
298 if(vc == this){
299 s.erase(it++);
300 }
301 else
302 if(vc->m_parent == this){
303 s.erase(it);
304 delete vc;
305 it = s.begin();
306 }
307 else
308 it++;
309 }
310 }
311
312 } // namespace void_cast_detail
313
314 BOOST_SYMBOL_VISIBLE void const *
315 void_upcast(
316 extended_type_info const & derived,
317 extended_type_info const & base,
318 void const * const t
319 );
320
321 // Given a void *, assume that it really points to an instance of one type
322 // and alter it so that it would point to an instance of a related type.
323 // Return the altered pointer. If there exists no sequence of casts that
324 // can transform from_type to to_type, return a NULL.
325 BOOST_SERIALIZATION_DECL void const *
326 void_upcast(
327 extended_type_info const & derived,
328 extended_type_info const & base,
329 void const * const t
330 ){
331 // same types - trivial case
332 if (derived == base)
333 return t;
334
335 // check to see if base/derived pair is found in the registry
336 const void_cast_detail::set_type & s
337 = void_cast_detail::void_caster_registry::get_const_instance();
338 const void_cast_detail::void_caster_argument ca(& derived, & base);
339
340 void_cast_detail::set_type::const_iterator it;
341 it = s.find(& ca);
342 if (s.end() != it)
343 return (*it)->upcast(t);
344
345 return NULL;
346 }
347
348 BOOST_SYMBOL_VISIBLE void const *
349 void_downcast(
350 extended_type_info const & derived,
351 extended_type_info const & base,
352 void const * const t
353 );
354
355 BOOST_SERIALIZATION_DECL void const *
356 void_downcast(
357 extended_type_info const & derived,
358 extended_type_info const & base,
359 void const * const t
360 ){
361 // same types - trivial case
362 if (derived == base)
363 return t;
364
365 // check to see if base/derived pair is found in the registry
366 const void_cast_detail::set_type & s
367 = void_cast_detail::void_caster_registry::get_const_instance();
368 const void_cast_detail::void_caster_argument ca(& derived, & base);
369
370 void_cast_detail::set_type::const_iterator it;
371 it = s.find(&ca);
372 if (s.end() != it)
373 return(*it)->downcast(t);
374
375 return NULL;
376 }
377
378 } // namespace serialization
379 } // namespace boost