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

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: add test 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
« no previous file with comments | « no previous file | tools/json_to_struct/element_generator_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 def _JSONToCString16(json_string_literal): 8 def _JSONToCString16(json_string_literal):
9 """Converts a JSON string literal to a C++ UTF-16 string literal. This is 9 """Converts a JSON string literal to a C++ UTF-16 string literal. This is
10 done by converting \\u#### to \\x####. 10 done by converting \\u#### to \\x####.
11 """ 11 """
12 c_string_literal = json_string_literal 12 c_string_literal = json_string_literal
13 escape_index = c_string_literal.find('\\') 13 escape_index = c_string_literal.find('\\')
14 while escape_index > 0: 14 while escape_index > 0:
15 if c_string_literal[escape_index + 1] == 'u': 15 if c_string_literal[escape_index + 1] == 'u':
16 # We close the C string literal after the 4 hex digits and reopen it right 16 # 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 17 # after, otherwise the Windows compiler will sometimes try to get more
18 # than 4 characters in the hex string. 18 # than 4 characters in the hex string.
19 c_string_literal = (c_string_literal[0:escape_index + 1] + 'x' + 19 c_string_literal = (c_string_literal[0:escape_index + 1] + 'x' +
20 c_string_literal[escape_index + 2:escape_index + 6] + '" L"' + 20 c_string_literal[escape_index + 2:escape_index + 6] + '" L"' +
21 c_string_literal[escape_index + 6:]) 21 c_string_literal[escape_index + 6:])
22 escape_index = c_string_literal.find('\\', escape_index + 6) 22 escape_index = c_string_literal.find('\\', escape_index + 6)
23 return c_string_literal 23 return c_string_literal
24 24
25 def _GenerateString(content, lines): 25 def _GenerateString(content, lines, indent=' '):
26 """Generates an UTF-8 string to be included in a static structure initializer. 26 """Generates an UTF-8 string to be included in a static structure initializer.
27 If content is not specified, uses NULL. 27 If content is not specified, uses NULL.
28 """ 28 """
29 if content is None: 29 if content is None:
30 lines.append(' NULL,') 30 lines.append(indent + 'NULL,')
31 else: 31 else:
32 # json.dumps quotes the string and escape characters as required. 32 # json.dumps quotes the string and escape characters as required.
33 lines.append(' %s,' % json.dumps(content)) 33 lines.append(indent + '%s,' % json.dumps(content))
34 34
35 def _GenerateString16(content, lines): 35 def _GenerateString16(content, lines, indent=' '):
36 """Generates an UTF-16 string to be included in a static structure 36 """Generates an UTF-16 string to be included in a static structure
37 initializer. If content is not specified, uses NULL. 37 initializer. If content is not specified, uses NULL.
38 """ 38 """
39 if content is None: 39 if content is None:
40 lines.append(' NULL,') 40 lines.append(indent + 'NULL,')
41 else: 41 else:
42 # json.dumps quotes the string and escape characters as required. 42 # json.dumps quotes the string and escape characters as required.
43 lines.append(' L%s,' % _JSONToCString16(json.dumps(content))) 43 lines.append(indent + 'L%s,' % _JSONToCString16(json.dumps(content)))
44 44
45 def _GenerateArray(element_name, field_info, content, lines): 45 def _GenerateArrayVariableName(element_name, field_name, field_name_count):
46 # Generates a unique variable name for an array variable.
47 var = 'array_%s_%s' % (element_name, field_name)
48 if var not in field_name_count:
49 field_name_count[var] = 0
50 return var
51 new_var = '%s_%d' % (var, field_name_count[var])
52 field_name_count[var] += 1
53 return new_var
54
55 def _GenerateArray(element_name, field_info, content, lines, indent,
56 field_name_count):
46 """Generates an array to be included in a static structure initializer. If 57 """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 58 content is not specified, uses NULL. The array is assigned to a temporary
48 variable which is initialized before the structure. 59 variable which is initialized before the structure.
49 """ 60 """
50 if content is None: 61 if content is None:
51 lines.append(' NULL,') 62 lines.append(indent + 'NULL,')
52 lines.append(' 0,') # Size of the array. 63 lines.append(indent + '0,') # Size of the array.
53 return 64 return
54 65
55 # Create a new array variable and use it in the structure initializer. 66 # Create a new array variable and use it in the structure initializer.
56 # This prohibits nested arrays. Add a clash detection and renaming mechanism 67 # This prohibits nested arrays. Add a clash detection and renaming mechanism
57 # to solve the problem. 68 # to solve the problem.
58 var = 'array_%s_%s' % (element_name, field_info['field']); 69 var = _GenerateArrayVariableName(element_name, field_info['field'],
59 lines.append(' %s,' % var) 70 field_name_count)
60 lines.append(' %s,' % len(content)) # Size of the array. 71 lines.append(indent + '%s,' % var)
72 lines.append(indent + '%s,' % len(content)) # Size of the array.
61 # Generate the array content. 73 # Generate the array content.
62 array_lines = [] 74 array_lines = []
63 field_info['contents']['field'] = var; 75 field_info['contents']['field'] = var;
64 array_lines.append(struct_generator.GenerateField( 76 array_lines.append(struct_generator.GenerateField(
65 field_info['contents']) + '[] = {') 77 field_info['contents']) + '[] = {')
66 for subcontent in content: 78 for subcontent in content:
67 GenerateFieldContent(element_name, field_info['contents'], subcontent, 79 GenerateFieldContent(element_name, field_info['contents'], subcontent,
68 array_lines) 80 array_lines, indent, field_name_count)
69 array_lines.append('};') 81 array_lines.append('};')
70 # Prepend the generated array so it is initialized before the structure. 82 # Prepend the generated array so it is initialized before the structure.
71 lines.reverse() 83 lines.reverse()
72 array_lines.reverse() 84 array_lines.reverse()
73 lines.extend(array_lines) 85 lines.extend(array_lines)
74 lines.reverse() 86 lines.reverse()
75 87
76 def GenerateFieldContent(element_name, field_info, content, lines): 88 def _GenerateStruct(element_name, field_info, content, lines, indent,
89 field_name_count):
90 """Generates a struct to be included in a static structure initializer. If
91 content is not specified, uses {0}.
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 field_name_count)
103 lines.append(indent + '},')
104
105 def GenerateFieldContent(element_name, field_info, content, lines, indent,
106 field_name_count):
77 """Generate the content of a field to be included in the static structure 107 """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 108 initializer. If the field's content is not specified, uses the default value
79 if one exists. 109 if one exists.
80 """ 110 """
81 if content is None: 111 if content is None:
82 content = field_info.get('default', None) 112 content = field_info.get('default', None)
83 type = field_info['type'] 113 type = field_info['type']
84 if type == 'int' or type == 'enum': 114 if type == 'int' or type == 'enum':
85 lines.append(' %s,' % content) 115 lines.append('%s%s,' % (indent, content))
86 elif type == 'string': 116 elif type == 'string':
87 _GenerateString(content, lines) 117 _GenerateString(content, lines, indent)
88 elif type == 'string16': 118 elif type == 'string16':
89 _GenerateString16(content, lines) 119 _GenerateString16(content, lines, indent)
90 elif type == 'array': 120 elif type == 'array':
91 _GenerateArray(element_name, field_info, content, lines) 121 _GenerateArray(element_name, field_info, content, lines, indent,
122 field_name_count)
123 elif type == 'struct':
124 _GenerateStruct(element_name, field_info, content, lines, indent,
125 field_name_count)
92 else: 126 else:
93 raise RuntimeError('Unknown field type "%s"' % type) 127 raise RuntimeError('Unknown field type "%s"' % type)
94 128
95 def GenerateElement(type_name, schema, element_name, element): 129 def GenerateElement(type_name, schema, element_name, element, field_name_count):
96 """Generate the static structure initializer for one element. 130 """Generate the static structure initializer for one element.
97 """ 131 """
98 lines = []; 132 lines = [];
99 lines.append('const %s %s = {' % (type_name, element_name)); 133 lines.append('const %s %s = {' % (type_name, element_name));
100 for field_info in schema: 134 for field_info in schema:
101 content = element.get(field_info['field'], None) 135 content = element.get(field_info['field'], None)
102 if (content == None and not field_info.get('optional', False)): 136 if (content == None and not field_info.get('optional', False)):
103 raise RuntimeError('Mandatory field "%s" omitted in element "%s".' % 137 raise RuntimeError('Mandatory field "%s" omitted in element "%s".' %
104 (field_info['field'], element_name)) 138 (field_info['field'], element_name))
105 GenerateFieldContent(element_name, field_info, content, lines) 139 GenerateFieldContent(element_name, field_info, content, lines, ' ',
140 field_name_count)
106 lines.append('};') 141 lines.append('};')
107 return '\n'.join(lines) 142 return '\n'.join(lines)
108 143
109 def GenerateElements(type_name, schema, description): 144 def GenerateElements(type_name, schema, description, field_name_count={}):
110 """Generate the static structure initializer for all the elements in the 145 """Generate the static structure initializer for all the elements in the
111 description['elements'] dictionary, as well as for any variables in 146 description['elements'] dictionary, as well as for any variables in
112 description['int_variables']. 147 description['int_variables'].
113 """ 148 """
114 result = []; 149 result = [];
115 for var_name, value in description.get('int_variables', {}).items(): 150 for var_name, value in description.get('int_variables', {}).items():
116 result.append('const int %s = %s;' % (var_name, value)) 151 result.append('const int %s = %s;' % (var_name, value))
117 result.append('') 152 result.append('')
118 153
119 for element_name, element in description.get('elements', {}).items(): 154 for element_name, element in description.get('elements', {}).items():
120 result.append(GenerateElement(type_name, schema, element_name, element)) 155 result.append(GenerateElement(type_name, schema, element_name, element,
156 field_name_count))
121 result.append('') 157 result.append('')
122 return '\n'.join(result) 158 return '\n'.join(result)
OLDNEW
« no previous file with comments | « no previous file | tools/json_to_struct/element_generator_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698