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}