|
|
@ -40,6 +40,12 @@ namespace DFHack
|
|
|
|
{
|
|
|
|
{
|
|
|
|
class virtual_class {};
|
|
|
|
class virtual_class {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
|
|
|
typedef void *virtual_ptr;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
typedef virtual_class *virtual_ptr;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
class DFHACK_EXPORT virtual_identity {
|
|
|
|
class DFHACK_EXPORT virtual_identity {
|
|
|
|
static virtual_identity *list;
|
|
|
|
static virtual_identity *list;
|
|
|
|
static std::map<void*, virtual_identity*> known;
|
|
|
|
static std::map<void*, virtual_identity*> known;
|
|
|
@ -56,9 +62,9 @@ namespace DFHack
|
|
|
|
protected:
|
|
|
|
protected:
|
|
|
|
virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent);
|
|
|
|
virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent);
|
|
|
|
|
|
|
|
|
|
|
|
bool check_instance(virtual_class *instance_ptr, bool allow_subclasses);
|
|
|
|
bool check_instance(virtual_ptr instance_ptr, bool allow_subclasses);
|
|
|
|
|
|
|
|
|
|
|
|
static void *get_vtable(virtual_class *instance_ptr) { return *(void**)instance_ptr; }
|
|
|
|
static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; }
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
const char *getName() { return dfhack_name; }
|
|
|
|
const char *getName() { return dfhack_name; }
|
|
|
@ -67,9 +73,9 @@ namespace DFHack
|
|
|
|
virtual_identity *getParent() { return parent; }
|
|
|
|
virtual_identity *getParent() { return parent; }
|
|
|
|
const std::vector<virtual_identity*> &getChildren() { return children; }
|
|
|
|
const std::vector<virtual_identity*> &getChildren() { return children; }
|
|
|
|
|
|
|
|
|
|
|
|
static virtual_identity *get(virtual_class *instance_ptr);
|
|
|
|
static virtual_identity *get(virtual_ptr instance_ptr);
|
|
|
|
|
|
|
|
|
|
|
|
bool is_instance(virtual_class *instance_ptr) {
|
|
|
|
bool is_instance(virtual_ptr instance_ptr) {
|
|
|
|
if (!instance_ptr) return false;
|
|
|
|
if (!instance_ptr) return false;
|
|
|
|
if (vtable_ptr) {
|
|
|
|
if (vtable_ptr) {
|
|
|
|
void *vtable = get_vtable(instance_ptr);
|
|
|
|
void *vtable = get_vtable(instance_ptr);
|
|
|
@ -79,7 +85,7 @@ namespace DFHack
|
|
|
|
return check_instance(instance_ptr, true);
|
|
|
|
return check_instance(instance_ptr, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool is_direct_instance(virtual_class *instance_ptr) {
|
|
|
|
bool is_direct_instance(virtual_ptr instance_ptr) {
|
|
|
|
if (!instance_ptr) return false;
|
|
|
|
if (!instance_ptr) return false;
|
|
|
|
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
|
|
|
|
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
|
|
|
|
: check_instance(instance_ptr, false);
|
|
|
|
: check_instance(instance_ptr, false);
|
|
|
@ -89,12 +95,12 @@ namespace DFHack
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
template<class T>
|
|
|
|
inline T *virtual_cast(virtual_class *ptr) {
|
|
|
|
inline T *virtual_cast(virtual_ptr ptr) {
|
|
|
|
return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL;
|
|
|
|
return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
template<class T>
|
|
|
|
inline T *strict_virtual_cast(virtual_class *ptr) {
|
|
|
|
inline T *strict_virtual_cast(virtual_ptr ptr) {
|
|
|
|
return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL;
|
|
|
|
return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|