• 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 { isMappedTypeNode } = require("typescript");
16const { InterfaceList, getArrayType, NumberIncrease, enumIndex,
17    isEnum, EnumValueType, getArrayTypeTwo, getMapType, EnumList,
18    jsType2CType, getUnionType } = require("../tools/common");
19const { NapiLog } = require("../tools/NapiLog");
20const { print } = require("../tools/tool");
21
22const specialPrefixArr = ["p->", "vio->out."];
23
24/**
25 * Get the real value name by deleting prefix like "p->", "vio->out.", e.g.
26 * @param {*} valueName, example: p->xxx, vio->out.yyy
27 * @returns the real value without prefix, example: xxx, yyy
28 */
29function delPrefix(valueName) {
30    for ( var i in specialPrefixArr) {
31        if (valueName.indexOf(specialPrefixArr[i]) == 0) {
32            // Find special prefix and delete it.
33            return valueName.substring(specialPrefixArr[i].length, valueName.length);
34        }
35    }
36    // Without special prefix, nothing is changed.
37    return valueName;
38}
39
40function cToJsForInterface(value, type, dest, deep) {
41    let lt = deep
42    let result = ""
43    let ifl = InterfaceList.getValue(type)
44    for (let i in ifl) {
45        let name2 = ifl[i].name
46        let type2 = ifl[i].type
47        let isSubEnum = EnumList.getValue(type2) ? true : false;
48        let subDest = isSubEnum ? dest : "tnv%d".format(lt)
49        let interfaceType = cToJs("%s.%s".format(value, name2), type2, subDest, deep + 1)
50        if (isSubEnum) {
51            // interface include enum properties
52            result += interfaceType
53        } else {
54            result += "{\nnapi_value tnv%d = nullptr;\n".format(lt) +
55            interfaceType + `\npxt->SetValueProperty(%s,"%s",tnv%d);\n}\n`
56                .format(dest, name2, lt)
57        }
58    }
59    return result
60}
61
62function cToJs(value, type, dest, deep = 1) {
63    var propertyName = delPrefix(value);
64    if (type.indexOf("|") >= 0) {
65        return unionTempleteFunc(value, type, dest);
66    } else if (type == "void")
67        return "%s = pxt->UndefinedValue();".format(dest);
68    else if (type == "boolean")
69        return "%s = pxt->SwapC2JsBool(%s);".format(dest, value);
70    else if (type == "string")
71        return `%s = pxt->SwapC2JsUtf8(%s.c_str());`.format(dest, value)
72    else if (InterfaceList.getValue(type)) {
73        return cToJsForInterface(value, type, dest, deep);
74    }
75    else if(EnumList.getValue(type)){
76        let lt = deep
77        let result = ""
78        let ifl = EnumList.getValue(type)
79        let type2 = ifl[0].type
80        let enumCtoJsStr = cToJs("enumInt%d".format(lt), type2, "tnv%d".format(lt), deep + 1)
81        result += "{\nnapi_value tnv%d = nullptr;\n".format(lt) + "int enumInt%d = %s;\n".format(lt, value) +
82                enumCtoJsStr + `\npxt->SetValueProperty(%s,"%s",tnv%d);\n}\n`
83                    .format(dest, propertyName, lt)
84        return result
85    }
86    else if (type.substring(0, 6) == "Array<" || type.substring(type.length - 2) == "[]") {
87        let arrayType = checkArrayParamType(type)
88        return arrayTempleteFunc(arrayType, deep, dest, value)
89    }
90    else if (type.substring(0, 4) == "Map<" || type.indexOf("{[key:") == 0) {
91        return mapTempleteFunc(type, deep, dest, value)
92    }
93    else if (type.substring(0, 12) == "NUMBER_TYPE_") {
94        return `%s = NUMBER_C_2_JS(pxt, %s);`.format(dest, value)
95    }
96    else if (type == "any") {
97        return anyTempleteFunc(value)
98    }
99    else if (type == "Object" || type == "object") {
100        return objectTempleteFuncReturn(value)
101    }
102    else {
103        NapiLog.logError(`\n---- This type do not generate cToJs %s,%s,%s ----\n`.format(value, type, dest));
104    }
105}
106
107function objectTempleteFuncReturn(value) {
108    let objectTemplete = `pxt->GetObjectValue(result, %s);`
109        .format(value)
110        return objectTemplete
111}
112
113function unionTempleteFunc(value, type, dest){
114    let unionType = getUnionType(type)
115    let unionTypeString = ''
116    for (let i = 0; i < unionType.length; i++) {
117        if (unionType[i] == "string") {
118            unionTypeString += `if (%s_type == "string"){
119                %s
120                %s
121            }\n`.format(value, "std::string union_string = std::any_cast<std::string>("+value+");",
122            cToJs("union_string", unionType[i], dest))
123        } else if (unionType[i].substring(0, 12) == "NUMBER_TYPE_") {
124            unionTypeString += `if (%s_type == "number"){
125                %s
126                %s
127            }\n`.format(value, "std::uint32_t union_number = std::any_cast<std::uint32_t>("+value+");",
128            cToJs("union_number", unionType[i], dest))
129        } else if (unionType[i] == "boolean") {
130            unionTypeString += `if (%s_type == "boolean"){
131                %s
132                %s
133            }\n`.format(value, "bool union_boolean = std::any_cast<bool>("+value+");",
134            cToJs("union_boolean", unionType[i], dest))
135        }
136    }
137    return unionTypeString
138}
139
140function checkArrayParamType(type) {
141    let arrayType
142    if (type.substring(type.length - 2) == "[]") {
143        arrayType = getArrayTypeTwo(type)
144    }
145    else {
146        arrayType = getArrayType(type)
147    }
148    return arrayType
149}
150
151function arrayTempleteFunc(arrayType, deep, dest, value) {
152    let lt = deep
153    let tnv = dest
154    let tnvdef = `pxt->CreateArray(%s);
155    uint32_t outLen%d = %s.size();
156    for(uint32_t i = 0; i < outLen%d; i++) {
157        napi_value tnv%d = nullptr;
158        [calc_out]
159        pxt->SetArrayElement(%s, i, tnv%d);
160    }`.format(tnv, lt, value, lt, lt, tnv, lt)
161    let ret = ""
162    if (arrayType.substring(0, 12) == "NUMBER_TYPE_") {
163        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = NUMBER_C_2_JS(pxt,%s[i]);`.format(lt, value))
164    }
165    else if (arrayType == "string") {
166        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = pxt->SwapC2JsUtf8(%s[i].c_str());`.format(lt, value))
167    }
168    else if (arrayType == "boolean") {
169        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = pxt->SwapC2JsBool(%s[i]);`.format(lt, value))
170    }
171    else if (arrayType == "any") {
172        return anyArrayTempleteFuncReturn(value)
173    }
174    else if (InterfaceList.getValue(arrayType)) {
175        ret = tnvdef.replaceAll("[calc_out]", cToJs(value + "[i]", arrayType, "tnv" + lt, deep + 1))
176    }
177    return ret
178}
179
180function mapTempleteFunc(type, deep, dest, value) {
181    let mapType = getMapType(type)
182    let lt = deep
183    let tnv = dest
184    let tnvdef = `result = nullptr;
185    for (auto i = %s.begin(); i != %s.end(); i++)
186        {
187            const char * tnv%d;
188            napi_value tnv%d = nullptr;
189            [calc_out]
190            pxt->SetMapElement(%s, tnv%d, tnv%d);
191        }`.format(value, value, lt, lt + 1, tnv, lt, lt + 1)
192    let ret = ""
193    if (mapType[1] != undefined && mapType[2] == undefined) {
194        ret = mapTempleteValue(mapType, tnvdef, lt, value, tnv)
195    }
196    else if (mapType[2] != undefined) {
197        ret = mapTempleteMap(mapType, tnvdef, lt)
198    }
199    else if (mapType[3] != undefined) {
200        ret = mapTempleteArray(mapType, tnvdef, lt)
201    }
202    return ret
203}
204
205function anyTempleteFunc(value) {
206    let anyTemplete = `pxt->GetAnyValue(%s_type, result, %s);`
207        .format(value, value)
208
209    return anyTemplete
210}
211
212function anyArrayTempleteFuncReturn(value) {
213    let anyTemplete = `pxt->GetAnyValue(%s_type, result, %s);`
214        .format(value, value)
215
216    return anyTemplete
217}
218
219function mapInterface(value, lt, tnv, mapType) {
220    let ret
221    let tnvdefInterface = `result = nullptr;
222    for (auto i = %s.begin(); i != %s.end(); i++)
223    {
224        const char *tnv%d;
225        [calc_out]
226    }`.format(value, value, lt, lt + 1, tnv, lt, lt + 1)
227    let interfaceValue = InterfaceList.getValue(mapType[1])
228    let interfaceVarName = ""
229    let interfaceVar = ""
230    let interfaceFun = ""
231    for (let i = 0; i < interfaceValue.length; i++) {
232        if (interfaceValue[i].type == 'string') {
233            interfaceVarName += `const char * tnv_%s_name;
234                napi_value tnv_%s = nullptr;\n`.format(interfaceValue[i].name, interfaceValue[i].name)
235            interfaceVar += `tnv_%s_name = "%s";
236                tnv_%s = pxt->SwapC2JsUtf8(i->second.%s.c_str());\n`
237                .format(interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name)
238            interfaceFun += `pxt->SetMapElement(result_obj, tnv_%s_name, tnv_%s);\n`
239                .format(interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name)
240        }
241        else if (interfaceValue[i].type.substring(0, 12) == "NUMBER_TYPE_") {
242            interfaceVarName += `const char * tnv_%s_name;
243                napi_value tnv_%s = nullptr;\n`.format(interfaceValue[i].name, interfaceValue[i].name)
244            interfaceVar += `tnv_%s_name = "%s";
245                tnv_%s = NUMBER_C_2_JS(pxt,i->second.%s);\n`
246                .format(interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name)
247            interfaceFun += `pxt->SetMapElement(result_obj, tnv_%s_name, tnv_%s);\n`
248                .format(interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name)
249        }
250        else if (interfaceValue[i].type == 'boolean') {
251            interfaceVarName += `const char * tnv_%s_name;
252                napi_value tnv_%s = nullptr;\n`.format(interfaceValue[i].name, interfaceValue[i].name)
253            interfaceVar += `tnv_%s_name = "%s";
254                tnv_%s = pxt->SwapC2JsBool(i->second.%s);\n`
255                .format(interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name)
256            interfaceFun += `pxt->SetMapElement(result_obj, tnv_%s_name, tnv_%s);\n`
257                .format(interfaceValue[i].name, interfaceValue[i].name, interfaceValue[i].name)
258        }
259    }
260    ret = tnvdefInterface.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str();
261        napi_value result_obj = nullptr;
262        %s
263        %s
264        %s
265        pxt->SetMapElement(result, tnv%d, result_obj);`
266        .format(lt, interfaceVarName, interfaceVar, interfaceFun, lt))
267    return ret
268}
269
270function mapTempleteValue(mapType, tnvdef, lt, value, tnv) {
271    let ret
272    if (mapType[1] == "string") {
273        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str();
274        tnv%d = pxt->SwapC2JsUtf8(i->second.c_str());`.format(lt, lt + 1))
275    } else if (mapType[1] == "boolean") {
276        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str();
277        tnv%d = pxt->SwapC2JsBool(i->second);`.format(lt, lt + 1))
278    } else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") {
279        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str();
280        tnv%d = NUMBER_C_2_JS(pxt,i->second);`.format(lt, lt + 1))
281    } else if (mapType[1] == "any") {
282        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str();
283        pxt->GetAnyValue(%s_type, tnv%d, i->second);`.format(lt, value, lt + 1))
284    }
285    else if (InterfaceList.getValue(mapType[1])) {
286        ret = mapInterface(value, lt, tnv, mapType)
287    }
288    else
289        NapiLog.logError(`This type do not generate cToJs %s,%s,%s`.format(value, type, dest));
290    return ret
291}
292
293function mapTempleteMap(mapType, tnvdef, lt) {
294    let ret
295    if (mapType[2] == "string") {
296        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = i->first.c_str();
297        for(auto j = i->second.begin(); j != i->second.end(); j++){
298            const char * tt%d;
299            napi_value tt%d;
300            tt%d = j->first.c_str();
301            tt%d = pxt->SwapC2JsUtf8(j->second.c_str());
302            pxt->SetMapElement(tnv%d, tt%d, tt%d);
303        }`.format(lt, lt + 2, lt + 3, lt + 2, lt + 3, lt + 1, lt + 2, lt + 3))
304    }
305    else if (mapType[2] == "boolean") {
306        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = i->first.c_str();
307        for(auto j = i->second.begin(); j != i->second.end(); j++){
308            const char * tt%d;
309            napi_value tt%d;
310            tt%d = j->first.c_str();
311            tt%d = pxt->SwapC2JsBool(j->second);
312            pxt->SetMapElement(tnv%d, tt%d, tt%d);
313        }`.format(lt, lt + 2, lt + 3, lt + 2, lt + 3, lt + 1, lt + 2, lt + 3))
314    }
315    if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") {
316        ret = tnvdef.replaceAll("[calc_out]", `tnv%d = i->first.c_str();
317        for(auto j = i->second.begin(); j != i->second.end(); j++){
318            const char * tt%d;
319            napi_value tt%d;
320            tt%d = j->first.c_str();
321            tt%d = NUMBER_C_2_JS(pxt,j->second);
322            pxt->SetMapElement(tnv%d, tt%d, tt%d);
323        }`.format(lt, lt + 2, lt + 3, lt + 2, lt + 3, lt + 1, lt + 2, lt + 3))
324    }
325    return ret
326}
327
328function mapTempleteArray(mapType, tnvdef, lt) {
329    let ret
330    if (mapType[3] == "string") {
331        ret = tnvdef.replaceAll("[calc_out]", `napi_value tnv%d = nullptr;
332        pxt->CreateArray(tnv%d);
333        tnv%d = (i -> first).c_str();
334        uint32_t len%d = i->second.size();
335        for(uint32_t j=0;j<len%d;j++) {
336            tnv%d = pxt->SwapC2JsUtf8(i->second[j].c_str());
337            pxt->SetArrayElement(tnv%d, j, tnv%d);
338        }`.format(lt + 2, lt + 2, lt, lt, lt, lt + 2, lt + 1, lt + 2))
339    } else if (mapType[3] == "boolean") {
340        ret = tnvdef.replaceAll("[calc_out]", `napi_value tnv%d = nullptr;
341        pxt->CreateArray(tnv%d);
342        tnv%d = (i -> first).c_str();
343        uint32_t len%d = i->second.size();
344        for(uint32_t j=0;j<len%d;j++) {
345            tnv%d = pxt->SwapC2JsBool(i->second[j]);
346            pxt->SetArrayElement(tnv%d, j, tnv%d);
347        }`.format(lt + 2, lt + 2, lt, lt, lt, lt + 2, lt + 1, lt + 2))
348    } else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") {
349        ret = tnvdef.replaceAll("[calc_out]", `napi_value tnv%d = nullptr;
350        pxt->CreateArray(tnv%d);
351        tnv%d = (i -> first).c_str();
352        uint32_t len%d = i->second.size();
353        for(uint32_t j=0;j<len%d;j++) {
354            tnv%d = NUMBER_C_2_JS(pxt,i->second[j]);
355            pxt->SetArrayElement(tnv%d, j, tnv%d);
356        }`.format(lt + 2, lt + 2, lt, lt, lt, lt + 2, lt + 1, lt + 2))
357    }
358    return ret
359}
360
361function returnGenerateMap(returnInfo, param) {
362    let type = returnInfo.type
363    let mapType = getMapType(type)
364    let mapTypeString
365    if (mapType[1] != undefined && mapType[2] == undefined) {
366        if (mapType[1] == "string") { mapTypeString = "std::string" }
367        else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = mapType[1] }
368        else if (mapType[1] == "boolean") { mapTypeString = "bool" }
369        else if (mapType[1] == "any") { mapTypeString = "std::any" }
370        else { mapTypeString = mapType[1] }
371    }
372    else if (mapType[2] != undefined) {
373        if (mapType[2] == "string") { mapTypeString = "std::map<std::string,std::string>" }
374        else if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") { "std::map<std::string,"+mapType[2]+">" }
375        else if (mapType[2] == "boolean") { mapTypeString = "std::map<std::string,bool>" }
376    }
377    else if (mapType[3] != undefined) {
378        if (mapType[3] == "string") { mapTypeString = "std::vector<std::string>" }
379        else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = "std::vector<"+mapType[3]+">" }
380        else if (mapType[3] == "boolean") { mapTypeString = "std::vector<bool>" }
381    }
382    let modifiers = returnInfo.optional ? "*" : "&"
383    param.valueOut = returnInfo.optional ? "std::map<std::string,%s>* out = nullptr;".format(mapTypeString)
384                                         : "std::map<std::string,%s> out;".format(mapTypeString)
385        param.valueDefine += "%sstd::map<std::string,%s>%s out"
386            .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString, modifiers)
387}
388
389function returnGenerateUnion (param) {
390    param.valueOut = `std::any out;
391            std::string out_type;`
392    param.valueDefine += "%sstd::any &out".format(param.valueDefine.length > 0 ? ", " : "")
393}
394
395function returnGenerateObject(returnInfo, param, data) {
396    param.valueOut = `std::map<std::string, std::any> out;`
397    param.valueDefine += "%sstd::map<std::string, std::any> &out".format(param.valueDefine.length > 0 ? ", " : "")
398
399}
400
401/**
402 * 获取方法返回参数的填充代码
403 * @param returnInfo 方法的返回参数信息
404 * @param param 方法的所有参数信息
405 * @returns 返回参数的填充代码123 返回测试的值
406 */
407function getReturnFill(returnInfo, param) {
408    let type = returnInfo.type
409    let valueFillStr = ""
410    if (param.callback) { // callback方法的返回参数处理
411        if (param.callback.isAsync) {
412            // 异步callback方法返回的是一个结构体,包含errcode和data两部分, 详见basic.d.ts中AsyncCallback的定义
413            valueFillStr = "vio->outErrCode"
414            param.valueDefine += "%suint32_t& outErrCode".format(param.valueDefine.length > 0 ? ", " : "")
415        }
416
417        if (type != "void") {
418            // callback<xxx> 中的xxx不是void时,生成的capp代码才需要用户填充out参数
419            valueFillStr += "%svio->out".format(valueFillStr.length > 0 ? ", " : "")
420        }
421    } else {  // 普通方法的返回参数处理
422        valueFillStr = "vio->out"
423    }
424    return valueFillStr
425}
426
427function isObjectType(type) {
428    if(type == "Object" || type == "object") {
429        return true;
430    }
431    return false;
432}
433
434function returnGenerate(returnInfo, param, data) {
435    let type = returnInfo.type
436    let valueFillStr = getReturnFill(returnInfo, param)
437    param.valueFill += ("%s" + valueFillStr).format(param.valueFill.length > 0 ? ", " : "")
438    let outParam = returnInfo.optional ? "(*vio->out)" : "vio->out"
439    let modifiers = returnInfo.optional ? "*" : "&"
440    if (returnInfo.optional) {
441        param.optionalParamDestory += "C_DELETE(vio->out);\n    "
442    }
443
444    if (!isEnum(type, data)) {
445        param.valuePackage = cToJs(outParam, type, "result")
446    } else if (type.indexOf("|") >= 0) {
447        returnGenerateUnion(param)
448    }
449
450    if (type == "string") {
451        param.valueOut = returnInfo.optional ? "std::string* out = nullptr;" : "std::string out;"
452        param.valueDefine += "%sstd::string%s out".format(param.valueDefine.length > 0 ? ", " : "", modifiers)
453    }
454    else if (type == "void") {
455        NapiLog.logInfo("The current void type don't need generate");
456    }
457    else if (type == "boolean") {
458        param.valueOut = returnInfo.optional ? "bool* out = nullptr;" : "bool out;"
459        param.valueDefine += "%sbool%s out".format(param.valueDefine.length > 0 ? ", " : "", modifiers)
460    }
461    else if (isEnum(type, data)) {
462        returnGenerateEnum(data, returnInfo, param)
463    }
464    else if(generateType(type)){
465        returnGenerate2(returnInfo, param, data)
466    }
467    else if (type.substring(0, 12) == "NUMBER_TYPE_") {
468        param.valueOut = type + (returnInfo.optional ? "* out = nullptr;" : " out;")
469        param.valueDefine += "%s%s%s out".format(param.valueDefine.length > 0 ? ", " : "", type, modifiers)
470    }
471    else if (isObjectType(type)) {
472        returnGenerateObject(returnInfo, param, data)
473    }
474    else {
475        NapiLog.logError("Do not support returning the type [%s].".format(type));
476    }
477}
478
479function generateType(type){
480    if (InterfaceList.getValue(type)) {
481        return true
482    }
483    else if (type.substring(0, 6) == "Array<") {
484        return true
485    }
486    else if (type.substring(type.length - 2) == "[]") {
487        return true
488    }
489    else if (type.substring(0, 4) == "Map<" || type.indexOf("{[key:") == 0) {
490        return true
491    }
492    else if (type == "any" || type == "Object" || type == "object") {
493        return true
494    }
495    else {
496        return false
497    }
498}
499function isMapType(type) {
500    if(type.substring(0, 4) == "Map<" || type.indexOf("{[key:") == 0) {
501        return true;
502    }
503    return false;
504}
505
506function returnGenerate2(returnInfo, param, data){
507    let type = returnInfo.type
508    let modifiers = returnInfo.optional ? "*" : "&"
509
510    if (InterfaceList.getValue(type)) {
511        param.valueOut = type + (returnInfo.optional ? "* out = nullptr;" : " out;")
512        param.valueDefine += "%s%s%s out".format(param.valueDefine.length > 0 ? ", " : "", type, modifiers)
513    }
514    else if (type.substring(0, 6) == "Array<") {
515        let arrayType = getArrayType(type)
516        arrayType = jsType2CType(arrayType)
517        if (arrayType == "any") {
518            param.valueOut = `std::any out;
519            std::string out_type;`
520            param.valueDefine += "%sstd::any &out".format(param.valueDefine.length > 0 ? ", " : "")
521        } else {
522            param.valueOut = returnInfo.optional ? "std::vector<%s>* out = nullptr;".format(arrayType)
523                                             : "std::vector<%s> out;".format(arrayType)
524            param.valueDefine += "%sstd::vector<%s>%s out".format(
525            param.valueDefine.length > 0 ? ", ": "", arrayType, modifiers)
526        }
527    }
528    else if (type.substring(type.length - 2) == "[]") {
529        let arrayType = getArrayTypeTwo(type)
530        arrayType = jsType2CType(arrayType)
531        if (arrayType == "any") {
532            param.valueOut = `std::any out;
533            std::string out_type;`
534            param.valueDefine += "%sstd::any &out".format(param.valueDefine.length > 0 ? ", " : "")
535        } else {
536            param.valueOut = returnInfo.optional ? "std::vector<%s>* out = nullptr;".format(arrayType)
537                                             : "std::vector<%s> out;".format(arrayType)
538            param.valueDefine += "%sstd::vector<%s>%s out".format(
539            param.valueDefine.length > 0 ? ", " : "", arrayType, modifiers)
540        }
541    }
542    else if (isMapType(type)) {
543        returnGenerateMap(returnInfo, param)
544    }
545    else if (type == "any") {
546        param.valueOut = `std::any out;
547            std::string out_type;`
548        param.valueDefine += "%sstd::any &out".format(param.valueDefine.length > 0 ? ", " : "")
549    }
550    else if (isObjectType(type)) {
551        param.valueOut = `std::map<std::string, std::any> out;`
552        param.valueDefine += "%sstd::map<std::string, std::any> &out".format(param.valueDefine.length > 0 ? ", " : "")
553    }
554}
555
556function returnGenerateEnum(data, returnInfo, param) {
557    let type = returnInfo.type
558    let index = enumIndex(type, data)
559    let modifiers = returnInfo.optional ? "*" : "&"
560    if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) {
561        type = "NUMBER_TYPE_" + NumberIncrease.getAndIncrease()
562    } else if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_STRING) {
563        type = "string"
564    } else {
565        NapiLog.logError(`function returnGenerateEnum:this type is not support %s`.format(type));
566        return
567    }
568    param.valuePackage = cToJs("vio->out", type, "result")
569    if (type == "string") {
570        param.valueOut = returnInfo.optional ? "std::string* out = nullptr;" : "std::string out;"
571        param.valueDefine += "%sstd::string%s out".format(param.valueDefine.length > 0 ? ", " : "", modifiers)
572    }
573    else if (type.substring(0, 12) == "NUMBER_TYPE_") {
574        param.valueOut = type + " out;"
575        param.valueDefine += "%s%s%s out".format(param.valueDefine.length > 0 ? ", " : "", type, modifiers)
576    }
577}
578
579module.exports = {
580    cToJs,
581    cToJsForInterface,
582    returnGenerate,
583    returnGenerateEnum
584}
585