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