| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import code | 5 import code |
| 6 import cpp_util | 6 import cpp_util |
| 7 from model import Platforms | 7 from model import Platforms |
| 8 from schema_util import CapitalizeFirstLetter | 8 from schema_util import CapitalizeFirstLetter |
| 9 from schema_util import JsFunctionNameToClassName | 9 from schema_util import JsFunctionNameToClassName |
| 10 | 10 |
| 11 import collections |
| 11 import copy | 12 import copy |
| 12 import json | 13 import json |
| 13 import os | 14 import os |
| 14 import re | 15 import re |
| 15 | 16 |
| 16 | 17 |
| 17 def _RemoveKey(node, key, type_restriction): | 18 def _RemoveKey(node, key, type_restriction): |
| 18 if isinstance(node, dict): | 19 if isinstance(node, dict): |
| 19 if key in node and isinstance(node[key], type_restriction): | 20 if key in node and isinstance(node[key], type_restriction): |
| 20 del node[key] | 21 del node[key] |
| 21 for value in node.values(): | 22 for value in node.values(): |
| 22 _RemoveKey(value, key, type_restriction) | 23 _RemoveKey(value, key, type_restriction) |
| 23 elif isinstance(node, list): | 24 elif isinstance(node, list): |
| 24 for value in node: | 25 for value in node: |
| 25 _RemoveKey(value, key, type_restriction) | 26 _RemoveKey(value, key, type_restriction) |
| 26 | 27 |
| 27 def _RemoveUnneededFields(schema): | 28 def _RemoveUnneededFields(schema): |
| 28 """Returns a copy of |schema| with fields that aren't necessary at runtime | 29 """Returns a copy of |schema| with fields that aren't necessary at runtime |
| 29 removed. | 30 removed. |
| 30 """ | 31 """ |
| 31 # Return a copy so that we don't pollute the global api object, which may be | 32 # Return a copy so that we don't pollute the global api object, which may be |
| 32 # used elsewhere. | 33 # used elsewhere. |
| 33 ret = copy.deepcopy(schema) | 34 ret = copy.deepcopy(schema) |
| 34 _RemoveKey(ret, "description", basestring) | 35 _RemoveKey(ret, "description", basestring) |
| 35 _RemoveKey(ret, "compiler_options", dict) | 36 _RemoveKey(ret, "compiler_options", dict) |
| 36 _RemoveKey(ret, "nodoc", bool) | 37 _RemoveKey(ret, "nodoc", bool) |
| 37 _RemoveKey(ret, "noinline_doc", bool) | 38 _RemoveKey(ret, "noinline_doc", bool) |
| 38 return ret | 39 return ret |
| 39 | 40 |
| 41 def _PrefixSchemaWithNamespace(schema): |
| 42 """Modifies |schema| in place to prefix all types and references with a |
| 43 namespace, if they aren't already qualified. That is, in the tabs API, this |
| 44 will turn type Tab into tabs.Tab, but will leave the fully-qualified |
| 45 windows.Window as-is. |
| 46 """ |
| 47 assert isinstance(schema, dict), "Schema is unexpected type" |
| 48 namespace = schema['namespace'] |
| 49 def prefix(obj, key, mandatory): |
| 50 if not key in obj: |
| 51 assert not mandatory, ( |
| 52 'Required key "%s" is not present in object.' % key) |
| 53 return |
| 54 assert type(obj[key]) in [str, unicode] |
| 55 if obj[key].find('.') == -1: |
| 56 obj[key] = '%s.%s' % (namespace, obj[key]) |
| 57 |
| 58 if 'types' in schema: |
| 59 assert isinstance(schema['types'], list) |
| 60 for t in schema['types']: |
| 61 assert isinstance(t, dict), "Type entry is unexpected type" |
| 62 prefix(t, 'id', True) |
| 63 prefix(t, 'customBindings', False) |
| 64 |
| 65 def prefix_refs(val): |
| 66 if type(val) is list: |
| 67 for sub_val in val: |
| 68 prefix_refs(sub_val) |
| 69 elif type(val) is dict or type(val) is collections.OrderedDict: |
| 70 prefix(val, '$ref', False) |
| 71 for key, sub_val in val.items(): |
| 72 prefix_refs(sub_val) |
| 73 prefix_refs(schema) |
| 74 return schema |
| 75 |
| 40 | 76 |
| 41 class CppBundleGenerator(object): | 77 class CppBundleGenerator(object): |
| 42 """This class contains methods to generate code based on multiple schemas. | 78 """This class contains methods to generate code based on multiple schemas. |
| 43 """ | 79 """ |
| 44 | 80 |
| 45 def __init__(self, | 81 def __init__(self, |
| 46 root, | 82 root, |
| 47 model, | 83 model, |
| 48 api_defs, | 84 api_defs, |
| 49 cpp_type_generator, | 85 cpp_type_generator, |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 c.Append() | 320 c.Append() |
| 285 c.Append('#include "%s"' % (os.path.join(self._bundle._source_file_dir, | 321 c.Append('#include "%s"' % (os.path.join(self._bundle._source_file_dir, |
| 286 'generated_schemas.h'))) | 322 'generated_schemas.h'))) |
| 287 c.Append() | 323 c.Append() |
| 288 c.Append('#include "base/lazy_instance.h"') | 324 c.Append('#include "base/lazy_instance.h"') |
| 289 c.Append() | 325 c.Append() |
| 290 c.Append('namespace {') | 326 c.Append('namespace {') |
| 291 for api in self._bundle._api_defs: | 327 for api in self._bundle._api_defs: |
| 292 namespace = self._bundle._model.namespaces[api.get('namespace')] | 328 namespace = self._bundle._model.namespaces[api.get('namespace')] |
| 293 # JSON parsing code expects lists of schemas, so dump a singleton list. | 329 # JSON parsing code expects lists of schemas, so dump a singleton list. |
| 294 json_content = json.dumps([_RemoveUnneededFields(api)], | 330 json_content = json.dumps([_PrefixSchemaWithNamespace( |
| 331 _RemoveUnneededFields(api))], |
| 295 separators=(',', ':')) | 332 separators=(',', ':')) |
| 296 # Escape all double-quotes and backslashes. For this to output a valid | 333 # Escape all double-quotes and backslashes. For this to output a valid |
| 297 # JSON C string, we need to escape \ and ". Note that some schemas are | 334 # JSON C string, we need to escape \ and ". Note that some schemas are |
| 298 # too large to compile on windows. Split the JSON up into several | 335 # too large to compile on windows. Split the JSON up into several |
| 299 # strings, since apparently that helps. | 336 # strings, since apparently that helps. |
| 300 max_length = 8192 | 337 max_length = 8192 |
| 301 segments = [json_content[i:i + max_length].replace('\\', '\\\\') | 338 segments = [json_content[i:i + max_length].replace('\\', '\\\\') |
| 302 .replace('"', '\\"') | 339 .replace('"', '\\"') |
| 303 for i in xrange(0, len(json_content), max_length)] | 340 for i in xrange(0, len(json_content), max_length)] |
| 304 c.Append('const char %s[] = "%s";' % | 341 c.Append('const char %s[] = "%s";' % |
| (...skipping 25 matching lines...) Expand all Loading... |
| 330 c.Append() | 367 c.Append() |
| 331 c.Append('// static') | 368 c.Append('// static') |
| 332 c.Sblock('bool %s::IsGenerated(std::string name) {' % | 369 c.Sblock('bool %s::IsGenerated(std::string name) {' % |
| 333 self._bundle._GenerateBundleClass('GeneratedSchemas')) | 370 self._bundle._GenerateBundleClass('GeneratedSchemas')) |
| 334 c.Append('return g_lazy_instance.Get().schemas.count(name) > 0;') | 371 c.Append('return g_lazy_instance.Get().schemas.count(name) > 0;') |
| 335 c.Eblock('}') | 372 c.Eblock('}') |
| 336 c.Append() | 373 c.Append() |
| 337 c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace)) | 374 c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace)) |
| 338 c.Append() | 375 c.Append() |
| 339 return c | 376 return c |
| OLD | NEW |