Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Side by Side Diff: tools/json_to_struct/element_generator.py

Issue 1209733002: Add the ability to code generated prepopulated static nested structs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import json 5 import json
6 import struct_generator 6 import struct_generator
7 7
8 field_name_count = {}
beaudoin 2015/07/06 16:01:11 Module-global mutable variables are against the st
danduong 2015/07/08 23:07:03 Done.
9
8 def _JSONToCString16(json_string_literal): 10 def _JSONToCString16(json_string_literal):
9 """Converts a JSON string literal to a C++ UTF-16 string literal. This is 11 """Converts a JSON string literal to a C++ UTF-16 string literal. This is
10 done by converting \\u#### to \\x####. 12 done by converting \\u#### to \\x####.
11 """ 13 """
12 c_string_literal = json_string_literal 14 c_string_literal = json_string_literal
13 escape_index = c_string_literal.find('\\') 15 escape_index = c_string_literal.find('\\')
14 while escape_index > 0: 16 while escape_index > 0:
15 if c_string_literal[escape_index + 1] == 'u': 17 if c_string_literal[escape_index + 1] == 'u':
16 # We close the C string literal after the 4 hex digits and reopen it right 18 # We close the C string literal after the 4 hex digits and reopen it right
17 # after, otherwise the Windows compiler will sometimes try to get more 19 # after, otherwise the Windows compiler will sometimes try to get more
18 # than 4 characters in the hex string. 20 # than 4 characters in the hex string.
19 c_string_literal = (c_string_literal[0:escape_index + 1] + 'x' + 21 c_string_literal = (c_string_literal[0:escape_index + 1] + 'x' +
20 c_string_literal[escape_index + 2:escape_index + 6] + '" L"' + 22 c_string_literal[escape_index + 2:escape_index + 6] + '" L"' +
21 c_string_literal[escape_index + 6:]) 23 c_string_literal[escape_index + 6:])
22 escape_index = c_string_literal.find('\\', escape_index + 6) 24 escape_index = c_string_literal.find('\\', escape_index + 6)
23 return c_string_literal 25 return c_string_literal
24 26
25 def _GenerateString(content, lines): 27 def _GenerateString(content, lines, indent=' '):
26 """Generates an UTF-8 string to be included in a static structure initializer. 28 """Generates an UTF-8 string to be included in a static structure initializer.
27 If content is not specified, uses NULL. 29 If content is not specified, uses NULL.
28 """ 30 """
29 if content is None: 31 if content is None:
30 lines.append(' NULL,') 32 lines.append(indent + 'NULL,')
31 else: 33 else:
32 # json.dumps quotes the string and escape characters as required. 34 # json.dumps quotes the string and escape characters as required.
33 lines.append(' %s,' % json.dumps(content)) 35 lines.append(indent + '%s,' % json.dumps(content))
34 36
35 def _GenerateString16(content, lines): 37 def _GenerateString16(content, lines, indent=' '):
36 """Generates an UTF-16 string to be included in a static structure 38 """Generates an UTF-16 string to be included in a static structure
37 initializer. If content is not specified, uses NULL. 39 initializer. If content is not specified, uses NULL.
38 """ 40 """
39 if content is None: 41 if content is None:
40 lines.append(' NULL,') 42 lines.append(indent + 'NULL,')
41 else: 43 else:
42 # json.dumps quotes the string and escape characters as required. 44 # json.dumps quotes the string and escape characters as required.
43 lines.append(' L%s,' % _JSONToCString16(json.dumps(content))) 45 lines.append(indent + 'L%s,' % _JSONToCString16(json.dumps(content)))
44 46
45 def _GenerateArray(element_name, field_info, content, lines): 47 def _GenerateArrayVariableName(element_name, field_name):
48 # Generates a unique variable name for an array variable.
49 global field_name_count
50 var = 'array_%s_%s' % (element_name, field_name)
51 if var not in field_name_count:
52 field_name_count[var] = 0
53 return var
54 new_var = '%s_%d' % (var, field_name_count[var])
55 field_name_count[var] += 1
56 return new_var
57
58 def _GenerateArray(element_name, field_info, content, lines, indent=' '):
46 """Generates an array to be included in a static structure initializer. If 59 """Generates an array to be included in a static structure initializer. If
47 content is not specified, uses NULL. The array is assigned to a temporary 60 content is not specified, uses NULL. The array is assigned to a temporary
48 variable which is initialized before the structure. 61 variable which is initialized before the structure.
49 """ 62 """
50 if content is None: 63 if content is None:
51 lines.append(' NULL,') 64 lines.append(indent + 'NULL,')
52 lines.append(' 0,') # Size of the array. 65 lines.append(indent + '0,') # Size of the array.
53 return 66 return
54 67
55 # Create a new array variable and use it in the structure initializer. 68 # Create a new array variable and use it in the structure initializer.
56 # This prohibits nested arrays. Add a clash detection and renaming mechanism 69 # This prohibits nested arrays. Add a clash detection and renaming mechanism
57 # to solve the problem. 70 # to solve the problem.
58 var = 'array_%s_%s' % (element_name, field_info['field']); 71 var = _GenerateArrayVariableName(element_name, field_info['field'])
59 lines.append(' %s,' % var) 72 lines.append(indent + '%s,' % var)
60 lines.append(' %s,' % len(content)) # Size of the array. 73 lines.append(indent + '%s,' % len(content)) # Size of the array.
61 # Generate the array content. 74 # Generate the array content.
62 array_lines = [] 75 array_lines = []
63 field_info['contents']['field'] = var; 76 field_info['contents']['field'] = var;
64 array_lines.append(struct_generator.GenerateField( 77 array_lines.append(struct_generator.GenerateField(
65 field_info['contents']) + '[] = {') 78 field_info['contents']) + '[] = {')
66 for subcontent in content: 79 for subcontent in content:
67 GenerateFieldContent(element_name, field_info['contents'], subcontent, 80 GenerateFieldContent(element_name, field_info['contents'], subcontent,
68 array_lines) 81 array_lines, indent)
69 array_lines.append('};') 82 array_lines.append('};')
70 # Prepend the generated array so it is initialized before the structure. 83 # Prepend the generated array so it is initialized before the structure.
71 lines.reverse() 84 lines.reverse()
72 array_lines.reverse() 85 array_lines.reverse()
73 lines.extend(array_lines) 86 lines.extend(array_lines)
74 lines.reverse() 87 lines.reverse()
75 88
76 def GenerateFieldContent(element_name, field_info, content, lines): 89 def _GenerateObject(element_name, field_info, content, lines, indent=' '):
90 """Generates an object to be included in a static structure initializer. If
91 content is not specified, uses {0}.
beaudoin 2015/07/06 16:01:11 Why {0}? Is this always a valid C++ object? Just f
danduong 2015/07/08 23:07:03 {0} should compile. That will initialize the first
92 """
93 if content is None:
94 lines.append(indent + '{0},')
95 return
96
97 fields = field_info['fields']
98 lines.append(indent + '{')
99 for field in fields:
100 subcontent = content.get(field['field'])
101 GenerateFieldContent(element_name, field, subcontent, lines, ' ' + indent)
102 lines.append(indent + '},')
103
104 def GenerateFieldContent(element_name, field_info, content, lines, indent=' '):
77 """Generate the content of a field to be included in the static structure 105 """Generate the content of a field to be included in the static structure
78 initializer. If the field's content is not specified, uses the default value 106 initializer. If the field's content is not specified, uses the default value
79 if one exists. 107 if one exists.
80 """ 108 """
81 if content is None: 109 if content is None:
82 content = field_info.get('default', None) 110 content = field_info.get('default', None)
83 type = field_info['type'] 111 type = field_info['type']
84 if type == 'int' or type == 'enum': 112 if type == 'int' or type == 'enum':
85 lines.append(' %s,' % content) 113 lines.append('%s%s,' % (indent, content))
86 elif type == 'string': 114 elif type == 'string':
87 _GenerateString(content, lines) 115 _GenerateString(content, lines, indent)
88 elif type == 'string16': 116 elif type == 'string16':
89 _GenerateString16(content, lines) 117 _GenerateString16(content, lines, indent)
90 elif type == 'array': 118 elif type == 'array':
91 _GenerateArray(element_name, field_info, content, lines) 119 _GenerateArray(element_name, field_info, content, lines, indent)
120 elif type == 'object':
121 _GenerateObject(element_name, field_info, content, lines, indent)
92 else: 122 else:
93 raise RuntimeError('Unknown field type "%s"' % type) 123 raise RuntimeError('Unknown field type "%s"' % type)
94 124
95 def GenerateElement(type_name, schema, element_name, element): 125 def GenerateElement(type_name, schema, element_name, element):
96 """Generate the static structure initializer for one element. 126 """Generate the static structure initializer for one element.
97 """ 127 """
98 lines = []; 128 lines = [];
99 lines.append('const %s %s = {' % (type_name, element_name)); 129 lines.append('const %s %s = {' % (type_name, element_name));
100 for field_info in schema: 130 for field_info in schema:
101 content = element.get(field_info['field'], None) 131 content = element.get(field_info['field'], None)
(...skipping 11 matching lines...) Expand all
113 """ 143 """
114 result = []; 144 result = [];
115 for var_name, value in description.get('int_variables', {}).items(): 145 for var_name, value in description.get('int_variables', {}).items():
116 result.append('const int %s = %s;' % (var_name, value)) 146 result.append('const int %s = %s;' % (var_name, value))
117 result.append('') 147 result.append('')
118 148
119 for element_name, element in description.get('elements', {}).items(): 149 for element_name, element in description.get('elements', {}).items():
120 result.append(GenerateElement(type_name, schema, element_name, element)) 150 result.append(GenerateElement(type_name, schema, element_name, element))
121 result.append('') 151 result.append('')
122 return '\n'.join(result) 152 return '\n'.join(result)
OLDNEW
« no previous file with comments | « no previous file | tools/json_to_struct/element_generator_test.py » ('j') | tools/json_to_struct/json_to_struct.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698