Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 '''python %prog [options] platform chromium_os_flag template | 6 '''python %prog [options] platform chromium_os_flag template |
| 7 | 7 |
| 8 platform specifies which platform source is being generated for | 8 platform specifies which platform source is being generated for |
| 9 and can be one of (win, mac, linux) | 9 and can be one of (win, mac, linux) |
| 10 chromium_os_flag should be 1 if this is a Chromium OS build | 10 chromium_os_flag should be 1 if this is a Chromium OS build |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 | 250 |
| 251 # A mapping of the simple schema types to base::Value::Types. | 251 # A mapping of the simple schema types to base::Value::Types. |
| 252 SIMPLE_SCHEMA_NAME_MAP = { | 252 SIMPLE_SCHEMA_NAME_MAP = { |
| 253 'boolean': 'TYPE_BOOLEAN', | 253 'boolean': 'TYPE_BOOLEAN', |
| 254 'integer': 'TYPE_INTEGER', | 254 'integer': 'TYPE_INTEGER', |
| 255 'null' : 'TYPE_NULL', | 255 'null' : 'TYPE_NULL', |
| 256 'number' : 'TYPE_DOUBLE', | 256 'number' : 'TYPE_DOUBLE', |
| 257 'string' : 'TYPE_STRING', | 257 'string' : 'TYPE_STRING', |
| 258 } | 258 } |
| 259 | 259 |
| 260 | |
| 261 class SchemaNodesGenerator: | 260 class SchemaNodesGenerator: |
| 262 """Builds the internal structs to represent a JSON schema.""" | 261 """Builds the internal structs to represent a JSON schema.""" |
| 263 | 262 |
| 264 def __init__(self, shared_strings): | 263 def __init__(self, shared_strings): |
| 265 """Creates a new generator. | 264 """Creates a new generator. |
| 266 | 265 |
| 267 |shared_strings| is a map of strings to a C expression that evaluates to | 266 |shared_strings| is a map of strings to a C expression that evaluates to |
| 268 that string at runtime. This mapping can be used to reuse existing string | 267 that string at runtime. This mapping can be used to reuse existing string |
| 269 constants.""" | 268 constants.""" |
| 270 self.shared_strings = shared_strings | 269 self.shared_strings = shared_strings |
| 271 self.schema_nodes = [] | 270 self.schema_nodes = [] |
| 272 self.property_nodes = [] | 271 self.property_nodes = [] |
| 273 self.properties_nodes = [] | 272 self.properties_nodes = [] |
| 273 self.restriction_nodes = [] | |
| 274 self.int_enums = [] | |
| 275 self.string_enums = [] | |
| 274 self.simple_types = { | 276 self.simple_types = { |
| 275 'boolean': None, | 277 'boolean': None, |
| 276 'integer': None, | 278 'integer': None, |
| 277 'null': None, | 279 'null': None, |
| 278 'number': None, | 280 'number': None, |
| 279 'string': None, | 281 'string': None, |
| 280 } | 282 } |
| 281 self.stringlist_type = None | 283 self.stringlist_type = None |
| 282 | 284 |
| 283 def GetString(self, s): | 285 def GetString(self, s): |
| 284 return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s | 286 return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s |
| 285 | 287 |
| 286 def AppendSchema(self, type, extra, comment=''): | 288 def AppendSchema(self, type, extra, comment=''): |
| 287 index = len(self.schema_nodes) | 289 index = len(self.schema_nodes) |
| 288 self.schema_nodes.append((type, extra, comment)) | 290 self.schema_nodes.append((type, extra, comment)) |
| 289 return index | 291 return index |
| 290 | 292 |
| 293 def AppendRestriction(self, first, second): | |
| 294 index = len(self.restriction_nodes) | |
| 295 self.restriction_nodes.append((first, second)) | |
| 296 return index | |
| 297 | |
| 291 def GetSimpleType(self, name): | 298 def GetSimpleType(self, name): |
| 292 if self.simple_types[name] == None: | 299 if self.simple_types[name] == None: |
| 293 self.simple_types[name] = self.AppendSchema( | 300 self.simple_types[name] = self.AppendSchema( |
| 294 SIMPLE_SCHEMA_NAME_MAP[name], | 301 SIMPLE_SCHEMA_NAME_MAP[name], |
| 295 -1, | 302 -1, |
| 296 'simple type: ' + name) | 303 'simple type: ' + name) |
| 297 return self.simple_types[name] | 304 return self.simple_types[name] |
| 298 | 305 |
| 299 def GetStringList(self): | 306 def GetStringList(self): |
| 300 if self.stringlist_type == None: | 307 if self.stringlist_type == None: |
| 301 self.stringlist_type = self.AppendSchema( | 308 self.stringlist_type = self.AppendSchema( |
| 302 'TYPE_LIST', | 309 'TYPE_LIST', |
| 303 self.GetSimpleType('string'), | 310 self.GetSimpleType('string'), |
| 304 'simple type: stringlist') | 311 'simple type: stringlist') |
| 305 return self.stringlist_type | 312 return self.stringlist_type |
| 306 | 313 |
| 314 def SchemaHaveRestriction(self, schema): | |
| 315 return 'minimum' in schema or 'maximum' in schema or 'enum' in schema | |
| 316 | |
| 317 def GetEnumIntegerType(self, schema): | |
| 318 offset_begin = len(self.int_enums) | |
|
Joao da Silva
2014/01/16 10:56:34
Add a check at the beginning:
assert all(type(x
Joao da Silva
2014/01/16 10:56:34
You had a nice idea about converting enums into ra
binjin
2014/01/17 14:29:01
Done.
binjin
2014/01/17 14:29:01
Done.
| |
| 319 self.int_enums += schema['enum'] | |
| 320 offset_end = len(self.int_enums) | |
| 321 return self.AppendSchema('TYPE_INTEGER', | |
| 322 self.AppendRestriction(offset_begin, offset_end), | |
| 323 'integer with enumeration restriction') | |
|
Joao da Silva
2014/01/16 10:56:34
Use "name" (from Generate()) for the 3rd argument
binjin
2014/01/17 14:29:01
Done.
| |
| 324 | |
| 325 def GetEnumStringType(self, schema): | |
| 326 offset_begin = len(self.string_enums) | |
|
Joao da Silva
2014/01/16 10:56:34
Add a check at the beginning:
assert all(type(x
binjin
2014/01/17 14:29:01
Done.
| |
| 327 self.string_enums += schema['enum'] | |
| 328 offset_end = len(self.string_enums) | |
| 329 return self.AppendSchema('TYPE_STRING', | |
| 330 self.AppendRestriction(offset_begin, offset_end), | |
| 331 'string with enumeration restriction') | |
|
Joao da Silva
2014/01/16 10:56:34
Use "name" from Generate() for the 3rd argument
binjin
2014/01/17 14:29:01
Done.
| |
| 332 | |
| 333 def GetEnumType(self, schema): | |
| 334 if len(schema['enum']) == 0: | |
| 335 raise RuntiemError('Empty enumeration in %s' % schema['name']) | |
|
Joao da Silva
2014/01/16 10:56:34
RuntimeError
schema['name'] does not exist; you h
binjin
2014/01/17 14:29:01
Done.
| |
| 336 elif schema['type'] == 'integer': | |
| 337 return self.GetEnumIntegerType(schema) | |
| 338 elif schema['type'] == 'string': | |
| 339 return self.GetEnumStringType(schema) | |
| 340 else: | |
| 341 raise RuntimeError('Unknown enumeration type in %s' % schema['name']) | |
|
Joao da Silva
2014/01/16 10:56:34
schema['name'] does not exist
binjin
2014/01/17 14:29:01
Done.
| |
| 342 | |
| 343 def GetRangedType(self, schema): | |
| 344 if schema['type'] != 'integer': | |
| 345 raise RuntimeError('Unknown ranged type in %s' % schema['name']) | |
|
Joao da Silva
2014/01/16 10:56:34
schema['name' does not exist; pass "name" from Gen
binjin
2014/01/17 14:29:01
Done.
| |
| 346 min_value_set, max_value_set = False, False | |
| 347 if 'minimum' in schema: | |
| 348 min_value = int(schema['minimum']) | |
| 349 min_value_set = True | |
| 350 if 'maximum' in schema: | |
| 351 max_value = int(schema['minimum']) | |
| 352 max_value_set = True | |
| 353 if min_value_set and max_value_set and min_value > max_value: | |
| 354 raise RuntimeError('Invalid ranged type in %s' % schema['name']) | |
|
Joao da Silva
2014/01/16 10:56:34
schema['name'] does not exist
binjin
2014/01/17 14:29:01
Done.
| |
| 355 index = self.AppendRestriction( | |
| 356 str(max_value) if max_value_set else 'INT_MAX', | |
| 357 str(min_value) if min_value_set else 'INT_MIN') | |
| 358 return self.AppendSchema('TYPE_INTEGER', | |
| 359 index, | |
| 360 'integer with ranged restriction') | |
|
Joao da Silva
2014/01/16 10:56:34
Use "name" for the 3rd argument
binjin
2014/01/17 14:29:01
Done.
| |
| 361 | |
| 307 def Generate(self, schema, name): | 362 def Generate(self, schema, name): |
| 308 """Generates the structs for the given schema. | 363 """Generates the structs for the given schema. |
| 309 | 364 |
| 310 |schema|: a valid JSON schema in a dictionary. | 365 |schema|: a valid JSON schema in a dictionary. |
| 311 |name|: the name of the current node, for the generated comments.""" | 366 |name|: the name of the current node, for the generated comments.""" |
| 312 # Simple types use shared nodes. | |
| 313 if schema['type'] in self.simple_types: | 367 if schema['type'] in self.simple_types: |
| 314 return self.GetSimpleType(schema['type']) | 368 if not self.SchemaHaveRestriction(schema): |
| 369 # Simple types use shared nodes. | |
| 370 return self.GetSimpleType(schema['type']) | |
| 371 elif 'enum' in schema: | |
| 372 return self.GetEnumType(schema) | |
| 373 else: | |
| 374 return self.GetRangedType(schema) | |
| 315 | 375 |
| 316 if schema['type'] == 'array': | 376 if schema['type'] == 'array': |
| 317 # Special case for lists of strings, which is a common policy type. | 377 # Special case for lists of strings, which is a common policy type. |
| 318 if schema['items']['type'] == 'string': | 378 if schema['items']['type'] == 'string': |
| 319 return self.GetStringList() | 379 return self.GetStringList() |
| 320 return self.AppendSchema( | 380 return self.AppendSchema( |
| 321 'TYPE_LIST', | 381 'TYPE_LIST', |
| 322 self.Generate(schema['items'], 'items of ' + name)) | 382 self.Generate(schema['items'], 'items of ' + name)) |
| 323 elif schema['type'] == 'object': | 383 elif schema['type'] == 'object': |
| 324 # Reserve an index first, so that dictionaries come before their | 384 # Reserve an index first, so that dictionaries come before their |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 key += ',' | 433 key += ',' |
| 374 f.write(' { %-50s %7d },\n' % (key, schema)) | 434 f.write(' { %-50s %7d },\n' % (key, schema)) |
| 375 f.write('};\n\n') | 435 f.write('};\n\n') |
| 376 | 436 |
| 377 f.write('const internal::PropertiesNode kProperties[] = {\n' | 437 f.write('const internal::PropertiesNode kProperties[] = {\n' |
| 378 '// Begin End Additional Properties\n') | 438 '// Begin End Additional Properties\n') |
| 379 for node in self.properties_nodes: | 439 for node in self.properties_nodes: |
| 380 f.write(' { %5d, %5d, %5d }, // %s\n' % node) | 440 f.write(' { %5d, %5d, %5d }, // %s\n' % node) |
| 381 f.write('};\n\n') | 441 f.write('};\n\n') |
| 382 | 442 |
| 443 f.write('const internal::RestrictionNode kRestrictionNodes[] = {\n') | |
| 444 for first, second in self.restriction_nodes: | |
| 445 f.write('{{%s,%s}},\n' % (first, second)) | |
|
Joao da Silva
2014/01/16 10:56:34
Use spacing and a header comment like the arrays a
binjin
2014/01/17 14:29:01
Done.
| |
| 446 f.write('};\n\n') | |
| 447 | |
| 448 f.write('const int kIntegerEnumerations[] = {\n') | |
| 449 for possible_values in self.int_enums: | |
| 450 f.write('%d,\n' % possible_values) | |
|
Joao da Silva
2014/01/16 10:56:34
Indent with 2 spaces
binjin
2014/01/17 14:29:01
Done.
| |
| 451 f.write('};\n\n') | |
| 452 | |
| 453 f.write('const char* kStringEnumerations[] = {\n') | |
| 454 for possible_values in self.string_enums: | |
| 455 f.write('%s\n' % self.GetString(possible_values)) | |
|
Joao da Silva
2014/01/16 10:56:34
Indent with 2 spaces
binjin
2014/01/17 14:29:01
Done.
| |
| 456 f.write('};\n\n') | |
| 457 | |
| 383 f.write('const internal::SchemaData kChromeSchemaData = {\n' | 458 f.write('const internal::SchemaData kChromeSchemaData = {\n' |
| 384 ' kSchemas,\n' | 459 ' kSchemas,\n' |
| 385 ' kPropertyNodes,\n' | 460 ' kPropertyNodes,\n' |
| 386 ' kProperties,\n' | 461 ' kProperties,\n' |
| 462 ' kRestrictionNodes,\n' | |
| 463 ' kIntegerEnumerations,\n' | |
| 464 ' kStringEnumerations,\n' | |
|
Joao da Silva
2014/01/16 10:56:34
Compilation fails when an array is empty. So if an
binjin
2014/01/17 14:29:01
Done.
| |
| 387 '};\n\n') | 465 '};\n\n') |
| 388 | 466 |
| 389 | 467 |
| 390 def _WritePolicyConstantSource(policies, os, f): | 468 def _WritePolicyConstantSource(policies, os, f): |
| 391 f.write('#include "policy/policy_constants.h"\n' | 469 f.write('#include "policy/policy_constants.h"\n' |
| 392 '\n' | 470 '\n' |
| 393 '#include <algorithm>\n' | 471 '#include <algorithm>\n' |
| 472 '#include <climits>\n' | |
| 394 '\n' | 473 '\n' |
| 395 '#include "base/logging.h"\n' | 474 '#include "base/logging.h"\n' |
| 396 '#include "components/policy/core/common/schema_internal.h"\n' | 475 '#include "components/policy/core/common/schema_internal.h"\n' |
| 397 '\n' | 476 '\n' |
| 398 'namespace policy {\n' | 477 'namespace policy {\n' |
| 399 '\n' | 478 '\n' |
| 400 'namespace {\n' | 479 'namespace {\n' |
| 401 '\n') | 480 '\n') |
| 402 | 481 |
| 403 # Generate the Chrome schema. | 482 # Generate the Chrome schema. |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 739 def _WriteCloudPolicyDecoder(policies, os, f): | 818 def _WriteCloudPolicyDecoder(policies, os, f): |
| 740 f.write(CPP_HEAD) | 819 f.write(CPP_HEAD) |
| 741 for policy in policies: | 820 for policy in policies: |
| 742 if policy.is_supported and not policy.is_device_only: | 821 if policy.is_supported and not policy.is_device_only: |
| 743 _WritePolicyCode(f, policy) | 822 _WritePolicyCode(f, policy) |
| 744 f.write(CPP_FOOT) | 823 f.write(CPP_FOOT) |
| 745 | 824 |
| 746 | 825 |
| 747 if __name__ == '__main__': | 826 if __name__ == '__main__': |
| 748 sys.exit(main()) | 827 sys.exit(main()) |
| OLD | NEW |