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.
2012-05-30 10:40:46 +00:00
|
|
|
#!/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
|
|
|
|
|
|
|
|
"""
|
2014-05-27 12:02:12 +00:00
|
|
|
Variable type for signed/unsigned Integers and floating point numbers:
|
|
|
|
'guint8', 'gint8'
|
|
|
|
'guint16', 'gint16'
|
|
|
|
'guint32', 'gint32'
|
|
|
|
'guint64', 'gint64'
|
|
|
|
'guint-sized'
|
|
|
|
'gfloat'
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
"""
|
|
|
|
class VariableInteger(Variable):
|
|
|
|
|
|
|
|
"""
|
|
|
|
Constructor
|
|
|
|
"""
|
|
|
|
def __init__(self, dictionary):
|
|
|
|
|
|
|
|
# Call the parent constructor
|
|
|
|
Variable.__init__(self, dictionary)
|
|
|
|
|
2012-07-04 13:59:23 +00:00
|
|
|
self.guint_sized_size = ''
|
|
|
|
if self.format == "guint-sized":
|
|
|
|
if 'guint-size' not in dictionary:
|
|
|
|
raise RuntimeError('Format \'guint-sized\' requires \'guint-size\' parameter')
|
|
|
|
else:
|
|
|
|
self.guint_sized_size = dictionary['guint-size']
|
|
|
|
self.private_format = 'guint64'
|
|
|
|
self.public_format = 'guint64'
|
|
|
|
else:
|
|
|
|
self.private_format = self.format
|
|
|
|
self.public_format = dictionary['public-format'] if 'public-format' in dictionary else self.private_format
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
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,
|
2012-07-04 13:59:23 +00:00
|
|
|
'len' : self.guint_sized_size,
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'variable_name' : variable_name,
|
|
|
|
'buffer_name' : buffer_name,
|
2012-10-20 00:26:15 +00:00
|
|
|
'buffer_len' : buffer_len,
|
|
|
|
'endian' : self.endian }
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
|
2012-07-04 13:59:23 +00:00
|
|
|
if self.format == 'guint-sized':
|
|
|
|
template = (
|
|
|
|
'${lp}/* Read the ${len}-byte long variable from the buffer */\n'
|
|
|
|
'${lp}qmi_utils_read_sized_guint_from_buffer (\n'
|
|
|
|
'${lp} &${buffer_name},\n'
|
|
|
|
'${lp} &${buffer_len},\n'
|
|
|
|
'${lp} ${len},\n'
|
2012-10-20 00:26:15 +00:00
|
|
|
'${lp} ${endian},\n'
|
2012-07-04 13:59:23 +00:00
|
|
|
'${lp} &(${variable_name}));\n')
|
|
|
|
elif self.private_format == self.public_format:
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
template = (
|
|
|
|
'${lp}/* Read the ${private_format} variable from the buffer */\n'
|
|
|
|
'${lp}qmi_utils_read_${private_format}_from_buffer (\n'
|
|
|
|
'${lp} &${buffer_name},\n'
|
2012-10-29 10:44:24 +00:00
|
|
|
'${lp} &${buffer_len},\n')
|
2014-05-27 12:02:12 +00:00
|
|
|
if self.private_format != 'guint8' and self.private_format != 'gint8' and self.private_format != 'gfloat':
|
2012-10-29 10:44:24 +00:00
|
|
|
template += (
|
|
|
|
'${lp} ${endian},\n')
|
|
|
|
template += (
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'${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'
|
2012-10-29 10:44:24 +00:00
|
|
|
'${lp} &${buffer_len},\n')
|
|
|
|
if self.private_format != 'guint8' and self.private_format != 'gint8':
|
|
|
|
template += (
|
|
|
|
'${lp} ${endian},\n')
|
|
|
|
template += (
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'${lp} &tmp);\n'
|
|
|
|
'${lp} ${variable_name} = (${public_format})tmp;\n'
|
|
|
|
'${lp}}\n')
|
|
|
|
f.write(string.Template(template).substitute(translations))
|
|
|
|
|
|
|
|
|
2012-10-30 14:08:02 +00:00
|
|
|
"""
|
|
|
|
Emits the code involved in computing the size of the variable.
|
|
|
|
"""
|
|
|
|
def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'len' : self.guint_sized_size,
|
|
|
|
'variable_name' : variable_name }
|
|
|
|
template = ''
|
|
|
|
if self.format == 'guint-sized':
|
|
|
|
template += (
|
|
|
|
'${lp}${variable_name} += ${len};\n')
|
|
|
|
elif self.private_format == 'guint8' or self.private_format == 'gint8':
|
|
|
|
template += (
|
|
|
|
'${lp}${variable_name} += 1;\n')
|
|
|
|
elif self.private_format == 'guint16' or self.private_format == 'gint16':
|
|
|
|
template += (
|
|
|
|
'${lp}${variable_name} += 2;\n')
|
2014-05-27 12:02:12 +00:00
|
|
|
elif self.private_format == 'guint32' or self.private_format == 'gint32' or self.private_format == 'gfloat':
|
2012-10-30 14:08:02 +00:00
|
|
|
template += (
|
|
|
|
'${lp}${variable_name} += 4;\n')
|
|
|
|
elif self.private_format == 'guint64' or self.private_format == 'gint64':
|
|
|
|
template += (
|
|
|
|
'${lp}${variable_name} += 8;\n')
|
|
|
|
f.write(string.Template(template).substitute(translations))
|
|
|
|
|
|
|
|
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
"""
|
|
|
|
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,
|
2012-07-04 13:59:23 +00:00
|
|
|
'len' : self.guint_sized_size,
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'variable_name' : variable_name,
|
|
|
|
'buffer_name' : buffer_name,
|
2012-10-20 00:26:15 +00:00
|
|
|
'buffer_len' : buffer_len,
|
|
|
|
'endian' : self.endian }
|
2012-07-04 13:59:23 +00:00
|
|
|
|
|
|
|
if self.format == 'guint-sized':
|
|
|
|
template = (
|
|
|
|
'${lp}/* Write the ${len}-byte long variable to the buffer */\n'
|
|
|
|
'${lp}qmi_utils_write_sized_guint_to_buffer (\n'
|
|
|
|
'${lp} &${buffer_name},\n'
|
|
|
|
'${lp} &${buffer_len},\n'
|
|
|
|
'${lp} ${len},\n'
|
2012-10-20 00:26:15 +00:00
|
|
|
'${lp} ${endian},\n'
|
2012-07-04 13:59:23 +00:00
|
|
|
'${lp} &(${variable_name}));\n')
|
|
|
|
elif self.private_format == self.public_format:
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
template = (
|
|
|
|
'${lp}/* Write the ${private_format} variable to the buffer */\n'
|
|
|
|
'${lp}qmi_utils_write_${private_format}_to_buffer (\n'
|
|
|
|
'${lp} &${buffer_name},\n'
|
2012-10-29 10:44:24 +00:00
|
|
|
'${lp} &${buffer_len},\n')
|
|
|
|
if self.private_format != 'guint8' and self.private_format != 'gint8':
|
|
|
|
template += (
|
|
|
|
'${lp} ${endian},\n')
|
|
|
|
template += (
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'${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'
|
2012-10-29 10:44:24 +00:00
|
|
|
'${lp} &${buffer_len},\n')
|
|
|
|
if self.private_format != 'guint8' and self.private_format != 'gint8':
|
|
|
|
template += (
|
|
|
|
'${lp} ${endian},\n')
|
|
|
|
template += (
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'${lp} &tmp);\n'
|
|
|
|
'${lp}}\n')
|
|
|
|
f.write(string.Template(template).substitute(translations))
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
2012-07-04 10:02:15 +00:00
|
|
|
Get the integer as a printable string.
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
"""
|
|
|
|
def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
|
2012-07-04 10:02:15 +00:00
|
|
|
common_format = ''
|
|
|
|
common_cast = ''
|
2012-11-02 12:13:47 +00:00
|
|
|
|
2012-07-04 10:02:15 +00:00
|
|
|
if self.private_format == 'guint8':
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
common_format = '%u'
|
2012-07-04 10:02:15 +00:00
|
|
|
common_cast = '(guint)'
|
|
|
|
elif self.private_format == 'guint16':
|
|
|
|
common_format = '%" G_GUINT16_FORMAT "'
|
|
|
|
elif self.private_format == 'guint32':
|
|
|
|
common_format = '%" G_GUINT32_FORMAT "'
|
|
|
|
elif self.private_format == 'guint64':
|
|
|
|
common_format = '%" G_GUINT64_FORMAT "'
|
|
|
|
elif self.private_format == 'gint8':
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
common_format = '%d'
|
2012-07-04 10:02:15 +00:00
|
|
|
common_cast = '(gint)'
|
|
|
|
elif self.private_format == 'gint16':
|
|
|
|
common_format = '%" G_GINT16_FORMAT "'
|
|
|
|
elif self.private_format == 'gint32':
|
|
|
|
common_format = '%" G_GINT32_FORMAT "'
|
|
|
|
elif self.private_format == 'gint64':
|
|
|
|
common_format = '%" G_GINT64_FORMAT "'
|
2014-05-27 12:02:12 +00:00
|
|
|
elif self.private_format == 'gfloat':
|
|
|
|
common_format = '%f'
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'private_format' : self.private_format,
|
2012-11-02 12:13:47 +00:00
|
|
|
'public_format' : self.public_format,
|
2012-07-04 13:59:23 +00:00
|
|
|
'len' : self.guint_sized_size,
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
'printable' : printable,
|
|
|
|
'buffer_name' : buffer_name,
|
|
|
|
'buffer_len' : buffer_len,
|
|
|
|
'common_format' : common_format,
|
2012-10-20 00:26:15 +00:00
|
|
|
'common_cast' : common_cast,
|
|
|
|
'endian' : self.endian }
|
2012-11-02 12:13:47 +00:00
|
|
|
template = (
|
|
|
|
'\n'
|
|
|
|
'${lp}{\n'
|
|
|
|
'${lp} ${private_format} tmp;\n'
|
|
|
|
'\n')
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
|
2012-07-04 13:59:23 +00:00
|
|
|
if self.format == 'guint-sized':
|
2012-11-02 12:13:47 +00:00
|
|
|
template += (
|
2012-07-04 13:59:23 +00:00
|
|
|
'${lp} /* Read the ${len}-byte long variable from the buffer */\n'
|
|
|
|
'${lp} qmi_utils_read_sized_guint_from_buffer (\n'
|
|
|
|
'${lp} &${buffer_name},\n'
|
|
|
|
'${lp} &${buffer_len},\n'
|
|
|
|
'${lp} ${len},\n'
|
2012-10-20 00:26:15 +00:00
|
|
|
'${lp} ${endian},\n'
|
2012-07-04 13:59:23 +00:00
|
|
|
'${lp} &tmp);\n'
|
2012-11-02 12:13:47 +00:00
|
|
|
'\n')
|
2012-07-04 13:59:23 +00:00
|
|
|
else:
|
2012-11-02 12:13:47 +00:00
|
|
|
template += (
|
2012-07-04 13:59:23 +00:00
|
|
|
'${lp} /* Read the ${private_format} variable from the buffer */\n'
|
|
|
|
'${lp} qmi_utils_read_${private_format}_from_buffer (\n'
|
|
|
|
'${lp} &${buffer_name},\n'
|
2012-10-29 10:44:24 +00:00
|
|
|
'${lp} &${buffer_len},\n')
|
2014-05-27 12:02:12 +00:00
|
|
|
if self.private_format != 'guint8' and self.private_format != 'gint8' and self.private_format != 'gfloat':
|
2012-10-29 10:44:24 +00:00
|
|
|
template += (
|
|
|
|
'${lp} ${endian},\n')
|
|
|
|
template += (
|
2012-07-04 13:59:23 +00:00
|
|
|
'${lp} &tmp);\n'
|
2012-11-02 12:13:47 +00:00
|
|
|
'\n')
|
|
|
|
|
|
|
|
if self.public_format == 'gboolean':
|
|
|
|
template += (
|
|
|
|
'${lp} g_string_append_printf (${printable}, "%s", tmp ? "yes" : "no");\n')
|
|
|
|
elif self.public_format != self.private_format:
|
|
|
|
translations['public_type_underscore'] = utils.build_underscore_name_from_camelcase(self.public_format)
|
2012-12-17 17:37:31 +00:00
|
|
|
translations['public_type_underscore_upper'] = utils.build_underscore_name_from_camelcase(self.public_format).upper()
|
2012-11-02 12:13:47 +00:00
|
|
|
template += (
|
|
|
|
'#if defined __${public_type_underscore_upper}_IS_ENUM__\n'
|
|
|
|
'${lp} g_string_append_printf (${printable}, "%s", ${public_type_underscore}_get_string ((${public_format})tmp));\n'
|
|
|
|
'#elif defined __${public_type_underscore_upper}_IS_FLAGS__\n'
|
|
|
|
'${lp} {\n'
|
|
|
|
'${lp} gchar *flags_str;\n'
|
2012-07-04 13:59:23 +00:00
|
|
|
'\n'
|
2012-11-02 12:13:47 +00:00
|
|
|
'${lp} flags_str = ${public_type_underscore}_build_string_from_mask ((${public_format})tmp);\n'
|
|
|
|
'${lp} g_string_append_printf (${printable}, "%s", flags_str);\n'
|
|
|
|
'${lp} g_free (flags_str);\n'
|
|
|
|
'${lp} }\n'
|
|
|
|
'#else\n'
|
|
|
|
'# error unexpected public format: ${public_format}\n'
|
|
|
|
'#endif\n')
|
|
|
|
else:
|
|
|
|
template += (
|
|
|
|
'${lp} g_string_append_printf (${printable}, "${common_format}", ${common_cast}tmp);\n')
|
|
|
|
|
|
|
|
template += (
|
|
|
|
'${lp}}\n')
|
|
|
|
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
f.write(string.Template(template).substitute(translations))
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
2012-07-03 11:58:52 +00:00
|
|
|
Variable declaration
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
"""
|
2012-07-03 11:58:52 +00:00
|
|
|
def build_variable_declaration(self, line_prefix, variable_name):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'private_format' : self.private_format,
|
|
|
|
'name' : variable_name }
|
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.
2012-05-30 10:40:46 +00:00
|
|
|
|
|
|
|
template = (
|
2012-07-03 11:58:52 +00:00
|
|
|
'${lp}${private_format} ${name};\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
Getter for the integer type
|
|
|
|
"""
|
|
|
|
def build_getter_declaration(self, line_prefix, variable_name):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'public_format' : self.public_format,
|
|
|
|
'name' : variable_name }
|
|
|
|
|
|
|
|
template = (
|
|
|
|
'${lp}${public_format} *${name},\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
Documentation for the getter
|
|
|
|
"""
|
|
|
|
def build_getter_documentation(self, line_prefix, variable_name):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'public_format' : self.public_format,
|
|
|
|
'name' : variable_name }
|
|
|
|
|
|
|
|
template = (
|
2012-10-08 11:28:28 +00:00
|
|
|
'${lp}@${name}: a placeholder for the output #${public_format}, or %NULL if not required.\n')
|
2012-07-03 11:58:52 +00:00
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
|
|
|
|
"""
|
|
|
|
Builds the Integer getter implementation
|
|
|
|
"""
|
|
|
|
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
|
|
|
|
needs_cast = True if self.public_format != self.private_format else False
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'from' : variable_name_from,
|
|
|
|
'to' : variable_name_to,
|
|
|
|
'cast_ini' : '(' + self.public_format + ')(' if needs_cast else '',
|
|
|
|
'cast_end' : ')' if needs_cast else '' }
|
|
|
|
|
|
|
|
if to_is_reference:
|
|
|
|
template = (
|
|
|
|
'${lp}if (${to})\n'
|
|
|
|
'${lp} *${to} = ${cast_ini}${from}${cast_end};\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
else:
|
|
|
|
template = (
|
|
|
|
'${lp}${to} = ${cast_ini}${from}${cast_end};\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
Setter for the integer type
|
|
|
|
"""
|
|
|
|
def build_setter_declaration(self, line_prefix, variable_name):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'public_format' : self.public_format,
|
|
|
|
'name' : variable_name }
|
|
|
|
|
|
|
|
template = (
|
|
|
|
'${lp}${public_format} ${name},\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
Documentation for the setter
|
|
|
|
"""
|
|
|
|
def build_setter_documentation(self, line_prefix, variable_name):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'public_format' : self.public_format,
|
|
|
|
'name' : variable_name }
|
|
|
|
|
|
|
|
template = (
|
|
|
|
'${lp}@${name}: a #${public_format}.\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
Implementation of the setter
|
|
|
|
"""
|
|
|
|
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
|
|
|
|
needs_cast = True if self.public_format != self.private_format else False
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'from' : variable_name_from,
|
|
|
|
'to' : variable_name_to,
|
|
|
|
'cast_ini' : '(' + self.private_format + ')(' if needs_cast else '',
|
|
|
|
'cast_end' : ')' if needs_cast else '' }
|
|
|
|
|
|
|
|
template = (
|
|
|
|
'${lp}${to} = ${cast_ini}${from}${cast_end};\n')
|
|
|
|
return string.Template(template).substitute(translations)
|
2012-10-08 11:28:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
Documentation for the struct field
|
|
|
|
"""
|
|
|
|
def build_struct_field_documentation(self, line_prefix, variable_name):
|
|
|
|
translations = { 'lp' : line_prefix,
|
|
|
|
'public_format' : self.public_format,
|
|
|
|
'name' : variable_name }
|
|
|
|
|
|
|
|
template = (
|
|
|
|
'${lp}@${name}: a #${public_format}.\n')
|
|
|
|
return string.Template(template).substitute(translations)
|