# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) any # later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License along # with this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Copyright (C) 2012 Lanedo GmbH # Copyright (C) 2012-2022 Aleksander Morgado # Copyright (c) 2022 Qualcomm Innovation Center, Inc. # import string import utils from Variable import Variable import VariableFactory """ Variable type for Arrays ('array' format) """ class VariableArray(Variable): def __init__(self, service, dictionary, array_element_type, container_type): # Call the parent constructor Variable.__init__(self, service, dictionary) self.fixed_size = 0 self.name = dictionary['name'] # The array and its contents need to get disposed self.needs_dispose = True # We need to know whether the variable comes in an Input container or in # an Output container, as we should not dump the element clear() helper method # if the variable is from an Input container. self.container_type = container_type # Disallow arrays of arrays, always use an intermediate struct if dictionary['array-element']['format'] == 'array': raise ValueError('Arrays of arrays not allowed in %s array: use an intermediate struct instead' % self.name) # Load variable type of this array if 'name' in dictionary['array-element']: self.array_element = VariableFactory.create_variable(self.service, dictionary['array-element'], array_element_type + ' ' + dictionary['array-element']['name'], self.container_type) else: self.array_element = VariableFactory.create_variable(self.service, dictionary['array-element'], '', self.container_type) if 'size-prefix-format' in dictionary and 'fixed-size' in dictionary: raise ValueError('Cannot give \'size-prefix-format\' and \'fixed-size\' in %s array at the same time' % self.name) elif 'size-prefix-format' in dictionary: # Load variable type for the array size prefix # We do NOT allow 64-bit types as array sizes (GArray won't support them) if dictionary['size-prefix-format'] not in [ 'guint8', 'guint16', 'guint32' ]: raise ValueError('Invalid size prefix format (%s) in %s array: not guint8 or guint16 or guint32' % (dictionary['size-prefix-format'], self.name)) default_array_size = { 'format' : dictionary['size-prefix-format'] } self.array_size_element = VariableFactory.create_variable(self.service, default_array_size, '', self.container_type) # Load variable type for the sequence prefix, if any if 'sequence-prefix-format' in dictionary: sequence = { 'format' : dictionary['sequence-prefix-format'] } self.array_sequence_element = VariableFactory.create_variable(self.service, sequence, '', self.container_type) else: self.array_sequence_element = '' elif 'fixed-size' in dictionary: # fixed-size arrays have no size element, obviously self.fixed_size = dictionary['fixed-size'] if int(self.fixed_size) == 0 or int(self.fixed_size) > 512: raise ValueError('Fixed array size %s out of bounds (not between 0 and 512)' % self.fixed_size) if 'sequence-prefix-format' in dictionary: raise ValueError('\'sequence-prefix-format\' is not supported along with \'fixed-size\' in %s array' % self.name) else: self.array_sequence_element = '' else: raise ValueError('Missing \'size-prefix-format\' or \'fixed-size\' in %s array' % self.name) # Arrays need compat GIR support if the array element needs compat GIR support self.needs_compat_gir = self.array_element.needs_compat_gir # Arrays contain personal info if the array element contains personal info or they themselves are personal info self.contains_personal_info = self.contains_personal_info or self.array_element.contains_personal_info def emit_types(self, hfile, cfile, since, static): self.array_element.emit_types(hfile, cfile, since, static) def emit_types_gir(self, hfile, cfile, since): if self.array_element.needs_compat_gir: self.array_element.emit_types_gir(hfile, cfile, since) def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'variable_name' : variable_name, 'private_format' : self.private_format, 'array_element_public_format' : self.array_element.public_format, 'array_element_clear_method' : self.array_element.clear_method, 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n' '\n') f.write(string.Template(template).substitute(translations)) else: translations['array_size_element_format'] = self.array_size_element.public_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n') if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp} ${array_sequence_element_format} ${common_var_prefix}_sequence;\n') template += ( '\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_n_items') if self.array_sequence_element != '': template = ( '\n' '${lp} /* Read sequence in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_sequence') template = ( '\n' '${lp} ${variable_name}_sequence = ${common_var_prefix}_sequence;\n') f.write(string.Template(template).substitute(translations)) template = ( '\n' '${lp} ${variable_name} = g_array_sized_new (\n' '${lp} FALSE,\n' '${lp} FALSE,\n' '${lp} sizeof (${array_element_public_format}),\n' '${lp} (guint)${common_var_prefix}_n_items);\n' '\n') if self.array_element.needs_dispose: template += ( '${lp} g_array_set_clear_func (${variable_name}, (GDestroyNotify)${array_element_clear_method});\n' '\n') template += ( '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' '${lp} ${array_element_public_format} ${common_var_prefix}_aux;\n' '\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_aux') template = ( '${lp} g_array_insert_val (${variable_name}, ${common_var_prefix}_i, ${common_var_prefix}_aux);\n' '${lp} }\n' '${lp}}\n') f.write(string.Template(template).substitute(translations)) def emit_buffer_write(self, f, line_prefix, tlv_name, variable_name): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'variable_name' : variable_name, 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size == 0: translations['array_size_element_format'] = self.array_size_element.private_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' '\n' '${lp} /* Write the number of items in the array first */\n' '${lp} ${common_var_prefix}_n_items = (${array_size_element_format}) ${variable_name}->len;\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_write(f, line_prefix + ' ', tlv_name, common_var_prefix + '_n_items') if self.array_sequence_element != '': self.array_sequence_element.emit_buffer_write(f, line_prefix + ' ', tlv_name, variable_name + '_sequence') template = ( '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${variable_name}->len; ${common_var_prefix}_i++) {\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_buffer_write(f, line_prefix + ' ', tlv_name, 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)') template = ( '${lp} }\n' '${lp}}\n') f.write(string.Template(template).substitute(translations)) def emit_get_printable(self, f, line_prefix, is_personal): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n') f.write(string.Template(template).substitute(translations)) if self.fixed_size: translations['fixed_size'] = self.fixed_size template = ( '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n' '\n') f.write(string.Template(template).substitute(translations)) else: translations['array_size_element_format'] = self.array_size_element.public_format template = ( '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n') if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp} ${array_sequence_element_format} ${common_var_prefix}_sequence;\n') template += ( '\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) self.array_size_element.emit_buffer_read(f, line_prefix + ' ', 'out', '&error', common_var_prefix + '_n_items') if self.array_sequence_element != '': template = ( '\n' '${lp} /* Read sequence */\n') f.write(string.Template(template).substitute(translations)) self.array_sequence_element.emit_buffer_read(f, line_prefix + ' ', 'out', '&error', common_var_prefix + '_sequence') template = ( '\n' '${lp} g_string_append_printf (printable, "[[Seq:%u]] ", ${common_var_prefix}_sequence);\n') f.write(string.Template(template).substitute(translations)) template = ( '\n' '${lp} g_string_append (printable, "{");\n' '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' '${lp} g_string_append_printf (printable, " [%u] = \'", ${common_var_prefix}_i);\n') f.write(string.Template(template).substitute(translations)) self.array_element.emit_get_printable(f, line_prefix + ' ', self.personal_info or is_personal); template = ( '${lp} g_string_append (printable, " \'");\n' '${lp} }\n' '\n' '${lp} g_string_append (printable, "}");\n' '${lp}}') f.write(string.Template(template).substitute(translations)) """ We need to include SEQUENCE + GARRAY """ def build_variable_declaration(self, line_prefix, variable_name): translations = { 'lp' : line_prefix, 'name' : variable_name } template = '' if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp}${array_sequence_element_format} ${name}_sequence;\n') template += ( '${lp}GArray *${name};\n') return string.Template(template).substitute(translations) """ We need to include GPTRARRAY """ def build_variable_declaration_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return '' translations = { 'lp' : line_prefix, 'name' : variable_name } template = ( '${lp}GPtrArray *${name}_ptr;\n') return string.Template(template).substitute(translations) """ We need to include SEQUENCE + GARRAY """ def build_struct_field_declaration(self, line_prefix, variable_name): return self.build_variable_declaration(line_prefix, variable_name) """ We need to include SEQUENCE + GPTRARRAY """ def build_struct_field_declaration_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return self.build_struct_field_declaration(line_prefix, variable_name) translations = { 'lp' : line_prefix, 'name' : variable_name } template = '' if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp}${array_sequence_element_format} ${name}_sequence;\n') template += ( '${lp}GPtrArray *${name};\n') return string.Template(template).substitute(translations) def build_getter_declaration(self, line_prefix, variable_name): if not self.visible: return '' translations = { 'lp' : line_prefix, 'name' : variable_name } template = '' if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp}${array_sequence_element_format} *${name}_sequence,\n') template += ( '${lp}GArray **${name},\n') return string.Template(template).substitute(translations) def build_getter_declaration_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return self.build_getter_declaration(line_prefix, variable_name) if not self.visible: return '' translations = { 'lp' : line_prefix, 'name' : variable_name } template = '' if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp}${array_sequence_element_format} *${name}_sequence,\n') template += ( '${lp}GPtrArray **${name}_ptr,\n') return string.Template(template).substitute(translations) def build_getter_documentation(self, line_prefix, variable_name): if not self.visible: return '' translations = { 'lp' : line_prefix, 'array_element_public_format' : self.array_element.public_format, 'array_element_element_type' : self.array_element.element_type, 'name' : variable_name } template = '' if self.array_sequence_element != '': template += ( '${lp}@${name}_sequence: (out)(optional): a placeholder for the output sequence number, or %NULL if not required.\n') template += ( '${lp}@${name}: (out)(optional)(element-type ${array_element_element_type})(transfer none): a placeholder for the output #GArray of #${array_element_public_format} elements, or %NULL if not required. Do not free it, it is owned by @self.\n') return string.Template(template).substitute(translations) def build_getter_documentation_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return self.build_getter_documentation(line_prefix, variable_name) if not self.visible: return '' translations = { 'lp' : line_prefix, 'array_element_public_format' : self.array_element.public_format, 'array_element_element_type_gir' : self.array_element.element_type_gir, 'name' : variable_name } template = '' if self.array_sequence_element != '': template += ( '${lp}@${name}_sequence: (out)(optional): a placeholder for the output sequence number, or %NULL if not required.\n') template += ( '${lp}@${name}_ptr: (out)(optional)(element-type ${array_element_element_type_gir})(transfer none): a placeholder for the output array of #${array_element_public_format} elements, or %NULL if not required. Do not free or modify it, it is owned by @self.\n') return string.Template(template).substitute(translations) def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to): if not self.visible: return '' translations = { 'lp' : line_prefix, 'from' : variable_name_from, 'to' : variable_name_to } template = '' if self.array_sequence_element != '': template += ( '${lp}if (${to}_sequence)\n' '${lp} *${to}_sequence = ${from}_sequence;\n') template += ( '${lp}if (${to})\n' '${lp} *${to} = ${from};\n') return string.Template(template).substitute(translations) def build_getter_implementation_gir(self, line_prefix, variable_name_from, variable_name_to): if not self.array_element.needs_compat_gir: return self.build_getter_implementation(line_prefix, variable_name_from, variable_name_to) if not self.visible: return '' common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'from' : variable_name_from, 'to' : variable_name_to } template = '' if self.array_sequence_element != '': template += ( '${lp}if (${to}_sequence)\n' '${lp} *${to}_sequence = ${from}_sequence;\n') template += ( '${lp}if (${to}_ptr) {\n' '${lp} if (!${from}_ptr) {\n') template += self.build_copy_to_gir(line_prefix + ' ', variable_name_from, variable_name_from + '_ptr') template += ( '${lp} }\n' '${lp} *${to}_ptr = ${from}_ptr;\n' '${lp}}') return string.Template(template).substitute(translations) def build_setter_declaration(self, line_prefix, variable_name): if not self.visible: return '' translations = { 'lp' : line_prefix, 'name' : variable_name } template = '' if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp}${array_sequence_element_format} ${name}_sequence,\n') template += ( '${lp}GArray *${name},\n') return string.Template(template).substitute(translations) def build_setter_declaration_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return self.build_setter_declaration(line_prefix, variable_name) if not self.visible: return '' translations = { 'lp' : line_prefix, 'name' : variable_name } template = '' if self.array_sequence_element != '': translations['array_sequence_element_format'] = self.array_sequence_element.public_format template += ( '${lp}${array_sequence_element_format} ${name}_sequence,\n') template += ( '${lp}GPtrArray *${name}_ptr,\n') return string.Template(template).substitute(translations) def build_setter_documentation(self, line_prefix, variable_name): if not self.visible: return "" translations = { 'lp' : line_prefix, 'array_element_public_format' : self.array_element.public_format, 'array_element_element_type' : self.array_element.element_type, 'name' : variable_name } template = '' if self.array_sequence_element != '': template += ( '${lp}@${name}_sequence: the sequence number.\n') template += ( '${lp}@${name}: (in)(element-type ${array_element_element_type})(transfer none): a #GArray of #${array_element_public_format} elements. A new reference to @${name} will be taken, so the caller must make sure the array was created with the correct #GDestroyNotify as clear function for each element in the array.\n') return string.Template(template).substitute(translations) def build_setter_documentation_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return self.build_setter_documentation(line_prefix, variable_name) if not self.visible: return "" translations = { 'lp' : line_prefix, 'array_element_public_format' : self.array_element.public_format, 'array_element_element_type_gir' : self.array_element.element_type_gir, 'name' : variable_name } template = '' if self.array_sequence_element != '': template += ( '${lp}@${name}_sequence: the sequence number.\n') template += ( '${lp}@${name}_ptr: (in)(element-type ${array_element_element_type_gir})(transfer none): array of #${array_element_public_format} elements. The contents of the given array will be copied, the #GPtrArray will not increase its reference count.\n') return string.Template(template).substitute(translations) def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to): if not self.visible: return "" translations = { 'lp' : line_prefix, 'from' : variable_name_from, 'to' : variable_name_to } template = '' if self.array_sequence_element != '': template += ( '${lp}${to}_sequence = ${from}_sequence;\n') template += self.build_dispose(line_prefix, variable_name_to) template += self.build_dispose_gir(line_prefix, variable_name_to) template +=( '${lp}${to} = g_array_ref (${from});\n') return string.Template(template).substitute(translations) def build_setter_implementation_gir(self, line_prefix, variable_name_from, variable_name_to): if not self.array_element.needs_compat_gir: return self.build_setter_implementation(line_prefix, variable_name_from, variable_name_to) if not self.visible: return "" common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'from' : variable_name_from, 'to' : variable_name_to } template = '' if self.array_sequence_element != '': template += ( '${lp}${to}_sequence = ${from}_sequence;\n') template += self.build_dispose(line_prefix, variable_name_to) template += self.build_dispose_gir(line_prefix, variable_name_to + '_ptr') template += self.build_copy_from_gir(line_prefix, variable_name_from + '_ptr', variable_name_to) return string.Template(template).substitute(translations) def build_struct_field_documentation(self, line_prefix, variable_name): translations = { 'lp' : line_prefix, 'array_element_public_format' : self.array_element.public_format, 'name' : variable_name } template = '' if self.array_sequence_element != '': template += ( '${lp}@${name}_sequence: the sequence number.\n') template += ( '${lp}@${name}: a #GArray of #${array_element_public_format} elements.\n') return string.Template(template).substitute(translations) def build_struct_field_documentation_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: return self.build_struct_field_documentation(line_prefix, variable_name) translations = { 'lp' : line_prefix, 'array_element_public_format' : self.array_element.public_format, 'array_element_element_type' : self.array_element.element_type, 'name' : variable_name } template = '' if self.array_sequence_element != '': template += ( '${lp}@${name}_sequence: the sequence number.\n') template += ( '${lp}@${name}: (element-type ${array_element_element_type}): an array of #${array_element_public_format} elements.\n') return string.Template(template).substitute(translations) def build_dispose(self, line_prefix, variable_name): translations = { 'lp' : line_prefix, 'variable_name' : variable_name } template = ( '${lp}g_clear_pointer (&${variable_name}, (GDestroyNotify)g_array_unref);\n') return string.Template(template).substitute(translations) def build_dispose_gir(self, line_prefix, variable_name): if not self.array_element.needs_compat_gir: self.build_dispose(line_prefix, variable_name) translations = { 'lp' : line_prefix, 'variable_name' : variable_name } template = ( '${lp}g_clear_pointer (&${variable_name}, (GDestroyNotify)g_ptr_array_unref);\n') return string.Template(template).substitute(translations) def build_copy_to_gir(self, line_prefix, variable_name_from, variable_name_to): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'to' : variable_name_to, 'from' : variable_name_from } if self.array_element.needs_compat_gir: translations['common_var_prefix'] = common_var_prefix translations['array_element_public_format'] = self.array_element.public_format translations['array_element_public_format_gir'] = self.array_element.public_format_gir translations['array_element_element_type_gir'] = self.array_element.element_type_gir translations['array_element_free_method_gir'] = self.array_element.free_method_gir translations['array_element_new_method_gir'] = self.array_element.new_method_gir template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n' '\n' '${lp} ${to} = g_ptr_array_new_full (${from}->len, (GDestroyNotify)${array_element_free_method_gir});\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${from}->len; ${common_var_prefix}_i++) {\n' '${lp} ${array_element_public_format} *${common_var_prefix}_aux_from;\n' '${lp} ${array_element_public_format_gir} *${common_var_prefix}_aux_to;\n' '\n' '${lp} ${common_var_prefix}_aux_from = &g_array_index (${from}, ${array_element_public_format}, ${common_var_prefix}_i);\n' '\n' '${lp} ${common_var_prefix}_aux_to = ${array_element_new_method_gir} ();\n') template += self.array_element.build_copy_to_gir(line_prefix + ' ', '(*${common_var_prefix}_aux_from)', '${common_var_prefix}_aux_to') template += ( '\n' '${lp} g_ptr_array_add (${to}, ${common_var_prefix}_aux_to);\n' '${lp} }\n' '${lp}}\n') else: template = ( '${lp}${to} = g_array_ref (${from});\n') return string.Template(template).substitute(translations) def build_copy_from_gir(self, line_prefix, variable_name_from, variable_name_to): translations = { 'lp' : line_prefix, 'to' : variable_name_to, 'from' : variable_name_from } if self.array_element.needs_compat_gir: common_var_prefix = utils.build_underscore_name(self.name) translations['common_var_prefix'] = common_var_prefix translations['array_element_public_format'] = self.array_element.public_format translations['array_element_public_format_gir'] = self.array_element.public_format_gir template = ( '${lp}{\n' '${lp} guint ${common_var_prefix}_i;\n' '\n' '${lp} ${to} = g_array_sized_new (FALSE, FALSE, sizeof (${array_element_public_format}), ${from}->len);\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${from}->len; ${common_var_prefix}_i++) {\n' '${lp} ${array_element_public_format} ${common_var_prefix}_aux_to;\n' '${lp} ${array_element_public_format_gir} *${common_var_prefix}_aux_from;\n' '\n' '${lp} ${common_var_prefix}_aux_from = g_ptr_array_index (${from}, ${common_var_prefix}_i);\n' '\n') template += self.array_element.build_copy_from_gir(line_prefix + ' ', '${common_var_prefix}_aux_from', '${common_var_prefix}_aux_to') template += ( '\n' '${lp} g_array_append_val (${to}, ${common_var_prefix}_aux_to);\n' '${lp} }\n' '${lp}}\n') else: template = ( '${lp}${to} = g_array_ref (${from});\n') return string.Template(template).substitute(translations) def build_copy_gir(self, line_prefix, variable_name_from, variable_name_to): common_var_prefix = utils.build_underscore_name(self.name) translations = { 'lp' : line_prefix, 'to' : variable_name_to, 'from' : variable_name_from } # our GPtrArrays and GArrays are immutable, we can just ref the array as a copy if self.array_element.needs_compat_gir: template = ( '${lp}${to} = g_ptr_array_ref (${from});\n') else: template = ( '${lp}${to} = g_array_ref (${from});\n') return string.Template(template).substitute(translations) def add_sections(self, sections): self.array_element.add_sections(sections)