blob: 7e977c224305b3c613deb45d52283bb1a458b568 [file] [log] [blame]
#!/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
if 'fixed-size' in dictionary:
self.is_fixed_size = True
# Fixed-size strings
self.needs_dispose = False
self.length_prefix_size = 0
self.fixed_size = dictionary['fixed-size']
self.max_size = ''
else:
self.is_fixed_size = False
# Variable-length strings in heap
self.needs_dispose = True
# Strings which are given as the full value of a TLV will NOT have a
# length prefix
if 'type' in dictionary and dictionary['type'] == 'TLV':
self.length_prefix_size = 0
elif 'size-prefix-format' in dictionary:
if dictionary['size-prefix-format'] == 'guint8':
self.length_prefix_size = 8
elif dictionary['size-prefix-format'] == 'guint16':
self.length_prefix_size = 16
else:
raise ValueError('Invalid size prefix format (%s): not guint8 or guint16' % dictionary['size-prefix-format'])
else:
# Default to UINT8
self.length_prefix_size = 8
self.fixed_size = ''
self.max_size = dictionary['max-size'] if 'max-size' in dictionary else ''
"""
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 }
if self.is_fixed_size:
translations['fixed_size'] = self.fixed_size
template = (
'${lp}/* Read the fixed-size string variable from the buffer */\n'
'${lp}qmi_utils_read_fixed_size_string_from_buffer (\n'
'${lp} &${buffer_name},\n'
'${lp} &${buffer_len},\n'
'${lp} ${fixed_size},\n'
'${lp} &${variable_name}[0]);\n'
'${lp}${variable_name}[${fixed_size}] = \'\\0\';\n')
else:
translations['length_prefix_size'] = self.length_prefix_size
translations['max_size'] = self.max_size if self.max_size != '' else '0'
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_size},\n'
'${lp} ${max_size},\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 }
if self.is_fixed_size:
translations['fixed_size'] = self.fixed_size
template = (
'${lp}/* Write the fixed-size string variable to the buffer */\n'
'${lp}qmi_utils_write_fixed_size_string_to_buffer (\n'
'${lp} &${buffer_name},\n'
'${lp} &${buffer_len},\n'
'${lp} ${fixed_size},\n'
'${lp} ${variable_name});\n')
else:
translations['length_prefix_size'] = self.length_prefix_size
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_size},\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 }
if self.is_fixed_size:
translations['fixed_size'] = self.fixed_size
translations['fixed_size_plus_one'] = int(self.fixed_size) + 1
template = (
'\n'
'${lp}{\n'
'${lp} gchar tmp[${fixed_size_plus_one}];\n'
'\n'
'${lp} /* Read the fixed-size string variable from the buffer */\n'
'${lp} qmi_utils_read_fixed_size_string_from_buffer (\n'
'${lp} &${buffer_name},\n'
'${lp} &${buffer_len},\n'
'${lp} ${fixed_size},\n'
'${lp} &tmp[0]);\n'
'${lp} tmp[${fixed_size}] = \'\\0\';\n'
'\n'
'${lp} g_string_append_printf (${printable}, "%s", tmp);\n'
'${lp}}\n')
else:
translations['length_prefix_size'] = self.length_prefix_size
translations['max_size'] = self.max_size if self.max_size != '' else '0'
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_size},\n'
'${lp} ${max_size},\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))
"""
Variable declaration
"""
def build_variable_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
if self.is_fixed_size:
translations['fixed_size_plus_one'] = int(self.fixed_size) + 1
template = (
'${lp}gchar ${name}[${fixed_size_plus_one}];\n')
else:
template = (
'${lp}gchar *${name};\n')
return string.Template(template).substitute(translations)
"""
Getter for the string type
"""
def build_getter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}const gchar **${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the getter
"""
def build_getter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output constant string, or #NULL if not required.\n')
return string.Template(template).substitute(translations)
"""
Builds the String getter implementation
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
if to_is_reference:
template = (
'${lp}if (${to})\n'
'${lp} *${to} = ${from};\n')
return string.Template(template).substitute(translations)
else:
template = (
'${lp}${to} = ${from};\n')
return string.Template(template).substitute(translations)
"""
Setter for the string type
"""
def build_setter_declaration(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
template = (
'${lp}const gchar *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the setter
"""
def build_setter_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'name' : variable_name }
if self.is_fixed_size:
translations['fixed_size'] = self.fixed_size
template = (
'${lp}@${name}: a constant string of exactly ${fixed_size} characters.\n')
elif self.max_size != '':
translations['max_size'] = self.max_size
template = (
'${lp}@${name}: a constant string with a maximum length of ${max_size} characters.\n')
else:
template = (
'${lp}@${name}: a constant string.\n')
return string.Template(template).substitute(translations)
"""
Builds the String setter implementation
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
if self.is_fixed_size:
translations['fixed_size'] = self.fixed_size
template = (
'${lp}if (!${from} || strlen (${from}) != ${fixed_size}) {\n'
'${lp} g_set_error (error,\n'
'${lp} QMI_CORE_ERROR,\n'
'${lp} QMI_CORE_ERROR_INVALID_ARGS,\n'
'${lp} "Input variable \'${from}\' must be ${fixed_size} characters long");\n'
'${lp} return FALSE;\n'
'${lp}}\n'
'${lp}memcpy (${to}, ${from}, ${fixed_size});\n'
'${lp}${to}[${fixed_size}] = \'\\0\';\n')
else:
template = ''
if self.max_size != '':
translations['max_size'] = self.max_size
template += (
'${lp}if (${from} && strlen (${from}) > ${max_size}) {\n'
'${lp} g_set_error (error,\n'
'${lp} QMI_CORE_ERROR,\n'
'${lp} QMI_CORE_ERROR_INVALID_ARGS,\n'
'${lp} "Input variable \'${from}\' must be less than ${max_size} characters long");\n'
'${lp} return FALSE;\n'
'${lp}}\n')
template += (
'${lp}g_free (${to});\n'
'${lp}${to} = g_strdup (${from} ? ${from} : "");\n')
return string.Template(template).substitute(translations)
"""
Dispose the string
"""
def build_dispose(self, line_prefix, variable_name):
# Fixed-size strings don't need dispose
if self.is_fixed_size:
return ''
translations = { 'lp' : line_prefix,
'variable_name' : variable_name }
template = (
'${lp}g_free (${variable_name});\n')
return string.Template(template).substitute(translations)