1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import class_generator
_INDENT = ' '
def _GenerateString(content, indent=' '):
"""Generates an UTF-8 string to be included in a static structure initializer.
If content is not specified, uses NULL.
"""
if content is None:
return indent + 'null,'
else:
# json.dumps quotes the string and escape characters as required.
return indent + '%s,' % json.dumps(content)
def _GenerateArrayVariableName(element_name, field_name, field_name_count):
"""Generates a unique variable name for an array variable.
"""
var = '%s_%s' % (element_name, field_name)
if var not in field_name_count:
field_name_count[var] = 0
return var
new_var = '%s_%d' % (var, field_name_count[var])
field_name_count[var] += 1
return new_var
def _GenerateArray(element_name, field_info, content, indent, field_name_count):
"""Generates an array created inline in a constructor call. If content is
not specified, null is used.
"""
if content is None:
return indent + 'null,'
lines = []
array_field = class_generator.GenerateField(field_info['contents'])
array_type = array_field[:array_field.find(' ')]
lines.append(indent + 'new %s[]{' % array_type)
for subcontent in content:
lines.append(
_GenerateFieldContent(element_name, field_info['contents'], subcontent,
indent + _INDENT, field_name_count))
lines.append(indent + '},')
return '\n'.join(lines)
def _GenerateClass(element_name, field_info, content, indent, field_name_count):
"""Generates a class to be used in a constructor call. If content is not
specified, use null.
"""
if content is None:
return indent + 'null'
lines = []
fields = field_info['fields']
class_name = field_info['type_name']
lines.append(indent + 'new ' + class_name + '(')
for field in fields:
subcontent = content.get(field['field'])
lines.append(
_GenerateFieldContent(element_name, field, subcontent, indent + _INDENT,
field_name_count))
# remove the trailing comma for the last parameter
lines[-1] = lines[-1][:-1]
lines.append(indent + '),')
return '\n'.join(lines)
def _GenerateFieldContent(element_name, field_info, content, indent,
field_name_count):
"""Generate the content of a field to be included in the constructor call. If
the field's content is not specified, uses the default value if one exists.
"""
if content is None:
content = field_info.get('java_default', None)
java_type = field_info['type']
if java_type in ('int', 'class'):
return '%s%s,' % (indent, content)
elif java_type == 'enum':
# TODO(peilinwang) temporarily treat enums as strings. Maybe use a
# different schema? Right now these scripts are only used for generating
# fieldtrial testing configs.
return '%s"%s",' % (indent, content)
elif java_type == 'string':
return _GenerateString(content, indent)
elif java_type == 'string16':
raise RuntimeError('Generating a UTF16 java String is not supported yet.')
elif java_type == 'array':
return _GenerateArray(element_name, field_info, content, indent,
field_name_count)
elif java_type == 'struct':
return _GenerateClass(element_name, field_info, content, indent,
field_name_count)
else:
raise RuntimeError('Unknown field type "%s"' % java_type)
def _GenerateElement(type_name, schema, element_name, element,
field_name_count):
"""Generate the constructor call for one element.
"""
lines = []
lines.append(_INDENT + 'public static final %s %s = ' %
(type_name, element_name))
lines.append(2 * _INDENT + 'new %s(' % (type_name))
for field_info in schema:
content = element.get(field_info['field'], None)
if (content == None and not field_info.get('optional', False)):
raise RuntimeError('Mandatory field "%s" omitted in element "%s".' %
(field_info['field'], element_name))
lines.append(
_GenerateFieldContent(element_name, field_info, content, 2 * _INDENT,
field_name_count))
# remove the trailing comma for the last parameter
lines[-1] = lines[-1][:-1]
lines.append(2 * _INDENT + ');')
return '\n'.join(lines)
def GenerateElements(type_name, schema, description, field_name_count={}):
"""Generate the static initializers for all the elements in the
description['elements'] dictionary, as well as for any variables in
description['int_variables']. All elements in description['elements']
will be generated as a public static final int/class.
"""
result = []
for var_name, value in description.get('int_variables', {}).items():
result.append('public static final int %s = %s;' % (var_name, value))
result.append('')
for element_name, element in description.get('elements', {}).items():
result.append(
_GenerateElement(type_name, schema, element_name, element,
field_name_count))
result.append('')
return '\n'.join(result)
|