Mercurial > paraspace
diff paraspace/dexfile.py @ 104:61cef1662035
Redirect types
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Thu, 28 Jul 2011 00:06:54 +0800 |
parents | 7fcd555d802b |
children | 7821c6e89622 |
line wrap: on
line diff
--- a/paraspace/dexfile.py Wed Jul 27 12:09:19 2011 +0800 +++ b/paraspace/dexfile.py Thu Jul 28 00:06:54 2011 +0800 @@ -1031,7 +1031,7 @@ class _DEX_TypeList(composite): num = uint32 - typeItems = array('num', uint16) + typeItems = array('num', depend_idx('DEXFile.typeIds')(uint16)) child_names = 'num typeItems'.split() pass @@ -1693,7 +1693,29 @@ ## \brief Return name string of a linked class definition item @staticmethod def get_classdef_name(classdef): - return classdef.classIdx.descriptorIdx.stringDataOff.data.data + return DEXFile_linked.get_typeid_name(classdef.classIdx) + + ## \brief Return name string of a linked type ID item. + @staticmethod + def get_typeid_name(typeid): + return typeid.descriptorIdx.stringDataOff.data.data + + ## \brief Get index of given type ID. + def get_idx_typeid(self, typeid): + return self.typeIds.items.index(typeid) + + ## \brief Find type ID item with given name. + def find_typeid_name(self, name): + for typeid in self.typeIds.items: + typeid_name = DEXFile_linked.get_typeid_name(typeid) + if typeid_name == name: + return typeid + pass + pass + + ## \brief Return type ID item with given index. + def find_typeid_idx(self, idx): + return self.typeIds.items[idx] def find_class_name(self, name): for classdef in self.classDefs.items: @@ -1703,6 +1725,15 @@ pass raise ValueError, 'can not find class definition for \'%s\'' % (name) + ## \brief Return a class definition corresponding for give type ID. + def find_class_typeid(self, typeid): + for classdef in self.classDefs.items: + if classdef.classIdx == typeid: + return classdef + pass + raise ValueError, \ + 'can not find class definition for typeid %s' % (repr(typeid)) + ## \brief Update size of map items. # # Corresponding data lists of maps may be changed, it should be updated @@ -1769,6 +1800,61 @@ return wmethod pass pass + + ## \brief Get name of given method ID. + @staticmethod + def get_methodid_name(methoid): + return methoid.nameIdx.stringDataOff.data.data + + ## \brief Find the method ID item of given index. + def find_methodid_idx(self, idx): + methodid = self.methodIds.items[idx] + return methodid + + ## \brief Find a method definition with an index to method ID. + def find_method_idx(self, idx): + methodid = self.find_methodid_idx(idx) + method_name = DEXFile_linked.get_methoid_name(methodid) + method_proto = methodid.protoIdx + method_typeid = methodid.classIdx + classdef = self.find_class_typeid(method_typeid) + + method = self.find_method_name_proto(method, method_proto, classdef) + + return method + + ## \brief Test if prototype of two methods are compatible. + @staticmethod + def _proto_is_compatible(proto1, proto2): + if proto1.returnTypeIdx != proto2.returnTypeIdx: + return False + typelist1 = proto1.parametersOffRef.value + typelist2 = proto2.parametersOffRef.value + if len(typelist1.typeItems.items) != len(typelist2.typeItems.items): + return False + + for typeid1, typeid2 in map(None, + typelist1.typeItems.items, + typelist2.typeItems.items): + if typeid1 != typeid2: + return False + pass + return True + + def find_method_name_proto(self, method_name, proto, classdef): + if not classdef.classDataOffRef.is_true: + return + + classdata = classdef.classDataOffRef.value + for wmethod in classdata.directMethods.items + \ + classdata.virtualMethods.items: + wmethod_name = DEXFile_linked.get_method_name(wmethod) + if method_name != wmethod_name: + continue + if DEXFile_linked._proto_is_compatible(wmethod.protoIdx, proto): + return wmethod + pass + raise ValueError, 'can not find a method for given name and prototype' pass