| # 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) |
| |
| 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) |
| 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+';' |
| |
| 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+';' |
| 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+';' |
| 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+';' |
| |
| # 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+';' |
| |
| 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);' |
| 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+');' |
| 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('OWN_PASS(' + 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 '+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;' |
| elif arg_type == 'bool_byref' or arg_type == 'bool_byaddr': |
| result += comment+\ |
| '\n if ('+arg_name+')'\ |
| '\n *'+arg_name+' = '+arg_name+'Bool?true:false;' |
| elif arg_type == 'struct_byref': |
| result += comment+\ |
| '\n if ('+arg_name+')'\ |
| '\n '+arg_name+'Obj.DetachTo(*'+arg_name+');' |
| 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(OWN_PASS(_retval));' |
| elif retval_type == 'ownptr_diff': |
| ptr_class = retval.get_type().get_ptr_type() |
| result += '\n return ' + ptr_class + 'CToCpp::UnwrapOwn(OWN_PASS(_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 OWN_RETURN_AS('+clsname+'CppToC::UnwrapOwn(reinterpret_cast<'+\ |
| get_capi_name(clsname, True)+'*>(s)), '+cur_clsname+');\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)) |