• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15const { replaceAll, getPrefix, getConstNum } = require('../tools/tool');
16const { paramGenerate } = require('./param_generate');
17const { returnGenerate } = require('./return_generate');
18const { jsonCfgList, InterfaceList } = require('../tools/common');
19
20/**
21 * 结果异步返回Async|Promise
22 */
23let funcAsyncMiddleHTemplete = `
24struct [funcName]_value_struct {[valueIn]
25    uint32_t outErrCode = 0;[valueOut]
26};
27
28[static_define]void [funcName]_execute(XNapiTool *pxt, DataPtr data);
29[static_define]void [funcName]_complete(XNapiTool *pxt, DataPtr data);
30[static_define]napi_value [funcName]_middle(napi_env env, napi_callback_info info);
31`;
32
33let funcAsyncTemplete = `
34void [middleClassName][funcName]_execute(XNapiTool *pxt, DataPtr data)
35{
36    void *data_ptr = data;
37    [funcName]_value_struct *vio = static_cast<[funcName]_value_struct *>(data_ptr);
38    [checkout_async_instance]
39    [callFunc]
40}
41
42void [middleClassName][funcName]_complete(XNapiTool *pxt, DataPtr data)
43{
44    void *data_ptr = data;
45    [funcName]_value_struct *vio = static_cast<[funcName]_value_struct *>(data_ptr);
46    napi_value result = nullptr;
47    [valuePackage]
48    napi_value errCodeResult = nullptr;
49    napi_value napiErrCode = nullptr;
50    napiErrCode = NUMBER_C_2_JS(pxt, vio->outErrCode);
51    pxt->SetValueProperty(errCodeResult, "code", napiErrCode);
52    {
53        napi_value args[XNapiTool::TWO] = {errCodeResult, result};
54        pxt->FinishAsync(XNapiTool::TWO, args);
55    }
56    [optionalParamDestory]
57    delete vio;
58}
59
60napi_value [middleClassName][funcName]_middle(napi_env env, napi_callback_info info)
61{
62    XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release();
63    if (pxt->IsFailed()) {
64        napi_value err = pxt->GetError();
65        delete pxt;
66        return err;
67    }
68    [unwarp_instance]
69    struct [funcName]_value_struct *vio = new [funcName]_value_struct();
70    [valueCheckout][optionalCallbackInit][start_async]
71    return result;
72}`;
73
74let cppTemplate = `
75bool %s%s(%s)
76{
77    %s[replace_valueOut]
78    return true;
79}
80`;
81
82let cppCbResultTemplate = `
83[replace_outDefine]
84void %s%sSetCbValue(%s)
85{
86  %s
87  return;
88}
89`;
90
91function removeEndlineEnter(value) {
92    for (let i = value.length; i > 0; i--) {
93        let len = value.length;
94        if (value.substring(len - 1, len) === '\n' || value.substring(len - 1, len) === ' ') {
95            value = value.substring(0, len - 1);
96        } else {
97            value = '    ' + value + '\n';
98            break;
99        }
100    }
101    return value;
102}
103
104function getOptionalCallbackInit(param) {
105    if (!param.callback.optional) {
106        return '';
107    }
108    let cType = param.valueOut.substr(0, param.valueOut.indexOf('*'));
109    return 'vio->out = new %s;'.format(cType);
110}
111
112function replaceBasicInfo(middleFunc, middleH, className) {
113    if (className === null || className === undefined) {
114        middleH = middleH.replaceAll('[static_define]', '');
115        middleFunc = middleFunc.replaceAll('[unwarp_instance]', '');
116        middleFunc = middleFunc.replaceAll('[checkout_async_instance]', '');
117        middleFunc = middleFunc.replaceAll('[middleClassName]', '');
118    }
119    else {
120        middleH = middleH.replaceAll('[static_define]', 'static ');
121        middleFunc = middleFunc.replaceAll('[unwarp_instance]',
122            `pxt->SetAsyncInstance(pxt->UnWarpInstance());`);
123        middleFunc = middleFunc.replaceAll('[checkout_async_instance]',
124            '%s *pInstance = (%s *)pxt->GetAsyncInstance();'.format(className, className));
125        middleFunc = middleFunc.replaceAll('[middleClassName]', className + '_middle' + '::');
126    }
127    return [middleFunc, middleH];
128}
129function generateFunctionAsync(func, data, className, implHCbVariable) {
130    let middleFunc = replaceAll(funcAsyncTemplete, '[funcName]', func.name);
131    let middleH = '';
132    if (func.name !== 'constructor') {
133        middleH = replaceAll(funcAsyncMiddleHTemplete, '[funcName]', func.name);
134    }
135    let basicInfoRes = replaceBasicInfo(middleFunc, middleH, className);
136    middleFunc = basicInfoRes[0];
137    middleH = basicInfoRes[1];
138
139    // 定义输入,定义输出,解析,填充到函数内,输出参数打包,impl参数定义,可选参数内存释放
140    let param = {
141        valueIn: '', valueOut: '', valueCheckout: '', valueFill: '',
142        valuePackage: '', valueDefine: '', optionalParamDestory: ''
143    };
144
145    for (let i in func.value) {
146        paramGenerate(i, func.value[i], param, data);
147    }
148    returnGenerate(param.callback, param, data);
149    middleH = replaceValueOut(middleH, param);
150
151    middleFunc = getMiddleFunc(param, middleFunc);
152    middleFunc = replaceAll(middleFunc, '[start_async]', `
153    napi_value result = pxt->StartAsync(%s_execute, reinterpret_cast<DataPtr>(vio), %s_complete,
154    pxt->GetArgc() == %s? pxt->GetArgv(%d) : nullptr);`
155        .format(func.name, func.name, getConstNum(parseInt(param.callback.offset) + 1),
156            getConstNum(param.callback.offset))); // 注册异步调用
157    let callFunc = '%s%s(%s);'.format((className === null || className === undefined) ?
158        '' : 'pInstance->', func.name, param.valueFill);
159    middleFunc = replaceAll(middleFunc, '[callFunc]', callFunc); // 执行
160    middleFunc = replaceAll(middleFunc, '[valuePackage]', param.valuePackage); // 输出参数打包
161    middleFunc = replaceAll(middleFunc, '[optionalParamDestory]', param.optionalParamDestory); // 可选参数内存释放
162
163    let prefixArr = getPrefix(data, func);
164    let implH = '';
165    let implCpp = '';
166    if (!func.isParentMember) {
167        // 只有类/接口自己的成员方法需要在.h.cpp中生成,父类/父接口不需要
168        implH = '\n%s%s%sbool %s(%s)%s;'.format(
169            prefixArr[0], prefixArr[1], prefixArr[2], func.name, param.valueDefine, prefixArr[3]);
170        let callStatement = jsonCfgList.getValue((className === null || className === undefined) ? '' : className,
171            func.name);
172        implCpp = cppTemplate.format((className === null || className === undefined) ? '' : className + '::',
173            func.name, param.valueDefine,
174            (callStatement === null || callStatement === undefined) ? '' : callStatement);
175
176        let outResult = generateCbInterfaceOutFunc(param, className, prefixArr, implHCbVariable, implCpp, implH);
177        implCpp = outResult[0];
178        implH = outResult[1];
179    }
180    return [middleFunc, implH, implCpp, middleH];
181}
182
183function getMiddleFunc(param, middleFunc) {
184    if (param.valueCheckout === '') {
185        middleFunc = replaceAll(middleFunc, '[valueCheckout]', param.valueCheckout); // # 输入参数解析
186    } else {
187        param.valueCheckout = removeEndlineEnter(param.valueCheckout);
188        middleFunc = replaceAll(middleFunc, '[valueCheckout]', param.valueCheckout); // # 输入参数解析
189    }
190    let optionalCallback = getOptionalCallbackInit(param);
191    if (optionalCallback === '') {
192        middleFunc = replaceAll(middleFunc, '[optionalCallbackInit]', optionalCallback); // 可选callback参数初始化
193    } else {
194        middleFunc = replaceAll(middleFunc, '[optionalCallbackInit]', optionalCallback + '\n    '); // 可选callback参数初始化
195    }
196    return middleFunc;
197}
198
199function generateCbInterfaceOutFunc(param, className, prefixArr, implHCbVariable, implCpp, implH) {
200    let cbInterfaceRes = '';
201    let outInterfaceDefine = param.valueDefine.substring(param.valueDefine.lastIndexOf(',') + 1,
202        param.valueDefine.length);
203    outInterfaceDefine = replaceAll(outInterfaceDefine, ' ', '');
204    let index = outInterfaceDefine.indexOf('&');
205    let outInterfaceName = outInterfaceDefine.substring(0, index);
206    if (InterfaceList.getValue(outInterfaceName)) {
207        let defineParams = '';
208        let useParams = '';
209        let interBody = InterfaceList.getValue(outInterfaceName);
210        for (let i = 0; i < interBody.length; i++) {
211            let realType = interBody[i].type === 'string' ? 'std::string' : interBody[i].type;
212            realType = interBody[i].type === 'boolean' ? 'bool' : realType;
213            defineParams += '%s %s, '.format(realType, interBody[i].name);
214            useParams += '%s%sOutRes.%s = %s;\n'.format((className === null || className === undefined) ? '' : className +
215                '::', outInterfaceName.toLocaleLowerCase(), interBody[i].name, interBody[i].name);
216        }
217        defineParams = defineParams.substring(0, defineParams.length - 2);
218        let cbOutDefine = '\n%s %s%sOutRes = {};'.format(outInterfaceName, (className === null || className === undefined) ?
219            '' : className + '::',
220            outInterfaceName.toLocaleLowerCase());
221        cbInterfaceRes = cppCbResultTemplate.format((className === null || className === undefined) ?
222            '' : className + '::', outInterfaceName.toLocaleLowerCase(),
223            defineParams, useParams);
224        if (className !== null && className !== undefined) {
225            cbInterfaceRes = replaceAll(cbInterfaceRes, '[replace_outDefine]', cbOutDefine);
226        } else {
227            cbInterfaceRes = replaceAll(cbInterfaceRes, '[replace_outDefine]', '');
228        }
229
230        // 多次使用interface(非匿名)作为Promise回调只需生成一次cbResult接口
231        let outResDefine = '\n%s%s%sstatic %s %sOutRes;'.format(
232            prefixArr[0], prefixArr[1], prefixArr[2], outInterfaceName, outInterfaceName.toLocaleLowerCase());
233        let replaceOut = '\n    out = %s%sOutRes;'.format((className === null || className === undefined) ?
234            '' : className + '::',
235            outInterfaceName.toLocaleLowerCase());
236        implCpp = replaceAll(implCpp, '[replace_valueOut]', replaceOut);
237        if (implHCbVariable.indexOf(outResDefine) < 0) {
238            implH += outResDefine;
239            implH += '\n%s%s%svoid %sSetCbValue(%s);'.format(
240                prefixArr[0], prefixArr[1], prefixArr[2], outInterfaceName.toLocaleLowerCase(), defineParams);
241            implCpp += cbInterfaceRes;
242        }
243    } else {
244        implCpp = replaceAll(implCpp, '[replace_valueOut]', '');
245    }
246    return [implCpp, implH];
247}
248
249function replaceValueOut(middleH, param) {
250    middleH = replaceAll(middleH, '[valueIn]', param.valueIn); // # 输入参数定义
251    if (param.valueOut === '') {
252        middleH = replaceAll(middleH, '[valueOut]', param.valueOut); // # 输出参数定义
253    } else {
254        middleH = replaceAll(middleH, '[valueOut]', '\n    ' + param.valueOut); // # 输出参数定义
255    }
256    return middleH;
257}
258
259module.exports = {
260    generateFunctionAsync
261};