]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
7c673cae
FG
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 boundries.
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 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 }
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 virtual ~void_caster_shortcut(){
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(*(*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
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(*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
188class 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 }
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 virtual ~void_caster_argument(){};
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(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
277BOOST_SERIALIZATION_DECL void
278void_caster::recursive_unregister() const {
b32b8144 279 BOOST_ASSERT(! void_caster_registry::is_destroyed());
7c673cae
FG
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
314BOOST_SYMBOL_VISIBLE void const *
315void_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.
325BOOST_SERIALIZATION_DECL void const *
326void_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
348BOOST_SYMBOL_VISIBLE void const *
349void_downcast(
350 extended_type_info const & derived,
351 extended_type_info const & base,
352 void const * const t
353);
354
355BOOST_SERIALIZATION_DECL void const *
356void_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