mirror of
https://github.com/autc04/Retro68.git
synced 2025-01-02 17:31:35 +00:00
139 lines
3.5 KiB
D
139 lines
3.5 KiB
D
/**
|
|
* Implementation of array assignment support routines.
|
|
*
|
|
* Copyright: Copyright Digital Mars 2004 - 2010.
|
|
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
|
|
* Authors: Walter Bright, Sean Kelly
|
|
* Source: $(DRUNTIMESRC rt/_cast_.d)
|
|
*/
|
|
|
|
/* Copyright Digital Mars 2004 - 2010.
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE or copy at
|
|
* http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
module rt.cast_;
|
|
|
|
extern (C):
|
|
@nogc:
|
|
nothrow:
|
|
pure:
|
|
|
|
// Needed because ClassInfo.opEquals(Object) does a dynamic cast,
|
|
// but we are trying to implement dynamic cast.
|
|
extern (D) private bool areClassInfosEqual(scope const ClassInfo a, scope const ClassInfo b) @safe
|
|
{
|
|
if (a is b)
|
|
return true;
|
|
// take care of potential duplicates across binaries
|
|
return a.name == b.name;
|
|
}
|
|
|
|
/******************************************
|
|
* Given a pointer:
|
|
* If it is an Object, return that Object.
|
|
* If it is an interface, return the Object implementing the interface.
|
|
* If it is null, return null.
|
|
* Else, undefined crash
|
|
*/
|
|
Object _d_toObject(return scope void* p)
|
|
{
|
|
if (!p)
|
|
return null;
|
|
|
|
Object o = cast(Object) p;
|
|
ClassInfo oc = typeid(o);
|
|
Interface* pi = **cast(Interface***) p;
|
|
|
|
/* Interface.offset lines up with ClassInfo.name.ptr,
|
|
* so we rely on pointers never being less than 64K,
|
|
* and Objects never being greater.
|
|
*/
|
|
if (pi.offset < 0x10000)
|
|
{
|
|
debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
|
|
return cast(Object)(p - pi.offset);
|
|
}
|
|
return o;
|
|
}
|
|
|
|
/*************************************
|
|
* Attempts to cast Object o to class c.
|
|
* Returns o if successful, null if not.
|
|
*/
|
|
void* _d_interface_cast(void* p, ClassInfo c)
|
|
{
|
|
debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
|
|
if (!p)
|
|
return null;
|
|
|
|
Interface* pi = **cast(Interface***) p;
|
|
|
|
debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
|
|
return _d_dynamic_cast(cast(Object)(p - pi.offset), c);
|
|
}
|
|
|
|
void* _d_dynamic_cast(Object o, ClassInfo c)
|
|
{
|
|
debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
|
|
|
|
void* res = null;
|
|
size_t offset = 0;
|
|
if (o && _d_isbaseof2(typeid(o), c, offset))
|
|
{
|
|
debug(cast_) printf("\toffset = %d\n", offset);
|
|
res = cast(void*) o + offset;
|
|
}
|
|
debug(cast_) printf("\tresult = %p\n", res);
|
|
return res;
|
|
}
|
|
|
|
int _d_isbaseof2(scope ClassInfo oc, scope const ClassInfo c, scope ref size_t offset) @safe
|
|
{
|
|
if (areClassInfosEqual(oc, c))
|
|
return true;
|
|
|
|
do
|
|
{
|
|
if (oc.base && areClassInfosEqual(oc.base, c))
|
|
return true;
|
|
|
|
// Bugzilla 2013: Use depth-first search to calculate offset
|
|
// from the derived (oc) to the base (c).
|
|
foreach (iface; oc.interfaces)
|
|
{
|
|
if (areClassInfosEqual(iface.classinfo, c) || _d_isbaseof2(iface.classinfo, c, offset))
|
|
{
|
|
offset += iface.offset;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
oc = oc.base;
|
|
} while (oc);
|
|
|
|
return false;
|
|
}
|
|
|
|
int _d_isbaseof(scope ClassInfo oc, scope const ClassInfo c) @safe
|
|
{
|
|
if (areClassInfosEqual(oc, c))
|
|
return true;
|
|
|
|
do
|
|
{
|
|
if (oc.base && areClassInfosEqual(oc.base, c))
|
|
return true;
|
|
|
|
foreach (iface; oc.interfaces)
|
|
{
|
|
if (areClassInfosEqual(iface.classinfo, c) || _d_isbaseof(iface.classinfo, c))
|
|
return true;
|
|
}
|
|
|
|
oc = oc.base;
|
|
} while (oc);
|
|
|
|
return false;
|
|
}
|