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