• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}