# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright (C) 2012 Lanedo GmbH
# Copyright (C) 2012-2017 Aleksander Morgado <aleksander@aleksander.es>
#
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, container_type):
# 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
self.container_type = container_type
# 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.container_type)
# Specify that the variable will be defined in the public header
member['object'].flag_public()
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, since):
# Emit types for each member
for member in self.members:
member['object'].emit_types(f, since)
translations = { 'format' : self.public_format,
'since' : since }
template = (
'\n'
'/**\n'
' * ${format}:\n')
f.write(string.Template(template).substitute(translations))
for member in self.members:
f.write(member['object'].build_struct_field_documentation(' * ', member['name']))
template = (
' *\n'
' * A ${format} struct.\n'
' *\n'
' * Since: ${since}\n'
' */\n'
'typedef struct _${format} {\n')
f.write(string.Template(template).substitute(translations))
for member in self.members:
f.write(member['object'].build_variable_declaration(True, ' ', member['name']))
template = ('} ${format};\n')
f.write(string.Template(template).substitute(translations))
"""
Emit helper methods for all types in the struct
"""
def emit_helper_methods(self, hfile, cfile):
# Emit for each member
for member in self.members:
member['object'].emit_helper_methods(hfile, cfile)
"""
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, tlv_out, error, variable_name):
for member in self.members:
member['object'].emit_buffer_read(f, line_prefix, tlv_out, error, variable_name + '.' + member['name'])
"""
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, tlv_name, variable_name):
for member in self.members:
member['object'].emit_buffer_write(f, line_prefix, tlv_name, variable_name + '.' + member['name'])
"""
The struct will be printed as a list of fields enclosed between square
brackets
"""
def emit_get_printable(self, f, line_prefix):
translations = { 'lp' : line_prefix }
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)
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))
"""
Variable declaration
"""
def build_variable_declaration(self, public, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}${format} ${name};\n')
return string.Template(template).substitute(translations)
"""
The getter for a struct variable will include independent getters for each
of the variables in the struct.
"""
def build_getter_declaration(self, line_prefix, variable_name):
if not self.visible:
return ""
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}${format} *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the getter
"""
def build_getter_documentation(self, line_prefix, variable_name):
if not self.visible:
return ""
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a placeholder for the output constant #${format}, or %NULL if not required.\n')
return string.Template(template).substitute(translations)
"""
Builds the Struct getter implementation
"""
def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
if not self.visible:
return ""
translations = { 'lp' : line_prefix,
'from' : variable_name_from,
'to' : variable_name_to }
if to_is_reference:
template = (
'${lp}if (${to})\n'
'${lp} *${to} = ${from};\n')
return string.Template(template).substitute(translations)
else:
template = (
'${lp}${to} = ${from};\n')
return string.Template(template).substitute(translations)
"""
The setter for a struct variable will include independent setters for each
of the variables in the struct.
"""
def build_setter_declaration(self, line_prefix, variable_name):
if not self.visible:
return ""
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}const ${format} *${name},\n')
return string.Template(template).substitute(translations)
"""
Documentation for the setter
"""
def build_setter_documentation(self, line_prefix, variable_name):
if not self.visible:
return ""
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: the address of the #${format} to set.\n')
return string.Template(template).substitute(translations)
"""
Builds the Struct setter implementation
"""
def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
if not self.visible:
return ""
built = ''
for member in self.members:
built += member['object'].build_setter_implementation(line_prefix,
variable_name_from + '->' + member['name'],
variable_name_to + '.' + member['name'])
return built
"""
Documentation for the struct field
"""
def build_struct_field_documentation(self, line_prefix, variable_name):
translations = { 'lp' : line_prefix,
'format' : self.public_format,
'name' : variable_name }
template = (
'${lp}@${name}: a #${format} struct.\n')
return string.Template(template).substitute(translations)
"""
Disposing a struct is just about disposing each of the struct fields one by
one.
"""
def build_dispose(self, line_prefix, variable_name):
built = ''
for member in self.members:
built += member['object'].build_dispose(line_prefix, variable_name + '.' + member['name'])
return built
"""
Add sections
"""
def add_sections(self, sections):
# Add sections for each member
for member in self.members:
member['object'].add_sections(sections)
sections['public-types'] += self.public_format + '\n'