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 base64
21import hashlib
22import file_parser
23import system_util
24
25
26# pylint:disable=huawei-redefined-outer-name
27
28# ------------------------------------------------------------------------------------------------------#
29
30
31def get_copyright():
32    content = \
33        """/*
34         * Copyright (c) $YEAR$ Huawei Device Co., Ltd.
35         * Licensed under the Apache License, Version 2.0 (the "License");
36         * you may not use this file except in compliance with the License.
37         * You may obtain a copy of the License at
38         *
39         *     http://www.apache.org/licenses/LICENSE-2.0
40         *
41         * Unless required by applicable law or agreed to in writing, software
42         * distributed under the License is distributed on an "AS IS" BASIS,
43         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44         * See the License for the specific language governing permissions and
45         * limitations under the License.
46         */
47        """
48
49    # add the copyright year
50    return content.replace('$YEAR$', system_util.get_year())
51
52
53# ------------------------------------------------------------------------------------------------------#
54
55
56def make_def_file(cls, class_name):
57    directory = cls.get_file_directory()
58
59    def_name = ''
60    if not directory is None:
61        def_name += directory + '_'
62
63    def_name += file_parser.get_capi_name(class_name, False)
64    return def_name
65
66
67# ------------------------------------------------------------------------------------------------------#
68
69
70def get_base_name(ident, header, class_name):
71    base_name = header.get_base_class_name(class_name)
72    if base_name == 'ArkWebBaseScoped':
73        base_name = 'ArkWeb' + ident + 'Scoped'
74    else:
75        base_name = 'ArkWeb' + ident + 'RefCounted'
76    return base_name
77
78
79# ------------------------------------------------------------------------------------------------------#
80
81
82def make_include_file(cls, ident, header, dir_name, class_name):
83    # include the headers for this class
84    capi_path = os.path.join(dir_name, 'capi', cls.get_capi_file_name())
85    include_path = os.path.join(dir_name, 'include', cls.get_file_name())
86    content = '#include "' + capi_path + '"\n' + \
87              '#include "' + include_path + '"\n'
88
89    base_name = header.get_base_class_name(class_name)
90    if base_name == 'ArkWebBaseScoped':
91        base_file = ident.lower() + '_scoped.h'
92    else:
93        base_file = ident.lower() + '_ref_counted.h'
94
95    base_path = os.path.join('base', ident.lower(), 'ark_web_' + base_file)
96    content += '#include "' + base_path + '"\n'
97    return {'content': content, 'base_name': get_base_name(ident, header, class_name)}
98
99
100# ------------------------------------------------------------------------------------------------------#
101
102
103def make_class_define(cls, ident, base_class, class_name, funcs_body):
104    capi_name = cls.get_capi_name()
105    content = 'class ' + class_name + ident + '\n' + \
106              '    : public ' + base_class + '<' + class_name + ident + ', ' + class_name + ', ' + capi_name + '> {\n' + \
107              '  public:\n' + \
108              '    ' + class_name + ident + '();\n' + \
109              '    virtual ~' + class_name + ident + '();\n\n'
110
111    if len(funcs_body) != 0:
112        content += funcs_body
113    content += '};\n'
114    return content
115
116
117# ------------------------------------------------------------------------------------------------------#
118
119
120def make_wrapper_type(cls, ident):
121    clsname = cls.get_name()
122    content = 'template<>\n' + \
123              'ArkWebBridgeType ArkWeb' + ident + 'RefCounted<' + clsname + ident + ', ' + clsname + ', ' + \
124              cls.get_capi_name() + '>\n::kBridgeType = ' + file_parser.get_wrapper_type_enum(clsname) + ';'
125    return content
126
127
128# ------------------------------------------------------------------------------------------------------#
129
130
131def get_derived_classes(cls, header):
132    # identify all classes that derive form class
133    derived_classes = []
134    class_name = cls.get_name()
135    all_classes = header.get_classes()
136    for cur_cls in all_classes:
137        if cur_cls.get_name() == class_name:
138            continue
139        if cur_cls.has_parent(class_name):
140            derived_classes.append(cur_cls.get_name())
141
142    derived_classes = sorted(derived_classes)
143    return derived_classes
144
145
146# ------------------------------------------------------------------------------------------------------#
147
148
149def get_func_hash_name(func, prefix):
150    args = func.get_arguments()
151    func_digest = prefix + '_' + func.get_capi_name() + ','.join(arg.get_raw_type() for arg in args)
152    return base64.b64encode(hashlib.md5(func_digest.encode()).digest(), altchars=b'$_').decode().rstrip('=')
153
154
155# ------------------------------------------------------------------------------------------------------#
156
157
158def get_func_name_list(funcs):
159    name_list = []
160    for func in funcs:
161        name_list.append(func.get_capi_name())
162    return name_list
163
164
165# ------------------------------------------------------------------------------------------------------#
166
167
168def get_func_name_count(name, old_list, new_list):
169    if old_list.count(name) != 1:
170        new_list.append(name)
171    return new_list
172
173
174# ------------------------------------------------------------------------------------------------------#
175
176
177def get_class_func_list(cls, header):
178    func_list = []
179    parent_cls = cls
180    while True:
181        func_list.extend(parent_cls.get_virtual_funcs())
182
183        parent_clsname = parent_cls.get_parent_name()
184        if file_parser.is_base_class(parent_clsname):
185            break
186
187        parent_cls = header.get_class(parent_clsname)
188        if parent_cls is None:
189            raise Exception('Class does not exist: ' + parent_clsname)
190    return func_list
191
192
193# ------------------------------------------------------------------------------------------------------#
194
195
196def get_func_pointer_name(cls, func, prefix, suffix):
197    if len(prefix) == 0:
198        func_name = func.get_capi_name() + suffix
199    else:
200        func_name = prefix + '_' + func.get_capi_name() + suffix
201    func_type = cls.get_name() + func.get_name() + 'Func' + suffix
202    return func_name, func_type
203
204
205# ------------------------------------------------------------------------------------------------------#
206
207
208def get_func_variable_name(func, suffix):
209    if file_parser.check_func_name_is_key_work(func.get_capi_name()):
210        if len(suffix) == 0:
211            var_name = func.get_capi_name() + '0'
212        else:
213            var_name = func.get_capi_name() + suffix
214    else:
215        var_name = func.get_capi_name() + suffix
216    return var_name
217
218
219# ------------------------------------------------------------------------------------------------------#
220
221
222def get_func_invalid_info(name, func):
223    invalid = []
224    args = func.get_arguments()
225    for arg in args:
226        if arg.get_arg_type() == 'invalid':
227            invalid.append(arg.get_name())
228
229    retval = func.get_retval()
230    retval_type = retval.get_retval_type()
231    if retval_type == 'invalid':
232        invalid.append('(return value)')
233
234    if len(invalid) == 0:
235        return ''
236
237    file_parser.notify(name + ' could not be autogenerated')
238    # code could not be auto-generated
239    result = '\n  // BEGIN DELETE BEFORE MODIFYING'
240    result += '\n  // COULD NOT IMPLEMENT DUE TO: ' + ', '.join(invalid)
241    result += '\n  #pragma message("Warning: " __FILE__ ": ' + name + ' is not implemented")'
242    result += '\n  // END DELETE BEFORE MODIFYING'
243    result += '\n}\n\n'
244    return result
245