summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mojo/public/bindings/generators/cpp_interface.template19
-rw-r--r--mojo/public/bindings/generators/cpp_struct.template43
-rw-r--r--mojo/public/bindings/generators/mojom_cpp_generator.py192
-rw-r--r--mojo/public/bindings/generators/mojom_pack.py6
-rwxr-xr-xmojo/public/bindings/generators/run_cpp_generator.py25
-rw-r--r--mojo/public/bindings/sample/sample_service.mojom31
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}]}]}]
+}