/* * Copyright (C) 2004 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, in both source and binary form, subject to the following * restrictions: * * o The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * o Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * o This notice may not be removed or altered from any source * distribution. */ import object; import std.c.stdio; /************************************* * Attempts to cast Object o to class c. * Returns o if successful, null if not. */ extern (C): Object _d_interface_cast(void* p, ClassInfo c) { Object o; //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); if (p) { Interface *pi = **cast(Interface ***)p; //printf("\tpi.offset = %d\n", pi.offset); o = cast(Object)(p - pi.offset); return _d_dynamic_cast(o, c); } return o; } Object _d_dynamic_cast(Object o, ClassInfo c) { ClassInfo oc; uint offset = 0; //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); if (o) { oc = o.classinfo; if (_d_isbaseof2(oc, c, offset)) { //printf("\toffset = %d\n", offset); o = cast(Object)(cast(void*)o + offset); } else o = null; } //printf("\tresult = %p\n", o); return o; } int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset) { int i; if (oc is c) return 1; do { if (oc.base is c) return 1; for (i = 0; i < oc.interfaces.length; i++) { ClassInfo ic; ic = oc.interfaces[i].classinfo; if (ic is c) { offset = oc.interfaces[i].offset; return 1; } } for (i = 0; i < oc.interfaces.length; i++) { ClassInfo ic; ic = oc.interfaces[i].classinfo; if (_d_isbaseof2(ic, c, offset)) { offset = oc.interfaces[i].offset; return 1; } } oc = oc.base; } while (oc); return 0; } int _d_isbaseof(ClassInfo oc, ClassInfo c) { int i; if (oc is c) return 1; do { if (oc.base is c) return 1; for (i = 0; i < oc.interfaces.length; i++) { ClassInfo ic; ic = oc.interfaces[i].classinfo; if (ic is c || _d_isbaseof(ic, c)) return 1; } oc = oc.base; } while (oc); return 0; } /********************************* * Find the vtbl[] associated with Interface ic. */ void *_d_interface_vtbl(ClassInfo ic, Object o) { int i; ClassInfo oc; //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic); assert(o); oc = o.classinfo; for (i = 0; i < oc.interfaces.length; i++) { ClassInfo oic; oic = oc.interfaces[i].classinfo; if (oic is ic) { return cast(void *)oc.interfaces[i].vtbl; } } assert(0); return null; }