• 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 } = require("../tools/tool");
16const { eventParamGenerate } = require("./param_generate");
17const { returnGenerate } = require("./return_generate");
18const { cToJs } = require("./return_generate");
19
20/**
21 * on和off接口生成模板
22 */
23let funcOnOffTemplete = `
24struct [funcName]_value_struct {
25    std::string eventName;
26};
27
28[static_define]napi_value [funcName]_middle(napi_env env, napi_callback_info info)
29{
30    XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release();
31    if (pxt->IsFailed()) {
32        napi_value err = pxt->GetError();
33        delete pxt;
34        return err;
35    }
36    [unwarp_instance]
37
38    struct [funcName]_value_struct *vio = new [funcName]_value_struct();
39    pxt->SwapJs2CUtf8(pxt->GetArgv(0), vio->eventName);
40
41    [handleRegist]
42
43    [instance][funcName](vio->eventName);
44
45    napi_value result = pxt->UndefinedValue();
46
47    delete vio;
48    if (pxt->IsFailed()) {
49        result = pxt->GetError();
50    }
51    delete pxt; // release
52    return result;
53}
54`
55
56let middleAsyncCallbackTemplate = `
57void AsyncCallback(const std::string &eventName, [callback_param_type] &ret)
58{
59	if(XNapiTool::asyncFuncs_.count(eventName) <= 0) {
60        return;
61    }
62	AsyncFunc * pAsyncFuncs = &XNapiTool::asyncFuncs_[eventName];
63	napi_value exports = nullptr;
64	XNapiTool *pxt = std::make_unique<XNapiTool>(pAsyncFuncs->env_, exports).release();
65    [native_return]
66
67	XNapiTool::CallAsyncFunc(pAsyncFuncs, napiRet);
68	delete pxt;
69}
70`
71
72let middleEventCallbakTemplate = `
73void [eventName]Callback([callback_param_type] &ret) {
74	AsyncCallback("[eventName]", ret);
75}
76`
77let implHEventCallbakTemplate = `
78void [eventName]Callback([callback_param_type] &ret);
79`
80
81function isOnTypeExist(onTypeList, newType) {
82    if (!onTypeList) {
83        return false
84    }
85
86    for (var i in onTypeList) {
87        if (onTypeList[i] == newType) {
88            return true
89        }
90    }
91    return false
92}
93
94function addOnTypeToList(data, newType) {
95    if (!data.onTypeList) {
96        data.onTypeList = []
97    }
98
99    data.onTypeList.push(newType)
100}
101
102function isOnOffFuncExist(data, funcName) {
103    return data.onOffList && data.onOffList.indexOf(funcName) > -1
104}
105
106function addOnOffFunc(data, funcName) {
107    if (!data.onOffList) {
108        data.onOffList = []
109    }
110    data.onOffList.push(funcName)
111}
112
113function gennerateOnOffContext(codeContext, func, data, className, param) {
114    codeContext.middleFunc = replaceAll(funcOnOffTemplete, "[funcName]", func.name)
115    if (className == null) {
116        codeContext.middleFunc = codeContext.middleFunc.replaceAll("[static_define]", "")
117        codeContext.middleFunc = codeContext.middleFunc.replaceAll("[unwarp_instance]", "")
118    }
119    else {
120        codeContext.middleFunc = codeContext.middleFunc.replaceAll("[static_define]", "static ")
121        codeContext.middleFunc = codeContext.middleFunc.replaceAll("[unwarp_instance]",
122            "%s *pInstance = (%s *)pxt->UnWarpInstance();".format(className, className))
123    }
124    let instancePtr = "%s".format(className == null ? "" : "pInstance->")
125    codeContext.middleFunc = replaceAll(codeContext.middleFunc, "[instance]", instancePtr)//执行
126
127    let registLine = func.name == 'on' ? "pxt->RegistAsyncFunc(vio->eventName, pxt->GetArgv(1));"
128        : "pxt->UnregistAsyncFunc(vio->eventName);"
129        codeContext.middleFunc = replaceAll(codeContext.middleFunc, "[handleRegist]", registLine)//注册/去注册event
130
131        codeContext.implH += "\nbool %s(%s);".format(func.name, param.valueDefine)
132        codeContext.implCpp += `
133bool %s%s(%s)
134{
135return true;
136}
137`.format(className == null ? "" : className + "::", func.name, param.valueDefine)
138
139    addOnOffFunc(data, func.name)
140}
141
142function gennerateEventCallback(codeContext, data, param) {
143    returnGenerate(param.callback, param)
144    let paramType = param.valueOut.substring(0, param.valueOut.length - "out;".length)
145    let realParamType = paramType.substring(0, 12) == "NUMBER_TYPE_" ? "uint32_t" : paramType
146    if (!isOnTypeExist(data.onTypeList, realParamType)) {
147        // 为每种callback参数类型的on方法生成一个统一回调方法
148        let nativeReturn = cToJs("ret", param.callback.type, "napi_value napiRet")
149        let callbackFunc = replaceAll(middleAsyncCallbackTemplate, "[callback_param_type]", realParamType)
150        callbackFunc = replaceAll(callbackFunc, "[native_return]", nativeReturn)
151        codeContext.middleFunc += callbackFunc
152        addOnTypeToList(data, realParamType)
153    }
154
155    // 为每个on的event事件生成回调方法
156    let middleEventCallBack = replaceAll(middleEventCallbakTemplate, "[eventName]", param.eventName)
157    middleEventCallBack = replaceAll(middleEventCallBack, "[callback_param_type]", realParamType)
158    codeContext.middleFunc += middleEventCallBack;
159
160    // 为每个on的event事件生成回调接口供用户侧使用
161    let implHCallBack = replaceAll(implHEventCallbakTemplate, "[eventName]", param.eventName)
162    implHCallBack = replaceAll(implHCallBack, "[callback_param_type]", paramType)
163    codeContext.implH += implHCallBack
164}
165
166function generateFunctionOnOff(func, data, className) {
167    let param = {
168        valueIn: "",//定义输入
169        valueOut: "",//定义输出
170        valueCheckout: "",//解析
171        valueFill: "",//填充到函数内
172        valuePackage: "",//输出参数打包
173        valueDefine: "",//impl参数定义
174        eventName:"",//注册/去注册事件名称
175        optionalParamDestory: ""//可选参数内存释放
176    }
177
178    for (let i in func.value) {
179        eventParamGenerate(i, func.value[i], param, data)
180    }
181
182    let codeContext = {
183        middleFunc: "",
184        implH: "",
185        implCpp: ""
186    }
187    if (!isOnOffFuncExist(data, func.name)) {
188        // 同一个ts文件中所有的on和off 接口只需要生成一份公共的native方法
189        gennerateOnOffContext(codeContext, func, data, className, param)
190    }
191
192    if (func.name == 'on') {
193        // 为每个on接口同步生成eventCallback方法供用户回调使用
194        gennerateEventCallback(codeContext, data, param)
195    }
196
197    return [codeContext.middleFunc, codeContext.implH, codeContext.implCpp]
198}
199
200module.exports = {
201    generateFunctionOnOff
202}