diff paraspace/dexfile.py @ 40:0c0a659187c2

Use _objs_asso to define association between two set of items. Derivation of _objs_asso define a rule to assocate elements from first set to another element in second set.
author Thinker K.F. Li <thinker@codemud.net>
date Sat, 18 Jun 2011 23:59:37 +0800
parents e625ebf17441
children c5cfc796af8b
line wrap: on
line diff
--- a/paraspace/dexfile.py	Thu Jun 16 08:03:50 2011 +0800
+++ b/paraspace/dexfile.py	Sat Jun 18 23:59:37 2011 +0800
@@ -175,7 +175,7 @@
 class tap(_dex_type):
     @staticmethod
     def parse(parent, data, off):
-        pass
+        return tap()
 
     @staticmethod
     def sizeof(v):
@@ -329,6 +329,84 @@
     return o.__class__.sizeof(o)
 
 
+## \biref Associate objects from two set of objects.
+#
+class _objs_asso(_dex_type):
+    left = None
+    left_ref = None
+    right = None
+    right_ref = None
+    
+    ## \brief Update references for a element pair from left and right.
+    #
+    # This method must be called by derivation to associate a pair of
+    # elements.
+    #
+    def _update_refs(self, left_elt, right_elt):
+        lref = getattr(left_elt, self.left_ref)
+        if not isinstance(right_elt, lref.target_path):
+            raise TypeError, 'invalid target_path in left %s' % (repr(le))
+        
+        rref = getattr(right_elt, self.right_ref)
+        if not isinstance(left_elt, rref.target_path):
+            raise TypeError, 'invalid target_path in right %s' % (repr(re))
+        
+        new_lref = ref(lref.target_path)
+        new_lref.target = right_elt
+        setattr(left_elt, self.left_ref, new_lref)
+
+        new_rref = ref(rref.target_path)
+        new_rref.target = left_elt
+        setattr(right_elt, self.right_ref, new_rref)
+        pass
+    
+    ## \brief Assocate elements from left list to a respective right element.
+    #
+    # This method must be called before linking dependencies.
+    #
+    def build_associations(self, left, right):
+        raise NotImplementedError, 'build_associations is not implemented'
+    pass
+
+
+## \brief One to one association.
+#
+# Associate nth element from left sequence to nth element in right
+# sequence.
+#
+class one2one(_objs_asso):
+    def __init__(self, left, left_ref, right, right_ref):
+        self.left = left
+        self.left_ref = left_ref
+        self.right = right
+        self.right_ref = right_ref
+        pass
+
+    ## \brief Associate elements from left list to elements from right list
+    #
+    def build_associations(self, left, right):
+        assert len(left) == len(right)
+        for le, re in map(None, left, right):
+            self._update_refs(le, re)
+            pass
+        pass
+    pass
+
+
+## \brief Implicit reference to a target.
+#
+# It is a placeholder for storing relationship defined by an association.
+#
+class ref(_dex_type):
+    target_path = None
+    target = None
+
+    def __init__(self, target_path=None):
+        self.target_path = target_path
+        pass
+    pass
+
+
 class relocatable(_dex_type):
     data_size = None
 
@@ -832,11 +910,18 @@
 
 
 class _DEX_TypeList(composite):
-    padding = auto_align(2)     # 2 bits alignment
     num = uint32
     typeItems = array('num', uint16)
 
-    child_names = 'padding num typeItems'.split()
+    child_names = 'num typeItems'.split()
+    pass
+
+
+class _DEX_TypeList_align(composite):
+    padding = auto_align(2)     # 2 bits alignment
+    value = _DEX_TypeList
+    
+    child_names = 'padding value'.split()
     pass
 
 
@@ -844,7 +929,8 @@
     startAddr = uint32
     insnCount = uint16
     handlerOff = depend_off_rel('_DEX_Code.handlers_size',
-                                '_DEX_Catch')(uint16)
+                                '_DEX_Try.catch_ref.target')(uint16)
+    catch_ref = ref('_DEX_Catch')
 
     child_names = 'startAddr insnCount handlerOff'.split()
     pass
@@ -870,6 +956,7 @@
     handlers = array('count', _DEX_CatchHandler)
     catchAllHandler = cond((lambda parent, data, off: parent.catchesAll),
                            _DEX_CatchAllHandler)
+    try_ref = ref('_DEX_Try')
 
     child_names = 'size handlers catchAllHandler'.split()
 
@@ -903,6 +990,8 @@
     handlers_size = cond(_has_tries, uleb128)
     catch_handler_items = cond(_has_tries,
                                array('handlers_size.value', _DEX_Catch))
+    try_catch_asso = one2one('try_items.value.items', 'catch_ref',
+                             'catch_handler_items.value.items', 'try_ref')
 
     padding2 = auto_align(2)
 
@@ -1326,7 +1415,7 @@
     methodIds = array(None, _DEX_MethodId)
     classDefs = array(None, _DEX_ClassDef)
     classDatas = array(None, _DEX_ClassData)
-    typeLists = array(None, _DEX_TypeList)
+    typeLists = array(None, _DEX_TypeList_align)
     codeItems = array(None, _DEX_Code)
     annotationSetItems = array(None, _DEX_AnnotationSetItem)
     annotationsDirectoryItems = array(None, _DEX_AnnotationsDirectoryItem)