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};