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