1 2/* 3* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15*/ 16const { NapiLog } = require("../tools/NapiLog"); 17const { replaceAll, getTab } = require("../tools/tool"); 18const re = require("../tools/re"); 19const { iServiceHTemplate, proxyHTemplate, stubHTemplate, serviceHTemplate, proxyCppTemplate, 20 proxyFuncTemplate, stubCppTemplate, stubInnerFuncTemplate, serviceCppTemplate, serviceFuncImplTemplate, 21 clientCppTemplate, buildGnTemplate, bundleJsonTemplate, profileGnTemplate, profileXmlTemplate, serviceCfgTemplate, 22 serviceCfgGnTemplate } = require("./fileTemplate"); 23const { DATA_WRITE_MAP, DATA_READ_MAP, getParcelType } = require("../tools/common"); 24 25let fileContent = { 26 "iServiceHFile": {}, 27 "proxyHFile": {}, 28 "stubHFile": {}, 29 "serviceHFile": {}, 30 "proxyCppFile": {}, 31 "stubCppFile": {}, 32 "serviceCppFile": {}, 33 "clientCppFile": {}, 34 "buildGnFile": {}, 35 "bundleJsonFile": {}, 36 "profileGnFile": {}, 37 "profileXmlFile": {}, 38 "serviceCfgFile": {}, 39 "serviceCfgGnFile": {} 40}; 41 42function getIncludeStr(includeList) { 43 let includeStr = ""; 44 for (let i = 0; i < includeList.length; ++i) { 45 includeStr += "#include " + includeList[i] + "\n"; 46 } 47 return includeStr; 48} 49 50function getFuncParamStr(params) { 51 let paramStr = ""; 52 for (let i = 0; i < params.length; ++i) { 53 paramStr += (i == 0) ? "" : ", "; 54 paramStr += params[i].type + " " + params[i].name; 55 } 56 return paramStr; 57} 58 59/** 60 * 生成c参数写入remote消息buffer(parcel data)的代码段 61 * @param {} srcName 待写入的c变量名 62 * @param {*} destName 写入目标(parcel data)变量的名称 63 * @param {*} vType c变量类型 64 * @returns 生成的代码段 65 */ 66function genWriteString(srcName, destName, vType) { 67 let matchs = re.match("(std::)?vector<([\x21-\x7e]+)>", vType); 68 if (matchs) { // write data of std::vector 69 let rowType = re.getReg(vType, matchs.regs[2]); 70 let parcelType = getParcelType(rowType); 71 let wFunc = DATA_WRITE_MAP.get(parcelType); 72 if (!wFunc) { 73 NapiLog.logError("Unsupport writing with type: " + vType); 74 return ""; 75 } 76 // use function Parcel::WriteVector(const std::vector<T1> &val, bool (Parcel::*Write)(T2)) 77 return "%s.WriteVector(%s, &(%s.%s));".format(destName, srcName, destName, wFunc); 78 } 79 80 let parcelType = getParcelType(vType); 81 let wFunc = DATA_WRITE_MAP.get(parcelType); 82 if (!wFunc) { 83 NapiLog.logError("Unsupport writing with type: " + vType); 84 return ""; 85 } 86 return "%s.%s(%s);".format(destName, wFunc, srcName); 87} 88 89/** 90 * 生成从remote消息buffer(parcel data)读取c参数的代码段 91 * @param {*} srcName 待读取的parcel data变量名称 92 * @param {*} destName 读取出的内容写入的c变量名称 93 * @param {*} vType c变量类型 94 * @returns 生成的代码段 95 */ 96function genReadString(srcName, destName, vType) { 97 let matchs = re.match("(std::)?vector<([\x21-\x7e]+)>", vType); 98 if (matchs) { // write data of std::vector 99 let rowType = re.getReg(vType, matchs.regs[2]); 100 let parcelType = getParcelType(rowType); 101 let rFunc = DATA_READ_MAP.get(parcelType); 102 if (!rFunc) { 103 NapiLog.logError("Unsupport reading with type: " + vType); 104 return ""; 105 } 106 // use function Parcel::ReadVector(std::vector<T> *val, bool (Parcel::*Read)(T &)) 107 return "%s.ReadVector(&(%s), &(%s.%s));".format(srcName, destName, srcName, rFunc); 108 } 109 110 let parcelType = getParcelType(vType); 111 let rFunc = DATA_READ_MAP.get(parcelType); 112 if (!rFunc) { 113 NapiLog.logError("Unsupport reading with type: " + vType); 114 return ""; 115 } 116 return "%s = %s.%s();".format(destName, srcName, rFunc); 117} 118 119function genProxyFunc(funcInfo, className, paramStr) { 120 let proxyFunc = replaceAll(proxyFuncTemplate, "[className]", className); 121 proxyFunc = replaceAll(proxyFunc, "[funcName]", funcInfo.name); 122 proxyFunc = replaceAll(proxyFunc, "[params]", paramStr); 123 proxyFunc = replaceAll(proxyFunc, "[retType]", funcInfo.retType); 124 proxyFunc = replaceAll(proxyFunc, "[funcEnum]", funcInfo.funcEnum); 125 126 // 入参处理 127 let writeDataStr = ""; 128 let tab = getTab(1); 129 for (let i = 0; i < funcInfo.params.length; ++i) { 130 let param = funcInfo.params[i]; 131 writeDataStr += (i == 0) ? "" : "\n" + tab; 132 writeDataStr += genWriteString(param.name, "data", param.type); 133 } 134 proxyFunc = replaceAll(proxyFunc, "[writeData]", writeDataStr); 135 136 // 返回值处理 137 let readReplyStr = ""; 138 if (funcInfo.retType != "void") { 139 readReplyStr = "%s result;".format(funcInfo.retType); 140 readReplyStr += "\n" + tab + genReadString("reply", "result", funcInfo.retType); 141 readReplyStr += "\n" + tab + "return result;"; 142 } 143 proxyFunc = replaceAll(proxyFunc, "[readReply]", readReplyStr); 144 145 return proxyFunc; 146} 147 148function genStubInnerFunc(funcInfo, className) { 149 let innerFunc = replaceAll(stubInnerFuncTemplate, "[className]", className); 150 innerFunc = replaceAll(innerFunc, "[funcName]", funcInfo.name); 151 152 // 入参处理 153 let readDataStr = ""; // 生成服务端读取客户端传参的代码段 154 let tab = getTab(1); 155 let innerParamStr = ""; // 调用业务方法时传入的入参列表 156 for (let i = 0; i < funcInfo.params.length; ++i) { 157 let param = funcInfo.params[i]; 158 let innerParamName = param.name + "Val"; 159 if (i > 0) { 160 readDataStr += "\n" + tab; 161 innerParamStr += " ,"; 162 } 163 164 //将remote请求中的参数值读取到内部参数变量中 165 readDataStr += "%s %s;".format(param.type, innerParamName); // 定义内部参数变量 166 readDataStr += "\n" + tab + genReadString("data", param.name + "Val", param.type); 167 innerParamStr += innerParamName; 168 } 169 innerFunc = replaceAll(innerFunc, "[readData]", readDataStr); 170 171 // 调用service的实际业务逻辑实现方法 172 let writeReplyStr = ""; // 生成调用服务端实现并返回结果的代码段 173 if (funcInfo.retType === "void") { 174 writeReplyStr += "%s(%s); // call business implementation".format(funcInfo.name, innerParamStr); 175 writeReplyStr += "\n" + tab + "reply.WriteInt32(retCode);"; 176 } else { 177 writeReplyStr += "%s retVal = %s(%s); // call business implementation".format( 178 funcInfo.retType, funcInfo.name, innerParamStr); 179 writeReplyStr += "\n" + tab + "reply.WriteInt32(retCode);"; 180 writeReplyStr += "\n" + tab + genWriteString("retVal", "reply", funcInfo.retType); 181 } 182 innerFunc = replaceAll(innerFunc, "[writeReply]", writeReplyStr); 183 return innerFunc; 184} 185 186function genServiceFunc(funcInfo, className, paramStr) { 187 let serviceFunc = replaceAll(serviceFuncImplTemplate, "[retType]", funcInfo.retType); 188 serviceFunc = replaceAll(serviceFunc, "[className]", className); 189 serviceFunc = replaceAll(serviceFunc, "[funcName]", funcInfo.name); 190 serviceFunc = replaceAll(serviceFunc, "[params]", paramStr); 191 return serviceFunc; 192} 193 194function genFunctions(classInfo, files) { 195 let res = genFunctionCode(classInfo); 196 files.iServiceH = replaceAll(files.iServiceH, "[funcEnum]", res.funcEnumStr); 197 files.iServiceH = replaceAll(files.iServiceH, "[functions]", res.iServiceFuncH); 198 files.proxyH = replaceAll(files.proxyH, "[functions]", res.proxyFuncH); 199 files.stubH = replaceAll(files.stubH, "[innerFuncDef]", res.stubInnerFuncH); 200 files.serviceH = replaceAll(files.serviceH, "[functions]", res.proxyFuncH); 201 files.proxyCpp = replaceAll(files.proxyCpp, "[remoteFuncImpl]", res.proxyFuncCpp); 202 files.stubCpp = replaceAll(files.stubCpp, "[innerFuncMap]", res.stubInnerFuncMap); 203 files.stubCpp = replaceAll(files.stubCpp, "[innerFuncImpl]", res.stubInnerFuncCpp); 204 files.serviceCpp = replaceAll(files.serviceCpp, "[serviceFuncImpl]", res.serviceFuncCpp); 205 files.clientCpp = replaceAll(files.clientCpp, "[clientFuncInvoke]", res.clientFuncCpp); 206} 207 208function genFilesByTemplate(upperServiceName, lowServiceName, rootInfo) { 209 let files = {}; 210 // 按模板生成.h和.cpp文件内容框架 211 files.iServiceH = replaceAll(iServiceHTemplate, "[marcoName]", upperServiceName); 212 files.proxyH = replaceAll(proxyHTemplate, "[marcoName]", upperServiceName); 213 files.stubH = replaceAll(stubHTemplate, "[marcoName]", upperServiceName); 214 files.serviceH = replaceAll(serviceHTemplate, "[marcoName]", upperServiceName); 215 files.proxyCpp = proxyCppTemplate; 216 files.stubCpp = stubCppTemplate; 217 files.serviceCpp = replaceAll(serviceCppTemplate, "[marcoName]", upperServiceName); 218 files.clientCpp = replaceAll(clientCppTemplate, "[marcoName]", upperServiceName); 219 220 // 按模板生成资源配置文件内容框架 221 files.buildGn = replaceAll(buildGnTemplate, "[lowServiceName]", lowServiceName); 222 files.buildGn = replaceAll(files.buildGn, "[stubCppFile]", fileContent.stubCppFile.name); 223 files.buildGn = replaceAll(files.buildGn, "[serviceCppFile]", fileContent.serviceCppFile.name); 224 files.buildGn = replaceAll(files.buildGn, "[proxyCppFile]", fileContent.proxyCppFile.name); 225 files.buildGn = replaceAll(files.buildGn, "[clientCppFile]", fileContent.clientCppFile.name); 226 files.bundleJson = replaceAll(bundleJsonTemplate, "[lowServiceName]", lowServiceName); 227 files.profileGn = replaceAll(profileGnTemplate, "[lowServiceName]", lowServiceName); 228 files.profileGn = replaceAll(files.profileGn, "[serviceId]", rootInfo.serviceId); 229 files.profileXml = replaceAll(profileXmlTemplate, "[lowServiceName]", lowServiceName); 230 files.profileXml = replaceAll(files.profileXml, "[serviceId]", rootInfo.serviceId); 231 files.serviceCfg = replaceAll(serviceCfgTemplate, "[lowServiceName]", lowServiceName); 232 files.serviceGnCfg = replaceAll(serviceCfgGnTemplate, "[lowServiceName]", lowServiceName); 233 return files; 234} 235 236function replaceClassName(files, classInfo) { 237 files.iServiceH = replaceAll(files.iServiceH, "[className]", classInfo.name); 238 files.proxyH = replaceAll(files.proxyH, "[className]", classInfo.name); 239 files.stubH = replaceAll(files.stubH, "[className]", classInfo.name); 240 files.serviceH = replaceAll(files.serviceH, "[className]", classInfo.name); 241 files.proxyCpp = replaceAll(files.proxyCpp, "[className]", classInfo.name); 242 files.stubCpp = replaceAll(files.stubCpp, "[className]", classInfo.name); 243 files.serviceCpp = replaceAll(files.serviceCpp, "[className]", classInfo.name); 244 files.clientCpp = replaceAll(files.clientCpp, "[className]", classInfo.name); 245} 246 247function replaceServiceName(files, rootInfo) { 248 files.iServiceH = replaceAll(files.iServiceH, "[serviceName]", rootInfo.serviceName); 249 files.proxyH = replaceAll(files.proxyH, "[serviceName]", rootInfo.serviceName); 250 files.stubH = replaceAll(files.stubH, "[serviceName]", rootInfo.serviceName); 251 files.serviceH = replaceAll(files.serviceH, "[serviceName]", rootInfo.serviceName); 252 files.proxyCpp = replaceAll(files.proxyCpp, "[serviceName]", rootInfo.serviceName); 253 files.stubCpp = replaceAll(files.stubCpp, "[serviceName]", rootInfo.serviceName); 254 files.serviceCpp = replaceAll(files.serviceCpp, "[serviceName]", rootInfo.serviceName); 255 files.clientCpp = replaceAll(files.clientCpp, "[serviceName]", rootInfo.serviceName); 256} 257 258function replaceIncludes(files, rootInfo) { 259 files.iServiceH = replaceAll(files.iServiceH, "[includes]", getIncludeStr(rootInfo.includes)); 260 files.proxyH = replaceAll(files.proxyH, "[iServiceHInclude]", fileContent.iServiceHFile.name); 261 files.stubH = replaceAll(files.stubH, "[iServiceHInclude]", fileContent.iServiceHFile.name); 262 files.serviceH = replaceAll(files.serviceH, "[stubHInclude]", fileContent.stubHFile.name); 263 files.proxyCpp = replaceAll(files.proxyCpp, "[proxyHInclude]", fileContent.proxyHFile.name); 264 files.stubCpp = replaceAll(files.stubCpp, "[stubHInclude]", fileContent.stubHFile.name); 265 files.serviceCpp = replaceAll(files.serviceCpp, "[serviceHInclude]", fileContent.serviceHFile.name); 266 files.clientCpp = replaceAll(files.clientCpp, "[proxyHInclude]", fileContent.proxyHFile.name); 267} 268 269function genFileNames(lowServiceName, rootInfo) { 270 fileContent.iServiceHFile.name = "i_%s_service.h".format(lowServiceName); 271 fileContent.proxyHFile.name = "%s_service_proxy.h".format(lowServiceName); 272 fileContent.stubHFile.name = "%s_service_stub.h".format(lowServiceName); 273 fileContent.serviceHFile.name = "%s_service.h".format(lowServiceName); 274 fileContent.proxyCppFile.name = "%s_service_proxy.cpp".format(lowServiceName); 275 fileContent.stubCppFile.name = "%s_service_stub.cpp".format(lowServiceName); 276 fileContent.serviceCppFile.name = "%s_service.cpp".format(lowServiceName); 277 fileContent.clientCppFile.name = "%s_client.cpp".format(lowServiceName); 278 fileContent.buildGnFile.name = "BUILD.gn"; 279 fileContent.bundleJsonFile.name = "bundle.json"; 280 fileContent.profileGnFile.name = "BUILD.gn"; 281 fileContent.profileXmlFile.name = rootInfo.serviceId + ".xml"; 282 fileContent.serviceCfgFile.name = "%s_service.cfg".format(lowServiceName); 283 fileContent.serviceCfgGnFile.name = "BUILD.gn"; 284} 285 286function genFunctionCode(classInfo) { 287 let funcList = classInfo.functions; 288 let genResult = {} 289 genResult.funcEnumStr = ""; 290 genResult.iServiceFuncH = ""; //i_service.h 方法定义 291 genResult.proxyFuncH = ""; //proxy.h 方法定义 292 genResult.stubInnerFuncH = ""; // stub.h 的inner方法定义 293 genResult.proxyFuncCpp = ""; //proxy.cpp 方法实现 294 genResult.stubInnerFuncMap = ""; // stub.cpp 的inner方法映射表 295 genResult.stubInnerFuncCpp = ""; // stub.cpp 的inner方法实现 296 genResult.serviceFuncCpp = ""; // service.cpp的方法实现 297 genResult.clientFuncCpp = ""; // client.cpp 的inner方法定义 298 299 let enumTab = getTab(2); 300 let funcTab = getTab(1); 301 for (var i = 0; i < funcList.length; ++i) { 302 funcList[i].funcEnum = funcList[i].name.toUpperCase(); // remote方法的枚举值 303 genResult.funcEnumStr += (i == 0) ? "" : ",\n" + enumTab; 304 genResult.funcEnumStr += funcList[i].funcEnum; 305 306 let paramStr = getFuncParamStr(funcList[i].params); 307 genResult.iServiceFuncH += (i == 0) ? "" : "\n" + funcTab; 308 genResult.iServiceFuncH += "virtual %s %s(%s) = 0;".format(funcList[i].retType, funcList[i].name, paramStr); 309 310 genResult.proxyFuncH += (i == 0) ? "" : "\n" + funcTab; 311 genResult.proxyFuncH += "%s %s(%s) override;".format(funcList[i].retType, funcList[i].name, paramStr); 312 313 genResult.stubInnerFuncH += (i == 0) ? "" : "\n" + funcTab; 314 genResult.stubInnerFuncH += 315 "ErrCode %sInner(MessageParcel &data, MessageParcel &reply);".format(funcList[i].name); 316 317 genResult.proxyFuncCpp += genProxyFunc(funcList[i], classInfo.name, paramStr); 318 319 genResult.stubInnerFuncMap += (i == 0) ? "" : "\n" + funcTab; 320 genResult.stubInnerFuncMap += "innerFuncs_[%s] = &%sStub::%sInner;".format( 321 funcList[i].funcEnum, classInfo.name, funcList[i].name); 322 323 genResult.stubInnerFuncCpp += genStubInnerFunc(funcList[i], classInfo.name); 324 genResult.serviceFuncCpp += genServiceFunc(funcList[i], classInfo.name, paramStr); 325 326 genResult.clientFuncCpp += (i == 0) ? "" : "\n" + funcTab; 327 genResult.clientFuncCpp += "// proxy->%s(%s);".format(funcList[i].name, paramStr); 328 } 329 return genResult; 330} 331 332function doGenerate(rootInfo) { 333 let lowServiceName = rootInfo.serviceName.toLowerCase(); 334 let upperServiceName = rootInfo.serviceName.toUpperCase(); 335 336 // 生成文件名 337 genFileNames(lowServiceName, rootInfo); 338 339 // 按模板生成.h和.cpp文件内容框架 340 let files = genFilesByTemplate(upperServiceName, lowServiceName, rootInfo); 341 342 // 替换文件includes 343 replaceIncludes(files, rootInfo); 344 345 // 替换namespace 346 replaceServiceName(files, rootInfo); 347 348 // 替换类名 349 let classInfo = rootInfo.class[0] 350 replaceClassName(files, classInfo); 351 352 // 生成函数定义与实现 353 genFunctions(classInfo, files); 354 355 // 文件内容汇总 356 fileContent.iServiceHFile.content = files.iServiceH; 357 fileContent.proxyHFile.content = files.proxyH; 358 fileContent.stubHFile.content = files.stubH; 359 fileContent.serviceHFile.content = files.serviceH; 360 fileContent.proxyCppFile.content = files.proxyCpp; 361 fileContent.stubCppFile.content = files.stubCpp; 362 fileContent.serviceCppFile.content = files.serviceCpp; 363 fileContent.clientCppFile.content = files.clientCpp; 364 fileContent.buildGnFile.content = files.buildGn; 365 fileContent.bundleJsonFile.content = files.bundleJson; 366 fileContent.profileGnFile.content = files.profileGn; 367 fileContent.profileXmlFile.content = files.profileXml; 368 fileContent.serviceCfgFile.content = files.serviceCfg; 369 fileContent.serviceCfgGnFile.content = files.serviceGnCfg; 370 return fileContent; 371} 372 373module.exports = { 374 doGenerate 375} 376