comparison lphobos/internal/cast.d @ 113:27b9f749d9fe trunk

[svn r117] Initial working implementation of interfaces. Groundwork for all the different types of class/interface casts laid out.
author lindquist
date Sat, 24 Nov 2007 06:33:00 +0100
parents
children
comparison
equal deleted inserted replaced
112:368547b1cbe6 113:27b9f749d9fe
1 /*
2 * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
3 * Written by Walter Bright
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, in both source and binary form, subject to the following
12 * restrictions:
13 *
14 * o The origin of this software must not be misrepresented; you must not
15 * claim that you wrote the original software. If you use this software
16 * in a product, an acknowledgment in the product documentation would be
17 * appreciated but is not required.
18 * o Altered source versions must be plainly marked as such, and must not
19 * be misrepresented as being the original software.
20 * o This notice may not be removed or altered from any source
21 * distribution.
22 */
23
24
25 import object;
26 import std.c.stdio;
27
28 extern (C):
29
30 /******************************************
31 * Given a pointer:
32 * If it is an Object, return that Object.
33 * If it is an interface, return the Object implementing the interface.
34 * If it is null, return null.
35 * Else, undefined crash
36 */
37
38 Object _d_toObject(void* p)
39 { Object o;
40
41 if (p)
42 {
43 o = cast(Object)p;
44 //ClassInfo oc = o.classinfo;
45 Interface *pi = **cast(Interface ***)p;
46
47 /* Interface.offset lines up with ClassInfo.name.ptr,
48 * so we rely on pointers never being less than 64K,
49 * and Objects never being greater.
50 */
51 if (pi.offset < 0x10000)
52 {
53 //printf("\tpi.offset = %d\n", pi.offset);
54 o = cast(Object)(p - pi.offset);
55 }
56 }
57 return o;
58 }
59
60
61 /*************************************
62 * Attempts to cast Object o to class c.
63 * Returns o if successful, null if not.
64 */
65
66 Object _d_interface_cast(void* p, ClassInfo c)
67 { Object o;
68
69 //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
70 if (p)
71 {
72 Interface *pi = **cast(Interface ***)p;
73
74 //printf("\tpi.offset = %d\n", pi.offset);
75 o = cast(Object)(p - pi.offset);
76 return _d_dynamic_cast(o, c);
77 }
78 return o;
79 }
80
81 Object _d_dynamic_cast(Object o, ClassInfo c)
82 { ClassInfo oc;
83 uint offset = 0;
84
85 //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
86
87 if (o)
88 {
89 oc = o.classinfo;
90 if (_d_isbaseof2(oc, c, offset))
91 {
92 //printf("\toffset = %d\n", offset);
93 o = cast(Object)(cast(void*)o + offset);
94 }
95 else
96 o = null;
97 }
98 //printf("\tresult = %p\n", o);
99 return o;
100 }
101
102 int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset)
103 { int i;
104
105 if (oc is c)
106 return 1;
107 do
108 {
109 if (oc.base is c)
110 return 1;
111 for (i = 0; i < oc.interfaces.length; i++)
112 {
113 ClassInfo ic;
114
115 ic = oc.interfaces[i].classinfo;
116 if (ic is c)
117 { offset = oc.interfaces[i].offset;
118 return 1;
119 }
120 }
121 for (i = 0; i < oc.interfaces.length; i++)
122 {
123 ClassInfo ic;
124
125 ic = oc.interfaces[i].classinfo;
126 if (_d_isbaseof2(ic, c, offset))
127 { offset = oc.interfaces[i].offset;
128 return 1;
129 }
130 }
131 oc = oc.base;
132 } while (oc);
133 return 0;
134 }
135
136 int _d_isbaseof(ClassInfo oc, ClassInfo c)
137 { int i;
138
139 if (oc is c)
140 return 1;
141 do
142 {
143 if (oc.base is c)
144 return 1;
145 for (i = 0; i < oc.interfaces.length; i++)
146 {
147 ClassInfo ic;
148
149 ic = oc.interfaces[i].classinfo;
150 if (ic is c || _d_isbaseof(ic, c))
151 return 1;
152 }
153 oc = oc.base;
154 } while (oc);
155 return 0;
156 }
157
158 /*********************************
159 * Find the vtbl[] associated with Interface ic.
160 */
161
162 void *_d_interface_vtbl(ClassInfo ic, Object o)
163 { int i;
164 ClassInfo oc;
165
166 //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
167
168 assert(o);
169
170 oc = o.classinfo;
171 for (i = 0; i < oc.interfaces.length; i++)
172 {
173 ClassInfo oic;
174
175 oic = oc.interfaces[i].classinfo;
176 if (oic is ic)
177 {
178 return cast(void *)oc.interfaces[i].vtbl;
179 }
180 }
181 assert(0);
182 }