summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-05-30 12:40:46 +0200
committerAleksander Morgado <aleksander@lanedo.com>2012-07-03 16:08:56 +0200
commit2a511da7d3ad724ba1784ab9d9090e717e8d9f48 (patch)
treed7d785fa6cd5bf088529a5b1e9406745aa3a1416
parent55e1355400b19e0060b0441081d786dd5bdfbc6e (diff)
qmi-codegen: refactor, don't use internal packed structs to match TLVs
This is a huge refactor to avoid using internal packed structs to match TLVs from a raw byte buffer. There are cases where packed structs do not help, for example when two variable-length fields (like strings) are found in the same TLV. Instead of packed structs, we'll read basic types one by one directly from the raw byte buffer. With this new logic, struct and array variables are no more than containers of other basic types. Each basic type, implemented as objects inheriting from a base Variable type, knows how to read/write from/to the raw buffer. Therefore, reading a struct is just about reading one by one each of the fields in the struct; and reading an array is just about providing a loop to read all the array elements one by one. This greatly simplifies reading basic types like integers, as the implementation is kept in a single place, regardless of having the integer as the only field in the TLV or as a field of a struct TLV or as an element of an array TLV. Strings are treated a bit differently. In string TLVs, the string is to be considered to be as long as the TLV value itself. In struct TLVs with string fields, the string is assumed to have a 1-byte length prefix which specifies the length of the string field within the TLV.
-rw-r--r--build-aux/qmi-codegen/Client.py18
-rw-r--r--build-aux/qmi-codegen/Container.py95
-rw-r--r--build-aux/qmi-codegen/ContainerOutput.py38
-rw-r--r--build-aux/qmi-codegen/Field.py233
-rw-r--r--build-aux/qmi-codegen/FieldArray.py185
-rw-r--r--build-aux/qmi-codegen/FieldBasic.py137
-rw-r--r--build-aux/qmi-codegen/FieldResult.py (renamed from build-aux/qmi-codegen/FieldStructResult.py)107
-rw-r--r--build-aux/qmi-codegen/FieldString.py115
-rw-r--r--build-aux/qmi-codegen/FieldStruct.py179
-rw-r--r--build-aux/qmi-codegen/Makefile.am14
-rw-r--r--build-aux/qmi-codegen/Message.py41
-rw-r--r--build-aux/qmi-codegen/MessageList.py22
-rw-r--r--build-aux/qmi-codegen/Struct.py69
-rw-r--r--build-aux/qmi-codegen/TypeFactory.py73
-rw-r--r--build-aux/qmi-codegen/Variable.py93
-rw-r--r--build-aux/qmi-codegen/VariableArray.py185
-rw-r--r--build-aux/qmi-codegen/VariableFactory.py (renamed from build-aux/qmi-codegen/ContainerInput.py)36
-rw-r--r--build-aux/qmi-codegen/VariableInteger.py153
-rw-r--r--build-aux/qmi-codegen/VariableString.py142
-rw-r--r--build-aux/qmi-codegen/VariableStruct.py146
-rw-r--r--build-aux/qmi-codegen/utils.py165
-rw-r--r--src/qmi-message.c128
-rw-r--r--src/qmi-message.h19
-rw-r--r--src/qmi-utils.c250
-rw-r--r--src/qmi-utils.h56
25 files changed, 1616 insertions, 1083 deletions
diff --git a/build-aux/qmi-codegen/Client.py b/build-aux/qmi-codegen/Client.py
index fa1bb16..32f5cb4 100644
--- a/build-aux/qmi-codegen/Client.py
+++ b/build-aux/qmi-codegen/Client.py
@@ -23,7 +23,15 @@ import string
from MessageList import MessageList
import utils
+"""
+The Client class is responsible for providing the QmiClient-based service
+specific client GObject.
+"""
class Client:
+
+ """
+ Constructor
+ """
def __init__(self, objects_dictionary):
self.name = None
@@ -37,6 +45,9 @@ class Client:
raise ValueError('Missing Client field')
+ """
+ Emits the generic GObject class implementation
+ """
def __emit_class(self, hfile, cfile):
translations = { 'underscore' : utils.build_underscore_name(self.name),
'no_prefix_underscore_upper' : string.upper(utils.build_underscore_name(self.name[4:])),
@@ -85,6 +96,9 @@ class Client:
cfile.write(string.Template(template).substitute(translations))
+ """
+ Emits the async methods for each known request/response
+ """
def __emit_methods(self, hfile, cfile, message_list):
translations = { 'underscore' : utils.build_underscore_name(self.name),
'camelcase' : utils.build_camelcase_name (self.name) }
@@ -205,6 +219,10 @@ class Client:
'\n' % input_arg_template)
cfile.write(string.Template(template).substitute(translations))
+
+ """
+ Emit the service-specific client implementation
+ """
def emit(self, hfile, cfile, message_list):
# First, emit common class code
utils.add_separator(hfile, 'CLIENT', self.name);
diff --git a/build-aux/qmi-codegen/Container.py b/build-aux/qmi-codegen/Container.py
index b232b39..d73c3f6 100644
--- a/build-aux/qmi-codegen/Container.py
+++ b/build-aux/qmi-codegen/Container.py
@@ -21,29 +21,35 @@
import string
import utils
-from FieldString import FieldString
-from FieldStruct import FieldStruct
-from FieldStructResult import FieldStructResult
-from FieldArray import FieldArray
-from FieldBasic import FieldBasic
+from FieldResult import FieldResult
+from Field import Field
+"""
+The Container class takes care of handling collections of Input or
+Output fields
+"""
class Container:
+
"""
- The Container class takes care of handling collections of Input or
- Output fields
+ Constructor
"""
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
+ def __init__(self, prefix, container_type, dictionary, common_objects_dictionary):
# The field container prefix usually contains the name of the Message,
# e.g. "Qmi Message Ctl Something"
self.prefix = prefix
- # self.name needs to be set by the subclass
- if self.name != 'Input' and self.name != 'Output':
- raise ValueError('Cannot handle container \'%s\'' % self.name)
+ # We may have 'Input' or 'Output' containers
+ if container_type == 'Input':
+ self.readonly = False
+ elif container_type == 'Output':
+ self.readonly = True
+ else:
+ raise ValueError('Cannot handle container type \'%s\'' % container_type)
+
+ self.name = container_type
# Create the composed full name (prefix + name),
- # e.g. "Qmi Message Ctl Something Output Result"
+ # e.g. "Qmi Message Ctl Something Output"
self.fullname = self.prefix + ' ' + self.name
self.fields = None
@@ -80,26 +86,16 @@ class Container:
# Then, really parse each field
for field_dictionary in sorted_dictionary:
if field_dictionary['type'] == 'TLV':
- if field_dictionary['format'] == 'array':
- self.fields.append(FieldArray(self.fullname, field_dictionary, common_objects_dictionary))
- elif field_dictionary['format'] == 'string':
- self.fields.append(FieldString(self.fullname, field_dictionary, common_objects_dictionary))
- elif field_dictionary['format'] == 'struct':
- if field_dictionary['name'] == 'Result':
- self.fields.append(FieldStructResult(self.fullname, field_dictionary, common_objects_dictionary))
- else:
- self.fields.append(FieldStruct(self.fullname, field_dictionary, common_objects_dictionary))
- elif field_dictionary['format'] == 'guint8' or \
- field_dictionary['format'] == 'guint16' or \
- field_dictionary['format'] == 'guint32' or \
- field_dictionary['format'] == 'gint8' or \
- field_dictionary['format'] == 'gint16' or \
- field_dictionary['format'] == 'gint32':
- self.fields.append(FieldBasic(self.fullname, field_dictionary, common_objects_dictionary))
+ if field_dictionary['format'] == 'struct' and \
+ field_dictionary['name'] == 'Result':
+ self.fields.append(FieldResult(self.fullname, field_dictionary, common_objects_dictionary))
else:
- raise ValueError('Cannot handle TLV format \'%s\'' % field_dictionary['format'])
+ self.fields.append(Field(self.fullname, field_dictionary, common_objects_dictionary))
+ """
+ Emit enumeration of TLVs in the container
+ """
def __emit_tlv_ids_enum(self, f):
if self.fields is None:
return
@@ -136,6 +132,9 @@ class Container:
f.write(string.Template(template).substitute(translations))
+ """
+ Emit new container types
+ """
def __emit_types(self, hfile, cfile, translations):
# Emit types header
template = (
@@ -147,26 +146,29 @@ class Container:
template = (
'\n'
'struct _${camelcase} {\n'
- ' volatile gint ref_count;\n'
- '\n')
+ ' volatile gint ref_count;\n')
cfile.write(string.Template(template).substitute(translations))
if self.fields is not None:
for field in self.fields:
- translations['field_type'] = field.field_type
- 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')
- cfile.write(string.Template(template).substitute(translations))
+ if field.variable is not None:
+ translations['field_type'] = field.variable.private_format if field.variable.private_format.endswith('*') else field.variable.private_format + ' '
+ 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')
+ cfile.write(string.Template(template).substitute(translations))
cfile.write(
'};\n')
+ """
+ Emit container handling core implementation
+ """
def __emit_core(self, hfile, cfile, translations):
# Emit container core header
template = (
@@ -215,12 +217,8 @@ class Container:
if self.fields is not None:
for field in self.fields:
- if field.dispose is not None:
- translations['field_dispose'] = field.dispose
- translations['field_variable_name'] = field.variable_name
- template = (
- ' ${field_dispose} (self->${field_variable_name});\n')
- cfile.write(string.Template(template).substitute(translations))
+ if field.variable is not None and field.variable.needs_dispose is True:
+ field.variable.emit_dispose(cfile, ' ', 'self->' + field.variable_name)
template = (
' g_slice_free (${camelcase}, self);\n'
@@ -253,6 +251,9 @@ class Container:
cfile.write(string.Template(template).substitute(translations))
+ """
+ Emit container implementation
+ """
def emit(self, hfile, cfile):
translations = { 'name' : self.name,
'camelcase' : utils.build_camelcase_name (self.fullname),
diff --git a/build-aux/qmi-codegen/ContainerOutput.py b/build-aux/qmi-codegen/ContainerOutput.py
deleted file mode 100644
index 8f17bcd..0000000
--- a/build-aux/qmi-codegen/ContainerOutput.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*-
-#
-# 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
-#
-
-import string
-
-from Field import Field
-from Container import Container
-
-class ContainerOutput(Container):
- """
- The ContainerOutput class takes care of handling collections of Output
- fields
- """
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
-
- self.name = 'Output'
- self.readonly = True
-
- # Call the parent constructor
- Container.__init__(self, prefix, dictionary, common_objects_dictionary)
diff --git a/build-aux/qmi-codegen/Field.py b/build-aux/qmi-codegen/Field.py
index 13432f0..8640f60 100644
--- a/build-aux/qmi-codegen/Field.py
+++ b/build-aux/qmi-codegen/Field.py
@@ -20,14 +20,18 @@
import string
-from Struct import Struct
import utils
+import VariableFactory
+import TypeFactory
+"""
+The Field class takes care of handling Input and Output TLVs
+"""
class Field:
+
"""
- The Field class takes care of handling Input and Output TLVs
+ Constructor
"""
-
def __init__(self, prefix, dictionary, common_objects_dictionary):
# The field prefix, usually the name of the Container,
# e.g. "Qmi Message Ctl Something Output"
@@ -38,11 +42,22 @@ class Field:
self.id = dictionary['id']
# Whether the field is to be considered mandatory in the message
self.mandatory = dictionary['mandatory']
- # Specific format of the field
- self.format = dictionary['format']
- self.public_format = dictionary['public-format'] if 'public-format' in dictionary else None
# The type, which must always be "TLV"
self.type = dictionary['type']
+
+ # Create the composed full name (prefix + name),
+ # e.g. "Qmi Message Ctl Something Output Result"
+ self.fullname = dictionary['fullname'] if 'fullname' in dictionary else self.prefix + ' ' + self.name
+
+ # Create our variable object
+ self.variable = VariableFactory.create_variable(dictionary, self.fullname)
+
+ # Create the variable name within the Container
+ self.variable_name = 'arg_' + string.lower(utils.build_underscore_name(self.name))
+
+ # Create the ID enumeration name
+ self.id_enum_name = string.upper(utils.build_underscore_name(self.prefix + ' TLV ' + self.name))
+
# Output Fields may have prerequisites
self.prerequisites = []
if 'prerequisites' in dictionary:
@@ -61,49 +76,37 @@ class Field:
else:
raise RuntimeError('Common type \'%s\' not found' % prerequisite_dictionary['name'])
- # Strings containing how the given type is to be copied and disposed
- self.copy = None
- self.dispose = None
- # The field type to be used in the generated code
- self.field_type = None
- self.public_field_type = None
-
- # Create the composed full name (prefix + name),
- # e.g. "Qmi Message Ctl Something Output Result"
- self.fullname = self.prefix + ' ' + self.name
-
- # Create the variable name within the Container
- self.variable_name = 'arg_' + string.lower(utils.build_underscore_name(self.name))
-
- # Create the ID enumeration name
- self.id_enum_name = string.upper(utils.build_underscore_name(self.prefix + ' TLV ' + self.name))
-
+ """
+ Emit new types required by this field
+ """
def emit_types(self, hfile, cfile):
- '''
- Subclasses can implement the method to emit the required type
- information
- '''
- pass
+ if TypeFactory.is_type_emitted(self.fullname) is False:
+ TypeFactory.set_type_emitted(self.fullname)
+ self.variable.emit_types(hfile)
+ """
+ Emit the method responsible for getting this TLV from the input/output
+ container
+ """
def emit_getter(self, hfile, cfile):
- public_field_type = self.public_field_type if self.public_field_type is not None else self.field_type
translations = { 'name' : self.name,
'variable_name' : self.variable_name,
- 'public_field_type' : public_field_type,
- 'public_field_out' : public_field_type if public_field_type.endswith('*') else public_field_type + ' ',
- 'dispose_warn' : ' Do not free the returned @value, it is owned by @self.' if self.dispose is not None else '',
+ '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) }
+ 'prefix_underscore' : utils.build_underscore_name(self.prefix),
+ 'const' : 'const ' if self.variable.pass_constant else '' }
# Emit the getter header
template = (
'\n'
'gboolean ${prefix_underscore}_get_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
- ' ${public_field_out}*value,\n'
+ ' ${const}${public_field_out}*value,\n'
' GError **error);\n')
hfile.write(string.Template(template).substitute(translations))
@@ -123,7 +126,7 @@ class Field:
'gboolean\n'
'${prefix_underscore}_get_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
- ' ${public_field_out}*value,\n'
+ ' ${const}${public_field_out}*value,\n'
' GError **error)\n'
'{\n'
' g_return_val_if_fail (self != NULL, FALSE);\n'
@@ -138,29 +141,32 @@ class Field:
'\n'
' /* Just for now, transfer-none always */\n'
' if (value)\n'
- ' *value = (${public_field_type})self->${variable_name};\n'
+ ' *value = (${public_field_out})(self->${variable_name});\n'
+ '\n'
' return TRUE;\n'
'}\n')
cfile.write(string.Template(template).substitute(translations))
+ """
+ Emit the method responsible for setting this TLV in the input/output
+ container
+ """
def emit_setter(self, hfile, cfile):
translations = { 'name' : self.name,
'variable_name' : self.variable_name,
- 'field_type' : self.field_type,
- 'public_field_type' : self.public_field_type if self.public_field_type is not None else self.field_type,
- 'field_dispose' : self.dispose + '(self->' + self.variable_name + ');\n' if self.dispose is not None else '',
- 'field_copy' : self.copy + ' ' if self.copy is not None else '',
+ '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) }
+ 'prefix_underscore' : utils.build_underscore_name(self.prefix),
+ 'const' : 'const ' if self.variable.pass_constant else '' }
# Emit the setter header
template = (
'\n'
'gboolean ${prefix_underscore}_set_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
- ' ${public_field_type} value,\n'
+ ' ${const}${field_type} value,\n'
' GError **error);\n')
hfile.write(string.Template(template).substitute(translations))
@@ -180,27 +186,59 @@ class Field:
'gboolean\n'
'${prefix_underscore}_set_${underscore} (\n'
' ${prefix_camelcase} *self,\n'
- ' ${public_field_type} value,\n'
+ ' ${const}${field_type} value,\n'
' GError **error)\n'
'{\n'
' g_return_val_if_fail (self != NULL, FALSE);\n'
'\n'
- ' ${field_dispose}\n'
- ' self->${variable_name}_set = TRUE;\n'
- ' self->${variable_name} = (${field_type})${field_copy}(value);\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(
'\n'
' return TRUE;\n'
- '}\n'
- '\n')
- cfile.write(string.Template(template).substitute(translations))
+ '}\n')
+
+ """
+ Emit the code responsible for adding the TLV to the QMI message
+ """
def emit_input_tlv_add(self, f, line_prefix):
- '''
- Subclasses can implement the method to emit the required TLV adding
- '''
- pass
+ translations = { 'name' : self.name,
+ 'tlv_id' : self.id_enum_name,
+ 'variable_name' : self.variable_name,
+ 'lp' : line_prefix }
+
+ template = (
+ '${lp}guint8 buffer[1024];\n'
+ '${lp}guint16 buffer_len = 1024;\n'
+ '${lp}guint8 *buffer_aux = buffer;\n'
+ '\n')
+ f.write(string.Template(template).substitute(translations))
+
+ # Now, write the contents of the variable into the buffer
+ self.variable.emit_buffer_write(f, line_prefix, 'input->' + self.variable_name, 'buffer_aux', 'buffer_len')
+
+ template = (
+ '\n'
+ '${lp}if (!qmi_message_tlv_add (self,\n'
+ '${lp} (guint8)${tlv_id},\n'
+ '${lp} (1024 - buffer_len),\n'
+ '${lp} buffer,\n'
+ '${lp} error)) {\n'
+ '${lp} g_prefix_error (error, \"Couldn\'t set the ${name} TLV: \");\n'
+ '${lp} qmi_message_unref (self);\n'
+ '${lp} return NULL;\n'
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+ """
+ Emit the code responsible for checking prerequisites in output TLVs
+ """
def emit_output_prerequisite_check(self, f, line_prefix):
if self.prerequisites == []:
f.write('%s/* No Prerequisites for field */\n' % line_prefix)
@@ -218,21 +256,98 @@ class Field:
f.write(string.Template(template).substitute(translations))
+ """
+ Emit the code responsible for retrieving the TLV from the QMI message
+ """
def emit_output_tlv_get(self, f, line_prefix):
- '''
- Subclasses can implement the method to emit the required TLV retrieval
- '''
- pass
+ translations = { 'name' : self.name,
+ 'container_underscore' : utils.build_underscore_name (self.prefix),
+ 'tlv_id' : self.id_enum_name,
+ 'variable_name' : self.variable_name,
+ 'lp' : line_prefix,
+ 'error' : 'error' if self.mandatory == 'yes' else 'NULL'}
+
+ template = (
+ '${lp}guint8 *buffer;\n'
+ '${lp}guint16 buffer_len;\n'
+ '\n'
+ '${lp}if (qmi_message_tlv_get (message,\n'
+ '${lp} ${tlv_id},\n'
+ '${lp} &buffer_len,\n'
+ '${lp} &buffer,\n'
+ '${lp} ${error})) {\n'
+ '${lp} self->${variable_name}_set = TRUE;\n'
+ '\n')
+ f.write(string.Template(template).substitute(translations))
+
+ # Now, read the contents of the buffer into the variable
+ self.variable.emit_buffer_read(f, line_prefix + ' ', 'self->' + self.variable_name, 'buffer', 'buffer_len')
+ template = (
+ '\n'
+ '${lp} /* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n'
+ '${lp} if (buffer_len > 0) {\n'
+ '${lp} g_warning ("Left \'%u\' bytes unread when getting the \'${name}\' TLV", buffer_len);\n'
+ '${lp} }\n')
+ if self.mandatory == 'yes':
+ template += (
+ '${lp}} else {\n'
+ '${lp} g_prefix_error (error, \"Couldn\'t get the ${name} TLV: \");\n'
+ '${lp} ${container_underscore}_unref (self);\n'
+ '${lp} return NULL;\n'
+ '${lp}}\n')
+ else:
+ template += (
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Emit the method responsible for creating a printable representation of the TLV
+ """
def emit_output_tlv_get_printable(self, f):
- translations = { 'underscore' : utils.build_underscore_name (self.fullname) }
+ if TypeFactory.is_get_printable_emitted(self.fullname):
+ return
+
+ TypeFactory.set_get_printable_emitted(self.fullname)
+
+ translations = { 'name' : self.name,
+ 'tlv_id' : self.id_enum_name,
+ 'underscore' : utils.build_underscore_name (self.fullname) }
template = (
+ '\n'
'static gchar *\n'
'${underscore}_get_printable (\n'
- ' QmiMessage *self,\n'
+ ' QmiMessage *message,\n'
' const gchar *line_prefix)\n'
'{\n'
+ ' guint8 *buffer;\n'
+ ' guint16 buffer_len;\n'
+ '\n'
+ ' if (qmi_message_tlv_get (message,\n'
+ ' ${tlv_id},\n'
+ ' &buffer_len,\n'
+ ' &buffer,\n'
+ ' NULL)) {\n'
+ ' GString *printable;\n'
+ '\n'
+ ' printable = g_string_new ("");\n')
+ f.write(string.Template(template).substitute(translations))
+
+ # Now, read the contents of the buffer into the printable representation
+ self.variable.emit_get_printable(f, ' ', 'printable', 'buffer', 'buffer_len')
+
+ template = (
+ '\n'
+ ' /* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n'
+ ' if (buffer_len > 0) {\n'
+ ' g_warning ("Left \'%u\' bytes unread when getting the \'${name}\' TLV as printable", buffer_len);\n'
+ ' }\n'
+ '\n'
+ ' return g_string_free (printable, FALSE);\n'
+ ' }\n'
+ '\n'
' return NULL;\n'
'}\n')
f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/FieldArray.py b/build-aux/qmi-codegen/FieldArray.py
deleted file mode 100644
index 371659a..0000000
--- a/build-aux/qmi-codegen/FieldArray.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env python
-# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*-
-#
-# 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
-#
-
-import string
-
-import utils
-from Struct import Struct
-from Field import Field
-
-class FieldArray(Field):
- """
- The FieldArray class takes care of handling 'array' format based
- Input and Output TLVs
- """
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
- # Call the parent constructor
- Field.__init__(self, prefix, dictionary, common_objects_dictionary)
-
- if dictionary['array-element']['format'] != 'struct':
- raise ValueError('Cannot handle arrays of format \'%s\'' % dictionary['array-element']['format'])
-
- # Set a struct as content
- self.array_element = Struct(utils.build_camelcase_name (self.fullname +
- ' ' +
- dictionary['array-element']['name']),
- dictionary['array-element']['contents'])
-
- # We'll use standard GArrays
- self.field_type = 'GArray *';
- # The array needs to get disposed
- self.dispose = 'g_array_unref'
-
-
- def emit_types(self, hfile, cfile):
- '''
- Emit the type for the struct used as array element
- '''
- self.array_element.emit(hfile)
- self.array_element.emit_packed(cfile)
-
-
- def emit_input_tlv_add(self, cfile, line_prefix):
- # TODO
- raise ValueError('Array as input not implemented yet')
-
- def emit_output_tlv_get(self, f, line_prefix):
- translations = { 'name' : self.name,
- 'container_underscore' : utils.build_underscore_name (self.prefix),
- 'array_element_type' : self.array_element.name,
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name,
- 'lp' : line_prefix,
- 'error' : 'error' if self.mandatory == 'yes' else 'NULL'}
-
- template = (
- '\n'
- '${lp}guint i;\n'
- '${lp}guint8 buffer[1024];\n'
- '${lp}guint16 buffer_len = 1024;\n'
- '${lp}${array_element_type}Packed *item;\n'
- '\n'
- '${lp}if (qmi_message_tlv_get_varlen (message,\n'
- '${lp} ${tlv_id},\n'
- '${lp} &buffer_len,\n'
- '${lp} buffer,\n'
- '${lp} ${error})) {\n'
- '${lp} guint8 nitems = buffer[0];\n'
- '\n'
- '${lp} self->${variable_name}_set = TRUE;\n'
- '${lp} self->${variable_name} = g_array_sized_new (FALSE, FALSE, sizeof (${array_element_type}), nitems);\n'
- '${lp} for (i = 0, item = (${array_element_type}Packed *)&buffer[1]; i < nitems; i++, item++) {\n'
- '${lp} ${array_element_type} tmp;\n'
- '\n')
- f.write(string.Template(template).substitute(translations))
-
- for struct_field in self.array_element.members:
- f.write('%s %s;\n' % (line_prefix,
- utils.he_from_le ('item->' + utils.build_underscore_name(struct_field['name']),
- 'tmp.' + utils.build_underscore_name(struct_field['name']),
- struct_field['format'])))
-
- template = (
- '${lp} g_array_insert_val (self->${variable_name}, i, tmp);\n'
- '${lp} }\n')
-
- if self.mandatory == 'yes':
- template += (
- '${lp}} else {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t get the ${name} TLV: \");\n'
- '${lp} ${container_underscore}_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- else:
- template += (
- '${lp}}\n')
- f.write(string.Template(template).substitute(translations))
-
-
- def emit_output_tlv_get_printable(self, f):
- translations = { 'underscore' : utils.build_underscore_name (self.fullname),
- 'array_element_type' : self.array_element.name,
- 'tlv_id' : self.id_enum_name }
- template = (
- '\n'
- 'static gchar *\n'
- '${underscore}_get_printable (\n'
- ' QmiMessage *self,\n'
- ' const gchar *line_prefix)\n'
- '{\n'
- ' GString *printable;\n'
- ' guint i;\n'
- ' guint8 buffer[1024];\n'
- ' guint16 buffer_len = 1024;\n'
- ' ${array_element_type}Packed *item;\n'
- '\n'
- ' printable = g_string_new ("");\n'
- ' if (qmi_message_tlv_get_varlen (self,\n'
- ' ${tlv_id},\n'
- ' &buffer_len,\n'
- ' buffer,\n'
- ' NULL)) {\n'
- ' guint8 nitems = buffer[0];\n'
- '\n'
- ' for (i = 0, item = (${array_element_type}Packed *)&buffer[1]; i < nitems; i++, item++) {\n'
- ' ${array_element_type} tmp;\n'
- '\n'
- ' g_string_append_printf (printable,\n'
- ' "\\n"\n'
- ' "%s [#%u]",\n'
- ' line_prefix, i);\n'
- '\n')
- f.write(string.Template(template).substitute(translations))
-
- for struct_field in self.array_element.members:
- translations['name_struct_field'] = struct_field['name']
- translations['underscore_struct_field'] = utils.build_underscore_name(struct_field['name'])
- translations['endianfix'] = utils.he_from_le ('item->' + utils.build_underscore_name(struct_field['name']),
- 'tmp.' + utils.build_underscore_name(struct_field['name']),
- struct_field['format'])
-
- template = (
- ' ${endianfix};\n')
-
- if struct_field['format'] == 'guint8' or \
- struct_field['format'] == 'guint16' or \
- struct_field['format'] == 'guin32':
- template += (
- ' g_string_append_printf (printable,\n'
- ' "\\n"\n'
- ' "%s [${name_struct_field} = %u] ",\n'
- ' line_prefix,\n'
- ' (guint)tmp.${underscore_struct_field});\n')
- else:
- template += (
- ' g_string_append_printf (printable,\n'
- ' "\\n"'
- ' "%s [${name_struct_field} = %d] ",\n'
- ' line_prefix,\n'
- ' (gint)tmp.${underscore_struct_field});\n')
- f.write(string.Template(template).substitute(translations))
-
- f.write(
- ' }\n'
- ' }\n'
- '\n'
- ' return g_string_free (printable, FALSE);\n'
- '}\n')
diff --git a/build-aux/qmi-codegen/FieldBasic.py b/build-aux/qmi-codegen/FieldBasic.py
deleted file mode 100644
index d0b50b2..0000000
--- a/build-aux/qmi-codegen/FieldBasic.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/env python
-# -*- 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
-#
-
-import string
-
-import utils
-from Field import Field
-
-class FieldBasic(Field):
- """
- The FieldBasic class takes care of handling Input and Output TLVs based
- on basic types (e.g. integers)
- """
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
-
- # Call the parent constructor
- Field.__init__(self, prefix, dictionary, common_objects_dictionary)
-
- # The field type to be used in the generated code is the same as the one
- # given in the database
- self.field_type = self.format;
- self.public_field_type = self.public_format;
-
- def emit_input_tlv_add(self, cfile, line_prefix):
- translations = { 'name' : self.name,
- 'tlv_id' : self.id_enum_name,
- 'field_type' : self.field_type,
- 'variable_name' : self.variable_name,
- 'set_variable' : utils.le_from_he ('input->' + self.variable_name, 'tmp', self.field_type),
- 'lp' : line_prefix }
-
- template = (
- '${lp}${field_type} tmp;\n'
- '\n'
- '${lp}${set_variable};\n'
- '\n'
- '${lp}if (!qmi_message_tlv_add (self,\n'
- '${lp} (guint8)${tlv_id},\n'
- '${lp} sizeof (tmp),\n'
- '${lp} &tmp,\n'
- '${lp} error)) {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t set the ${name} TLV: \");\n'
- '${lp} qmi_message_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- cfile.write(string.Template(template).substitute(translations))
-
-
- def emit_output_tlv_get(self, cfile, line_prefix):
- translations = { 'name' : self.name,
- 'container_underscore' : utils.build_underscore_name (self.prefix),
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name,
- 'lp' : line_prefix,
- 'error' : 'error' if self.mandatory == 'yes' else 'NULL'}
-
- template = (
- '${lp}if (qmi_message_tlv_get (message,\n'
- '${lp} ${tlv_id},\n'
- '${lp} sizeof (self->${variable_name}),\n'
- '${lp} &self->${variable_name},\n'
- '${lp} ${error})) {\n'
- '${lp} self->${variable_name}_set = TRUE;\n')
- cfile.write(string.Template(template).substitute(translations))
-
- cfile.write('%s %s;\n' % (line_prefix,
- utils.le_from_he ('self->' + self.variable_name,
- 'self->' + self.variable_name,
- self.field_type)))
- if self.mandatory == 'yes':
- template = (
- '${lp}} else {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t get the ${name} TLV: \");\n'
- '${lp} ${container_underscore}_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- else:
- template = (
- '${lp}}\n')
- cfile.write(string.Template(template).substitute(translations))
-
-
- def emit_output_tlv_get_printable(self, f):
- translations = { 'underscore' : utils.build_underscore_name (self.fullname),
- 'field_type' : self.field_type,
- 'tlv_id' : self.id_enum_name }
-
- template = (
- '\n'
- 'static gchar *\n'
- '${underscore}_get_printable (\n'
- ' QmiMessage *self,\n'
- ' const gchar *line_prefix)\n'
- '{\n'
- ' ${field_type} tmp;\n'
- ' gchar *printable;\n'
- '\n'
- ' g_assert (qmi_message_tlv_get (self,\n'
- ' ${tlv_id},\n'
- ' sizeof (tmp),\n'
- ' &tmp,\n'
- ' NULL));\n')
-
- template += (' %s;\n' % (utils.le_from_he('tmp', 'tmp', self.field_type)))
-
- if self.format == 'guint8' or \
- self.format == 'guint16' or \
- self.format == 'guin32':
- template += (
- ' printable = g_strdup_printf ("%u", (guint)tmp);\n')
- else:
- template += (
- ' printable = g_strdup_printf ("%d", (gint)tmp);\n')
-
- template += (
- '\n'
- ' return printable;\n'
- '}\n')
- f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/FieldStructResult.py b/build-aux/qmi-codegen/FieldResult.py
index af34de9..eada8d9 100644
--- a/build-aux/qmi-codegen/FieldStructResult.py
+++ b/build-aux/qmi-codegen/FieldResult.py
@@ -21,19 +21,30 @@
import string
import utils
-from Struct import Struct
-from FieldStruct import FieldStruct
+import TypeFactory
+from Field import Field
+
+
+"""
+The FieldResult class takes care of handling the common 'Result' TLV
+"""
+class FieldResult(Field):
-class FieldStructResult(FieldStruct):
"""
- The FieldResult class takes care of handling the common 'Result' TLV
+ Emit the types required to the source file (they will not be exposed in the
+ interface)
"""
-
def emit_types(self, hfile, cfile):
- # Emit both packed/unpacked types to the SOURCE file (not public)
- self.contents.emit_packed(cfile)
- self.contents.emit(cfile)
+ if TypeFactory.is_type_emitted(self.fullname) is False:
+ TypeFactory.set_type_emitted(self.fullname)
+ self.variable.emit_types(cfile)
+
+ """
+ Emit the method responsible for getting the Result TLV contents. This
+ special TLV will have its own getter implementation, as we want to have
+ proper GErrors built from the QMI result status/code.
+ """
def emit_getter(self, hfile, cfile):
translations = { 'variable_name' : self.variable_name,
'prefix_camelcase' : utils.build_camelcase_name(self.prefix),
@@ -91,14 +102,20 @@ class FieldStructResult(FieldStruct):
'}\n')
cfile.write(string.Template(template).substitute(translations))
+
+ """
+ Emit the method responsible for getting a printable representation of this
+ TLV field.
+ """
def emit_output_tlv_get_printable(self, f):
- translations = { 'name' : self.name,
- 'underscore' : utils.build_underscore_name (self.fullname),
- 'container_underscore' : utils.build_underscore_name (self.prefix),
- 'field_type' : self.field_type,
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name }
+ if TypeFactory.is_get_printable_emitted(self.fullname):
+ return
+
+ TypeFactory.set_get_printable_emitted(self.fullname)
+ translations = { 'name' : self.name,
+ 'tlv_id' : self.id_enum_name,
+ 'underscore' : utils.build_underscore_name (self.fullname) }
template = (
'\n'
'static gchar *\n'
@@ -106,34 +123,40 @@ class FieldStructResult(FieldStruct):
' QmiMessage *self,\n'
' const gchar *line_prefix)\n'
'{\n'
- ' GString *printable;\n'
- ' ${field_type}Packed tmp;\n'
+ ' guint8 *buffer;\n'
+ ' guint16 buffer_len;\n'
'\n'
- ' printable = g_string_new ("");\n'
- ' g_assert (qmi_message_tlv_get (self,\n'
- ' ${tlv_id},\n'
- ' sizeof (tmp),\n'
- ' &tmp,\n'
- ' NULL));\n')
- f.write(string.Template(template).substitute(translations))
-
- for struct_field in self.contents.members:
- translations['name_struct_field'] = struct_field['name']
- translations['underscore_struct_field'] = utils.build_underscore_name(struct_field['name'])
- translations['endianfix'] = utils.he_from_le ('tmp.' + utils.build_underscore_name(struct_field['name']),
- 'tmp.' + utils.build_underscore_name(struct_field['name']),
- struct_field['format'])
- template = (
- ' ${endianfix};')
-
- f.write(
- ' if (tmp.error_status == QMI_STATUS_SUCCESS)\n'
- ' g_string_append (printable,\n'
- ' "SUCCESS");\n'
- ' else\n'
- ' g_string_append_printf (printable,\n'
- ' "FAILURE: %s",\n'
- ' qmi_protocol_error_get_string ((QmiProtocolError) tmp.error_code));\n'
+ ' if (qmi_message_tlv_get (self,\n'
+ ' ${tlv_id},\n'
+ ' &buffer_len,\n'
+ ' &buffer,\n'
+ ' NULL)) {\n'
+ ' GString *printable;\n'
+ ' guint16 error_status;\n'
+ ' guint16 error_code;\n'
+ '\n'
+ ' printable = g_string_new ("");\n'
+ ' qmi_utils_read_guint16_from_buffer (\n'
+ ' &buffer,\n'
+ ' &buffer_len,\n'
+ ' &error_status);\n'
+ ' qmi_utils_read_guint16_from_buffer (\n'
+ ' &buffer,\n'
+ ' &buffer_len,\n'
+ ' &error_code);\n'
+ '\n'
+ ' g_warn_if_fail (buffer_len == 0);\n'
'\n'
- ' return g_string_free (printable, FALSE);\n'
+ ' if (error_status == QMI_STATUS_SUCCESS)\n'
+ ' g_string_append (printable, "SUCCESS");\n'
+ ' else\n'
+ ' g_string_append_printf (printable,\n'
+ ' "FAILURE: %s",\n'
+ ' qmi_protocol_error_get_string ((QmiProtocolError) error_code));\n'
+ '\n'
+ ' return g_string_free (printable, FALSE);\n'
+ ' }\n'
+ '\n'
+ ' return NULL;\n'
'}\n')
+ f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/FieldString.py b/build-aux/qmi-codegen/FieldString.py
deleted file mode 100644
index 405f19e..0000000
--- a/build-aux/qmi-codegen/FieldString.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/env python
-# -*- 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
-#
-
-import string
-
-import utils
-from Field import Field
-
-class FieldString(Field):
- """
- The FieldString class takes care of handling 'string' format based
- Input and Output TLVs
- """
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
- # Call the parent constructor
- Field.__init__(self, prefix, dictionary, common_objects_dictionary)
-
- # The field type will be the given string name
- self.field_type = 'gchar *'
- self.public_field_type = 'const gchar *'
- # The string needs to get disposed
- self.dispose = 'g_free'
- # The string needs to be copied when set
- self.copy = 'g_strdup'
-
-
- def emit_input_tlv_add(self, cfile, line_prefix):
- translations = { 'name' : self.name,
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name,
- 'lp' : line_prefix }
- template = (
- '${lp}if (!qmi_message_tlv_add (self,\n'
- '${lp} (guint8)${tlv_id},\n'
- '${lp} strlen (input->${variable_name}) + 1,\n'
- '${lp} input->${variable_name},\n'
- '${lp} error)) {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t set the \'${name}\' TLV: \");\n'
- '${lp} qmi_message_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- cfile.write(string.Template(template).substitute(translations))
-
-
- def emit_output_tlv_get(self, f, line_prefix):
- translations = { 'name' : self.name,
- 'container_underscore' : utils.build_underscore_name (self.prefix),
- 'field_type' : self.field_type,
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name,
- 'lp' : line_prefix,
- 'error' : 'error' if self.mandatory == 'yes' else 'NULL'}
-
- template = (
- '${lp}self->${variable_name} = qmi_message_tlv_get_string (message,\n'
- '${lp} ${tlv_id},\n'
- '${lp} ${error});\n'
- '${lp}if (self->${variable_name}) {\n'
- '${lp} self->${variable_name}_set = TRUE;\n')
-
- if self.mandatory == 'yes':
- template += (
- '${lp}} else {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t get the ${name} TLV: \");\n'
- '${lp} ${container_underscore}_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- else:
- template += (
- '${lp}}\n')
- f.write(string.Template(template).substitute(translations))
-
-
- def emit_output_tlv_get_printable(self, f):
- translations = { 'underscore' : utils.build_underscore_name (self.fullname),
- 'tlv_id' : self.id_enum_name }
-
- template = (
- '\n'
- 'static gchar *\n'
- '${underscore}_get_printable (\n'
- ' QmiMessage *self,\n'
- ' const gchar *line_prefix)\n'
- '{\n'
- ' gchar *str;\n'
- ' gchar *printable;\n'
- '\n'
- ' str = qmi_message_tlv_get_string (self,\n'
- ' ${tlv_id},\n'
- ' NULL);\n'
- ' g_assert (str != NULL);\n'
- ' printable = g_strdup_printf ("\'%s\'", str);\n'
- ' g_free (str);\n'
- '\n'
- ' return printable;\n'
- '}\n')
- f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/FieldStruct.py b/build-aux/qmi-codegen/FieldStruct.py
deleted file mode 100644
index c812ede..0000000
--- a/build-aux/qmi-codegen/FieldStruct.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#!/usr/bin/env python
-# -*- 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
-#
-
-import string
-
-import utils
-from Struct import Struct
-from Field import Field
-
-class FieldStruct(Field):
- """
- The FieldStruct class takes care of handling 'struct' format based
- Input and Output TLVs
- """
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
- # Call the parent constructor
- Field.__init__(self, prefix, dictionary, common_objects_dictionary)
-
- # The field type will be the given struct name
- self.field_type = utils.build_camelcase_name(self.fullname)
-
- # Set a struct as content
- self.contents = Struct(self.field_type,
- dictionary['contents'])
-
-
- def emit_types(self, hfile, cfile):
- '''
- Emit the Struct type info
- '''
- self.contents.emit_packed(cfile)
- self.contents.emit(hfile)
-
-
- def emit_input_tlv_add(self, cfile, line_prefix):
- translations = { 'name' : self.name,
- 'tlv_id' : self.id_enum_name,
- 'field_type' : self.field_type,
- 'variable_name' : self.variable_name,
- 'lp' : line_prefix }
-
- template = (
- '${lp}${field_type}Packed tmp;\n'
- '\n')
- cfile.write(string.Template(template).substitute(translations))
-
- # uint32 and uint16 fields need to be converted to host-endianness
- for struct_field in self.contents.members:
- cfile.write('%s%s;\n' % (line_prefix,
- utils.le_from_he ('input->' + self.variable_name + '.' + utils.build_underscore_name(struct_field['name']),
- 'tmp.' + utils.build_underscore_name(struct_field['name']),
- struct_field['format'])))
-
- template = (
- '\n'
- '${lp}if (!qmi_message_tlv_add (self,\n'
- '${lp} (guint8)${tlv_id},\n'
- '${lp} sizeof (tmp),\n'
- '${lp} &tmp,\n'
- '${lp} error)) {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t set the ${name} TLV: \");\n'
- '${lp} qmi_message_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- cfile.write(string.Template(template).substitute(translations))
-
-
- def emit_output_tlv_get(self, f, line_prefix):
- translations = { 'name' : self.name,
- 'container_underscore' : utils.build_underscore_name (self.prefix),
- 'field_type' : self.field_type,
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name,
- 'lp' : line_prefix,
- 'error' : 'error' if self.mandatory == 'yes' else 'NULL'}
-
- template = (
- '${lp}${field_type}Packed tmp;\n'
- '\n'
- '${lp}if (qmi_message_tlv_get (message,\n'
- '${lp} ${tlv_id},\n'
- '${lp} sizeof (tmp),\n'
- '${lp} &tmp,\n'
- '${lp} ${error})) {\n'
- '${lp} self->${variable_name}_set = TRUE;\n')
- f.write(string.Template(template).substitute(translations))
-
- for struct_field in self.contents.members:
- f.write('%s %s;\n' % (line_prefix,
- utils.he_from_le ('tmp.' + utils.build_underscore_name(struct_field['name']),
- 'self->' + self.variable_name + '.' + utils.build_underscore_name(struct_field['name']),
- struct_field['format'])))
- if self.mandatory == 'yes':
- template = (
- '${lp}} else {\n'
- '${lp} g_prefix_error (error, \"Couldn\'t get the ${name} TLV: \");\n'
- '${lp} ${container_underscore}_unref (self);\n'
- '${lp} return NULL;\n'
- '${lp}}\n')
- else:
- template = (
- '${lp}}\n')
- f.write(string.Template(template).substitute(translations))
-
- def emit_output_tlv_get_printable(self, f):
- translations = { 'name' : self.name,
- 'underscore' : utils.build_underscore_name (self.fullname),
- 'container_underscore' : utils.build_underscore_name (self.prefix),
- 'field_type' : self.field_type,
- 'tlv_id' : self.id_enum_name,
- 'variable_name' : self.variable_name }
-
- template = (
- '\n'
- 'static gchar *\n'
- '${underscore}_get_printable (\n'
- ' QmiMessage *self,\n'
- ' const gchar *line_prefix)\n'
- '{\n'
- ' GString *printable;\n'
- ' ${field_type}Packed tmp;\n'
- '\n'
- ' printable = g_string_new ("");\n'
- ' g_assert (qmi_message_tlv_get (self,\n'
- ' ${tlv_id},\n'
- ' sizeof (tmp),\n'
- ' &tmp,\n'
- ' NULL));\n')
- f.write(string.Template(template).substitute(translations))
-
- first = False
- for struct_field in self.contents.members:
- translations['name_struct_field'] = struct_field['name']
- translations['underscore_struct_field'] = utils.build_underscore_name(struct_field['name'])
- translations['endianfix'] = utils.he_from_le ('tmp.' + utils.build_underscore_name(struct_field['name']),
- 'tmp.' + utils.build_underscore_name(struct_field['name']),
- struct_field['format'])
- template = (
- ' ${endianfix};'
- ' g_string_append_printf (printable,\n')
-
- if struct_field['format'] == 'guint8' or \
- struct_field['format'] == 'guint16' or \
- struct_field['format'] == 'guin32':
- template += (
- ' "\\n"\n'
- ' "%s [${name_struct_field} = %u] ",\n'
- ' line_prefix,\n'
- ' (guint)tmp.${underscore_struct_field});\n')
- else:
- template += (
- ' "\\n"\n'
- ' "%s [${name_struct_field} = %d] ",\n'
- ' line_prefix,\n'
- ' (gint)tmp.${underscore_struct_field});\n')
- f.write(string.Template(template).substitute(translations))
-
- f.write(
- '\n'
- ' return g_string_free (printable, FALSE);\n'
- '}\n')
diff --git a/build-aux/qmi-codegen/Makefile.am b/build-aux/qmi-codegen/Makefile.am
index 2568738..d1682f7 100644
--- a/build-aux/qmi-codegen/Makefile.am
+++ b/build-aux/qmi-codegen/Makefile.am
@@ -1,15 +1,17 @@
EXTRA_DIST = \
+ TypeFactory.py \
Client.py \
MessageList.py \
Message.py \
Container.py \
- ContainerInput.py \
- ContainerOutput.py \
Field.py \
- FieldArray.py \
- FieldStruct.py \
- FieldStructResult.py \
- FieldBasic.py \
+ FieldResult.py \
+ Variable.py \
+ VariableFactory.py \
+ VariableArray.py \
+ VariableStruct.py \
+ VariableInteger.py \
+ VariableString.py \
utils.py \
qmi-codegen
diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py
index c51bc00..054a997 100644
--- a/build-aux/qmi-codegen/Message.py
+++ b/build-aux/qmi-codegen/Message.py
@@ -21,10 +21,16 @@
import string
import utils
-from ContainerOutput import ContainerOutput
-from ContainerInput import ContainerInput
+from Container import Container
+"""
+The Message class takes care of request/response message handling
+"""
class Message:
+
+ """
+ Constructor
+ """
def __init__(self, dictionary, common_objects_dictionary):
# The message prefix
self.prefix = 'Qmi Message'
@@ -48,19 +54,24 @@ class Message:
# Every defined message will have its own output container, which
# will generate a new Output type and public getters for each output
# field
- self.output = ContainerOutput(self.fullname,
- dictionary['output'],
- common_objects_dictionary)
+ self.output = Container(self.fullname,
+ 'Output',
+ dictionary['output'],
+ common_objects_dictionary)
# Build input container.
# Every defined message will have its own input container, which
# will generate a new Input type and public getters for each input
# field
- self.input = ContainerInput(self.fullname,
- dictionary['input'] if 'input' in dictionary else None,
- common_objects_dictionary)
+ self.input = Container(self.fullname,
+ 'Input',
+ dictionary['input'] if 'input' in dictionary else None,
+ common_objects_dictionary)
+ """
+ Emit method responsible for creating a new request of the given type
+ """
def __emit_request_creator(self, hfile, cfile):
translations = { 'name' : self.name,
'service' : self.service,
@@ -161,6 +172,9 @@ class Message:
'}\n')
+ """
+ Emit method responsible for parsing a response of the given type
+ """
def __emit_response_parser(self, hfile, cfile):
translations = { 'name' : self.name,
'container' : utils.build_camelcase_name (self.output.fullname),
@@ -219,6 +233,10 @@ class Message:
'}\n')
+ """
+ Emit method responsible for getting a printable representation of the whole
+ request/response
+ """
def __emit_get_printable(self, hfile, cfile):
if self.input.fields is not None:
@@ -293,8 +311,6 @@ class Message:
' }\n'
' }\n'
'\n'
- '\n'
- '\n'
' if (!tlv_type_str) {\n'
' gchar *value_str = NULL;\n'
'\n'
@@ -350,6 +366,9 @@ class Message:
cfile.write(string.Template(template).substitute(translations))
+ """
+ Emit request/response handling implementation
+ """
def emit(self, hfile, cfile):
utils.add_separator(hfile, 'REQUEST/RESPONSE', self.fullname);
utils.add_separator(cfile, 'REQUEST/RESPONSE', self.fullname);
@@ -364,4 +383,6 @@ class Message:
self.output.emit(hfile, cfile)
self.__emit_response_parser(hfile, cfile)
+ hfile.write('\n/* --- Printable -- */\n');
+ cfile.write('\n/* --- Printable -- */\n');
self.__emit_get_printable(hfile, cfile)
diff --git a/build-aux/qmi-codegen/MessageList.py b/build-aux/qmi-codegen/MessageList.py
index eafb068..ee2d7a6 100644
--- a/build-aux/qmi-codegen/MessageList.py
+++ b/build-aux/qmi-codegen/MessageList.py
@@ -23,7 +23,15 @@ import string
from Message import Message
import utils
+"""
+The MessageList class handles the generation of all messages for a given
+specific service
+"""
class MessageList:
+
+ """
+ Constructor
+ """
def __init__(self, objects_dictionary, common_objects_dictionary):
self.list = []
self.message_id_enum_name = None
@@ -49,6 +57,9 @@ class MessageList:
raise ValueError('Missing Service field')
+ """
+ Emit the enumeration of the messages found in the specific service
+ """
def emit_message_ids_enum(self, f):
translations = { 'enum_type' : utils.build_camelcase_name (self.message_id_enum_name) }
template = (
@@ -67,6 +78,10 @@ class MessageList:
f.write(string.Template(template).substitute(translations))
+ """
+ Emit the method responsible for getting a printable representation of all
+ messages of a given service.
+ """
def __emit_get_printable(self, hfile, cfile):
translations = { 'service' : string.lower(self.service) }
@@ -103,6 +118,9 @@ class MessageList:
cfile.write(string.Template(template).substitute(translations))
+ """
+ Emit the message list handling implementation
+ """
def emit(self, hfile, cfile):
# First, emit the message IDs enum
self.emit_message_ids_enum(cfile)
@@ -112,6 +130,6 @@ class MessageList:
message.emit(hfile, cfile)
# First, emit common class code
- utils.add_separator(hfile, 'PRINTABLE', self.service);
- utils.add_separator(cfile, 'PRINTABLE', self.service);
+ utils.add_separator(hfile, 'Service-specific printable', self.service);
+ utils.add_separator(cfile, 'Service-specific printable', self.service);
self.__emit_get_printable(hfile, cfile)
diff --git a/build-aux/qmi-codegen/Struct.py b/build-aux/qmi-codegen/Struct.py
deleted file mode 100644
index 04bd307..0000000
--- a/build-aux/qmi-codegen/Struct.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python
-# -*- 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
-#
-
-import string
-
-import utils
-
-class Struct:
-
- def __init__(self, name, members):
- # The struct type name, e.g. QmiTheStruct
- self.name = name
- # The struct members, a dictionary of 'format'+'name' pairs
- self.members = members
-
-
- # Emits the packed definition of the struct, meant to be private
- def emit_packed(self, f):
- translations = { 'name' : self.name }
- template = (
- '\n'
- 'typedef struct _${name}Packed {\n')
- f.write(string.Template(template).substitute(translations))
-
- for var in self.members:
- translations['variable_type'] = var['format']
- translations['variable_name'] = utils.build_underscore_name(var['name'])
- template = (
- ' ${variable_type} ${variable_name};\n')
- f.write(string.Template(template).substitute(translations))
-
- template = ('} __attribute__((__packed__)) ${name}Packed;\n\n')
- f.write(string.Template(template).substitute(translations))
-
-
- # Emits the public non-packed definition of the struct
- def emit(self, f):
- translations = { 'name' : self.name }
- template = (
- '\n'
- 'typedef struct _${name} {\n')
- f.write(string.Template(template).substitute(translations))
-
- for var in self.members:
- translations['variable_type'] = var['public-format'] if 'public-format' in var else var['format']
- translations['variable_name'] = utils.build_underscore_name(var['name'])
- template = (
- ' ${variable_type} ${variable_name};\n')
- f.write(string.Template(template).substitute(translations))
-
- template = ('} ${name};\n\n')
- f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/TypeFactory.py b/build-aux/qmi-codegen/TypeFactory.py
new file mode 100644
index 0000000..302b666
--- /dev/null
+++ b/build-aux/qmi-codegen/TypeFactory.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil -*-
+#
+# 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
+#
+
+
+"""
+List to keep track of types already emitted to the source/header files.
+"""
+emitted_types = []
+
+"""
+Checks whether a given type has already been emitted.
+"""
+def is_type_emitted(type_name):
+ for i in emitted_types:
+ if i == type_name:
+ return True
+ else:
+ return False
+
+"""
+Sets the given type as already emitted.
+"""
+def set_type_emitted(type_name):
+ if is_type_emitted(type_name):
+ return False
+ else:
+ emitted_types.append(type_name)
+ return True
+
+
+
+"""
+List to keep track of type-specific get_printable() methods already emitted to
+the source/header files.
+"""
+emitted_get_printable = []
+
+"""
+Checks whether a given type-specific get_printable() has already been emitted.
+"""
+def is_get_printable_emitted(type_name):
+ for i in emitted_get_printable:
+ if i == type_name:
+ return True
+ else:
+ return False
+
+"""
+Sets the given type-specific get_printable() as already emitted.
+"""
+def set_get_printable_emitted(type_name):
+ if is_get_printable_emitted(type_name):
+ return False
+ else:
+ emitted_get_printable.append(type_name)
+ return True
diff --git a/build-aux/qmi-codegen/Variable.py b/build-aux/qmi-codegen/Variable.py
new file mode 100644
index 0000000..5d05ef8
--- /dev/null
+++ b/build-aux/qmi-codegen/Variable.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# -*- 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
+#
+
+import string
+import utils
+
+"""
+Base class for every variable type defined in the database
+"""
+class Variable:
+
+ """
+ Constructor with common variable handling
+ """
+ def __init__(self, dictionary):
+ """
+ Variables can define specific public and private formats to be used.
+ The public format will be that used in the generated interface file,
+ while the private one will only be used internally.
+ """
+ self.format = dictionary['format']
+ self.public_format = None
+ self.private_format = None
+
+ """
+ Variables that get allocated in heap need to get properly disposed.
+ """
+ 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.
+ """
+ def emit_types(self, f):
+ pass
+
+
+ """
+ Emits the code involved in reading the variable from the raw byte stream
+ into the specific private format.
+ """
+ def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ pass
+
+
+ """
+ Emits the code involved in writing the variable to the raw byte stream
+ from the specific private format.
+ """
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ pass
+
+
+ """
+ Emits the code to get the contents of the given variable as a printable string.
+ """
+ def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
+ pass
+
+ """
+ Emits the code to copy a variable into another one of the same type.
+ """
+ def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
+ pass
+
+ """
+ Emits the code to dispose the variable.
+ """
+ def emit_dispose(self, f, line_prefix, variable_name):
+ pass
diff --git a/build-aux/qmi-codegen/VariableArray.py b/build-aux/qmi-codegen/VariableArray.py
new file mode 100644
index 0000000..68674ed
--- /dev/null
+++ b/build-aux/qmi-codegen/VariableArray.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+# -*- 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
+#
+
+import string
+import utils
+from Variable import Variable
+import VariableFactory
+
+"""
+Variable type for Arrays ('array' format)
+"""
+class VariableArray(Variable):
+
+ """
+ Constructor
+ """
+ def __init__(self, dictionary, array_element_type):
+
+ # Call the parent constructor
+ Variable.__init__(self, dictionary)
+
+ self.private_format = 'GArray *'
+ self.public_format = self.private_format
+
+ # The array and its contents need to get disposed
+ self.needs_dispose = True
+
+ # Load variable type of this array
+ if 'name' in dictionary['array-element']:
+ self.array_element = VariableFactory.create_variable(dictionary['array-element'], array_element_type + ' ' + dictionary['array-element']['name'])
+ else:
+ self.array_element = VariableFactory.create_variable(dictionary['array-element'], '')
+
+
+ """
+ Emit the type for the array element
+ """
+ def emit_types(self, f):
+ self.array_element.emit_types(f)
+
+
+ """
+ Reading an array from the raw byte buffer is just about providing a loop to
+ read every array element one by one.
+ """
+ def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'private_format' : self.private_format,
+ 'public_array_element_format' : self.array_element.public_format,
+ 'variable_name' : variable_name,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len }
+
+ template = (
+ '${lp}{\n'
+ '${lp} guint i;\n'
+ '${lp} guint8 n_items;\n'
+ '\n'
+ '${lp} /* Read number of items in the array */\n'
+ '${lp} n_items = ${buffer_name}[0];\n'
+ '${lp} ${buffer_name}++;\n'
+ '${lp} ${buffer_len}--;\n'
+ '\n'
+ '${lp} ${variable_name} = g_array_sized_new (\n'
+ '${lp} FALSE,\n'
+ '${lp} FALSE,\n'
+ '${lp} sizeof (${public_array_element_format}),\n'
+ '${lp} n_items);\n'
+ '\n'
+ '${lp} for (i = 0; i < n_items; i++) {\n'
+ '${lp} ${public_array_element_format} aux;\n'
+ '\n')
+ f.write(string.Template(template).substitute(translations))
+
+ self.array_element.emit_buffer_read(f, line_prefix + ' ', 'aux', buffer_name, buffer_len)
+
+ template = (
+ '${lp} g_array_insert_val (${variable_name}, i, aux);\n'
+ '${lp} }\n'
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Writing an array to the raw byte buffer is just about providing a loop to
+ write every array element one by one.
+ """
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ raise RuntimeError('Not implemented yet')
+
+
+ """
+ The array will be printed as a list of fields enclosed between curly
+ brackets
+ """
+ def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'printable' : printable,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len }
+
+ template = (
+ '${lp}{\n'
+ '${lp} guint i;\n'
+ '${lp} guint8 n_items;\n'
+ '\n'
+ '${lp} /* Read number of items in the array */\n'
+ '${lp} n_items = ${buffer_name}[0];\n'
+ '${lp} ${buffer_name}++;\n'
+ '${lp} ${buffer_len}--;\n'
+ '\n'
+ '${lp} g_string_append (${printable}, "{");\n'
+ '\n'
+ '${lp} for (i = 0; i < n_items; i++) {\n'
+ '${lp} g_string_append_printf (${printable}, " [%u] = \'", i);\n')
+ f.write(string.Template(template).substitute(translations))
+
+ self.array_element.emit_get_printable(f, line_prefix + ' ', printable, buffer_name, buffer_len);
+
+ template = (
+ '${lp} g_string_append (${printable}, " \'");\n'
+ '${lp} }\n'
+ '\n'
+ '${lp} g_string_append (${printable}, "}");\n'
+ '${lp}}')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ GArrays are ref-counted, so we can just provide a new ref to the array.
+ """
+ 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 }
+
+ template = (
+ '${lp}${to} = g_array_ref (${from});\n')
+ f.write(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):
+ translations = { 'lp' : line_prefix,
+ 'variable_name' : variable_name }
+
+ 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))
+
+ self.array_element.emit_dispose(f, line_prefix, 'g_array_index (' + variable_name + ',' + self.array_element.public_format + ', i)')
+
+ template = (
+ '${lp} }\n'
+ '${lp}}')
+ f.write(string.Template(template).substitute(translations))
+
+
+ template = (
+ '${lp}g_array_unref (${variable_name});\n')
+ f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/ContainerInput.py b/build-aux/qmi-codegen/VariableFactory.py
index 7c15306..e8d9ba4 100644
--- a/build-aux/qmi-codegen/ContainerInput.py
+++ b/build-aux/qmi-codegen/VariableFactory.py
@@ -18,21 +18,25 @@
# Copyright (C) 2012 Lanedo GmbH
#
-import string
+import utils
+from VariableInteger import VariableInteger
+from VariableString import VariableString
+from VariableStruct import VariableStruct
+from VariableArray import VariableArray
-from Field import Field
-from Container import Container
-class ContainerInput(Container):
- """
- The ContainerInput class takes care of handling collections of Input
- fields
- """
-
- def __init__(self, prefix, dictionary, common_objects_dictionary):
-
- self.name = 'Input'
- self.readonly = False
-
- # Call the parent constructor
- Container.__init__(self, prefix, dictionary, common_objects_dictionary)
+"""
+Helps in the creation of Variable objects based on the specific 'format' found
+in the given dictionary
+"""
+def create_variable(dictionary, new_type_name):
+ if utils.format_is_integer(dictionary['format']):
+ return VariableInteger(dictionary)
+ elif dictionary['format'] == 'string':
+ return VariableString(dictionary)
+ elif dictionary['format'] == 'struct':
+ return VariableStruct(dictionary, new_type_name)
+ elif dictionary['format'] == 'array':
+ return VariableArray(dictionary, new_type_name)
+ else:
+ raise RuntimeError('Unexpected field format \'%s\'' % dictionary['format'])
diff --git a/build-aux/qmi-codegen/VariableInteger.py b/build-aux/qmi-codegen/VariableInteger.py
new file mode 100644
index 0000000..54b194e
--- /dev/null
+++ b/build-aux/qmi-codegen/VariableInteger.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+# -*- 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
+#
+
+import string
+import utils
+from Variable import Variable
+
+"""
+Variable type for signed/unsigned Integers
+('guint8', 'gint8', 'guint16', 'gint16', 'guint32', 'gint32' formats)
+"""
+class VariableInteger(Variable):
+
+ """
+ Constructor
+ """
+ def __init__(self, dictionary):
+
+ # Call the parent constructor
+ Variable.__init__(self, dictionary)
+
+ self.private_format = self.format
+ self.public_format = dictionary['public-format'] if 'public-format' in dictionary else self.private_format
+
+
+ """
+ Read a single integer from the raw byte buffer
+ """
+ def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'public_format' : self.public_format,
+ 'private_format' : self.private_format,
+ 'variable_name' : variable_name,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len }
+
+ if self.private_format == self.public_format:
+ template = (
+ '${lp}/* Read the ${private_format} variable from the buffer */\n'
+ '${lp}qmi_utils_read_${private_format}_from_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} &(${variable_name}));\n')
+ else:
+ template = (
+ '${lp}{\n'
+ '${lp} ${private_format} tmp;\n'
+ '\n'
+ '${lp} /* Read the ${private_format} variable from the buffer */\n'
+ '${lp} qmi_utils_read_${private_format}_from_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} &tmp);\n'
+ '${lp} ${variable_name} = (${public_format})tmp;\n'
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Write a single integer to the raw byte buffer
+ """
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'private_format' : self.private_format,
+ 'variable_name' : variable_name,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len }
+ if self.private_format == self.public_format:
+ template = (
+ '${lp}/* Write the ${private_format} variable to the buffer */\n'
+ '${lp}qmi_utils_write_${private_format}_to_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} &(${variable_name}));\n')
+ else:
+ template = (
+ '${lp}{\n'
+ '${lp} ${private_format} tmp;\n'
+ '\n'
+ '${lp} tmp = (${private_format})${variable_name};\n'
+ '${lp} /* Write the ${private_format} variable to the buffer */\n'
+ '${lp} qmi_utils_write_${private_format}_to_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} &tmp);\n'
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Get the integer as a printable string. Given that we support max 32-bit
+ integers, it is safe to cast all them to standard integers when printing.
+ """
+ def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
+ if utils.format_is_unsigned_integer(self.private_format):
+ common_format = '%u'
+ common_cast = 'guint'
+ else:
+ common_format = '%d'
+ common_cast = 'gint'
+
+ translations = { 'lp' : line_prefix,
+ 'private_format' : self.private_format,
+ 'printable' : printable,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len,
+ 'common_format' : common_format,
+ 'common_cast' : common_cast }
+
+ template = (
+ '\n'
+ '${lp}{\n'
+ '${lp} ${private_format} tmp;\n'
+ '\n'
+ '${lp} /* Read the ${private_format} variable from the buffer */\n'
+ '${lp} qmi_utils_read_${private_format}_from_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} &tmp);\n'
+ '\n'
+ '${lp} g_string_append_printf (${printable}, "${common_format}", (${common_cast})tmp);\n'
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Copy an integer to another one
+ """
+ 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 }
+
+ template = (
+ '${lp}${to} = ${from};\n')
+ f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/VariableString.py b/build-aux/qmi-codegen/VariableString.py
new file mode 100644
index 0000000..0c8abf4
--- /dev/null
+++ b/build-aux/qmi-codegen/VariableString.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# -*- 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
+#
+
+import string
+import utils
+from Variable import Variable
+
+"""
+Variable type for Strings ('string' format)
+"""
+class VariableString(Variable):
+
+ """
+ Constructor
+ """
+ def __init__(self, dictionary):
+
+ # Call the parent constructor
+ Variable.__init__(self, dictionary)
+
+ self.private_format = 'gchar *'
+ self.public_format = self.private_format
+
+ # 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
+
+
+ """
+ Read a string from the raw byte buffer.
+ """
+ def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'variable_name' : variable_name,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len,
+ 'length_prefix' : 'TRUE' if self.length_prefix else 'FALSE' }
+
+ template = (
+ '${lp}/* Read the string variable from the buffer */\n'
+ '${lp}qmi_utils_read_string_from_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} ${length_prefix},\n'
+ '${lp} &(${variable_name}));\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Write a string to the raw byte buffer.
+ """
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'variable_name' : variable_name,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len,
+ 'length_prefix' : 'TRUE' if self.length_prefix else 'FALSE' }
+
+ template = (
+ '${lp}/* Write the string variable to the buffer */\n'
+ '${lp}qmi_utils_write_string_to_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} ${length_prefix},\n'
+ '${lp} &(${variable_name}));\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Get the string as printable
+ """
+ def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'printable' : printable,
+ 'buffer_name' : buffer_name,
+ 'buffer_len' : buffer_len,
+ 'length_prefix' : 'TRUE' if self.length_prefix else 'FALSE' }
+
+ template = (
+ '\n'
+ '${lp}{\n'
+ '${lp} gchar *tmp;\n'
+ '\n'
+ '${lp} /* Read the string variable from the buffer */\n'
+ '${lp} qmi_utils_read_string_from_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} ${length_prefix},\n'
+ '${lp} &tmp);\n'
+ '\n'
+ '${lp} g_string_append_printf (${printable}, "%s", tmp);\n'
+ '${lp} g_free (tmp);\n'
+ '${lp}}\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Copy the string
+ """
+ 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 }
+
+ template = (
+ '${lp}${to} = g_strdup (${from});\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Dispose the string
+ """
+ def emit_dispose(self, f, 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))
diff --git a/build-aux/qmi-codegen/VariableStruct.py b/build-aux/qmi-codegen/VariableStruct.py
new file mode 100644
index 0000000..415ca7c
--- /dev/null
+++ b/build-aux/qmi-codegen/VariableStruct.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+# -*- 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
+#
+
+import string
+import utils
+from Variable import Variable
+import VariableFactory
+
+"""
+Variable type for Structs ('struct' format)
+"""
+class VariableStruct(Variable):
+
+ """
+ Constructor
+ """
+ def __init__(self, dictionary, struct_type_name):
+
+ # Call the parent constructor
+ Variable.__init__(self, dictionary)
+
+ # The public format of the struct is built directly from the suggested
+ # struct type name
+ self.public_format = utils.build_camelcase_name(struct_type_name)
+ self.private_format = self.public_format
+
+ # Load members of this struct
+ self.members = []
+ for member_dictionary in dictionary['contents']:
+ member = {}
+ member['name'] = utils.build_underscore_name(member_dictionary['name'])
+ member['object'] = VariableFactory.create_variable(member_dictionary, struct_type_name + ' ' + member['name'])
+ self.members.append(member)
+
+ # We'll need to dispose if at least one of the members needs it
+ for member in self.members:
+ if member['object'].needs_dispose == True:
+ self.needs_dispose = True
+
+
+ """
+ Emit all types for the members of the struct plus the new struct type itself
+ """
+ def emit_types(self, f):
+ # Emit types for each member
+ for member in self.members:
+ member['object'].emit_types(f)
+
+ translations = { 'format' : self.public_format }
+ template = (
+ '\n'
+ 'typedef struct _${format} {\n')
+ f.write(string.Template(template).substitute(translations))
+
+ for member in self.members:
+ translations['variable_format'] = member['object'].public_format
+ translations['variable_name'] = member['name']
+ template = (
+ ' ${variable_format} ${variable_name};\n')
+ f.write(string.Template(template).substitute(translations))
+
+ template = ('} ${format};\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ Reading the contents of a struct is just about reading each of the struct
+ fields one by one.
+ """
+ def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ for member in self.members:
+ member['object'].emit_buffer_read(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len)
+
+
+ """
+ Writing the contents of a struct is just about writing each of the struct
+ fields one by one.
+ """
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ for member in self.members:
+ member['object'].emit_buffer_write(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len)
+
+
+ """
+ The struct will be printed as a list of fields enclosed between square
+ brackets
+ """
+ def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
+ translations = { 'lp' : line_prefix,
+ 'printable' : printable }
+
+ template = (
+ '${lp}g_string_append (${printable}, "[");\n')
+ f.write(string.Template(template).substitute(translations))
+
+ for member in self.members:
+ translations['variable_name'] = member['name']
+ template = (
+ '${lp}g_string_append (${printable}, " ${variable_name} = \'");\n')
+ f.write(string.Template(template).substitute(translations))
+
+ member['object'].emit_get_printable(f, line_prefix, printable, buffer_name, buffer_len)
+
+ template = (
+ '${lp}g_string_append (${printable}, "\'");\n')
+ f.write(string.Template(template).substitute(translations))
+
+ template = (
+ '${lp}g_string_append (${printable}, " ]");\n')
+ f.write(string.Template(template).substitute(translations))
+
+
+ """
+ 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.
+ """
+ def emit_copy(self, f, line_prefix, variable_name_from, variable_name_to):
+ for member in self.members:
+ member['object'].emit_copy(f, line_prefix, variable_name_from + '.' + member['name'], variable_name_to + '.' + member['name'])
+
+
+ """
+ Disposing a struct is just about disposing each of the struct fields one by
+ one.
+ """
+ def emit_dispose(self, f, line_prefix, variable_name):
+ for member in self.members:
+ member['object'].emit_dispose(f, line_prefix, variable_name + '.' + member['name'])
diff --git a/build-aux/qmi-codegen/utils.py b/build-aux/qmi-codegen/utils.py
index a13443b..fe36c06 100644
--- a/build-aux/qmi-codegen/utils.py
+++ b/build-aux/qmi-codegen/utils.py
@@ -20,35 +20,47 @@
import string
+"""
+Add the common copyright header to the given file
+"""
def add_copyright(f):
- f.write("\n"
- "/* GENERATED CODE... DO NOT EDIT */\n"
- "\n"
- "/*\n"
- " * This library is free software; you can redistribute it and/or\n"
- " * modify it under the terms of the GNU Lesser General Public\n"
- " * License as published by the Free Software Foundation; either\n"
- " * version 2 of the License, or (at your option) any later version.\n"
- " *\n"
- " * This library is distributed in the hope that it will be useful,\n"
- " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
- " * Lesser General Public License for more details.\n"
- " *\n"
- " * You should have received a copy of the GNU Lesser General Public\n"
- " * License along with this library; if not, write to the\n"
- " * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n"
- " * Boston, MA 02110-1301 USA.\n"
- " *\n"
- " * Copyright (C) 2012 Lanedo GmbH\n"
- " */\n"
- "\n");
-
+ f.write(
+ "\n"
+ "/* GENERATED CODE... DO NOT EDIT */\n"
+ "\n"
+ "/*\n"
+ " * This library is free software; you can redistribute it and/or\n"
+ " * modify it under the terms of the GNU Lesser General Public\n"
+ " * License as published by the Free Software Foundation; either\n"
+ " * version 2 of the License, or (at your option) any later version.\n"
+ " *\n"
+ " * This library is distributed in the hope that it will be useful,\n"
+ " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ " * Lesser General Public License for more details.\n"
+ " *\n"
+ " * You should have received a copy of the GNU Lesser General Public\n"
+ " * License along with this library; if not, write to the\n"
+ " * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n"
+ " * Boston, MA 02110-1301 USA.\n"
+ " *\n"
+ " * Copyright (C) 2012 Lanedo GmbH\n"
+ " */\n"
+ "\n");
+
+
+"""
+Build a header guard string based on the given filename
+"""
def build_header_guard(output_name):
return "__LIBQMI_GLIB_" + string.upper(string.replace (output_name, '-', '_')) + "__"
+
+"""
+Write the common header start chunk
+"""
def add_header_start(f, output_name):
- template = string.Template (
+ template = string.Template(
"\n"
"#ifndef ${guard}\n"
"#define ${guard}\n"
@@ -65,6 +77,10 @@ def add_header_start(f, output_name):
"\n")
f.write(template.substitute(guard = build_header_guard(output_name)))
+
+"""
+Write the common header stop chunk
+"""
def add_header_stop(f, output_name):
template = string.Template (
"\n"
@@ -73,19 +89,10 @@ def add_header_stop(f, output_name):
"#endif /* ${guard} */\n")
f.write(template.substitute(guard = build_header_guard(output_name)))
-#def add_global_include(f, header):
-# template = string.Template (
-# "\n"
-# "#include <${header}>\n")
-# f.write(template.substitute(header = header))
-#
-#def add_local_include(f, header):
-# template = string.Template (
-# "\n"
-# "#include \"${header}\"\n")
-# f.write(template.substitute(header = header))
-
+"""
+Write the common source file start chunk
+"""
def add_source_start(f, output_name):
template = string.Template (
"\n"
@@ -102,6 +109,9 @@ def add_source_start(f, output_name):
f.write(template.substitute(name = output_name))
+"""
+Write a separator comment in the file
+"""
def add_separator(f, separator_type, separator_name):
template = string.Template (
"\n"
@@ -111,46 +121,27 @@ def add_separator(f, separator_type, separator_name):
f.write(template.substitute(type = separator_type,
name = separator_name))
+
+"""
+Build an underscore name from the given full name
+e.g.: "This is a message" --> "this_is_a_message"
+"""
def build_underscore_name(name):
return string.lower(string.replace (name, ' ', '_'))
+
+"""
+Build a camelcase name from the given full name
+e.g.: "This is a message" --> "ThisIsAMessage"
+"""
def build_camelcase_name(name):
return string.replace(string.capwords(name), ' ', '')
-#def emit_struct_type(f, struct_type, dictionary):
-# translations = { 'struct_type' : struct_type }
-# template = (
-# '\n'
-# 'typedef struct _${struct_type} {\n')
-# f.write(string.Template(template).substitute(translations))
-# for var in dictionary['contents']:
-# translations['variable_type'] = var['type']
-# translations['variable_name'] = build_underscore_name(var['name'])
-# template = (
-# ' ${variable_type} ${variable_name};\n')
-# f.write(string.Template(template).substitute(translations))
-# template = ('} __attribute__((__packed__)) ${struct_type};\n\n')
-# f.write(string.Template(template).substitute(translations))
-
-
-def he_from_le(input_variable, output_variable, variable_type):
- if variable_type == 'guint16':
- return '%s = GUINT16_FROM_LE (%s)' % (output_variable, input_variable)
- elif variable_type == 'guint32':
- return '%s = GUINT32_FROM_LE (%s)' % (output_variable, input_variable)
- if variable_type == 'gint16':
- return '%s = GINT16_FROM_LE (%s)' % (output_variable, input_variable)
- elif variable_type == 'gint32':
- return '%s = GINT32_FROM_LE (%s)' % (output_variable, input_variable)
- else:
- return '%s = %s' % (output_variable, input_variable)
-
-
-def le_from_he(input_variable, output_variable, variable_type):
- return he_from_le(input_variable, output_variable, variable_type)
-
-
+"""
+Read the contents of the JSON file, skipping lines prefixed with '//', which are
+considered comments.
+"""
def read_json_file(path):
f = open(path)
out = ''
@@ -162,3 +153,39 @@ def read_json_file(path):
else:
out += line
return out
+
+
+"""
+Returns True if the given format corresponds to a basic unsigned integer type
+"""
+def format_is_unsigned_integer(fmt):
+ if fmt == 'guint8' or \
+ fmt == 'guint16' or \
+ fmt == 'guint32':
+ return True
+ else:
+ return False
+
+
+"""
+Returns True if the given format corresponds to a basic signed integer type
+"""
+def format_is_signed_integer(fmt):
+ if fmt == 'gint8' or \
+ fmt == 'gint16' or \
+ fmt == 'gint32':
+ return True
+ else:
+ return False
+
+
+"""
+Returns True if the given format corresponds to a basic signed or unsigned
+integer type
+"""
+def format_is_integer(fmt):
+ if format_is_unsigned_integer(fmt) or \
+ format_is_signed_integer(fmt):
+ return True
+ else:
+ return False
diff --git a/src/qmi-message.c b/src/qmi-message.c
index 6a624e4..8d3abee 100644
--- a/src/qmi-message.c
+++ b/src/qmi-message.c
@@ -45,30 +45,30 @@
#define PACKED __attribute__((packed))
struct qmux {
- uint16_t length;
- uint8_t flags;
- uint8_t service;
- uint8_t client;
+ guint16 length;
+ guint8 flags;
+ guint8 service;
+ guint8 client;
} PACKED;
struct control_header {
- uint8_t flags;
- uint8_t transaction;
- uint16_t message;
- uint16_t tlv_length;
+ guint8 flags;
+ guint8 transaction;
+ guint16 message;
+ guint16 tlv_length;
} PACKED;
struct service_header {
- uint8_t flags;
- uint16_t transaction;
- uint16_t message;
- uint16_t tlv_length;
+ guint8 flags;
+ guint16 transaction;
+ guint16 message;
+ guint16 tlv_length;
} PACKED;
struct tlv {
- uint8_t type;
- uint16_t length;
- char value[];
+ guint8 type;
+ guint16 length;
+ guint8 value[];
} PACKED;
struct control_message {
@@ -82,7 +82,7 @@ struct service_message {
} PACKED;
struct full_message {
- uint8_t marker;
+ guint8 marker;
struct qmux qmux;
union {
struct control_message control;
@@ -105,7 +105,7 @@ qmi_message_get_qmux_length (QmiMessage *self)
static inline void
set_qmux_length (QmiMessage *self,
- uint16_t length)
+ guint16 length)
{
self->buf->qmux.length = GUINT16_TO_LE (length);
}
@@ -223,7 +223,7 @@ qmi_message_get_tlv_length (QmiMessage *self)
static void
set_qmi_message_get_tlv_length (QmiMessage *self,
- guint16 length)
+ guint16 length)
{
if (qmi_message_is_control (self))
self->buf->qmi.control.header.tlv_length = GUINT16_TO_LE (length);
@@ -240,16 +240,16 @@ qmi_tlv (QmiMessage *self)
return self->buf->qmi.service.tlv;
}
-static char *
+static guint8 *
qmi_end (QmiMessage *self)
{
- return (char *) self->buf + self->len;
+ return (guint8 *) self->buf + self->len;
}
static struct tlv *
tlv_next (struct tlv *tlv)
{
- return (struct tlv *)((char *)tlv + sizeof(struct tlv) + le16toh (tlv->length));
+ return (struct tlv *)((guint8 *)tlv + sizeof(struct tlv) + le16toh (tlv->length));
}
static struct tlv *
@@ -290,7 +290,7 @@ qmi_message_check (QmiMessage *self,
GError **error)
{
gsize header_length;
- gchar *end;
+ guint8 *end;
struct tlv *tlv;
g_assert (self != NULL);
@@ -407,7 +407,7 @@ qmi_message_new (QmiService service,
if (service == QMI_SERVICE_CTL) {
self->buf->qmi.control.header.flags = 0;
- self->buf->qmi.control.header.transaction = (uint8_t)transaction_id;
+ self->buf->qmi.control.header.transaction = (guint8)transaction_id;
self->buf->qmi.control.header.message = htole16 (message_id);
} else {
self->buf->qmi.service.header.flags = 0;
@@ -457,13 +457,12 @@ qmi_message_get_raw (QmiMessage *self,
return self->buf;
}
-static gboolean
-qmimsg_tlv_get_internal (QmiMessage *self,
- guint8 type,
- guint16 *length,
- gpointer value,
- gboolean length_exact,
- GError **error)
+gboolean
+qmi_message_tlv_get (QmiMessage *self,
+ guint8 type,
+ guint16 *length,
+ guint8 **value,
+ GError **error)
{
struct tlv *tlv;
@@ -474,27 +473,9 @@ qmimsg_tlv_get_internal (QmiMessage *self,
for (tlv = qmi_tlv_first (self); tlv; tlv = qmi_tlv_next (self, tlv)) {
if (tlv->type == type) {
- if (length_exact && (le16toh (tlv->length) != *length)) {
- g_set_error (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_TLV_NOT_FOUND,
- "TLV found but wrong length (%u != %u)",
- tlv->length,
- *length);
- return FALSE;
- } else if (value && le16toh (tlv->length) > *length) {
- g_set_error (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_TLV_TOO_LONG,
- "TLV found but too long (%u > %u)",
- le16toh (tlv->length),
- *length);
- return FALSE;
- }
-
- *length = le16toh (tlv->length);
+ *length = GUINT16_FROM_LE (tlv->length);
if (value)
- memcpy (value, tlv->value, le16toh (tlv->length));
+ *value = &(tlv->value[0]);
return TRUE;
}
}
@@ -506,49 +487,6 @@ qmimsg_tlv_get_internal (QmiMessage *self,
return FALSE;
}
-gboolean
-qmi_message_tlv_get (QmiMessage *self,
- guint8 type,
- guint16 length,
- gpointer value,
- GError **error)
-{
- return qmimsg_tlv_get_internal (self, type, &length, value, TRUE, error);
-}
-
-gboolean
-qmi_message_tlv_get_varlen (QmiMessage *self,
- guint8 type,
- guint16 *length,
- gpointer value,
- GError **error)
-{
- return qmimsg_tlv_get_internal (self, type, length, value, FALSE, error);
-}
-
-gchar *
-qmi_message_tlv_get_string (QmiMessage *self,
- guint8 type,
- GError **error)
-{
- uint16_t length;
- gchar *value;
-
- /* Read length only first */
- if (!qmi_message_tlv_get_varlen (self, type, &length, NULL, error))
- return NULL;
-
- /* Read exact length and value */
- value = g_malloc (length + 1);
- if (!qmi_message_tlv_get (self, type, length, value, error)) {
- g_free (value);
- return NULL;
- }
- value[length] = '\0';
-
- return value;
-}
-
void
qmi_message_tlv_foreach (QmiMessage *self,
QmiMessageForeachTlvFn callback,
@@ -610,8 +548,8 @@ qmi_message_tlv_add (QmiMessage *self,
memcpy (tlv->value, value, length);
/* Update length fields. */
- set_qmux_length (self, (uint16_t)(qmi_message_get_qmux_length (self) + tlv_len));
- set_qmi_message_get_tlv_length (self, (uint16_t)(qmi_message_get_tlv_length(self) + tlv_len));
+ set_qmux_length (self, (guint16)(qmi_message_get_qmux_length (self) + tlv_len));
+ set_qmi_message_get_tlv_length (self, (guint16)(qmi_message_get_tlv_length(self) + tlv_len));
/* Make sure we didn't break anything. */
if (!qmi_message_check (self, error)) {
diff --git a/src/qmi-message.h b/src/qmi-message.h
index 0aab9f9..ff64a91 100644
--- a/src/qmi-message.h
+++ b/src/qmi-message.h
@@ -56,20 +56,11 @@ void qmi_message_tlv_foreach (QmiMessage *self,
QmiMessageForeachTlvFn callback,
gpointer user_data);
-gboolean qmi_message_tlv_get (QmiMessage *self,
- guint8 type,
- guint16 length,
- gpointer value,
- GError **error);
-gboolean qmi_message_tlv_get_varlen (QmiMessage *self,
- guint8 type,
- guint16 *length,
- gpointer value,
- GError **error);
-gchar *qmi_message_tlv_get_string (QmiMessage *self,
- guint8 type,
- GError **error);
-
+gboolean qmi_message_tlv_get (QmiMessage *self,
+ guint8 type,
+ guint16 *length,
+ guint8 **value,
+ GError **error);
gboolean qmi_message_tlv_add (QmiMessage *self,
guint8 type,
diff --git a/src/qmi-utils.c b/src/qmi-utils.c
index 2a5aed8..d1e50f0 100644
--- a/src/qmi-utils.c
+++ b/src/qmi-utils.c
@@ -60,3 +60,253 @@ qmi_utils_str_hex (gconstpointer mem,
/* Set output string */
return new_str;
}
+
+void
+qmi_utils_read_guint8_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint8 *out)
+{
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 1);
+
+ *out = (*buffer)[0];
+
+ *buffer = &((*buffer)[1]);
+ *buffer_size = (*buffer_size) - 1;
+}
+
+void
+qmi_utils_read_gint8_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint8 *out)
+{
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 1);
+
+ *out = *((gint8 *)(&((*buffer)[0])));
+
+ *buffer = &((*buffer)[1]);
+ *buffer_size = (*buffer_size) - 1;
+}
+
+void
+qmi_utils_read_guint16_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint16 *out)
+{
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 2);
+
+ *out = GUINT16_FROM_LE (*((guint16 *)&((*buffer)[0])));
+
+ *buffer = &((*buffer)[2]);
+ *buffer_size = (*buffer_size) - 2;
+}
+
+void
+qmi_utils_read_gint16_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint16 *out)
+{
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 2);
+
+ *out = GINT16_FROM_LE (*((guint16 *)&((*buffer)[0])));
+
+ *buffer = &((*buffer)[2]);
+ *buffer_size = (*buffer_size) - 2;
+}
+
+void
+qmi_utils_read_guint32_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint32 *out)
+{
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 4);
+
+ *out = GUINT32_FROM_LE (*((guint32 *)&((*buffer)[0])));
+
+ *buffer = &((*buffer)[4]);
+ *buffer_size = (*buffer_size) - 4;
+}
+
+void
+qmi_utils_read_gint32_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint32 *out)
+{
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 4);
+
+ *out = GUINT32_FROM_LE (*((guint32 *)&((*buffer)[0])));
+
+ *buffer = &((*buffer)[4]);
+ *buffer_size = (*buffer_size) - 4;
+}
+
+void
+qmi_utils_write_guint8_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint8 *in)
+{
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 1);
+
+ (*buffer)[0] = *in;
+
+ *buffer = &((*buffer)[1]);
+ *buffer_size = (*buffer_size) - 1;
+}
+
+void
+qmi_utils_write_gint8_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint8 *in)
+{
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 1);
+
+ *((gint8 *)(&((*buffer)[0]))) = *in;
+
+ *buffer = &((*buffer)[1]);
+ *buffer_size = (*buffer_size) - 1;
+}
+
+void
+qmi_utils_write_guint16_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint16 *in)
+{
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 2);
+
+ *((guint16 *)(&((*buffer)[0]))) = GUINT16_TO_LE (*in);
+
+ *buffer = &((*buffer)[2]);
+ *buffer_size = (*buffer_size) - 2;
+}
+
+void
+qmi_utils_write_gint16_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint16 *in)
+{
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 2);
+
+ *((gint16 *)(&((*buffer)[0]))) = GINT16_TO_LE (*in);
+
+ *buffer = &((*buffer)[2]);
+ *buffer_size = (*buffer_size) - 2;
+}
+
+void
+qmi_utils_write_guint32_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint32 *in)
+{
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 4);
+
+ *((guint32 *)(&((*buffer)[0]))) = GUINT32_TO_LE (*in);
+
+ *buffer = &((*buffer)[4]);
+ *buffer_size = (*buffer_size) - 4;
+}
+
+void
+qmi_utils_write_gint32_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint32 *in)
+{
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+ g_assert (*buffer_size >= 4);
+
+ *((gint32 *)(&((*buffer)[0]))) = GINT32_TO_LE (*in);
+
+ *buffer = &((*buffer)[4]);
+ *buffer_size = (*buffer_size) - 4;
+}
+
+void
+qmi_utils_read_string_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gboolean length_prefix,
+ gchar **out)
+{
+ guint16 string_length;
+
+ g_assert (out != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+
+ /* If no length prefix given, read the whole buffer into a string */
+ if (!length_prefix)
+ string_length = *buffer_size;
+ else {
+ /* We assume the length prefix is always a guint8 */
+ guint8 string_length_8;
+
+ qmi_utils_read_guint8_from_buffer (buffer, buffer_size, &string_length_8);
+ string_length = string_length_8;
+ }
+
+ *out = g_malloc (string_length + 1);
+ (*out)[string_length] = '\0';
+ memcpy (*out, *buffer, string_length);
+
+ *buffer = &((*buffer)[string_length]);
+ *buffer_size = (*buffer_size) - string_length;
+}
+
+void
+qmi_utils_write_string_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gboolean length_prefix,
+ gchar **in)
+{
+ guint16 len;
+
+ g_assert (in != NULL);
+ g_assert (buffer != NULL);
+ g_assert (buffer_size != NULL);
+
+ len = (guint16) strlen (*in);
+
+ if (length_prefix) {
+ guint8 len_8;
+
+ g_warn_if_fail (len <= G_MAXUINT8);
+ len_8 = (guint8)len;
+ qmi_utils_write_guint8_to_buffer (buffer, buffer_size, &len_8);
+ }
+
+ memcpy (*buffer, *in, len);
+ *buffer = &((*buffer)[len]);
+ *buffer_size = (*buffer_size) - len;
+}
diff --git a/src/qmi-utils.h b/src/qmi-utils.h
index f1a2f27..7c098a0 100644
--- a/src/qmi-utils.h
+++ b/src/qmi-utils.h
@@ -34,6 +34,62 @@ gchar *qmi_utils_str_hex (gconstpointer mem,
gsize size,
gchar delimiter);
+/* Reading/Writing integer variables */
+
+void qmi_utils_read_guint8_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint8 *out);
+void qmi_utils_read_gint8_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint8 *out);
+
+void qmi_utils_read_guint16_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint16 *out);
+void qmi_utils_read_gint16_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint16 *out);
+
+void qmi_utils_read_guint32_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint32 *out);
+void qmi_utils_read_gint32_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint32 *out);
+
+void qmi_utils_write_guint8_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint8 *in);
+void qmi_utils_write_gint8_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint8 *in);
+
+void qmi_utils_write_guint16_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint16 *in);
+void qmi_utils_write_gint16_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint16 *in);
+
+void qmi_utils_write_guint32_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ guint32 *in);
+void qmi_utils_write_gint32_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gint32 *in);
+
+/* Reading/Writing string variables */
+
+void qmi_utils_read_string_from_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gboolean length_prefix,
+ gchar **out);
+
+void qmi_utils_write_string_to_buffer (guint8 **buffer,
+ guint16 *buffer_size,
+ gboolean length_prefix,
+ gchar **in);
+
G_END_DECLS
#endif /* _LIBQMI_GLIB_QMI_UTILS_H_ */