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, 17 EnumList, getUnionType } = require("../tools/common"); 18const re = require("../tools/re"); 19const { NapiLog } = require("../tools/NapiLog"); 20const { print } = 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 jsToC(dest, napiVn, type, enumType = 0) { 36 if (type.indexOf("|") >= 0) { 37 return unionTempleteFunc(dest, napiVn, type) 38 } else if (type == "string") { 39 if (napiVn.indexOf("GetValueProperty") >= 0) { 40 let lt = LenIncrease.getAndIncrease() 41 return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){pxt->SwapJs2CUtf8(tnv%d,%s);}` 42 .format(lt, napiVn, lt, lt, dest) 43 } else { 44 return "pxt->SwapJs2CUtf8(%s, %s);".format(napiVn, dest) 45 } 46 } else if (type.substring(type.length - 2) == "[]") { 47 return arrTemplete(dest, napiVn, type); 48 } else if (type.substring(0, 12) == "NUMBER_TYPE_") { 49 return numTempleteFunc (enumType, napiVn, type, dest); 50 } else if (InterfaceList.getValue(type)) { 51 let tt = "" 52 let ifl = InterfaceList.getValue(type) 53 for (let i in ifl) { 54 let name2 = ifl[i].name 55 let type2 = ifl[i].type 56 tt += jsToC("%s.%s".format(dest, name2), getValueProperty(napiVn, name2), type2) 57 } 58 return tt 59 } else if (EnumList.getValue(type)) { 60 return jsToCEnum(type, dest, napiVn) 61 } else if (type.indexOf("Array<") == 0) { 62 return arrTemplete(dest, napiVn, type); 63 } else if (type == "boolean") { 64 return `BOOLEAN_JS_2_C(%s,%s,%s);`.format(napiVn, "bool", dest) 65 } else if (type.substring(0, 4) == "Map<" || type.substring(0, 6) == "{[key:") { 66 return mapTempleteFunc(dest, napiVn, type); 67 } else if (type == "any") { 68 return anyTempleteFunc(dest, napiVn, type); 69 } else if (type == "Object" || type == "object") { 70 return objectTempleteFunc(dest, napiVn); 71 }else { 72 NapiLog.logError(`do not support to generate jsToC %s,%s,%s`.format(dest, napiVn, type)); 73 } 74} 75 76function unionTempleteFunc(dest, napiVn, type) { 77 let unionType = getUnionType(type) 78 let unionTypeString = '' 79 unionTypeString += '%s_type = pxt->GetUnionType(%s);\n'.format(dest, napiVn) 80 for (let i = 0; i < unionType.length; i++) { 81 if (unionType[i] == "string") { 82 unionTypeString += `if (%s_type == "string"){ 83 std::string union_string; 84 %s 85 %s 86 }\n`.format(dest, jsToC("union_string", napiVn, unionType[i]), dest+" = union_string;") 87 } else if (unionType[i].substring(0, 12) == "NUMBER_TYPE_") { 88 unionTypeString += `if (%s_type == "number"){ 89 std::uint32_t union_number; 90 %s 91 %s 92 }\n`.format(dest, jsToC("union_number", napiVn, unionType[i]), dest+" = union_number;") 93 } else if (unionType[i] == "boolean") { 94 unionTypeString += `if (%s_type == "boolean"){ 95 bool union_boolean; 96 %s 97 %s 98 }\n`.format(dest, jsToC("union_boolean", napiVn, unionType[i]), dest+" = union_boolean;") 99 } 100 } 101 return unionTypeString 102} 103 104function jsToCEnum(type, dest, napiVn) { 105 let tt = "" 106 let ifl = EnumList.getValue(type) 107 for (let i in ifl) { 108 let type2 = ifl[i].type 109 tt += jsToC("%s".format(dest), getValueProperty(napiVn, dest), type2, type) 110 } 111 return tt 112} 113 114function getArrayTypeTemplete(type) { 115 let arrayType 116 if (type.substring(type.length - 2) == "[]") { 117 arrayType = getArrayTypeTwo(type) 118 } else { 119 arrayType = getArrayType(type) 120 } 121 if (arrayType == "string") { 122 arrayType = "std::string" 123 } else if (arrayType == "boolean") { 124 arrayType = "bool" 125 } else if (arrayType == "any") { 126 arrayType = "any" 127 } else if (arrayType == "[key:string]:string" || arrayType == "Map<string,string>") { 128 arrayType = "std::map<std::string, std::string>" 129 } else if (arrayType.substring(0, arrayType.length-1) == "[key:string]:NUMBER_TYPE_" || 130 arrayType.substring(0, arrayType.length-1) == "Map<string,NUMBER_TYPE_>") { 131 let len = arrayType.length 132 let num = arrayType.substring(len-1, len) 133 arrayType = "std::map<std::string, NUMBER_TYPE_%s>".format(num) 134 } else if (arrayType == "[key:string]:boolean" || arrayType == "Map<string,boolean>") { 135 arrayType = "std::map<std::string, bool>" 136 } else if (arrayType.substring(0, 14) == "[key:string]:") { 137 let valueType = arrayType.substring(14, arrayType.length) 138 arrayType = "std::map<std::string, %s>".format(valueType) 139 } else if (arrayType.substring(0, 11) == "Map<string,") { 140 let valueType = arrayType.substring(11, arrayType.length-1) 141 arrayType = "std::map<std::string, %s>".format(valueType) 142 } 143 return arrayType 144} 145 146function arrTemplete(dest, napiVn, type) { 147 let lt = LenIncrease.getAndIncrease() 148 let arrayType = getArrayTypeTemplete(type) 149 if (arrayType == "any") { 150 return anyArrayTempleteFunc(dest, napiVn); 151 } 152 let arrTemplete = `\ 153 uint32_t len[replace_lt]=pxt->GetArrayLength(%s); 154 for(uint32_t i[replace_lt]=0;i[replace_lt]<len[replace_lt];i[replace_lt]++) { 155 %s tt[replace_lt]; 156 [replace_swap] 157 %s.push_back(tt[replace_lt]); 158 159 }\n`.format(napiVn, arrayType == "boolean" ? "bool" : arrayType, dest) 160 161 let arrMapTemplete = `\ 162 uint32_t len[replace_lt]=pxt->GetArrayLength(%s); 163 for(uint32_t i[replace_lt]=0;i[replace_lt]<len[replace_lt];i[replace_lt]++) { 164 %s tt[replace_lt]; 165 166 napi_value mapPara = pxt->GetArrayElement(pxt->GetArgv(0),i[replace_lt]); 167 uint32_t len2=pxt->GetMapLength(mapPara); 168 for(uint32_t i2=0;i2<len2;i2++) { 169 std::string ttName; 170 pxt->SwapJs2CUtf8(pxt->GetMapElementName(mapPara, i2), ttName); 171 napi_value mapValue = pxt->GetMapElementValue(mapPara,ttName.c_str()); 172 [code_gen] 173 174 tt[replace_lt].insert(std::make_pair(ttName, ttValue)); 175 } 176 %s.push_back(tt[replace_lt]); 177 178 }\n`.format(napiVn, arrayType, dest) 179 arrTemplete = arrTemplete.replaceAll("[replace_lt]", lt) 180 181 let str = "std::map<std::string," 182 let strLen = str.length 183 if (arrayType.substring(0, strLen) == "std::map<std::string,") { 184 let codegen = getMapValueCode(arrayType) 185 if (codegen == null) { 186 return arrMapTemplete 187 } 188 arrMapTemplete = arrMapTemplete.replaceAll("[replace_lt]", lt) 189 arrMapTemplete = arrMapTemplete.replaceAll("[code_gen]", codegen) 190 return arrMapTemplete 191 } else { 192 arrTemplete = getArrTempletereplaceSwap(arrTemplete, arrayType, napiVn, lt) 193 } 194 return arrTemplete 195} 196 197function numTempleteFunc(enumType, napiVn, type, dest) { 198 if (enumType) { 199 if (napiVn.indexOf("GetValueProperty") >= 0) { 200 let lt = LenIncrease.getAndIncrease() 201 return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){NUMBER_JS_2_C_ENUM(tnv%d,%s,%s,%s);}` 202 .format(lt, napiVn, lt, lt, type, dest, enumType) 203 } else { 204 return `NUMBER_JS_2_C_ENUM(%s,%s,%s,%s);`.format(napiVn, type, dest, enumType) 205 } 206 } else { 207 if (napiVn.indexOf("GetValueProperty") >= 0) { 208 let lt = LenIncrease.getAndIncrease() 209 return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){NUMBER_JS_2_C(tnv%d,%s,%s);}` 210 .format(lt, napiVn, lt, lt, type, dest) 211 } else { 212 return `NUMBER_JS_2_C(%s,%s,%s);`.format(napiVn, type, dest) 213 } 214 } 215} 216 217function getMapValueCode(arrayType) { 218 let valueTypeOut = arrayType.substring(22, arrayType.length-1) 219 let strTypeOut = "%s".format(valueTypeOut) 220 let codegen 221 if (strTypeOut == "std::string") { 222 codegen = '\ 223 std::string ttValue;\ 224 pxt->SwapJs2CUtf8(mapValue, ttValue);' 225 } else if (strTypeOut == "bool") { 226 codegen = '\ 227 bool ttValue;\ 228 ttValue = pxt->SwapJs2CBool(mapValue);' 229 } else if (strTypeOut.substr(0, 12) == "NUMBER_TYPE_") { 230 codegen = '\ 231 %s ttValue;\ 232 NUMBER_JS_2_C(mapValue,%s,ttValue);'.format(strTypeOut, strTypeOut) 233 } 234 return codegen 235} 236 237function getArrTempletereplaceSwap(arrTemplete, arrayType, napiVn, lt) { 238 if (arrayType.substring(0, 12) == "NUMBER_TYPE_") { 239 arrTemplete = arrTemplete.replaceAll("[replace_swap]", 240 "NUMBER_JS_2_C(pxt->GetArrayElement(%s,i%d),%s,tt%d);".format(napiVn, lt, arrayType, lt)) 241 } else if (arrayType == "std::string") { 242 arrTemplete = arrTemplete.replaceAll("[replace_swap]", 243 "pxt->SwapJs2CUtf8(pxt->GetArrayElement(%s,i%d), tt%d);".format(napiVn, lt, lt)) 244 } else if (InterfaceList.getValue(arrayType)) { 245 arrTemplete = arrTemplete.replaceAll("[replace_swap]", 246 jsToC("tt" + lt, "pxt->GetArrayElement(%s,i%d)".format(napiVn, lt), arrayType)) 247 } else if (arrayType == "bool") { 248 arrTemplete = arrTemplete.replaceAll("[replace_swap]", 249 "tt%d = pxt->SwapJs2CBool(pxt->GetArrayElement(%s,i%d));".format(lt, napiVn, lt)) 250 } 251 return arrTemplete 252} 253function getMapValueType(strLen, keyType, arrayType){ 254 let valueTypeIn 255 if (keyType == "[key:string]:"){ 256 valueTypeIn = arrayType.substring(strLen, arrayType.length) 257 } else if (keyType == "Map<string,"){ 258 valueTypeIn = arrayType.substring(strLen, arrayType.length - 1) 259 } 260 261 let mapValueType 262 if (valueTypeIn == "string") { 263 mapValueType = "std::string" 264 } else if (valueTypeIn == "boolean") { 265 mapValueType = "bool" 266 } else { 267 mapValueType = valueTypeIn 268 } 269 return mapValueType 270} 271 272function getMapKeyLen(arrayType) { 273 let strLen 274 if (arrayType.substring(0,13) == "[key:string]:") { 275 strLen = "[key:string]:".length 276 }else if (arrayType.substring(0,10) == "Map<string") { 277 strLen = "Map<string,".length 278 } 279 return strLen 280} 281 282function paramGenerateArray(p, funcValue, param) { 283 let type = funcValue.type 284 let name = funcValue.name 285 let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p 286 let modifiers = funcValue.optional ? "* " : "&" 287 if (type.substring(type.length - 2) == "[]") { 288 let arrayType = getArrayTypeTwo(type) 289 if (arrayType == "string") arrayType = "std::string" 290 if (arrayType == "boolean") arrayType = "bool" 291 if (arrayType == "any") { 292 return paramGenerateAnyArray(p, name, type, param) 293 } 294 param.valueIn += funcValue.optional ? "\n std::vector<%s>* in%d = nullptr;".format(arrayType, p) 295 : "\n std::vector<%s> in%d;".format(arrayType, p) 296 param.valueCheckout += jsToC(inParamName, "pxt->GetArgv(%d)".format(p), type) 297 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 298 param.valueDefine += "%sstd::vector<%s> %s%s".format(param.valueDefine.length > 0 ? ", " 299 : "", arrayType, modifiers, name) 300 } else if (type.substring(0, 6) == "Array<") { 301 let arrayType = getArrayType(type) 302 let strLen = getMapKeyLen(arrayType) 303 let keyType = arrayType.substring(0, strLen) 304 let suType = arrayType.substring(0,12) 305 if (arrayType == "string") { 306 arrayType = "std::string" 307 } else if (arrayType == "boolean") { 308 arrayType = "bool" 309 } else if (arrayType == "any") { 310 return paramGenerateAnyArray(p, name, type, param) 311 } 312 else if (keyType == "[key:string]:"|| keyType == "Map<string,") { 313 let mapValueType = getMapValueType(strLen, keyType, arrayType); 314 arrayType = "std::map<std::string, %s>".format(mapValueType) 315 } 316 param.valueIn += funcValue.optional ? "\n std::vector<%s>* in%d = nullptr;".format(arrayType, p) 317 : "\n std::vector<%s> in%d;".format(arrayType, p) 318 let arrValueCheckout = jsToC(inParamName, "pxt->GetArgv(%d)".format(p), type) 319 if (funcValue.optional) { 320 arrValueCheckout = "if (pxt->GetArgc() > %s) {\n vio->in%d = new std::vector<%s>;\n" 321 .format(p, p, arrayType) + arrValueCheckout + " }\n" 322 param.optionalParamDestory += "C_DELETE(vio->in%d);\n ".format(p) 323 } 324 param.valueCheckout += arrValueCheckout 325 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 326 param.valueDefine += "%sstd::vector<%s> %s%s".format(param.valueDefine.length > 0 ? ", " 327 : "", arrayType, modifiers, name) 328 } else { 329 NapiLog.logError("The current version do not support to this param to generate :", name, "type :", type); 330 } 331} 332 333function paramGenerateAny(p, name, type, param) { 334 param.valueIn += `\n std::any in%d; 335 std::string in%d_type;`.format(p, p) 336 param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) 337 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 338 param.valueDefine += "%sstd::any &%s".format(param.valueDefine.length > 0 ? ", " : "", name) 339} 340 341function paramGenerateAnyArray(p, name, type, param) { 342 param.valueIn += `\n std::any in%d; 343 std::string in%d_type;`.format(p, p) 344 param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) 345 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 346 param.valueDefine += "%sstd::any &%s".format(param.valueDefine.length > 0 ? ", " : "", name) 347} 348 349function paramGenerateEnum(data, funcValue, param, p) { 350 let index = enumIndex(funcValue.type, data) 351 if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) { 352 funcValue.type = "NUMBER_TYPE_" + NumberIncrease.getAndIncrease() 353 } else if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_STRING) { 354 funcValue.type = "string" 355 } else { 356 NapiLog.logError(`paramGenerate is not support`); 357 return 358 } 359 paramGenerate(p, funcValue, param, data) 360} 361 362function paramGenerateMap(funcValue, param, p) { 363 let type = funcValue.type 364 let name = funcValue.name 365 let mapType = getMapType(type) 366 let mapTypeString 367 if (mapType[1] != undefined && mapType[2] == undefined) { 368 if (mapType[1] == "string") { mapTypeString = "std::string" } 369 else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = mapType[1] } 370 else if (mapType[1] == "boolean") { mapTypeString = "bool" } 371 else if (mapType[1] == "any") { mapTypeString = "std::any" } 372 else { mapTypeString = mapType[1] } 373 } 374 else if (mapType[2] != undefined) { 375 if (mapType[2] == "string") { mapTypeString = "std::map<std::string,std::string>" } 376 else if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") { "std::map<std::string,"+mapType[2]+">" } 377 else if (mapType[2] == "boolean") { mapTypeString = "std::map<std::string,bool>" } 378 } 379 else if (mapType[3] != undefined) { 380 if (mapType[3] == "string") { mapTypeString = "std::vector<std::string>" } 381 else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = "std::vector<"+mapType[3]+">" } 382 else if (mapType[3] == "boolean") { mapTypeString = "std::vector<bool>" } 383 } 384 paramGenerateMap2(funcValue, param, p, mapType, mapTypeString, name) 385} 386 387function paramGenerateMap2(funcValue, param, p, mapType, mapTypeString, name) { 388 let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p 389 let modifiers = funcValue.optional ? "*" : "&" 390 if (mapType[1] == "any") { 391 param.valueIn += funcValue.optional ? `\n std::map<std::string,%s>* in%d = nullptr; 392 std::string in%d_type;`.format(mapTypeString, p, p) 393 : `\n std::map<std::string,%s> in%d; 394 std::string in%d_type;`.format(mapTypeString, p, p) 395 } else { 396 param.valueIn += funcValue.optional ? "\n std::map<std::string,%s>* in%d = nullptr;".format(mapTypeString, p) 397 : "\n std::map<std::string,%s> in%d;".format(mapTypeString, p) 398 } 399 param.valueCheckout += getValueCheckout(funcValue, param, inParamName, p, 400 "std::map<std::string,%s>".format(mapTypeString)) 401 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 402 param.valueDefine += "%sstd::map<std::string,%s>%s %s" 403 .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString, modifiers, name) 404} 405 406function mapTempleteFunc(dest, napiVn, type) { 407 let mapType = getMapType(type) 408 let lt = LenIncrease.getAndIncrease() 409 let mapTemplete = "" 410 if (mapType[1] != undefined && mapType[2] == undefined) { 411 mapTemplete = mapValue(mapType, napiVn, dest, lt) 412 } 413 else if (mapType[2] != undefined) { 414 mapTemplete = mapMap(mapType, napiVn, dest, lt) 415 } 416 else if (mapType[3] != undefined) { 417 mapTemplete = mapArray(mapType, napiVn, dest, lt) 418 } 419 return mapTemplete 420} 421 422function anyTempleteFunc(dest) { 423 let anyTemplete = `%s_type = pxt->GetAnyType(pxt->GetArgv(0)); 424 pxt->SetAnyValue(%s_type, pxt->GetArgv(0), %s);` 425 .format(dest, dest, dest) 426 427 return anyTemplete 428} 429 430function anyArrayTempleteFunc(dest, napiVn) { 431 let anyArrayTemplete = `%s_type = pxt->GetAnyArrayType(%s); 432 pxt->SetAnyValue(%s_type, %s, %s);` 433 .format(dest, napiVn, dest, napiVn, dest) 434 435 return anyArrayTemplete 436} 437 438let mapValueTemplete = `\ 439uint32_t len[replace_lt]=pxt->GetMapLength(%s); 440for(uint32_t i[replace_lt]=0;i[replace_lt]<len[replace_lt];i[replace_lt]++) { 441 std::string tt[replace_lt]; 442 %s tt[replace_lt+1]; 443 [replace_swap] 444 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 445}` 446 447function mapInterface(mapTypeString, mapTemplete, napiVn, lt) { 448 let interfaceValue = InterfaceList.getValue(mapTypeString) 449 let interfaceVarName = "" 450 let interfaceFun = "" 451 for (let i = 0; i < interfaceValue.length; i++) { 452 if (interfaceValue[i].type == 'string') { 453 interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name, interfaceValue[i].name) 454 interfaceFun += 455 `pxt->%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(0),tt%d.c_str()),%sName.c_str()),tt%d.%s);` 456 .format("SwapJs2CUtf8", "GetMapElementValue", 457 lt, interfaceValue[i].name, lt+1, interfaceValue[i].name) 458 } 459 else if (interfaceValue[i].type.substring(0, 12) == "NUMBER_TYPE_") { 460 interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name, interfaceValue[i].name) 461 interfaceFun += 462 `%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(0),tt%d.c_str()),%sName.c_str()),%s,tt%d.%s);\n` 463 .format("NUMBER_JS_2_C", "GetMapElementValue", lt, interfaceValue[i].name, 464 interfaceValue[i].type, lt + 1, interfaceValue[i].name) 465 } 466 else if (interfaceValue[i].type == 'boolean') { 467 interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name, interfaceValue[i].name) 468 interfaceFun += 469 `tt%d.%s = pxt->%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(0),tt%d.c_str()),%sName.c_str()));\n` 470 .format(lt + 1, interfaceValue[i].name, "SwapJs2CBool", "GetMapElementValue", 471 lt, interfaceValue[i].name) 472 } 473 } 474 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 475 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 476 %d 477 %d`.format(napiVn, lt, lt, interfaceVarName, interfaceFun)) 478 return mapTemplete 479} 480 481function mapValue(mapType, napiVn, dest, lt) { 482 let mapTypeString 483 if (mapType[1] == "string") { mapTypeString = "std::string" } 484 else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = mapType[1] } 485 else if (mapType[1] == "boolean") { mapTypeString = "bool" } 486 else if (mapType[1] == "any") { mapTypeString = "std::any" } 487 else if (mapType[1] != null) { mapTypeString = mapType[1] } 488 let mapTemplete = mapValueTemplete.format(napiVn, mapTypeString, dest) 489 mapTemplete = mapTemplete.replaceAll("[replace_lt]", lt) 490 mapTemplete = mapTemplete.replaceAll("[replace_lt+1]", lt + 1) 491 if (mapTypeString == "std::string") { 492 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 493 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 494 pxt->SwapJs2CUtf8(pxt->GetMapElementValue(%s,tt%d.c_str()), tt%d);` 495 .format(napiVn, lt, lt, napiVn, lt, lt + 1)) 496 } 497 else if (mapTypeString.substring(0, 12) == "NUMBER_TYPE_") { 498 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 499 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 500 NUMBER_JS_2_C(pxt->GetMapElementValue(%s,tt%d.c_str()),%s,tt%d);` 501 .format(napiVn, lt, lt, napiVn, lt, mapTypeString, lt + 1)) 502 } 503 else if (mapTypeString == "bool") { 504 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 505 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 506 tt%d = pxt->SwapJs2CBool(pxt->GetMapElementValue(%s,tt%d.c_str()));` 507 .format(napiVn, lt, lt, lt + 1, napiVn, lt)) 508 } 509 if (mapTypeString == "std::any") { 510 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 511 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 512 if (i%d == 0){ 513 %s_type = pxt->GetAnyType(pxt->GetMapElementValue(%s,tt%d.c_str())); 514 } 515 pxt->SetAnyValue(%s_type, pxt->GetMapElementValue(%s,tt%d.c_str()), tt%d);` 516 .format(napiVn, lt, lt, lt, dest, napiVn, lt, dest, napiVn, lt, lt + 1)) 517 } 518 else if (InterfaceList.getValue(mapTypeString)) { 519 mapTemplete = mapInterface(mapTypeString, mapTemplete, napiVn, lt) 520 } 521 return mapTemplete 522} 523 524let mapMapTemplete = `\ 525uint32_t len[replace_lt]=pxt->GetMapLength(%s); 526for(uint32_t i[replace_lt]=0;i[replace_lt]<len[replace_lt];i[replace_lt]++) { 527 std::string tt[replace_lt]; 528 std::map<std::string,%s> tt[replace_lt+1]; 529 [replace_swap] 530 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 531}` 532 533function mapMapString (mapTemplete, napiVn, lt) { 534 return mapTemplete.replaceAll("[replace_swap]", 535 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 536 uint32_t len%d=pxt->GetMapLength(pxt->GetMapElementValue(%s,tt%d.c_str())); 537 for(uint32_t i%d=0;i%d<len%d;i%d++){ 538 std::string tt%d; 539 std::string tt%d; 540 pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s,tt%d.c_str()), i%d),tt%d); 541 pxt->SwapJs2CUtf8(pxt->GetMapElementValue(pxt->GetMapElementValue(%s,tt%d.c_str()),tt%d.c_str()),tt%d); 542 tt%d.insert(std::make_pair(tt%d, tt%d)); 543 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, lt + 1, 544 lt + 2, lt + 3, napiVn, lt, lt + 1, lt + 2, napiVn, lt, lt + 2, lt + 3, lt + 1, lt + 2, lt + 3)) 545} 546 547function mapMapBoolean (mapTemplete, napiVn, lt) { 548 return mapTemplete.replaceAll("[replace_swap]", 549 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 550 uint32_t len%d=pxt->GetMapLength(pxt->GetMapElementValue(%s,tt%d.c_str())); 551 for(uint32_t i%d=0;i%d<len%d;i%d++){ 552 std::string tt%d; 553 bool tt%d; 554 pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s,tt%d.c_str()), i%d),tt%d); 555 tt%d = pxt->%s(pxt->GetMapElementValue(pxt->GetMapElementValue(%s,tt%d.c_str()),tt%d.c_str())); 556 tt%d.insert(std::make_pair(tt%d, tt%d)); 557 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, lt + 1, 558 lt + 2, lt + 3, napiVn, lt, lt + 1, lt + 2, lt + 3, "SwapJs2CBool" 559 ,napiVn, lt, lt + 2, lt + 1, lt + 2, lt + 3)) 560} 561 562function mapMapNumber (mapTemplete, napiVn, lt, mapTypeString) { 563 return mapTemplete.replaceAll("[replace_swap]", 564 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); 565 uint32_t len%d=pxt->GetMapLength(pxt->GetMapElementValue(%s,tt%d.c_str())); 566 for(uint32_t i%d=0;i%d<len%d;i%d++){ 567 std::string tt%d; 568 %s tt%d; 569 pxt->SwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s,tt%d.c_str()), i%d),tt%d); 570 NUMBER_JS_2_C(pxt->GetMapElementValue(pxt->GetMapElementValue(%s,tt%d.c_str()),tt%d.c_str()),%s,tt%d); 571 tt%d.insert(std::make_pair(tt%d, tt%d)); 572 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, lt + 1, 573 lt + 2, mapTypeString, lt + 3, napiVn, lt, lt + 1, lt + 2, napiVn, lt, lt + 2, 574 mapTypeString, lt + 3, lt + 1, lt + 2, lt + 3)) 575} 576 577function mapMap(mapType, napiVn, dest, lt) { 578 let mapTypeString 579 if (mapType[2] == "string") { mapTypeString = "std::string" } 580 else if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = mapType[2] } 581 else if (mapType[2] == "boolean") { mapTypeString = "bool" } 582 let mapTemplete = mapMapTemplete.format(napiVn, mapTypeString, dest) 583 mapTemplete = mapTemplete.replaceAll("[replace_lt]", lt) 584 mapTemplete = mapTemplete.replaceAll("[replace_lt+1]", lt + 1) 585 if (mapType[2] == "string") { 586 mapTemplete = mapMapString (mapTemplete, napiVn, lt) 587 } 588 else if (mapType[2] == "boolean") { 589 mapTemplete = mapMapBoolean (mapTemplete, napiVn, lt) 590 } 591 else if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") { 592 mapTemplete = mapMapNumber (mapTemplete, napiVn, lt, mapTypeString) 593 } 594 return mapTemplete 595} 596 597let mapArrayTemplete = `\ 598uint32_t len[replace_lt]=pxt->GetMapLength(%s); 599for(uint32_t i[replace_lt]=0;i[replace_lt]<len[replace_lt];i[replace_lt]++) { 600 std::string tt[replace_lt]; 601 std::vector<%s> tt[replace_lt+1]; 602 [replace_swap] 603 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 604}` 605 606function mapArray(mapType, napiVn, dest, lt) { 607 let mapTypeString 608 if (mapType[3] == "string") { mapTypeString = "std::string" } 609 else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = mapType[3] } 610 else if (mapType[3] == "boolean") { mapTypeString = "bool" } 611 let mapTemplete = mapArrayTemplete.format(napiVn, mapTypeString, dest) 612 mapTemplete = mapTemplete.replaceAll("[replace_lt]", lt) 613 mapTemplete = mapTemplete.replaceAll("[replace_lt+1]", lt + 1) 614 if (mapType[3] == "string") { 615 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 616 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%s), tt%d); 617 uint32_t len%s=pxt->GetArrayLength(pxt->GetMapElementValue(%s,tt%d.c_str())); 618 for(uint32_t i%d=0;i%d<len%d;i%d++){ 619 std::string tt%d; 620 pxt->SwapJs2CUtf8(pxt->GetArrayElement(pxt->GetMapElementValue(%s,tt%d.c_str()),i%d), tt%d); 621 tt%d.push_back(tt%d); 622 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, 623 lt + 1, lt + 2, napiVn, lt, lt + 1, lt + 2, lt + 1, lt + 2)) 624 } 625 else if (mapType[3] == "boolean") { 626 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 627 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%s), tt%d); 628 uint32_t len%s=pxt->GetArrayLength(pxt->GetMapElementValue(%s,tt%d.c_str())); 629 for(uint32_t i%d=0;i%d<len%d;i%d++){ 630 bool tt%d; 631 tt%d = pxt->SwapJs2CBool(pxt->GetArrayElement(pxt->GetMapElementValue(%s,tt%d.c_str()),i%d)); 632 tt%d.push_back(tt%d); 633 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, 634 lt + 1, lt + 2, lt + 2, napiVn, lt, lt, lt + 1, lt + 2)) 635 } 636 else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { 637 mapTemplete = mapTemplete.replaceAll("[replace_swap]", 638 `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%s), tt%d); 639 uint32_t len%s=pxt->GetArrayLength(pxt->GetMapElementValue(%s,tt%d.c_str())); 640 for(uint32_t i%d=0;i%d<len%d;i%d++){ 641 %s tt%d; 642 NUMBER_JS_2_C(pxt->GetArrayElement(pxt->GetMapElementValue(%s,tt%d.c_str()),i%d), %s, tt%d); 643 tt%d.push_back(tt%d); 644 }`.format(napiVn, lt, lt, lt + 1, napiVn, lt, lt + 1, lt + 1, lt + 1, 645 lt + 1, mapTypeString, lt + 2, napiVn, lt, lt + 1, mapTypeString, lt + 2, lt + 1, lt + 2)) 646 } 647 return mapTemplete 648} 649 650function paramGenerateCallBack(data, funcValue, param, p) { 651 let type = funcValue.type 652 let arrayType = re.match("(Async)*Callback<(Array<([a-zA-Z_0-9]+)>)>", type) 653 let regType 654 if (arrayType) { 655 regType = re.getReg(type, arrayType.regs[2]) 656 } 657 658 let arrayType2 = re.match("(Async)*Callback<(([a-zA-Z_0-9]+)\\[\\])>", type) 659 if (arrayType2) { 660 regType = re.getReg(type, arrayType2.regs[2]) 661 } 662 663 let tt = re.match("(Async)*Callback<([a-zA-Z_0-9]+)>", type) 664 if (tt) { 665 regType = re.getReg(type, tt.regs[2]) 666 } 667 if (isEnum(regType, data)) { 668 let index = enumIndex(regType, data) 669 if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) { 670 regType = "NUMBER_TYPE_" + NumberIncrease.getAndIncrease() 671 } else if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_STRING) { 672 regType = "string" 673 } else { 674 NapiLog.logError(`paramGenerate is not support`); 675 return 676 } 677 } 678 param.callback = { 679 type: regType, 680 offset: p, 681 optional: funcValue.optional, 682 isAsync: type.indexOf("AsyncCallback") >= 0 683 } 684} 685 686function isArrayType(type) { 687 if (type.substring(type.length - 2) == "[]" || type.substring(0, 6) == "Array<") { 688 return true; 689 } 690 return false; 691} 692 693function getValueCheckout(funcValue, param, inParamName, p, cType) { 694 let valueCheckout = jsToC(inParamName, "pxt->GetArgv(%d)".format(p), funcValue.type) + "\n " 695 if (funcValue.optional) { 696 valueCheckout = "if (pxt->GetArgc() > %d) {\n vio->in%d = new %s;\n ".format(p, p, cType) 697 + valueCheckout + "}\n " 698 param.optionalParamDestory += "C_DELETE(vio->in%d);\n ".format(p) 699 } 700 return valueCheckout; 701} 702 703function paramGenerateUnion(type, param, p, name) { 704 param.valueIn += `\n std::any in%d; 705 std::string in%d_type;`.format(p, p) 706 param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) 707 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 708 param.valueDefine += "%sstd::any &%s".format(param.valueDefine.length > 0 ? ", " : "", name) 709} 710 711function paramGenerateCommon(p, cType, funcValue, param, modifiers, inParamName) { 712 param.valueIn += funcValue.optional ? "\n %s* in%d = nullptr;".format(cType, p) 713 : "\n %s in%d;".format(cType, p) 714 param.valueCheckout += getValueCheckout(funcValue, param, inParamName, p, cType) 715 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 716 param.valueDefine += "%s%s%s %s".format( 717 param.valueDefine.length > 0 ? ", " : "", cType, modifiers, funcValue.name) 718} 719 720let objectTemplete = `\ 721 uint32_t len[replace_lt]=pxt->GetMapLength(%s); 722 for(uint32_t i[replace_lt]=0;i[replace_lt]<len[replace_lt];i[replace_lt]++) { 723 std::string tt[replace_lt]; 724 std::any tt[replace_lt+1]; 725 726 pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i[replace_lt]), tt[replace_lt]); 727 napi_value valueObj = pxt->GetMapElementValue(%s,tt[replace_lt].c_str()); 728 std::string valueObjType = pxt->GetAnyType(valueObj); 729 730 [replace_swap] 731 %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); 732 }` 733 734function objectTempleteFunc(dest, napiVn) { 735 let lt = LenIncrease.getAndIncrease() 736 let objTemplete = objectTemplete.format(napiVn, napiVn, napiVn, dest) 737 738 objTemplete = objTemplete.replaceAll("[replace_swap]", 739 ` 740 if (valueObjType == "string") { 741 std::string tt[replace_lt+2]; 742 pxt->SwapJs2CUtf8(valueObj, tt[replace_lt+2]); 743 tt[replace_lt+1] = tt[replace_lt+2]; 744 } else if (valueObjType == "boolean") { 745 bool tt[replace_lt+2]; 746 tt[replace_lt+2] = pxt->SwapJs2CBool(valueObj); 747 tt[replace_lt+1] = tt[replace_lt+2]; 748 } else if (valueObjType == "number") { 749 NUMBER_JS_2_C(valueObj, NUMBER_TYPE_%d, tt[replace_lt+1]); 750 } 751 `).format(lt) 752 objTemplete = objTemplete.replaceAll("[replace_lt]", lt) 753 objTemplete = objTemplete.replaceAll("[replace_lt+1]", lt + 1) 754 objTemplete = objTemplete.replaceAll("[replace_lt+2]", lt + 2) 755 return objTemplete 756} 757 758function paramGenerateObject(p, funcValue, param) { 759 let type = funcValue.type 760 let name = funcValue.name 761 let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p 762 let modifiers = funcValue.optional ? "* " : "&" 763 764 let arrayType = "std::map<std::string, std::any>" 765 param.valueIn += funcValue.optional ? "\n %s* in%d = nullptr;".format(arrayType, p) 766 : "\n %s in%d;".format(arrayType, p) 767 768 let arrValueCheckout = jsToC(inParamName, "pxt->GetArgv(%d)".format(p), type) 769 param.valueCheckout += arrValueCheckout 770 param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) 771 param.valueDefine += "%s%s %s%s".format(param.valueDefine.length > 0 ? ", " 772 : "", arrayType, modifiers, name) 773} 774 775// 函数的参数处理 776function paramGenerate(p, funcValue, param, data) { 777 let type = funcValue.type 778 let name = funcValue.name 779 let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p 780 let modifiers = funcValue.optional ? "*" : "&" 781 if (type.indexOf("|") >= 0) { 782 return paramGenerateUnion(type, param, p, name) 783 } 784 else if (type == "string") { 785 paramGenerateCommon(p, "std::string", funcValue, param, modifiers, inParamName) 786 } 787 else if (type.substring(0, 12) == "NUMBER_TYPE_" && type.indexOf("[]") < 0) { 788 paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName) 789 } 790 else if (InterfaceList.getValue(type)) { 791 paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName) 792 } 793 else if (type.substring(0, 9) == "Callback<" || type.substring(0, 14) == "AsyncCallback<") { 794 paramGenerateCallBack(data, funcValue, param, p) 795 } 796 else if (type == "boolean") { 797 paramGenerateCommon(p, "bool", funcValue, param, modifiers, inParamName) 798 } 799 else if (isEnum(type, data)) { 800 paramGenerateEnum(data, funcValue, param, p) 801 } 802 else if (type.substring(0, 4) == "Map<" || type.substring(0, 6) == "{[key:") { 803 paramGenerateMap(funcValue, param, p) 804 } else if (isArrayType(type)) { 805 paramGenerateArray(p, funcValue, param); 806 } else if (type == "any") { 807 paramGenerateAny(p, name, type, param); 808 } else if (type == "object" || type == "Object") { 809 paramGenerateObject(p, funcValue, param); 810 } else { 811 NapiLog.logError( 812 "The current version does not support generating parameter [%s] with type [%s]".format(name, type)); 813 } 814} 815 816// on/off 接口的event名称参数处理 817function eventParamGenerate(p, funcValue, param, data) { 818 let name = funcValue.name; 819 let type = funcValue.type; 820 let regName = re.match("'([a-zA-Z_0-9]+)'", type) 821 if (regName) { 822 param.eventName = re.getReg(type, regName.regs[1]) 823 param.valueDefine += "%sstd::string &%s".format(param.valueDefine.length > 0 ? ", " : "", name) 824 } else if (type.substring(0, 9) == "Callback<" || type.substring(0, 14) == "AsyncCallback<") { 825 paramGenerateCallBack(data, funcValue, param, p) 826 } else { 827 NapiLog.logError("function eventParamGenerate:The current version do not support to this param to generate :" 828 , name, "type :", type); 829 } 830} 831 832module.exports = { 833 jsToC, 834 jsToCEnum, 835 arrTemplete, 836 paramGenerate, 837 paramGenerateArray, 838 paramGenerateMap, 839 mapTempleteFunc, 840 eventParamGenerate 841}