blob: 7e977c224305b3c613deb45d52283bb1a458b568 [file] [log] [blame]
Aleksander Morgado2a511da2012-05-30 12:40:46 +02001#!/usr/bin/env python
2# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3#
4# This program is free software; you can redistribute it and/or modify it under
5# the terms of the GNU Lesser General Public License as published by the Free
6# Software Foundation; either version 2 of the License, or (at your option) any
7# later version.
8#
9# This program is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12# details.
13#
14# You should have received a copy of the GNU Lesser General Public License along
15# with this program; if not, write to the Free Software Foundation, Inc., 51
16# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17#
18# Copyright (C) 2012 Lanedo GmbH
19#
20
21import string
22import utils
23from Variable import Variable
24
25"""
26Variable type for Strings ('string' format)
27"""
28class VariableString(Variable):
29
30 """
31 Constructor
32 """
33 def __init__(self, dictionary):
34
35 # Call the parent constructor
36 Variable.__init__(self, dictionary)
37
38 self.private_format = 'gchar *'
39 self.public_format = self.private_format
40
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020041 if 'fixed-size' in dictionary:
42 self.is_fixed_size = True
43 # Fixed-size strings
44 self.needs_dispose = False
Dan Williamse7a72f22012-08-31 15:04:00 -050045 self.length_prefix_size = 0
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020046 self.fixed_size = dictionary['fixed-size']
Aleksander Morgado6ba2b612012-07-06 09:43:15 +020047 self.max_size = ''
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020048 else:
49 self.is_fixed_size = False
50 # Variable-length strings in heap
51 self.needs_dispose = True
52 # Strings which are given as the full value of a TLV will NOT have a
53 # length prefix
Dan Williamse7a72f22012-08-31 15:04:00 -050054 if 'type' in dictionary and dictionary['type'] == 'TLV':
55 self.length_prefix_size = 0
Aleksander Morgado201e0ce2012-09-19 12:02:05 +020056 elif 'size-prefix-format' in dictionary:
57 if dictionary['size-prefix-format'] == 'guint8':
58 self.length_prefix_size = 8
59 elif dictionary['size-prefix-format'] == 'guint16':
60 self.length_prefix_size = 16
61 else:
62 raise ValueError('Invalid size prefix format (%s): not guint8 or guint16' % dictionary['size-prefix-format'])
Dan Williamse7a72f22012-08-31 15:04:00 -050063 else:
64 # Default to UINT8
65 self.length_prefix_size = 8
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020066 self.fixed_size = ''
Aleksander Morgado6ba2b612012-07-06 09:43:15 +020067 self.max_size = dictionary['max-size'] if 'max-size' in dictionary else ''
Aleksander Morgado2a511da2012-05-30 12:40:46 +020068
69
70 """
71 Read a string from the raw byte buffer.
72 """
73 def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
74 translations = { 'lp' : line_prefix,
75 'variable_name' : variable_name,
76 'buffer_name' : buffer_name,
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020077 'buffer_len' : buffer_len }
Aleksander Morgado2a511da2012-05-30 12:40:46 +020078
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020079 if self.is_fixed_size:
80 translations['fixed_size'] = self.fixed_size
81 template = (
82 '${lp}/* Read the fixed-size string variable from the buffer */\n'
83 '${lp}qmi_utils_read_fixed_size_string_from_buffer (\n'
84 '${lp} &${buffer_name},\n'
85 '${lp} &${buffer_len},\n'
86 '${lp} ${fixed_size},\n'
87 '${lp} &${variable_name}[0]);\n'
88 '${lp}${variable_name}[${fixed_size}] = \'\\0\';\n')
89 else:
Dan Williamse7a72f22012-08-31 15:04:00 -050090 translations['length_prefix_size'] = self.length_prefix_size
Aleksander Morgado334177e2012-09-04 14:17:39 +020091 translations['max_size'] = self.max_size if self.max_size != '' else '0'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020092 template = (
93 '${lp}/* Read the string variable from the buffer */\n'
94 '${lp}qmi_utils_read_string_from_buffer (\n'
95 '${lp} &${buffer_name},\n'
96 '${lp} &${buffer_len},\n'
Dan Williamse7a72f22012-08-31 15:04:00 -050097 '${lp} ${length_prefix_size},\n'
Aleksander Morgado334177e2012-09-04 14:17:39 +020098 '${lp} ${max_size},\n'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020099 '${lp} &(${variable_name}));\n')
100
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200101 f.write(string.Template(template).substitute(translations))
102
103
104 """
105 Write a string to the raw byte buffer.
106 """
107 def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
108 translations = { 'lp' : line_prefix,
109 'variable_name' : variable_name,
110 'buffer_name' : buffer_name,
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200111 'buffer_len' : buffer_len }
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200112
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200113 if self.is_fixed_size:
114 translations['fixed_size'] = self.fixed_size
115 template = (
116 '${lp}/* Write the fixed-size string variable to the buffer */\n'
117 '${lp}qmi_utils_write_fixed_size_string_to_buffer (\n'
118 '${lp} &${buffer_name},\n'
119 '${lp} &${buffer_len},\n'
120 '${lp} ${fixed_size},\n'
121 '${lp} ${variable_name});\n')
122 else:
Dan Williamse7a72f22012-08-31 15:04:00 -0500123 translations['length_prefix_size'] = self.length_prefix_size
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200124 template = (
125 '${lp}/* Write the string variable to the buffer */\n'
126 '${lp}qmi_utils_write_string_to_buffer (\n'
127 '${lp} &${buffer_name},\n'
128 '${lp} &${buffer_len},\n'
Dan Williamse7a72f22012-08-31 15:04:00 -0500129 '${lp} ${length_prefix_size},\n'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200130 '${lp} ${variable_name});\n')
131
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200132 f.write(string.Template(template).substitute(translations))
133
134
135 """
136 Get the string as printable
137 """
138 def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
139 translations = { 'lp' : line_prefix,
140 'printable' : printable,
141 'buffer_name' : buffer_name,
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200142 'buffer_len' : buffer_len }
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200143
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200144 if self.is_fixed_size:
145 translations['fixed_size'] = self.fixed_size
146 translations['fixed_size_plus_one'] = int(self.fixed_size) + 1
147 template = (
148 '\n'
149 '${lp}{\n'
150 '${lp} gchar tmp[${fixed_size_plus_one}];\n'
151 '\n'
152 '${lp} /* Read the fixed-size string variable from the buffer */\n'
153 '${lp} qmi_utils_read_fixed_size_string_from_buffer (\n'
154 '${lp} &${buffer_name},\n'
155 '${lp} &${buffer_len},\n'
156 '${lp} ${fixed_size},\n'
157 '${lp} &tmp[0]);\n'
158 '${lp} tmp[${fixed_size}] = \'\\0\';\n'
159 '\n'
160 '${lp} g_string_append_printf (${printable}, "%s", tmp);\n'
161 '${lp}}\n')
162 else:
Dan Williamse7a72f22012-08-31 15:04:00 -0500163 translations['length_prefix_size'] = self.length_prefix_size
Aleksander Morgado334177e2012-09-04 14:17:39 +0200164 translations['max_size'] = self.max_size if self.max_size != '' else '0'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200165 template = (
166 '\n'
167 '${lp}{\n'
168 '${lp} gchar *tmp;\n'
169 '\n'
170 '${lp} /* Read the string variable from the buffer */\n'
171 '${lp} qmi_utils_read_string_from_buffer (\n'
172 '${lp} &${buffer_name},\n'
173 '${lp} &${buffer_len},\n'
Dan Williamse7a72f22012-08-31 15:04:00 -0500174 '${lp} ${length_prefix_size},\n'
Aleksander Morgado334177e2012-09-04 14:17:39 +0200175 '${lp} ${max_size},\n'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200176 '${lp} &tmp);\n'
177 '\n'
178 '${lp} g_string_append_printf (${printable}, "%s", tmp);\n'
179 '${lp} g_free (tmp);\n'
180 '${lp}}\n')
181
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200182 f.write(string.Template(template).substitute(translations))
183
184
185 """
Aleksander Morgado4130a722012-07-03 13:58:52 +0200186 Variable declaration
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200187 """
Aleksander Morgado4130a722012-07-03 13:58:52 +0200188 def build_variable_declaration(self, line_prefix, variable_name):
189 translations = { 'lp' : line_prefix,
190 'name' : variable_name }
191
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200192 if self.is_fixed_size:
193 translations['fixed_size_plus_one'] = int(self.fixed_size) + 1
194 template = (
195 '${lp}gchar ${name}[${fixed_size_plus_one}];\n')
196 else:
197 template = (
198 '${lp}gchar *${name};\n')
Aleksander Morgado4130a722012-07-03 13:58:52 +0200199 return string.Template(template).substitute(translations)
200
201
202 """
203 Getter for the string type
204 """
205 def build_getter_declaration(self, line_prefix, variable_name):
206 translations = { 'lp' : line_prefix,
207 'name' : variable_name }
208
209 template = (
210 '${lp}const gchar **${name},\n')
211 return string.Template(template).substitute(translations)
212
213
214 """
215 Documentation for the getter
216 """
217 def build_getter_documentation(self, line_prefix, variable_name):
218 translations = { 'lp' : line_prefix,
219 'name' : variable_name }
220
221 template = (
222 '${lp}@${name}: a placeholder for the output constant string, or #NULL if not required.\n')
223 return string.Template(template).substitute(translations)
224
225
226 """
227 Builds the String getter implementation
228 """
229 def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
230 translations = { 'lp' : line_prefix,
231 'from' : variable_name_from,
232 'to' : variable_name_to }
233
234 if to_is_reference:
235 template = (
236 '${lp}if (${to})\n'
237 '${lp} *${to} = ${from};\n')
238 return string.Template(template).substitute(translations)
239 else:
240 template = (
241 '${lp}${to} = ${from};\n')
242 return string.Template(template).substitute(translations)
243
244
245 """
246 Setter for the string type
247 """
248 def build_setter_declaration(self, line_prefix, variable_name):
249 translations = { 'lp' : line_prefix,
250 'name' : variable_name }
251
252 template = (
253 '${lp}const gchar *${name},\n')
254 return string.Template(template).substitute(translations)
255
256
257 """
258 Documentation for the setter
259 """
260 def build_setter_documentation(self, line_prefix, variable_name):
261 translations = { 'lp' : line_prefix,
262 'name' : variable_name }
263
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200264 if self.is_fixed_size:
265 translations['fixed_size'] = self.fixed_size
266 template = (
267 '${lp}@${name}: a constant string of exactly ${fixed_size} characters.\n')
Aleksander Morgado6ba2b612012-07-06 09:43:15 +0200268 elif self.max_size != '':
269 translations['max_size'] = self.max_size
270 template = (
271 '${lp}@${name}: a constant string with a maximum length of ${max_size} characters.\n')
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200272 else:
273 template = (
274 '${lp}@${name}: a constant string.\n')
Aleksander Morgado4130a722012-07-03 13:58:52 +0200275 return string.Template(template).substitute(translations)
276
277
278 """
279 Builds the String setter implementation
280 """
281 def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200282 translations = { 'lp' : line_prefix,
283 'from' : variable_name_from,
284 'to' : variable_name_to }
285
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200286 if self.is_fixed_size:
287 translations['fixed_size'] = self.fixed_size
288 template = (
289 '${lp}if (!${from} || strlen (${from}) != ${fixed_size}) {\n'
290 '${lp} g_set_error (error,\n'
291 '${lp} QMI_CORE_ERROR,\n'
292 '${lp} QMI_CORE_ERROR_INVALID_ARGS,\n'
293 '${lp} "Input variable \'${from}\' must be ${fixed_size} characters long");\n'
294 '${lp} return FALSE;\n'
295 '${lp}}\n'
296 '${lp}memcpy (${to}, ${from}, ${fixed_size});\n'
297 '${lp}${to}[${fixed_size}] = \'\\0\';\n')
298 else:
Aleksander Morgado6ba2b612012-07-06 09:43:15 +0200299 template = ''
300 if self.max_size != '':
301 translations['max_size'] = self.max_size
302 template += (
303 '${lp}if (${from} && strlen (${from}) > ${max_size}) {\n'
304 '${lp} g_set_error (error,\n'
305 '${lp} QMI_CORE_ERROR,\n'
306 '${lp} QMI_CORE_ERROR_INVALID_ARGS,\n'
307 '${lp} "Input variable \'${from}\' must be less than ${max_size} characters long");\n'
308 '${lp} return FALSE;\n'
309 '${lp}}\n')
310 template += (
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200311 '${lp}g_free (${to});\n'
312 '${lp}${to} = g_strdup (${from} ? ${from} : "");\n')
313
Aleksander Morgado4130a722012-07-03 13:58:52 +0200314 return string.Template(template).substitute(translations)
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200315
316
317 """
318 Dispose the string
319 """
Aleksander Morgado4130a722012-07-03 13:58:52 +0200320 def build_dispose(self, line_prefix, variable_name):
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200321 # Fixed-size strings don't need dispose
322 if self.is_fixed_size:
323 return ''
324
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200325 translations = { 'lp' : line_prefix,
326 'variable_name' : variable_name }
327
328 template = (
329 '${lp}g_free (${variable_name});\n')
Aleksander Morgado4130a722012-07-03 13:58:52 +0200330 return string.Template(template).substitute(translations)