[Xcb] [[PATCH proto]] Add list length calc. if in reply wo/ length expr.

Daniel Martin consume.noise at gmail.com
Sat Feb 23 02:30:33 PST 2013


This one adds (injects) a calculation for a list if it is in a reply and
no length expression was specified.

The formula used is:
    (length*4 + 32 - sizeof(reply¹)) / sizeof(listtype)

The formula will be added by injecting the necessary xml tree
(expression, value and fieldref nodes) into the list itself.

¹ The fixed part of the reply.

Signed-off-by: Daniel Martin <consume.noise at gmail.com>
---
I thought about removing the 2. case in __add_list_len_calc() and
leaving it up to the compiler/whatever to optimize a useless
calculation out. Anyone has an opinion on this? I don't.

 xcbgen/xtypes.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/xcbgen/xtypes.py b/xcbgen/xtypes.py
index f6d4634..26c3df3 100644
--- a/xcbgen/xtypes.py
+++ b/xcbgen/xtypes.py
@@ -1,6 +1,7 @@
 '''
 This module contains the classes which represent XCB data types.
 '''
+from xml.etree.cElementTree import SubElement
 from xcbgen.expr import Field, Expression
 import __main__
 
@@ -160,12 +161,89 @@ class ListType(Type):
     expr is an Expression object containing the length information, for variable-sized lists.
     '''
     def __init__(self, elt, member, *parent):
+        def __find_reply(parents):
+            for p in parents:
+                if hasattr(p, 'is_reply') and p.is_reply:
+                    return p
+                elif hasattr(p, 'parents'):
+                    q = parent_is_reply(p.parents)
+                    if q: return q
+            return None
+
+        def __add_list_len_calc(reply_size, type_size):
+            # Basic formula:
+            #     (length*4 + 32 - reply_size) / type_size
+            # as we already know reply_size:
+            #     (length*4 + rep_sub_32) / type_size # 1. case
+            # and if rep_sub_32 == 0:
+            #     (length*4) / type_size              # 2. case
+
+            rep_sub_32 = reply_size - 32
+            if rep_sub_32: # 1. case
+                # <op op="/">
+                #     <op op="+">
+                #         <op op="*">
+                #             <fieldref>length</fieldref>
+                #             <value>4</value>
+                #         </op>
+                #         <value>rep_sub_32</value>
+                #     </op>
+                #     <value>type_size</value>
+                # </op>
+                op_div = SubElement(elt, 'op')
+                op_div.set('op', '/')
+
+                op_sum = SubElement(op_div, 'op')
+                op_sum.set('op', '+')
+
+                op_mul = SubElement(op_sum, 'op')
+                op_mul.set('op', '*')
+                ref_len = SubElement(op_mul, 'fieldref')
+                ref_len.text = 'length'
+                val_4 = SubElement(op_mul, 'value')
+                val_4.text = '4'
+
+                val_rep_sub_32 = SubElement(op_sum, 'value')
+                val_rep_sub_32.text = str(rep_sub_32)
+
+                val_type = SubElement(op_div, 'value')
+                val_type.text = str(type_size)
+            else:
+                # <op op="/">
+                #     <op op="*">
+                #         <fieldref>length</fieldref>
+                #         <value>4</value>
+                #     </op>
+                #     <value>type_size</value>
+                # </op>
+                op_div = SubElement(elt, 'op')
+                op_div.set('op', '/')
+
+                op_mul = SubElement(op_div, 'op')
+                op_mul.set('op', '*')
+                ref_len = SubElement(op_mul, 'fieldref')
+                ref_len.text = 'length'
+                val_4 = SubElement(op_mul, 'value')
+                val_4.text = '4'
+
+                val_type = SubElement(op_div, 'value')
+                val_type.text = str(type_size)
+            # def __add_list_len_calc(reply_size, type_size):
+
         Type.__init__(self, member.name)
         self.is_list = True
         self.member = member
         self.parents = list(parent)
 
         if elt.tag == 'list':
+            if not len(list(elt)):
+                # List with no children (no length expression). Check if it's
+                # in a reply, then we need to add a list length calculation.
+                reply = __find_reply(self.parents)
+                if reply:
+                    __add_list_len_calc(reply.get_fixed_part_size(),
+                            self.member.get_fixed_part_size())
+
             elts = list(elt)
             self.expr = Expression(elts[0] if len(elts) else elt, self)
         elif elt.tag == 'valueparam':
@@ -353,6 +431,17 @@ class ComplexType(Type):
                 return False
         return True
 
+    def get_fixed_part_size(self):
+        size = 0
+        for m in self.fields:
+            if not m.wire:
+                continue
+            if m.type.fixed_size():
+                size = size + (m.type.size * m.type.nmemb)
+            else:
+                break
+        return size
+
 class SwitchType(ComplexType):
     '''
     Derived class which represents a List of Items.  
-- 
1.8.1.4



More information about the Xcb mailing list