[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