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
3 # found in the LICENSE file.
6 import struct_generator
8 def _JSONToCString16(json_string_literal
):
9 """Converts a JSON string literal to a C++ UTF-16 string literal. This is
10 done by converting \\u#### to \\x####.
12 c_string_literal
= json_string_literal
13 escape_index
= c_string_literal
.find('\\')
14 while escape_index
> 0:
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
17 # after, otherwise the Windows compiler will sometimes try to get more
18 # than 4 characters in the hex string.
19 c_string_literal
= (c_string_literal
[0:escape_index
+ 1] + 'x' +
20 c_string_literal
[escape_index
+ 2:escape_index
+ 6] + '" L"' +
21 c_string_literal
[escape_index
+ 6:])
22 escape_index
= c_string_literal
.find('\\', escape_index
+ 6)
23 return c_string_literal
25 def _GenerateString(content
, lines
):
26 """Generates an UTF-8 string to be included in a static structure initializer.
27 If content is not specified, uses NULL.
30 lines
.append(' NULL,')
32 # json.dumps quotes the string and escape characters as required.
33 lines
.append(' %s,' % json
.dumps(content
))
35 def _GenerateString16(content
, lines
):
36 """Generates an UTF-16 string to be included in a static structure
37 initializer. If content is not specified, uses NULL.
40 lines
.append(' NULL,')
42 # json.dumps quotes the string and escape characters as required.
43 lines
.append(' L%s,' % _JSONToCString16(json
.dumps(content
)))
45 def _GenerateArray(element_name
, field_info
, content
, lines
):
46 """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
48 variable which is initialized before the structure.
51 lines
.append(' NULL,')
52 lines
.append(' 0,') # Size of the array.
55 # Create a new array variable and use it in the structure initializer.
56 # This prohibits nested arrays. Add a clash detection and renaming mechanism
57 # to solve the problem.
58 var
= 'array_%s_%s' % (element_name
, field_info
['field']);
59 lines
.append(' %s,' % var
)
60 lines
.append(' %s,' % len(content
)) # Size of the array.
61 # Generate the array content.
63 field_info
['contents']['field'] = var
;
64 array_lines
.append(struct_generator
.GenerateField(
65 field_info
['contents']) + '[] = {')
66 for subcontent
in content
:
67 GenerateFieldContent(element_name
, field_info
['contents'], subcontent
,
69 array_lines
.append('};')
70 # Prepend the generated array so it is initialized before the structure.
73 lines
.extend(array_lines
)
76 def GenerateFieldContent(element_name
, field_info
, content
, lines
):
77 """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
82 content
= field_info
.get('default', None)
83 type = field_info
['type']
84 if type == 'int' or type == 'enum':
85 lines
.append(' %s,' % content
)
86 elif type == 'string':
87 _GenerateString(content
, lines
)
88 elif type == 'string16':
89 _GenerateString16(content
, lines
)
91 _GenerateArray(element_name
, field_info
, content
, lines
)
93 raise RuntimeError('Unknown field type "%s"' % type)
95 def GenerateElement(type_name
, schema
, element_name
, element
):
96 """Generate the static structure initializer for one element.
99 lines
.append('const %s %s = {' % (type_name
, element_name
));
100 for field_info
in schema
:
101 content
= element
.get(field_info
['field'], None)
102 if (content
== None and not field_info
.get('optional', False)):
103 raise RuntimeError('Mandatory field "%s" omitted in element "%s".' %
104 (field_info
['field'], element_name
))
105 GenerateFieldContent(element_name
, field_info
, content
, lines
)
107 return '\n'.join(lines
)
109 def GenerateElements(type_name
, schema
, description
):
110 """Generate the static structure initializer for all the elements in the
111 description['elements'] dictionary, as well as for any variables in
112 description['int_variables'].
115 for var_name
, value
in description
.get('int_variables', {}).items():
116 result
.append('const int %s = %s;' % (var_name
, value
))
119 for element_name
, element
in description
.get('elements', {}).items():
120 result
.append(GenerateElement(type_name
, schema
, element_name
, element
))
122 return '\n'.join(result
)