2 * Implementation of array assignment support routines.
4 * Copyright: Copyright Digital Mars 2004 - 2010.
5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors: Walter Bright, Sean Kelly
7 * Source: $(DRUNTIMESRC rt/_cast_.d)
10 /* Copyright Digital Mars 2004 - 2010.
11 * Distributed under the Boost Software License, Version 1.0.
12 * (See accompanying file LICENSE or copy at
13 * http://www.boost.org/LICENSE_1_0.txt)
22 // Needed because ClassInfo.opEquals(Object) does a dynamic cast,
23 // but we are trying to implement dynamic cast.
24 extern (D
) private bool areClassInfosEqual(scope const ClassInfo a
, scope const ClassInfo b
) @safe
28 // take care of potential duplicates across binaries
29 return a
.name
== b
.name
;
32 /******************************************
34 * If it is an Object, return that Object.
35 * If it is an interface, return the Object implementing the interface.
36 * If it is null, return null.
37 * Else, undefined crash
39 Object
_d_toObject(return scope void* p
)
44 Object o
= cast(Object
) p
;
45 ClassInfo oc
= typeid(o
);
46 Interface
* pi
= **cast(Interface
***) p
;
48 /* Interface.offset lines up with ClassInfo.name.ptr,
49 * so we rely on pointers never being less than 64K,
50 * and Objects never being greater.
52 if (pi
.offset
< 0x10000)
54 debug(cast_
) printf("\tpi.offset = %d\n", pi
.offset
);
55 return cast(Object
)(p
- pi
.offset
);
60 /*************************************
61 * Attempts to cast Object o to class c.
62 * Returns o if successful, null if not.
64 void* _d_interface_cast(void* p
, ClassInfo c
)
66 debug(cast_
) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p
, c
.name
);
70 Interface
* pi
= **cast(Interface
***) p
;
72 debug(cast_
) printf("\tpi.offset = %d\n", pi
.offset
);
73 return _d_dynamic_cast(cast(Object
)(p
- pi
.offset
), c
);
76 void* _d_dynamic_cast(Object o
, ClassInfo c
)
78 debug(cast_
) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o
, c
.name
);
82 if (o
&& _d_isbaseof2(typeid(o
), c
, offset
))
84 debug(cast_
) printf("\toffset = %d\n", offset
);
85 res
= cast(void*) o
+ offset
;
87 debug(cast_
) printf("\tresult = %p\n", res
);
91 int _d_isbaseof2(scope ClassInfo oc
, scope const ClassInfo c
, scope ref size_t offset
) @safe
93 if (areClassInfosEqual(oc
, c
))
98 if (oc
.base
&& areClassInfosEqual(oc
.base
, c
))
101 // Bugzilla 2013: Use depth-first search to calculate offset
102 // from the derived (oc) to the base (c).
103 foreach (iface
; oc
.interfaces
)
105 if (areClassInfosEqual(iface
.classinfo
, c
) ||
_d_isbaseof2(iface
.classinfo
, c
, offset
))
107 offset
+= iface
.offset
;
118 int _d_isbaseof(scope ClassInfo oc
, scope const ClassInfo c
) @safe
121 return _d_isbaseof2(oc
, c
, offset
);