diff options
author | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-17 16:01:32 +0000 |
---|---|---|
committer | teravest@chromium.org <teravest@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-17 16:01:32 +0000 |
commit | 8c311f064c0ad5a70049f771bd15677bf7c9b098 (patch) | |
tree | 2a2727243475ff72eec47736e2567db064bba953 /ppapi/generators | |
parent | d68206fcca8a719e5152a09c6e9d235cdbcdeec3 (diff) | |
download | chromium_src-8c311f064c0ad5a70049f771bd15677bf7c9b098.zip chromium_src-8c311f064c0ad5a70049f771bd15677bf7c9b098.tar.gz chromium_src-8c311f064c0ad5a70049f771bd15677bf7c9b098.tar.bz2 |
Add support for generating thunk source from IDL.
This introduces a few new IDL attributes:
generate_thunk - Enables thunk generation for an IDL file.
create_func - Overrides the guessed create function name.
on_failure - Overrides the default return value on failure.
report_errors - Allows error reporting to be disabled.
By using these attributes, we can generate _thunk.cc files for many IDL
files.
I'll send CLs for moving the thunks separately, as I found it tiring to
review them all in a big lump. I have PPB_Widget_Dev here as an example.
BUG=
Review URL: https://chromiumcodereview.appspot.com/11417010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168450 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/generators')
-rwxr-xr-x | ppapi/generators/generator.py | 3 | ||||
-rwxr-xr-x | ppapi/generators/idl_c_header.py | 1 | ||||
-rwxr-xr-x | ppapi/generators/idl_c_proto.py | 75 | ||||
-rwxr-xr-x | ppapi/generators/idl_generator.py | 1 | ||||
-rwxr-xr-x | ppapi/generators/idl_thunk.py | 403 | ||||
-rw-r--r-- | ppapi/generators/test_thunk/basic_test_types.idl | 58 | ||||
-rw-r--r-- | ppapi/generators/test_thunk/simple.idl | 34 | ||||
-rw-r--r-- | ppapi/generators/test_thunk/simple_thunk.cc | 96 |
8 files changed, 643 insertions, 28 deletions
diff --git a/ppapi/generators/generator.py b/ppapi/generators/generator.py index 4511cd9..a71893c 100755 --- a/ppapi/generators/generator.py +++ b/ppapi/generators/generator.py @@ -13,6 +13,7 @@ from idl_option import ParseOptions from idl_outfile import IDLOutFile from idl_parser import ParseFiles from idl_c_header import HGen +from idl_thunk import TGen from idl_gen_pnacl import PnaclGen @@ -25,6 +26,7 @@ def Main(args): '--wnone', '--cgen', '--range=start,end', '--pnacl', '--pnaclshim', '../native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c', + '--tgen', ] current_dir = os.path.abspath(os.getcwd()) script_dir = os.path.abspath(os.path.dirname(__file__)) @@ -53,4 +55,3 @@ def Main(args): if __name__ == '__main__': sys.exit(Main(sys.argv[1:])) - diff --git a/ppapi/generators/idl_c_header.py b/ppapi/generators/idl_c_header.py index c1e6071..43b1745 100755 --- a/ppapi/generators/idl_c_header.py +++ b/ppapi/generators/idl_c_header.py @@ -21,7 +21,6 @@ from idl_generator import Generator, GeneratorByFile Option('dstroot', 'Base directory of output', default=os.path.join('..', 'c')) Option('guard', 'Include guard prefix', default=os.path.join('ppapi', 'c')) -Option('out', 'List of output files', default='') def GetOutFileName(filenode, relpath=None, prefix=None): diff --git a/ppapi/generators/idl_c_proto.py b/ppapi/generators/idl_c_proto.py index c522bab..fea5615 100755 --- a/ppapi/generators/idl_c_proto.py +++ b/ppapi/generators/idl_c_proto.py @@ -426,12 +426,15 @@ class CGen(object): # include_name - If true, include member name in the signature. # If false, leave it out. In any case, prefix and ptr_prefix # are always included. + # include_version - if True, include version in the member name # def GetSignature(self, node, release, mode, prefix='', func_as_ptr=True, - ptr_prefix='', include_name=True): + ptr_prefix='', include_name=True, include_version=False): self.LogEnter('GetSignature %s %s as func=%s' % (node, mode, func_as_ptr)) rtype, name, arrayspec, callspec = self.GetComponents(node, release, mode) + if include_version: + name = self.GetStructName(node, release, True) out = self.Compose(rtype, name, arrayspec, callspec, prefix, func_as_ptr, ptr_prefix, include_name) self.LogExit('Exit GetSignature: %s' % out) @@ -562,9 +565,49 @@ class CGen(object): # # Generate a comment or copyright block # - def Copyright(self, node, tabs=0): + def Copyright(self, node, cpp_style=False): lines = node.GetName().split('\n') - return CommentLines(lines, tabs) + if cpp_style: + return '//' + '\n//'.join(filter(lambda f: f != '', lines)) + '\n' + return CommentLines(lines) + + + def Indent(self, data, tabs=0): + """Handles indentation and 80-column line wrapping.""" + tab = ' ' * tabs + lines = [] + for line in data.split('\n'): + # Add indentation + line = tab + line + if len(line) <= 80: + lines.append(line.rstrip()) + else: + left = line.rfind('(') + 1 + args = line[left:].split(',') + orig_args = args + orig_left = left + # Try to split on '(arg1)' or '(arg1, arg2)', not '()' + while args[0][0] == ')': + left = line.rfind('(', 0, left - 1) + 1 + if left == 0: # No more parens, take the original option + args = orig_args + left = orig_left + break + args = line[left:].split(',') + + line_max = 0 + for arg in args: + if len(arg) > line_max: line_max = len(arg) + + if left + line_max >= 80: + indent = '%s ' % tab + args = (',\n%s' % indent).join([arg.strip() for arg in args]) + lines.append('%s\n%s%s' % (line[:left], indent, args)) + else: + indent = ' ' * (left - 1) + args = (',\n%s' % indent).join(args) + lines.append('%s%s' % (line[:left], args)) + return '\n'.join(lines) # Define a top level object. @@ -596,30 +639,10 @@ class CGen(object): out += comment_txt out += define_txt - tab = ' ' * tabs - lines = [] - for line in out.split('\n'): - # Add indentation - line = tab + line - if len(line) > 80: - left = line.rfind('(') + 1 - args = line[left:].split(',') - line_max = 0 - for arg in args: - if len(arg) > line_max: line_max = len(arg) - - if left + line_max >= 80: - space = '%s ' % tab - args = (',\n%s' % space).join([arg.strip() for arg in args]) - lines.append('%s\n%s%s' % (line[:left], space, args)) - else: - space = ' ' * (left - 1) - args = (',\n%s' % space).join(args) - lines.append('%s%s' % (line[:left], args)) - else: - lines.append(line.rstrip()) + indented_out = self.Indent(out, tabs) self.LogExit('Exit Define') - return '\n'.join(lines) + return indented_out + # Clean a string representing an object definition and return then string # as a single space delimited set of tokens. diff --git a/ppapi/generators/idl_generator.py b/ppapi/generators/idl_generator.py index 218b6b4..63277d2 100755 --- a/ppapi/generators/idl_generator.py +++ b/ppapi/generators/idl_generator.py @@ -11,6 +11,7 @@ from idl_parser import ParseFiles GeneratorList = [] +Option('out', 'List of output files', default='') Option('release', 'Which release to generate.', default='') Option('range', 'Which ranges in the form of MIN,MAX.', default='start,end') diff --git a/ppapi/generators/idl_thunk.py b/ppapi/generators/idl_thunk.py new file mode 100755 index 0000000..eb41f01 --- /dev/null +++ b/ppapi/generators/idl_thunk.py @@ -0,0 +1,403 @@ +#!/usr/bin/env python +# Copyright (c) 2012 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. + +""" Generator for C++ style thunks """ + +import glob +import os +import re +import sys + +from idl_log import ErrOut, InfoOut, WarnOut +from idl_node import IDLAttribute, IDLNode +from idl_ast import IDLAst +from idl_option import GetOption, Option, ParseOptions +from idl_outfile import IDLOutFile +from idl_parser import ParseFiles +from idl_c_proto import CGen, GetNodeComments, CommentLines, Comment +from idl_generator import Generator, GeneratorByFile + +Option('thunkroot', 'Base directory of output', + default=os.path.join('..', 'thunk')) + + +class TGenError(Exception): + def __init__(self, msg): + self.value = msg + + def __str__(self): + return repr(self.value) + + +def _GetBaseFileName(filenode): + """Returns the base name for output files, given the filenode. + + Examples: + 'dev/ppb_find_dev.h' -> 'ppb_find' + 'trusted/ppb_buffer_trusted.h' -> 'ppb_buffer_trusted' + """ + path, name = os.path.split(filenode.GetProperty('NAME')) + name = os.path.splitext(name)[0] + if name.endswith('_dev'): + # Clip off _dev suffix. + name = name[:-len('_dev')] + return name + + +def _GetHeaderFileName(filenode): + """Returns the name for the header for this file.""" + path, name = os.path.split(filenode.GetProperty('NAME')) + name = os.path.splitext(name)[0] + if path: + header = "ppapi/c/%s/%s.h" % (path, name) + else: + header = "ppapi/c/%s.h" % name + return header + + +def _GetThunkFileName(filenode, relpath): + """Returns the thunk file name.""" + path = os.path.split(filenode.GetProperty('NAME'))[0] + name = _GetBaseFileName(filenode) + # We don't reattach the path for thunk. + if relpath: name = os.path.join(relpath, name) + name = '%s%s' % (name, '_thunk.cc') + return name + + +def _MakeEnterLine(filenode, interface, arg, handle_errors, callback): + """Returns an EnterInstance/EnterResource string for a function.""" + if arg[0] == 'PP_Instance': + if callback is None: + return 'EnterInstance enter(%s);' % arg[1] + else: + return 'EnterInstance enter(%s, %s);' % (arg[1], callback) + elif arg[0] == 'PP_Resource': + api_name = interface.GetName() + if api_name.endswith('_Dev'): + api_name = api_name[:-len('_Dev')] + api_name += '_API' + + enter_type = 'EnterResource<%s>' % api_name + if callback is None: + return '%s enter(%s, %s);' % (enter_type, arg[1], + str(handle_errors).lower()) + else: + return '%s enter(%s, %s, %s);' % (enter_type, arg[1], + callback, + str(handle_errors).lower()) + else: + raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) + + +def _GetShortName(interface, filter_suffixes): + """Return a shorter interface name that matches Is* and Create* functions.""" + parts = interface.GetName().split('_')[1:] + tail = parts[len(parts) - 1] + if tail in filter_suffixes: + parts = parts[:-1] + return ''.join(parts) + + +def _IsTypeCheck(interface, node): + """Returns true if node represents a type-checking function.""" + return node.GetName() == 'Is%s' % _GetShortName(interface, ['Dev', 'Private']) + + +def _GetCreateFuncName(interface): + """Returns the creation function name for an interface.""" + return 'Create%s' % _GetShortName(interface, ['Dev']) + + +def _GetDefaultFailureValue(t): + """Returns the default failure value for a given type. + + Returns None if no default failure value exists for the type. + """ + values = { + 'PP_Bool': 'PP_FALSE', + 'PP_Resource': '0', + 'struct PP_Var': 'PP_MakeUndefined()', + 'int32_t': 'enter.retval()', + 'uint16_t': '0', + 'uint32_t': '0', + 'uint64_t': '0', + } + if t in values: + return values[t] + return None + + +def _MakeCreateMemberBody(interface, member, args): + """Returns the body of a Create() function. + + Args: + interface - IDLNode for the interface + member - IDLNode for member function + args - List of arguments for the Create() function + """ + if args[0][0] == 'PP_Resource': + body = ' Resource* object =\n' + body += ' PpapiGlobals::Get()->GetResourceTracker()->' + body += 'GetResource(%s);\n' % args[0][1] + body += ' if (!object)\n' + body += ' return 0;\n' + body += ' EnterResourceCreation enter(object->pp_instance());\n' + elif args[0][0] == 'PP_Instance': + body = ' EnterResourceCreation enter(%s);\n' % args[0][1] + else: + raise TGenError('Unknown arg type for Create(): %s' % args[0][0]) + + body += ' if (enter.failed())\n' + body += ' return 0;\n' + arg_list = ', '.join([a[1] for a in args]) + if member.GetProperty('create_func'): + create_func = member.GetProperty('create_func') + else: + create_func = _GetCreateFuncName(interface) + body += ' return enter.functions()->%s(%s);' % (create_func, + arg_list) + return body + + +def _MakeNormalMemberBody(filenode, node, member, rtype, args): + """Returns the body of a typical function. + + Args: + filenode - IDLNode for the file + node - IDLNode for the interface + member - IDLNode for the member function + rtype - Return type for the member function + args - List of 4-tuple arguments for the member function + """ + is_callback_func = args[len(args) - 1][0] == 'struct PP_CompletionCallback' + + if is_callback_func: + call_args = args[:-1] + [('', 'enter.callback()', '', '')] + else: + call_args = args + + if args[0][0] == 'PP_Instance': + call_arglist = ', '.join(a[1] for a in call_args) + function_container = 'functions' + else: + call_arglist = ', '.join(a[1] for a in call_args[1:]) + function_container = 'object' + + invocation = 'enter.%s()->%s(%s)' % (function_container, + member.GetName(), + call_arglist) + + handle_errors = not (member.GetProperty('report_errors') == 'False') + if is_callback_func: + body = ' %s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, + args[len(args) - 1][1]) + body += ' if (enter.failed())\n' + value = member.GetProperty('on_failure') + if value is None: + value = 'enter.retval()' + body += ' return %s;\n' % value + body += ' return enter.SetResult(%s);\n' % invocation + elif rtype == 'void': + body = ' %s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, + None) + body += ' if (enter.succeeded())\n' + body += ' %s;' % invocation + else: + value = member.GetProperty('on_failure') + if value is None: + value = _GetDefaultFailureValue(rtype) + if value is None: + raise TGenError('No default value for rtype %s' % rtype) + + body = ' %s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, + None) + body += ' if (enter.failed())\n' + body += ' return %s;\n' % value + body += ' return %s;' % invocation + return body + + +def DefineMember(filenode, node, member, release, include_version): + """Returns a definition for a member function of an interface. + + Args: + filenode - IDLNode for the file + node - IDLNode for the interface + member - IDLNode for the member function + release - release to generate + include_version - include the version in emitted function name. + Returns: + A string with the member definition. + """ + cgen = CGen() + rtype, name, arrays, args = cgen.GetComponents(member, release, 'return') + + if _IsTypeCheck(node, member): + body = ' %s\n' % _MakeEnterLine(filenode, node, args[0], False, None) + body += ' return PP_FromBool(enter.succeeded());' + elif member.GetName() == 'Create': + body = _MakeCreateMemberBody(node, member, args) + else: + body = _MakeNormalMemberBody(filenode, node, member, rtype, args) + + signature = cgen.GetSignature(member, release, 'return', func_as_ptr=False, + include_version=include_version) + member_code = '%s {\n%s\n}' % (signature, body) + return cgen.Indent(member_code, tabs=0) + + +class TGen(GeneratorByFile): + def __init__(self): + Generator.__init__(self, 'Thunk', 'tgen', 'Generate the C++ thunk.') + + def GenerateFile(self, filenode, releases, options): + savename = _GetThunkFileName(filenode, GetOption('thunkroot')) + my_min, my_max = filenode.GetMinMax(releases) + if my_min > releases[-1] or my_max < releases[0]: + if os.path.isfile(savename): + print "Removing stale %s for this range." % filenode.GetName() + os.remove(os.path.realpath(savename)) + return False + do_generate = filenode.GetProperty('generate_thunk') + if not do_generate: + return False + + thunk_out = IDLOutFile(savename) + self.GenerateHead(thunk_out, filenode, releases, options) + self.GenerateBody(thunk_out, filenode, releases, options) + self.GenerateTail(thunk_out, filenode, releases, options) + return thunk_out.Close() + + def GenerateHead(self, out, filenode, releases, options): + __pychecker__ = 'unusednames=options' + cgen = CGen() + + cright_node = filenode.GetChildren()[0] + assert(cright_node.IsA('Copyright')) + out.Write('%s\n' % cgen.Copyright(cright_node, cpp_style=True)) + + # Wrap the From ... modified ... comment if it would be >80 characters. + from_text = 'From %s' % ( + filenode.GetProperty('NAME').replace(os.sep,'/')) + modified_text = 'modified %s.' % ( + filenode.GetProperty('DATETIME')) + if len(from_text) + len(modified_text) < 74: + out.Write('// %s %s\n\n' % (from_text, modified_text)) + else: + out.Write('// %s,\n// %s\n\n' % (from_text, modified_text)) + + + # TODO(teravest): Don't emit includes we don't need. + includes = ['ppapi/c/pp_errors.h', + 'ppapi/shared_impl/tracked_callback.h', + 'ppapi/thunk/enter.h', + 'ppapi/thunk/ppb_instance_api.h', + 'ppapi/thunk/resource_creation_api.h', + 'ppapi/thunk/thunk.h'] + includes.append(_GetHeaderFileName(filenode)) + includes.append('ppapi/thunk/%s_api.h' % _GetBaseFileName(filenode)) + for include in sorted(includes): + out.Write('#include "%s"\n' % include) + out.Write('\n') + out.Write('namespace ppapi {\n') + out.Write('namespace thunk {\n') + out.Write('\n') + out.Write('namespace {\n') + out.Write('\n') + + def GenerateBody(self, out, filenode, releases, options): + __pychecker__ = 'unusednames=options' + for node in filenode.GetListOf('Interface'): + # Skip if this node is not in this release + if not node.InReleases(releases): + print "Skipping %s" % node + continue + + # Generate Member functions + if node.IsA('Interface'): + members = [] + for child in node.GetListOf('Member'): + build_list = child.GetUniqueReleases(releases) + # We have to filter out releases this node isn't in. + build_list = filter(lambda r: child.InReleases([r]), build_list) + if len(build_list) == 0: + continue + release = build_list[-1] # Pick the newest release. + member = DefineMember(filenode, node, child, release, False) + if not member: + continue + members.append(member) + for build in build_list[:-1]: + member = DefineMember(filenode, node, child, build, True) + if not member: + continue + members.append(member) + out.Write('\n\n'.join(members)) + + def GenerateTail(self, out, filenode, releases, options): + __pychecker__ = 'unusednames=options' + cgen = CGen() + + version_list = [] + out.Write('\n\n') + for node in filenode.GetListOf('Interface'): + build_list = node.GetUniqueReleases(releases) + for build in build_list: + version = node.GetVersion(build).replace('.', '_') + thunk_name = 'g_' + node.GetName().lower() + '_thunk_' + \ + version + thunk_type = '_'.join((node.GetName(), version)) + version_list.append((thunk_type, thunk_name)) + + out.Write('const %s %s = {\n' % (thunk_type, thunk_name)) + for child in node.GetListOf('Member'): + rtype, name, arrays, args = cgen.GetComponents( + child, build, 'return') + if child.InReleases([build]): # TEST + out.Write(' &%s,\n' % name) + out.Write('};\n\n') + + out.Write('} // namespace\n') + out.Write('\n') + for thunk_type, thunk_name in version_list: + thunk_decl = 'const %s* Get%s_Thunk() {\n' % (thunk_type, thunk_type) + if len(thunk_decl) > 80: + thunk_decl = 'const %s*\n Get%s_Thunk() {\n' % (thunk_type, + thunk_type) + out.Write(thunk_decl) + out.Write(' return &%s;\n' % thunk_name) + out.Write('}\n') + out.Write('\n') + out.Write('} // namespace thunk\n') + out.Write('} // namespace ppapi\n') + + +tgen = TGen() + + +def Main(args): + # Default invocation will verify the golden files are unchanged. + failed = 0 + if not args: + args = ['--wnone', '--diff', '--test', '--thunkroot=.'] + + ParseOptions(args) + + idldir = os.path.split(sys.argv[0])[0] + idldir = os.path.join(idldir, 'test_thunk', '*.idl') + filenames = glob.glob(idldir) + ast = ParseFiles(filenames) + if tgen.GenerateRange(ast, ['M13', 'M14'], {}): + print "Golden file for M13-M14 failed." + failed = 1 + else: + print "Golden file for M13-M14 passed." + + return failed + + +if __name__ == '__main__': + sys.exit(Main(sys.argv[1:])) diff --git a/ppapi/generators/test_thunk/basic_test_types.idl b/ppapi/generators/test_thunk/basic_test_types.idl new file mode 100644 index 0000000..0f42466 --- /dev/null +++ b/ppapi/generators/test_thunk/basic_test_types.idl @@ -0,0 +1,58 @@ +/* Copyright (c) 2011 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. + */ + +/** + * This file defines some basic types for use in testing. + */ + +label Chrome { + M13 = 0.0, + M14 = 1.0, + M15 = 2.0 +}; + +[version=0.0] +describe { + /** Standard Ints. */ + int8_t; + int16_t; + int32_t; + int64_t; + uint8_t; + uint16_t; + uint32_t; + uint64_t; + /** Small and large floats. */ + double_t; + float_t; + + /** Native file handle (int). */ + handle_t; + + /** Interface object (void *). */ + interface_t; + + /** Used for padding, should be (u)int8_t */ + char; + + /** Pointer to memory (void *). */ + mem_t; + + /** Pointer to null terminated string (char *). */ + str_t; + + /** No return value. */ + void; + + /** Pointer to pointer to memory (void **). */ + blob_t; + + /** Pepper types */ + PP_Bool; + PP_Instance; + PP_Resource; + PP_Var; +}; + diff --git a/ppapi/generators/test_thunk/simple.idl b/ppapi/generators/test_thunk/simple.idl new file mode 100644 index 0000000..30beace --- /dev/null +++ b/ppapi/generators/test_thunk/simple.idl @@ -0,0 +1,34 @@ +/* Copyright (c) 2012 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. + */ + +[generate_thunk] + +/** + * This file defines the <code>PPB_Simple</code> interface. + */ + +label Chrome { + M13 = 0.5, + M14 = 1.0 +}; + +interface PPB_Simple { + PP_Resource Create([in] PP_Instance instance); + + PP_Bool IsSimple([in] PP_Resource resource); + + [deprecate=1.0] + void PostMessage([in] PP_Instance instance, [in] PP_Var message); + + uint32_t DoUint32Instance([in] PP_Instance instance); + + uint32_t DoUint32Resource([in] PP_Resource instance); + + [report_errors=False] + uint32_t DoUint32ResourceNoErrors([in] PP_Resource instance); + + [version=1.0, on_failure="12"] + int32_t OnFailure12([in] PP_Instance instance); +}; diff --git a/ppapi/generators/test_thunk/simple_thunk.cc b/ppapi/generators/test_thunk/simple_thunk.cc new file mode 100644 index 0000000..e6418f0 --- /dev/null +++ b/ppapi/generators/test_thunk/simple_thunk.cc @@ -0,0 +1,96 @@ +// Copyright (c) 2012 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. + +// From ../test_thunk/simple.idl modified Fri Nov 16 11:26:06 2012. + +#include "ppapi/c/../test_thunk/simple.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_instance_api.h" +#include "ppapi/thunk/resource_creation_api.h" +#include "ppapi/thunk/simple_api.h" +#include "ppapi/thunk/thunk.h" + +namespace ppapi { +namespace thunk { + +namespace { + +PP_Resource Create(PP_Instance instance) { + EnterResourceCreation enter(instance); + if (enter.failed()) + return 0; + return enter.functions()->CreateSimple(instance); +} + +PP_Bool IsSimple(PP_Resource resource) { + EnterResource<PPB_Simple_API> enter(resource, false); + return PP_FromBool(enter.succeeded()); +} + +void PostMessage(PP_Instance instance, PP_Var message) { + EnterInstance enter(instance); + if (enter.succeeded()) + enter.functions()->PostMessage(instance, message); +} + +uint32_t DoUint32Instance(PP_Instance instance) { + EnterInstance enter(instance); + if (enter.failed()) + return 0; + return enter.functions()->DoUint32Instance(instance); +} + +uint32_t DoUint32Resource(PP_Resource instance) { + EnterResource<PPB_Simple_API> enter(instance, true); + if (enter.failed()) + return 0; + return enter.object()->DoUint32Resource(); +} + +uint32_t DoUint32ResourceNoErrors(PP_Resource instance) { + EnterResource<PPB_Simple_API> enter(instance, false); + if (enter.failed()) + return 0; + return enter.object()->DoUint32ResourceNoErrors(); +} + +int32_t OnFailure12(PP_Instance instance) { + EnterInstance enter(instance); + if (enter.failed()) + return 12; + return enter.functions()->OnFailure12(instance); +} + +const PPB_Simple_0_5 g_ppb_simple_thunk_0_5 = { + &Create, + &IsSimple, + &PostMessage, + &DoUint32Instance, + &DoUint32Resource, + &DoUint32ResourceNoErrors, +}; + +const PPB_Simple_1_0 g_ppb_simple_thunk_1_0 = { + &Create, + &IsSimple, + &DoUint32Instance, + &DoUint32Resource, + &DoUint32ResourceNoErrors, + &OnFailure12, +}; + +} // namespace + +const PPB_Simple_0_5* GetPPB_Simple_0_5_Thunk() { + return &g_ppb_simple_thunk_0_5; +} + +const PPB_Simple_1_0* GetPPB_Simple_1_0_Thunk() { + return &g_ppb_simple_thunk_1_0; +} + +} // namespace thunk +} // namespace ppapi |