Index: mojo/public/bindings/generators/mojom_cpp_generator.py |
diff --git a/mojo/public/bindings/generators/mojom_cpp_generator.py b/mojo/public/bindings/generators/mojom_cpp_generator.py |
index a86341932343b20faa8dcc127e4a125e1f3ae657..e5c764e08ba645ee41a4a64b3709157fba898b65 100644 |
--- a/mojo/public/bindings/generators/mojom_cpp_generator.py |
+++ b/mojo/public/bindings/generators/mojom_cpp_generator.py |
@@ -17,32 +17,11 @@ from string import Template |
# cpp = mojom_cpp_generator.CPPGenerator(module) |
# cpp.GenerateFiles("/tmp/g") |
-class DependentKinds(set): |
- """Set subclass to find the unique set of non POD types.""" |
- def AddKind(self, kind): |
- if isinstance(kind, mojom.Struct): |
- self.add(kind) |
- if isinstance(kind, mojom.Array): |
- self.AddKind(kind.kind) |
- |
- |
-class Forwards(object): |
- """Helper class to maintain unique set of forward declarations.""" |
- def __init__(self): |
- self.kinds = DependentKinds() |
- |
- def Add(self, kind): |
- self.kinds.AddKind(kind) |
- |
- def __repr__(self): |
- return '\n'.join( |
- sorted(map(lambda kind: "class %s;" % kind.name, self.kinds))) |
- |
- |
class Lines(object): |
"""Helper class to maintain list of template expanded lines.""" |
- def __init__(self, template): |
+ def __init__(self, template, indent = None): |
self.template = template |
+ self.indent = indent |
self.lines = [] |
def Add(self, map = {}, **substitutions): |
@@ -53,6 +32,10 @@ class Lines(object): |
self.lines.append(self.template.substitute(map)) |
def __repr__(self): |
+ if self.indent is not None: |
+ prefix = "".ljust(self.indent, ' ') |
+ repr = '\n'.join(self.lines) |
+ self.lines = map(lambda l: prefix + l, repr.splitlines()) |
return '\n'.join(self.lines) |
@@ -103,8 +86,6 @@ class CPPGenerator(object): |
ptr_getter_template = \ |
Template(" $TYPE $FIELD() const { return ${FIELD}_.ptr; }") |
pad_template = Template(" uint8_t _pad${COUNT}_[$PAD];") |
- name_template = \ |
- Template("const uint32_t k${INTERFACE}_${METHOD}_Name = $NAME;") |
templates = {} |
HEADER_SIZE = 8 |
@@ -220,9 +201,7 @@ class CPPGenerator(object): |
def GetHeaderFile(self, *components): |
components = map(lambda c: CamelToUnderscores(c), components) |
component_string = '_'.join(components) |
- return os.path.join( |
- self.header_dir, |
- "%s_%s.h" % (CamelToUnderscores(self.module.name), component_string)) |
+ return os.path.join(self.header_dir, "%s.h" % component_string) |
# Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all files |
# to stdout. |
@@ -231,13 +210,10 @@ class CPPGenerator(object): |
self.header_dir = header_dir |
self.output_dir = output_dir |
- def WriteTemplateToFile(self, template_name, name, **substitutions): |
- template_name = CamelToUnderscores(template_name) |
- name = CamelToUnderscores(name) |
+ def WriteTemplateToFile(self, template_name, **substitutions): |
template = self.GetTemplate(template_name) |
- filename = "%s_%s" % (CamelToUnderscores(self.module.name), template_name) |
- filename = filename.replace("interface", name) |
- filename = filename.replace("struct", name) |
+ filename = \ |
+ template_name.replace("module", CamelToUnderscores(self.module.name)) |
substitutions['YEAR'] = datetime.date.today().year |
substitutions['NAMESPACE'] = self.module.namespace |
if self.output_dir is None: |
@@ -250,8 +226,7 @@ class CPPGenerator(object): |
if self.output_dir is not None: |
file.close() |
- def GetStructDeclaration(self, name, ps): |
- params_template = self.GetTemplate("struct_declaration") |
+ def GetStructDeclaration(self, name, ps, template, subs = {}): |
fields = [] |
setters = [] |
getters = [] |
@@ -280,24 +255,23 @@ class CPPGenerator(object): |
size = offset + pad |
else: |
size = 0 |
- return params_template.substitute( |
+ subs.update( |
CLASS = name, |
SETTERS = '\n'.join(setters), |
GETTERS = '\n'.join(getters), |
FIELDS = '\n'.join(fields), |
SIZE = size + self.HEADER_SIZE) |
+ return template.substitute(subs) |
- def GetStructImplementation(self, name, ps): |
- return self.GetTemplate("struct_implementation").substitute( |
- CLASS = name, |
- NUM_FIELDS = len(ps.packed_fields)) |
- |
- def GetStructSerialization(self, class_name, param_name, ps): |
+ def GetStructSerialization( |
+ self, class_name, param_name, ps, template, indent = None): |
struct = ps.struct |
- encodes = Lines(self.struct_serialization_encode_template) |
- encode_handles = Lines(self.struct_serialization_encode_handle_template) |
- decodes = Lines(self.struct_serialization_decode_template) |
- decode_handles = Lines(self.struct_serialization_decode_handle_template) |
+ encodes = Lines(self.struct_serialization_encode_template, indent) |
+ encode_handles = \ |
+ Lines(self.struct_serialization_encode_handle_template, indent) |
+ decodes = Lines(self.struct_serialization_decode_template, indent) |
+ decode_handles = \ |
+ Lines(self.struct_serialization_decode_handle_template, indent) |
fields = self.GetSerializedFields(ps) |
handle_fields = self.GetHandleFields(ps) |
for field in fields: |
@@ -308,7 +282,7 @@ class CPPGenerator(object): |
substitutions = {'NAME': param_name, 'FIELD': field.name} |
encode_handles.Add(substitutions) |
decode_handles.Add(substitutions) |
- return self.GetTemplate("struct_serialization").substitute( |
+ return template.substitute( |
CLASS = "%s::%s" % (self.module.namespace, class_name), |
NAME = param_name, |
ENCODES = encodes, |
@@ -316,174 +290,84 @@ class CPPGenerator(object): |
ENCODE_HANDLES = encode_handles, |
DECODE_HANDLES = decode_handles) |
- def GenerateStructHeader(self, ps): |
- struct = ps.struct |
- forwards = Forwards() |
- for field in struct.fields: |
- forwards.Add(field.kind) |
- |
- self.WriteTemplateToFile("struct.h", struct.name, |
- HEADER_GUARD = self.GetHeaderGuard(struct.name), |
- CLASS = struct.name, |
- FORWARDS = forwards, |
- DECLARATION = self.GetStructDeclaration(struct.name, ps)) |
- |
- def GenerateStructSource(self, ps): |
- struct = ps.struct |
- header = self.GetHeaderFile(struct.name) |
- implementation = self.GetStructImplementation(struct.name, ps) |
- self.WriteTemplateToFile("struct.cc", struct.name, |
- CLASS = struct.name, |
- NUM_FIELDS = len(struct.fields), |
- HEADER = header, |
- IMPLEMENTATION = implementation) |
- |
- def GenerateStructSerializationHeader(self, ps): |
- struct = ps.struct |
- self.WriteTemplateToFile("struct_serialization.h", struct.name, |
- HEADER_GUARD = self.GetHeaderGuard(struct.name + "_SERIALIZATION"), |
- CLASS = struct.name, |
- NAME = CamelToUnderscores(struct.name), |
- FULL_CLASS = "%s::%s" % \ |
- (self.module.namespace, struct.name)) |
- |
- def GenerateStructSerializationSource(self, ps): |
- struct = ps.struct |
- serialization_header = self.GetHeaderFile(struct.name, "serialization") |
- param_name = CamelToUnderscores(struct.name) |
- |
- kinds = DependentKinds() |
- for field in struct.fields: |
- kinds.AddKind(field.kind) |
- headers = \ |
- map(lambda kind: self.GetHeaderFile(kind.name, "serialization"), kinds) |
- headers.append(self.GetHeaderFile(struct.name)) |
- includes = map(lambda header: "#include \"%s\"" % header, sorted(headers)) |
- |
- class_header = self.GetHeaderFile(struct.name) |
- clones = Lines(self.struct_serialization_clone_template) |
- sizes = " return sizeof(*%s)" % param_name |
- fields = self.GetSerializedFields(ps) |
- for field in fields: |
- substitutions = {'NAME': param_name, 'FIELD': field.name} |
- sizes += \ |
- self.struct_serialization_compute_template.substitute(substitutions) |
- clones.Add(substitutions) |
- sizes += ";" |
- serialization = self.GetStructSerialization(struct.name, param_name, ps) |
- self.WriteTemplateToFile("struct_serialization.cc", struct.name, |
- NAME = param_name, |
- CLASS = "%s::%s" % (self.module.namespace, struct.name), |
- SERIALIZATION_HEADER = serialization_header, |
- INCLUDES = '\n'.join(includes), |
- SIZES = sizes, |
- CLONES = clones, |
- SERIALIZATION = serialization) |
- |
- def GenerateInterfaceHeader(self, interface): |
+ def GetStructClassDeclarations(self): |
+ struct_decls = map( |
+ lambda s: self.GetStructDeclaration( |
+ s.name, |
+ mojom_pack.PackedStruct(s), |
+ self.GetTemplate("struct_declaration"), |
+ {}), |
+ self.module.structs) |
+ return '\n'.join(struct_decls) |
+ |
+ def GetInterfaceClassDeclaration(self, interface, template, method_postfix): |
methods = [] |
- forwards = Forwards() |
for method in interface.methods: |
params = [] |
for param in method.parameters: |
- forwards.Add(param.kind) |
params.append("%s %s" % (self.GetConstType(param.kind), param.name)) |
methods.append( |
- " virtual void %s(%s) = 0;" % (method.name, ", ".join(params))) |
- |
- self.WriteTemplateToFile("interface.h", interface.name, |
- HEADER_GUARD = self.GetHeaderGuard(interface.name), |
- CLASS = interface.name, |
- FORWARDS = forwards, |
- METHODS = '\n'.join(methods)) |
- |
- def GenerateInterfaceStubHeader(self, interface): |
- header = self.GetHeaderFile(interface.name) |
- self.WriteTemplateToFile("interface_stub.h", interface.name, |
- HEADER_GUARD = self.GetHeaderGuard(interface.name + "_STUB"), |
- CLASS = interface.name, |
- HEADER = header) |
- |
- def GenerateInterfaceStubSource(self, interface): |
- stub_header = self.GetHeaderFile(interface.name, "stub") |
- serialization_header = self.GetHeaderFile(interface.name, "serialization") |
+ " virtual void %s(%s) %s;" % |
+ (method.name, ", ".join(params), method_postfix)) |
+ return template.substitute( |
+ CLASS=interface.name, |
+ METHODS='.\n'.join(methods)) |
+ |
+ def GetInterfaceClassDeclarations(self): |
+ template = self.GetTemplate("interface_declaration") |
+ interface_decls = \ |
+ map(lambda i: |
+ self.GetInterfaceClassDeclaration(i, template, " = 0"), |
+ self.module.interfaces) |
+ return '\n'.join(interface_decls) |
+ |
+ def GetInterfaceProxyDeclarations(self): |
+ template = self.GetTemplate("interface_proxy_declaration") |
+ interface_decls = \ |
+ map(lambda i: |
+ self.GetInterfaceClassDeclaration(i, template, "MOJO_OVERRIDE"), |
+ self.module.interfaces) |
+ return '\n'.join(interface_decls) |
+ |
+ def GetInterfaceStubDeclarations(self): |
+ template = self.GetTemplate("interface_stub_declaration") |
+ interface_decls = \ |
+ map(lambda i: template.substitute(CLASS=i.name), self.module.interfaces) |
+ return '\n'.join(interface_decls) |
+ |
+ def GenerateModuleHeader(self): |
+ self.WriteTemplateToFile("module.h", |
+ HEADER_GUARD = self.GetHeaderGuard(self.module.name), |
+ STRUCT_CLASS_DECLARARTIONS = self.GetStructClassDeclarations(), |
+ INTERFACE_CLASS_DECLARATIONS = self.GetInterfaceClassDeclarations(), |
+ INTERFACE_PROXY_DECLARATIONS = self.GetInterfaceProxyDeclarations(), |
+ INTERFACE_STUB_DECLARATIONS = self.GetInterfaceStubDeclarations()) |
+ |
+ def GetParamsDefinition(self, interface, method, next_id): |
+ struct = GetStructFromMethod(interface, method) |
+ method_name = "k%s_%s_Name" % (interface.name, method.name) |
+ if method.ordinal is not None: |
+ next_id = method.ordinal |
+ params_def = self.GetStructDeclaration( |
+ struct.name, |
+ mojom_pack.PackedStruct(struct), |
+ self.GetTemplate("params_definition"), |
+ {'METHOD_NAME': method_name, 'METHOD_ID': next_id}) |
+ return params_def, next_id + 1 |
+ |
+ def GetStructDefinitions(self): |
+ template = self.GetTemplate("struct_definition") |
+ return '\n'.join(map( |
+ lambda s: template.substitute( |
+ CLASS = s.name, NUM_FIELDS = len(s.fields)), |
+ self.module.structs)); |
+ |
+ def GetInterfaceDefinition(self, interface): |
cases = [] |
- for method in interface.methods: |
- cases.append(self.GetCaseLine(interface, method)) |
- self.WriteTemplateToFile("interface_stub.cc", interface.name, |
- CLASS = interface.name, |
- CASES = '\n'.join(cases), |
- STUB_HEADER = stub_header, |
- SERIALIZATION_HEADER = serialization_header) |
- |
- def GenerateInterfaceSerializationHeader(self, interface): |
- kinds = DependentKinds() |
- for method in interface.methods: |
- for param in method.parameters: |
- kinds.AddKind(param.kind) |
- headers = \ |
- map(lambda kind: self.GetHeaderFile(kind.name, "serialization"), kinds) |
- headers.append(self.GetHeaderFile(interface.name)) |
- headers.append("mojo/public/bindings/lib/bindings_serialization.h") |
- includes = map(lambda header: "#include \"%s\"" % header, sorted(headers)) |
- |
- names = [] |
- name = 1 |
- param_classes = [] |
- param_templates = [] |
- template_declaration = self.GetTemplate("template_declaration") |
- for method in interface.methods: |
- names.append(self.name_template.substitute( |
- INTERFACE = interface.name, |
- METHOD = method.name, |
- NAME = name)) |
- name += 1 |
- |
- struct = GetStructFromMethod(interface, method) |
- ps = mojom_pack.PackedStruct(struct) |
- param_classes.append(self.GetStructDeclaration(struct.name, ps)) |
- param_templates.append(template_declaration.substitute(CLASS=struct.name)) |
- |
- self.WriteTemplateToFile("interface_serialization.h", interface.name, |
- HEADER_GUARD = self.GetHeaderGuard(interface.name + "_SERIALIZATION"), |
- INCLUDES = '\n'.join(includes), |
- NAMES = '\n'.join(names), |
- PARAM_CLASSES = '\n'.join(param_classes), |
- PARAM_TEMPLATES = '\n'.join(param_templates)) |
- |
- def GenerateInterfaceSerializationSource(self, interface): |
- implementations = [] |
- serializations = [] |
- for method in interface.methods: |
- struct = GetStructFromMethod(interface, method) |
- ps = mojom_pack.PackedStruct(struct) |
- implementations.append(self.GetStructImplementation(struct.name, ps)) |
- serializations.append( |
- self.GetStructSerialization("internal::" + struct.name, "params", ps)) |
- self.WriteTemplateToFile("interface_serialization.cc", interface.name, |
- HEADER = self.GetHeaderFile(interface.name, "serialization"), |
- IMPLEMENTATIONS = '\n'.join(implementations), |
- SERIALIZATIONS = '\n'.join(serializations)) |
- |
- def GenerateInterfaceProxyHeader(self, interface): |
- methods = [] |
- for method in interface.methods: |
- params = map( |
- lambda param: "%s %s" % (self.GetConstType(param.kind), param.name), |
- method.parameters) |
- methods.append( |
- " virtual void %s(%s) MOJO_OVERRIDE;" \ |
- % (method.name, ", ".join(params))) |
- |
- self.WriteTemplateToFile("interface_proxy.h", interface.name, |
- HEADER_GUARD = self.GetHeaderGuard(interface.name + "_PROXY"), |
- HEADER = self.GetHeaderFile(interface.name), |
- CLASS = interface.name, |
- METHODS = '\n'.join(methods)) |
- |
- def GenerateInterfaceProxySource(self, interface): |
implementations = Lines(self.GetTemplate("proxy_implementation")) |
+ |
for method in interface.methods: |
+ cases.append(self.GetCaseLine(interface, method)) |
sets = [] |
computes = Lines(self.param_struct_compute_template) |
for param in method.parameters: |
@@ -496,8 +380,8 @@ class CPPGenerator(object): |
params_list = map( |
lambda param: "%s %s" % (self.GetConstType(param.kind), param.name), |
method.parameters) |
- name = "internal::k%s_%s_Name" % (interface.name, method.name) |
- params_name = "internal::%s_%s_Params" % (interface.name, method.name) |
+ name = "k%s_%s_Name" % (interface.name, method.name) |
+ params_name = "%s_%s_Params" % (interface.name, method.name) |
implementations.Add( |
CLASS = interface.name, |
@@ -507,25 +391,93 @@ class CPPGenerator(object): |
PARAMS_LIST = ', '.join(params_list), |
COMPUTES = computes, |
SETS = '\n'.join(sets)) |
- self.WriteTemplateToFile("interface_proxy.cc", interface.name, |
- HEADER = self.GetHeaderFile(interface.name, "proxy"), |
- SERIALIZATION_HEADER = \ |
- self.GetHeaderFile(interface.name, "serialization"), |
+ stub_definition = self.GetTemplate("interface_stub_definition").substitute( |
CLASS = interface.name, |
- IMPLEMENTATIONS = implementations) |
+ CASES = '\n'.join(cases)) |
+ return self.GetTemplate("interface_definition").substitute( |
+ CLASS = interface.name + "Proxy", |
+ PROXY_DEFINITIONS = implementations, |
+ STUB_DEFINITION = stub_definition) |
- def GenerateFiles(self): |
- for struct in self.module.structs: |
- ps = mojom_pack.PackedStruct(struct) |
- self.GenerateStructHeader(ps) |
- self.GenerateStructSource(ps) |
- self.GenerateStructSerializationHeader(ps) |
- self.GenerateStructSerializationSource(ps) |
+ def GetInterfaceDefinitions(self): |
+ return '\n'.join( |
+ map(lambda i: self.GetInterfaceDefinition(i), self.module.interfaces)) |
+ |
+ def GetStructSerializationDefinition(self, struct): |
+ ps = mojom_pack.PackedStruct(struct) |
+ param_name = CamelToUnderscores(struct.name) |
+ |
+ clones = Lines(self.struct_serialization_clone_template) |
+ sizes = " return sizeof(*%s)" % param_name |
+ fields = self.GetSerializedFields(ps) |
+ for field in fields: |
+ substitutions = {'NAME': param_name, 'FIELD': field.name} |
+ sizes += \ |
+ self.struct_serialization_compute_template.substitute(substitutions) |
+ clones.Add(substitutions) |
+ sizes += ";" |
+ serialization = self.GetStructSerialization( |
+ struct.name, param_name, ps, self.GetTemplate("struct_serialization")) |
+ return self.GetTemplate("struct_serialization_definition").substitute( |
+ NAME = param_name, |
+ CLASS = "%s::%s" % (self.module.namespace, struct.name), |
+ SIZES = sizes, |
+ CLONES = clones, |
+ SERIALIZATION = serialization) |
+ |
+ def GetStructSerializationDefinitions(self): |
+ return '\n'.join( |
+ map(lambda i: self.GetStructSerializationDefinition(i), |
+ self.module.structs)) |
+ |
+ def GetInterfaceSerializationDefinitions(self): |
+ serializations = [] |
+ for interface in self.module.interfaces: |
+ for method in interface.methods: |
+ struct = GetStructFromMethod(interface, method) |
+ ps = mojom_pack.PackedStruct(struct) |
+ serializations.append(self.GetStructSerialization( |
+ struct.name, |
+ "params", |
+ ps, |
+ self.GetTemplate("params_serialization"), |
+ 2)) |
+ return '\n'.join(serializations) |
+ |
+ def GetParamsDefinitions(self): |
+ params_defs = [] |
for interface in self.module.interfaces: |
- self.GenerateInterfaceHeader(interface) |
- self.GenerateInterfaceStubHeader(interface) |
- self.GenerateInterfaceStubSource(interface) |
- self.GenerateInterfaceSerializationHeader(interface) |
- self.GenerateInterfaceSerializationSource(interface) |
- self.GenerateInterfaceProxyHeader(interface) |
- self.GenerateInterfaceProxySource(interface) |
+ next_id = 0 |
+ for method in interface.methods: |
+ (params_def, next_id) = \ |
+ self.GetParamsDefinition(interface, method, next_id) |
+ params_defs.append(params_def) |
+ return '\n'.join(params_defs) |
+ |
+ def GenerateModuleSource(self): |
+ self.WriteTemplateToFile("module.cc", |
+ HEADER = self.GetHeaderFile(self.module.name), |
+ INTERNAL_HEADER = self.GetHeaderFile(self.module.name, "internal"), |
+ PARAM_DEFINITIONS = self.GetParamsDefinitions(), |
+ STRUCT_DEFINITIONS = self.GetStructDefinitions(), |
+ INTERFACE_DEFINITIONS = self.GetInterfaceDefinitions(), |
+ STRUCT_SERIALIZATION_DEFINITIONS = |
+ self.GetStructSerializationDefinitions(), |
+ INTERFACE_SERIALIZATION_DEFINITIONS = |
+ self.GetInterfaceSerializationDefinitions()) |
+ |
+ def GenerateModuleInternalHeader(self): |
+ traits = map( |
+ lambda s: self.GetTemplate("struct_serialization_traits").substitute( |
+ NAME = CamelToUnderscores(s.name), |
+ FULL_CLASS = "%s::%s" % (self.module.namespace, s.name)), |
+ self.module.structs); |
+ self.WriteTemplateToFile("module_internal.h", |
+ HEADER_GUARD = self.GetHeaderGuard(self.module.name + "_INTERNAL"), |
+ HEADER = self.GetHeaderFile(self.module.name), |
+ TRAITS = '\n'.join(traits)) |
+ |
+ def GenerateFiles(self): |
+ self.GenerateModuleHeader() |
+ self.GenerateModuleInternalHeader() |
+ self.GenerateModuleSource() |