diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index b83648ef8..a6b98fba2 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -66,6 +66,9 @@ class memory_info::Private // cache for faster name lookup, indexed by classID vector classnames; + // map between vptr and class id, needs further type id lookup for multi-classes, not inherited + map classIDs; + // index for the next added class uint32_t classindex; @@ -336,41 +339,56 @@ void memory_info::setClassChild (t_class * parent, const char * name, const char //cout << " classtype " << name << ", assign " << mcc->assign << ", vtable " << mcc->type << endl; } - +// FIXME: stupid. we need a better container bool memory_info::resolveObjectToClassID(const uint32_t address, int32_t & classid) { uint32_t vtable = g_pProcess->readDWord(address); - // FIXME: stupid search. we need a better container - string classname = g_pProcess->readClassName(vtable); - for(uint32_t i = 0;i< d->classes.size();i++) + // try to find the vtable in our cache + map::iterator it; + it = d->classIDs.find(vtable); + t_class * cl; + + // class found in cache? + if(it != d->classIDs.end()) { - if(d->classes[i]->classname == classname) // got class + cl = (*it).second; + } + else// couldn't find? + { + // we set up the class for the first time + string classname = g_pProcess->readClassName(vtable); + d->classIDs[vtable] = cl = setClass(classname.c_str(),vtable); + } + // and isn't a multi-class + if(!cl->type_offset) + { + // return + classid = cl->assign; + return true; + } + // and is a multiclass + else + { + // find the type + vector & vec = cl->subs; + uint32_t type = g_pProcess->readWord(address + cl->type_offset); + // return typed building if successful + //FIXME: the vector should map directly to the type IDs here, so we don't have to mess with O(n) search + for (uint32_t k = 0; k < vec.size();k++) { - // if it is a multiclass, try resolving it - if(d->classes[i]->type_offset) + if(vec[k]->type == type) { - vector & vec = d->classes[i]->subs; - uint32_t type = g_pProcess->readWord(address + d->classes[i]->type_offset); - //printf ("class %d:%s offset 0x%x\n", i , classes[i].classname.c_str(), classes[i].type_offset); - // return typed building if successful - for (uint32_t k = 0; k < vec.size();k++) - { - if(vec[k]->type == type) - { - //cout << " multi " << address + classes[i].type_offset << " " << vec[k].classname << endl; - classid = vec[k]->assign; - return true; - } - } + //cout << " multi " << address + classes[i].type_offset << " " << vec[k].classname << endl; + classid = vec[k]->assign; + return true; } - // otherwise return the class we found - classid = d->classes[i]->assign; - return true; } + // couldn't find the type... now what do we do here? throw? + // this is a case where it might be a good idea, because it uncovers some deeper problems + // we return the parent class instead, it doesn't change the API semantics and sort-of makes sense + classid = cl->assign; + return true; } - t_class * c = setClass(classname.c_str(),vtable); - classid = c->assign; - return true; } //ALERT: doesn't care about multiclasses diff --git a/library/pydfhack.i b/library/pydfhack.i index 2547bac84..988719576 100644 --- a/library/pydfhack.i +++ b/library/pydfhack.i @@ -186,7 +186,7 @@ namespace DFHack bool getCursorCoords (int32_t &x, int32_t &y, int32_t &z); bool setCursorCoords (const int32_t x, const int32_t y, const int32_t z); - bool getCurrentCursorCreatures(std::vector &OUTPUT); + bool getCurrentCursorCreature(uint32_t &OUTPUT); bool InitViewSize(); diff --git a/output/Memory.xml b/output/Memory.xml index 937021b7f..fc7918e78 100644 --- a/output/Memory.xml +++ b/output/Memory.xml @@ -1696,6 +1696,12 @@ 0x14 0x1C 0x20 + + + + + + 51c73ff46b2688aafaee0204efe91a94