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 [className] *p = new [className](); 31 napi_value thisvar = pxt->WrapInstance(reinterpret_cast<DataPtr>(p), release); 32 return thisvar; 33 } 34 static void release(DataPtr p) 35 { 36 void *dataPtr = p; 37 [className] *p2 = static_cast<[className] *>(dataPtr); 38 delete p2; 39 } 40 [static_funcs] 41};`; 42 43function generateVariable(name, type, variable, className) { 44 if (type === 'string') { 45 variable.hDefine += '\n std::string %s;'.format(name); 46 } else if (type.substring(0, 12) === 'NUMBER_TYPE_') { 47 variable.hDefine += '\n %s %s;'.format(type, name); 48 } else if (InterfaceList.getValue(type)) { 49 variable.hDefine += '\n %s %s;'.format(type, name); 50 } else if (type.indexOf('Array<') === 0) { 51 let type2 = getArrayType(type); 52 if (type2 === 'string') { 53 type2 = 'std::string'; 54 } 55 if (type2 === 'boolean') { 56 type2 = 'bool'; 57 } 58 variable.hDefine += '\n std::vector<%s> %s;'.format(type2, name); 59 } else if (type === 'boolean') { 60 variable.hDefine += '\n bool %s;'.format(name); 61 } else if (type.indexOf('[]') === 0) { 62 variable.hDefine += '\n std::vector<%s> %s;'.format(type, name); 63 } else { 64 NapiLog.logError(` 65 ---- generateVariable fail %s,%s ---- 66 `.format(name, type)); 67 } 68 variable.middleValue += ` 69 static napi_value getvalue_%s(napi_env env, napi_callback_info info) 70 { 71 XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release(); 72 void *instPtr = pxt->UnWarpInstance(); 73 %s *p = static_cast<%s *>(instPtr); 74 napi_value result = nullptr; 75 `.format(name, className, className) + cToJs('p->' + name, type, 'result') + ` 76 delete pxt; 77 return result; 78 } 79 static napi_value setvalue_%s(napi_env env, napi_callback_info info) 80 { 81 std::shared_ptr<XNapiTool> pxt = std::make_shared<XNapiTool>(env, info); 82 void *instPtr = pxt->UnWarpInstance(); 83 %s *p = static_cast<%s *>(instPtr); 84 `.format(name, className, className) + jsToC('p->' + name, 'pxt->GetArgv(XNapiTool::ZERO)', type) + ` 85 return nullptr; 86 } 87`; 88} 89 90function generateClass(name, data, inNamespace, functiontType) { 91 let resultConnect = connectResult(data, inNamespace, name); 92 let middleFunc = resultConnect[0]; 93 let implH = functiontType === 'static' ? '\n' + 'static ' + 94 resultConnect[1].substring(1, resultConnect[1].length) : resultConnect[1]; 95 let implCpp = resultConnect[2]; 96 let middleInit = resultConnect[3]; 97 let middleH = resultConnect[4]; 98 let selfNs = ''; 99 if (inNamespace.length > 0) { 100 let nsl = inNamespace.split('::'); 101 nsl.pop(); 102 if (nsl.length >= 2) { 103 selfNs = ', ' + nsl[nsl.length - 1]; 104 } 105 } 106 let toolNamespace = getToolNamespace(inNamespace); 107 middleInit += `\n pxt->DefineClass("%s", %s%s%s_middle::constructor, valueList, funcList%s);\n}\n` 108 .format(name, inNamespace, toolNamespace, name, selfNs); 109 let result = { 110 implH: ` 111class %s { 112public:%s 113};`.format(name, implH), 114 implCpp: implCpp, 115 middleBody: middleBodyTmplete.replaceAll('[className]', name).replaceAll('[static_funcs]', middleFunc), 116 middleInit: middleInit, 117 declarationH: ` 118class %s;\r`.format(name), 119 middleH: middleH 120 }; 121 return result; 122} 123 124function connectResult(data, inNamespace, name) { 125 let implH = ''; 126 let implCpp = ''; 127 let middleFunc = ''; 128 let middleInit = ''; 129 let middleH = ''; 130 let variable = { 131 hDefine: '', 132 middleValue: '', 133 }; 134 let toolNamespace = getToolNamespace(inNamespace); 135 middleInit = `{\n std::map<const char *, std::map<const char *, napi_callback>> valueList;`; 136 for (let i in data.value) { 137 let v = data.value[i]; 138 generateVariable(v.name, v.type, variable, name); 139 middleInit += ` 140 valueList["%s"]["getvalue"] = %s%s%s_middle::getvalue_%s; 141 valueList["%s"]["setvalue"] = %s%s%s_middle::setvalue_%s;` 142 .format(v.name, inNamespace, toolNamespace, name, v.name, v.name, inNamespace, toolNamespace, name, v.name); 143 } 144 implH += variable.hDefine; 145 middleFunc += variable.middleValue; 146 middleInit += `\n std::map<const char *, napi_callback> funcList;`; 147 for (let i in data.function) { 148 let func = data.function[i]; 149 let tmp = []; 150 switch (func.type) { 151 case FuncType.DIRECT: 152 tmp = generateFunctionDirect(func, '', name); 153 break; 154 case FuncType.SYNC: 155 tmp = generateFunctionSync(func, '', name); 156 break; 157 case FuncType.ASYNC: 158 case FuncType.PROMISE: 159 tmp = generateFunctionAsync(func, '', name); 160 break; 161 default: 162 tmp = []; 163 break; 164 } 165 middleFunc += tmp[0]; 166 implH += tmp[1]; 167 implCpp += tmp[2]; 168 middleH += tmp[3]; 169 middleInit += `\n funcList["%s"] = %s%s%s_middle::%s_middle;` 170 .format(func.name, inNamespace, toolNamespace, name, func.name); 171 } 172 return [middleFunc, implH, implCpp, middleInit, middleH]; 173} 174 175function getToolNamespace(inNamespace) { 176 let index = inNamespace.lastIndexOf('::'); 177 let toolNamespace; 178 if (index > 0) { 179 let bodyTmp = inNamespace.substring(0, index); 180 let index2 = bodyTmp.lastIndexOf('::'); 181 if (index2 > 0 && index2 < index) { 182 toolNamespace = inNamespace.substring(index2 + 2, index) + '_interface::'; 183 } else { 184 toolNamespace = bodyTmp + '_interface::'; 185 } 186 } else { 187 toolNamespace = inNamespace + '_interface::'; 188 } 189 return toolNamespace; 190} 191 192module.exports = { 193 generateClass 194};