| # 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_ctocpp_impl_proto(clsname, name, func, parts): |
| const = '' |
| |
| proto = 'NO_SANITIZE("cfi-icall") ' |
| if clsname is None: |
| proto += 'CEF_GLOBAL ' + parts['retval'] + ' ' |
| else: |
| proto += parts['retval'] + ' ' + clsname |
| if isinstance(func, obj_function_virtual): |
| proto += 'CToCpp' |
| if func.is_const(): |
| const = ' const' |
| |
| proto += '::' |
| |
| proto += name + '(' + ', '.join(parts['args']) + ')' + const |
| return proto |
| |
| |
| def make_ctocpp_function_impl_existing(clsname, name, func, impl): |
| notify(name + ' has manual edits') |
| |
| # retrieve the C++ prototype parts |
| parts = func.get_cpp_parts(True) |
| |
| changes = format_translation_changes(impl, parts) |
| if len(changes) > 0: |
| notify(name + ' prototype changed') |
| |
| return make_ctocpp_impl_proto(clsname, name, func, parts)+'{'+ \ |
| changes+impl['body']+'\n}\n\n' |
| |
| |
| def make_ctocpp_function_impl_new(clsname, name, func, base_scoped): |
| # Special handling for the CefShutdown global function. |
| is_cef_shutdown = name == 'CefShutdown' and isinstance( |
| func.parent, obj_header) |
| |
| # build the C++ prototype |
| parts = func.get_cpp_parts(True) |
| result = make_ctocpp_impl_proto(clsname, 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' |
| |
| if isinstance(func, obj_function_virtual): |
| # determine how the struct should be referenced |
| if clsname == func.parent.get_name(): |
| result += '\n ' + get_capi_name(clsname, |
| True) + '* _struct = GetStruct();' |
| else: |
| result += '\n '+func.parent.get_capi_name()+'* _struct = reinterpret_cast<'+\ |
| func.parent.get_capi_name()+'*>(GetStruct());' |
| |
| 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(False) |
| if len(retval_default) > 0: |
| retval_default = ' ' + retval_default |
| |
| # add API hash check |
| if func.has_attrib('api_hash_check'): |
| result += '\n const char* api_hash = cef_api_hash(0);'\ |
| '\n if (strcmp(api_hash, CEF_API_HASH_PLATFORM)) {'\ |
| '\n // The libcef API hash does not match the current header API hash.'\ |
| '\n NOTREACHED();'\ |
| '\n return'+retval_default+';'\ |
| '\n }\n' |
| |
| if isinstance(func, obj_function_virtual): |
| # add the structure size check |
| result += '\n if (CEF_MEMBER_MISSING(_struct, ' + func.get_capi_name( |
| ) + '))' |
| result += '\n return' + retval_default + ';\n' |
| |
| 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 |
| 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_byaddr' or arg_type == 'bool_byaddr': |
| result += comment+\ |
| '\n DCHECK('+arg_name+');'\ |
| '\n if (!'+arg_name+')'\ |
| '\n return'+retval_default+';' |
| elif arg_type == 'refptr_same' or arg_type == 'refptr_diff' or \ |
| arg_type == 'ownptr_same' or arg_type == 'ownptr_diff': |
| result += comment+\ |
| '\n DCHECK('+arg_name+'.get());'\ |
| '\n if (!'+arg_name+'.get())'\ |
| '\n return'+retval_default+';' |
| elif arg_type == 'rawptr_same' or arg_type == 'rawptr_diff': |
| result += comment+\ |
| '\n DCHECK('+arg_name+');'\ |
| '\n if (!'+arg_name+')'\ |
| '\n return'+retval_default+';' |
| elif arg_type == 'string_byref_const': |
| result += comment+\ |
| '\n DCHECK(!'+arg_name+'.empty());'\ |
| '\n if ('+arg_name+'.empty())'\ |
| '\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 = [] |
| if isinstance(func, obj_function_virtual): |
| params.append('_struct') |
| |
| 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' or \ |
| arg_type == 'bool_byval': |
| params.append(arg_name) |
| elif arg_type == 'simple_byref' or arg_type == 'simple_byref_const' or \ |
| arg_type == 'struct_byref_const' or arg_type == 'struct_byref': |
| params.append('&' + arg_name) |
| elif arg_type == 'bool_byref': |
| result += comment+\ |
| '\n int '+arg_name+'Int = '+arg_name+';' |
| params.append('&' + arg_name + 'Int') |
| elif arg_type == 'bool_byaddr': |
| result += comment+\ |
| '\n int '+arg_name+'Int = '+arg_name+'?*'+arg_name+':0;' |
| params.append('&' + arg_name + 'Int') |
| elif arg_type == 'string_byref_const': |
| params.append(arg_name + '.GetStruct()') |
| elif arg_type == 'string_byref': |
| params.append(arg_name + '.GetWritableStruct()') |
| elif arg_type == 'refptr_same': |
| ptr_class = arg.get_type().get_ptr_type() |
| params.append(ptr_class + 'CToCpp::Unwrap(' + arg_name + ')') |
| elif arg_type == 'ownptr_same': |
| ptr_class = arg.get_type().get_ptr_type() |
| params.append(ptr_class + 'CToCpp::UnwrapOwn(OWN_PASS(' + arg_name + '))') |
| elif arg_type == 'rawptr_same': |
| ptr_class = arg.get_type().get_ptr_type() |
| params.append(ptr_class + 'CToCpp::UnwrapRaw(' + arg_name + ')') |
| elif arg_type == 'refptr_diff': |
| ptr_class = arg.get_type().get_ptr_type() |
| params.append(ptr_class + 'CppToC::Wrap(' + arg_name + ')') |
| elif arg_type == 'ownptr_diff': |
| ptr_class = arg.get_type().get_ptr_type() |
| params.append(ptr_class + 'CppToC::WrapOwn(OWN_PASS(' + arg_name + '))') |
| elif arg_type == 'rawptr_diff': |
| ptr_class = arg.get_type().get_ptr_type() |
| result += comment+\ |
| '\n CefOwnPtr<'+ptr_class+'CppToC> '+arg_name+'Ptr('+ptr_class+'CppToC::WrapRaw('+arg_name+'));' |
| params.append(arg_name + 'Ptr->GetStruct()') |
| elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': |
| ptr_class = arg.get_type().get_ptr_type() |
| ptr_struct = arg.get_type().get_result_ptr_type_root() |
| if arg_type == 'refptr_same_byref': |
| assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + ')' |
| else: |
| assign = ptr_class + 'CppToC::Wrap(' + arg_name + ')' |
| result += comment+\ |
| '\n '+ptr_struct+'* '+arg_name+'Struct = NULL;'\ |
| '\n if ('+arg_name+'.get())'\ |
| '\n '+arg_name+'Struct = '+assign+';'\ |
| '\n '+ptr_struct+'* '+arg_name+'Orig = '+arg_name+'Struct;' |
| params.append('&' + arg_name + 'Struct') |
| elif arg_type == 'string_vec_byref' or arg_type == 'string_vec_byref_const': |
| result += comment+\ |
| '\n cef_string_list_t '+arg_name+'List = cef_string_list_alloc();'\ |
| '\n DCHECK('+arg_name+'List);'\ |
| '\n if ('+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 cef_string_map_t '+arg_name+'Map = cef_string_map_alloc();'\ |
| '\n DCHECK('+arg_name+'Map);'\ |
| '\n if ('+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 cef_string_multimap_t '+arg_name+'Multimap = cef_string_multimap_alloc();'\ |
| '\n DCHECK('+arg_name+'Multimap);'\ |
| '\n if ('+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': |
| count_func = arg.get_attrib_count_func() |
| vec_type = arg.get_type().get_result_vector_type_root() |
| if arg_type == 'refptr_vec_same_byref': |
| ptr_class = arg.get_type().get_ptr_type() |
| assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + '[i])' |
| elif arg_type == 'refptr_vec_diff_byref': |
| ptr_class = arg.get_type().get_ptr_type() |
| assign = ptr_class + 'CppToC::Wrap(' + arg_name + '[i])' |
| else: |
| assign = arg_name + '[i]' |
| result += comment+\ |
| '\n size_t '+arg_name+'Size = '+arg_name+'.size();'\ |
| '\n size_t '+arg_name+'Count = std::max('+count_func+'(), '+arg_name+'Size);'\ |
| '\n '+vec_type+'* '+arg_name+'List = NULL;'\ |
| '\n if ('+arg_name+'Count > 0) {'\ |
| '\n '+arg_name+'List = new '+vec_type+'['+arg_name+'Count];'\ |
| '\n DCHECK('+arg_name+'List);'\ |
| '\n if ('+arg_name+'List) {'\ |
| '\n memset('+arg_name+'List, 0, sizeof('+vec_type+')*'+arg_name+'Count);'\ |
| '\n }'\ |
| '\n if ('+arg_name+'List && '+arg_name+'Size > 0) {'\ |
| '\n for (size_t i = 0; i < '+arg_name+'Size; ++i) {'\ |
| '\n '+arg_name+'List[i] = '+assign+';'\ |
| '\n }'\ |
| '\n }'\ |
| '\n }' |
| params.append('&' + arg_name + 'Count') |
| 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': |
| count_func = arg.get_attrib_count_func() |
| vec_type = arg.get_type().get_result_vector_type_root() |
| if arg_type == 'simple_vec_byref_const' or arg_type == 'bool_vec_byref_const': |
| assign = arg_name + '[i]' |
| else: |
| ptr_class = arg.get_type().get_ptr_type() |
| if arg_type == 'refptr_vec_same_byref_const': |
| assign = ptr_class + 'CToCpp::Unwrap(' + arg_name + '[i])' |
| elif arg_type == 'refptr_vec_diff_byref_const': |
| assign = ptr_class + 'CppToC::Wrap(' + arg_name + '[i])' |
| elif arg_type == 'rawptr_vec_same_byref_const': |
| assign = ptr_class + 'CToCpp::UnwrapRaw(' + arg_name + '[i])' |
| elif arg_type == 'rawptr_vec_diff_byref_const': |
| assign = ptr_class + 'CppToC::WrapRaw(' + arg_name + '[i]).release()->GetStruct()' |
| result += comment+\ |
| '\n const size_t '+arg_name+'Count = '+arg_name+'.size();'\ |
| '\n '+vec_type+'* '+arg_name+'List = NULL;'\ |
| '\n if ('+arg_name+'Count > 0) {'\ |
| '\n '+arg_name+'List = new '+vec_type+'['+arg_name+'Count];'\ |
| '\n DCHECK('+arg_name+'List);'\ |
| '\n if ('+arg_name+'List) {'\ |
| '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ |
| '\n '+arg_name+'List[i] = '+assign+';'\ |
| '\n }'\ |
| '\n }'\ |
| '\n }' |
| params.append(arg_name + 'Count') |
| 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' or retval_type == 'bool': |
| result += retval.get_type().get_result_simple_type_root() |
| elif retval_type == 'string': |
| result += 'cef_string_userfree_t' |
| elif retval_type == 'refptr_same' or retval_type == 'refptr_diff' or \ |
| retval_type == 'ownptr_same' or retval_type == 'ownptr_diff': |
| ptr_struct = retval.get_type().get_result_ptr_type_root() |
| result += ptr_struct + '*' |
| else: |
| raise Exception('Unsupported return type %s in %s' % (retval_type, name)) |
| |
| result += ' _retval = ' |
| |
| if isinstance(func, obj_function_virtual): |
| result += '_struct->' |
| result += func.get_capi_name() + '(' |
| |
| if len(params) > 0: |
| if not isinstance(func, obj_function_virtual): |
| result += '\n ' |
| result += ',\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 == 'bool_byref': |
| result += comment+\ |
| '\n '+arg_name+' = '+arg_name+'Int?true:false;' |
| elif arg_type == 'bool_byaddr': |
| result += comment+\ |
| '\n if ('+arg_name+')'\ |
| '\n *'+arg_name+' = '+arg_name+'Int?true:false;' |
| elif arg_type == 'refptr_same_byref' or arg_type == 'refptr_diff_byref': |
| ptr_class = arg.get_type().get_ptr_type() |
| ptr_struct = arg.get_type().get_result_ptr_type_root() |
| if arg_type == 'refptr_same_byref': |
| assign = ptr_class + 'CToCpp::Wrap(' + arg_name + 'Struct)' |
| else: |
| assign = ptr_class + 'CppToC::Unwrap(' + arg_name + 'Struct)' |
| result += comment+\ |
| '\n if ('+arg_name+'Struct) {'\ |
| '\n if ('+arg_name+'Struct != '+arg_name+'Orig) {'\ |
| '\n '+arg_name+' = '+assign+';'\ |
| '\n }'\ |
| '\n } else {'\ |
| '\n '+arg_name+' = nullptr;'\ |
| '\n }' |
| elif arg_type == 'string_vec_byref': |
| result += comment+\ |
| '\n if ('+arg_name+'List) {'\ |
| '\n '+arg_name+'.clear();'\ |
| '\n transfer_string_list_contents('+arg_name+'List, '+arg_name+');'\ |
| '\n cef_string_list_free('+arg_name+'List);'\ |
| '\n }' |
| elif arg_type == 'string_vec_byref_const': |
| result += comment+\ |
| '\n if ('+arg_name+'List)'\ |
| '\n cef_string_list_free('+arg_name+'List);' |
| elif arg_type == 'string_map_single_byref': |
| result += comment+\ |
| '\n if ('+arg_name+'Map) {'\ |
| '\n '+arg_name+'.clear();'\ |
| '\n transfer_string_map_contents('+arg_name+'Map, '+arg_name+');'\ |
| '\n cef_string_map_free('+arg_name+'Map);'\ |
| '\n }' |
| elif arg_type == 'string_map_single_byref_const': |
| result += comment+\ |
| '\n if ('+arg_name+'Map)'\ |
| '\n cef_string_map_free('+arg_name+'Map);' |
| elif arg_type == 'string_map_multi_byref': |
| result += comment+\ |
| '\n if ('+arg_name+'Multimap) {'\ |
| '\n '+arg_name+'.clear();'\ |
| '\n transfer_string_multimap_contents('+arg_name+'Multimap, '+arg_name+');'\ |
| '\n cef_string_multimap_free('+arg_name+'Multimap);'\ |
| '\n }' |
| elif arg_type == 'string_map_multi_byref_const': |
| result += comment+\ |
| '\n if ('+arg_name+'Multimap)'\ |
| '\n cef_string_multimap_free('+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': |
| count_func = arg.get_attrib_count_func() |
| vec_type = arg.get_type().get_result_vector_type_root() |
| if arg_type == 'refptr_vec_same_byref': |
| ptr_class = arg.get_type().get_ptr_type() |
| assign = ptr_class + 'CToCpp::Wrap(' + arg_name + 'List[i])' |
| elif arg_type == 'refptr_vec_diff_byref': |
| ptr_class = arg.get_type().get_ptr_type() |
| assign = ptr_class + 'CppToC::Unwrap(' + arg_name + 'List[i])' |
| elif arg_type == 'bool_vec_byref': |
| assign = arg_name + 'List[i]?true:false' |
| else: |
| assign = arg_name + 'List[i]' |
| result += comment+\ |
| '\n '+arg_name+'.clear();'\ |
| '\n if ('+arg_name+'Count > 0 && '+arg_name+'List) {'\ |
| '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ |
| '\n '+arg_name+'.push_back('+assign+');'\ |
| '\n }'\ |
| '\n delete [] '+arg_name+'List;'\ |
| '\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 == 'rawptr_vec_same_byref_const' or arg_type == 'rawptr_vec_diff_byref_const': |
| result += comment |
| if arg_type == 'rawptr_vec_diff_byref_const': |
| result += '\n if ('+arg_name+'Count > 0) {'\ |
| '\n for (size_t i = 0; i < '+arg_name+'Count; ++i) {'\ |
| '\n delete '+ptr_class+'CppToC::GetWrapper('+arg_name+'List[i]);'\ |
| '\n }'\ |
| '\n }' |
| result += '\n if ('+arg_name+'List)'\ |
| '\n delete [] '+arg_name+'List;' |
| |
| 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': |
| result += '\n return _retval;' |
| elif retval_type == 'bool': |
| result += '\n return _retval?true:false;' |
| elif retval_type == 'string': |
| result += '\n CefString _retvalStr;'\ |
| '\n _retvalStr.AttachToUserFree(_retval);'\ |
| '\n return _retvalStr;' |
| elif retval_type == 'refptr_same' or retval_type == 'ownptr_same': |
| ptr_class = retval.get_type().get_ptr_type() |
| result += '\n return ' + ptr_class + 'CToCpp::Wrap(_retval);' |
| elif retval_type == 'refptr_diff': |
| ptr_class = retval.get_type().get_ptr_type() |
| result += '\n return ' + ptr_class + 'CppToC::Unwrap(_retval);' |
| elif retval_type == 'ownptr_diff': |
| ptr_class = retval.get_type().get_ptr_type() |
| result += '\n return ' + ptr_class + 'CppToC::UnwrapOwn(_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_ctocpp_function_impl(clsname, funcs, existing, base_scoped): |
| impl = '' |
| |
| for func in funcs: |
| name = func.get_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_ctocpp_function_impl_existing(clsname, name, func, value) |
| else: |
| impl += make_ctocpp_function_impl_new(clsname, name, func, base_scoped) |
| |
| return impl |
| |
| |
| def make_ctocpp_virtual_function_impl(header, cls, existing, base_scoped): |
| impl = make_ctocpp_function_impl(cls.get_name(), |
| cls.get_virtual_funcs(), existing, |
| base_scoped) |
| |
| 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) |
| if parent_cls is None: |
| raise Exception('Class does not exist: ' + parent_name) |
| impl += make_ctocpp_function_impl(cls.get_name(), |
| parent_cls.get_virtual_funcs(), |
| existing, base_scoped) |
| cur_cls = header.get_class(parent_name) |
| |
| return impl |
| |
| |
| def make_ctocpp_unwrap_derived(header, cls, base_scoped): |
| # identify all classes that derive from cls |
| derived_classes = [] |
| clsname = cls.get_name() |
| allclasses = header.get_classes() |
| for cur_cls in allclasses: |
| if cur_cls.get_name() == clsname: |
| continue |
| if cur_cls.has_parent(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 reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\ |
| clsname+'CToCpp::UnwrapOwn(CefOwnPtr<'+clsname+'>(reinterpret_cast<'+clsname+'*>(c.release()))));\n'+\ |
| ' }\n' |
| impl[1] += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\ |
| ' return reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\ |
| clsname+'CToCpp::UnwrapRaw(CefRawPtr<'+clsname+'>(reinterpret_cast<'+clsname+'*>(CEF_RAW_PTR_GET(c)))));\n'+\ |
| ' }\n' |
| else: |
| impl = '' |
| for clsname in derived_classes: |
| impl += ' if (type == '+get_wrapper_type_enum(clsname)+') {\n'+\ |
| ' return reinterpret_cast<'+get_capi_name(cls.get_name(), True)+'*>('+\ |
| clsname+'CToCpp::Unwrap(reinterpret_cast<'+clsname+'*>(c)));\n'+\ |
| ' }\n' |
| return impl |
| |
| |
| def make_ctocpp_class_impl(header, clsname, impl): |
| cls = header.get_class(clsname) |
| if cls is None: |
| raise Exception('Class does not exist: ' + clsname) |
| |
| capiname = cls.get_capi_name() |
| |
| # retrieve the existing virtual function implementations |
| existing = get_function_impls(impl, clsname + 'CToCpp::') |
| |
| base_class_name = header.get_base_class_name(clsname) |
| base_scoped = True if base_class_name == 'CefBaseScoped' else False |
| if base_scoped: |
| template_class = 'CefCToCppScoped' |
| else: |
| template_class = 'CefCToCppRefCounted' |
| |
| # generate virtual functions |
| virtualimpl = make_ctocpp_virtual_function_impl(header, cls, existing, |
| base_scoped) |
| if len(virtualimpl) > 0: |
| virtualimpl = '\n// VIRTUAL METHODS - Body may be edited by hand.\n\n' + virtualimpl |
| |
| # retrieve the existing static function implementations |
| existing = get_function_impls(impl, clsname + '::') |
| |
| # generate static functions |
| staticimpl = make_ctocpp_function_impl(clsname, |
| cls.get_static_funcs(), existing, |
| base_scoped) |
| if len(staticimpl) > 0: |
| staticimpl = '\n// STATIC METHODS - Body may be edited by hand.\n\n' + staticimpl |
| |
| resultingimpl = staticimpl + virtualimpl |
| |
| # any derived classes can be unwrapped |
| unwrapderived = make_ctocpp_unwrap_derived(header, cls, base_scoped) |
| |
| const = '// CONSTRUCTOR - Do not edit by hand.\n\n'+ \ |
| clsname+'CToCpp::'+clsname+'CToCpp() {\n'+ \ |
| '}\n\n'+ \ |
| '// DESTRUCTOR - Do not edit by hand.\n\n'+ \ |
| clsname+'CToCpp::~'+clsname+'CToCpp() {\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 + 'CToCpp, ' + clsname + ', ' + capiname + '>' |
| |
| if base_scoped: |
| const += 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerivedOwn(CefWrapperType type, CefOwnPtr<'+clsname+'> c) {\n'+ \ |
| unwrapderived[0] + \ |
| ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \ |
| ' return nullptr;\n'+ \ |
| '}\n\n' + \ |
| 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerivedRaw(CefWrapperType type, CefRawPtr<'+clsname+'> c) {\n'+ \ |
| unwrapderived[1] + \ |
| ' NOTREACHED() << "Unexpected class type: " << type;\n'+ \ |
| ' return nullptr;\n'+ \ |
| '}\n\n' |
| else: |
| const += 'template<> '+capiname+'* '+parent_sig+'::UnwrapDerived(CefWrapperType type, '+clsname+'* c) {\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 += const |
| |
| return result |
| |
| |
| def make_ctocpp_global_impl(header, impl): |
| # retrieve the existing global function implementations |
| existing = get_function_impls(impl, 'CEF_GLOBAL') |
| |
| # generate static functions |
| impl = make_ctocpp_function_impl(None, header.get_funcs(), existing, False) |
| if len(impl) > 0: |
| impl = '\n// GLOBAL METHODS - 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// Define used to facilitate parsing.\n#define CEF_GLOBAL\n\n' + impl |
| |
| return result |
| |
| |
| def write_ctocpp_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) + '_ctocpp.cc') |
| |
| if path_exists(file): |
| oldcontents = read_file(file) |
| else: |
| oldcontents = '' |
| |
| if clsname is None: |
| newcontents = make_ctocpp_global_impl(header, oldcontents) |
| else: |
| newcontents = make_ctocpp_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>\n') |
| 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) |
| |
| # dump the result to stdout |
| sys.stdout.write(make_ctocpp_class_impl(header, sys.argv[2], data)) |