1 /** 2 * Implementation of array assignment support routines. 3 * 4 * Copyright: Copyright Digital Mars 2004 - 2010. 5 * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 * Authors: Walter Bright, Sean Kelly 7 */ 8 9 /* Copyright Digital Mars 2004 - 2010. 10 * Distributed under the Boost Software License, Version 1.0. 11 * (See accompanying file LICENSE or copy at 12 * http://www.boost.org/LICENSE_1_0.txt) 13 */ 14 module rt.cast_; 15 16 extern (C): 17 18 /****************************************** 19 * Given a pointer: 20 * If it is an Object, return that Object. 21 * If it is an interface, return the Object implementing the interface. 22 * If it is null, return null. 23 * Else, undefined crash 24 */ 25 Object _d_toObject(void* p) 26 { 27 if (!p) 28 return null; 29 30 Object o = cast(Object) p; 31 ClassInfo oc = typeid(o); 32 Interface* pi = **cast(Interface***) p; 33 34 /* Interface.offset lines up with ClassInfo.name.ptr, 35 * so we rely on pointers never being less than 64K, 36 * and Objects never being greater. 37 */ 38 if (pi.offset < 0x10000) 39 { 40 debug(cast_) printf("\tpi.offset = %d\n", pi.offset); 41 return cast(Object)(p - pi.offset); 42 } 43 return o; 44 } 45 46 /************************************* 47 * Attempts to cast Object o to class c. 48 * Returns o if successful, null if not. 49 */ 50 void* _d_interface_cast(void* p, ClassInfo c) 51 { 52 debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); 53 if (!p) 54 return null; 55 56 Interface* pi = **cast(Interface***) p; 57 58 debug(cast_) printf("\tpi.offset = %d\n", pi.offset); 59 return _d_dynamic_cast(cast(Object)(p - pi.offset), c); 60 } 61 62 void* _d_dynamic_cast(Object o, ClassInfo c) 63 { 64 debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); 65 66 void* res = null; 67 size_t offset = 0; 68 if (o && _d_isbaseof2(typeid(o), c, offset)) 69 { 70 debug(cast_) printf("\toffset = %d\n", offset); 71 res = cast(void*) o + offset; 72 } 73 debug(cast_) printf("\tresult = %p\n", res); 74 return res; 75 } 76 77 int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset) 78 { 79 if (oc is c) 80 return true; 81 82 do 83 { 84 if (oc.base is c) 85 return true; 86 87 // Bugzilla 2013: Use depth-first search to calculate offset 88 // from the derived (oc) to the base (c). 89 foreach (iface; oc.interfaces) 90 { 91 if (iface.classinfo is c || _d_isbaseof2(iface.classinfo, c, offset)) 92 { 93 offset += iface.offset; 94 return true; 95 } 96 } 97 98 oc = oc.base; 99 } while (oc); 100 101 return false; 102 } 103 104 int _d_isbaseof(ClassInfo oc, ClassInfo c) 105 { 106 if (oc is c) 107 return true; 108 109 do 110 { 111 if (oc.base is c) 112 return true; 113 114 foreach (iface; oc.interfaces) 115 { 116 if (iface.classinfo is c || _d_isbaseof(iface.classinfo, c)) 117 return true; 118 } 119 120 oc = oc.base; 121 } while (oc); 122 123 return false; 124 } 125 126 /********************************* 127 * Find the vtbl[] associated with Interface ic. 128 */ 129 void* _d_interface_vtbl(ClassInfo ic, Object o) 130 { 131 debug(cast_) printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic); 132 133 assert(o); 134 135 foreach (iface; typeid(o).interfaces) 136 { 137 if (iface.classinfo is ic) 138 return cast(void*) iface.vtbl; 139 } 140 assert(0); 141 } 142