1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2024 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from __future__ import absolute_import 18 19import os 20import file_parser 21import make_file_base 22 23# pylint:disable=huawei-redefined-outer-name 24 25# ------------------------------------------------------------------------------------------------------# 26 27def make_capi_static_funcs(funcs, indent, defined_names, translate_map): 28 new_list = [] 29 old_list = make_file_base.get_func_name_list(funcs) 30 31 result = '' 32 for func in funcs: 33 if func.get_retval().get_type().is_result_string(): 34 result += indent + '// The resulting string must be freed by calling cef_string_userfree_free().\n' 35 36 suffix = '' 37 new_list = make_file_base.get_func_name_count(func.get_capi_name(), old_list, new_list) 38 if new_list.count(func.get_capi_name()) != 0: 39 suffix = str(new_list.count(func.get_capi_name())) 40 41 result += '\n' + indent + 'ARK_WEB_EXPORT ' + func.get_capi_proto(defined_names, suffix) + ';\n' 42 43 return result 44 45# ------------------------------------------------------------------------------------------------------# 46 47def make_capi_class_funcs(funcs, indent, defined_names, translate_map): 48 new_list = [] 49 old_list = make_file_base.get_func_name_list(funcs) 50 51 result = '' 52 for func in funcs: 53 result += '\n' 54 if func.get_retval().get_type().is_result_string(): 55 result += indent + '// The resulting string must be freed by calling cef_string_userfree_free().\n' 56 57 suffix = '' 58 new_list = make_file_base.get_func_name_count(func.get_capi_name(), old_list, new_list) 59 if new_list.count(func.get_capi_name()) != 0: 60 suffix = str(new_list.count(func.get_capi_name())) 61 elif file_parser.check_func_name_is_key_work(func.get_capi_name()): 62 suffix = '0' 63 64 parts = func.get_capi_parts() 65 result += indent+parts['retval']+' (ARK_WEB_CALLBACK *'+parts['name'] + suffix + \ 66 ')('+', '.join(parts['args'])+');\n' 67 68 return result 69 70# ------------------------------------------------------------------------------------------------------# 71 72def make_capi_include_file(clses, header, file_name, all_declares): 73 result = '' 74 75 # identify all includes and forward declarations 76 internal_includes = set([]) 77 translated_includes = set([]) 78 for cls in clses: 79 includes = cls.get_includes() 80 for include in includes: 81 translated_includes.add(include) 82 83 declares = cls.get_forward_declares() 84 for declare in declares: 85 declare_cls = header.get_class(declare) 86 if declare_cls is None: 87 raise Exception('Unknown class: %s' % declare) 88 89 all_declares.add(declare_cls.get_capi_name()) 90 91 # output translated includes 92 flag = True 93 if len(translated_includes) > 0: 94 sorted_includes = sorted(translated_includes) 95 for include in sorted_includes: 96 if include == 'base/include/ark_web_base_ref_counted' and flag: 97 flag = False 98 result += '#include "base/capi/ark_web_base_ref_counted_capi.h"\n' 99 elif include == 'base/include/ark_web_types' or include == 'ohos_nweb/include/ark_web_value' \ 100 or include == 'ohos_nweb/include/ark_web_message' or include == 'ohos_nweb/include/ark_web_nweb_structs' \ 101 or include == 'ohos_adapter/include/ark_web_adapter_structs' or include.endswith('_vector'): 102 result += '#include "' + include + '.h"\n' 103 else: 104 if include.startswith('ohos_nweb/include/') and flag: 105 flag = False 106 result += '#include "base/capi/ark_web_base_ref_counted_capi.h"\n' 107 result += '#include "' + include.replace('/include/', '/capi/') + '_capi.h"\n' 108 else: 109 result += '#include "base/capi/ark_web_base_ref_counted_capi.h"\n' 110 111 # output internal includes 112 if len(internal_includes) > 0: 113 sorted_includes = sorted(internal_includes) 114 for include in sorted_includes: 115 result += '#include "include/' + include + '.h"\n' 116 117 return result 118 119# ------------------------------------------------------------------------------------------------------# 120 121def make_capi_class_body(clses, header, file_name, all_declares): 122 result = '' 123 124 # output forward declarations 125 if len(all_declares) > 0: 126 sorted_declares = sorted(all_declares) 127 for declare in sorted_declares: 128 result += '\n' + \ 129 'typedef struct _' + declare + ' ' + declare + ';\n' 130 131 # structure names that have already been defined 132 defined_names = header.get_defined_structs() 133 134 # map of strings that will be changed in C++ comments 135 translate_map = header.get_capi_translations() 136 137 # output classes 138 for cls in clses: 139 # virtual functions are inside the structure 140 capi_name = cls.get_capi_name() 141 result += '\n' + \ 142 'typedef struct _' + capi_name + ' {\n' + \ 143 ' /**\n' + \ 144 ' * @brief Base structure.\n' + \ 145 ' */\n' + \ 146 ' ' + cls.get_parent_capi_name() + ' base;\n' 147 funcs = cls.get_virtual_funcs() 148 result += make_capi_class_funcs(funcs, ' ', defined_names, translate_map) 149 result += '} ' + capi_name + ';\n' 150 151 defined_names.append(capi_name) 152 153 # static functions become global 154 funcs = cls.get_static_funcs() 155 if len(funcs) > 0: 156 result += make_capi_static_funcs(funcs, '', defined_names, translate_map) 157 158 # output global functions 159 funcs = header.get_funcs(file_name) 160 if len(funcs) > 0: 161 result += make_capi_static_funcs(funcs, '', defined_names, translate_map) + '\n' 162 163 return result 164 165# ------------------------------------------------------------------------------------------------------# 166 167def make_capi_header_file(header, dir_path, dir_name, file_name): 168 # header string 169 content = make_file_base.get_copyright() 170 171 content += \ 172""" 173#ifndef $GUARD$ 174#define $GUARD$ 175#pragma once 176""" 177 content += '\n' 178 179 clses = header.get_classes(file_name) 180 181 all_declares = set([]) 182 content += make_capi_include_file(clses, header, file_name, all_declares) 183 184 content += \ 185""" 186#ifdef __cplusplus 187extern "C" { 188#endif 189""" 190 191 content += make_capi_class_body(clses, header, file_name, all_declares) 192 193 # footer string 194 content += \ 195""" 196#ifdef __cplusplus 197} 198#endif 199 200#endif // $GUARD$ 201""" 202 203 # add the guard string 204 guard = file_name.replace('/', '_').replace('.', '_capi_').upper() + '_' 205 content = content.replace('$GUARD$', guard) 206 207 absolute_dir = os.path.join(os.path.join(dir_path, dir_name), 'capi') 208 absolute_path = os.path.join(absolute_dir, file_name.replace('.', '_capi.')) 209 210 return (content, absolute_path) 211 212