summaryrefslogtreecommitdiff
path: root/tools/make_cpptoc_impl.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/make_cpptoc_impl.py')
-rw-r--r--tools/make_cpptoc_impl.py765
1 files changed, 765 insertions, 0 deletions
diff --git a/tools/make_cpptoc_impl.py b/tools/make_cpptoc_impl.py
new file mode 100644
index 00000000..96924511
--- /dev/null
+++ b/tools/make_cpptoc_impl.py
@@ -0,0 +1,765 @@
+# Copyright (c) 2011 The Chromium Embedded Framework 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 __future__ import absolute_import
+from cef_parser import *
+
+
+def make_cpptoc_impl_proto(name, func, parts):
+ if isinstance(func, obj_function_virtual):
+ proto = parts['retval'] + ' CEF_CALLBACK'
+ else:
+ proto = 'CEF_EXPORT ' + parts['retval']
+
+ proto += ' ' + name + '(' + ', '.join(parts['args']) + ')'
+ return proto
+
+
+def make_cpptoc_function_impl_existing(cls, name, func, impl, defined_names):
+ notify(name + ' has manual edits')
+
+ # retrieve the C API prototype parts
+ parts = func.get_capi_parts(defined_names, True)
+
+ changes = format_translation_changes(impl, parts)
+ if len(changes) > 0:
+ notify(name + ' prototype changed')
+
+ return make_cpptoc_impl_proto(
+ name, func, parts) + '{' + changes + impl['body'] + '\n}\n\n'
+
+
+def make_cpptoc_function_impl_new(cls, name, func, defined_names, base_scoped):
+ # Special handling for the cef_shutdown global function.
+ is_cef_shutdown = name == 'cef_shutdown' and isinstance(
+ func.parent, obj_header)
+
+ # retrieve the C API prototype parts
+ parts = func.get_capi_parts(defined_names, True)
+ result = make_cpptoc_impl_proto(name, func, parts) + ' {'
+
+ if isinstance(func.parent, obj_class) and \
+ not func.parent.has_attrib('no_debugct_check') and \
+ not base_scoped:
+ result += '\n shutdown_checker::AssertNotShutdown();\n'
+
+ invalid = []
+
+ # retrieve the function arguments
+ args = func.get_arguments()
+
+ # determine the argument types
+ for arg in args:
+ if arg.get_arg_type() == 'invalid':
+ invalid.append(arg.get_name())
+
+ # retrieve the function return value
+ retval = func.get_retval()
+ retval_type = retval.get_retval_type()
+ if retval_type == 'invalid':
+ invalid.append('(return value)')
+ retval_default = ''
+ else:
+ retval_default = retval.get_retval_default(True)
+ if len(retval_default) > 0:
+ retval_default = ' ' + retval_default
+
+ if len(invalid) > 0:
+ notify(name + ' could not be autogenerated')
+ # code could not be auto-generated
+ result += '\n // BEGIN DELETE BEFORE MODIFYING'
+ result += '\n // AUTO-GENERATED CONTENT'
+ result += '\n // COULD NOT IMPLEMENT DUE TO: ' + ', '.join(invalid)
+ result += '\n #pragma message("Warning: "__FILE__": ' + name + ' is not implemented")'
+ result += '\n // END DELETE BEFORE MODIFYING'
+ result += '\n}\n\n'
+ return result
+
+ result += '\n // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING\n'
+
+ result_len = len(result)
+
+ optional = []
+
+ # parameter verification
+ if isinstance(func, obj_function_virtual):
+ result += '\n DCHECK(self);'\
+ '\n if (!self) {'\
+ '\n return'+retval_default+';'\
+ '\n }'
+
+ for arg in args:
+ arg_type = arg.get_arg_type()
+ arg_name = arg.get_type().get_name()
+
+ # skip optional params
+ optional_params = arg.parent.get_attrib_list('optional_param')
+ if not optional_params is None and arg_name in optional_params:
+ optional.append(arg_name)
+ continue
+
+ comment = '\n // Verify param: ' + arg_name + '; type: ' + arg_type
+
+ if arg_type == 'simple_byref' or arg_type == 'simple_byref_const' or \
+ arg_type == 'simple_byaddr' or arg_type == 'bool_byref' or arg_type == 'bool_byaddr' or \
+ arg_type == 'struct_byref_const' or arg_type == 'struct_byref' or \
+ arg_type == 'string_byref_const' or arg_type == 'string_byref' or \
+ arg_type == 'refptr_same' or arg_type == 'refptr_same_byref' or \
+ arg_type == 'refptr_diff' or arg_type == 'refptr_diff_byref' or \
+ arg_type == 'ownptr_same' or arg_type == 'ownptr_same_byref' or \
+ arg_type == 'ownptr_diff' or arg_type == 'ownptr_diff_byref' or \
+ arg_type == 'rawptr_same' or arg_type == 'rawptr_same_byref' or \
+ arg_type == 'rawptr_diff' or arg_type == 'rawptr_diff_byref' or \
+ arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const' or \
+ arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const' or \
+ arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const':
+ result += comment+\
+ '\n DCHECK('+arg_name+');'\
+ '\n if (!'+arg_name+') {'\
+ '\n return'+retval_default+';'\
+ '\n }'
+ if arg_type == 'struct_byref_const' or arg_type == 'struct_byref':
+ result +=\
+ '\n if (!template_util::has_valid_size('+arg_name+')) {'\
+ '\n NOTREACHED() << "invalid '+arg_name+'->[base.]size";'\
+ '\n return'+retval_default+';'\
+ '\n }'
+ elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
+ arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref' or \
+ arg_type == 'ownptr_vec_same_byref' or arg_type == 'ownptr_vec_diff_byref' or \
+ arg_type == 'rawptr_vec_same_byref' or arg_type == 'rawptr_vec_diff_byref':
+ result += comment+\
+ '\n DCHECK('+arg_name+'Count && (*'+arg_name+'Count == 0 || '+arg_name+'));'\
+ '\n if (!'+arg_name+'Count || (*'+arg_name+'Count > 0 && !'+arg_name+')) {'\
+ '\n return'+retval_default+';'\
+ '\n }'
+ elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \
+ arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \
+ arg_type == 'ownptr_vec_same_byref_const' or arg_type == 'ownptr_vec_diff_byref_const' or \
+ arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const':
+ result += comment+\
+ '\n DCHECK('+arg_name+'Count == 0 || '+arg_name+');'\
+ '\n if ('+arg_name+'Count > 0 && !'+arg_name+') {'\
+ '\n return'+retval_default+';'\
+ '\n }'
+
+ # check index params
+ index_params = arg.parent.get_attrib_list('index_param')
+ if not index_params is None and arg_name in index_params:
+ result += comment+\
+ '\n DCHECK_GE('+arg_name+', 0);'\
+ '\n if ('+arg_name+' < 0) {'\
+ '\n return'+retval_default+';'\
+ '\n }'
+
+ if len(optional) > 0:
+ # Wrap the comment at 80 characters.
+ str = '\n // Unverified params: ' + optional[0]
+ for name in optional[1:]:
+ str += ','
+ if len(str) + len(name) + 1 > 80:
+ result += str
+ str = '\n //'
+ str += ' ' + name
+ result += str
+
+ if len(result) != result_len:
+ result += '\n'
+ result_len = len(result)
+
+ # parameter translation
+ params = []
+
+ for arg in args:
+ arg_type = arg.get_arg_type()
+ arg_name = arg.get_type().get_name()
+
+ comment = '\n // Translate param: ' + arg_name + '; type: ' + arg_type
+
+ if arg_type == 'simple_byval' or arg_type == 'simple_byaddr':
+ params.append(arg_name)
+ elif arg_type == 'simple_byref' or arg_type == 'simple_byref_const':
+ data_type = arg.get_type().get_type()
+ default = arg.get_type().get_result_simple_default()
+ result += comment+\
+ '\n '+data_type+' '+arg_name+'Val = '+arg_name+'?*'+arg_name+':'+default+';'
+ params.append(arg_name + 'Val')
+ elif arg_type == 'bool_byval':
+ params.append(arg_name + '?true:false')
+ elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr':
+ result += comment+\
+ '\n bool '+arg_name+'Bool = ('+arg_name+' && *'+arg_name+')?true:false;'
+ if arg_type == 'bool_byref':
+ params.append(arg_name + 'Bool')
+ else:
+ params.append('&' + arg_name + 'Bool')
+ elif arg_type == 'struct_byref_const':
+ struct_type = arg.get_type().get_type()
+ result += comment+\
+ '\n '+struct_type+' '+arg_name+'Obj;'\
+ '\n if ('+arg_name+') {'\
+ '\n '+arg_name+'Obj.Set(*'+arg_name+', false);'\
+ '\n }'
+ params.append(arg_name + 'Obj')
+ elif arg_type == 'struct_byref':
+ struct_type = arg.get_type().get_type()
+ result += comment+\
+ '\n '+struct_type+' '+arg_name+'Obj;'\
+ '\n if ('+arg_name+') {'\
+ '\n '+arg_name+'Obj.AttachTo(*'+arg_name+');'\
+ '\n }'
+ params.append(arg_name + 'Obj')
+ elif arg_type == 'string_byref_const':
+ params.append('CefString(' + arg_name + ')')
+ elif arg_type == 'string_byref':
+ result += comment+\
+ '\n CefString '+arg_name+'Str('+arg_name+');'
+ params.append(arg_name + 'Str')
+ elif arg_type == 'refptr_same' or arg_type == 'refptr_diff':
+ ptr_class = arg.get_type().get_ptr_type()
+ if arg_type == 'refptr_same':
+ params.append(ptr_class + 'CppToC::Unwrap(' + arg_name + ')')
+ else:
+ params.append(ptr_class + 'CToCpp::Wrap(' + arg_name + ')')
+ elif arg_type == 'ownptr_same' or arg_type == 'rawptr_same':
+ ptr_class = arg.get_type().get_ptr_type()
+ if arg_type == 'ownptr_same':
+ params.append(ptr_class + 'CppToC::UnwrapOwn(' + arg_name + ')')
+ else:
+ params.append(ptr_class + 'CppToC::UnwrapRaw(' + arg_name + ')')
+ elif arg_type == 'ownptr_diff' or arg_type == 'rawptr_diff':
+ ptr_class = arg.get_type().get_ptr_type()
+ result += comment+\
+ '\n CefOwnPtr<'+ptr_class+'> '+arg_name+'Ptr('+ptr_class+'CToCpp::Wrap('+arg_name+'));'
+ if arg_type == 'ownptr_diff':
+ params.append('std::move(' + arg_name + 'Ptr)')
+ else:
+ params.append(arg_name + 'Ptr.get()')
+ elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
+ ptr_class = arg.get_type().get_ptr_type()
+ if arg_type == 'refptr_same_byref':
+ assign = ptr_class + 'CppToC::Unwrap(*' + arg_name + ')'
+ else:
+ assign = ptr_class + 'CToCpp::Wrap(*' + arg_name + ')'
+ result += comment+\
+ '\n CefRefPtr<'+ptr_class+'> '+arg_name+'Ptr;'\
+ '\n if ('+arg_name+' && *'+arg_name+') {'\
+ '\n '+arg_name+'Ptr = '+assign+';'\
+ '\n }'\
+ '\n '+ptr_class+'* '+arg_name+'Orig = '+arg_name+'Ptr.get();'
+ params.append(arg_name + 'Ptr')
+ elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const':
+ result += comment+\
+ '\n std::vector<CefString> '+arg_name+'List;'\
+ '\n transfer_string_list_contents('+arg_name+', '+arg_name+'List);'
+ params.append(arg_name + 'List')
+ elif arg_type == 'string_map_single_byref' or arg_type == 'string_map_single_byref_const':
+ result += comment+\
+ '\n std::map<CefString, CefString> '+arg_name+'Map;'\
+ '\n transfer_string_map_contents('+arg_name+', '+arg_name+'Map);'
+ params.append(arg_name + 'Map')
+ elif arg_type == 'string_map_multi_byref' or arg_type == 'string_map_multi_byref_const':
+ result += comment+\
+ '\n std::multimap<CefString, CefString> '+arg_name+'Multimap;'\
+ '\n transfer_string_multimap_contents('+arg_name+', '+arg_name+'Multimap);'
+ params.append(arg_name + 'Multimap')
+ elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
+ arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref':
+ vec_type = arg.get_type().get_vector_type()
+ if arg_type == 'simple_vec_byref':
+ assign = arg_name + '[i]'
+ elif arg_type == 'bool_vec_byref':
+ assign = arg_name + '[i]?true:false'
+ elif arg_type == 'refptr_vec_same_byref':
+ ptr_class = arg.get_type().get_ptr_type()
+ assign = ptr_class + 'CppToC::Unwrap(' + arg_name + '[i])'
+ elif arg_type == 'refptr_vec_diff_byref':
+ ptr_class = arg.get_type().get_ptr_type()
+ assign = ptr_class + 'CToCpp::Wrap(' + arg_name + '[i])'
+ result += comment+\
+ '\n std::vector<'+vec_type+' > '+arg_name+'List;'\
+ '\n if ('+arg_name+'Count && *'+arg_name+'Count > 0 && '+arg_name+') {'\
+ '\n for (size_t i = 0; i < *'+arg_name+'Count; ++i) {'\
+ '\n '+arg_name+'List.push_back('+assign+');'\
+ '\n }'\
+ '\n }'
+ params.append(arg_name + 'List')
+ elif arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const' or \
+ arg_type == 'refptr_vec_same_byref_const' or arg_type == 'refptr_vec_diff_byref_const' or \
+ arg_type == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const':
+ vec_type = arg.get_type().get_vector_type()
+ if arg_type == 'simple_vec_byref_const':
+ assign = arg_name + '[i]'
+ elif arg_type == 'bool_vec_byref_const':
+ assign = arg_name + '[i]?true:false'
+ else:
+ ptr_class = arg.get_type().get_ptr_type()
+ if arg_type == 'refptr_vec_same_byref_const':
+ assign = ptr_class + 'CppToC::Unwrap(' + arg_name + '[i])'
+ elif arg_type == 'refptr_vec_diff_byref_const':
+ assign = ptr_class + 'CToCpp::Wrap(' + arg_name + '[i])'
+ elif arg_type == 'rawptr_vec_same_byref_const':
+ assign = ptr_class + 'CppToC::UnwrapRaw(' + arg_name + '[i])'
+ elif arg_type == 'rawptr_vec_diff_byref_const':
+ assign = ptr_class + 'CToCpp::Wrap(' + arg_name + '[i]).release()'
+ result += comment+\
+ '\n std::vector<'+vec_type+' > '+arg_name+'List;'\
+ '\n if ('+arg_name+'Count > 0) {'\
+ '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\
+ '\n '+vec_type+' '+arg_name+'Val = '+assign+';'\
+ '\n '+arg_name+'List.push_back('+arg_name+'Val);'\
+ '\n }'\
+ '\n }'
+ params.append(arg_name + 'List')
+ else:
+ raise Exception('Unsupported argument type %s for parameter %s in %s' %
+ (arg_type, arg_name, name))
+
+ if len(result) != result_len:
+ result += '\n'
+ result_len = len(result)
+
+ if is_cef_shutdown:
+ result += '\n\n#if DCHECK_IS_ON()'\
+ '\n shutdown_checker::SetIsShutdown();'\
+ '\n#endif\n'
+
+ # execution
+ result += '\n // Execute\n '
+
+ if retval_type != 'none':
+ # has a return value
+ if retval_type == 'simple':
+ result += retval.get_type().get_result_simple_type()
+ else:
+ result += retval.get_type().get_type()
+ result += ' _retval = '
+
+ if isinstance(func.parent, obj_class):
+ # virtual and static class methods
+ if isinstance(func, obj_function_virtual):
+ if cls.get_name() == func.parent.get_name():
+ # virtual method for the current class
+ result += func.parent.get_name() + 'CppToC::Get(self)->'
+ else:
+ # virtual method for a parent class
+ result += cls.get_name(
+ ) + 'CppToC::Get(reinterpret_cast<' + cls.get_capi_name() + '*>(self))->'
+ else:
+ result += func.parent.get_name() + '::'
+ result += func.get_name() + '('
+
+ if len(params) > 0:
+ result += '\n ' + ',\n '.join(params)
+
+ result += ');\n'
+
+ result_len = len(result)
+
+ # parameter restoration
+ for arg in args:
+ arg_type = arg.get_arg_type()
+ arg_name = arg.get_type().get_name()
+
+ comment = '\n // Restore param: ' + arg_name + '; type: ' + arg_type
+
+ if arg_type == 'simple_byref':
+ result += comment+\
+ '\n if ('+arg_name+') {'\
+ '\n *'+arg_name+' = '+arg_name+'Val;'\
+ '\n }'
+ elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr':
+ result += comment+\
+ '\n if ('+arg_name+') {'\
+ '\n *'+arg_name+' = '+arg_name+'Bool?true:false;'\
+ '\n }'
+ elif arg_type == 'struct_byref':
+ result += comment+\
+ '\n if ('+arg_name+') {'\
+ '\n '+arg_name+'Obj.DetachTo(*'+arg_name+');'\
+ '\n }'
+ elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref':
+ ptr_class = arg.get_type().get_ptr_type()
+ if arg_type == 'refptr_same_byref':
+ assign = ptr_class + 'CppToC::Wrap(' + arg_name + 'Ptr)'
+ else:
+ assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + 'Ptr)'
+ result += comment+\
+ '\n if ('+arg_name+') {'\
+ '\n if ('+arg_name+'Ptr.get()) {'\
+ '\n if ('+arg_name+'Ptr.get() != '+arg_name+'Orig) {'\
+ '\n *'+arg_name+' = '+assign+';'\
+ '\n }'\
+ '\n } else {'\
+ '\n *'+arg_name+' = nullptr;'\
+ '\n }'\
+ '\n }'
+ elif arg_type == 'string_vec_byref':
+ result += comment+\
+ '\n cef_string_list_clear('+arg_name+');'\
+ '\n transfer_string_list_contents('+arg_name+'List, '+arg_name+');'
+ elif arg_type == 'string_map_single_byref':
+ result += comment+\
+ '\n cef_string_map_clear('+arg_name+');'\
+ '\n transfer_string_map_contents('+arg_name+'Map, '+arg_name+');'
+ elif arg_type == 'string_map_multi_byref':
+ result += comment+\
+ '\n cef_string_multimap_clear('+arg_name+');'\
+ '\n transfer_string_multimap_contents('+arg_name+'Multimap, '+arg_name+');'
+ elif arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref' or \
+ arg_type == 'refptr_vec_same_byref' or arg_type == 'refptr_vec_diff_byref':
+ if arg_type == 'simple_vec_byref' or arg_type == 'bool_vec_byref':
+ assign = arg_name + 'List[i]'
+ elif arg_type == 'refptr_vec_same_byref':
+ ptr_class = arg.get_type().get_ptr_type()
+ assign = ptr_class + 'CppToC::Wrap(' + arg_name + 'List[i])'
+ elif arg_type == 'refptr_vec_diff_byref':
+ ptr_class = arg.get_type().get_ptr_type()
+ assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + 'List[i])'
+ result += comment+\
+ '\n if ('+arg_name+'Count && '+arg_name+') {'\
+ '\n *'+arg_name+'Count = std::min('+arg_name+'List.size(), *'+arg_name+'Count);'\
+ '\n if (*'+arg_name+'Count > 0) {'\
+ '\n for (size_t i = 0; i < *'+arg_name+'Count; ++i) {'\
+ '\n '+arg_name+'[i] = '+assign+';'\
+ '\n }'\
+ '\n }'\
+ '\n }'
+ elif arg_type == 'rawptr_vec_diff_byref_const':
+ result += comment+\
+ '\n if ('+arg_name+'Count > 0) {'\
+ '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\
+ '\n delete '+arg_name+'List[i];'\
+ '\n }'\
+ '\n }'
+
+ if len(result) != result_len:
+ result += '\n'
+ result_len = len(result)
+
+ if len(result) != result_len:
+ result += '\n'
+ result_len = len(result)
+
+ # return translation
+ if retval_type != 'none':
+ # has a return value
+ result += '\n // Return type: ' + retval_type
+ if retval_type == 'simple' or retval_type == 'bool':
+ result += '\n return _retval;'
+ elif retval_type == 'string':
+ result += '\n return _retval.DetachToUserFree();'
+ elif retval_type == 'refptr_same':
+ ptr_class = retval.get_type().get_ptr_type()
+ result += '\n return ' + ptr_class + 'CppToC::Wrap(_retval);'
+ elif retval_type == 'refptr_diff':
+ ptr_class = retval.get_type().get_ptr_type()
+ result += '\n return ' + ptr_class + 'CToCpp::Unwrap(_retval);'
+ elif retval_type == 'ownptr_same':
+ ptr_class = retval.get_type().get_ptr_type()
+ result += '\n return ' + ptr_class + 'CppToC::WrapOwn(std::move(_retval));'
+ elif retval_type == 'ownptr_diff':
+ ptr_class = retval.get_type().get_ptr_type()
+ result += '\n return ' + ptr_class + 'CToCpp::UnwrapOwn(std::move(_retval));'
+ else:
+ raise Exception('Unsupported return type %s in %s' % (retval_type, name))
+
+ if len(result) != result_len:
+ result += '\n'
+
+ result += '}\n\n'
+ return result
+
+
+def make_cpptoc_function_impl(cls, funcs, existing, prefixname, defined_names,
+ base_scoped):
+ impl = ''
+
+ for func in funcs:
+ if not prefixname is None:
+ name = prefixname + '_' + func.get_capi_name()
+ else:
+ name = func.get_capi_name()
+ value = get_next_function_impl(existing, name)
+ if not value is None \
+ and value['body'].find('// AUTO-GENERATED CONTENT') < 0:
+ # an implementation exists that was not auto-generated
+ impl += make_cpptoc_function_impl_existing(cls, name, func, value,
+ defined_names)
+ else:
+ impl += make_cpptoc_function_impl_new(cls, name, func, defined_names,
+ base_scoped)
+
+ return impl
+
+
+def make_cpptoc_virtual_function_impl(header, cls, existing, prefixname,
+ defined_names, base_scoped):
+ funcs = []
+ funcs.extend(cls.get_virtual_funcs())
+ cur_cls = cls
+ while True:
+ parent_name = cur_cls.get_parent_name()
+ if is_base_class(parent_name):
+ break
+ else:
+ parent_cls = header.get_class(parent_name, defined_names)
+ if parent_cls is None:
+ raise Exception('Class does not exist: ' + parent_name)
+ funcs.extend(parent_cls.get_virtual_funcs())
+ cur_cls = header.get_class(parent_name, defined_names)
+
+ return make_cpptoc_function_impl(cls, funcs, existing, prefixname,
+ defined_names, base_scoped)
+
+
+def make_cpptoc_virtual_function_assignment_block(funcs, offset, prefixname):
+ impl = ''
+ for func in funcs:
+ name = func.get_capi_name()
+ impl += ' GetStruct()->' + offset + name + ' = ' + prefixname + '_' + name + ';\n'
+ return impl
+
+
+def make_cpptoc_virtual_function_assignment(header, cls, prefixname,
+ defined_names):
+ impl = make_cpptoc_virtual_function_assignment_block(cls.get_virtual_funcs(),
+ '', prefixname)
+
+ cur_cls = cls
+ offset = ''
+ while True:
+ parent_name = cur_cls.get_parent_name()
+ offset += 'base.'
+ if is_base_class(parent_name):
+ break
+ else:
+ parent_cls = header.get_class(parent_name, defined_names)
+ if parent_cls is None:
+ raise Exception('Class does not exist: ' + parent_name)
+ impl += make_cpptoc_virtual_function_assignment_block(
+ parent_cls.get_virtual_funcs(), offset, prefixname)
+ cur_cls = header.get_class(parent_name, defined_names)
+
+ return impl
+
+
+def make_cpptoc_unwrap_derived(header, cls, base_scoped):
+ # identify all classes that derive from cls
+ derived_classes = []
+ cur_clsname = cls.get_name()
+ allclasses = header.get_classes()
+ for cur_cls in allclasses:
+ if cur_cls.get_name() == cur_clsname:
+ continue
+ if cur_cls.has_parent(cur_clsname):
+ derived_classes.append(cur_cls.get_name())
+
+ derived_classes = sorted(derived_classes)
+
+ if base_scoped:
+ impl = ['', '']
+ for clsname in derived_classes:
+ impl[0] += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
+ ' return '+clsname+'CppToC::UnwrapOwn(reinterpret_cast<'+\
+ get_capi_name(clsname, True)+'*>(s));\n'+\
+ ' }\n'
+ impl[1] += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
+ ' return '+clsname+'CppToC::UnwrapRaw(reinterpret_cast<'+\
+ get_capi_name(clsname, True)+'*>(s));\n'+\
+ ' }\n'
+ else:
+ impl = ''
+ for clsname in derived_classes:
+ impl += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\
+ ' return '+clsname+'CppToC::Unwrap(reinterpret_cast<'+\
+ get_capi_name(clsname, True)+'*>(s));\n'+\
+ ' }\n'
+ return impl
+
+
+def make_cpptoc_class_impl(header, clsname, impl):
+ # structure names that have already been defined
+ defined_names = header.get_defined_structs()
+
+ # retrieve the class and populate the defined names
+ cls = header.get_class(clsname, defined_names)
+ if cls is None:
+ raise Exception('Class does not exist: ' + clsname)
+
+ capiname = cls.get_capi_name()
+ prefixname = get_capi_name(clsname[3:], False)
+
+ # retrieve the existing virtual function implementations
+ existing = get_function_impls(impl, 'CEF_CALLBACK')
+
+ base_class_name = header.get_base_class_name(clsname)
+ base_scoped = True if base_class_name == 'CefBaseScoped' else False
+ if base_scoped:
+ template_class = 'CefCppToCScoped'
+ else:
+ template_class = 'CefCppToCRefCounted'
+
+ # generate virtual functions
+ virtualimpl = make_cpptoc_virtual_function_impl(
+ header, cls, existing, prefixname, defined_names, base_scoped)
+ if len(virtualimpl) > 0:
+ virtualimpl = '\nnamespace {\n\n// MEMBER FUNCTIONS - Body may be edited by hand.\n\n' + virtualimpl + '} // namespace'
+
+ # the current class is already defined for static functions
+ defined_names.append(cls.get_capi_name())
+
+ # retrieve the existing static function implementations
+ existing = get_function_impls(impl, 'CEF_EXPORT')
+
+ # generate static functions
+ staticimpl = make_cpptoc_function_impl(cls,
+ cls.get_static_funcs(), existing, None,
+ defined_names, base_scoped)
+ if len(staticimpl) > 0:
+ staticimpl = '\n// GLOBAL FUNCTIONS - Body may be edited by hand.\n\n' + staticimpl
+
+ resultingimpl = staticimpl + virtualimpl
+
+ # any derived classes can be unwrapped
+ unwrapderived = make_cpptoc_unwrap_derived(header, cls, base_scoped)
+
+ const = '// CONSTRUCTOR - Do not edit by hand.\n\n'+ \
+ clsname+'CppToC::'+clsname+'CppToC() {\n'
+ const += make_cpptoc_virtual_function_assignment(header, cls, prefixname,
+ defined_names)
+ const += '}\n\n'+ \
+ '// DESTRUCTOR - Do not edit by hand.\n\n'+ \
+ clsname+'CppToC::~'+clsname+'CppToC() {\n'
+
+ if not cls.has_attrib('no_debugct_check') and not base_scoped:
+ const += ' shutdown_checker::AssertNotShutdown();\n'
+
+ const += '}\n\n'
+
+ # determine what includes are required by identifying what translation
+ # classes are being used
+ includes = format_translation_includes(header, const + resultingimpl +
+ (unwrapderived[0]
+ if base_scoped else unwrapderived))
+
+ # build the final output
+ result = get_copyright()
+
+ result += includes + '\n' + resultingimpl + '\n'
+
+ parent_sig = template_class + '<' + clsname + 'CppToC, ' + clsname + ', ' + capiname + '>'
+
+ if base_scoped:
+ const += 'template<> CefOwnPtr<'+clsname+'> '+parent_sig+'::UnwrapDerivedOwn(CefWrapperType type, '+capiname+'* s) {\n' + \
+ unwrapderived[0] + \
+ ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+ ' return CefOwnPtr<'+clsname+'>();\n'+ \
+ '}\n\n' + \
+ 'template<> CefRawPtr<'+clsname+'> '+parent_sig+'::UnwrapDerivedRaw(CefWrapperType type, '+capiname+'* s) {\n' + \
+ unwrapderived[1] + \
+ ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+ ' return nullptr;\n'+ \
+ '}\n\n'
+ else:
+ const += 'template<> CefRefPtr<'+clsname+'> '+parent_sig+'::UnwrapDerived(CefWrapperType type, '+capiname+'* s) {\n' + \
+ unwrapderived + \
+ ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \
+ ' return nullptr;\n'+ \
+ '}\n\n'
+
+ const += 'template<> CefWrapperType ' + parent_sig + '::kWrapperType = ' + get_wrapper_type_enum(
+ clsname) + ';'
+
+ result += '\n\n' + const
+
+ return result
+
+
+def make_cpptoc_global_impl(header, impl):
+ # structure names that have already been defined
+ defined_names = header.get_defined_structs()
+
+ # retrieve the existing global function implementations
+ existing = get_function_impls(impl, 'CEF_EXPORT')
+
+ # generate global functions
+ impl = make_cpptoc_function_impl(None,
+ header.get_funcs(), existing, None,
+ defined_names, False)
+ if len(impl) > 0:
+ impl = '\n// GLOBAL FUNCTIONS - Body may be edited by hand.\n\n' + impl
+
+ includes = ''
+
+ # include required headers for global functions
+ filenames = []
+ for func in header.get_funcs():
+ filename = func.get_file_name()
+ if not filename in filenames:
+ includes += '#include "include/'+func.get_file_name()+'"\n' \
+ '#include "include/capi/'+func.get_capi_file_name()+'"\n'
+ filenames.append(filename)
+
+ # determine what includes are required by identifying what translation
+ # classes are being used
+ includes += format_translation_includes(header, impl)
+
+ # build the final output
+ result = get_copyright()
+
+ result += includes + '\n' + impl
+
+ return result
+
+
+def write_cpptoc_impl(header, clsname, dir):
+ if clsname is None:
+ # global file
+ file = dir
+ else:
+ # class file
+ # give the output file the same directory offset as the input file
+ cls = header.get_class(clsname)
+ dir = os.path.dirname(os.path.join(dir, cls.get_file_name()))
+ file = os.path.join(dir, get_capi_name(clsname[3:], False) + '_cpptoc.cc')
+
+ if path_exists(file):
+ oldcontents = read_file(file)
+ else:
+ oldcontents = ''
+
+ if clsname is None:
+ newcontents = make_cpptoc_global_impl(header, oldcontents)
+ else:
+ newcontents = make_cpptoc_class_impl(header, clsname, oldcontents)
+ return (file, newcontents)
+
+
+# test the module
+if __name__ == "__main__":
+ import sys
+
+ # verify that the correct number of command-line arguments are provided
+ if len(sys.argv) < 4:
+ sys.stderr.write('Usage: ' + sys.argv[0] +
+ ' <infile> <classname> <existing_impl>')
+ sys.exit()
+
+ # create the header object
+ header = obj_header()
+ header.add_file(sys.argv[1])
+
+ # read the existing implementation file into memory
+ try:
+ with open(sys.argv[3], 'r') as f:
+ data = f.read()
+ except IOError as e:
+ (errno, strerror) = e.args
+ raise Exception('Failed to read file ' + sys.argv[3] + ': ' + strerror)
+ else:
+ f.close()
+
+ # dump the result to stdout
+ sys.stdout.write(make_cpptoc_class_impl(header, sys.argv[2], data))