first_field_after_varsized = None
for field in self.fields:
- _c_type_setup(field.type, field.field_type, ())
- if field.type.is_list:
- _c_type_setup(field.type.member, field.field_type, ())
- if (field.type.nmemb is None):
- self.c_need_sizeof = True
-
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)
if field.type.fixed_size():
field.prev_varsized_field = None
+ # recurse into this field this has to be done here, i.e.,
+ # after the field has been set up. Otherwise the function
+ # _c_helper_absolute_name will produce garbage or crash
+ _c_type_setup(field.type, field.field_type, ())
+ if field.type.is_list:
+ _c_type_setup(field.type.member, field.field_type, ())
+ if (field.type.nmemb is None):
+ self.c_need_sizeof = True
+
if self.c_need_serialize:
# when _unserialize() is wanted, create _sizeof() as well for consistency reasons
self.c_need_sizeof = True
_c_serialize('sizeof', self)
# _c_type_setup()
+# Functions for querying field properties
+def _c_field_needs_list_accessor(field):
+ return field.type.is_list and not field.type.fixed_size()
+
+def _c_field_needs_field_accessor(field):
+ if field.type.is_list:
+ return False
+ else:
+ return (field.prev_varsized_field is not None or
+ not field.type.fixed_size())
+
+def _c_field_needs_accessor(field):
+ return (_c_field_needs_list_accessor(field) or
+ _c_field_needs_field_accessor(field))
+
+def _c_field_is_member_of_case_or_bitcase(field):
+ return field.parent and field.parent.is_case_or_bitcase
+
def _c_helper_absolute_name(prefix, field=None):
"""
turn prefix, which is a list of tuples (name, separator, Type obj) into a string
if field is not None, append the field name as well
"""
prefix_str = ''
+ last_sep =''
for name, sep, obj in prefix:
- prefix_str += name
+ prefix_str += last_sep + name
if '' == sep:
sep = '->'
if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase
(obj.is_switch and len(obj.parents)>1)):
sep = '.'
- prefix_str += sep
- if field is not None:
- prefix_str += _cpp(field.field_name)
+ last_sep = sep
+
+ if field is None:
+ # add separator for access to a yet unknown field
+ prefix_str += last_sep
+ else:
+ if _c_field_needs_accessor(field):
+ if _c_field_is_member_of_case_or_bitcase(field):
+ # case members are available in the deserialized struct,
+ # so there is no need to use the accessor function
+ # (also, their accessor function needs a different arglist
+ # so this would require special treatment here)
+ # Therefore: Access as struct member
+ prefix_str += last_sep + _cpp(field.field_name)
+ else:
+ # Access with the accessor function
+ prefix_str = field.c_accessor_name + "(" + prefix_str + ")"
+ else:
+ # Access as struct member
+ prefix_str += last_sep + _cpp(field.field_name)
+
return prefix_str
# _c_absolute_name
return (param_fields, wire_fields, params)
# get_serialize_params()
-def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
+def _c_serialize_helper_insert_padding(context, code_lines, space, postpone, is_case_or_bitcase):
code_lines.append('%s /* insert padding */' % space)
- code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
+ if is_case_or_bitcase:
+ code_lines.append(
+ '%s xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);'
+ % space)
+ else:
+ code_lines.append(
+ '%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
# code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
code_lines.append('%s }' % space)
code_lines.append('%s xcb_block_len = 0;' % space)
+ if is_case_or_bitcase:
+ code_lines.append('%s xcb_padding_offset = 0;' % space)
# keep tracking of xcb_parts entries for serialize
return 1
# Variable length pad is <pad align= />
code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
count += _c_serialize_helper_insert_padding(context, code_lines, space,
- self.c_var_followed_by_fixed_fields)
+ self.c_var_followed_by_fixed_fields,
+ is_case_or_bitcase)
continue
else:
# switch/bitcase: always calculate padding before and after variable sized fields
if need_padding or is_case_or_bitcase:
count += _c_serialize_helper_insert_padding(context, code_lines, space,
- self.c_var_followed_by_fixed_fields)
+ self.c_var_followed_by_fixed_fields,
+ is_case_or_bitcase)
value, length = _c_serialize_helper_fields_variable_size(context, self, field,
code_lines, temp_vars,
code_lines, temp_vars,
space, prefix, False)
# "final padding"
- count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+ count += _c_serialize_helper_insert_padding(context, code_lines, space, False, self.is_switch)
return count
# _c_serialize_helper()
_c(' char *xcb_out = *_buffer;')
_c(' unsigned int xcb_buffer_len = 0;')
_c(' unsigned int xcb_align_to = 0;')
+ if self.is_switch:
+ _c(' unsigned int xcb_padding_offset = ((size_t)xcb_out) & 7;')
prefix = [('_aux', '->', self)]
aux_ptr = 'xcb_out'
_c(' unsigned int xcb_block_len = 0;')
_c(' unsigned int xcb_pad = 0;')
_c(' unsigned int xcb_align_to = 0;')
+ if self.is_switch:
+ _c(' unsigned int xcb_padding_offset = ((size_t)_buffer) & 7;')
elif 'sizeof' == context:
param_names = [p[2] for p in params]
else:
_c(' char *xcb_tmp = (char *)_buffer;')
prefix = [('_aux', '->', self)]
+ if self.is_switch:
+ _c(' unsigned int xcb_padding_offset = 0;')
count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
# update variable size fields (only important for context=='serialize'
if True:
for field in self.fields:
if not field.type.is_pad:
- if field.type.is_list and not field.type.fixed_size():
+ if _c_field_needs_list_accessor(field):
_c_accessors_list(self, field)
- elif field.prev_varsized_field is not None or not field.type.fixed_size():
+ elif _c_field_needs_field_accessor(field):
_c_accessors_field(self, field)
def c_simple(self, name):
for b in self.bitcases:
space = ''
if b.type.has_name:
- _h(' struct _%s {', b.c_field_name)
+ _h(' struct {')
space = ' '
for field in b.type.fields:
_c_complex_field(self, field, space)