RTTI.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include <Jolt.h>
  4. #include <Core/RTTI.h>
  5. #include <Core/StringTools.h>
  6. namespace JPH {
  7. JPH_IMPLEMENT_RTTI_VIRTUAL_BASE(RTTIAttribute)
  8. {
  9. }
  10. //////////////////////////////////////////////////////////////////////////////////////////
  11. // RTTI
  12. //////////////////////////////////////////////////////////////////////////////////////////
  13. RTTI::RTTI(const char *inName, int inSize, pCreateObjectFunction inCreateObject, pDestructObjectFunction inDestructObject) :
  14. mName(inName),
  15. mSize(inSize),
  16. mCreate(inCreateObject),
  17. mDestruct(inDestructObject)
  18. {
  19. JPH_ASSERT(inDestructObject != nullptr, "Object cannot be destructed");
  20. }
  21. RTTI::RTTI(const char *inName, int inSize, pCreateObjectFunction inCreateObject, pDestructObjectFunction inDestructObject, pCreateRTTIFunction inCreateRTTI) :
  22. mName(inName),
  23. mSize(inSize),
  24. mCreate(inCreateObject),
  25. mDestruct(inDestructObject)
  26. {
  27. JPH_ASSERT(inDestructObject != nullptr, "Object cannot be destructed");
  28. inCreateRTTI(*this);
  29. }
  30. int RTTI::GetBaseClassCount() const
  31. {
  32. return (int)mBaseClasses.size();
  33. }
  34. const RTTI *RTTI::GetBaseClass(int inIdx) const
  35. {
  36. return mBaseClasses[inIdx].mRTTI;
  37. }
  38. uint32 RTTI::GetHash() const
  39. {
  40. // Perform diffusion step to get from 64 to 32 bits (see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function)
  41. uint64 hash = HashString(mName);
  42. return (uint32)(hash ^ (hash >> 32));
  43. }
  44. void *RTTI::CreateObject() const
  45. {
  46. return IsAbstract()? nullptr : mCreate();
  47. }
  48. void RTTI::DestructObject(void *inObject) const
  49. {
  50. mDestruct(inObject);
  51. }
  52. void RTTI::AddBaseClass(const RTTI *inRTTI, int inOffset)
  53. {
  54. JPH_ASSERT(inOffset >= 0 && inOffset < mSize, "Base class not contained in derived class");
  55. // Add base class
  56. BaseClass base;
  57. base.mRTTI = inRTTI;
  58. base.mOffset = inOffset;
  59. mBaseClasses.push_back(base);
  60. // Add attributes of base class
  61. for (AttributeRefC a : inRTTI->mAttributes)
  62. mAttributes.push_back(a);
  63. }
  64. bool RTTI::operator == (const RTTI &inRHS) const
  65. {
  66. // Compare addresses
  67. if (this == &inRHS)
  68. return true;
  69. // Check that the names differ (if that is the case we probably have two instances
  70. // of the same attribute info across the program, probably the second is in a DLL)
  71. JPH_ASSERT(strcmp(mName, inRHS.mName) != 0);
  72. return false;
  73. }
  74. bool RTTI::IsKindOf(const RTTI *inRTTI) const
  75. {
  76. // Check if this is the same type
  77. if (this == inRTTI)
  78. return true;
  79. // Check all base classes
  80. for (const BaseClass &b : mBaseClasses)
  81. if (b.mRTTI->IsKindOf(inRTTI))
  82. return true;
  83. return false;
  84. }
  85. const void *RTTI::CastTo(const void *inObject, const RTTI *inRTTI) const
  86. {
  87. JPH_ASSERT(inObject != nullptr);
  88. // Check if this is the same type
  89. if (this == inRTTI)
  90. return inObject;
  91. // Check all base classes
  92. for (const BaseClass &b : mBaseClasses)
  93. {
  94. // Cast the pointer to the base class
  95. const void *casted = (const void *)(((const uint8 *)inObject) + b.mOffset);
  96. // Test base class
  97. const void *rv = b.mRTTI->CastTo(casted, inRTTI);
  98. if (rv != nullptr)
  99. return rv;
  100. }
  101. // Not possible to cast
  102. return nullptr;
  103. }
  104. void RTTI::AddAttribute(RTTIAttribute *inAttribute)
  105. {
  106. mAttributes.push_back(inAttribute);
  107. }
  108. int RTTI::GetAttributeCount() const
  109. {
  110. return (int)mAttributes.size();
  111. }
  112. const RTTIAttribute *RTTI::GetAttribute(int inIdx) const
  113. {
  114. return mAttributes[inIdx];
  115. }
  116. const RTTIAttribute *RTTI::GetAttribute(const RTTI *inRTTI, const char *inName) const
  117. {
  118. for (AttributeRefC a : mAttributes)
  119. if (::JPH::IsKindOf(a, inRTTI) && strcmp(inName, a->GetName()) == 0)
  120. return a;
  121. return nullptr;
  122. }
  123. } // JPH