diff options
-rw-r--r-- | mojo/public/bindings/generators/cpp_interface.template | 19 | ||||
-rw-r--r-- | mojo/public/bindings/generators/cpp_struct.template | 43 | ||||
-rw-r--r-- | mojo/public/bindings/generators/mojom_cpp_generator.py | 192 | ||||
-rw-r--r-- | mojo/public/bindings/generators/mojom_pack.py | 6 | ||||
-rwxr-xr-x | mojo/public/bindings/generators/run_cpp_generator.py | 25 | ||||
-rw-r--r-- | mojo/public/bindings/sample/sample_service.mojom | 31 |
6 files changed, 314 insertions, 2 deletions
diff --git a/mojo/public/bindings/generators/cpp_interface.template b/mojo/public/bindings/generators/cpp_interface.template new file mode 100644 index 0000000..874e2f4 --- /dev/null +++ b/mojo/public/bindings/generators/cpp_interface.template @@ -0,0 +1,19 @@ +// Copyright $year The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef $header_guard +#define $header_guard + +#include "mojo/public/bindings/lib/bindings.h" + +namespace $namespace { + +class $classname { + public: +$methods +}; + +} // namespace $namespace + +#endif // $header_guard diff --git a/mojo/public/bindings/generators/cpp_struct.template b/mojo/public/bindings/generators/cpp_struct.template new file mode 100644 index 0000000..5078792 --- /dev/null +++ b/mojo/public/bindings/generators/cpp_struct.template @@ -0,0 +1,43 @@ +// Copyright $year The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef $header_guard +#define $header_guard + +#include "mojo/public/bindings/lib/bindings.h" + +namespace $namespace { + +#pragma pack(push, 1) + +class $classname { + public: + static $classname* New(mojo::Buffer* buf) { + return new (buf->Allocate(sizeof($classname))) $classname(); + } + +$setters + +$getters + + private: + friend class mojo::internal::ObjectTraits<$classname>; + + $classname() { + header_.num_bytes = sizeof(*this); + header_.num_fields = $num_fields; + } + ~$classname(); // NOT IMPLEMENTED + + mojo::internal::StructHeader _header_; +$fields +}; + +MOJO_COMPILE_ASSERT(sizeof($classname) == $size, bad_sizeof_$classname); + +#pragma pack(pop) + +} // namespace $namespace + +#endif // $header_guard diff --git a/mojo/public/bindings/generators/mojom_cpp_generator.py b/mojo/public/bindings/generators/mojom_cpp_generator.py new file mode 100644 index 0000000..fc807e6 --- /dev/null +++ b/mojo/public/bindings/generators/mojom_cpp_generator.py @@ -0,0 +1,192 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import datetime +import mojom +import mojom_pack +import os +import sys + +from string import Template + +# mojom_cpp_generator provides a way to generate c++ code from a mojom.Module. +# cpp = mojom_cpp_generator.CPPGenerator(module) +# cpp.GenerateFiles("/tmp/g") +def ReadTemplate(filename): + dir = os.path.dirname(__file__) + with open(dir + '/' + filename, 'r') as file: + return Template(file.read()) + + +class CPPGenerator(object): + struct_template = ReadTemplate("cpp_struct.template") + interface_template = ReadTemplate("cpp_interface.template") + field_template = Template(" $itype ${field}_;") + bool_field_template = Template(" uint8_t ${field}_ : 1;") + setter_template = \ + Template(" void set_$field($stype $field) { ${field}_ = $field; }") + getter_template = \ + Template(" $gtype $field() const { return ${field}_; }") + ptr_getter_template = \ + Template(" $gtype $field() const { return ${field}_.ptr; }") + pad_template = Template(" uint8_t _pad${count}_[$pad];") + + kind_to_type = { + mojom.BOOL: "bool", + mojom.INT8: "int8_t", + mojom.UINT8: "uint8_t", + mojom.INT16: "int16_t", + mojom.UINT16: "uint16_t", + mojom.INT32: "int32_t", + mojom.UINT32: "uint32_t", + mojom.FLOAT: "float", + mojom.HANDLE: "mojo::Handle", + mojom.INT64: "int64_t", + mojom.UINT64: "uint64_t", + mojom.DOUBLE: "double", + } + + @classmethod + def GetType(cls, kind): + if isinstance(kind, mojom.Struct): + return "%s*" % kind.name.capitalize() + if isinstance(kind, mojom.Array): + return "mojo::Array<%s>*" % cls.GetType(kind.kind) + if kind.spec == 's': + return "mojo::String*" + return cls.kind_to_type[kind] + + @classmethod + def GetConstType(cls, kind): + if isinstance(kind, mojom.Struct): + return "const %s*" % kind.name.capitalize() + if isinstance(kind, mojom.Array): + return "const mojo::Array<%s>*" % cls.GetConstType(kind.kind) + if kind.spec == 's': + return "const mojo::String*" + return cls.kind_to_type[kind] + + @classmethod + def GetGetterLine(cls, pf): + kind = pf.field.kind + template = None + gtype = cls.GetConstType(kind) + if isinstance(kind, (mojom.Struct, mojom.Array)) or kind.spec == 's': + template = cls.ptr_getter_template + else: + template = cls.getter_template + return template.substitute(field=pf.field.name, gtype=gtype) + + @classmethod + def GetSetterLine(cls, pf): + stype = cls.GetType(pf.field.kind) + return cls.setter_template.substitute(field=pf.field.name, stype=stype) + + @classmethod + def GetFieldLine(cls, pf): + kind = pf.field.kind + if kind.spec == 'b': + return cls.bool_field_template.substitute(field=pf.field.name) + itype = None + if isinstance(kind, mojom.Struct): + itype = "mojo::internal::StructPointer<%s>" % kind.name.capitalize() + elif isinstance(kind, mojom.Array): + itype = "mojo::internal::StructPointer<%s>" % cls.GetType(kind.kind) + elif kind.spec == 's': + itype = "mojo::internal::StringPointer" + else: + itype = cls.kind_to_type[kind] + return cls.field_template.substitute(field=pf.field.name, itype=itype) + + def GetHeaderGuard(self, component): + return "MOJO_GENERATED_BINDINGS_%s_%s_H_" % \ + (self.module.name.upper(), component.name.upper()) + + def OpenComponentFile(self, directory, component): + filename = "%s_%s.h" % \ + (self.module.name.lower(), component.name.lower()) + return open(directory + '/' + filename, "w+") + + def __init__(self, module): + self.module = module + self.file = file + + def GenerateStruct(self, struct, file): + fields = [] + setters = [] + getters = [] + + ps = mojom_pack.PackedStruct(struct) + pad_count = 0 + num_fields = len(ps.packed_fields) + for i in xrange(num_fields): + pf = ps.packed_fields[i] + fields.append(self.GetFieldLine(pf)) + if i < (num_fields - 2): + next_pf = ps.packed_fields[i+1] + pad = next_pf.offset - (pf.offset + pf.size) + if pad > 0: + fields.append(self.pad_template.substitute(count=pad_count, pad=pad)) + pad_count += 1 + setters.append(self.GetSetterLine(pf)) + getters.append(self.GetGetterLine(pf)) + + if num_fields > 0: + last_field = ps.packed_fields[num_fields - 1] + offset = last_field.offset + last_field.size + pad = mojom_pack.GetPad(offset, 8) + if pad > 0: + fields.append(self.pad_template.substitute(count=pad_count, pad=pad)) + pad_count += 1 + size = offset + pad + else: + size = 0 + + file.write(self.struct_template.substitute( + year = datetime.date.today().year, + header_guard = self.GetHeaderGuard(struct), + namespace = self.module.namespace, + classname = struct.name.capitalize(), + num_fields = len(ps.packed_fields), + size = size + 8, + setters = '\n'.join(setters), + getters = '\n'.join(getters), + fields = '\n'.join(fields))) + + def GenerateInterface(self, interface, file): + cpp_methods = [] + for method in interface.methods: + cpp_method = " virtual void %s(" % method.name + first_param = True + for param in method.parameters: + if first_param == True: + first_param = False + else: + cpp_method += ", " + cpp_method += "%s %s" % (self.GetConstType(param.kind), param.name) + cpp_method += ") = 0;" + cpp_methods.append(cpp_method) + + file.write(self.interface_template.substitute( + year = datetime.date.today().year, + header_guard = self.GetHeaderGuard(interface), + namespace = self.module.namespace, + classname = interface.name.capitalize(), + methods = '\n'.join(cpp_methods))) + + # Pass |directory| to emit files to disk. Omit |directory| to echo all files + # to stdout. + def GenerateFiles(self, directory=None): + for struct in self.module.structs: + if directory is None: + self.GenerateStruct(struct, sys.stdout) + else: + with self.OpenComponentFile(directory, struct) as file: + self.GenerateStruct(struct, file) + for interface in self.module.interfaces: + if directory is None: + self.GenerateInterface(interface, sys.stdout) + else: + with self.OpenComponentFile(directory, interface) as file: + self.GenerateInterface(interface, file) diff --git a/mojo/public/bindings/generators/mojom_pack.py b/mojo/public/bindings/generators/mojom_pack.py index 8eab569..521dc14 100644 --- a/mojo/public/bindings/generators/mojom_pack.py +++ b/mojo/public/bindings/generators/mojom_pack.py @@ -41,6 +41,9 @@ class PackedField(object): self.offset = None self.bit = None +# Returns the pad necessary to reserve space for alignment of |size|. +def GetPad(offset, size): + return (size - (offset % size)) % size # Returns a 2-tuple of the field offset and bit (for BOOLs) def GetFieldOffset(field, last_field): @@ -50,8 +53,7 @@ def GetFieldOffset(field, last_field): return (last_field.offset, last_field.bit + 1) offset = last_field.offset + last_field.size - size = field.size - pad = (size - (offset % size)) % size + pad = GetPad(offset, field.size) return (offset + pad, 0) diff --git a/mojo/public/bindings/generators/run_cpp_generator.py b/mojo/public/bindings/generators/run_cpp_generator.py new file mode 100755 index 0000000..651669e --- /dev/null +++ b/mojo/public/bindings/generators/run_cpp_generator.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import ast +import mojom +import mojom_cpp_generator +import mojom_data +import mojom_pack +import sys + +def ReadDict(file): + with open(file, 'r') as f: + s = f.read() + dict = ast.literal_eval(s) + return dict + +dict = ReadDict(sys.argv[1]) +module = mojom_data.ModuleFromData(dict) +cpp = mojom_cpp_generator.CPPGenerator(module) +dir = None +if len(sys.argv) > 2: + dir = sys.argv[2] +cpp.GenerateFiles(dir) diff --git a/mojo/public/bindings/sample/sample_service.mojom b/mojo/public/bindings/sample/sample_service.mojom new file mode 100644 index 0000000..abbf28f --- /dev/null +++ b/mojo/public/bindings/sample/sample_service.mojom @@ -0,0 +1,31 @@ +{ + 'name': 'sample', + 'namespace': 'sample', + 'structs': [{ + 'name': 'Bar', + 'fields': [ + {'name': 'alpha', 'kind': 'u8', 'ordinal': 0}, + {'name': 'beta', 'kind': 'u8', 'ordinal': 1}, + {'name': 'gamma', 'kind': 'u8', 'ordinal': 2}]}, { + 'name': 'Foo', + 'fields': [ + {'name': 'name', 'kind': 's', 'ordinal': 8}, + {'name': 'x', 'kind': 'i32', 'ordinal': 0}, + {'name': 'y', 'kind': 'i32', 'ordinal': 1}, + {'name': 'a', 'kind': 'b', 'ordinal': 2}, + {'name': 'b', 'kind': 'b', 'ordinal': 3}, + {'name': 'c', 'kind': 'b', 'ordinal': 4}, + {'name': 'bar', 'kind': 'x:Bar', 'ordinal': 5}, + {'name': 'extra_bars', 'kind': 'a:x:Bar', 'ordinal': 7}, + {'name': 'data', 'kind': 'a:u8', 'ordinal': 6}, + {'name': 'files', 'kind': 'a:h', 'ordinal': 9}]}], + 'interfaces': [{ + 'name': 'Service', + 'methods': [{ + 'name': 'Frobinate', + 'ordinal': 0, + 'parameters': [ + {'name': 'foo', 'kind': 'x:Foo', 'ordinal': 0}, + {'name': 'baz', 'kind': 'b', 'ordinal': 1}, + {'name': 'port', 'kind': 'h', 'ordinal': 2}]}]}] +} |