Changeset View
Changeset View
Standalone View
Standalone View
tools/sdc.py
1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python | ||
---|---|---|---|---|---|
2 | # -*- coding: utf-8 -*- | 2 | # -*- coding: utf-8 -*- | ||
3 | from __future__ import print_function | 3 | from __future__ import print_function, unicode_literals | ||
4 | # | 4 | # | ||
5 | # This file is part of the KDE project | 5 | # This file is part of the KDE project | ||
6 | # Copyright (C) 2010-2015 Jarosław Staniek <staniek@kde.org> | 6 | # Copyright (C) 2010-2015 Jarosław Staniek <staniek@kde.org> | ||
7 | # | 7 | # | ||
8 | # Shared Data Compiler (SDC) | 8 | # Shared Data Compiler (SDC) | ||
9 | 9 | | |||
10 | version = '0.3' | 10 | version = '0.3' | ||
11 | 11 | | |||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Line(s) | 90 | if len(sys.argv) < 3: | |||
92 | sys.exit(0) | 92 | sys.exit(0) | ||
93 | 93 | | |||
94 | # --- open --- | 94 | # --- open --- | ||
95 | in_fname = sys.argv[1] | 95 | in_fname = sys.argv[1] | ||
96 | out_fname = sys.argv[2] | 96 | out_fname = sys.argv[2] | ||
97 | 97 | | |||
98 | try: | 98 | try: | ||
99 | infile = open(in_fname, "rb") # binary mode needed for Windows | 99 | infile = open(in_fname, "rb") # binary mode needed for Windows | ||
100 | outfile = open(out_fname, "w") | 100 | outfile = open(out_fname, "wb") | ||
101 | except Exception, inst: | 101 | except Exception as inst: | ||
102 | print(inst) | 102 | print(inst) | ||
103 | sys.exit(1) | 103 | sys.exit(1) | ||
104 | 104 | | |||
105 | outfile_sdc = None | 105 | outfile_sdc = None | ||
106 | 106 | | |||
107 | # --- utils --- | 107 | # --- utils --- | ||
108 | def write(f, line): | ||||
109 | f.write(line.encode('utf-8')) | ||||
110 | | ||||
108 | def param(lst, name): | 111 | def param(lst, name): | ||
109 | for item in lst: | 112 | for item in lst: | ||
110 | s = item.split('=') | 113 | s = item.split('=') | ||
111 | if len(s) > 1 and s[0] == name: | 114 | if len(s) > 1 and s[0] == name: | ||
112 | return s[1] | 115 | return s[1] | ||
113 | return '' | 116 | return '' | ||
114 | 117 | | |||
115 | def param_exists(lst, name): | 118 | def param_exists(lst, name): | ||
Show All 36 Lines | 154 | if fname.rfind(os.sep) == -1: | |||
152 | return fname | 155 | return fname | ||
153 | return fname[fname.rfind(os.sep)+1:] | 156 | return fname[fname.rfind(os.sep)+1:] | ||
154 | 157 | | |||
155 | def open_sdc(): | 158 | def open_sdc(): | ||
156 | global outfile_sdc, shared_class_options | 159 | global outfile_sdc, shared_class_options | ||
157 | if not outfile_sdc: | 160 | if not outfile_sdc: | ||
158 | sdc_fname = out_fname.replace('.h', '_sdc.cpp') | 161 | sdc_fname = out_fname.replace('.h', '_sdc.cpp') | ||
159 | try: | 162 | try: | ||
160 | outfile_sdc = open(sdc_fname, "w") | 163 | outfile_sdc = open(sdc_fname, "wb") | ||
161 | except Exception, inst: | 164 | except Exception as inst: | ||
162 | print(inst) | 165 | print(inst) | ||
163 | sys.exit(1) | 166 | sys.exit(1) | ||
164 | outfile_sdc.write(warningHeader()) | 167 | write(outfile_sdc, warningHeader()) | ||
165 | outfile_sdc.write("""#include "%s" | 168 | write(outfile_sdc, """#include "%s" | ||
166 | #include <QVariant> | 169 | #include <QVariant> | ||
167 | 170 | | |||
168 | """ % get_file(out_fname)) | 171 | """ % get_file(out_fname)) | ||
169 | 172 | | |||
170 | if shared_class_options['namespace']: | 173 | if shared_class_options['namespace']: | ||
171 | outfile_sdc.write("""using namespace %s; | 174 | write(outfile_sdc, """using namespace %s; | ||
172 | 175 | | |||
173 | """ % shared_class_options['namespace']) | 176 | """ % shared_class_options['namespace']) | ||
174 | 177 | | |||
175 | """ | 178 | """ | ||
176 | Inserts generated fromMap(), toMap() code into the output. | 179 | Inserts generated fromMap(), toMap() code into the output. | ||
177 | Declarations are inserted into the header, definitions into extra *_sdc.cpp file | 180 | Declarations are inserted into the header, definitions into extra *_sdc.cpp file | ||
178 | """ | 181 | """ | ||
179 | def insert_fromMap_toMap_methods(): | 182 | def insert_fromMap_toMap_methods(): | ||
180 | global outfile, shared_class_name, toMap_impl, fromMap_impl | 183 | global outfile, shared_class_name, toMap_impl, fromMap_impl | ||
181 | outfile.write(""" /*! @return map with saved attributes of the %s object. | 184 | write(outfile, """ /*! @return map with saved attributes of the %s object. | ||
182 | 185 | | |||
183 | @see %s(const QMap<QString, QString>&, bool *). | 186 | @see %s(const QMap<QString, QString>&, bool *). | ||
184 | */ | 187 | */ | ||
185 | QMap<QString, QString> toMap() const { | 188 | QMap<QString, QString> toMap() const { | ||
186 | return d->toMap(); | 189 | return d->toMap(); | ||
187 | } | 190 | } | ||
188 | 191 | | |||
189 | """ % (shared_class_name, shared_class_name)) | 192 | """ % (shared_class_name, shared_class_name)) | ||
190 | open_sdc() | 193 | open_sdc() | ||
191 | outfile_sdc.write("""%s::Data::Data(const QMap<QString, QString> &map, bool *ok) | 194 | write(outfile_sdc, """%s::Data::Data(const QMap<QString, QString> &map, bool *ok) | ||
192 | { | 195 | { | ||
193 | if (ok) { | 196 | if (ok) { | ||
194 | *ok = true; | 197 | *ok = true; | ||
195 | } | 198 | } | ||
196 | %s} | 199 | %s} | ||
197 | 200 | | |||
198 | QMap<QString, QString> %s::Data::toMap() const | 201 | QMap<QString, QString> %s::Data::toMap() const | ||
199 | { | 202 | { | ||
200 | QMap<QString, QString> map; | 203 | QMap<QString, QString> map; | ||
201 | %s return map; | 204 | %s return map; | ||
202 | } | 205 | } | ||
203 | """ % (shared_class_name, fromMap_impl, shared_class_name, toMap_impl)) | 206 | """ % (shared_class_name, fromMap_impl, shared_class_name, toMap_impl)) | ||
204 | outfile_sdc.close() | 207 | outfile_sdc.close() | ||
205 | 208 | | |||
206 | """ | 209 | """ | ||
207 | Inserts generated operator==() code for shared class into the output. | 210 | Inserts generated operator==() code for shared class into the output. | ||
208 | """ | 211 | """ | ||
209 | def insert_operator_eq(): | 212 | def insert_operator_eq(): | ||
210 | global outfile, shared_class_name, shared_class_options, superclass | 213 | global outfile, shared_class_name, shared_class_options, superclass | ||
211 | data = 'data()' if superclass else 'd' | 214 | data = 'data()' if superclass else 'd' | ||
212 | otherData = 'other.' + data | 215 | otherData = 'other.' + data | ||
213 | if not shared_class_options['explicit']: # deep comparison only for implicitly shared data | 216 | if not shared_class_options['explicit']: # deep comparison only for implicitly shared data | ||
214 | data = '*' + data | 217 | data = '*' + data | ||
215 | otherData = '*' + otherData | 218 | otherData = '*' + otherData | ||
216 | outfile.write(""" //! @return true if this object is equal to @a other; otherwise returns false. | 219 | write(outfile, """ //! @return true if this object is equal to @a other; otherwise returns false. | ||
217 | bool operator==(const %s &other) const { | 220 | bool operator==(const %s &other) const { | ||
218 | return %s == %s; | 221 | return %s == %s; | ||
219 | } | 222 | } | ||
220 | 223 | | |||
221 | """ % (shared_class_name, data, otherData)) | 224 | """ % (shared_class_name, data, otherData)) | ||
222 | 225 | | |||
223 | """ | 226 | """ | ||
224 | Inserts generated operator!=() code for shared class into the output. | 227 | Inserts generated operator!=() code for shared class into the output. | ||
225 | """ | 228 | """ | ||
226 | def insert_operator_neq(): | 229 | def insert_operator_neq(): | ||
227 | global outfile, shared_class_name, shared_class_options, superclass | 230 | global outfile, shared_class_name, shared_class_options, superclass | ||
228 | outfile.write(""" //! @return true if this object is not equal to @a other; otherwise returns false. | 231 | write(outfile, """ //! @return true if this object is not equal to @a other; otherwise returns false. | ||
229 | bool operator!=(const %s &other) const { | 232 | bool operator!=(const %s &other) const { | ||
230 | return !operator==(other); | 233 | return !operator==(other); | ||
231 | } | 234 | } | ||
232 | 235 | | |||
233 | """ % (shared_class_name)) | 236 | """ % (shared_class_name)) | ||
234 | 237 | | |||
235 | """ | 238 | """ | ||
236 | Prepends 'virtual' to the method if there is superclass, otherwise appends 'override'. | 239 | Prepends 'virtual' to the method if there is superclass, otherwise appends 'override'. | ||
Show All 12 Lines | 247 | def insert_clone(): | |||
249 | if custom_clone: | 252 | if custom_clone: | ||
250 | line += """; | 253 | line += """; | ||
251 | """ | 254 | """ | ||
252 | else: | 255 | else: | ||
253 | line += """ { | 256 | line += """ { | ||
254 | return %s(d->clone()); | 257 | return %s(d->clone()); | ||
255 | } | 258 | } | ||
256 | """ % (shared_class_name) | 259 | """ % (shared_class_name) | ||
257 | outfile.write(line) | 260 | write(outfile, line) | ||
258 | 261 | | |||
259 | """ | 262 | """ | ||
260 | Inserts generated Data::operator==() code into the output. | 263 | Inserts generated Data::operator==() code into the output. | ||
261 | """ | 264 | """ | ||
262 | def insert_data_operator_eq(): | 265 | def insert_data_operator_eq(): | ||
263 | global outfile, members_list, superclass | 266 | global outfile, members_list, superclass | ||
264 | outfile.write(""" bool operator==(const Data &other) const { | 267 | write(outfile, """ bool operator==(const Data &other) const { | ||
265 | """) | 268 | """) | ||
266 | outfile.write(" return ") | 269 | write(outfile, " return ") | ||
267 | first = True; | 270 | first = True; | ||
268 | space = """ | 271 | space = """ | ||
269 | && """ | 272 | && """ | ||
270 | if superclass: | 273 | if superclass: | ||
271 | outfile.write('%s::Data::operator==(other)' % superclass) | 274 | write(outfile, '%s::Data::operator==(other)' % superclass) | ||
272 | first = False; | 275 | first = False; | ||
273 | for member in members_list: | 276 | for member in members_list: | ||
274 | if member['internal']: | 277 | if member['internal']: | ||
275 | continue | 278 | continue | ||
276 | outfile.write("""%s%s == other.%s""" % ('' if first else space, member['name'], member['name'])) | 279 | write(outfile, """%s%s == other.%s""" % ('' if first else space, member['name'], member['name'])) | ||
277 | if first: | 280 | if first: | ||
278 | first = False | 281 | first = False | ||
279 | outfile.write("""; | 282 | write(outfile, """; | ||
280 | } | 283 | } | ||
281 | 284 | | |||
282 | """) | 285 | """) | ||
283 | 286 | | |||
284 | """ | 287 | """ | ||
285 | Inserts generated code into the output. | 288 | Inserts generated code into the output. | ||
286 | """ | 289 | """ | ||
287 | def insert_generated_code(context): | 290 | def insert_generated_code(context): | ||
288 | global infile, outfile, generated_code_inserted, data_class_ctor, data_class_copy_ctor, superclass | 291 | global infile, outfile, generated_code_inserted, data_class_ctor, data_class_copy_ctor, superclass | ||
289 | global data_class_members, data_accesors, protected_data_accesors, main_ctor, shared_class_name, shared_class_options | 292 | global data_class_members, data_accesors, protected_data_accesors, main_ctor, shared_class_name, shared_class_options | ||
290 | global prev_line | 293 | global prev_line | ||
291 | if generated_code_inserted: | 294 | if generated_code_inserted: | ||
292 | return; | 295 | return; | ||
293 | #print "--------insert_generated_code--------" | 296 | #print "--------insert_generated_code--------" | ||
294 | #outfile.write('//CONTEXT:' + str(context) + '\n') | 297 | #write(outfile, '//CONTEXT:' + str(context) + '\n') | ||
295 | #outfile.write('//data_class_ctor>\n') | 298 | #write(outfile, '//data_class_ctor>\n') | ||
296 | outfile.write(data_class_ctor) | 299 | write(outfile, data_class_ctor) | ||
297 | #outfile.write('//<data_class_ctor\n') | 300 | #write(outfile, '//<data_class_ctor\n') | ||
298 | outfile.write(""" { | 301 | write(outfile,""" { | ||
299 | } | 302 | } | ||
300 | """) | 303 | """) | ||
301 | outfile.write(data_class_copy_ctor) | 304 | write(outfile, data_class_copy_ctor) | ||
302 | outfile.write(""" { | 305 | write(outfile, """ { | ||
303 | } | 306 | } | ||
304 | 307 | | |||
305 | """) | 308 | """) | ||
306 | outfile.write(""" %s {} | 309 | write(outfile, """ %s {} | ||
307 | 310 | | |||
308 | """ % virtual_or_override(superclass, '~Data()')) | 311 | """ % virtual_or_override(superclass, '~Data()')) | ||
309 | outfile.write(""" //! Clones the object with all attributes; the copy isn't shared with the original. | 312 | write(outfile, """ //! Clones the object with all attributes; the copy isn't shared with the original. | ||
310 | %s""" % virtual_or_override(superclass, ((superclass + '::') if superclass else '') + "Data* clone() const")) | 313 | %s""" % virtual_or_override(superclass, ((superclass + '::') if superclass else '') + "Data* clone() const")) | ||
311 | if shared_class_options['custom_clone']: | 314 | if shared_class_options['custom_clone']: | ||
312 | outfile.write("""; | 315 | write(outfile, """; | ||
313 | 316 | | |||
314 | """) | 317 | """) | ||
315 | else: | 318 | else: | ||
316 | outfile.write(""" { return new Data(*this); } | 319 | write(outfile, """ { return new Data(*this); } | ||
317 | 320 | | |||
318 | """) | 321 | """) | ||
319 | 322 | | |||
320 | if shared_class_options['with_from_to_map']: | 323 | if shared_class_options['with_from_to_map']: | ||
321 | outfile.write(""" /*! Constructor for Data object, takes attributes saved to map @a map. | 324 | write(outfile, """ /*! Constructor for Data object, takes attributes saved to map @a map. | ||
322 | If @a ok is not 0, *ok is set to true on success and to false on failure. @see toMap(). */ | 325 | If @a ok is not 0, *ok is set to true on success and to false on failure. @see toMap(). */ | ||
323 | Data(const QMap<QString, QString> &map, bool *ok); | 326 | Data(const QMap<QString, QString> &map, bool *ok); | ||
324 | 327 | | |||
325 | QMap<QString, QString> toMap() const; | 328 | QMap<QString, QString> toMap() const; | ||
326 | 329 | | |||
327 | """) | 330 | """) | ||
328 | if shared_class_options['operator=='] and not shared_class_options['explicit']: | 331 | if shared_class_options['operator=='] and not shared_class_options['explicit']: | ||
329 | insert_data_operator_eq() | 332 | insert_data_operator_eq() | ||
330 | 333 | | |||
331 | outfile.write(data_class_members) | 334 | write(outfile, data_class_members) | ||
332 | outfile.write(main_ctor) | 335 | write(outfile, main_ctor) | ||
333 | outfile.write(data_accesors) | 336 | write(outfile, data_accesors) | ||
334 | outfile.write("\n") | 337 | write(outfile, "\n") | ||
335 | if shared_class_options['with_from_to_map']: | 338 | if shared_class_options['with_from_to_map']: | ||
336 | insert_fromMap_toMap_methods() | 339 | insert_fromMap_toMap_methods() | ||
337 | if shared_class_options['operator==']: | 340 | if shared_class_options['operator==']: | ||
338 | insert_operator_eq() | 341 | insert_operator_eq() | ||
339 | insert_operator_neq() | 342 | insert_operator_neq() | ||
340 | if shared_class_options['explicit'] and (not superclass or shared_class_options['custom_clone']): | 343 | if shared_class_options['explicit'] and (not superclass or shared_class_options['custom_clone']): | ||
341 | insert_clone() | 344 | insert_clone() | ||
342 | if protected_data_accesors: | 345 | if protected_data_accesors: | ||
343 | outfile.write("protected:") | 346 | write(outfile, "protected:") | ||
344 | outfile.write(protected_data_accesors) | 347 | write(outfile, protected_data_accesors) | ||
345 | outfile.write("\npublic:") | 348 | write(outfile, "\npublic:") | ||
346 | outfile.write("\n") | 349 | write(outfile, "\n") | ||
347 | generated_code_inserted = True | 350 | generated_code_inserted = True | ||
348 | 351 | | |||
349 | 352 | | |||
350 | """ | 353 | """ | ||
351 | Reads documentation for single section (setter or getter) and returns it. | 354 | Reads documentation for single section (setter or getter) and returns it. | ||
352 | Leaves the file pointer before */ or another @getter/@setter mark. | 355 | Leaves the file pointer before */ or another @getter/@setter mark. | ||
353 | """ | 356 | """ | ||
354 | def read_getter_or_setter_doc(): | 357 | def read_getter_or_setter_doc(): | ||
355 | global prev_line, line | 358 | global prev_line, line | ||
356 | result = '' | 359 | result = '' | ||
357 | while True: | 360 | while True: | ||
358 | prev_pos = infile.tell() | 361 | prev_pos = infile.tell() | ||
359 | prev_line = line | 362 | prev_line = line | ||
360 | line = infile.readline() | 363 | line = infile.readline().decode('utf-8') | ||
361 | if not line: | 364 | if not line: | ||
362 | break | 365 | break | ||
363 | elif line.find('*/') != -1 or line.find('@getter') != -1 or line.find('@setter') != -1: | 366 | elif line.find('*/') != -1 or line.find('@getter') != -1 or line.find('@setter') != -1: | ||
364 | #print "seek prev from " + line | 367 | #print "seek prev from " + line | ||
365 | infile.seek(prev_pos) | 368 | infile.seek(prev_pos) | ||
366 | break | 369 | break | ||
367 | else: | 370 | else: | ||
368 | result += line | 371 | result += line | ||
369 | return result | 372 | return result | ||
370 | 373 | | |||
371 | def process_docs(comment): | 374 | def process_docs(comment): | ||
372 | global prev_line, line | 375 | global prev_line, line | ||
373 | result = {} | 376 | result = {} | ||
374 | while True: | 377 | while True: | ||
375 | prev_line = line | 378 | prev_line = line | ||
376 | line = infile.readline() | 379 | line = infile.readline().decode('utf-8') | ||
377 | #print "process_docs: " + line | 380 | #print "process_docs: " + line | ||
378 | if not line: | 381 | if not line: | ||
379 | break | 382 | break | ||
380 | elif line.find('*/') != -1: | 383 | elif line.find('*/') != -1: | ||
381 | if result == {}: | 384 | if result == {}: | ||
382 | insert_generated_code(1) | 385 | insert_generated_code(1) | ||
383 | outfile.write(line) | 386 | write(outfile, line) | ||
384 | break | 387 | break | ||
385 | elif line.find('@getter') != -1: | 388 | elif line.find('@getter') != -1: | ||
386 | result['getter'] = read_getter_or_setter_doc() | 389 | result['getter'] = read_getter_or_setter_doc() | ||
387 | elif line.find('@setter') != -1: | 390 | elif line.find('@setter') != -1: | ||
388 | result['setter'] = read_getter_or_setter_doc() | 391 | result['setter'] = read_getter_or_setter_doc() | ||
389 | else: | 392 | else: | ||
390 | insert_generated_code(2) | 393 | insert_generated_code(2) | ||
391 | outfile.write(comment) | 394 | write(outfile, comment) | ||
392 | outfile.write(line) | 395 | write(outfile, line) | ||
393 | if result == {}: | 396 | if result == {}: | ||
394 | result = None | 397 | result = None | ||
395 | #print "process_docs result: " + str(result) | 398 | #print "process_docs result: " + str(result) | ||
396 | return result | 399 | return result | ||
397 | 400 | | |||
398 | def try_read_member_docs(comment): | 401 | def try_read_member_docs(comment): | ||
399 | global prev_line, line | 402 | global prev_line, line | ||
400 | prev_pos = infile.tell() | 403 | prev_pos = infile.tell() | ||
401 | result = comment | 404 | result = comment | ||
402 | while True: | 405 | while True: | ||
403 | prev_line = line | 406 | prev_line = line | ||
404 | line = infile.readline() | 407 | line = infile.readline().decode('utf-8') | ||
405 | if not line or line.find('@getter') != -1 or line.find('@setter') != -1: | 408 | if not line or line.find('@getter') != -1 or line.find('@setter') != -1: | ||
406 | infile.seek(prev_pos) | 409 | infile.seek(prev_pos) | ||
407 | return None | 410 | return None | ||
408 | elif line.find('*/') != -1: | 411 | elif line.find('*/') != -1: | ||
409 | return result | 412 | return result | ||
410 | else: | 413 | else: | ||
411 | result += line | 414 | result += line | ||
412 | return None | 415 | return None | ||
413 | 416 | | |||
414 | """ makes setter out of name or returns forceSetter if specified """ | 417 | """ makes setter out of name or returns forceSetter if specified """ | ||
415 | def makeSetter(name, forceSetter): | 418 | def makeSetter(name, forceSetter): | ||
416 | if forceSetter: | 419 | if forceSetter: | ||
417 | return forceSetter | 420 | return forceSetter | ||
418 | return 'set' + name[0].upper() + name[1:] | 421 | return 'set' + name[0].upper() + name[1:] | ||
419 | 422 | | |||
420 | def update_data_accesors(): | 423 | def update_data_accesors(): | ||
421 | global data_accesors, protected_data_accesors, member | 424 | global data_accesors, protected_data_accesors, member | ||
422 | if not member['no_getter']: | 425 | if not member['no_getter']: | ||
423 | if member.has_key('getter_docs'): | 426 | if 'getter_docs' in member: | ||
424 | val = '\n /*!\n' + member['getter_docs'] + ' */' | 427 | val = '\n /*!\n' + member['getter_docs'] + ' */' | ||
425 | if member['access'] == 'public': | 428 | if member['access'] == 'public': | ||
426 | data_accesors += val | 429 | data_accesors += val | ||
427 | else: # protected | 430 | else: # protected | ||
428 | protected_data_accesors += val | 431 | protected_data_accesors += val | ||
429 | getter = member['getter'] | 432 | getter = member['getter'] | ||
430 | if not getter: | 433 | if not getter: | ||
431 | getter = member['name'] | 434 | getter = member['name'] | ||
432 | invokable = 'Q_INVOKABLE ' if member['invokable'] else '' | 435 | invokable = 'Q_INVOKABLE ' if member['invokable'] else '' | ||
433 | if member['custom_getter']: | 436 | if member['custom_getter']: | ||
434 | val = """ | 437 | val = """ | ||
435 | %s%s %s() const; | 438 | %s%s %s() const; | ||
436 | """ % (invokable, member['type'], getter) | 439 | """ % (invokable, member['type'], getter) | ||
437 | else: | 440 | else: | ||
438 | val = """ | 441 | val = """ | ||
439 | %s%s %s() const { | 442 | %s%s %s() const { | ||
440 | return %s->%s; | 443 | return %s->%s; | ||
441 | } | 444 | } | ||
442 | """ % (invokable, member['type'], getter, 'data()' if superclass else 'd', member['name']) | 445 | """ % (invokable, member['type'], getter, 'data()' if superclass else 'd', member['name']) | ||
443 | if member['access'] == 'public': | 446 | if member['access'] == 'public': | ||
444 | data_accesors += val | 447 | data_accesors += val | ||
445 | else: # protected | 448 | else: # protected | ||
446 | protected_data_accesors += val | 449 | protected_data_accesors += val | ||
447 | if not member['no_setter']: | 450 | if not member['no_setter']: | ||
448 | if member.has_key('setter_docs'): | 451 | if 'setter_docs' in member: | ||
449 | val = '\n /*!\n' + member['setter_docs'] + ' */' | 452 | val = '\n /*!\n' + member['setter_docs'] + ' */' | ||
450 | if member['access'] == 'public': | 453 | if member['access'] == 'public': | ||
451 | data_accesors += val | 454 | data_accesors += val | ||
452 | else: # protected | 455 | else: # protected | ||
453 | protected_data_accesors += val | 456 | protected_data_accesors += val | ||
454 | # heuristics to check if the const & should be used: | 457 | # heuristics to check if the const & should be used: | ||
455 | arg_type = member['type'] | 458 | arg_type = member['type'] | ||
456 | if arg_type.lower() != arg_type and not member['simple_type']: | 459 | if arg_type.lower() != arg_type and not member['simple_type']: | ||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Line(s) | 554 | def get_pos_for_QSharedData_h(): | |||
552 | global infile, prev_line, line | 555 | global infile, prev_line, line | ||
553 | prev_pos = infile.tell() | 556 | prev_pos = infile.tell() | ||
554 | line_number = -1 | 557 | line_number = -1 | ||
555 | infile.seek(0) | 558 | infile.seek(0) | ||
556 | # find last #include | 559 | # find last #include | ||
557 | last_include = -1 | 560 | last_include = -1 | ||
558 | while True: | 561 | while True: | ||
559 | prev_line = line | 562 | prev_line = line | ||
560 | line = infile.readline().lower() | 563 | line = infile.readline().decode('utf-8').lower() | ||
561 | if not line: | 564 | if not line: | ||
562 | break | 565 | break | ||
563 | line_number += 1 | 566 | line_number += 1 | ||
564 | if line.find('#include ') != -1: | 567 | if line.find('#include ') != -1: | ||
565 | if line.find('qshareddata') != -1: | 568 | if line.find('qshareddata') != -1: | ||
566 | last_include = -1 | 569 | last_include = -1 | ||
567 | break | 570 | break | ||
568 | else: | 571 | else: | ||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Line(s) | 636 | def simplify_multiline_doc(doc): | |||
659 | result[-1] = result[-1][:-1] # remove last \n | 662 | result[-1] = result[-1][:-1] # remove last \n | ||
660 | return ''.join(result) | 663 | return ''.join(result) | ||
661 | 664 | | |||
662 | def process(): | 665 | def process(): | ||
663 | global infile, outfile, generated_code_inserted, data_class_ctor, data_class_copy_ctor | 666 | global infile, outfile, generated_code_inserted, data_class_ctor, data_class_copy_ctor | ||
664 | global shared_class_name, superclass, shared_class_options, shared_class_inserted, data_class_members | 667 | global shared_class_name, superclass, shared_class_options, shared_class_inserted, data_class_members | ||
665 | global members_list, data_accesors, member, main_ctor, toMap_impl, fromMap_impl | 668 | global members_list, data_accesors, member, main_ctor, toMap_impl, fromMap_impl | ||
666 | global prev_line, line | 669 | global prev_line, line | ||
667 | outfile.write(warningHeader()) | 670 | write(outfile, warningHeader()) | ||
668 | 671 | | |||
669 | member = {} | 672 | member = {} | ||
670 | after_member = False | 673 | after_member = False | ||
671 | 674 | | |||
672 | data_class_ctor = '' | 675 | data_class_ctor = '' | ||
673 | data_class_copy_ctor = '' | 676 | data_class_copy_ctor = '' | ||
674 | data_class_ctor_changed = False | 677 | data_class_ctor_changed = False | ||
675 | data_class_copy_ctor_changed = False | 678 | data_class_copy_ctor_changed = False | ||
676 | position_for_include_QSharedData_h = get_pos_for_QSharedData_h() | 679 | position_for_include_QSharedData_h = get_pos_for_QSharedData_h() | ||
677 | 680 | | |||
678 | line_number = -1 # used for writing #include <QSharedData> | 681 | line_number = -1 # used for writing #include <QSharedData> | ||
679 | while True: | 682 | while True: | ||
680 | prev_line = line | 683 | prev_line = line | ||
681 | line = infile.readline() | 684 | line = infile.readline().decode('utf-8') | ||
682 | line_number += 1 | 685 | line_number += 1 | ||
683 | if not line: | 686 | if not line: | ||
684 | break | 687 | break | ||
685 | # print line, | 688 | # print line, | ||
686 | lst = line.split() | 689 | lst = line.split() | ||
687 | #print lst, find_index(lst, '//SDC:') | 690 | #print lst, find_index(lst, '//SDC:') | ||
688 | if line_number == position_for_include_QSharedData_h: | 691 | if line_number == position_for_include_QSharedData_h: | ||
689 | outfile.write("""#include <QSharedData> | 692 | write(outfile, """#include <QSharedData> | ||
690 | """) | 693 | """) | ||
691 | position_for_include_QSharedData_h = -1 | 694 | position_for_include_QSharedData_h = -1 | ||
692 | line_starts_with_class = len(lst) > 0 and lst[0] == 'class' | 695 | line_starts_with_class = len(lst) > 0 and lst[0] == 'class' | ||
693 | if line_starts_with_class and find_index(lst, '//SDC:') < 0: | 696 | if line_starts_with_class and find_index(lst, '//SDC:') < 0: | ||
694 | shared_class_inserted = False # required because otherwise QSharedDataPointer<Data> d will be added to all classes | 697 | shared_class_inserted = False # required because otherwise QSharedDataPointer<Data> d will be added to all classes | ||
695 | outfile.write(line) | 698 | write(outfile, line) | ||
696 | elif line_starts_with_class and find_index(lst, '//SDC:') > 0: | 699 | elif line_starts_with_class and find_index(lst, '//SDC:') > 0: | ||
697 | # re-init variables, needed if there are more than one shared class per file | 700 | # re-init variables, needed if there are more than one shared class per file | ||
698 | shared_class_inserted = False | 701 | shared_class_inserted = False | ||
699 | generated_code_inserted = False | 702 | generated_code_inserted = False | ||
700 | shared_class_options = {} | 703 | shared_class_options = {} | ||
701 | data_class_ctor = '' | 704 | data_class_ctor = '' | ||
702 | data_class_copy_ctor = '' | 705 | data_class_copy_ctor = '' | ||
703 | data_class_members = '' | 706 | data_class_members = '' | ||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | 751 | """ % (shared_class_name, superclass, superclass) | |||
755 | : d(new Data(map, ok)) | 758 | : d(new Data(map, ok)) | ||
756 | { | 759 | { | ||
757 | } | 760 | } | ||
758 | """ % (shared_class_name, shared_class_name) | 761 | """ % (shared_class_name, shared_class_name) | ||
759 | main_ctor += """ | 762 | main_ctor += """ | ||
760 | %s; | 763 | %s; | ||
761 | """ % virtual_or_override(superclass and shared_class_options['virtual_dtor'], '~' + shared_class_name + '()') | 764 | """ % virtual_or_override(superclass and shared_class_options['virtual_dtor'], '~' + shared_class_name + '()') | ||
762 | if shared_class_options['explicit']: | 765 | if shared_class_options['explicit']: | ||
763 | outfile.write("""/*! @note objects of this class are explicitly shared, what means they behave like regular | 766 | write(outfile, """/*! @note objects of this class are explicitly shared, what means they behave like regular | ||
764 | C++ pointers, except that by doing reference counting and not deleting the shared | 767 | C++ pointers, except that by doing reference counting and not deleting the shared | ||
765 | data object until the reference count is 0, they avoid the dangling pointer problem. | 768 | data object until the reference count is 0, they avoid the dangling pointer problem. | ||
766 | See <a href="http://doc.qt.io/qt-5/qexplicitlyshareddatapointer.html#details">Qt documentation</a>. | 769 | See <a href="http://doc.qt.io/qt-5/qexplicitlyshareddatapointer.html#details">Qt documentation</a>. | ||
767 | */ | 770 | */ | ||
768 | """) | 771 | """) | ||
769 | else: | 772 | else: | ||
770 | outfile.write("""/*! @note objects of this class are implicitly shared, what means they have value semantics | 773 | write(outfile, """/*! @note objects of this class are implicitly shared, what means they have value semantics | ||
771 | by offering copy-on-write behaviour to maximize resource usage and minimize copying. | 774 | by offering copy-on-write behaviour to maximize resource usage and minimize copying. | ||
772 | Only a pointer to the data is passed around. See <a href="http://doc.qt.io/qt-5/qshareddatapointer.html#details">Qt documentation</a>. | 775 | Only a pointer to the data is passed around. See <a href="http://doc.qt.io/qt-5/qshareddatapointer.html#details">Qt documentation</a>. | ||
773 | */ | 776 | */ | ||
774 | """) | 777 | """) | ||
775 | 778 | | |||
776 | # Finally output the class name: use all remaining elements of 'lst' except | 779 | # Finally output the class name: use all remaining elements of 'lst' except | ||
777 | # the 0th (which is the 'shared' keyword): | 780 | # the 0th (which is the 'shared' keyword): | ||
778 | outfile.write('//! @note This class has been generated using the following SDC class options: ' | 781 | write(outfile, '//! @note This class has been generated using the following SDC class options: ' | ||
779 | + ', '.join(enabled_shared_class_options()) + '\n') | 782 | + ', '.join(enabled_shared_class_options()) + '\n') | ||
780 | outfile.write(' '.join(remove_cpp_comment(lst)) + '\n') | 783 | write(outfile, ' '.join(remove_cpp_comment(lst)) + '\n') | ||
781 | while True: | 784 | while True: | ||
782 | prev_line = line | 785 | prev_line = line | ||
783 | line = infile.readline() # output everything until 'public:' | 786 | line = infile.readline().decode('utf-8') # output everything until 'public:' | ||
784 | outfile.write(line) | 787 | write(outfile, line) | ||
785 | if line.strip().startswith('public:'): | 788 | if line.strip().startswith('public:'): | ||
786 | break | 789 | break | ||
787 | shared_class_inserted = True | 790 | shared_class_inserted = True | ||
788 | elif len(lst) >= 2 and lst[0] == '#if' and lst[1] == '0': | 791 | elif len(lst) >= 2 and lst[0] == '#if' and lst[1] == '0': | ||
789 | insert_generated_code(3) | 792 | insert_generated_code(3) | ||
790 | outfile.write(line) | 793 | write(outfile, line) | ||
791 | while True: | 794 | while True: | ||
792 | prev_line = line | 795 | prev_line = line | ||
793 | line = infile.readline() | 796 | line = infile.readline().decode('utf-8') | ||
794 | lst = line.split() | 797 | lst = line.split() | ||
795 | if not line: | 798 | if not line: | ||
796 | break | 799 | break | ||
797 | elif len(lst) >= 1 and lst[0] == '#endif': | 800 | elif len(lst) >= 1 and lst[0] == '#endif': | ||
798 | outfile.write(line) | 801 | write(outfile, line) | ||
799 | break | 802 | break | ||
800 | outfile.write(line) | 803 | write(outfile, line) | ||
801 | elif len(lst) == 1 and (lst[0] == '/**' or lst[0] == '/*!'): | 804 | elif len(lst) == 1 and (lst[0] == '/**' or lst[0] == '/*!'): | ||
802 | comment = line | 805 | comment = line | ||
803 | 806 | | |||
804 | member_docs = try_read_member_docs(comment) | 807 | member_docs = try_read_member_docs(comment) | ||
805 | #print "member_docs:" + str(member_docs) | 808 | #print "member_docs:" + str(member_docs) | ||
806 | 809 | | |||
807 | docs = None | 810 | docs = None | ||
808 | if member_docs: | 811 | if member_docs: | ||
809 | member = {} | 812 | member = {} | ||
810 | member['docs'] = '\n ' + member_docs.replace('\n', '\n ') + ' */'; | 813 | member['docs'] = '\n ' + member_docs.replace('\n', '\n ') + ' */'; | ||
811 | else: | 814 | else: | ||
812 | docs = process_docs(comment) | 815 | docs = process_docs(comment) | ||
813 | if docs: | 816 | if docs: | ||
814 | #print "DOCS:" + str(docs) | 817 | #print "DOCS:" + str(docs) | ||
815 | member = {} | 818 | member = {} | ||
816 | if docs.has_key('getter'): | 819 | if 'getter' in docs: | ||
817 | member['getter_docs'] = docs['getter'] | 820 | member['getter_docs'] = docs['getter'] | ||
818 | if docs.has_key('setter'): | 821 | if 'setter' in docs: | ||
819 | member['setter_docs'] = docs['setter'] | 822 | member['setter_docs'] = docs['setter'] | ||
820 | elif not member_docs: | 823 | elif not member_docs: | ||
821 | insert_generated_code(4) | 824 | insert_generated_code(4) | ||
822 | outfile.write(comment) | 825 | write(outfile, comment) | ||
823 | elif len(lst) >= 2 and lst[0] == 'enum': | 826 | elif len(lst) >= 2 and lst[0] == 'enum': | ||
824 | # skip enums: until '};' found | 827 | # skip enums: until '};' found | ||
825 | outfile.write(line) | 828 | write(outfile, line) | ||
826 | while True: | 829 | while True: | ||
827 | prev_line = line | 830 | prev_line = line | ||
828 | line = infile.readline() | 831 | line = infile.readline().decode('utf-8') | ||
829 | lst = line.split() | 832 | lst = line.split() | ||
830 | if len(lst) > 0 and lst[0] == '};': | 833 | if len(lst) > 0 and lst[0] == '};': | ||
831 | outfile.write(line) | 834 | write(outfile, line) | ||
832 | break | 835 | break | ||
833 | outfile.write(line) | 836 | write(outfile, line) | ||
834 | elif data_member_found(lst): | 837 | elif data_member_found(lst): | ||
835 | """ for syntax see top of the file """ | 838 | """ for syntax see top of the file """ | ||
836 | if lst[1].endswith(';'): | 839 | if lst[1].endswith(';'): | ||
837 | lst[1] = lst[1][:-1] # strip ';' from member name | 840 | lst[1] = lst[1][:-1] # strip ';' from member name | ||
838 | sdc_index = find_index(lst, '//SDC:') | 841 | sdc_index = find_index(lst, '//SDC:') | ||
839 | options_list = lst[sdc_index+1:] | 842 | options_list = lst[sdc_index+1:] | ||
840 | #print lst | 843 | #print lst | ||
841 | member['name'] = lst[1] | 844 | member['name'] = lst[1] | ||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Line(s) | 890 | if data_class_ctor_changed: | |||
888 | data_class_ctor += ', ' | 891 | data_class_ctor += ', ' | ||
889 | else: | 892 | else: | ||
890 | data_class_ctor += ': ' | 893 | data_class_ctor += ': ' | ||
891 | data_class_ctor_changed = True | 894 | data_class_ctor_changed = True | ||
892 | data_class_ctor += member['name'] + '(' + member['default'] + ')\n' | 895 | data_class_ctor += member['name'] + '(' + member['default'] + ')\n' | ||
893 | # print data_class_ctor | 896 | # print data_class_ctor | ||
894 | if not member['internal']: | 897 | if not member['internal']: | ||
895 | data_class_copy_ctor += ' , %s(other.%s)\n' % (member['name'], member['name']) | 898 | data_class_copy_ctor += ' , %s(other.%s)\n' % (member['name'], member['name']) | ||
896 | if member.has_key('docs'): | 899 | if 'docs' in member: | ||
897 | data_class_members += simplify_multiline_doc(member['docs']) + '\n'; | 900 | data_class_members += simplify_multiline_doc(member['docs']) + '\n'; | ||
898 | 901 | | |||
899 | mutable = 'mutable ' if member['mutable'] else '' | 902 | mutable = 'mutable ' if member['mutable'] else '' | ||
900 | data_class_members += " %s%s;" % (mutable, ' '.join(lst[:sdc_index])) | 903 | data_class_members += " %s%s;" % (mutable, ' '.join(lst[:sdc_index])) | ||
901 | # add doc for shared data member | 904 | # add doc for shared data member | ||
902 | if not isMethodDeclaration: | 905 | if not isMethodDeclaration: | ||
903 | if isInternalMember: | 906 | if isInternalMember: | ||
904 | data_class_members += ' //!< @internal' | 907 | data_class_members += ' //!< @internal' | ||
Show All 19 Lines | 923 | if not isMethodDeclaration: | |||
924 | update_data_accesors() | 927 | update_data_accesors() | ||
925 | 928 | | |||
926 | member = {} | 929 | member = {} | ||
927 | if len(prev_line.split()) == 0: # remove current line because it's not going to the output now; this helps to remove duplicated empty lines | 930 | if len(prev_line.split()) == 0: # remove current line because it's not going to the output now; this helps to remove duplicated empty lines | ||
928 | line = '' | 931 | line = '' | ||
929 | after_member = True | 932 | after_member = True | ||
930 | elif len(lst) > 0 and lst[0] == '};' and line[:2] == '};' and shared_class_inserted: | 933 | elif len(lst) > 0 and lst[0] == '};' and line[:2] == '};' and shared_class_inserted: | ||
931 | insert_generated_code(5) | 934 | insert_generated_code(5) | ||
932 | # outfile.write('\nprivate:\n'); | 935 | # write(outfile, '\nprivate:\n'); | ||
933 | outfile.write('\nprotected:\n'); | 936 | write(outfile, '\nprotected:\n'); | ||
934 | if shared_class_options['explicit']: | 937 | if shared_class_options['explicit']: | ||
935 | if superclass: | 938 | if superclass: | ||
936 | outfile.write(""" virtual const Data* data() const { return dynamic_cast<const Data*>(%s::d.constData()); } | 939 | write(outfile, """ virtual const Data* data() const { return dynamic_cast<const Data*>(%s::d.constData()); } | ||
937 | virtual Data* data() { return dynamic_cast<Data*>(%s::d.data()); } | 940 | virtual Data* data() { return dynamic_cast<Data*>(%s::d.data()); } | ||
938 | """ % (superclass, superclass)) | 941 | """ % (superclass, superclass)) | ||
939 | else: | 942 | else: | ||
940 | outfile.write(""" %s(Data *data) | 943 | write(outfile, """ %s(Data *data) | ||
941 | : d(data) | 944 | : d(data) | ||
942 | { | 945 | { | ||
943 | } | 946 | } | ||
944 | 947 | | |||
945 | %s(QExplicitlySharedDataPointer<%s::Data> &data) | 948 | %s(QExplicitlySharedDataPointer<%s::Data> &data) | ||
946 | : d(data) | 949 | : d(data) | ||
947 | { | 950 | { | ||
948 | } | 951 | } | ||
949 | 952 | | |||
950 | QExplicitlySharedDataPointer<Data> d; | 953 | QExplicitlySharedDataPointer<Data> d; | ||
951 | """ % (shared_class_name, shared_class_name, shared_class_name)) | 954 | """ % (shared_class_name, shared_class_name, shared_class_name)) | ||
952 | else: | 955 | else: | ||
953 | outfile.write(' QSharedDataPointer<Data> d;\n'); | 956 | write(outfile, ' QSharedDataPointer<Data> d;\n'); | ||
954 | outfile.write(line) | 957 | write(outfile, line) | ||
955 | 958 | | |||
956 | if shared_class_options['explicit']: | 959 | if shared_class_options['explicit']: | ||
957 | outfile.write(""" | 960 | write(outfile, """ | ||
958 | template<> | 961 | template<> | ||
959 | %s %s::Data *QSharedDataPointer<%s::Data>::clone(); | 962 | %s %s::Data *QSharedDataPointer<%s::Data>::clone(); | ||
960 | """ % (export_macro, shared_class_name, shared_class_name)) | 963 | """ % (export_macro, shared_class_name, shared_class_name)) | ||
961 | open_sdc() | 964 | open_sdc() | ||
962 | outfile_sdc.write("""template<> | 965 | write(outfile_sdc, """template<> | ||
963 | %s %s::Data *QSharedDataPointer<%s::Data>::clone() | 966 | %s %s::Data *QSharedDataPointer<%s::Data>::clone() | ||
964 | { | 967 | { | ||
965 | return d->clone(); | 968 | return d->clone(); | ||
966 | } | 969 | } | ||
967 | """ % (export_macro, shared_class_name, shared_class_name)) | 970 | """ % (export_macro, shared_class_name, shared_class_name)) | ||
968 | 971 | | |||
969 | else: | 972 | else: | ||
970 | #outfile.write('____ELSE____\n'); | 973 | #write(outfile, '____ELSE____\n'); | ||
971 | if False and other_comment(line): | 974 | if False and other_comment(line): | ||
972 | prev_pos = infile.tell() | 975 | prev_pos = infile.tell() | ||
973 | prev_line_number = line_number | 976 | prev_line_number = line_number | ||
974 | ln = line[:-1].strip(' ') | 977 | ln = line[:-1].strip(' ') | ||
975 | result = '' | 978 | result = '' | ||
976 | print("'" + ln + "'") | 979 | print("'" + ln + "'") | ||
977 | if ln.startswith('/**') or ln.startswith('/*!'): | 980 | if ln.startswith('/**') or ln.startswith('/*!'): | ||
978 | while True: | 981 | while True: | ||
979 | result += line | 982 | result += line | ||
980 | if not line or ln.endswith('*/'): | 983 | if not line or ln.endswith('*/'): | ||
981 | result = result[:-1] | 984 | result = result[:-1] | ||
982 | break | 985 | break | ||
983 | prev_line = line | 986 | prev_line = line | ||
984 | line = infile.readline() | 987 | line = infile.readline().decode('utf-8') | ||
985 | line_number += 1 | 988 | line_number += 1 | ||
986 | ln = line[:-1].strip(' ') | 989 | ln = line[:-1].strip(' ') | ||
987 | print(result) | 990 | print(result) | ||
988 | if result: | 991 | if result: | ||
989 | member['docs'] = result | 992 | member['docs'] = result | ||
990 | infile.seek(prev_pos) | 993 | infile.seek(prev_pos) | ||
991 | prev_line = line | 994 | prev_line = line | ||
992 | line = infile.readline() | 995 | line = infile.readline().decode('utf-8') | ||
993 | lst = line.split() | 996 | lst = line.split() | ||
994 | line_number = prev_line_number | 997 | line_number = prev_line_number | ||
995 | 998 | | |||
996 | if not lst: | 999 | if not lst: | ||
997 | if len(prev_line.split()) > 0: | 1000 | if len(prev_line.split()) > 0: | ||
998 | #outfile.write('['+prev_line + ']prev_line[' + line +']') | 1001 | #write(outfile, '['+prev_line + ']prev_line[' + line +']') | ||
999 | outfile.write(line) | 1002 | write(outfile, line) | ||
1000 | elif not after_member or len(lst) > 0: | 1003 | elif not after_member or len(lst) > 0: | ||
1001 | if shared_class_inserted: | 1004 | if shared_class_inserted: | ||
1002 | insert_generated_code(6) | 1005 | insert_generated_code(6) | ||
1003 | outfile.write(line) | 1006 | write(outfile, line) | ||
1004 | elif generated_code_inserted and len(lst) == 0: | 1007 | elif generated_code_inserted and len(lst) == 0: | ||
1005 | #outfile.write('ELSE>>>' + line) | 1008 | #write(outfile, 'ELSE>>>' + line) | ||
1006 | outfile.write(line) | 1009 | write(outfile, line) | ||
1007 | # else: | 1010 | # else: | ||
1008 | # outfile.write(line) | 1011 | # write(outfile, line) | ||
1009 | 1012 | | |||
1010 | process() | 1013 | process() | ||
1011 | 1014 | | |||
1012 | # --- close --- | 1015 | # --- close --- | ||
1013 | infile.close() | 1016 | infile.close() | ||
1014 | outfile.close() | 1017 | outfile.close() |