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 { generateFunctionDirect } = require("./function_direct"); 16const { generateFunctionSync } = require("./function_sync"); 17const { generateFunctionAsync } = require("./function_async"); 18const { FuncType, InterfaceList, getArrayType } = require("../tools/common"); 19const { jsToC } = require("./param_generate"); 20const { cToJs } = require("./return_generate"); 21const re = require("../tools/re"); 22const { NapiLog } = require("../tools/NapiLog"); 23 24let middleBodyTmplete = ` 25class [className]_middle { 26public: 27 static napi_value constructor(napi_env env, napi_callback_info info) 28 { 29 XNapiTool *pxt = new XNapiTool(env, info); 30 31 [className] *p = new [className](); 32 33 napi_value thisvar = pxt->WrapInstance(p, release); 34 35 return thisvar; 36 } 37 static void release(void *p) 38 { 39 [className] *p2 = ([className] *)p; 40 delete p2; 41 } 42 [static_funcs] 43};` 44 45function generateVariable(name, type, variable, className) { 46 if (type == "string") variable.hDefine += "\n std::string %s;".format(name) 47 else if (type.substring(0, 12) == "NUMBER_TYPE_") variable.hDefine += "\n %s %s;".format(type, name) 48 else if (InterfaceList.getValue(type)) variable.hDefine += "\n %s %s;".format(type, name) 49 else if (type.indexOf("Array<") == 0) { 50 let type2 = getArrayType(type) 51 if (type2 == "string") type2 = "std::string" 52 if (type2 == "boolean") type2 = "bool" 53 variable.hDefine += "\n std::vector<%s> %s;".format(type2, name) 54 } else if (type == "boolean") { 55 variable.hDefine += "\n bool %s;".format(name) 56 } else if (type.indexOf("[]") == 0) { 57 variable.hDefine += "\n std::vector<%s> %s;".format(type, name) 58 } 59 else 60 NapiLog.logError(` 61 ---- generateVariable fail %s,%s ---- 62 `.format(name, type)); 63 variable.middleValue += ` 64 static napi_value getvalue_%s(napi_env env, napi_callback_info info) 65 { 66 XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release(); 67 %s *p = (%s *)pxt->UnWarpInstance(); 68 napi_value result = nullptr; 69 `.format(name, className, className) + cToJs("p->" + name, type, "result") + ` 70 delete pxt; 71 return result; 72 } 73 static napi_value setvalue_%s(napi_env env, napi_callback_info info) 74 { 75 std::shared_ptr<XNapiTool> pxt = std::make_shared<XNapiTool>(env, info); 76 %s *p = (%s *)pxt->UnWarpInstance(); 77 `.format(name, className, className) + jsToC("p->" + name, "pxt->GetArgv(0)", type) + ` 78 return nullptr; 79 } 80` 81} 82 83function generateClass(name, data, inNamespace, functiontType) { 84 let resultConnect = connectResult(data, inNamespace, name) 85 let middleFunc = resultConnect[0] 86 let implH = functiontType == "static" ? "\n" + "static " + 87 resultConnect[1].substring(1, resultConnect[1].length) : resultConnect[1] 88 let implCpp = resultConnect[2] 89 let middleInit = resultConnect[3] 90 let selfNs = "" 91 if (inNamespace.length > 0) { 92 let nsl = inNamespace.split("::") 93 nsl.pop() 94 if (nsl.length >= 2) { 95 selfNs = ", " + nsl[nsl.length - 1] 96 } 97 } 98 middleInit += `\n pxt->DefineClass("%s", %s%s_middle::constructor, valueList ,funcList%s);\n}\n` 99 .format(name, inNamespace, name, selfNs) 100 let result = { 101 implH: ` 102class %s { 103public:%s 104};`.format(name, implH), 105 implCpp: implCpp, 106 middleBody: middleBodyTmplete.replaceAll("[className]", name).replaceAll("[static_funcs]", middleFunc), 107 middleInit: middleInit 108 } 109 return result 110} 111 112function connectResult(data, inNamespace, name) { 113 let implH = "" 114 let implCpp = "" 115 let middleFunc = "" 116 let middleInit = "" 117 let variable = { 118 hDefine: "", 119 middleValue: "", 120 } 121 middleInit = `{\n std::map<const char *,std::map<const char *,napi_callback>> valueList;` 122 for (let i in data.value) { 123 let v = data.value[i] 124 generateVariable(v.name, v.type, variable, name) 125 middleInit += ` 126 valueList["%s"]["getvalue"]=%s%s_middle::getvalue_%s; 127 valueList["%s"]["setvalue"]=%s%s_middle::setvalue_%s;` 128 .format(v.name, inNamespace, name, v.name, v.name, inNamespace, name, v.name) 129 } 130 implH += variable.hDefine 131 middleFunc += variable.middleValue 132 middleInit += `\n std::map<const char *, napi_callback> funcList;` 133 for (let i in data.function) { 134 let func = data.function[i] 135 let tmp; 136 switch (func.type) { 137 case FuncType.DIRECT: 138 tmp = generateFunctionDirect(func, '', name) 139 break; 140 case FuncType.SYNC: 141 tmp = generateFunctionSync(func, '', name) 142 break 143 case FuncType.ASYNC: 144 case FuncType.PROMISE: 145 tmp = generateFunctionAsync(func, '', name) 146 break 147 default: 148 return 149 } 150 middleFunc += tmp[0] 151 implH += tmp[1] 152 implCpp += tmp[2] 153 middleInit += `\n funcList["%s"] = %s%s_middle::%s_middle;`.format(func.name, inNamespace, name, func.name) 154 } 155 return [middleFunc, implH, implCpp, middleInit] 156} 157 158module.exports = { 159 generateClass 160}