[Xcb] [PUSHED] [PATCH libxcb 1/1] calculate lengthless list
Christian Linhart
chris at DemoRecorder.com
Tue Jan 5 17:50:15 PST 2016
I have pushed this patch.
Besides adding useful functionality, it helps to avoid a future ABI/API issue in the present extension,
in the following functions:
* xcb_present_redirect_notify_notifies_length
* xcb_present_redirect_notify_notifies_iterator
Cheers,
Chris
On 2015-11-11 01:02, Christian Linhart wrote:
> From: Jaya Tiwari <tiwari.jaya18 at gmail.com>
>
> Some rework done by Christian Linhart
>
> Signed-off-by: Jaya Tiwari <tiwari.jaya18 at gmail.com>
> Signed-off-by: Christian Linhart <chris at demorecorder.com>
> ---
> src/c_client.py | 84 ++++++++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 62 insertions(+), 22 deletions(-)
>
> diff --git a/src/c_client.py b/src/c_client.py
> index 5d01289..797c85b 100644
> --- a/src/c_client.py
> +++ b/src/c_client.py
> @@ -467,15 +467,16 @@ def _c_type_setup(self, name, postfix):
> field.prev_varsized_offset = prev_varsized_offset
>
> if prev_varsized_offset == 0:
> first_field_after_varsized = field
> field.first_field_after_varsized = first_field_after_varsized
>
> if field.type.fixed_size():
> - prev_varsized_offset += field.type.size
> + if field.wire:
> + prev_varsized_offset += field.type.size
> # special case: intermixed fixed and variable size fields
> if prev_varsized_field is not None and not field.type.is_pad and field.wire:
> if not self.is_union:
> self.c_need_serialize = True
> self.c_var_followed_by_fixed_fields = True
> else:
> self.last_varsized_field = field
> @@ -645,15 +646,15 @@ def _c_helper_resolve_field_names (prefix):
> return all_fields
>
> def get_expr_fields(self):
> """
> get the Fields referenced by switch or list expression
> """
> def get_expr_field_names(expr):
> - if expr.op is None:
> + if expr.op is None or expr.op == 'calculate_len':
> if expr.lenfield_name is not None:
> return [expr.lenfield_name]
> else:
> # constant value expr
> return []
> else:
> if expr.op == '~':
> @@ -722,23 +723,25 @@ def resolve_expr_fields_list(self, parents):
> that cannot be resolved within the parents of the list.
> These are normally fields that need to be given as function parameters
> for length and iterator functions.
> """
> all_fields = []
> expr_fields = get_expr_fields(self)
> unresolved = []
> -
> + dont_resolve_this = ''
> for complex_obj in parents:
> for field in complex_obj.fields:
> + if field.type.is_list and field.type.expr.op == 'calculate_len':
> + dont_resolve_this = field.type.expr.lenfield_name
> if field.wire:
> all_fields.append(field)
>
> # try to resolve expr fields
> for e in expr_fields:
> - if e not in all_fields and e not in unresolved:
> + if e not in all_fields and e not in unresolved and e.field_name != dont_resolve_this:
> unresolved.append(e)
>
> return unresolved
> # resolve_expr_fields_list()
>
>
> def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
> @@ -771,15 +774,17 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
> # fixed and variable size fields
> if self.is_switch:
> param_fields = get_expr_fields(self)
>
> # _serialize()/_unserialize()/_unpack() function parameters
> # note: don't use set() for params, it is unsorted
> params = []
> -
> + parameter = ''
> + if self.is_list:
> + parameter = self.type.expr.lenfield_name
> # 1. the parameter for the void * buffer
> if 'serialize' == context:
> params.append(('void', '**', buffer_var))
> elif context in ('unserialize', 'unpack', 'sizeof'):
> params.append(('const void', '*', buffer_var))
>
> # 2. any expr fields that cannot be resolved within self and descendants
> @@ -791,15 +796,15 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
> # that do not appear in the data type struct
> for p in param_fields:
> if self.is_switch:
> typespec = p.c_field_const_type
> pointerspec = p.c_pointer
> add_param(params, (typespec, pointerspec, p.c_field_name))
> else:
> - if p.visible and not p.wire and not p.auto:
> + if p.visible and not p.wire and not p.auto and p.field_name != parameter:
> typespec = p.c_field_type
> pointerspec = ''
> add_param(params, (typespec, pointerspec, p.c_field_name))
>
> # 4. aux argument
> if 'serialize' == context:
> add_param(params, ('const %s' % self.c_type, '*', aux_var))
> @@ -980,16 +985,18 @@ def _c_serialize_helper_list_field(context, self, field,
> field.c_field_name)
>
> field_mapping.update(_c_helper_resolve_field_names(prefix))
> resolved += [x for x in unresolved if x in field_mapping]
> unresolved = [x for x in unresolved if x not in field_mapping]
> if len(unresolved)>0:
> raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
> -
> - list_length = _c_accessor_get_expr(expr, field_mapping)
> + if expr.op == 'calculate_len':
> + list_length = field.type.expr.lenfield_name
> + else:
> + list_length = _c_accessor_get_expr(expr, field_mapping)
>
> # default: list with fixed size elements
> length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
>
> # list with variable-sized elements
> if not field.type.member.fixed_size():
> # compute string for argumentlist for member-type functions
> @@ -1717,15 +1724,15 @@ def _c_accessor_get_expr(expr, field_mapping):
> _c_pre.pop_indent()
> _c_pre.code("}")
> _c_pre.code("/* sumof end. Result is in %s */", sumvar)
> _c_pre.end()
> return sumvar
> elif expr.op == 'listelement-ref':
> return '(*xcb_listelement)'
> - elif expr.op != None:
> + elif expr.op != None and expr.op != 'calculate_len':
> return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
> ' ' + expr.op + ' ' +
> _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
> elif expr.bitfield:
> return 'xcb_popcount(' + lenexp + ')'
> else:
> return lenexp
> @@ -1907,16 +1914,42 @@ def _c_accessors_list(self, field):
> _hc('%s (const %s *R,', field.c_length_name, R_obj.c_type)
> _h('%sconst %s *S%s);', spacing, S_obj.c_type, add_param_str)
> _c('%sconst %s *S%s)', spacing, S_obj.c_type, add_param_str)
> else:
> _h('%s (const %s *R%s);', field.c_length_name, c_type, add_param_str)
> _c('%s (const %s *R%s)', field.c_length_name, c_type, add_param_str)
> _c('{')
> - length = _c_accessor_get_expr(field.type.expr, fields)
> - _c(' return %s;', length)
> +
> + def get_length():
> + if field.type.expr.op == 'calculate_len':
> + if field.type.member.fixed_size():
> + if field.prev_varsized_field is None:
> + # the list is directly after the fixed size part of the
> + # request: simply subtract the size of the fixed-size part
> + # from the request size and divide that by the member size
> + return '(((R->length * 4) - sizeof('+ self.c_type + '))/'+'sizeof('+field.type.member.c_wiretype+'))'
> + else:
> + # use the accessor to get the start of the list, then
> + # compute the length of it by subtracting it from
> + # the adress of the first byte after the end of the
> + # request
> + after_end_of_request = '(((char*)R) + R->length * 4)'
> + start_of_list = '%s(R)' % (field.c_accessor_name)
> + bytesize_of_list = '%s - (char*)(%s)' % (after_end_of_request, start_of_list)
> + return '(%s) / sizeof(%s)' % (bytesize_of_list, field.type.member.c_wiretype)
> + else:
> + raise Exception(
> + "lengthless lists with varsized members are not supported. Fieldname '%s'"
> + %
> + (field.c_field_name)
> + );
> + else:
> + return _c_accessor_get_expr(field.type.expr, fields)
> +
> + _c(' return %s;', get_length())
> _c('}')
>
> if field.type.member.is_simple:
> _hc('')
> _hc('xcb_generic_iterator_t')
> spacing = ' '*(len(field.c_end_name)+2)
> add_param_str = additional_params_to_str(spacing)
> @@ -1929,53 +1962,52 @@ def _c_accessors_list(self, field):
> _c('%s (const %s *R%s)', field.c_end_name, c_type, add_param_str)
> _c('{')
> _c(' xcb_generic_iterator_t i;')
>
> param = 'R' if switch_obj is None else 'S'
> if switch_obj is not None:
> _c(' i.data = %s + %s;', fields[field.c_field_name][0],
> - _c_accessor_get_expr(field.type.expr, fields))
> + get_length())
> elif field.prev_varsized_field == None:
> _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
> - _c_accessor_get_expr(field.type.expr, fields))
> + get_length())
> else:
> (prev_varsized_field, align_pad) = get_align_pad(field)
>
> if align_pad is None:
> align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
> type_pad_type(field.first_field_after_varsized.type.c_type))
>
> _c(' xcb_generic_iterator_t prev = %s;',
> _c_iterator_get_end(prev_varsized_field, 'R'))
> _c(' i.data = ((%s *) ((char*) prev.data + %s)) + (%s);',
> field.type.c_wiretype, align_pad,
> - _c_accessor_get_expr(field.type.expr, fields))
> + get_length())
>
> _c(' i.rem = 0;')
> _c(' i.index = (char *) i.data - (char *) %s;', param)
> _c(' return i;')
> _c('}')
>
> else:
> _hc('')
> _hc('%s', field.c_iterator_type)
> spacing = ' '*(len(field.c_iterator_name)+2)
> - add_param_str = additional_params_to_str(spacing)
> if switch_obj is not None:
> _hc('%s (const %s *R,', field.c_iterator_name, R_obj.c_type)
> _h('%sconst %s *S%s);', spacing, S_obj.c_type, add_param_str)
> _c('%sconst %s *S%s)', spacing, S_obj.c_type, add_param_str)
> else:
> _h('%s (const %s *R%s);', field.c_iterator_name, c_type, add_param_str)
> _c('%s (const %s *R%s)', field.c_iterator_name, c_type, add_param_str)
> _c('{')
> _c(' %s i;', field.c_iterator_type)
>
> _c_pre.start()
> - length_expr_str = _c_accessor_get_expr(field.type.expr, fields)
> + length_expr_str = get_length()
>
> if switch_obj is not None:
> _c_pre.end()
> _c(' i.data = %s;', fields[field.c_field_name][0])
> _c(' i.rem = %s;', length_expr_str)
> elif field.prev_varsized_field == None:
> _c_pre.end()
> @@ -2350,19 +2382,24 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
> if not field.type.fixed_size():
> _c(' /* %s %s */', field.type.c_type, field.c_field_name)
> # default: simple cast to char *
> if not field.type.c_need_serialize and not field.type.c_need_sizeof:
> _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
> if field.type.is_list:
> if field.type.member.fixed_size():
> - _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
> - _c_accessor_get_expr(field.type.expr, None),
> - field.type.member.c_wiretype)
> + if field.type.expr.op == 'calculate_len':
> + lenfield = field.type.expr.lenfield_name
> + else:
> + lenfield = _c_accessor_get_expr(field.type.expr, None)
> +
> + _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count, lenfield,
> + field.type.member.c_wiretype)
> else:
> list_length = _c_accessor_get_expr(field.type.expr, None)
> + length = ''
>
> _c(" xcb_parts[%d].iov_len = 0;" % count)
> _c(" xcb_tmp = (char *)%s;", field.c_field_name)
> _c(" for(i=0; i<%s; i++) {" % list_length)
> _c(" xcb_tmp_len = %s(xcb_tmp);" %
> (field.type.c_sizeof_name))
> _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
> @@ -3109,17 +3146,20 @@ def c_request(self, name):
> else:
> # Request prototypes
> _c_request_helper(self, name, void=True, regular=False)
> _c_request_helper(self, name, void=True, regular=True)
> if self.c_need_aux:
> _c_request_helper(self, name, void=True, regular=False, aux=True)
> _c_request_helper(self, name, void=True, regular=True, aux=True)
> - if config_server_side:
> - _c_accessors(self, name, name)
> -
> + for field in self.fields:
> + if not field.type.is_pad and field.wire:
> + if _c_field_needs_list_accessor(field):
> + _c_accessors_list(self, field)
> + elif _c_field_needs_field_accessor(field):
> + _c_accessors_field(self, field)
> # We generate the manpage afterwards because _c_type_setup has been called.
> # TODO: what about aux helpers?
> _man_request(self, name, void=not self.reply, aux=False)
>
> def c_event(self, name):
> '''
> Exported function that handles event declarations.
More information about the Xcb
mailing list