special case 'intermixed variable and fixed size fields': fixed reply side, needs testing
This commit is contained in:
parent
77b594f958
commit
fe0e32b5fa
250
src/c_client.py
250
src/c_client.py
|
@ -292,12 +292,10 @@ def _c_type_setup(self, name, postfix):
|
|||
self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
|
||||
self.c_serialize_name = _n(name + ('serialize',))
|
||||
self.c_unserialize_name = _n(name + ('unserialize',))
|
||||
self.c_unpack_name = _n(name + ('unpack',))
|
||||
self.c_sizeof_name = _n(name + ('sizeof',))
|
||||
# if hasattr(self, 'reply'):
|
||||
# if self.reply is not None:
|
||||
# self.c_serialize_name = _n(name + ('reply', 'serialize'))
|
||||
# self.c_unserialize_name = _n(name + ('reply', 'unserialize'))
|
||||
# indicates rare structs where variable size fields are followed fixed size fields
|
||||
|
||||
# special case: structs where variable size fields are followed by fixed size fields
|
||||
self.var_followed_by_fixed_fields = False
|
||||
|
||||
# whether a request or reply has a switch field
|
||||
|
@ -323,18 +321,19 @@ def _c_type_setup(self, name, postfix):
|
|||
# if field.type.member.need_serialize:
|
||||
# self.need_serialize = True
|
||||
self.need_sizeof = True
|
||||
# print "-> variable size list elements: %s (%s %s)" % (self.c_type, field.field_type, field.field_name)
|
||||
|
||||
field.c_field_type = _t(field.field_type)
|
||||
field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
|
||||
field.c_field_name = _cpp(field.field_name)
|
||||
field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
|
||||
field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
|
||||
|
||||
# correct the c_pointer field for variable size non-list types
|
||||
if not field.type.fixed_size() and field.c_pointer == ' ':
|
||||
field.c_pointer = '*'
|
||||
if field.type.is_list and not field.type.member.fixed_size():
|
||||
field.c_pointer = '*'
|
||||
|
||||
if field.type.is_switch:
|
||||
field.c_pointer = '*'
|
||||
field.c_field_const_type = 'const ' + field.c_field_type
|
||||
|
@ -369,16 +368,10 @@ def _c_type_setup(self, name, postfix):
|
|||
prev_varsized_field = field
|
||||
prev_varsized_offset = 0
|
||||
|
||||
# very special case - if self.var_followed_by_fixed_fields==True,
|
||||
# we have to generate accessor functions also for fixed size fields
|
||||
# now there might a naming conflict if the length field ends with _length
|
||||
if self.var_followed_by_fixed_fields:
|
||||
if field.type.is_list:
|
||||
if field.type.expr.lenfield_name is not None:
|
||||
full_lenfield_name = _n(name + (field.type.expr.lenfield_name,))
|
||||
if full_lenfield_name == field.c_length_name:
|
||||
field.c_length_name += '_'
|
||||
|
||||
if field.type.fixed_size():
|
||||
field.prev_varsized_field = None
|
||||
|
||||
if self.need_serialize:
|
||||
# when _unserialize() is wanted, create _sizeof() as well for consistency reasons
|
||||
self.need_sizeof = True
|
||||
|
@ -390,16 +383,18 @@ def _c_type_setup(self, name, postfix):
|
|||
finished_switch.append(self.c_type)
|
||||
# special: switch C structs get pointer fields for variable-sized members
|
||||
_c_complex(self)
|
||||
# FIXME: declare switch (un)packing functions
|
||||
_c_accessors(self, name, name)
|
||||
# FIXME: what about accessors & switch (un)packing functions
|
||||
# _c_iterator() does not seem to be the right place to do it,
|
||||
# as the accessors would need any parameters to pass to _unpack() as well
|
||||
|
||||
# FIXME - in case of request/reply, serialize() is not always needed
|
||||
if not self.is_bitcase:
|
||||
if self.need_serialize:
|
||||
if self.c_serialize_name not in finished_serializers:
|
||||
finished_serializers.append(self.c_serialize_name)
|
||||
_c_serialize(self)
|
||||
_c_unserialize(self)
|
||||
# _unpack() and _unserialize() are only needed for special cases
|
||||
if self.is_switch or self.var_followed_by_fixed_fields:
|
||||
_c_unserialize(self)
|
||||
if self.need_sizeof:
|
||||
if self.c_sizeof_name not in finished_sizeof:
|
||||
finished_sizeof.append(self.c_sizeof_name)
|
||||
|
@ -500,7 +495,7 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
|
|||
params = []
|
||||
if 'serialize' == context:
|
||||
params.append(('void', '**', buffer_var))
|
||||
elif context in ('unserialize', 'sizeof'):
|
||||
elif context in ('unserialize', 'unpack', 'sizeof'):
|
||||
params.append(('const void', '*', buffer_var))
|
||||
|
||||
# look for special cases
|
||||
|
@ -526,10 +521,10 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
|
|||
if 'serialize' == context:
|
||||
add_param(params, ('const %s' % self.c_type, '*', aux_var))
|
||||
elif 'unserialize' == context:
|
||||
if self.is_switch:
|
||||
add_param(params, ('%s' % self.c_type, '*', aux_var))
|
||||
else:
|
||||
add_param(params, ('%s' % self.c_type, '**', aux_var))
|
||||
add_param(params, ('%s' % self.c_type, '**', aux_var))
|
||||
elif 'unpack' == context:
|
||||
add_param(params, ('%s' % self.c_type, '*', aux_var))
|
||||
|
||||
if not self.is_switch and 'serialize' == context:
|
||||
for p in param_fields:
|
||||
if not p.type.fixed_size():
|
||||
|
@ -573,8 +568,6 @@ def _c_field_mapping(context, complex_type, prefix):
|
|||
|
||||
fname = "%s%s" % (prefix_str, f.c_field_name)
|
||||
if fields.has_key(f.field_name):
|
||||
continue
|
||||
# FIXME
|
||||
raise Exception("field name %s has been registered before" % f.field_name)
|
||||
fields[f.field_name] = (fname, f)
|
||||
if f.type.is_container:
|
||||
|
@ -604,7 +597,7 @@ def _c_serialize_helper_insert_padding(context, code_lines, space):
|
|||
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
|
||||
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
|
||||
code_lines.append('%s xcb_parts_idx++;' % space)
|
||||
elif 'unserialize' == context:
|
||||
elif context in ('unserialize', 'unpack', 'sizeof'):
|
||||
code_lines.append('%s xcb_tmp += xcb_pad;' % space)
|
||||
|
||||
code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
|
||||
|
@ -626,6 +619,7 @@ def _c_serialize_helper_switch(context, self, complex_name,
|
|||
for b in self.bitcases:
|
||||
bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix_str)
|
||||
code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
|
||||
code_lines.append(' printf("entering bitcase section for %%%%d...\\n", %s);' % bitcase_expr)
|
||||
b_prefix = switch_prefix
|
||||
if b.type.has_name:
|
||||
b_prefix = switch_prefix + [(b.c_field_name, '.', b.type)]
|
||||
|
@ -638,7 +632,7 @@ def _c_serialize_helper_switch(context, self, complex_name,
|
|||
|
||||
if 'serialize' == context:
|
||||
count += _c_serialize_helper_insert_padding(context, code_lines, space)
|
||||
if 'unserialize' == context:
|
||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
||||
# padding
|
||||
code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
|
||||
code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
|
||||
|
@ -651,6 +645,7 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
|
|||
param_fields, wire_fields, params = get_serialize_params(context, self)
|
||||
args = get_expr_fields(field.type)
|
||||
field_mapping = _c_field_mapping(context, self, prefix)
|
||||
prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
|
||||
|
||||
# determine which params to pass to _unserialize() and their prefixes
|
||||
switch_len_fields = resolve_fields(self, field.type)
|
||||
|
@ -662,10 +657,14 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
|
|||
c_field_names += "%s, " % field_mapping[a.c_field_name][0]
|
||||
for a in args:
|
||||
c_field_names += "%s, " % field_mapping[a.c_field_name][0]
|
||||
# switch_field_name = field_mapping[field.field_name][0]
|
||||
# call _unserialize() to determine the actual size
|
||||
length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name,
|
||||
c_field_names, c_switch_variable) #switch_field_name)
|
||||
|
||||
# call _serialize()/_unpack() to determine the actual size
|
||||
if 'serialize' == context:
|
||||
length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
|
||||
c_field_names, prefix_str, field.c_field_name)
|
||||
elif context in ('unserialize', 'unpack'):
|
||||
length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
|
||||
c_field_names, prefix_str, field.c_field_name)
|
||||
return length
|
||||
# _c_serialize_helper_switch_field()
|
||||
|
||||
|
@ -704,7 +703,7 @@ def _c_serialize_helper_list_field(context, self, field,
|
|||
# list with variable-sized elements
|
||||
if not field.type.member.fixed_size():
|
||||
length = ''
|
||||
if context in ('unserialize', 'sizeof'):
|
||||
if context in ('unserialize', 'sizeof', 'unpack'):
|
||||
int_i = ' unsigned int i;'
|
||||
xcb_tmp_len = ' unsigned int xcb_tmp_len;'
|
||||
if int_i not in temp_vars:
|
||||
|
@ -743,7 +742,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
|
|||
|
||||
length = "sizeof(%s)" % field.c_field_type
|
||||
|
||||
if context in ('unserialize', 'sizeof'):
|
||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
||||
value = ' %s%s = *(%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
|
||||
if field.type.is_pad and field.type.nmemb > 1:
|
||||
value = ''
|
||||
|
@ -751,7 +750,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
|
|||
code_lines.append('%s %s%s[%d] = *(%s *)xcb_tmp;' %
|
||||
(space, prefix_str, field.c_field_name, i, field.c_field_type))
|
||||
length += " * %d" % field.type.nmemb
|
||||
# FIXME? - lists
|
||||
|
||||
if field.type.is_list:
|
||||
raise Exception('list with fixed number of elemens unhandled in _unserialize()')
|
||||
elif 'serialize' == context:
|
||||
|
@ -791,30 +790,37 @@ def _c_serialize_helper_fields_variable_size(context, self, field,
|
|||
space, prefix):
|
||||
prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
|
||||
|
||||
if context in ('unserialize', 'sizeof'):
|
||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
||||
value = ''
|
||||
var_field_name = 'xcb_tmp'
|
||||
if self.var_followed_by_fixed_fields and 'unserialize' == context:
|
||||
value = ' %s = xcb_tmp;' % field.c_field_name
|
||||
temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
|
||||
if 'unpack' == context:
|
||||
value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
|
||||
elif 'serialize' == context:
|
||||
address_of = '&' if (self.is_bitcase and self.has_name) else ''
|
||||
value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s%s;' % (address_of, prefix_str, field.c_field_name)
|
||||
var_field_name = "%s%s%s" % (address_of, prefix_str, field.c_field_name)
|
||||
value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
|
||||
length = ''
|
||||
|
||||
prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
|
||||
code_lines.append('%s /* %s */' % (space, field.c_field_name))
|
||||
|
||||
if field.type.is_list:
|
||||
if value != '':
|
||||
code_lines.append("%s%s" % (space, value))
|
||||
value = ''
|
||||
length = _c_serialize_helper_list_field(context, self, field,
|
||||
code_lines, temp_vars,
|
||||
space, prefix)
|
||||
elif field.type.is_switch:
|
||||
prev = filter(lambda x: x.find('xcb_switch_field'), temp_vars)
|
||||
var_name = 'xcb_switch_field%d' % len(prev)
|
||||
temp_vars.append(' %s %s;' % (field.type.c_type, var_name))
|
||||
length = _c_serialize_helper_switch_field(context, self, field, var_name, prefix)
|
||||
value = ''
|
||||
if context == 'serialize':
|
||||
value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
|
||||
length = _c_serialize_helper_switch_field(context, self, field, 'xcb_parts[xcb_parts_idx].iov_base', prefix)
|
||||
else:
|
||||
length = "%s(xcb_tmp)" % (field.type.c_sizeof_name)
|
||||
length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
|
||||
|
||||
return (value, length)
|
||||
# _c_serialize_helper_fields_variable_size
|
||||
|
@ -866,18 +872,17 @@ def _c_serialize_helper_fields(context, self,
|
|||
code_lines.append('%s%s' % (space, value))
|
||||
if field.type.fixed_size() and is_bitcase:
|
||||
code_lines.append('%s xcb_block_len += %s;' % (space, length))
|
||||
if context in ('unserialize', 'sizeof'):
|
||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
||||
code_lines.append('%s xcb_tmp += %s;' % (space, length))
|
||||
else:
|
||||
# padding
|
||||
if '' != length:
|
||||
code_lines.append('%s xcb_block_len = %s;' % (space, length))
|
||||
if (not field.type.fixed_size() and
|
||||
self.var_followed_by_fixed_fields and
|
||||
'unserialize' == context):
|
||||
self.var_followed_by_fixed_fields and 'unserialize' == context):
|
||||
temp_vars.append(' int %s_len;' % field.c_field_name)
|
||||
code_lines.append(' %s_len = xcb_block_len;' % field.c_field_name)
|
||||
if context in ('unserialize', 'sizeof'):
|
||||
if context in ('unserialize', 'sizeof', 'unpack'):
|
||||
code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
|
||||
if 'serialize' == context:
|
||||
if '' != length:
|
||||
|
@ -912,7 +917,7 @@ def _c_serialize_helper(context, complex_type,
|
|||
# all other data types can be evaluated one field a time
|
||||
else:
|
||||
# unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
|
||||
if context in ('unserialize', 'sizeof') and not self.var_followed_by_fixed_fields:
|
||||
if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
|
||||
code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
|
||||
code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
|
||||
_c_serialize_helper_insert_padding(context, code_lines, space)
|
||||
|
@ -1043,7 +1048,13 @@ def _c_unserialize(self):
|
|||
variable_size_fields = 0
|
||||
# maximum space required for type definition of function arguments
|
||||
maxtypelen = 0
|
||||
param_fields, wire_fields, params = get_serialize_params('unserialize', self)
|
||||
if self.is_switch:
|
||||
context = 'unpack'
|
||||
func_name = self.c_unpack_name
|
||||
else:
|
||||
context = 'unserialize'
|
||||
func_name = self.c_unserialize_name
|
||||
param_fields, wire_fields, params = get_serialize_params(context, self)
|
||||
|
||||
# determine N(variable_fields)
|
||||
for field in param_fields:
|
||||
|
@ -1058,10 +1069,10 @@ def _c_unserialize(self):
|
|||
for idx, p in enumerate(params):
|
||||
line = ""
|
||||
typespec, pointerspec, field_name = p
|
||||
indent = ' '*(len(self.c_unserialize_name)+2)
|
||||
indent = ' '*(len(func_name)+2)
|
||||
# p==0: function declaration
|
||||
if 0==idx:
|
||||
line = "%s (" % self.c_unserialize_name
|
||||
line = "%s (" % func_name
|
||||
indent = ''
|
||||
spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
|
||||
line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
|
||||
|
@ -1084,7 +1095,7 @@ def _c_unserialize(self):
|
|||
|
||||
code_lines = []
|
||||
temp_vars = []
|
||||
_c_serialize_helper('unserialize', self,
|
||||
_c_serialize_helper(context, self,
|
||||
code_lines, temp_vars)
|
||||
for t in temp_vars:
|
||||
_c(t)
|
||||
|
@ -1093,9 +1104,21 @@ def _c_unserialize(self):
|
|||
for l in code_lines:
|
||||
_c(l)
|
||||
_c('')
|
||||
if not self.is_switch:
|
||||
if self.var_followed_by_fixed_fields:
|
||||
_c(' free(_aux);')
|
||||
|
||||
if 'unserialize' == context:
|
||||
# allocate memory automatically
|
||||
_c(' if (NULL == *_aux) {')
|
||||
_c(' /* allocate memory */')
|
||||
_c(' *_aux = malloc(xcb_buffer_len);')
|
||||
_c(' }')
|
||||
_c('')
|
||||
_c(' **_aux = xcb_out;')
|
||||
_c(' xcb_tmp = (char *)++(*_aux);')
|
||||
for field in param_fields:
|
||||
if not field.type.fixed_size():
|
||||
_c(' memcpy(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
|
||||
_c(' xcb_tmp += %s_len;', field.c_field_name)
|
||||
_c('')
|
||||
|
||||
_c(' return xcb_buffer_len;')
|
||||
_c('}')
|
||||
|
@ -1142,25 +1165,31 @@ def _c_sizeof_helper(self):
|
|||
_c("%s)" % line)
|
||||
|
||||
_c('{')
|
||||
# if self.is_switch: call serialize
|
||||
|
||||
param_names = [p[2] for p in params]
|
||||
if self.is_switch:
|
||||
# switch: call _unpack()
|
||||
_c(' %s _aux;', self.c_type)
|
||||
param_names = [p[2] for p in params]
|
||||
_c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
|
||||
elif self.var_followed_by_fixed_fields:
|
||||
# special case: call _unserialize()
|
||||
_c(' %s *_aux = NULL;', self.c_type)
|
||||
_c(' return %s(%s, &_aux);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
|
||||
# otherwise: evaluate parameters directly
|
||||
else:
|
||||
_c(' char *xcb_tmp = (char *)_buffer;')
|
||||
if not self.var_followed_by_fixed_fields:
|
||||
_c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
|
||||
else:
|
||||
_c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
|
||||
_c(' unsigned int xcb_buffer_len = 0;')
|
||||
_c(' unsigned int xcb_block_len = 0;')
|
||||
_c(' unsigned int xcb_pad = 0;')
|
||||
code_lines = []
|
||||
temp_vars = []
|
||||
_c_serialize_helper('sizeof', self,
|
||||
code_lines, temp_vars)
|
||||
_c(' char *xcb_tmp = (char *)_buffer;')
|
||||
if len(filter(lambda x: x.find('_aux')!=-1, code_lines))>0:
|
||||
if not self.var_followed_by_fixed_fields:
|
||||
_c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
|
||||
else:
|
||||
_c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
|
||||
_c(' unsigned int xcb_buffer_len = 0;')
|
||||
_c(' unsigned int xcb_block_len = 0;')
|
||||
_c(' unsigned int xcb_pad = 0;')
|
||||
for t in temp_vars:
|
||||
_c(t)
|
||||
_c('')
|
||||
|
@ -1168,11 +1197,7 @@ def _c_sizeof_helper(self):
|
|||
for l in code_lines:
|
||||
_c(l)
|
||||
_c('')
|
||||
if not self.is_switch:
|
||||
if self.var_followed_by_fixed_fields:
|
||||
_c(' free(_aux);')
|
||||
_c(' return xcb_buffer_len;')
|
||||
|
||||
_c('}')
|
||||
# _c_sizeof_helper()
|
||||
|
||||
|
@ -1350,7 +1375,7 @@ def _c_accessor_get_expr(expr, prefix='', sep='->'):
|
|||
prefix += sep
|
||||
list_name = "%s%s" % (prefix, field.c_field_name)
|
||||
c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
|
||||
# FIXME
|
||||
# FIXME - works only for integers this way!!
|
||||
c_length_func = _c_accessor_get_expr(field.type.expr, prefix='', sep='')
|
||||
return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
|
||||
elif expr.op != None:
|
||||
|
@ -1399,16 +1424,24 @@ def _c_accessors_field(self, field):
|
|||
_hc(' **')
|
||||
_hc(' *****************************************************************************/')
|
||||
_hc(' ')
|
||||
_hc('%s *', field.c_field_type)
|
||||
if field.type.is_switch:
|
||||
return_type = 'void *'
|
||||
else:
|
||||
return_type = '%s *' % field.c_field_type
|
||||
|
||||
_hc(return_type)
|
||||
_h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
|
||||
_c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
|
||||
_c('{')
|
||||
if field.prev_varsized_field is None:
|
||||
_c(' return (%s *) (R + 1);', field.c_field_type)
|
||||
_c(' return (%s) (R + 1);', return_type)
|
||||
# note: the special case 'variable fields followed by fixed size fields'
|
||||
# is not of any consequence here, since the ordering gets
|
||||
# 'corrected' in the reply function
|
||||
else:
|
||||
_c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
|
||||
_c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
|
||||
field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
|
||||
_c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
|
||||
return_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
|
||||
_c('}')
|
||||
|
||||
def _c_accessors_list(self, field):
|
||||
|
@ -1526,15 +1559,14 @@ def _c_accessors(self, name, base):
|
|||
'''
|
||||
Declares the accessor functions for the fields of a structure.
|
||||
'''
|
||||
for field in self.fields:
|
||||
# no accessors for switch -
|
||||
# switch always needs to be unserialized explicitly
|
||||
if self.is_switch:
|
||||
continue
|
||||
if field.type.is_list and not field.type.fixed_size():
|
||||
_c_accessors_list(self, field)
|
||||
elif field.prev_varsized_field != None or not field.type.fixed_size():
|
||||
_c_accessors_field(self, field)
|
||||
# no accessors for switch -
|
||||
# switch always needs to be unpacked explicitly
|
||||
if not self.is_switch:
|
||||
for field in self.fields:
|
||||
if field.type.is_list and not field.type.fixed_size():
|
||||
_c_accessors_list(self, field)
|
||||
elif field.prev_varsized_field is not None or not field.type.fixed_size():
|
||||
_c_accessors_field(self, field)
|
||||
|
||||
def c_simple(self, name):
|
||||
'''
|
||||
|
@ -1925,7 +1957,29 @@ def _c_reply(self, name):
|
|||
spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
|
||||
spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
|
||||
spacing3 = ' ' * (len(self.c_reply_name) + 2)
|
||||
|
||||
|
||||
# check if _unserialize() has to be called for any field
|
||||
def look_for_special_cases(complex_obj):
|
||||
unserialize_fields = []
|
||||
# no unserialize call in case of switch
|
||||
if not complex_obj.is_switch:
|
||||
for field in complex_obj.fields:
|
||||
# three cases: 1. field with special case
|
||||
# 2. container that contains special case field
|
||||
# 3. list with special case elements
|
||||
if field.type.var_followed_by_fixed_fields:
|
||||
unserialize_fields.append(field)
|
||||
elif field.type.is_container:
|
||||
unserialize_fields += look_for_special_cases(field.type)
|
||||
elif field.type.is_list:
|
||||
if field.type.member.var_followed_by_fixed_fields:
|
||||
unserialize_fields.append(field)
|
||||
if field.type.member.is_container:
|
||||
unserialize_fields += look_for_special_cases(field.type.member)
|
||||
return unserialize_fields
|
||||
|
||||
unserialize_fields = look_for_special_cases(self.reply)
|
||||
|
||||
_h('')
|
||||
_h('/**')
|
||||
_h(' * Return the reply')
|
||||
|
@ -1960,7 +2014,35 @@ def _c_reply(self, name):
|
|||
_h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
|
||||
_c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
|
||||
_c('{')
|
||||
_c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
|
||||
|
||||
if len(unserialize_fields)>0:
|
||||
# certain variable size fields need to be unserialized explicitly
|
||||
_c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
|
||||
self.c_reply_type, self.c_reply_type)
|
||||
_c(' int i;')
|
||||
for field in unserialize_fields:
|
||||
if field.type.is_list:
|
||||
_c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
|
||||
_c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
|
||||
_c(' %s *%s_data;', field.c_field_type, field.c_field_name)
|
||||
else:
|
||||
raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
|
||||
# call _unserialize(), using the reply as source and target buffer
|
||||
_c(' /* special cases: transform parts of the reply to match XCB data structures */')
|
||||
for field in unserialize_fields:
|
||||
if field.type.is_list:
|
||||
_c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
|
||||
_c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
|
||||
_c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
|
||||
field.c_field_name, field.c_field_name)
|
||||
_c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
|
||||
_c(' }')
|
||||
# return the transformed reply
|
||||
_c(' return reply;')
|
||||
|
||||
else:
|
||||
_c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
|
||||
|
||||
_c('}')
|
||||
|
||||
def _c_opcode(name, opcode):
|
||||
|
|
Loading…
Reference in New Issue