1/* 2* Copyright (c) 2024 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*/ 15 16const { NapiLog } = require('../tools/NapiLog'); 17const util = require('util'); 18const path = require('path'); 19const fs = require('fs'); 20const { writeFile, readFile } = require('../tools/tool'); 21const re = require('../tools/re'); 22const LENGTH = 10; 23const TWO_DECIMAL = 2; 24 25function analyzeRetIsObject(retType, objectInfo) { 26 // 去除 * 和 空格 27 retType = retType.replace('*', '').replace('struct', '').trim(); 28 let objKeys = Object.keys(objectInfo); 29 for (let i = 0; i < objKeys.length; i++) { 30 if (retType === objKeys[i]) { 31 return true; 32 } 33 } 34 return false; 35} 36 37 38function analyzeRetIsTypeDef(type, info) { 39 let typedefKeys = Object.keys(info); 40 for (let i = 0; i < typedefKeys.length; i++) { 41 if (type === typedefKeys[i]) { 42 return info[type]; 43 } 44 } 45 return null; 46} 47 48//tsFuncName 49function generateDirectFunction(params, index, tsFuncName, directFuncPath, hFileName) { 50 let funcInfo = { 51 'name': '', 52 'params': [], 53 'retType': '', 54 }; 55 56 let funcNameReplace = tsFuncName; 57 58 // 方法的注册 59 let initReplace = genInitFunction(directFuncPath, funcNameReplace); 60 61 // 分析方法 分析第index个方法 62 analyzeFunction(funcInfo, params, index); 63 64 // 生成 65 let paramGenResult = genParamInfo(directFuncPath, funcInfo, params); 66 67 // 返回值处理 对于对象要使用循环处理 68 let retGenResult = ''; 69 let retObjInfo = { 70 'objName': '', 71 'flag': false 72 }; 73 74 let funcRetOutPath = directFuncPath.cppTempleteDetails.funcBody.funcReturnOut; 75 retGenResult = returnTypeC2Js(funcRetOutPath, funcInfo, params, retGenResult, retObjInfo); 76 77 let { bodyReplace, funcInfoParams } = getReplaceInfo(directFuncPath, funcInfo, funcNameReplace, hFileName); 78 79 let funcGetParamTempletePath = path.join(__dirname, 80 directFuncPath.cppTempleteDetails.funcBody.funcParamIn.funcGetParamTemplete); 81 let funcGetParamTemplete = readFile(funcGetParamTempletePath); 82 let genParamReplace = getGenParamReplace(funcGetParamTemplete, funcInfo, funcNameReplace, paramGenResult); 83 bodyReplace = getBodyReplace2(funcInfo, bodyReplace, genParamReplace); 84 if (funcInfo.retType.replace('*', '').trim() !== 'void') { 85 let returnType = funcInfo.retType === 'std::string' ? 'const char *' : funcInfo.retType; 86 returnType = returnType === 'size_t' ? 'int64_t' : returnType; 87 let funcReturnTempletePath = path.join(__dirname, funcRetOutPath.funcReturnTemplete); 88 let funcReturnTemplete = readFile(funcReturnTempletePath); 89 let funcReturnReplace = replaceAll(funcReturnTemplete, '[return_name]', retObjInfo.objName); 90 funcReturnReplace = replaceAll(funcReturnReplace, '[funcName]', funcNameReplace); 91 funcReturnReplace = replaceAll(funcReturnReplace, '[return_replace]', retGenResult); 92 bodyReplace = replaceAll(bodyReplace, '[func_return_replace]', funcReturnReplace); 93 } else { 94 bodyReplace = replaceAll(bodyReplace, '[func_return_replace]', ' return NULL;\n'); 95 } 96 bodyReplace = replaceAll(bodyReplace, '[return_replace]', retGenResult); 97 98 let funcHDeclare = genFuncHDeclare(directFuncPath, funcNameReplace, hFileName, funcInfo, funcInfoParams); 99 100 return [funcHDeclare, initReplace, bodyReplace]; 101} 102 103function getReplaceInfo(directFuncPath, funcInfo, funcNameReplace, hFileName) { 104 let funcBodyTempletePath = path.join(__dirname, directFuncPath.cppTempleteDetails.funcBody.funcBodyTemplete); 105 let bodyTemplete = readFile(funcBodyTempletePath); 106 let funcInfoParams = genFuncInfoParams(funcInfo); 107 let bodyReplace = replaceAll(bodyTemplete, '[funcName]', funcNameReplace); 108 bodyReplace = getBodyReplace(bodyReplace, funcNameReplace, hFileName, funcInfo, funcInfoParams); 109 return { bodyReplace, funcInfoParams }; 110} 111 112function getBodyReplace(bodyReplace, funcNameReplace, hFileName, funcInfo, funcInfoParams) { 113 bodyReplace = replaceAll(bodyReplace, '[get_error_msg_tag]', funcNameReplace); 114 bodyReplace = replaceAll(bodyReplace, '[file_introduce_replace]', hFileName); 115 bodyReplace = replaceAll(bodyReplace, '[func_introduce_replace]', funcInfo.name); 116 bodyReplace = replaceAll(bodyReplace, '[input_introduce_replace]', funcInfoParams === '' ? 'void' : funcInfoParams); 117 bodyReplace = replaceAll(bodyReplace, '[output_introduce_replace]', funcInfo.retType); 118 return bodyReplace; 119} 120 121function getBodyReplace2(funcInfo, bodyReplace, genParamReplace) { 122 if (funcInfo.params.length !== 0) { 123 bodyReplace = replaceAll(bodyReplace, '[func_getParam_replace]', genParamReplace); 124 } else { 125 bodyReplace = replaceAll(bodyReplace, '[func_getParam_replace]', ''); 126 } 127 return bodyReplace; 128} 129 130function getGenParamReplace(funcGetParamTemplete, funcInfo, funcNameReplace, paramGenResult) { 131 let genParamReplace = replaceAll(funcGetParamTemplete, '[param_length]', 'PARAMS' + funcInfo.params.length); 132 genParamReplace = replaceAll(genParamReplace, '[funcName]', funcNameReplace); 133 genParamReplace = replaceAll(genParamReplace, '[getParam_replace]', paramGenResult); 134 return genParamReplace; 135} 136 137function genFuncInfoParams(funcInfo) { 138 let funcInfoParams = ''; 139 let funcInfoParamTemp = '[paramName]: [paramType]; '; 140 for (let i = 0; i < funcInfo.params.length; i++) { 141 let funcInfoParamReplace = replaceAll(funcInfoParamTemp, '[paramName]', funcInfo.params[i].name); 142 funcInfoParamReplace = replaceAll(funcInfoParamReplace, '[paramType]', funcInfo.params[i].type); 143 funcInfoParams += funcInfoParamReplace; 144 } 145 return funcInfoParams; 146} 147 148function genFuncHDeclare(directFuncPath, funcNameReplace, hFileName, funcInfo, funcInfoParams) { 149 let funcHDeclarePath = path.join(__dirname, directFuncPath.cppTempleteDetails.funcHDeclare.funcHDeclare); 150 let funcHDeclare = readFile(funcHDeclarePath); 151 funcHDeclare = replaceAll(funcHDeclare, '[funcName]', funcNameReplace); 152 153 funcHDeclare = replaceAll(funcHDeclare, '[file_introduce_replace]', hFileName); 154 funcHDeclare = replaceAll(funcHDeclare, '[func_introduce_replace]', funcInfo.name); 155 funcHDeclare = replaceAll(funcHDeclare, '[input_introduce_replace]', funcInfoParams === '' ? 'void' : funcInfoParams); 156 funcHDeclare = replaceAll(funcHDeclare, '[output_introduce_replace]', funcInfo.retType); 157 return funcHDeclare; 158} 159 160function genParamInfo(directFuncPath, funcInfo, params) { 161 let relativeParamGenPath = directFuncPath.cppTempleteDetails.funcBody.funcParamIn.paramGenTemplete; 162 let paramGenTempletePath = path.join(__dirname, relativeParamGenPath); 163 let paramGenTemplete = readFile(paramGenTempletePath); 164 let funcParamTypePath = directFuncPath.cppTempleteDetails.funcBody.funcParamIn.funcParamType; 165 let paramGenResult = ''; 166 // napi 获取参数 167 for (let i = 0; i < funcInfo.params.length; i++) { 168 paramGenResult = getParamJs2C(funcInfo, i, paramGenTemplete, funcParamTypePath, paramGenResult, params); 169 } 170 return paramGenResult; 171} 172 173function analyzeFunction(funcInfo, params, index) { 174 funcInfo.name = params.functions[index].name; 175 funcInfo.retType = params.functions[index].rtnType; 176 let parseParams = params.functions[index].parameters; 177 for (let i = 0; i < parseParams.length; ++i) { 178 let param = createParam(parseParams[i]); 179 funcInfo.params.push(param); 180 } 181} 182 183function genInitFunction(directFuncPath, funcNameReplace) { 184 let funcInitPath = path.join(__dirname, directFuncPath.initTempleteDetails.funcInitTemplete); 185 let funcInitTemplete = readFile(funcInitPath); 186 let initReplace = replaceAll(funcInitTemplete, '[func_name_replace]', funcNameReplace); 187 return initReplace; 188} 189 190function getParamJs2C(funcInfo, i, paramGenTemplete, funcParamTypePath, paramGenResult, params) { 191 let paramType = funcInfo.params[i].type === 'size_t' ? 'int64_t' : funcInfo.params[i].type; 192 // 去除const 和 * 193 paramType = paramType.replace('const', '').replace('*', '').trim(); 194 let paramName = funcInfo.params[i].name; 195 let paramGen = replaceAll(paramGenTemplete, '[param_index_replace]', 'PARAMS' + i); 196 paramGen = replaceAll(paramGen, '[param_name_replace]', paramName); 197 if (paramType === 'double') { 198 let getParamPath = path.join(__dirname, funcParamTypePath.double); 199 paramGen = getParamGenCon(getParamPath, i, paramName, paramGen); 200 paramGenResult += paramGen; 201 } else if (paramType === 'uint32_t') { 202 let getParamPath = path.join(__dirname, funcParamTypePath.uint32_t); 203 paramGen = getParamGenCon(getParamPath, i, paramName, paramGen); 204 paramGenResult += paramGen; 205 } else if (paramType === 'int32_t' || paramType === 'int') { 206 let getParamPath = path.join(__dirname, funcParamTypePath.int32_t); 207 paramGen = getParamGenCon(getParamPath, i, paramName, paramGen); 208 paramGenResult += paramGen; 209 } else if (paramType === 'int64_t' || paramType === 'size_t') { 210 let getParamPath = path.join(__dirname, funcParamTypePath.int64_t); 211 paramGen = getParamGenCon(getParamPath, i, paramName, paramGen); 212 paramGenResult += paramGen; 213 } else if (paramType === 'bool') { 214 let getParamPath = path.join(__dirname, funcParamTypePath.bool); 215 paramGen = getParamGenCon(getParamPath, i, paramName, paramGen); 216 paramGenResult += paramGen; 217 } else if (paramType === 'std::string' || paramType.indexOf('char') >= 0) { 218 let getParamPath = path.join(__dirname, funcParamTypePath.string); 219 paramGen = getParamGenCon(getParamPath, i, paramName, paramGen); 220 paramGenResult += paramGen; 221 } else if (analyzeRetIsTypeDef(paramType, params.typedefs)) { // typedefs 222 funcInfo.params[i].type = analyzeRetIsTypeDef(paramType, params.typedefs); 223 paramGenResult = getParamJs2C(funcInfo, i, paramGenTemplete, funcParamTypePath, paramGenResult, params); 224 } 225 // 其他情况,处理成对象 napi_get_cb_info之后不做任何处理 226 return paramGenResult; 227} 228 229function getParamGenCon(getParamPath, i, paramName, paramGen) { 230 let getParam = readFile(getParamPath); 231 getParam = replaceAll(getParam, '[param_index_replace]', 'PARAMS' + i); 232 getParam = replaceAll(getParam, '[param_name_replace]', paramName); 233 paramGen = replaceAll(paramGen, '[getParam_replace]', getParam); 234 return paramGen; 235} 236 237function returnTypeC2Js(funcRetOutPath, funcInfo, params, retGenResult, retObjInfo) { 238 let setRetPropertyPath = path.join(__dirname, funcRetOutPath.funcReturnType.returnObj.funcReturnObjectToSet); 239 let setRetProperty = readFile(setRetPropertyPath); 240 let returnName = funcInfo.name; 241 if (!retObjInfo.flag) { 242 retObjInfo.objName = returnName; 243 } 244 if (funcInfo.retType === 'uint32_t') { 245 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.uint32_t); 246 retGenResult = getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty); 247 } else if (funcInfo.retType === 'double') { 248 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.double); 249 retGenResult = getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty); 250 } else if (funcInfo.retType === 'int32_t' || funcInfo.retType === 'int') { 251 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.int32_t); 252 retGenResult = getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty); 253 } else if (funcInfo.retType === 'int64_t' || funcInfo.retType === 'size_t') { 254 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.int64_t); 255 retGenResult = getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty); 256 } else if (funcInfo.retType === 'bool') { 257 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.bool); 258 retGenResult = getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty); 259 } else if (funcInfo.retType === 'std::string' || funcInfo.retType.substring(0, 10) === 'const char' || 260 funcInfo.retType === 'char *') { 261 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.string); 262 retGenResult = getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty); 263 } else if (analyzeRetIsObject(funcInfo.retType, params.classes)) { // 返回值是对象 264 if (!retObjInfo.flag) { 265 retGenResult = getObjRetContent(funcRetOutPath, retGenResult, returnName); 266 retObjInfo.flag = true; 267 let objectProperty = getObjectProperty(funcInfo, params); 268 // 遍历属性 269 for (let i = 0; i < objectProperty.length; i++) { 270 let testRes = returnTypeC2Js(funcRetOutPath, objectProperty[i], params, retGenResult, retObjInfo); 271 retGenResult = testRes; 272 } 273 } else { 274 retGenResult = getObjRetGenResult(retObjInfo, retGenResult, funcRetOutPath, returnName, setRetPropertyPath); 275 } 276 } else if (analyzeRetIsTypeDef(funcInfo.retType, params.typedefs)) { // typedefs 277 funcInfo.retType = analyzeRetIsTypeDef(funcInfo.retType, params.typedefs); 278 retGenResult = returnTypeC2Js(funcRetOutPath, funcInfo, params, retGenResult, retObjInfo); 279 } 280 return retGenResult; 281} 282 283function getObjectProperty(funcInfo, params) { 284 let retType = funcInfo.retType.replace('*', '').trim(); 285 let objectName = ''; 286 let objectProperty = []; 287 288 let myObject = params.classes[retType]; 289 objectName = myObject.bare_name; 290 let myObjectProperty = myObject.properties.public; 291 for (let j = 0; j < myObjectProperty.length; j++) { 292 let propertyObj = { 293 'name': '', 294 'retType': '' 295 }; 296 propertyObj.name = myObjectProperty[j].name; 297 propertyObj.retType = myObjectProperty[j].type; 298 299 objectProperty.push(propertyObj); 300 } 301 return objectProperty; 302} 303 304function getObjRetGenResult(retObjInfo, retGenResult, funcRetOutPath, returnName, setRetPropertyPath) { 305 if (retObjInfo.objName !== '') { 306 retGenResult = getObjRetContent(funcRetOutPath, retGenResult, returnName); 307 let setRetPropertyObj = readFile(setRetPropertyPath); 308 setRetPropertyObj = replaceAll(setRetPropertyObj, '[set_objname_replace]', retObjInfo.objName); 309 setRetPropertyObj = replaceAll(setRetPropertyObj, '[set_propname_replace]', returnName); 310 setRetPropertyObj = replaceAll(setRetPropertyObj, '[set_propvalue_replace]', returnName); 311 retGenResult += setRetPropertyObj; 312 } 313 return retGenResult; 314} 315 316function getObjRetContent(funcRetOutPath, retGenResult, returnName) { 317 let funcReturnTypePath = path.join(__dirname, funcRetOutPath.funcReturnType.returnObj.object); 318 let funcReturnType = readFile(funcReturnTypePath); 319 retGenResult += replaceAll(funcReturnType, '[return_name_replace]', returnName); 320 return retGenResult; 321} 322 323function getRetTypeContent(funcReturnTypePath, returnName, retGenResult, retObjInfo, setRetProperty) { 324 let funcReturnType = readFile(funcReturnTypePath); 325 funcReturnType = replaceAll(funcReturnType, '[return_name_replace]', returnName); 326 retGenResult += funcReturnType; 327 if (retObjInfo.flag) { 328 setRetProperty = replaceAll(setRetProperty, '[set_objname_replace]', retObjInfo.objName); 329 setRetProperty = replaceAll(setRetProperty, '[set_propname_replace]', returnName); 330 setRetProperty = replaceAll(setRetProperty, '[set_propvalue_replace]', returnName); 331 retGenResult += setRetProperty; 332 } 333 return retGenResult; 334} 335 336function replaceAll(s, sfrom, sto) { 337 while (s.indexOf(sfrom) >= 0) { 338 s = s.replace(sfrom, sto); 339 } 340 return s; 341} 342 343function createParam(parseParamInfo) { 344 let param = { 345 'name': '', 346 'type': '' 347 }; 348 param.name = parseParamInfo.name; 349 param.type = parseParamInfo.type; 350 return param; 351} 352 353module.exports = { 354 generateDirectFunction 355};