qmi-codegen: let variables decide how the getter/setter methods pass them

And change the structs to be passed by reference.
This commit is contained in:
Aleksander Morgado 2012-07-03 13:58:52 +02:00
parent b2cc173502
commit 4130a72091
9 changed files with 456 additions and 83 deletions

View File

@ -152,15 +152,15 @@ class Container:
if self.fields is not None:
for field in self.fields:
if field.variable is not None:
translations['field_type'] = field.variable.private_format if field.variable.private_format.endswith('*') else field.variable.private_format + ' '
variable_declaration = field.variable.build_variable_declaration(' ', field.variable_name)
translations['field_variable_name'] = field.variable_name
translations['field_name'] = field.name
template = (
'\n'
' /* ${field_name} */\n'
' gboolean ${field_variable_name}_set;\n'
' ${field_type}${field_variable_name};\n')
' gboolean ${field_variable_name}_set;\n')
cfile.write(string.Template(template).substitute(translations))
cfile.write(variable_declaration)
cfile.write(
'};\n')
@ -218,7 +218,7 @@ class Container:
if self.fields is not None:
for field in self.fields:
if field.variable is not None and field.variable.needs_dispose is True:
field.variable.emit_dispose(cfile, ' ', 'self->' + field.variable_name)
template += field.variable.build_dispose(' ', 'self->' + field.variable_name)
template = (
' g_slice_free (${camelcase}, self);\n'

View File

@ -91,22 +91,25 @@ class Field:
container
"""
def emit_getter(self, hfile, cfile):
translations = { 'name' : self.name,
'variable_name' : self.variable_name,
'public_field_type' : self.variable.public_format,
'public_field_out' : self.variable.public_format if self.variable.public_format.endswith('*') else self.variable.public_format + ' ',
'dispose_warn' : ' Do not free the returned @value, it is owned by @self.' if self.variable.needs_dispose is True else '',
'underscore' : utils.build_underscore_name(self.name),
'prefix_camelcase' : utils.build_camelcase_name(self.prefix),
'prefix_underscore' : utils.build_underscore_name(self.prefix),
'const' : 'const ' if self.variable.pass_constant else '' }
input_variable_name = utils.build_underscore_name(self.name)
variable_getter_dec = self.variable.build_getter_declaration(' ', input_variable_name)
variable_getter_doc = self.variable.build_getter_documentation(' * ', input_variable_name)
variable_getter_imp = self.variable.build_getter_implementation(' ', 'self->' + self.variable_name, input_variable_name, True)
translations = { 'name' : self.name,
'variable_name' : self.variable_name,
'variable_getter_dec' : variable_getter_dec,
'variable_getter_doc' : variable_getter_doc,
'variable_getter_imp' : variable_getter_imp,
'underscore' : utils.build_underscore_name(self.name),
'prefix_camelcase' : utils.build_camelcase_name(self.prefix),
'prefix_underscore' : utils.build_underscore_name(self.prefix) }
# Emit the getter header
template = (
'\n'
'gboolean ${prefix_underscore}_get_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
' ${const}${public_field_out}*value,\n'
'${variable_getter_dec}'
' GError **error);\n')
hfile.write(string.Template(template).substitute(translations))
@ -116,17 +119,17 @@ class Field:
'/**\n'
' * ${prefix_underscore}_get_${underscore}:\n'
' * @self: a ${prefix_camelcase}.\n'
' * @value: a placeholder for the output value, or #NULL.\n'
'${variable_getter_doc}'
' * @error: a #GError.\n'
' *\n'
' * Get the \'${name}\' field from @self.\n'
' *\n'
' * Returns: #TRUE if the field is found and @value is set, #FALSE otherwise.${dispose_warn}\n'
' * Returns: #TRUE if the field is found, #FALSE otherwise.\n'
' */\n'
'gboolean\n'
'${prefix_underscore}_get_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
' ${const}${public_field_out}*value,\n'
'${variable_getter_dec}'
' GError **error)\n'
'{\n'
' g_return_val_if_fail (self != NULL, FALSE);\n'
@ -139,9 +142,7 @@ class Field:
' return FALSE;\n'
' }\n'
'\n'
' /* Just for now, transfer-none always */\n'
' if (value)\n'
' *value = (${public_field_out})(self->${variable_name});\n'
'${variable_getter_imp}'
'\n'
' return TRUE;\n'
'}\n')
@ -153,20 +154,25 @@ class Field:
container
"""
def emit_setter(self, hfile, cfile):
translations = { 'name' : self.name,
'variable_name' : self.variable_name,
'field_type' : self.variable.public_format,
'underscore' : utils.build_underscore_name(self.name),
'prefix_camelcase' : utils.build_camelcase_name(self.prefix),
'prefix_underscore' : utils.build_underscore_name(self.prefix),
'const' : 'const ' if self.variable.pass_constant else '' }
input_variable_name = utils.build_underscore_name(self.name)
variable_setter_dec = self.variable.build_setter_declaration(' ', input_variable_name)
variable_setter_doc = self.variable.build_setter_documentation(' * ', input_variable_name)
variable_setter_imp = self.variable.build_setter_implementation(' ', input_variable_name, 'self->' + self.variable_name)
translations = { 'name' : self.name,
'variable_name' : self.variable_name,
'variable_setter_dec' : variable_setter_dec,
'variable_setter_doc' : variable_setter_doc,
'variable_setter_imp' : variable_setter_imp,
'underscore' : utils.build_underscore_name(self.name),
'prefix_camelcase' : utils.build_camelcase_name(self.prefix),
'prefix_underscore' : utils.build_underscore_name(self.prefix) }
# Emit the setter header
template = (
'\n'
'gboolean ${prefix_underscore}_set_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
' ${const}${field_type} value,\n'
'${variable_setter_dec}'
' GError **error);\n')
hfile.write(string.Template(template).substitute(translations))
@ -176,7 +182,7 @@ class Field:
'/**\n'
' * ${prefix_underscore}_set_${underscore}:\n'
' * @self: a ${prefix_camelcase}.\n'
' * @value: the value to set.\n'
'${variable_setter_doc}'
' * @error: a #GError.\n'
' *\n'
' * Set the \'${name}\' field in the message.\n'
@ -186,21 +192,17 @@ class Field:
'gboolean\n'
'${prefix_underscore}_set_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
' ${const}${field_type} value,\n'
'${variable_setter_dec}'
' GError **error)\n'
'{\n'
' g_return_val_if_fail (self != NULL, FALSE);\n'
'\n'
' self->${variable_name}_set = TRUE;\n')
cfile.write(string.Template(template).substitute(translations))
self.variable.emit_dispose(cfile, ' ', 'self->' + self.variable_name)
self.variable.emit_copy(cfile, ' ', 'value', 'self->' + self.variable_name)
cfile.write(
' self->${variable_name}_set = TRUE;\n'
'${variable_setter_imp}'
'\n'
' return TRUE;\n'
'}\n')
cfile.write(string.Template(template).substitute(translations))
"""

View File

@ -44,12 +44,6 @@ class Variable:
"""
self.needs_dispose = False
"""
Variables may suggest to be passed flagged as 'const' in the get/set
methods generated.
"""
self.pass_constant = False
"""
Emits the code to declare specific new types required by the variable.
@ -81,13 +75,49 @@ class Variable:
pass
"""
Emits the code to copy a variable into another one of the same type.
Builds the code to include the declaration of a variable of this kind.
"""
def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
pass
def build_variable_declaration(self, line_prefix, variable_name):
return ''
"""
Builds the code to include in the getter method declaration for this kind of variable.
"""
def build_getter_declaration(self, line_prefix, variable_name):
return ''
"""
Builds the documentation of the getter code
"""
def build_getter_documentation(self, line_prefix, variable_name):
return ''
"""
Builds the code to implement getting this kind of variable.
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
return ''
"""
Builds the code to include in the setter method for this kind of variable.
"""
def build_setter_declaration(self, line_prefix, variable_name):
return ''
"""
Builds the documentation of the setter code
"""
def build_setter_documentation(self, line_prefix, variable_name):
return ''
"""
Builds the code to implement setting this kind of variable.
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
return ''
"""
Emits the code to dispose the variable.
"""
def emit_dispose(self, f, line_prefix, variable_name):
pass
def build_dispose(self, line_prefix, variable_name):
return ''

View File

@ -144,42 +144,128 @@ class VariableArray(Variable):
"""
GArrays are ref-counted, so we can just provide a new ref to the array.
Variable declaration
"""
def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
def build_variable_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}GArray *${name};\n')
return string.Template(template).substitute(translations)
"""
Getter for the array type
"""
def build_getter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}GArray **${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the getter
"""
def build_getter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'public_array_element_format' : self.array_element.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output #GArray of #${public_array_element_format} elements, or #NULL if not required. Do not free it, it is owned by @self.\n')
return string.Template(template).substitute(translations)
"""
Builds the array getter implementation
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
if to_is_reference:
template = (
'${lp}if (${to})\n'
'${lp} *${to} = ${from};\n')
return string.Template(template).substitute(translations)
else:
template = (
'${lp}${to} = ${from};\n')
return string.Template(template).substitute(translations)
"""
Setter for the array type
"""
def build_setter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}GArray *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the setter
"""
def build_setter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'public_array_element_format' : self.array_element.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a #GArray of #${public_array_element_format} elements. A new reference to @{name} will be taken.\n')
return string.Template(template).substitute(translations)
"""
Builds the array setter implementation
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
template = (
'${lp}if (${to})\n'
'${lp} g_array_unref (${to});\n'
'${lp}${to} = g_array_ref (${from});\n')
f.write(string.Template(template).substitute(translations))
return string.Template(template).substitute(translations)
"""
FIXME: we should only dispose the members of the array if the refcount of
the array reached zero. Use g_array_set_clear_func() for that.
"""
def emit_dispose(self, f, line_prefix, variable_name):
def build_dispose(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'variable_name' : variable_name }
built = ''
if self.array_element.needs_dispose == True:
template = (
'${lp}{\n'
'${lp} guint i;\n'
'\n'
'${lp} for (i = 0; i < ${variable_name}->len; i++) {\n')
f.write(string.Template(template).substitute(translations))
built += string.Template(template).substitute(translations)
self.array_element.emit_dispose(f, line_prefix, 'g_array_index (' + variable_name + ',' + self.array_element.public_format + ', i)')
built += self.array_element.build_dispose(line_prefix, 'g_array_index (' + variable_name + ',' + self.array_element.public_format + ', i)')
template = (
'${lp} }\n'
'${lp}}')
f.write(string.Template(template).substitute(translations))
built += string.Template(template).substitute(translations)
template = (
'${lp}g_array_unref (${variable_name});\n')
f.write(string.Template(template).substitute(translations))
built += string.Template(template).substitute(translations)
return built

View File

@ -141,13 +141,102 @@ class VariableInteger(Variable):
"""
Copy an integer to another one
Variable declaration
"""
def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
def build_variable_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'private_format' : self.private_format,
'name' : variable_name }
template = (
'${lp}${to} = ${from};\n')
f.write(string.Template(template).substitute(translations))
'${lp}${private_format} ${name};\n')
return string.Template(template).substitute(translations)
"""
Getter for the integer type
"""
def build_getter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'public_format' : self.public_format,
'name' : variable_name }
template = (
'${lp}${public_format} *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the getter
"""
def build_getter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'public_format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output #${public_format}, or #NULL if not required.\n')
return string.Template(template).substitute(translations)
"""
Builds the Integer getter implementation
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
needs_cast = True if self.public_format != self.private_format else False
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to,
'cast_ini' : '(' + self.public_format + ')(' if needs_cast else '',
'cast_end' : ')' if needs_cast else '' }
if to_is_reference:
template = (
'${lp}if (${to})\n'
'${lp} *${to} = ${cast_ini}${from}${cast_end};\n')
return string.Template(template).substitute(translations)
else:
template = (
'${lp}${to} = ${cast_ini}${from}${cast_end};\n')
return string.Template(template).substitute(translations)
"""
Setter for the integer type
"""
def build_setter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'public_format' : self.public_format,
'name' : variable_name }
template = (
'${lp}${public_format} ${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the setter
"""
def build_setter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'public_format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a #${public_format}.\n')
return string.Template(template).substitute(translations)
"""
Implementation of the setter
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
needs_cast = True if self.public_format != self.private_format else False
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to,
'cast_ini' : '(' + self.private_format + ')(' if needs_cast else '',
'cast_end' : ')' if needs_cast else '' }
template = (
'${lp}${to} = ${cast_ini}${from}${cast_end};\n')
return string.Template(template).substitute(translations)

View File

@ -41,9 +41,6 @@ class VariableString(Variable):
# Strings will be heap-allocated
self.needs_dispose = True
# We want to get the strings be passed as 'const'
self.pass_constant = True
# Strings which are given as the full value of a TLV will NOT have a
# length prefix
self.length_prefix = False if 'type' in dictionary and dictionary['type'] == 'TLV' else True
@ -118,25 +115,105 @@ class VariableString(Variable):
"""
Copy the string
Variable declaration
"""
def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
def build_variable_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}gchar *${name};\n')
return string.Template(template).substitute(translations)
"""
Getter for the string type
"""
def build_getter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}const gchar **${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the getter
"""
def build_getter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output constant string, or #NULL if not required.\n')
return string.Template(template).substitute(translations)
"""
Builds the String getter implementation
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
if to_is_reference:
template = (
'${lp}if (${to})\n'
'${lp} *${to} = ${from};\n')
return string.Template(template).substitute(translations)
else:
template = (
'${lp}${to} = ${from};\n')
return string.Template(template).substitute(translations)
"""
Setter for the string type
"""
def build_setter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}const gchar *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the setter
"""
def build_setter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output constant string, or #NULL if not required.\n')
return string.Template(template).substitute(translations)
"""
Builds the String setter implementation
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
template = (
'${lp}g_free (${to});\n'
'${lp}${to} = g_strdup (${from});\n')
f.write(string.Template(template).substitute(translations))
return string.Template(template).substitute(translations)
"""
Dispose the string
"""
def emit_dispose(self, f, line_prefix, variable_name):
def build_dispose(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'variable_name' : variable_name }
template = (
'${lp}g_free (${variable_name});\n')
f.write(string.Template(template).substitute(translations))
return string.Template(template).substitute(translations)

View File

@ -128,19 +128,108 @@ class VariableStruct(Variable):
"""
Copying a struct is just about copying each of the struct fields one by one.
Note that we shouldn't just "a = b" with the structs, as the members may be
heap-allocated strings.
Variable declaration
"""
def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
def build_variable_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}${format} ${name};\n')
return string.Template(template).substitute(translations)
"""
The getter for a struct variable will include independent getters for each
of the variables in the struct.
"""
def build_getter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}${format} *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the getter
"""
def build_getter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output constant #${format}, or #NULL if not required.\n')
return string.Template(template).substitute(translations)
"""
Builds the Struct getter implementation
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
if to_is_reference:
template = (
'${lp}if (${to})\n'
'${lp} *${to} = ${from};\n')
return string.Template(template).substitute(translations)
else:
template = (
'${lp}${to} = ${from};\n')
return string.Template(template).substitute(translations)
"""
The setter for a struct variable will include independent setters for each
of the variables in the struct.
"""
def build_setter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}const ${format} *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the setter
"""
def build_setter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: the address of the #${format} to set.\n')
return string.Template(template).substitute(translations)
"""
Builds the Struct setter implementation
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
built = ''
for member in self.members:
member['object'].emit_copy(f, line_prefix, variable_name_from + '.' + member['name'], variable_name_to + '.' + member['name'])
built += member['object'].build_setter_implementation(line_prefix,
variable_name_from + '->' + member['name'],
variable_name_to + '.' + member['name'])
return built
"""
Disposing a struct is just about disposing each of the struct fields one by
one.
"""
def emit_dispose(self, f, line_prefix, variable_name):
def build_dispose(self, line_prefix, variable_name):
built = ''
for member in self.members:
member['object'].emit_dispose(f, line_prefix, variable_name + '.' + member['name'])
built += member['object'].build_dispose(line_prefix, variable_name + '.' + member['name'])
return built

View File

@ -575,7 +575,7 @@ uim_set_pin_protection_input_create (const gchar *str)
info.protection_enabled = read_enable_disable_from_string (split[1]);
info.pin = read_non_empty_string (split[2], "current PIN");
qmi_message_dms_uim_set_pin_protection_input_set_info (input, info, NULL);
qmi_message_dms_uim_set_pin_protection_input_set_info (input, &info, NULL);
g_strfreev (split);
return input;
@ -643,7 +643,7 @@ uim_verify_pin_input_create (const gchar *str)
info.pin_id = read_pin_id_from_string (split[0]);
info.pin = read_non_empty_string (split[1], "current PIN");
qmi_message_dms_uim_verify_pin_input_set_info (input, info, NULL);
qmi_message_dms_uim_verify_pin_input_set_info (input, &info, NULL);
g_strfreev (split);
return input;
@ -712,7 +712,7 @@ uim_unblock_pin_input_create (const gchar *str)
info.puk = read_non_empty_string (split[1], "PUK");
info.new_pin = read_non_empty_string (split[2], "new PIN");
qmi_message_dms_uim_unblock_pin_input_set_info (input, info, NULL);
qmi_message_dms_uim_unblock_pin_input_set_info (input, &info, NULL);
g_strfreev (split);
return input;
@ -781,7 +781,7 @@ uim_change_pin_input_create (const gchar *str)
info.old_pin = read_non_empty_string (split[1], "old PIN");
info.new_pin = read_non_empty_string (split[2], "new PIN");
qmi_message_dms_uim_change_pin_input_set_info (input, info, NULL);
qmi_message_dms_uim_change_pin_input_set_info (input, &info, NULL);
g_strfreev (split);
return input;

View File

@ -788,7 +788,7 @@ qmi_device_release_client (QmiDevice *self,
/* And now, really try to release the CID */
input = qmi_message_ctl_release_cid_input_new ();
qmi_message_ctl_release_cid_input_set_release_info (input, info, NULL);
qmi_message_ctl_release_cid_input_set_release_info (input, &info, NULL);
/* And now, really try to release the CID */
qmi_client_ctl_release_cid (self->priv->client_ctl,