📄 rtti.cpp
字号:
// Output: pointer to the appropriate sub-object of targetted type; NULL if cast fails
//
// Side-effects: NONE.
//
static _RTTIBaseClassDescriptor * __cdecl FindSITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
_RTTITypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
_RTTITypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase;
_RTTIBaseClassDescriptor * const *pBasePtr;
DWORD i;
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
// Test type of selected base class
pBase = *pBasePtr;
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE)) {
return pBase;
}
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
//
// FindMITargetTypeInstance - workhorse routine of __RTDynamicCast() in a Multiple-Inheritance hierarchy
//
// Output: pointer to the appropriate sub-object of targetted type; NULL if cast fails
//
// Side-effects: NONE.
//
static _RTTIBaseClassDescriptor * __cdecl FindMITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
_RTTITypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
_RTTITypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase, *pSubBase;
_RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
DWORD i, j;
// First, try down-casts
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Test type of selected base class
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
// If base class is proper type, see if it contains our instance of source class
for (j = 0, pSubBasePtr = pBasePtr+1;
j < pBase->numContainedBases;
j++, pSubBasePtr++) {
pSubBase = *pSubBasePtr;
if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
(PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset)) {
// Yes, this is the proper instance of source class
return pBase;
}
}
}
}
// Down-cast failed, try cross-cast
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Check if base class has proper type, is accessible & is unambiguous
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS)) {
return pBase;
}
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
//
// FindVITargetTypeInstance - workhorse routine of __RTDynamicCast() in a Virtual-Inheritance hierarchy
//
// Output: pointer to the appropriate sub-object of targetted type; NULL if cast fails
//
// Side-effects: NONE.
//
static _RTTIBaseClassDescriptor * __cdecl FindVITargetTypeInstance (
PVOID pCompleteObject, // pointer to complete object
_RTTICompleteObjectLocator *pCOLocator, // pointer to Locator of complete object
_RTTITypeDescriptor *pSrcTypeID, // pointer to TypeDescriptor of source object
int SrcOffset, // offset of source object in complete object
_RTTITypeDescriptor *pTargetTypeID) // pointer to TypeDescriptor of result of cast
{
_RTTIBaseClassDescriptor *pBase, *pSubBase;
_RTTIBaseClassDescriptor * const *pBasePtr, * const *pSubBasePtr;
_RTTIBaseClassDescriptor *pResult = NULL;
DWORD i, j;
// First, try down-casts
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Test type of selected base class
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID)) {
// If base class is proper type, see if it contains our instance of source class
for (j = 0, pSubBasePtr = pBasePtr+1;
j < pBase->numContainedBases;
j++, pSubBasePtr++) {
pSubBase = *pSubBasePtr;
if (TYPEIDS_EQ(pSubBase->pTypeDescriptor, pSrcTypeID) &&
(PMDtoOffset(pCompleteObject, pSubBase->where) == SrcOffset)) {
// Yes, this is the proper instance of source class - make sure it is unambiguous
// Ambiguity now determined by inequality of offsets of source class within complete object, not pointer inequality
if ((pResult != NULL) && (PMDtoOffset(pCompleteObject, pResult->where) != PMDtoOffset(pCompleteObject, pBase->where))) {
// We already found an earlier instance, hence ambiguity
return NULL;
}
else {
// Unambiguous
pResult = pBase;
}
}
}
}
}
if (pResult != NULL)
return pResult;
// Down-cast failed, try cross-cast
for (i = 0, pBasePtr = pCOLocator->pClassDescriptor->pBaseClassArray->arrayOfBaseClassDescriptors;
i < pCOLocator->pClassDescriptor->numBaseClasses;
i++, pBasePtr++) {
pBase = *pBasePtr;
// Check if base class has proper type, is accessible & is unambiguous
if (TYPEIDS_EQ(pBase->pTypeDescriptor, pTargetTypeID) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_NOTVISIBLE) &&
!(BCD_ATTRIBUTES(*pBase) & BCD_AMBIGUOUS)) {
return pBase;
}
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
//
// PMDtoOffset - Calculate member offset from PMD & this
//
// Output: The offset of the base within the complete object.
//
// Side-effects: NONE.
//
static ptrdiff_t __cdecl PMDtoOffset(
PVOID pThis, // ptr to complete object
const PMD& pmd) // pointer-to-member-data structure
{
ptrdiff_t RetOff = 0;
if (pmd.pdisp >= 0) { // if base is in the virtual part of class
RetOff = pmd.pdisp;
RetOff += *(ptrdiff_t*)((char*)*(ptrdiff_t*)((char*)pThis + RetOff) + pmd.vdisp);
}
RetOff += pmd.mdisp;
return RetOff;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -