1 module lifetime.class_; 2 3 pragma(LDC_no_moduleinfo); 4 5 import lifetime.common; 6 7 /// Allocate and initialise a class 8 extern(C) Object _d_newclass(const TypeInfo_Class ti) 9 { 10 auto buff = lwdrInternal_allocBytes(ti.m_init.length); 11 foreach(i; 0 .. ti.m_init.length) 12 buff[i] = ti.m_init[i]; 13 return cast(Object)buff.ptr; 14 } 15 16 /// Finalize and deallocate a class 17 extern(C) void _d_delclass(Object* o) nothrow @nogc 18 { 19 if(*o) 20 { 21 rt_finalize(cast(void*)*o); 22 23 lwdrInternal_free(cast(void*)*o); 24 *o = null; 25 } 26 } 27 28 /// Allocate and initialise a class 29 extern(C) Object _d_allocclass(TypeInfo_Class ti) 30 { 31 auto buff = lwdrInternal_allocBytes(ti.m_init.length); 32 foreach(i; 0 .. ti.m_init.length) 33 buff[i] = ti.m_init[i]; 34 return cast(Object)buff.ptr; 35 } 36 37 /****************************************** 38 * Given a pointer: 39 * If it is an Object, return that Object. 40 * If it is an interface, return the Object implementing the interface. 41 * If it is null, return null. 42 * Else, undefined crash 43 */ 44 extern(C) Object _d_toObject(return void* p) pure nothrow @nogc 45 { 46 if (!p) 47 return null; 48 49 Object o = cast(Object) p; 50 ClassInfo oc = typeid(o); 51 Interface* pi = **cast(Interface***) p; 52 53 /* Interface.offset lines up with ClassInfo.name.ptr, 54 * so we rely on pointers never being less than 64K, 55 * and Objects never being greater. 56 */ 57 if (pi.offset < 0x10000) 58 { 59 debug(cast_) printf("\tpi.offset = %d\n", pi.offset); 60 return cast(Object)(p - pi.offset); 61 } 62 return o; 63 } 64 65 /************************************* 66 * Attempts to cast Object o to class c. 67 * Returns o if successful, null if not. 68 */ 69 extern(C) void* _d_interface_cast(void* p, ClassInfo c) pure nothrow @nogc 70 { 71 debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); 72 if (!p) 73 return null; 74 75 Interface* pi = **cast(Interface***) p; 76 77 debug(cast_) printf("\tpi.offset = %d\n", pi.offset); 78 return _d_dynamic_cast(cast(Object)(p - pi.offset), c); 79 } 80 81 /// Cast an Object from one representation to another 82 extern(C) void* _d_dynamic_cast(Object o, ClassInfo c) pure nothrow @nogc 83 { 84 debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); 85 86 void* res = null; 87 size_t offset = 0; 88 if (o && _d_isbaseof2(typeid(o), c, offset)) 89 { 90 debug(cast_) printf("\toffset = %d\n", offset); 91 res = cast(void*) o + offset; 92 } 93 debug(cast_) printf("\tresult = %p\n", res); 94 return res; 95 } 96 97 /// Check if `c` is base of `oc` 98 extern(C) int _d_isbaseof2(scope ClassInfo oc, scope const ClassInfo c, scope ref size_t offset) @safe pure nothrow @nogc 99 { 100 if (oc is c) 101 return true; 102 103 do 104 { 105 if (oc.base is c) 106 return true; 107 108 // Bugzilla 2013: Use depth-first search to calculate offset 109 // from the derived (oc) to the base (c). 110 foreach (iface; oc.interfaces) 111 { 112 if (iface.classinfo is c || _d_isbaseof2(iface.classinfo, c, offset)) 113 { 114 offset += iface.offset; 115 return true; 116 } 117 } 118 119 oc = oc.base; 120 } while (oc); 121 122 return false; 123 } 124 125 /// Check if `c` is base of `oc` 126 extern(C) int _d_isbaseof(scope ClassInfo oc, scope const ClassInfo c) @safe pure nothrow @nogc 127 { 128 if (oc is c) 129 return true; 130 131 do 132 { 133 if (oc.base is c) 134 return true; 135 136 foreach (iface; oc.interfaces) 137 { 138 if (iface.classinfo is c || _d_isbaseof(iface.classinfo, c)) 139 return true; 140 } 141 142 oc = oc.base; 143 } while (oc); 144 145 return false; 146 }