blob: 5be84e27be12990ae2facf070f8493a33cbad27e [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
56 elif 'length-prefix-size' in dictionary:
57 self.length_prefix_size = dictionary['length-prefix-size']
58 if self.length_prefix_size not in ['8', '16']:
59 raise ValueError('Invalid length prefix size %s: not 8 or 16' % self.length_prefix_size)
60 else:
61 # Default to UINT8
62 self.length_prefix_size = 8
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020063 self.fixed_size = ''
Aleksander Morgado6ba2b612012-07-06 09:43:15 +020064 self.max_size = dictionary['max-size'] if 'max-size' in dictionary else ''
Aleksander Morgado2a511da2012-05-30 12:40:46 +020065
66
67 """
68 Read a string from the raw byte buffer.
69 """
70 def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len):
71 translations = { 'lp' : line_prefix,
72 'variable_name' : variable_name,
73 'buffer_name' : buffer_name,
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020074 'buffer_len' : buffer_len }
Aleksander Morgado2a511da2012-05-30 12:40:46 +020075
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020076 if self.is_fixed_size:
77 translations['fixed_size'] = self.fixed_size
78 template = (
79 '${lp}/* Read the fixed-size string variable from the buffer */\n'
80 '${lp}qmi_utils_read_fixed_size_string_from_buffer (\n'
81 '${lp} &${buffer_name},\n'
82 '${lp} &${buffer_len},\n'
83 '${lp} ${fixed_size},\n'
84 '${lp} &${variable_name}[0]);\n'
85 '${lp}${variable_name}[${fixed_size}] = \'\\0\';\n')
86 else:
Dan Williamse7a72f22012-08-31 15:04:00 -050087 translations['length_prefix_size'] = self.length_prefix_size
Aleksander Morgado334177e2012-09-04 14:17:39 +020088 translations['max_size'] = self.max_size if self.max_size != '' else '0'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020089 template = (
90 '${lp}/* Read the string variable from the buffer */\n'
91 '${lp}qmi_utils_read_string_from_buffer (\n'
92 '${lp} &${buffer_name},\n'
93 '${lp} &${buffer_len},\n'
Dan Williamse7a72f22012-08-31 15:04:00 -050094 '${lp} ${length_prefix_size},\n'
Aleksander Morgado334177e2012-09-04 14:17:39 +020095 '${lp} ${max_size},\n'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +020096 '${lp} &(${variable_name}));\n')
97
Aleksander Morgado2a511da2012-05-30 12:40:46 +020098 f.write(string.Template(template).substitute(translations))
99
100
101 """
102 Write a string to the raw byte buffer.
103 """
104 def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
105 translations = { 'lp' : line_prefix,
106 'variable_name' : variable_name,
107 'buffer_name' : buffer_name,
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200108 'buffer_len' : buffer_len }
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200109
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200110 if self.is_fixed_size:
111 translations['fixed_size'] = self.fixed_size
112 template = (
113 '${lp}/* Write the fixed-size string variable to the buffer */\n'
114 '${lp}qmi_utils_write_fixed_size_string_to_buffer (\n'
115 '${lp} &${buffer_name},\n'
116 '${lp} &${buffer_len},\n'
117 '${lp} ${fixed_size},\n'
118 '${lp} ${variable_name});\n')
119 else:
Dan Williamse7a72f22012-08-31 15:04:00 -0500120 translations['length_prefix_size'] = self.length_prefix_size
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200121 template = (
122 '${lp}/* Write the string variable to the buffer */\n'
123 '${lp}qmi_utils_write_string_to_buffer (\n'
124 '${lp} &${buffer_name},\n'
125 '${lp} &${buffer_len},\n'
Dan Williamse7a72f22012-08-31 15:04:00 -0500126 '${lp} ${length_prefix_size},\n'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200127 '${lp} ${variable_name});\n')
128
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200129 f.write(string.Template(template).substitute(translations))
130
131
132 """
133 Get the string as printable
134 """
135 def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len):
136 translations = { 'lp' : line_prefix,
137 'printable' : printable,
138 'buffer_name' : buffer_name,
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200139 'buffer_len' : buffer_len }
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200140
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200141 if self.is_fixed_size:
142 translations['fixed_size'] = self.fixed_size
143 translations['fixed_size_plus_one'] = int(self.fixed_size) + 1
144 template = (
145 '\n'
146 '${lp}{\n'
147 '${lp} gchar tmp[${fixed_size_plus_one}];\n'
148 '\n'
149 '${lp} /* Read the fixed-size string variable from the buffer */\n'
150 '${lp} qmi_utils_read_fixed_size_string_from_buffer (\n'
151 '${lp} &${buffer_name},\n'
152 '${lp} &${buffer_len},\n'
153 '${lp} ${fixed_size},\n'
154 '${lp} &tmp[0]);\n'
155 '${lp} tmp[${fixed_size}] = \'\\0\';\n'
156 '\n'
157 '${lp} g_string_append_printf (${printable}, "%s", tmp);\n'
158 '${lp}}\n')
159 else:
Dan Williamse7a72f22012-08-31 15:04:00 -0500160 translations['length_prefix_size'] = self.length_prefix_size
Aleksander Morgado334177e2012-09-04 14:17:39 +0200161 translations['max_size'] = self.max_size if self.max_size != '' else '0'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200162 template = (
163 '\n'
164 '${lp}{\n'
165 '${lp} gchar *tmp;\n'
166 '\n'
167 '${lp} /* Read the string variable from the buffer */\n'
168 '${lp} qmi_utils_read_string_from_buffer (\n'
169 '${lp} &${buffer_name},\n'
170 '${lp} &${buffer_len},\n'
Dan Williamse7a72f22012-08-31 15:04:00 -0500171 '${lp} ${length_prefix_size},\n'
Aleksander Morgado334177e2012-09-04 14:17:39 +0200172 '${lp} ${max_size},\n'
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200173 '${lp} &tmp);\n'
174 '\n'
175 '${lp} g_string_append_printf (${printable}, "%s", tmp);\n'
176 '${lp} g_free (tmp);\n'
177 '${lp}}\n')
178
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200179 f.write(string.Template(template).substitute(translations))
180
181
182 """
Aleksander Morgado4130a722012-07-03 13:58:52 +0200183 Variable declaration
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200184 """
Aleksander Morgado4130a722012-07-03 13:58:52 +0200185 def build_variable_declaration(self, line_prefix, variable_name):
186 translations = { 'lp' : line_prefix,
187 'name' : variable_name }
188
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200189 if self.is_fixed_size:
190 translations['fixed_size_plus_one'] = int(self.fixed_size) + 1
191 template = (
192 '${lp}gchar ${name}[${fixed_size_plus_one}];\n')
193 else:
194 template = (
195 '${lp}gchar *${name};\n')
Aleksander Morgado4130a722012-07-03 13:58:52 +0200196 return string.Template(template).substitute(translations)
197
198
199 """
200 Getter for the string type
201 """
202 def build_getter_declaration(self, line_prefix, variable_name):
203 translations = { 'lp' : line_prefix,
204 'name' : variable_name }
205
206 template = (
207 '${lp}const gchar **${name},\n')
208 return string.Template(template).substitute(translations)
209
210
211 """
212 Documentation for the getter
213 """
214 def build_getter_documentation(self, line_prefix, variable_name):
215 translations = { 'lp' : line_prefix,
216 'name' : variable_name }
217
218 template = (
219 '${lp}@${name}: a placeholder for the output constant string, or #NULL if not required.\n')
220 return string.Template(template).substitute(translations)
221
222
223 """
224 Builds the String getter implementation
225 """
226 def build_getter_implementation(self, line_prefix, variable_name_from, variable_name_to, to_is_reference):
227 translations = { 'lp' : line_prefix,
228 'from' : variable_name_from,
229 'to' : variable_name_to }
230
231 if to_is_reference:
232 template = (
233 '${lp}if (${to})\n'
234 '${lp} *${to} = ${from};\n')
235 return string.Template(template).substitute(translations)
236 else:
237 template = (
238 '${lp}${to} = ${from};\n')
239 return string.Template(template).substitute(translations)
240
241
242 """
243 Setter for the string type
244 """
245 def build_setter_declaration(self, line_prefix, variable_name):
246 translations = { 'lp' : line_prefix,
247 'name' : variable_name }
248
249 template = (
250 '${lp}const gchar *${name},\n')
251 return string.Template(template).substitute(translations)
252
253
254 """
255 Documentation for the setter
256 """
257 def build_setter_documentation(self, line_prefix, variable_name):
258 translations = { 'lp' : line_prefix,
259 'name' : variable_name }
260
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200261 if self.is_fixed_size:
262 translations['fixed_size'] = self.fixed_size
263 template = (
264 '${lp}@${name}: a constant string of exactly ${fixed_size} characters.\n')
Aleksander Morgado6ba2b612012-07-06 09:43:15 +0200265 elif self.max_size != '':
266 translations['max_size'] = self.max_size
267 template = (
268 '${lp}@${name}: a constant string with a maximum length of ${max_size} characters.\n')
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200269 else:
270 template = (
271 '${lp}@${name}: a constant string.\n')
Aleksander Morgado4130a722012-07-03 13:58:52 +0200272 return string.Template(template).substitute(translations)
273
274
275 """
276 Builds the String setter implementation
277 """
278 def build_setter_implementation(self, line_prefix, variable_name_from, variable_name_to):
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200279 translations = { 'lp' : line_prefix,
280 'from' : variable_name_from,
281 'to' : variable_name_to }
282
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200283 if self.is_fixed_size:
284 translations['fixed_size'] = self.fixed_size
285 template = (
286 '${lp}if (!${from} || strlen (${from}) != ${fixed_size}) {\n'
287 '${lp} g_set_error (error,\n'
288 '${lp} QMI_CORE_ERROR,\n'
289 '${lp} QMI_CORE_ERROR_INVALID_ARGS,\n'
290 '${lp} "Input variable \'${from}\' must be ${fixed_size} characters long");\n'
291 '${lp} return FALSE;\n'
292 '${lp}}\n'
293 '${lp}memcpy (${to}, ${from}, ${fixed_size});\n'
294 '${lp}${to}[${fixed_size}] = \'\\0\';\n')
295 else:
Aleksander Morgado6ba2b612012-07-06 09:43:15 +0200296 template = ''
297 if self.max_size != '':
298 translations['max_size'] = self.max_size
299 template += (
300 '${lp}if (${from} && strlen (${from}) > ${max_size}) {\n'
301 '${lp} g_set_error (error,\n'
302 '${lp} QMI_CORE_ERROR,\n'
303 '${lp} QMI_CORE_ERROR_INVALID_ARGS,\n'
304 '${lp} "Input variable \'${from}\' must be less than ${max_size} characters long");\n'
305 '${lp} return FALSE;\n'
306 '${lp}}\n')
307 template += (
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200308 '${lp}g_free (${to});\n'
309 '${lp}${to} = g_strdup (${from} ? ${from} : "");\n')
310
Aleksander Morgado4130a722012-07-03 13:58:52 +0200311 return string.Template(template).substitute(translations)
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200312
313
314 """
315 Dispose the string
316 """
Aleksander Morgado4130a722012-07-03 13:58:52 +0200317 def build_dispose(self, line_prefix, variable_name):
Aleksander Morgadob3f6aab2012-07-06 08:43:49 +0200318 # Fixed-size strings don't need dispose
319 if self.is_fixed_size:
320 return ''
321
Aleksander Morgado2a511da2012-05-30 12:40:46 +0200322 translations = { 'lp' : line_prefix,
323 'variable_name' : variable_name }
324
325 template = (
326 '${lp}g_free (${variable_name});\n')
Aleksander Morgado4130a722012-07-03 13:58:52 +0200327 return string.Template(template).substitute(translations)