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((str(first), str(second))) | |
296 return index | |
Joao da Silva
2014/01/20 10:49:10
If you look at the output you'll see that there ar
binjin
2014/01/20 14:09:23
Done.
| |
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 isConsecutiveInterval(self, seq): | |
Joao da Silva
2014/01/20 10:49:10
Start the function name with a capital letter:
binjin
2014/01/20 14:09:23
Done.
| |
318 if len(seq) == 1: | |
319 return True | |
Joao da Silva
2014/01/20 10:49:10
This special case is not needed; xrange(0) will be
binjin
2014/01/20 14:09:23
Done.
| |
320 sortedSeq = sorted(seq) | |
321 return all(sortedSeq[i] + 1 == sortedSeq[i + 1] | |
322 for i in xrange(len(sortedSeq) - 1)) | |
323 | |
324 def GetEnumIntegerType(self, schema, name): | |
325 assert all(type(x) == int for x in schema['enum']) | |
326 possible_values = schema['enum'] | |
327 if self.isConsecutiveInterval(possible_values): | |
328 index = self.AppendRestriction(max(possible_values), min(possible_values)) | |
329 return self.AppendSchema('TYPE_INTEGER', index, | |
330 'integer with enumeration restriction(use ranged instead): %s' % name) | |
Joao da Silva
2014/01/20 10:49:10
nit: space before (, "used range instead":
binjin
2014/01/20 14:09:23
Done.
| |
331 offset_begin = len(self.int_enums) | |
332 self.int_enums += possible_values | |
333 offset_end = len(self.int_enums) | |
334 return self.AppendSchema('TYPE_INTEGER', | |
335 self.AppendRestriction(offset_begin, offset_end), | |
336 'integer with enumeration restriction: %s' % name) | |
337 | |
338 def GetEnumStringType(self, schema, name): | |
339 assert all(type(x) == str for x in schema['enum']) | |
340 offset_begin = len(self.string_enums) | |
341 self.string_enums += schema['enum'] | |
342 offset_end = len(self.string_enums) | |
343 return self.AppendSchema('TYPE_STRING', | |
344 self.AppendRestriction(offset_begin, offset_end), | |
345 'string with enumeration restriction: %s' % name) | |
346 | |
347 def GetEnumType(self, schema, name): | |
348 if len(schema['enum']) == 0: | |
349 raise RuntimeError('Empty enumeration in %s' % name) | |
350 elif schema['type'] == 'integer': | |
351 return self.GetEnumIntegerType(schema, name) | |
352 elif schema['type'] == 'string': | |
353 return self.GetEnumStringType(schema, name) | |
354 else: | |
355 raise RuntimeError('Unknown enumeration type in %s' % name) | |
356 | |
357 def GetRangedType(self, schema, name): | |
358 if schema['type'] != 'integer': | |
359 raise RuntimeError('Unknown ranged type in %s' % name) | |
360 min_value_set, max_value_set = False, False | |
361 if 'minimum' in schema: | |
362 min_value = int(schema['minimum']) | |
363 min_value_set = True | |
364 if 'maximum' in schema: | |
365 max_value = int(schema['minimum']) | |
366 max_value_set = True | |
367 if min_value_set and max_value_set and min_value > max_value: | |
368 raise RuntimeError('Invalid ranged type in %s' % name) | |
369 index = self.AppendRestriction( | |
370 str(max_value) if max_value_set else 'INT_MAX', | |
371 str(min_value) if min_value_set else 'INT_MIN') | |
372 return self.AppendSchema('TYPE_INTEGER', | |
373 index, | |
374 'integer with ranged restriction: %s' % name) | |
375 | |
307 def Generate(self, schema, name): | 376 def Generate(self, schema, name): |
308 """Generates the structs for the given schema. | 377 """Generates the structs for the given schema. |
309 | 378 |
310 |schema|: a valid JSON schema in a dictionary. | 379 |schema|: a valid JSON schema in a dictionary. |
311 |name|: the name of the current node, for the generated comments.""" | 380 |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: | 381 if schema['type'] in self.simple_types: |
314 return self.GetSimpleType(schema['type']) | 382 if not self.SchemaHaveRestriction(schema): |
383 # Simple types use shared nodes. | |
384 return self.GetSimpleType(schema['type']) | |
385 elif 'enum' in schema: | |
386 return self.GetEnumType(schema, name) | |
387 else: | |
388 return self.GetRangedType(schema, name) | |
315 | 389 |
316 if schema['type'] == 'array': | 390 if schema['type'] == 'array': |
317 # Special case for lists of strings, which is a common policy type. | 391 # Special case for lists of strings, which is a common policy type. |
318 if schema['items']['type'] == 'string': | 392 if schema['items']['type'] == 'string': |
319 return self.GetStringList() | 393 return self.GetStringList() |
320 return self.AppendSchema( | 394 return self.AppendSchema( |
321 'TYPE_LIST', | 395 'TYPE_LIST', |
322 self.Generate(schema['items'], 'items of ' + name)) | 396 self.Generate(schema['items'], 'items of ' + name)) |
323 elif schema['type'] == 'object': | 397 elif schema['type'] == 'object': |
324 # Reserve an index first, so that dictionaries come before their | 398 # 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 += ',' | 447 key += ',' |
374 f.write(' { %-50s %7d },\n' % (key, schema)) | 448 f.write(' { %-50s %7d },\n' % (key, schema)) |
375 f.write('};\n\n') | 449 f.write('};\n\n') |
376 | 450 |
377 f.write('const internal::PropertiesNode kProperties[] = {\n' | 451 f.write('const internal::PropertiesNode kProperties[] = {\n' |
378 '// Begin End Additional Properties\n') | 452 '// Begin End Additional Properties\n') |
379 for node in self.properties_nodes: | 453 for node in self.properties_nodes: |
380 f.write(' { %5d, %5d, %5d }, // %s\n' % node) | 454 f.write(' { %5d, %5d, %5d }, // %s\n' % node) |
381 f.write('};\n\n') | 455 f.write('};\n\n') |
382 | 456 |
457 f.write('const internal::RestrictionNode kRestrictionNodes[] = {\n') | |
458 f.write('// FIRST, SECOND\n') | |
459 for first, second in self.restriction_nodes: | |
460 f.write(' {{ %-8s %4s}},\n' % (first + ',', second)) | |
461 f.write('};\n\n') | |
462 | |
463 f.write('const int kIntegerEnumerations[] = {\n') | |
464 for possible_values in self.int_enums: | |
465 f.write(' %d,\n' % possible_values) | |
466 f.write('};\n\n') | |
467 | |
468 f.write('const char* kStringEnumerations[] = {\n') | |
469 for possible_values in self.string_enums: | |
470 f.write(' %s,\n' % self.GetString(possible_values)) | |
471 f.write('};\n\n') | |
472 | |
383 f.write('const internal::SchemaData kChromeSchemaData = {\n' | 473 f.write('const internal::SchemaData kChromeSchemaData = {\n' |
384 ' kSchemas,\n' | 474 ' kSchemas,\n' |
385 ' kPropertyNodes,\n' | 475 ' kPropertyNodes,\n' |
386 ' kProperties,\n' | 476 ' kProperties,\n'); |
387 '};\n\n') | 477 f.write(' kRestrictionNodes,\n' if self.restriction_nodes else ' NULL,\n') |
478 f.write(' kIntegerEnumerations,\n' if self.int_enums else ' NULL,\n') | |
479 f.write(' kStringEnumerations,\n' if self.string_enums else ' NULL,\n') | |
480 f.write('};\n\n') | |
388 | 481 |
389 | 482 |
390 def _WritePolicyConstantSource(policies, os, f): | 483 def _WritePolicyConstantSource(policies, os, f): |
391 f.write('#include "policy/policy_constants.h"\n' | 484 f.write('#include "policy/policy_constants.h"\n' |
392 '\n' | 485 '\n' |
393 '#include <algorithm>\n' | 486 '#include <algorithm>\n' |
487 '#include <climits>\n' | |
394 '\n' | 488 '\n' |
395 '#include "base/logging.h"\n' | 489 '#include "base/logging.h"\n' |
396 '#include "components/policy/core/common/schema_internal.h"\n' | 490 '#include "components/policy/core/common/schema_internal.h"\n' |
397 '\n' | 491 '\n' |
398 'namespace policy {\n' | 492 'namespace policy {\n' |
399 '\n' | 493 '\n' |
400 'namespace {\n' | 494 'namespace {\n' |
401 '\n') | 495 '\n') |
402 | 496 |
403 # Generate the Chrome schema. | 497 # Generate the Chrome schema. |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
739 def _WriteCloudPolicyDecoder(policies, os, f): | 833 def _WriteCloudPolicyDecoder(policies, os, f): |
740 f.write(CPP_HEAD) | 834 f.write(CPP_HEAD) |
741 for policy in policies: | 835 for policy in policies: |
742 if policy.is_supported and not policy.is_device_only: | 836 if policy.is_supported and not policy.is_device_only: |
743 _WritePolicyCode(f, policy) | 837 _WritePolicyCode(f, policy) |
744 f.write(CPP_FOOT) | 838 f.write(CPP_FOOT) |
745 | 839 |
746 | 840 |
747 if __name__ == '__main__': | 841 if __name__ == '__main__': |
748 sys.exit(main()) | 842 sys.exit(main()) |
OLD | NEW |