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 { InterfaceList, getArrayType, getArrayTypeTwo, NumberIncrease, 16 enumIndex, isEnum, EnumValueType, getMapType, getLogErrInfo, 17 EnumList, getUnionType, TypeList, CallFunctionList, isFuncType, isArrowFunc } = require('../tools/common'); 18const re = require('../tools/re'); 19const { NapiLog } = require('../tools/NapiLog'); 20const { getConstNum } = require('../tools/tool'); 21 22class LenIncrease { } 23LenIncrease.LEN_TO = 1; 24LenIncrease.Reset = function () { 25 LenIncrease.LEN_TO = 1; 26}; 27LenIncrease.getAndIncrease = function () { 28 return LenIncrease.LEN_TO++; 29}; 30 31function getValueProperty(napiVn, name) { 32 return 'pxt->GetValueProperty(%s, "%s")'.format(napiVn, name); 33} 34 35function getCType(type) { 36 if (type === 'boolean') { 37 return 'bool'; 38 } else if (type === 'string') { 39 return 'std::string'; 40 } else if (type.substring(0, 6) === 'Array<' || type.substring(type.length - 2) === '[]') { 41 return 'std::vector<%s>'.format(getArrayTypeTemplete(type)); 42 } else if (type.substring(0, 4) === 'Map<' || type.indexOf('{[key:') === 0) { 43 return getMapCType(type); 44 } else { 45 return type; 46 } 47} 48 49function getMapCType(type) { 50 let mapType = getMapType(type); 51 let mapTypeString = ''; 52 53 if (mapType[1] !== undefined && mapType[2] === undefined) { 54 if (mapType[1] === 'string') { mapTypeString = 'std::string' } 55 else if (mapType[1].substring(0, 12) === 'NUMBER_TYPE_') { mapTypeString = mapType[1] } 56 else if (mapType[1] === 'boolean') { mapTypeString = 'bool' } 57 else if (mapType[1] === 'any') { mapTypeString = 'std::any' } 58 else if (mapType[1] !== null) { mapTypeString = mapType[1] } 59 } else if (mapType[2] !== undefined) { 60 if (mapType[2] === 'string') { 61 mapTypeString = 'std::map<std::string, std::string>'; 62 } 63 else if (mapType[2].substring(0, 12) === 'NUMBER_TYPE_') { 64 mapTypeString = 'std::map<std::string, %s>'.format(mapType[2]); 65 } 66 else if (mapType[2] === 'boolean') { mapTypeString = 'std::map<std::string, bool>' } 67 } else if (mapType[3] !== undefined) { 68 if (mapType[3] === 'string') { mapTypeString = 'std::vector<std::string>' } 69 else if (mapType[3].substring(0, 12) === 'NUMBER_TYPE_') { 70 mapTypeString = 'std::vector<%s>'.format(mapType[3]); 71 } 72 else if (mapType[3] === 'boolean') { mapTypeString = 'std::vector<bool>' } 73 } 74 return 'std::map<std::string, %s>'.format(mapTypeString); 75} 76 77function jsToC(dest, napiVn, type, enumType = 0, optional) { 78 if (type.indexOf('|') >= 0) { 79 return unionTempleteFunc(dest, napiVn, type, optional); 80 } else if (type === 'string') { 81 let verifyEnumValue = getVeriyEnumValue(enumType, dest); 82 83 if (napiVn.indexOf('GetValueProperty') >= 0) { 84 let lt = LenIncrease.getAndIncrease(); 85 return `napi_value tnv%d = %s;\n if (tnv%d != nullptr) {pxt->SwapJs2CUtf8(tnv%d, %s);}\n` 86 .format(lt, napiVn, lt, lt, dest); 87 } else { 88 return 'pxt->SwapJs2CUtf8(%s, %s);'.format(napiVn, dest) + verifyEnumValue; 89 } 90 } else if (type.substring(type.length - 2) === '[]') { 91 return arrTemplete(dest, napiVn, type); 92 } else if (type.substring(0, 12) === 'NUMBER_TYPE_') { 93 return numTempleteFunc(enumType, napiVn, type, dest); 94 } else if (InterfaceList.getValue(type)) { 95 return interfaceTempleteFunc(type, napiVn, dest); 96 } else if (TypeList.getValue(type)) { 97 return typeTempleteFunc(type, dest, napiVn); 98 } else if (EnumList.getValue(type)) { 99 return jsToCEnum(type, dest, napiVn); 100 } else if (type.indexOf('Array<') === 0) { 101 return arrTemplete(dest, napiVn, type); 102 } else if (type === 'boolean') { 103 return `BOOLEAN_JS_2_C(%s, %s, %s);\n`.format(napiVn, 'bool', dest); 104 } else if (type.substring(0, 4) === 'Map<' || type.substring(0, 6) === '{[key:') { 105 return mapTempleteFunc(dest, napiVn, type); 106 } else if (type === 'any') { 107 return anyTempleteFunc(dest, napiVn, type); 108 } else if (type === 'Object' || type === 'object') { 109 return objectTempleteFunc(dest, napiVn); 110 } else { 111 NapiLog.logError(`do not support to generate jsToC %s,%s,%s` 112 .format(dest, napiVn, type), getLogErrInfo()); 113 return null; 114 } 115} 116 117function getVeriyEnumValue(enumType, dest) { 118 let verifyEnumValue = ''; 119 let strlt = LenIncrease.getAndIncrease(); 120 if (enumType) { 121 // 对枚举是string的值做校验 122 verifyEnumValue = ` 123 bool isStrValueInMap%s = false; 124 for (const auto& pair : enumMap%s) { 125 const char* charPtr = std::any_cast<const char*>(pair.second); 126 std::string value = charPtr; 127 if (value == %s) { 128 isStrValueInMap%s = true; 129 break; 130 } 131 } 132 if (!isStrValueInMap%s) { 133 napi_throw_error(env, nullptr, "enum value is wrong!"); 134 return nullptr; 135 }`.format(strlt, enumType, dest, strlt, strlt); 136 } 137 return verifyEnumValue; 138} 139 140function interfaceTempleteFunc(type, napiVn, dest) { 141 let tt = ''; 142 let ifl = InterfaceList.getValue(type); 143 for (let i in ifl) { 144 let name2 = ifl[i].name; 145 let type2 = ifl[i].type; 146 let optional2 = ifl[i].optional; 147 if (name2 === undefined || type2 === undefined) { 148 NapiLog.logError(`interfaceTempleteFunc: name2 or type2 is undefined!`); 149 return tt; 150 } else if (optional2 && type2.indexOf('|') < 0) { 151 let optType2 = getCType(type2); 152 tt += ` if (pxt->GetProperty(%s, "%s")) {\n `.format(napiVn, name2); 153 tt += ` %s %s_tmp;\n`.format(optType2, name2); 154 tt += jsToC('%s'.format('%s_tmp'.format(name2)), getValueProperty(napiVn, name2), type2); 155 tt += ` %s.%s.emplace(%s_tmp);\n`.format(dest, name2, name2); 156 tt += ` }\n`; 157 } else if (optional2 && type2.indexOf('|') >= 0) { 158 tt += ` if (pxt->GetProperty(%s, "%s")) {\n `.format(napiVn, name2); 159 tt += jsToC('%s.%s'.format(dest, name2), getValueProperty(napiVn, name2), type2, 0, optional2); 160 tt += ` }\n`; 161 } else { 162 tt += jsToC('%s.%s'.format(dest, name2), getValueProperty(napiVn, name2), type2); 163 } 164 } 165 return tt; 166} 167 168function typeTempleteFunc(type, dest, napiVn) { 169 let tt = ''; 170 let ifl = TypeList.getValue(type); 171 if (typeof (ifl) === 'object') { 172 for (let i in ifl) { 173 let name2 = ifl[i].name; 174 let type2 = ifl[i].type; 175 let optional2 = ifl[i].optional; 176 if (optional2 && type2.indexOf('|') < 0) { 177 let optType2 = getCType(type2); 178 tt += ` if (pxt->GetProperty(%s, "%s")) {\n `.format(napiVn, name2); 179 tt += ` %s %s_tmp;\n`.format(optType2, name2); 180 tt += jsToC('%s'.format('%s_tmp'.format(name2)), getValueProperty(napiVn, name2), type2); 181 tt += ` %s.%s.emplace(%s_tmp);\n`.format(dest, name2, name2); 182 tt += ` }\n`; 183 } else if (optional2 && type2.indexOf('|') >= 0) { 184 tt += ` if (pxt->GetProperty(%s, "%s")) {\n `.format(napiVn, name2); 185 tt += jsToC('%s.%s'.format(dest, name2), getValueProperty(napiVn, name2), type2, 0, optional2); 186 tt += ` }\n`; 187 } else { 188 tt += jsToC('%s.%s'.format(dest, name2), getValueProperty(napiVn, name2), type2); 189 } 190 } 191 } else { 192 tt += jsToC(dest, napiVn, ifl); 193 } 194 return tt; 195} 196 197function unionTempleteFunc(dest, napiVn, type, optional) { 198 let unionType = getUnionType(type); 199 let unionTypeString = ''; 200 let typeStr = 'type'; 201 if (optional) { 202 typeStr = 'type.value()'; 203 unionTypeString += '%s_type.emplace(pxt->GetUnionType(%s));\n'.format(dest, napiVn); 204 } else { 205 unionTypeString += '%s_type = pxt->GetUnionType(%s);\n'.format(dest, napiVn); 206 } 207 for (let i = 0; i < unionType.length; i++) { 208 if (unionType[i] === 'string') { 209 unionTypeString += `if (%s_%s == "string") { 210 std::string union_string; 211 %s 212 %s 213 }\n`.format(dest, typeStr, jsToC('union_string', napiVn, unionType[i]), 214 optional ? dest + '.emplace(union_string);' : dest + ' = union_string;'); 215 } else if (unionType[i].substring(0, 12) === 'NUMBER_TYPE_') { 216 unionTypeString += `if (%s_%s == "number") { 217 std::uint32_t union_number; 218 %s 219 %s 220 }\n`.format(dest, typeStr, jsToC('union_number', napiVn, unionType[i]), 221 optional ? dest + '.emplace(union_number);' : dest + ' = union_number;'); 222 } else if (unionType[i] === 'boolean') { 223 unionTypeString += `if (%s_%s == "boolean") { 224 bool union_boolean; 225 %s 226 %s 227 }\n`.format(dest, typeStr, jsToC('union_boolean', napiVn, unionType[i]), 228 optional ? dest + '.emplace(union_boolean);' : dest + ' = union_boolean;'); 229 } 230 } 231 return unionTypeString; 232} 233 234function jsToCEnum(type, dest, napiVn) { 235 let tt = ''; 236 let ifl = EnumList.getValue(type); 237 let type2 = ''; 238 if (ifl && ifl.length > 0) { 239 type2 = ifl[0].type; 240 } else { 241 return null; 242 } 243 tt += jsToC('%s'.format(dest), napiVn, type2, type); 244 return tt; 245} 246 247function getArrayTypeTemplete(type) { 248 let arrayType; 249 if (type.substring(type.length - 2) === '[]') { 250 arrayType = getArrayTypeTwo(type); 251 } else { 252 arrayType = getArrayType(type); 253 } 254 if (arrayType === 'string') { 255 arrayType = 'std::string'; 256 } else if (arrayType === 'boolean') { 257 arrayType = 'bool'; 258 } else if (arrayType === 'any') { 259 arrayType = 'any'; 260 } else if (arrayType === '[key:string]:string' || arrayType === 'Map<string,string>') { 261 arrayType = 'std::map<std::string, std::string>'; 262 } else if (arrayType.substring(0, arrayType.lastIndexOf('_') + 1) === '[key:string]:NUMBER_TYPE_' || 263 arrayType.substring(0, arrayType.lastIndexOf('_') + 1) === 'Map<string,NUMBER_TYPE_>') { 264 let len = arrayType.length; 265 let num = arrayType.substring(arrayType.lastIndexOf('_') + 1, len); 266 arrayType = 'std::map<std::string, NUMBER_TYPE_%s>'.format(num); 267 } else if (arrayType === '[key:string]:boolean' || arrayType === 'Map<string,boolean>') { 268 arrayType = 'std::map<std::string, bool>'; 269 } else if (arrayType.substring(0, 14) === '[key:string]:') { 270 let valueType = arrayType.substring(14, arrayType.length); 271 arrayType = 'std::map<std::string, %s>'.format(valueType); 272 } else if (arrayType.substring(0, 11) === 'Map<string,') { 273 let valueType = arrayType.substring(11, arrayType.length - 1); 274 arrayType = 'std::map<std::string, %s>'.format(valueType); 275 } 276 return arrayType; 277} 278 279function arrTemplete(dest, napiVn, type) { 280 let lt = LenIncrease.getAndIncrease(); 281 let arrayType = getArrayTypeTemplete(type); 282 if (arrayType === 'any') { 283 return anyArrayTempleteFunc(dest, napiVn); 284 } 285 let arrTemplete = `\ 286 uint32_t len[replace_lt] = pxt->GetArrayLength(%s); 287 for (uint32_t i[replace_lt] = 0; i[replace_lt] < len[replace_lt]; i[replace_lt]++) { 288 %s tt[replace_lt]; 289 [replace_swap] 290 %s.push_back(tt[replace_lt]); 291 }\n`.format(napiVn, arrayType === 'boolean' ? 'bool' : arrayType, dest); 292 293 let arrMapTemplete = `\ 294 uint32_t len[replace_lt] = pxt->GetArrayLength(%s); 295 for (uint32_t i[replace_lt] = 0; i[replace_lt] < len[replace_lt]; i[replace_lt]++) { 296 %s tt[replace_lt]; 297 napi_value mapPara = pxt->GetArrayElement(pxt->GetArgv(XNapiTool::ZERO), i[replace_lt]); 298 uint32_t len2 = pxt->GetMapLength(mapPara); 299 for (uint32_t i2 = 0; i2 < len2; i2++) { 300 std::string ttName; 301 pxt->SwapJs2CUtf8(pxt->GetMapElementName(mapPara, i2), ttName); 302 napi_value mapValue = pxt->GetMapElementValue(mapPara, ttName.c_str()); 303 [code_gen] 304 tt[replace_lt].insert(std::make_pair(ttName, ttValue)); 305 } 306 %s.push_back(tt[replace_lt]); 307 }\n`.format(napiVn, arrayType, dest); 308 arrTemplete = arrTemplete.replaceAll('[replace_lt]', lt); 309 310 let str = 'std::map<std::string,'; 311 let strLen = str.length; 312 if (arrayType.substring(0, strLen) === 'std::map<std::string,') { 313 let codegen = getMapValueCode(arrayType); 314 if (codegen === null) { 315 return arrMapTemplete; 316 } 317 arrMapTemplete = arrMapTemplete.replaceAll('[replace_lt]', lt); 318 arrMapTemplete = arrMapTemplete.replaceAll('[code_gen]', codegen); 319 return arrMapTemplete; 320 } else { 321 arrTemplete = getArrTempletereplaceSwap(arrTemplete, arrayType, napiVn, lt); 322 } 323 return arrTemplete; 324} 325 326function numTempleteFunc(enumType, napiVn, type, dest) { 327 if (enumType) { 328 let strlt = LenIncrease.getAndIncrease(); 329 // 对传入的枚举值做校验 330 let verifyEnumValue = ` 331 bool isValueInMap%s = false; 332 for (const auto& pair : enumMap%s) { 333 int value = std::any_cast<int>(pair.second); 334 if (value == (int)%s) { 335 isValueInMap%s = true; 336 break; 337 } 338 } 339 if (!isValueInMap%s) { 340 napi_throw_error(env, nullptr, "enum value is wrong!"); 341 return nullptr; 342 }`.format(strlt, enumType, dest, strlt, strlt); 343 if (napiVn.indexOf('GetValueProperty') >= 0) { 344 let lt = LenIncrease.getAndIncrease(); 345 return `napi_value tnv%d = %s;\n if (tnv%d != nullptr) {NUMBER_JS_2_C_ENUM(tnv%d, %s, %s, %s);}\n` 346 .format(lt, napiVn, lt, lt, type, dest, enumType) + verifyEnumValue; 347 } else { 348 return `NUMBER_JS_2_C_ENUM(%s, %s, %s, %s);`.format(napiVn, type, dest, enumType) + verifyEnumValue; 349 } 350 351 } else { 352 if (napiVn.indexOf('GetValueProperty') >= 0) { 353 let lt = LenIncrease.getAndIncrease(); 354 return `napi_value tnv%d = %s;\n if (tnv%d != nullptr) {NUMBER_JS_2_C(tnv%d, %s, %s);}\n` 355 .format(lt, napiVn, lt, lt, type, dest); 356 } else { 357 return `NUMBER_JS_2_C(%s, %s, %s);`.format(napiVn, type, dest); 358 } 359 } 360} 361 362function getMapValueCode(arrayType) { 363 let valueTypeOut = arrayType.substring(22, arrayType.length - 1); 364 let strTypeOut = '%s'.format(valueTypeOut); 365 let codegen; 366 if (strTypeOut === 'std::string') { 367 codegen = '\ 368 std::string ttValue;\n\ 369 pxt->SwapJs2CUtf8(mapValue, ttValue);'; 370 } else if (strTypeOut === 'bool') { 371 codegen = '\ 372 bool ttValue;\n\ 373 ttValue = pxt->SwapJs2CBool(mapValue);'; 374 } else if (strTypeOut.substr(0, 12) === 'NUMBER_TYPE_') { 375 codegen = '\ 376 %s ttValue;\n\ 377 NUMBER_JS_2_C(mapValue, %s, ttValue);'.format(strTypeOut, strTypeOut); 378 } 379 return codegen; 380} 381 382function getArrTempletereplaceSwap(arrTemplete, arrayType, napiVn, lt) { 383 if (arrayType.substring(0, 12) === 'NUMBER_TYPE_') { 384 arrTemplete = arrTemplete.replaceAll('[replace_swap]', 385 'NUMBER_JS_2_C(pxt->GetArrayElement(%s, i%d), %s, tt%d);'.format(napiVn, lt, arrayType, lt)); 386 } else if (arrayType === 'std::string') { 387 arrTemplete = arrTemplete.replaceAll('[replace_swap]', 388 'pxt->SwapJs2CUtf8(pxt->GetArrayElement(%s, i%d), tt%d);'.format(napiVn, lt, lt)); 389 } else if (InterfaceList.getValue(arrayType)) { 390 arrTemplete = arrTemplete.replaceAll('[replace_swap]', 391 jsToC('tt' + lt, 'pxt->GetArrayElement(%s, i%d)'.format(napiVn, lt), arrayType)); 392 } else if (arrayType === 'bool') { 393 arrTemplete = arrTemplete.replaceAll('[replace_swap]', 394 'tt%d = pxt->SwapJs2CBool(pxt->GetArrayElement(%s, i%d));'.format(lt, napiVn, lt)); 395 } 396 return arrTemplete; 397} 398function getMapValueType(strLen, keyType, arrayType) { 399 let valueTypeIn; 400 if (keyType === '[key:string]:') { 401 valueTypeIn = arrayType.substring(strLen, arrayType.length); 402 } else if (keyType === 'Map<string,') { 403 valueTypeIn = arrayType.substring(strLen, arrayType.length - 1); 404 } 405 406 let mapValueType; 407 if (valueTypeIn === 'string') { 408 mapValueType = 'std::string'; 409 } else if (valueTypeIn === 'boolean') { 410 mapValueType = 'bool'; 411 } else { 412 mapValueType = valueTypeIn; 413 } 414 return mapValueType; 415} 416 417function getMapKeyLen(arrayType) { 418 let strLen; 419 if (arrayType.substring(0, 13) === '[key:string]:') { 420 strLen = '[key:string]:'.length; 421 } else if (arrayType.substring(0, 10) === 'Map<string') { 422 strLen = 'Map<string,'.length; 423 } 424 return strLen; 425} 426 427function paramGenerateArray(p, funcValue, param) { 428 let type = funcValue.type; 429 let name = funcValue.name; 430 let inParamName = funcValue.optional ? '(*vio->in' + p + ')' : 'vio->in' + p; 431 let modifiers = funcValue.optional ? '* ' : '&'; 432 if (type.substring(type.length - 2) === '[]') { 433 let arrayType = getArrayTypeTwo(type); 434 if (arrayType === 'string') { 435 arrayType = 'std::string'; 436 } 437 if (arrayType === 'boolean') { 438 arrayType = 'bool'; 439 } 440 if (arrayType === 'any') { 441 paramGenerateAnyArray(p, name, type, param); 442 return; 443 } 444 param.valueIn += funcValue.optional ? '\n std::vector<%s>* in%d = nullptr;'.format(arrayType, p) 445 : '\n std::vector<%s> in%d;'.format(arrayType, p); 446 param.valueCheckout += jsToC(inParamName, 'pxt->GetArgv(%d)'.format(getConstNum(p)), type); 447 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 448 param.valueDefine += '%sstd::vector<%s>%s%s'.format(param.valueDefine.length > 0 ? ', ' 449 : '', arrayType, modifiers, name); 450 } else if (type.substring(0, 6) === 'Array<') { 451 let arrayType = getArrayType(type); 452 let strLen = getMapKeyLen(arrayType); 453 let keyType = arrayType.substring(0, strLen); 454 if (arrayType === 'string') { 455 arrayType = 'std::string'; 456 } else if (arrayType === 'boolean') { 457 arrayType = 'bool'; 458 } else if (arrayType === 'any') { 459 paramGenerateAnyArray(p, name, type, param); 460 return; 461 } 462 else if (checkIsMap(keyType)) { 463 let mapValueType = getMapValueType(strLen, keyType, arrayType); 464 arrayType = 'std::map<std::string, %s>'.format(mapValueType); 465 } 466 paramGenArray(param, funcValue, arrayType, p, inParamName, type, modifiers, name); 467 } else { 468 NapiLog.logError('The current version do not support to this param to generate :', name, 469 'type :', type, getLogErrInfo()); 470 return; 471 } 472} 473 474function paramGenArray(param, funcValue, arrayType, p, inParamName, type, modifiers, name) { 475 param.valueIn += funcValue.optional ? '\n std::vector<%s>* in%d = nullptr;'.format(arrayType, p) 476 : '\n std::vector<%s> in%d;'.format(arrayType, p); 477 let arrValueCheckout = jsToC(inParamName, 'pxt->GetArgv(%d)'.format(getConstNum(p)), type); 478 arrValueCheckout = getFuncOptionalValue(funcValue, arrValueCheckout, p, arrayType, param); 479 param.valueCheckout += arrValueCheckout; 480 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 481 param.valueDefine += '%sstd::vector<%s>%s%s'.format(param.valueDefine.length > 0 ? ', ' 482 : '', arrayType, modifiers, name); 483} 484 485function checkIsMap(keyType) { 486 return keyType === '[key:string]:' || keyType === 'Map<string,'; 487} 488 489function getFuncOptionalValue(funcValue, arrValueCheckout, p, arrayType, param) { 490 if (funcValue.optional) { 491 arrValueCheckout = 'if (pxt->GetArgc() > %s) {\n vio->in%d = new std::vector<%s>;\n' 492 .format(getConstNum(p), p, arrayType) + arrValueCheckout + ' }\n'; 493 param.optionalParamDestory += 'C_DELETE(vio->in%d);\n '.format(p); 494 } 495 return arrValueCheckout; 496} 497 498function paramGenerateAny(p, name, type, param) { 499 param.valueIn += `\n std::any in%d; 500 std::string in%d_type;`.format(p, p); 501 param.valueCheckout += jsToC('vio->in' + p, 'pxt->GetArgv(%d)'.format(getConstNum(p)), type); 502 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 503 param.valueDefine += '%sstd::any &%s'.format(param.valueDefine.length > 0 ? ', ' : '', name); 504} 505 506function paramGenerateAnyArray(p, name, type, param) { 507 param.valueIn += `\n std::any in%d; 508 std::string in%d_type;`.format(p, p); 509 param.valueCheckout += jsToC('vio->in' + p, 'pxt->GetArgv(%d)'.format(getConstNum(p)), type); 510 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 511 param.valueDefine += '%sstd::any &%s'.format(param.valueDefine.length > 0 ? ', ' : '', name); 512} 513 514function paramGenerateEnum(data, funcValue, param, p) { 515 let index = enumIndex(funcValue.type, data); 516 if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_NUMBER) { 517 funcValue.type = 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease(); 518 } else if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) { 519 funcValue.type = 'string'; 520 } else { 521 NapiLog.logError(`paramGenerate is not support`, getLogErrInfo()); 522 return; 523 } 524 paramGenerate(p, funcValue, param, data); 525} 526 527function paramGenerateMap(funcValue, param, p) { 528 let type = funcValue.type; 529 let name = funcValue.name; 530 let mapType = getMapType(type); 531 let mapTypeString; 532 if (mapType[1] !== undefined && mapType[2] === undefined) { 533 if (mapType[1] === 'string') { mapTypeString = 'std::string' } 534 else if (mapType[1].substring(0, 12) === 'NUMBER_TYPE_') { mapTypeString = mapType[1] } 535 else if (mapType[1] === 'boolean') { mapTypeString = 'bool' } 536 else if (mapType[1] === 'any') { mapTypeString = 'std::any' } 537 else { mapTypeString = mapType[1] } 538 } 539 else if (mapType[2] !== undefined) { 540 if (mapType[2] === 'string') { mapTypeString = 'std::map<std::string, std::string>' } 541 else if (mapType[2].substring(0, 12) === 'NUMBER_TYPE_') { 'std::map<std::string, ' + mapType[2] + '>' } 542 else if (mapType[2] === 'boolean') { mapTypeString = 'std::map<std::string, bool>' } 543 } 544 else if (mapType[3] !== undefined) { 545 if (mapType[3] === 'string') { mapTypeString = 'std::vector<std::string>' } 546 else if (mapType[3].substring(0, 12) === 'NUMBER_TYPE_') { mapTypeString = 'std::vector<' + mapType[3] + '>' } 547 else if (mapType[3] === 'boolean') { mapTypeString = 'std::vector<bool>' } 548 } 549 paramGenerateMap2(funcValue, param, p, mapType, mapTypeString, name); 550} 551 552function paramGenerateMap2(funcValue, param, p, mapType, mapTypeString, name) { 553 let inParamName = funcValue.optional ? '(*vio->in' + p + ')' : 'vio->in' + p; 554 let modifiers = funcValue.optional ? '*' : '&'; 555 if (mapType[1] === 'any') { 556 param.valueIn += funcValue.optional ? `\n std::map<std::string, %s>* in%d = nullptr; 557 std::string in%d_type;`.format(mapTypeString, p, p) 558 : `\n std::map<std::string, %s> in%d; 559 std::string in%d_type;`.format(mapTypeString, p, p); 560 } else { 561 param.valueIn += funcValue.optional ? '\n std::map<std::string, %s>* in%d = nullptr;' 562 .format(mapTypeString, p) 563 : '\n std::map<std::string, %s> in%d;'.format(mapTypeString, p); 564 } 565 param.valueCheckout += getValueCheckout(funcValue, param, inParamName, p, 566 'std::map<std::string, %s>'.format(mapTypeString)); 567 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 568 param.valueDefine += '%sstd::map<std::string, %s>%s %s' 569 .format(param.valueDefine.length > 0 ? ', ' : '', mapTypeString, modifiers, name); 570} 571 572function mapTempleteFunc(dest, napiVn, type) { 573 let mapType = getMapType(type); 574 let lt = LenIncrease.getAndIncrease(); 575 let mapTemplete = ''; 576 if (mapType[1] !== undefined && mapType[2] === undefined) { 577 mapTemplete = mapValue(mapType, napiVn, dest, lt); 578 } 579 else if (mapType[2] !== undefined) { 580 mapTemplete = mapMap(mapType, napiVn, dest, lt); 581 } 582 else if (mapType[3] !== undefined) { 583 mapTemplete = mapArray(mapType, napiVn, dest, lt); 584 } 585 return mapTemplete; 586} 587 588function anyTempleteFunc(dest) { 589 let anyTemplete = `%s_type = pxt->GetAnyType(pxt->GetArgv(XNapiTool::ZERO)); 590 pxt->SetAnyValue(%s_type, pxt->GetArgv(XNapiTool::ZERO), %s);\n` 591 .format(dest, dest, dest); 592 593 return anyTemplete; 594} 595 596function anyArrayTempleteFunc(dest, napiVn) { 597 let anyArrayTemplete = `%s_type = pxt->GetAnyArrayType(%s); 598 pxt->SetAnyValue(%s_type, %s, %s);\n` 599 .format(dest, napiVn, dest, napiVn, dest); 600 601 return anyArrayTemplete; 602} 603 604let mapValueTemplete = `\ 605uint32_t len[replace_lt] = pxt->GetMapLength(%s); 606for (uint32_t i[replace_lt] = 0; i[replace_lt] < len[replace_lt]; i[replace_lt]++) { 607 std::string tt[replace_lt]; 608 %s tt[replace_lt+1]; 609 [replace_swap] 610 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 611}`; 612 613function mapInterface(mapTypeString, mapTemplete, napiVn, lt) { 614 let interfaceValue = InterfaceList.getValue(mapTypeString); 615 let interfaceVarName = ''; 616 let interfaceFun = ''; 617 for (let i = 0; i < interfaceValue.length; i++) { 618 if (interfaceValue[i].type === 'string') { 619 interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name, interfaceValue[i].name); 620 interfaceFun += 621 `pxt->%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(XNapiTool::ZERO), 622 tt%d.c_str()), %sName.c_str()), tt%d.%s);\n` 623 .format('SwapJs2CUtf8', 'GetMapElementValue', 624 lt, interfaceValue[i].name, lt + 1, interfaceValue[i].name); 625 } 626 else if (interfaceValue[i].type.substring(0, 12) === 'NUMBER_TYPE_') { 627 interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name, interfaceValue[i].name); 628 interfaceFun += 629 `%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(XNapiTool::ZERO), 630 tt%d.c_str()), %sName.c_str()), %s, tt%d.%s);\n` 631 .format('NUMBER_JS_2_C', 'GetMapElementValue', lt, interfaceValue[i].name, 632 interfaceValue[i].type, lt + 1, interfaceValue[i].name); 633 } 634 else if (interfaceValue[i].type === 'boolean') { 635 interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name, interfaceValue[i].name); 636 interfaceFun += 637 `tt%d.%s = pxt->%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(XNapiTool::ZERO), 638 tt%d.c_str()), %sName.c_str()));\n` 639 .format(lt + 1, interfaceValue[i].name, 'SwapJs2CBool', 'GetMapElementValue', 640 lt, interfaceValue[i].name); 641 } 642 } 643 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 644 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 645 %d 646 %d`.format(napiVn, lt, lt, interfaceVarName, interfaceFun)); 647 return mapTemplete; 648} 649 650function mapValue(mapType, napiVn, dest, lt) { 651 let mapTypeString; 652 if (mapType[1] === 'string') { mapTypeString = 'std::string' } 653 else if (mapType[1].substring(0, 12) === 'NUMBER_TYPE_') { mapTypeString = mapType[1] } 654 else if (mapType[1] === 'boolean') { mapTypeString = 'bool' } 655 else if (mapType[1] === 'any') { mapTypeString = 'std::any' } 656 else if (mapType[1] !== null) { mapTypeString = mapType[1] } 657 let mapTemplete = mapValueTemplete.format(napiVn, mapTypeString, dest); 658 mapTemplete = mapTemplete.replaceAll('[replace_lt]', lt); 659 mapTemplete = mapTemplete.replaceAll('[replace_lt+1]', lt + 1); 660 if (mapTypeString === 'std::string') { 661 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 662 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 663 pxt->SwapJs2CUtf8(pxt->GetMapElementValue(%s, tt%d.c_str()), tt%d);\n` 664 .format(napiVn, lt, lt, napiVn, lt, lt + 1)); 665 } 666 else if (mapTypeString.substring(0, 12) === 'NUMBER_TYPE_') { 667 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 668 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 669 NUMBER_JS_2_C(pxt->GetMapElementValue(%s, tt%d.c_str()), %s, tt%d);\n` 670 .format(napiVn, lt, lt, napiVn, lt, mapTypeString, lt + 1)); 671 } 672 else if (mapTypeString === 'bool') { 673 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 674 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 675 tt%d = pxt->SwapJs2CBool(pxt->GetMapElementValue(%s, tt%d.c_str()));\n` 676 .format(napiVn, lt, lt, lt + 1, napiVn, lt)); 677 } 678 if (mapTypeString === 'std::any') { 679 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 680 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 681 if (i%d == 0) { 682 %s_type = pxt->GetAnyType(pxt->GetMapElementValue(%s, tt%d.c_str())); 683 } 684 pxt->SetAnyValue(%s_type, pxt->GetMapElementValue(%s, tt%d.c_str()), tt%d);\n` 685 .format(napiVn, lt, lt, lt, dest, napiVn, lt, dest, napiVn, lt, lt + 1)); 686 } 687 else if (InterfaceList.getValue(mapTypeString)) { 688 mapTemplete = mapInterface(mapTypeString, mapTemplete, napiVn, lt); 689 } 690 return mapTemplete; 691} 692 693let mapMapTemplete = `\ 694uint32_t len[replace_lt] = pxt->GetMapLength(%s); 695for (uint32_t i[replace_lt] = 0; i[replace_lt] < len[replace_lt]; i[replace_lt]++) { 696 std::string tt[replace_lt]; 697 std::map<std::string, %s> tt[replace_lt+1]; 698 [replace_swap] 699 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 700}`; 701 702function mapMapString(mapTemplete, napiVn, lt) { 703 return mapTemplete.replaceAll('[replace_swap]', 704 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 705 uint32_t len%d = pxt->GetMapLength(pxt->GetMapElementValue(%s, tt%d.c_str())); 706 for (uint32_t i%d = 0; i%d < len%d; i%d++) { 707 std::string tt%d; 708 std::string tt%d; 709 pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s, 710 tt%d.c_str()), i%d), tt%d); 711 pxt->SwapJs2CUtf8(pxt->GetMapElementValue(pxt->GetMapElementValue(%s, 712 tt%d.c_str()), tt%d.c_str()), tt%d); 713 tt%d.insert(std::make_pair(tt%d, tt%d)); 714 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, lt + 1, 715 lt + 2, lt + 3, napiVn, lt, lt + 1, lt + 2, napiVn, lt, lt + 2, lt + 3, lt + 1, lt + 2, lt + 3)); 716} 717 718function mapMapBoolean(mapTemplete, napiVn, lt) { 719 return mapTemplete.replaceAll('[replace_swap]', 720 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 721 uint32_t len%d = pxt->GetMapLength(pxt->GetMapElementValue(%s, tt%d.c_str())); 722 for (uint32_t i%d = 0; i%d < len%d; i%d++) { 723 std::string tt%d; 724 bool tt%d; 725 pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s, 726 tt%d.c_str()), i%d), tt%d); 727 tt%d = pxt->%s(pxt->GetMapElementValue(pxt->GetMapElementValue(%s, 728 tt%d.c_str()), tt%d.c_str())); 729 tt%d.insert(std::make_pair(tt%d, tt%d)); 730 }\n`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, lt + 1, 731 lt + 2, lt + 3, napiVn, lt, lt + 1, lt + 2, lt + 3, 'SwapJs2CBool' 732 , napiVn, lt, lt + 2, lt + 1, lt + 2, lt + 3)); 733} 734 735function mapMapNumber(mapTemplete, napiVn, lt, mapTypeString) { 736 return mapTemplete.replaceAll('[replace_swap]', 737 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%d), tt%d); 738 uint32_t len%d = pxt->GetMapLength(pxt->GetMapElementValue(%s, tt%d.c_str())); 739 for (uint32_t i%d = 0; i%d < len%d; i%d++) { 740 std::string tt%d; 741 %s tt%d; 742 pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s, 743 tt%d.c_str()), i%d), tt%d); 744 NUMBER_JS_2_C(pxt->GetMapElementValue(pxt->GetMapElementValue(%s, 745 tt%d.c_str()), tt%d.c_str()), %s, tt%d); 746 tt%d.insert(std::make_pair(tt%d, tt%d)); 747 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, lt + 1, 748 lt + 2, mapTypeString, lt + 3, napiVn, lt, lt + 1, lt + 2, napiVn, lt, lt + 2, 749 mapTypeString, lt + 3, lt + 1, lt + 2, lt + 3)); 750} 751 752function mapMap(mapType, napiVn, dest, lt) { 753 let mapTypeString; 754 if (mapType[2] === 'string') { mapTypeString = 'std::string' } 755 else if (mapType[2].substring(0, 12) === 'NUMBER_TYPE_') { mapTypeString = mapType[2] } 756 else if (mapType[2] === 'boolean') { mapTypeString = 'bool' } 757 let mapTemplete = mapMapTemplete.format(napiVn, mapTypeString, dest); 758 mapTemplete = mapTemplete.replaceAll('[replace_lt]', lt); 759 mapTemplete = mapTemplete.replaceAll('[replace_lt+1]', lt + 1); 760 if (mapType[2] === 'string') { 761 mapTemplete = mapMapString(mapTemplete, napiVn, lt); 762 } 763 else if (mapType[2] === 'boolean') { 764 mapTemplete = mapMapBoolean(mapTemplete, napiVn, lt); 765 } 766 else if (mapType[2].substring(0, 12) === 'NUMBER_TYPE_') { 767 mapTemplete = mapMapNumber(mapTemplete, napiVn, lt, mapTypeString); 768 } 769 return mapTemplete; 770} 771 772let mapArrayTemplete = `\ 773uint32_t len[replace_lt] = pxt->GetMapLength(%s); 774for (uint32_t i[replace_lt] = 0; i[replace_lt] < len[replace_lt]; i[replace_lt]++) { 775 std::string tt[replace_lt]; 776 std::vector<%s> tt[replace_lt+1]; 777 [replace_swap] 778 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 779}`; 780 781function mapArray(mapType, napiVn, dest, lt) { 782 let mapTypeString; 783 if (mapType[3] === 'string') { mapTypeString = 'std::string' } 784 else if (mapType[3].substring(0, 12) === 'NUMBER_TYPE_') { mapTypeString = mapType[3] } 785 else if (mapType[3] === 'boolean') { mapTypeString = 'bool' } 786 let mapTemplete = mapArrayTemplete.format(napiVn, mapTypeString, dest); 787 mapTemplete = mapTemplete.replaceAll('[replace_lt]', lt); 788 mapTemplete = mapTemplete.replaceAll('[replace_lt+1]', lt + 1); 789 if (mapType[3] === 'string') { 790 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 791 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%s), tt%d); 792 uint32_t len%s = pxt->GetArrayLength(pxt->GetMapElementValue(%s, tt%d.c_str())); 793 for (uint32_t i%d = 0; i%d < len%d; i%d++) { 794 std::string tt%d; 795 pxt->SwapJs2CUtf8(pxt->GetArrayElement(pxt->GetMapElementValue(%s, 796 tt%d.c_str()), i%d), tt%d); 797 tt%d.push_back(tt%d); 798 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, 799 lt + 1, lt + 2, napiVn, lt, lt + 1, lt + 2, lt + 1, lt + 2)); 800 } 801 else if (mapType[3] === 'boolean') { 802 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 803 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%s), tt%d); 804 uint32_t len%s = pxt->GetArrayLength(pxt->GetMapElementValue(%s, tt%d.c_str())); 805 for (uint32_t i%d = 0; i%d < len%d; i%d++) { 806 bool tt%d; 807 tt%d = pxt->SwapJs2CBool(pxt->GetArrayElement(pxt->GetMapElementValue(%s, 808 tt%d.c_str()), i%d)); 809 tt%d.push_back(tt%d); 810 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, 811 lt + 1, lt + 2, lt + 2, napiVn, lt, lt, lt + 1, lt + 2)); 812 } 813 else if (mapType[3].substring(0, 12) === 'NUMBER_TYPE_') { 814 mapTemplete = mapTemplete.replaceAll('[replace_swap]', 815 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i%s), tt%d); 816 uint32_t len%s = pxt->GetArrayLength(pxt->GetMapElementValue(%s, tt%d.c_str())); 817 for (uint32_t i%d = 0; i%d < len%d; i%d++) { 818 %s tt%d; 819 NUMBER_JS_2_C(pxt->GetArrayElement(pxt->GetMapElementValue(%s, 820 tt%d.c_str()), i%d), %s, tt%d); 821 tt%d.push_back(tt%d); 822 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, 823 lt + 1, mapTypeString, lt + 2, napiVn, lt, lt + 1, mapTypeString, lt + 2, lt + 1, lt + 2)); 824 } 825 return mapTemplete; 826} 827 828function getCBparaTypeForArrow(type) { 829 let cbParamType; 830 const typeSplits = type.split('=>', 2); 831 let callbackParams = typeSplits[0]; 832 let returnType = typeSplits[1]; 833 callbackParams = callbackParams.substring(1, callbackParams.length - 1); // 去掉参数列表两侧的小括号 834 if (callbackParams.length <= 0) { //无参 835 cbParamType = 'void'; 836 } 837 838 if (callbackParams.indexOf(',') >= 0) { // 多个参数,进行分割 839 callbackParams = callbackParams.split(','); 840 for (let i = 0; i < callbackParams.length; i++) { 841 NapiLog.logInfo('muilti paramets'); 842 } 843 } else { // 一个参数 844 let params = callbackParams.split(':', 2); 845 cbParamType = params[1]; 846 } 847 return [cbParamType, returnType]; 848} 849 850function matchCBParamType(cbParamType, type) { 851 let arrayType = re.match('(Async)*Callback<(Array<([a-zA-Z_0-9]+)>)>', type); 852 if (arrayType) { 853 cbParamType = re.getReg(type, arrayType.regs[2]); 854 } 855 856 let arrayType2 = re.match('(Async)*Callback<(([a-zA-Z_0-9]+)\\[\\])>', type); 857 if (arrayType2) { 858 cbParamType = re.getReg(type, arrayType2.regs[2]); 859 } 860 861 let tt = re.match('(Async)*Callback<([a-zA-Z_0-9]+)>', type); 862 if (tt) { 863 cbParamType = re.getReg(type, tt.regs[2]); 864 } 865 return cbParamType; 866} 867 868function paramGenerateCallBack(data, funcValue, param, p) { 869 let cbParamType; 870 let returnType = 'void'; 871 872 let type = funcValue.type; 873 874 if (isFuncType(type)) { 875 cbParamType = 'void'; 876 } 877 cbParamType = matchCBParamType(cbParamType, type); 878 879 if (isEnum(cbParamType, data)) { 880 let index = enumIndex(cbParamType, data); 881 if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_NUMBER) { 882 cbParamType = 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease(); 883 } else if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) { 884 cbParamType = 'string'; 885 } else { 886 NapiLog.logError(`paramGenerate is not support`, getLogErrInfo()); 887 return; 888 } 889 } 890 891 param.callback = { 892 // function类型参数,按照空参数、空返回值回调处理 () => void {} 893 type: cbParamType, 894 offset: p, 895 returnType: returnType, 896 optional: funcValue.optional, 897 isAsync: type.indexOf('AsyncCallback') >= 0 898 }; 899} 900 901function paramGenerateArrowCallBack(funcValue, param, p, onFlag = false) { 902 let cbParamType; 903 let returnType = 'void'; 904 905 let type = funcValue.type; 906 let cbParamList = []; 907 908 if (CallFunctionList.getValue(type)) { 909 // callFunction => 函数参数处理 910 let funcBody = CallFunctionList.getValue(type)[0]; // 取出回调方法参数 911 returnType = CallFunctionList.getValue(type)[1]; 912 cbParamType = type; 913 for (let i in funcBody) { 914 let cbParam = { 915 name: funcBody[i].name, 916 type: funcBody[i].type 917 }; 918 cbParamList[i] = cbParam; 919 } 920 } 921 922 param.callback = { 923 // function类型参数,按照空参数、空返回值回调处理 () => void {} 924 type: cbParamType, 925 offset: p, 926 returnType: returnType, 927 optional: funcValue.optional, 928 isArrowFuncFlag: true, 929 arrowFuncParamList:cbParamList, 930 onFlag: onFlag, 931 isAsync: type.indexOf('AsyncCallback') >= 0 932 }; 933} 934 935function isArrayType(type) { 936 if (type.substring(type.length - 2) === '[]' || type.substring(0, 6) === 'Array<') { 937 return true; 938 } 939 return false; 940} 941 942function getValueCheckout(funcValue, param, inParamName, p, cType) { 943 let enumType = 0; 944 if (funcValue.type !== funcValue.realType) { 945 enumType = funcValue.realType; 946 } 947 let valueCheckout = jsToC(inParamName, 'pxt->GetArgv(%d)'.format(getConstNum(p)), funcValue.type, enumType) + '\n '; 948 if (funcValue.optional) { 949 valueCheckout = 'if (pxt->GetArgc() > %d) {\n vio->in%d = new %s;\n ' 950 .format(getConstNum(p), p, cType) + valueCheckout + '}\n '; 951 param.optionalParamDestory += 'C_DELETE(vio->in%d);\n '.format(p); 952 } 953 return valueCheckout; 954} 955 956function paramGenerateUnion(type, param, p, name) { 957 param.valueIn += `\n std::any in%d; 958 std::string in%d_type;`.format(p, p); 959 param.valueCheckout += jsToC('vio->in' + p, 'pxt->GetArgv(%d)'.format(getConstNum(p)), type); 960 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 961 param.valueDefine += '%sstd::any &%s'.format(param.valueDefine.length > 0 ? ', ' : '', name); 962} 963 964function isEnumTypeFunc(cType, funcValue) { 965 if (cType !== funcValue.realType && funcValue.type !== funcValue.realType && funcValue.type !== 'string') { 966 return true; 967 } else { 968 return false; 969 } 970} 971 972 973function paramGenerateCommon(p, cType, funcValue, param, modifiers, inParamName) { 974 // string类型和number类型枚举处理时才走该分支 975 if (isEnumTypeFunc(cType, funcValue)) { 976 cType = funcValue.realType; 977 } 978 979 param.valueIn += funcValue.optional ? '\n %s* in%d = nullptr;'.format(cType, p) 980 : '\n %s in%d;'.format(cType, p); 981 if (TypeList.getValue(cType)) { 982 let realType = TypeList.getValue(cType); 983 if (realType.indexOf('|') > 0) { 984 param.valueIn += `\n std::string in%d_type;`.format(p, p); 985 } 986 } 987 param.valueCheckout += getValueCheckout(funcValue, param, inParamName, p, cType); 988 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 989 param.valueDefine += '%s%s%s %s'.format( 990 param.valueDefine.length > 0 ? ', ' : '', cType, modifiers, funcValue.name); 991} 992 993let objectTemplete = `\ 994 uint32_t len[replace_lt] = pxt->GetMapLength(%s); 995 for (uint32_t i[replace_lt] = 0; i[replace_lt] < len[replace_lt]; i[replace_lt]++) { 996 std::string tt[replace_lt]; 997 std::any tt[replace_lt+1]; 998 pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s, i[replace_lt]), tt[replace_lt]); 999 napi_value valueObj = pxt->GetMapElementValue(%s, tt[replace_lt].c_str()); 1000 std::string valueObjType = pxt->GetAnyType(valueObj); 1001 [replace_swap] 1002 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 1003 }\n`; 1004 1005// To avoid function that exceed 50 lines 1006let objectTempleteArrnum = `\ 1007 uint32_t len[replace_lt+1] = pxt->GetArrayLength(valueObj); 1008 std::vector<NUMBER_TYPE_%d> arr; 1009 for(uint32_t i[replace_lt+1] = 0; i[replace_lt+1] < len[replace_lt+1]; i[replace_lt+1]++) { 1010 napi_value arr_value_result; 1011 NUMBER_TYPE_%d tt[replace_lt+2]; 1012 napi_get_element(env, valueObj, i[replace_lt+1], &arr_value_result); 1013 NUMBER_JS_2_C(arr_value_result, NUMBER_TYPE_%d, tt[replace_lt+2]); 1014 arr.push_back(tt[replace_lt+2]); 1015 } 1016 tt[replace_lt+1] = arr; 1017`; 1018 1019let objectTempleteMap = `\ 1020 napi_value obj_name_value; 1021 napi_value obj_name_result; 1022 napi_valuetype obj_name_type; 1023 napi_get_property_names (env, valueObj, &obj_name_value); 1024 uint32_t ret; 1025 napi_get_array_length(env, obj_name_value, &ret); 1026 std::vector<std::any> anyValue; 1027 for(uint32_t i[replace_lt+1] = 0; i[replace_lt+1] < ret; i[replace_lt+1]++) { 1028 napi_get_element (env, obj_name_value, i[replace_lt+1], &obj_name_result); 1029 napi_typeof(env, obj_name_result, &obj_name_type); 1030 if (obj_name_type == napi_string) { 1031 napi_value obj_value; 1032 napi_valuetype obj_value_type; 1033 std::string obj_name_string; 1034 pxt->SwapJs2CUtf8(obj_name_result, obj_name_string); 1035 napi_get_named_property (env, valueObj, obj_name_string.c_str(), &obj_value); 1036 napi_typeof(env, obj_value, &obj_value_type); 1037 std::map<std::string, std::any> anyValueMap; 1038 if (obj_value_type == napi_string) { 1039 std::string tt[replace_lt+2]; 1040 pxt->SwapJs2CUtf8(obj_value, tt[replace_lt+2]); 1041 anyValueMap.insert(std::make_pair(obj_name_string, tt[replace_lt+2])); 1042 anyValue.push_back(anyValueMap); 1043 } else if (obj_value_type == napi_number) { 1044 NUMBER_TYPE_%d tt[replace_lt+2]; 1045 NUMBER_JS_2_C(obj_value, NUMBER_TYPE_%d, tt[replace_lt+2] ); 1046 anyValueMap.insert(std::make_pair(obj_name_string, tt[replace_lt+2])); 1047 anyValue.push_back(anyValueMap); 1048 } else if (obj_value_type == napi_boolean) { 1049 bool tt[replace_lt+2]; 1050 tt[replace_lt+2] = pxt->SwapJs2CBool(obj_value); 1051 anyValueMap.insert(std::make_pair(obj_name_string, tt[replace_lt+2])); 1052 anyValue.push_back(anyValueMap); 1053 } 1054 } 1055 } 1056 tt[replace_lt+1] = anyValue; 1057`; 1058 1059function objectTempleteFunc(dest, napiVn) { 1060 let lt = LenIncrease.getAndIncrease(); 1061 let objTemplete = objectTemplete.format(napiVn, napiVn, napiVn, dest); 1062 1063 objTemplete = objTemplete.replaceAll('[replace_swap]', 1064 `if (valueObjType == "string") { 1065 std::string tt[replace_lt+2]; 1066 pxt->SwapJs2CUtf8(valueObj, tt[replace_lt+2]); 1067 tt[replace_lt+1] = tt[replace_lt+2]; 1068 } else if (valueObjType == "boolean") { 1069 bool tt[replace_lt+2]; 1070 tt[replace_lt+2] = pxt->SwapJs2CBool(valueObj); 1071 tt[replace_lt+1] = tt[replace_lt+2]; 1072 } else if (valueObjType == "number") { 1073 NUMBER_JS_2_C(valueObj, NUMBER_TYPE_%d, tt[replace_lt+1]); 1074 } else if (valueObjType == "arr_string") { 1075 uint32_t len[replace_lt+1] = pxt->GetArrayLength(valueObj); 1076 std::vector<std::string> arr; 1077 for(uint32_t i[replace_lt+1] = 0; i[replace_lt+1] < len[replace_lt+1]; i[replace_lt+1]++) { 1078 napi_value arr_value_result; 1079 napi_get_element(env, valueObj, i[replace_lt+1], &arr_value_result); 1080 std::string tt[replace_lt+2]; 1081 pxt->SwapJs2CUtf8(arr_value_result, tt[replace_lt+2]); 1082 arr.push_back(tt[replace_lt+2]); 1083 } 1084 tt[replace_lt+1] = arr; 1085 } else if (valueObjType == "arr_boolean") { 1086 uint32_t len[replace_lt+1] = pxt->GetArrayLength(valueObj); 1087 std::vector<bool> arr; 1088 for(uint32_t i[replace_lt+1] = 0; i[replace_lt+1] < len[replace_lt+1]; i[replace_lt+1]++) { 1089 napi_value arr_value_result; 1090 napi_get_element(env, valueObj, i[replace_lt+1], &arr_value_result); 1091 bool tt[replace_lt+2]; 1092 tt[replace_lt+2] = pxt->SwapJs2CBool(arr_value_result); 1093 arr.push_back(tt[replace_lt+2]); 1094 } 1095 tt[replace_lt+1] = arr; 1096 } else if (valueObjType == "arr_number") { 1097 [replace_objectTemplete_arrnum] 1098 } else if (valueObjType == "map_string" || valueObjType == "map_number" || valueObjType == "map_boolean") { 1099 [replace_objectTemplete_map] 1100 } 1101 `).format(lt); 1102 objTemplete = objTemplete.replaceAll('[replace_objectTemplete_arrnum]', objectTempleteArrnum.format(lt, lt, lt)); 1103 objTemplete = objTemplete.replaceAll('[replace_objectTemplete_map]', objectTempleteMap.format(lt, lt)); 1104 objTemplete = objTemplete.replaceAll('[replace_lt]', lt); 1105 objTemplete = objTemplete.replaceAll('[replace_lt+1]', lt + 1); 1106 objTemplete = objTemplete.replaceAll('[replace_lt+2]', lt + 2); 1107 return objTemplete; 1108} 1109 1110function paramGenerateObject(p, funcValue, param) { 1111 let type = funcValue.type; 1112 let name = funcValue.name; 1113 let inParamName = funcValue.optional ? '(*vio->in' + p + ')' : 'vio->in' + p; 1114 let modifiers = funcValue.optional ? '* ' : '&'; 1115 1116 let arrayType = 'std::map<std::string, std::any>'; 1117 param.valueIn += funcValue.optional ? '\n %s* in%d = nullptr;'.format(arrayType, p) 1118 : '\n %s in%d;'.format(arrayType, p); 1119 1120 let arrValueCheckout = jsToC(inParamName, 'pxt->GetArgv(%d)'.format(getConstNum(p)), type); 1121 param.valueCheckout += arrValueCheckout; 1122 param.valueFill += '%svio->in%d'.format(param.valueFill.length > 0 ? ', ' : '', p); 1123 param.valueDefine += '%s%s %s%s'.format(param.valueDefine.length > 0 ? ', ' 1124 : '', arrayType, modifiers, name); 1125} 1126 1127function isCallbackFunc(type) { 1128 let callbackFunc = false; 1129 if (type.substring(0, 9) === 'Callback<' || 1130 type.substring(0, 14) === 'AsyncCallback<' || 1131 isFuncType(type)) { 1132 callbackFunc = true; 1133 } 1134 return callbackFunc; 1135} 1136 1137// 函数的参数处理 1138function paramGenerate(p, funcValue, param, data) { 1139 let type = funcValue.type; 1140 let name = funcValue.name; 1141 let inParamName = funcValue.optional ? '(*vio->in' + p + ')' : 'vio->in' + p; 1142 let modifiers = funcValue.optional ? '*' : '&'; 1143 if (type.indexOf('|') >= 0) { 1144 paramGenerateUnion(type, param, p, name); 1145 return; 1146 } else if (type === 'string') { 1147 paramGenerateCommon(p, 'std::string', funcValue, param, modifiers, inParamName); 1148 } else if (type.substring(0, 12) === 'NUMBER_TYPE_' && type.indexOf('[]') < 0) { 1149 paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName); 1150 } else if (InterfaceList.getValue(type)) { 1151 paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName); 1152 } else if (TypeList.getValue(type)) { 1153 paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName); 1154 } else if (isCallbackFunc(type)) { 1155 paramGenerateCallBack(data, funcValue, param, p); 1156 } else if (CallFunctionList.getValue(type)) { 1157 paramGenerateArrowCallBack(funcValue, param, p); 1158 } else if (type === 'boolean') { 1159 paramGenerateCommon(p, 'bool', funcValue, param, modifiers, inParamName); 1160 } else if (isEnum(type, data)) { 1161 paramGenerateEnum(data, funcValue, param, p); 1162 } else if (type.substring(0, 4) === 'Map<' || type.substring(0, 6) === '{[key:') { 1163 paramGenerateMap(funcValue, param, p); 1164 } else if (isArrayType(type)) { 1165 paramGenerateArray(p, funcValue, param); 1166 } else if (type === 'any') { 1167 paramGenerateAny(p, name, type, param); 1168 } else if (type === 'object' || type === 'Object') { 1169 paramGenerateObject(p, funcValue, param); 1170 } else { 1171 NapiLog.logError('The current version does not support generating parameter [%s] with type [%s].' 1172 .format(name, type), getLogErrInfo()); 1173 } 1174} 1175 1176// on/off 接口的参数处理 1177function eventParamGenerate(p, funcValue, param, data) { 1178 let type = funcValue.type; 1179 if (type === undefined) { 1180 NapiLog.logError('eventParamGenerate param error: funcValue.type is null'); 1181 return; 1182 } 1183 if (type.indexOf("'") >= 0) { 1184 type = type.replaceAll('\'', ''); 1185 } 1186 let regName = re.match('([a-zA-Z_0-9]+)', type); 1187 if (isFuncType(type)) { 1188 paramGenerateCallBack(data, funcValue, param, p); 1189 } else if (type.substring(0, 9) === 'Callback<' || type.substring(0, 14) === 'AsyncCallback<') { 1190 paramGenerateCallBack(data, funcValue, param, p); // callback参数处理 1191 } else if (CallFunctionList.getValue(type)) { // 判断条件 1192 let onFlag = true; // callFunction => 函数参数处理 1193 paramGenerateArrowCallBack(funcValue, param, p, onFlag); 1194 } else if (InterfaceList.getValue(type)) { 1195 let aaOnFlag = true; 1196 } else if (regName) { // event type参数处理 1197 param.eventName = re.getReg(type, regName.regs[1]); // string类型如何处理? 1198 if (param.eventName === 'string') { 1199 param.eventNameIsStr = true; 1200 param.eventName = 'string%d'.format(NumberIncrease.getAndIncrease()); 1201 } 1202 param.valueDefine += '%sstd::string &%s'.format(param.valueDefine.length > 0 ? ', ' : '', funcValue.name); 1203 } else { 1204 NapiLog.logError('function eventParamGenerate:The current version do not support to this param to generate :', 1205 funcValue.name, 'type :', type, getLogErrInfo()); 1206 } 1207} 1208 1209module.exports = { 1210 jsToC, 1211 getCType, 1212 jsToCEnum, 1213 arrTemplete, 1214 paramGenerate, 1215 paramGenerateArray, 1216 paramGenerateMap, 1217 paramGenerateCommon, 1218 paramGenerateUnion, 1219 paramGenerateCallBack, 1220 paramGenerateAny, 1221 paramGenerateObject, 1222 mapTempleteFunc, 1223 eventParamGenerate, 1224 anyTempleteFunc, 1225 objectTempleteFunc, 1226 unionTempleteFunc 1227}; 1228