2 # Copyright 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 # Format for the JSON schema file:
8 # "type_name": "DesiredCStructName",
9 # "headers": [ // Optional list of headers to be included by the .h.
12 # "schema": [ // Fields of the generated structure.
14 # "field": "my_enum_field",
15 # "type": "enum", // Either: int, string, string16, enum, array, struct.
16 # "default": "RED", // Optional. Cannot be used for array.
17 # "ctype": "Color" // Only for enum, specify the C type.
20 # "field": "my_int_array_field", // my_int_array_field_size will also
21 # "type": "array", // be generated.
23 # "type": "int" // Either: int, string, string16, enum, array.
27 # "field": "my_struct_field",
28 # "type_name": "PointStuct",
31 # {"field": "x", "type": "int"},
32 # {"field": "y", "type": "int"}
39 # Format for the JSON description file:
41 # "int_variables": { // An optional list of constant int variables.
42 # "kDesiredConstantName": 45
44 # "elements": { // All the elements for which to create static
45 # // initialization code in the .cc file.
46 # "my_const_variable": {
48 # "my_string_field": "foo bar",
49 # "my_enum_field": "BLACK",
50 # "my_int_array_field": [ 1, 2, 3, 5, 7 ],
51 # "my_struct_field": {"x": 1, "y": 2}
53 # "my_other_const_variable": {
60 from datetime
import datetime
65 _script_path
= os
.path
.realpath(__file__
)
67 sys
.path
.insert(0, os
.path
.normpath(_script_path
+ "/../../json_comment_eater"))
69 import json_comment_eater
73 import struct_generator
74 import element_generator
76 HEAD
= """// Copyright %d The Chromium Authors. All rights reserved.
77 // Use of this source code is governed by a BSD-style license that can be
78 // found in the LICENSE file.
80 // GENERATED FROM THE SCHEMA DEFINITION AND DESCRIPTION IN
87 def _GenerateHeaderGuard(h_filename
):
88 """Generates the string used in #ifndef guarding the header file.
90 result
= re
.sub('[%s\\\\.]' % os
.sep
, '_', h_filename
.upper())
91 return re
.sub('^_*', '', result
) + '_' # Remove leading underscores.
93 def _GenerateH(basepath
, fileroot
, head
, namespace
, schema
, description
):
94 """Generates the .h file containing the definition of the structure specified
98 basepath: The base directory in which files are generated.
99 fileroot: The filename and path, relative to basepath, of the file to
100 create, without an extension.
101 head: The string to output as the header of the .h file.
102 namespace: A string corresponding to the C++ namespace to use.
103 schema: A dict containing the schema. See comment at the top of this file.
104 description: A dict containing the description. See comment at the top of
108 h_filename
= fileroot
+ '.h'
109 with
open(os
.path
.join(basepath
, h_filename
), 'w') as f
:
112 header_guard
= _GenerateHeaderGuard(h_filename
)
113 f
.write('#ifndef %s\n' % header_guard
)
114 f
.write('#define %s\n' % header_guard
)
117 f
.write('#include <cstddef>\n')
120 for header
in schema
.get('headers', []):
121 f
.write('#include "%s"\n' % header
)
125 f
.write('namespace %s {\n' % namespace
)
128 f
.write(struct_generator
.GenerateStruct(
129 schema
['type_name'], schema
['schema']))
132 for var_name
, value
in description
.get('int_variables', {}).items():
133 f
.write('extern const int %s;\n' % var_name
)
136 for element_name
, element
in description
['elements'].items():
137 f
.write('extern const %s %s;\n' % (schema
['type_name'], element_name
))
141 f
.write('} // namespace %s\n' % namespace
)
144 f
.write( '#endif // %s\n' % header_guard
)
146 def _GenerateCC(basepath
, fileroot
, head
, namespace
, schema
, description
):
147 """Generates the .cc file containing the static initializers for the
148 of the elements specified in the description.
151 basepath: The base directory in which files are generated.
152 fileroot: The filename and path, relative to basepath, of the file to
153 create, without an extension.
154 head: The string to output as the header of the .cc file.
155 namespace: A string corresponding to the C++ namespace to use.
156 schema: A dict containing the schema. See comment at the top of this file.
157 description: A dict containing the description. See comment at the top of
161 with
open(os
.path
.join(basepath
, fileroot
+ '.cc'), 'w') as f
:
164 f
.write('#include "%s"\n' % (fileroot
+ '.h'))
168 f
.write('namespace %s {\n' % namespace
)
171 f
.write(element_generator
.GenerateElements(schema
['type_name'],
172 schema
['schema'], description
))
176 f
.write('} // namespace %s\n' % namespace
)
179 """Loads a JSON file int a Python object and return this object.
181 # TODO(beaudoin): When moving to Python 2.7 use object_pairs_hook=OrderedDict.
182 with
open(filename
, 'r') as handle
:
183 result
= json
.loads(json_comment_eater
.Nom(handle
.read()))
186 def GenerateStruct(basepath
, output_root
, namespace
, schema
, description
,
187 description_filename
, schema_filename
, year
=None):
188 """Generates a C++ struct from a JSON description.
191 basepath: The base directory in which files are generated.
192 output_root: The filename and path, relative to basepath, of the file to
193 create, without an extension.
194 namespace: A string corresponding to the C++ namespace to use.
195 schema: A dict containing the schema. See comment at the top of this file.
196 description: A dict containing the description. See comment at the top of
198 description_filename: The description filename. This is added to the
199 header of the outputted files.
200 schema_filename: The schema filename. This is added to the header of the
202 year: Year to display next to the copy-right in the header.
204 year
= int(year
) if year
else datetime
.now().year
205 head
= HEAD
% (year
, schema_filename
, description_filename
)
206 _GenerateH(basepath
, output_root
, head
, namespace
, schema
, description
)
207 _GenerateCC(basepath
, output_root
, head
, namespace
, schema
, description
)
209 if __name__
== '__main__':
210 parser
= optparse
.OptionParser(
211 description
='Generates an C++ array of struct from a JSON description.',
212 usage
='usage: %prog [option] -s schema description')
213 parser
.add_option('-b', '--destbase',
214 help='base directory of generated files.')
215 parser
.add_option('-d', '--destdir',
216 help='directory to output generated files, relative to destbase.')
217 parser
.add_option('-n', '--namespace',
218 help='C++ namespace for generated files. e.g search_providers.')
219 parser
.add_option('-s', '--schema', help='path to the schema file, '
221 parser
.add_option('-o', '--output', help='output filename, ')
222 (opts
, args
) = parser
.parse_args()
225 parser
.error('You must specify a --schema.')
227 description_filename
= os
.path
.normpath(args
[0])
228 root
, ext
= os
.path
.splitext(description_filename
)
229 shortroot
= opts
.output
if opts
.output
else os
.path
.split(root
)[1]
231 output_root
= os
.path
.join(os
.path
.normpath(opts
.destdir
), shortroot
)
233 output_root
= shortroot
236 basepath
= os
.path
.normpath(opts
.destbase
)
240 schema
= _Load(opts
.schema
)
241 description
= _Load(description_filename
)
242 GenerateStruct(basepath
, output_root
, opts
.namespace
, schema
, description
,
243 description_filename
, opts
.schema
)