[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