diff --git a/src/gen/analyze/interface.js b/src/gen/analyze/interface.js index f95b615f6af4ee719a98ff487fce28ba7bce2be3..17345bebbd00b88c9a7a38731aaf9d7ed3d4a51d 100644 --- a/src/gen/analyze/interface.js +++ b/src/gen/analyze/interface.js @@ -31,20 +31,22 @@ function analyzeInterface(data) {//same as class while (t.length > 0 && t[-1] == ' ')//去除后面的空格 t = t.substring(0, t.length - 1) if (t == "") break//如果t为空直接返回 - let tt = re.match(" *([a-zA-Z0-9_]+) *: *([a-zA-Z_0-9<>]+)", t) + let tt = re.match(" *([a-zA-Z0-9_]+) *: *([a-zA-Z_0-9<>,:{}[\\] ]+)", t) if (tt) {//变量 let valueName = re.getReg(t, tt.regs[1]) let valueType = re.getReg(t, tt.regs[2]) - if (valueType.indexOf("number") >= 0) { + let index = valueType.indexOf("number") + while (index !== -1){ valueType = valueType.replace("number", "NUMBER_TYPE_" + NumberIncrease.getAndIncrease()) + index = valueType.indexOf("number") } result.value.push({ name: valueName, type: valueType }) } - tt = re.match(" *([A-Za-z0-9_]+)\\(([\n a-zA-Z:;=,_0-9?<>{}|]*)\\) *: *([A-Za-z0-9_<>{}:, .]+)", t) + tt = re.match(" *([A-Za-z0-9_]+)\\(([\n a-zA-Z:;=,_0-9?<>{}|[\\]]*)\\) *: *([A-Za-z0-9_<>{}:, .[\\]]+)", t) if (tt) {//函数 let funcDetail = analyzeFunction(re.getReg(t, tt.regs[1]), re.getReg(t, tt.regs[2]), re.getReg(t, tt.regs[3])) diff --git a/src/gen/extend/x_napi_tool.js b/src/gen/extend/x_napi_tool.js index 0cd75ce570d4367a4ad658b2ddd573a77dbbf432..2752e3cc6e85646cd52bcce3bf7d2ffbf42adaef 100644 --- a/src/gen/extend/x_napi_tool.js +++ b/src/gen/extend/x_napi_tool.js @@ -68,6 +68,11 @@ public: uint32_t GetArrayLength(napi_value value); napi_value GetArrayElement(napi_value value, uint32_t p); napi_value SetArrayElement(napi_value &value, uint32_t p, napi_value ele); + + uint32_t GetMapLength(napi_value value); + napi_value GetMapElementName(napi_value value, uint32_t p); + napi_value GetMapElementValue(napi_value value, const char * p); + napi_value SetMapElement(napi_value &value, const char * ele_key, napi_value value); napi_value SyncCallBack(napi_value func, size_t argc, napi_value *args); @@ -273,6 +278,44 @@ napi_value XNapiTool::SetArrayElement(napi_value &value, uint32_t p, napi_value return value; } +uint32_t XNapiTool::GetMapLength(napi_value value) +{ + napi_value name_result; + napi_get_property_names(env_, value, &name_result); + uint32_t ret; + napi_status result_status = napi_get_array_length(env_, name_result, &ret); + CC_ASSERT(result_status == napi_ok); + return ret; +} + +napi_value XNapiTool::GetMapElementName(napi_value value, uint32_t p) +{ + napi_value result; + napi_status result_status = napi_get_element(env_, value, p, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::GetMapElementValue(napi_value value, const char * utf8Name) +{ + napi_value result; + napi_status result_status = napi_get_named_property(env_, value, utf8Name, &result); + CC_ASSERT(result_status == napi_ok); + return result; +} + +napi_value XNapiTool::SetMapElement(napi_value &value, const char * ele_key, napi_value ele_value) +{ + napi_status result_status; + if (value == nullptr) { + result_status = napi_create_object(env_, &value); + CC_ASSERT(result_status == napi_ok); + } + result_status = napi_set_named_property(env_, value, ele_key, ele_value); + CC_ASSERT(result_status == napi_ok); + return value; +} + bool XNapiTool::CheckFailed(bool b, const char *errStr) { if (bFailed_) { diff --git a/src/gen/generate.js b/src/gen/generate.js index 267701d004bafd74ca72bd447ec1db72a5a2758e..14e5aa6ebb8433b11262432a5b26958c6869b4a9 100644 --- a/src/gen/generate.js +++ b/src/gen/generate.js @@ -100,6 +100,7 @@ let implHTemplete = `\ #include #include #include +#include [numberUsing] diff --git a/src/gen/generate/interface.js b/src/gen/generate/interface.js index cf81017cd37542afa34bdb939568725d1444c351..78129a25f1f5f161f5aa003e623ed78b558532b1 100644 --- a/src/gen/generate/interface.js +++ b/src/gen/generate/interface.js @@ -15,7 +15,7 @@ const { generateFunctionDirect } = require("./function_direct"); const { generateFunctionSync } = require("./function_sync"); const { generateFunctionAsync } = require("./function_async"); -const { FuncType, InterfaceList, getArrayType } = require("../tools/common"); +const { FuncType, InterfaceList, getArrayType, getMapType } = require("../tools/common"); const { jsToC } = require("./param_generate"); const { cToJs } = require("./return_generate"); const re = require("../tools/re"); @@ -55,6 +55,8 @@ function generateVariable(name, type, variable, className) { variable.hDefine += "\n bool %s;".format(name) } else if (type.indexOf("[]") == 0) { variable.hDefine += "\n std::vector<%s> %s;".format(type, name) + } else if (type.indexOf("{") == 0) { + variable.hDefine += mapTypeString(type, name) } else NapiLog.logError(` @@ -80,6 +82,34 @@ function generateVariable(name, type, variable, className) { ` } +function mapTypeString(type, name){ + let mapType = getMapType(type) + let mapTypeString + if (mapType[1] != undefined && mapType[2] == undefined){ + if (mapType[1] == "string") mapTypeString = "std::string,std::string" + else if (mapType[1] == "boolean") mapTypeString = "std::string,bool" + else if (mapType[1].substring(0,12) == "NUMBER_TYPE_") { + mapTypeString = "std::string,%s".format(mapType[1]) + } + else if (InterfaceList.getValue(mapType[1])) mapTypeString = "std::string,%s".format(mapType[1]) + } + if (mapType[2] != undefined){ + if (mapType[2] == "string") mapTypeString = "std::string,std::map" + else if (mapType[2] == "boolean") mapTypeString = "std::string,std::map" + else if (mapType[2].substring(0,12) == "NUMBER_TYPE_") { + mapTypeString = "std::string,std::map".format(mapType[2]) + } + } + if (mapType[3] != undefined){ + if (mapType[3] == "string") mapTypeString = "std::string,std::vector" + else if (mapType[3] == "boolean") mapTypeString = "std::string,std::vector" + else if (mapType[3].substring(0,12) == "NUMBER_TYPE_") { + mapTypeString = "std::string,std::vector<%s>".format(mapType[3]) + } + } + return "\n std::map<%s> %s;".format(mapTypeString, name); +} + function generateInterface(name, data, inNamespace) { let resultConnect = connectResult(data, inNamespace, name) let middleFunc = resultConnect[0] diff --git a/src/gen/generate/param_generate.js b/src/gen/generate/param_generate.js index 5084a895e4e7c712d52a724e406da425854a81ef..7ad20e146cc070a6e57eefab5e5062c6ddeca60b 100644 --- a/src/gen/generate/param_generate.js +++ b/src/gen/generate/param_generate.js @@ -13,7 +13,7 @@ * limitations under the License. */ const { InterfaceList, getArrayType, getArrayTypeTwo, NumberIncrease, - enumIndex, isEnum, EnumValueType } = require("../tools/common"); + enumIndex, isEnum, EnumValueType, getMapType } = require("../tools/common"); const re = require("../tools/re"); const { NapiLog } = require("../tools/NapiLog"); @@ -69,7 +69,9 @@ function jsToC(dest, napiVn, type) { else if (type == "boolean") { return `BOOLEAN_JS_2_C(%s,%s,%s);`.format(napiVn, "bool", dest) } - + else if (type.indexOf("{") == 0) { + return mapTempleteFunc(dest, napiVn, type); + } else NapiLog.logError(`do not support to generate jsToC %s,%s,%s`.format(dest, napiVn, type)); } @@ -147,6 +149,231 @@ function paramGenerateEnum(data, type, param, name, p) { paramGenerate(p, name, type, param, data) } +function paramGenerateMap(type, param, p, name){ + let mapType = getMapType(type) + if(mapType[1] != undefined && mapType[2] == undefined){ + let mapTypeString + if (mapType[1] == "string") {mapTypeString = "std::string"} + else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") {mapTypeString = mapType[1]} + else if (mapType[1] == "boolean") {mapTypeString = "bool"} + param.valueIn += "\n std::map in%d;".format(mapTypeString, p) + param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) + param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) + param.valueDefine += "%sstd::map &%s" + .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString, name) + } +} + +function mapTempleteFunc (dest, napiVn, type) { + let mapType = getMapType(type) + let lt = LenIncrease.getAndIncrease() + let mapTemplete = "" + if(mapType[1] != undefined && mapType[2] == undefined){ + mapTemplete = mapValue(mapType, napiVn, dest, lt) + } + else if(mapType[2] != undefined){ + mapTemplete = mapMap(mapType, napiVn, dest, lt) + } + else if(mapType[3] != undefined){ + mapTemplete = mapArray(mapType, napiVn, dest, lt) + } + return mapTemplete +} + +let mapValueTemplete = `\ +uint32_t len[replace_lt]=pxt->GetMapLength(%s); +for(uint32_t i[replace_lt]=0;i[replace_lt]%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(0),tt%d.c_str()),%sName.c_str()),%s);" + .format(lt+1,interfaceValue[i].name,"SwapJs2CUtf8","GetMapElementValue", + lt,interfaceValue[i].name,interfaceValue[i].name) + } + else if(interfaceValue[i].type.substring(0, 12) == "NUMBER_TYPE_"){ + interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name,interfaceValue[i].name) + interfaceVar += `std::string %s;\n`.format(interfaceValue[i].name) + interfaceFun += + "%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(0),tt%d.c_str()),%sName.c_str()),%s,tt%d.%s);\n" + .format("NUMBER_JS_2_C","GetMapElementValue",lt,interfaceValue[i].name, + interfaceValue[i].type,lt+1,interfaceValue[i].name) + } + else if (interfaceValue[i].type == 'boolean'){ + interfaceVarName += `std::string %dName = "%d";\n`.format(interfaceValue[i].name,interfaceValue[i].name) + interfaceVar += `std::string %s;\n`.format(interfaceValue[i].name) + interfaceFun += + "tt%d.%s = pxt->%s(pxt->%s(pxt->GetMapElementValue(pxt->GetArgv(0),tt%d.c_str()),%sName.c_str()),%s);\n" + .format(lt+1,interfaceValue[i].name,"SwapJs2CBool","GetMapElementValue", + lt,interfaceValue[i].name,interfaceValue[i].name) + } + } + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + %d + %d + %d`.format(napiVn, lt, lt, interfaceVarName, interfaceVar, interfaceFun)) + return mapTemplete +} + +function mapValue(mapType, napiVn, dest, lt){ + let mapTypeString + if (mapType[1] == "string") {mapTypeString = "std::string"} + else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") {mapTypeString = mapType[1]} + else if (mapType[1] == "boolean") {mapTypeString = "bool"} + else if (mapType[1] != null) {mapTypeString = mapType[1]} + let mapTemplete = mapValueTemplete.format(napiVn, mapTypeString, dest) + mapTemplete = mapTemplete.replaceAll("[replace_lt]", lt) + mapTemplete = mapTemplete.replaceAll("[replace_lt+1]", lt+1) + if (mapTypeString == "std::string") { + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + pxt->SwapJs2CUtf8(pxt->GetMapElementValue(%s,tt%d.c_str()), tt%d);` + .format(napiVn, lt, lt, napiVn, lt, lt+1)) + } + else if (mapTypeString.substring(0, 12) == "NUMBER_TYPE_") { + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + NUMBER_JS_2_C(pxt->GetMapElementValue(%s,tt%d.c_str()),%s,tt%d);` + .format(napiVn, lt, lt, napiVn, lt, mapTypeString, lt+1)) + } + else if (mapTypeString == "bool") { + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + tt%d = pxt->SwapJs2CBool(pxt->GetMapElementValue(%s,tt%d.c_str()));` + .format(napiVn, lt, lt, lt+1, napiVn, lt)) + } + else if (InterfaceList.getValue(mapTypeString)) { + mapTemplete = mapInterface(mapTypeString, mapTemplete, napiVn, lt) + } + return mapTemplete +} + +let mapMapTemplete = `\ +uint32_t len[replace_lt]=pxt->GetMapLength(%s); +for(uint32_t i[replace_lt]=0;i[replace_lt] tt[replace_lt+1]; + [replace_swap] + %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); +}` + +function mapMap(mapType, napiVn, dest, lt){ + let mapTypeString + if (mapType[2] == "string") {mapTypeString = "std::string"} + else if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") {mapTypeString = mapType[2]} + else if (mapType[2] == "boolean") {mapTypeString = "bool"} + let mapTemplete = mapMapTemplete.format(napiVn, mapTypeString, dest) + mapTemplete = mapTemplete.replaceAll("[replace_lt]", lt) + mapTemplete = mapTemplete.replaceAll("[replace_lt+1]", lt+1) + if(mapType[2] == "string"){ + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + uint32_t len%d=pxt->GetMapLength(pxt->GetMapElementValue(%s,tt%d.c_str())); + for(uint32_t i%d=0;i%dSwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s,tt%d.c_str()), i%d),tt%d); + pxt->SwapJs2CUtf8(pxt->GetMapElementValue(pxt->GetMapElementValue(%s,tt%d.c_str()),tt%d.c_str()),tt%d); + tt%d.insert(std::make_pair(tt%d, tt%d)); + }`.format(napiVn, lt, lt, lt+1, napiVn, lt, lt+1, lt+1, lt+1, lt+1, + lt+2, lt+3,napiVn, lt ,lt+1,lt+2, napiVn, lt ,lt+2, lt+3 ,lt+1, lt+2, lt+3)) + } + else if(mapType[2] == "boolean"){ + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + uint32_t len%d=pxt->GetMapLength(pxt->GetMapElementValue(%s,tt%d.c_str())); + for(uint32_t i%d=0;i%dSwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s,tt%d.c_str()), i%d),tt%d); + pxt->SwapJs2CBool(pxt->GetMapElementValue(pxt->GetMapElementValue(%s,tt%d.c_str()),tt%d.c_str()),tt%d); + tt%d.insert(std::make_pair(tt%d, tt%d)); + }`.format(napiVn, lt, lt, lt+1, napiVn, lt, lt+1, lt+1, lt+1, lt+1, + lt+2, lt+3,napiVn, lt ,lt+1,lt+2, napiVn, lt ,lt+2, lt+3 ,lt+1, lt+2, lt+3)) + } + else if(mapType[2].substring(0, 12) == "NUMBER_TYPE_"){ + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%d), tt%d); + uint32_t len%d=pxt->GetMapLength(pxt->GetMapElementValue(%s,tt%d.c_str())); + for(uint32_t i%d=0;i%dSwapJs2CUtf8(pxt->GetMapElementName(pxt->GetMapElementValue(%s,tt%d.c_str()), i%d),tt%d); + NUMBER_JS_2_C(pxt->GetMapElementValue(pxt->GetMapElementValue(%s,tt%d.c_str()),tt%d.c_str()),%s,tt%d); + tt%d.insert(std::make_pair(tt%d, tt%d)); + }`.format(napiVn, lt, lt, lt+1, napiVn, lt, lt+1, lt+1, lt+1, lt+1, + lt+2, mapTypeString, lt+3, napiVn, lt ,lt+1, lt+2, napiVn, lt ,lt+2, + mapTypeString, lt+3 ,lt+1, lt+2, lt+3)) + } + return mapTemplete +} + +let mapArrayTemplete = `\ +uint32_t len[replace_lt]=pxt->GetMapLength(%s); +for(uint32_t i[replace_lt]=0;i[replace_lt] tt[replace_lt+1]; + [replace_swap] + %s.insert(std::make_pair(tt[replace_lt], tt[replace_lt+1])); +}` + +function mapArray(mapType, napiVn, dest, lt){ + let mapTypeString + if (mapType[3] == "string") {mapTypeString = "std::string"} + else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") {mapTypeString = mapType[3]} + else if (mapType[3] == "boolean") {mapTypeString = "bool"} + let mapTemplete = mapArrayTemplete.format(napiVn, mapTypeString, dest) + mapTemplete = mapTemplete.replaceAll("[replace_lt]", lt) + mapTemplete = mapTemplete.replaceAll("[replace_lt+1]", lt+1) + if(mapType[3] == "string"){ + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%s), tt%d); + uint32_t len%s=pxt->GetArrayLength(pxt->GetMapElementValue(%s,tt%d.c_str())); + for(uint32_t i%d=0;i%dSwapJs2CUtf8(pxt->GetArrayElement(pxt->GetMapElementValue(%s,tt%d.c_str()),i%d), tt%d); + tt%d.push_back(tt%d); + }`.format(napiVn, lt, lt, lt+1, napiVn, lt, lt+1, lt+1, lt+1, + lt+1, lt+2, napiVn, lt, lt, lt+2 ,lt+1, lt+2)) + } + else if(mapType[3] == "boolean"){ + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%s), tt%d); + uint32_t len%s=pxt->GetArrayLength(pxt->GetMapElementValue(%s,tt%d.c_str())); + for(uint32_t i%d=0;i%dSwapJs2CBool(pxt->GetArrayElement(pxt->GetMapElementValue(%s,tt%d.c_str()),i%d), tt%d); + tt%d.push_back(tt%d); + }`.format(napiVn, lt, lt, lt+1, napiVn, lt, lt+1, lt+1, lt+1, + lt+1, lt+2, napiVn, lt, lt, lt+2 ,lt+1, lt+2)) + } + else if(mapType[3].substring(0, 12) == "NUMBER_TYPE_"){ + mapTemplete = mapTemplete.replaceAll("[replace_swap]", + `pxt->SwapJs2CUtf8(pxt->GetMapElementName(%s,i%s), tt%d); + uint32_t len%s=pxt->GetArrayLength(pxt->GetMapElementValue(%s,tt%d.c_str())); + for(uint32_t i%d=0;i%dGetArrayElement(pxt->GetMapElementValue(%s,tt%d.c_str()),i%d), %s, tt%d); + tt%d.push_back(tt%d); + }`.format(napiVn, lt, lt, lt+1, napiVn, lt, lt+1, lt+1, lt+1, + lt+1, mapTypeString ,lt+2, napiVn, lt, lt, mapTypeString,lt+2 ,lt+1, lt+2)) + } + return mapTemplete +} + // 函数的参数处理 function paramGenerate(p, name, type, param, data) { if (type == "string") { @@ -183,6 +410,9 @@ function paramGenerate(p, name, type, param, data) { else if (isEnum(type, data)) { paramGenerateEnum(data, type, param, name, p) } + else if (type.indexOf("{") == 0) { + paramGenerateMap(type, param, p, name) + } else { paramGenerateArray(p, name, type, param); } diff --git a/src/gen/generate/return_generate.js b/src/gen/generate/return_generate.js index d6f923749d1a546f693d0290cd614622d3a8785b..2849f3662bd8afe03108152ea7e6c914c550c54a 100644 --- a/src/gen/generate/return_generate.js +++ b/src/gen/generate/return_generate.js @@ -13,7 +13,7 @@ * limitations under the License. */ const { InterfaceList, getArrayType, NumberIncrease, enumIndex, - isEnum, EnumValueType, getArrayTypeTwo } = require("../tools/common"); + isEnum, EnumValueType, getArrayTypeTwo, getMapType} = require("../tools/common"); const { NapiLog } = require("../tools/NapiLog"); function cToJs(value, type, dest, deep = 1) { @@ -41,7 +41,28 @@ function cToJs(value, type, dest, deep = 1) { } else if (type.substring(0, 6) == "Array<" || type.substring(type.length - 2) == "[]") { let arrayType = checkArrayParamType(type) - let lt = deep + return arrayTempleteFunc(arrayType, deep, dest, value) + } + else if (type.substring(0, 1) == "{" ) { + return mapTempleteFunc(type, deep, dest, value) + } + else + NapiLog.logError(`This type do not generate cToJs %s,%s,%s`.format(value, type, dest)); +} + +function checkArrayParamType(type) { + let arrayType + if (type.substring(type.length - 2) == "[]") { + arrayType = getArrayTypeTwo(type) + } + else { + arrayType = getArrayType(type) + } + return arrayType +} + +function arrayTempleteFunc(arrayType, deep, dest, value){ + let lt = deep let tnv = dest let tnvdef = `uint32_t len%d=%s.size(); for(uint32_t i=0;iSetMapElement(%s, tnv%d, tnv%d); + }`.format(value, value, lt, lt+1, tnv, lt, lt+1) + let ret = "" + if (mapType[1] != undefined && mapType[2] == undefined){ + ret = mapTempleteValue(mapType, tnvdef, lt, value, tnv) + } + else if (mapType[2] != undefined){ + ret = mapTempleteMap(mapType, tnvdef, lt) + } + else if(mapType[3] != undefined){ + ret = mapTempleteArray(mapType, tnvdef, lt) + } + return ret +} + +function mapInterface(value, lt, tnv, mapType){ + let ret + let tnvdefInterface = `for (auto i = %s.begin(); i != %s.end(); i++) + { + const char *tnv%d; + [calc_out] + }`.format(value, value, lt, lt+1, tnv, lt, lt+1) + let interfaceValue = InterfaceList.getValue(mapType[1]) + let interfaceVarName = "" + let interfaceVar = "" + let interfaceFun = "" + for (let i = 0; i < interfaceValue.length; i++){ + if(interfaceValue[i].type == 'string'){ + interfaceVarName += `const char * tnv_%s_name; + napi_value tnv_%s = nullptr;\n`.format(interfaceValue[i].name,interfaceValue[i].name) + interfaceVar += `tnv_%s_name = "%s"; + tnv_%s = pxt->SwapC2JsUtf8(i->second.%s.c_str());\n` + .format(interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name) + interfaceFun += `pxt->SetMapElement(result_obj, tnv_%s_name, tnv_%s);\n` + .format(interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name) + } + else if(interfaceValue[i].type.substring(0, 12) == "NUMBER_TYPE_"){ + interfaceVarName += `const char * tnv_%s_name; + napi_value tnv_%s = nullptr;\n`.format(interfaceValue[i].name,interfaceValue[i].name) + interfaceVar += `tnv_%s_name = "%s"; + tnv_%s = NUMBER_C_2_JS(pxt,i->second.%s);\n` + .format(interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name) + interfaceFun += `pxt->SetMapElement(result_obj, tnv_%s_name, tnv_%s);\n` + .format(interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name) + } + else if(interfaceValue[i].type == 'boolean'){ + interfaceVarName += `const char * tnv_%s_name; + napi_value tnv_%s = nullptr;\n`.format(interfaceValue[i].name,interfaceValue[i].name) + interfaceVar += `tnv_%s_name = "%s"; + tnv_%s = pxt->SwapC2JsBool(i->second.%s);\n` + .format(interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name) + interfaceFun += `pxt->SetMapElement(result_obj, tnv_%s_name, tnv_%s);\n` + .format(interfaceValue[i].name,interfaceValue[i].name,interfaceValue[i].name) + } + } + ret = tnvdefInterface.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str(); + napi_value result_obj; + %s + %s + %s + pxt->SetMapElement(result, tnv%d, result_obj);` + .format(lt,interfaceVarName,interfaceVar,interfaceFun,lt)) + return ret +} + +function mapTempleteValue(mapType, tnvdef, lt, value, tnv){ + let ret + if (mapType[1] == "string") { + ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str(); + tnv%d = pxt->SwapC2JsUtf8(i->second.c_str());`.format(lt ,lt+1)) + }else if (mapType[1] == "boolean") { + ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str(); + tnv%d = pxt->SwapC2JsBool(i->second);`.format(lt, lt+1)) + }else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") { + ret = tnvdef.replaceAll("[calc_out]", `tnv%d = (i -> first).c_str(); + tnv%d = NUMBER_C_2_JS(pxt,i->second);`.format(lt, lt+1)) + } + else if (InterfaceList.getValue(mapType[1])){ + ret = mapInterface(value, lt, tnv, mapType) } else NapiLog.logError(`This type do not generate cToJs %s,%s,%s`.format(value, type, dest)); + return ret } -function checkArrayParamType(type) { - let arrayType - if (type.substring(type.length - 2) == "[]") { - arrayType = getArrayTypeTwo(type) +function mapTempleteMap(mapType, tnvdef, lt){ + let ret + if (mapType[2] == "string") { + ret = tnvdef.replaceAll("[calc_out]", `std::string tt%d = i->first; + for(auto j = i->second.begin(); j != i->second.end(); j++){ + const char * tt%d; + napi_value tt%d; + tt%d = j->first.c_str(); + tt%d = pxt->SwapC2JsUtf8(j->second.c_str()); + pxt->SetMapElement(tnv%d, tt%d, tt%d); + }`.format(lt, lt+2, lt+3, lt+2, lt+3, lt+1, lt+2, lt+3)) } - else { - arrayType = getArrayType(type) + else if (mapType[2] == "boolean") { + ret = tnvdef.replaceAll("[calc_out]", `std::string tt%d = i->first; + for(auto j = i->second.begin(); j != i->second.end(); j++){ + const char * tt%d; + napi_value tt%d; + tt%d = j->first.c_str(); + tt%d = pxt->SwapC2JsBool(j->second); + pxt->SetMapElement(tnv%d, tt%d, tt%d); + }`.format(lt, lt+2, lt+3, lt+2, lt+3, lt+1, lt+2, lt+3)) } - return arrayType + if (mapType[2].substring(0, 12) == "NUMBER_TYPE_") { + ret = tnvdef.replaceAll("[calc_out]", `std::string tt%d = i->first; + for(auto j = i->second.begin(); j != i->second.end(); j++){ + const char * tt%d; + napi_value tt%d; + tt%d = j->first.c_str(); + tt%d = NUMBER_C_2_JS(pxt,j->second); + pxt->SetMapElement(tnv%d, tt%d, tt%d); + }`.format(lt, lt+2, lt+3, lt+2, lt+3, lt+1, lt+2, lt+3)) + } + return ret +} + +function mapTempleteArray(mapType, tnvdef, lt){ + let ret + if (mapType[3] == "string") { + ret = tnvdef.replaceAll("[calc_out]", `napi_value tnv%d = nullptr; + tnv%d = (i -> first).c_str(); + uint32_t len%d = i->second.size(); + for(uint32_t j=0;jSwapC2JsUtf8(i->second[j].c_str()); + pxt->SetArrayElement(tnv%d, j, tnv%d); + }`.format(lt+2, lt, lt, lt, lt+1, lt+2, lt+1)) + }else if (mapType[3] == "boolean") { + ret = tnvdef.replaceAll("[calc_out]", `napi_value tnv%d = nullptr; + tnv%d = (i -> first).c_str(); + uint32_t len%d = i->second.size(); + for(uint32_t j=0;jSwapC2JsBool(i->second[j]); + pxt->SetArrayElement(tnv%d, j, tnv%d); + }`.format(lt+2, lt, lt, lt, lt+1, lt+2, lt+1)) + }else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { + ret = tnvdef.replaceAll("[calc_out]", `napi_value tnv%d = nullptr; + tnv%d = (i -> first).c_str(); + uint32_t len%d = i->second.size(); + for(uint32_t j=0;jsecond[j]); + pxt->SetArrayElement(tnv%d, j, tnv%d); + }`.format(lt+2, lt, lt, lt, lt+1, lt+2, lt+1)) + } + return ret +} + +function returnGenerateMap(type, param){ + let mapType = getMapType(type) + if(mapType[1] != undefined && mapType[2] == undefined){ + let mapTypeString + if (mapType[1] == "string") { + mapTypeString = "std::string" + } + else if (mapType[1].substring(0, 12) == "NUMBER_TYPE_") { + mapTypeString = mapType[1] + } + else if (mapType[1] == "boolean") { + mapTypeString = "bool" + } + param.valueOut = "std::map out;".format(mapTypeString) + param.valueDefine += "%sstd::map &out" + .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString) + } } function returnGenerate(type, param, data) { @@ -115,6 +300,9 @@ function returnGenerate(type, param, data) { param.valueOut = "std::vector<%s> out;".format(arrayType) param.valueDefine += "%sstd::vector<%s> &out".format(param.valueDefine.length > 0 ? ", " : "", arrayType) } + else if (type.substring(0, 1) == "{") { + returnGenerateMap(type, param) + } else { NapiLog.logError("The current version do not support this type return %s`.format(type)"); } diff --git a/src/gen/test.js b/src/gen/test.js index fb05591b0b4ebd6f07ad3e339f6177f8595df6dd..e18db25f35ed85ac990558fa7fdf22e8633bf88f 100644 --- a/src/gen/test.js +++ b/src/gen/test.js @@ -13,4 +13,4 @@ * limitations under the License. */ const main = require("./main"); -main.doGenerate("nodejs_test/gen/@ohos.napitest.d.ts"); \ No newline at end of file +main.doGenerate("nodejs_test/gen/@ohos.napitest.d.ts","nodejs_test/gen/out"); \ No newline at end of file diff --git a/src/gen/tools/common.js b/src/gen/tools/common.js index 6d3030675b925e7ce85a9e8b281505177b2aac6c..b0c5721187576344b1edf285ae2802dda7fea21b 100644 --- a/src/gen/tools/common.js +++ b/src/gen/tools/common.js @@ -122,6 +122,34 @@ function enumIndex(type, data) { return index } +function getMapType(type) { + type = type.replace(/\s*/g,"") + let tt1 = re.search("Map<([a-zA-Z_0-9]+),", type) + let tt2 = re.search(",([a-zA-Z_0-9]+)>", type) + let tt3 + let tt4 + + let valueType + let valueMapType + let valueArrayType + if(tt1 == null && tt2 == null){ + tt1 = re.search("key:([a-zA-Z_0-9]+)", type) + tt2 = re.search(":([a-zA-Z_0-9]+)}", type) + tt3 = re.search(":([a-zA-Z_0-9]+)}}", type) + tt4 = re.search("Array<([a-zA-Z_0-9]+)>", type) + } + if(tt2 != null){ + valueType = re.getReg(type, tt2.regs[1]) + } + if(tt3 != null){ + valueMapType = re.getReg(type, tt3.regs[1]) + } + if(tt4 != null){ + valueArrayType = re.getReg(type, tt4.regs[1]) + } + return [re.getReg(type, tt1.regs[1]), valueType, valueMapType, valueArrayType] +} + module.exports = { FuncType, EnumValueType, @@ -131,5 +159,6 @@ module.exports = { getArrayTypeTwo, checkFileError, isEnum, - enumIndex + enumIndex, + getMapType } \ No newline at end of file diff --git a/test/storytest/test_map/@ohos.test.d.ts b/test/storytest/test_map/@ohos.test.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..9622008779737cbe00c7373f33c7c9f5f22e0bef --- /dev/null +++ b/test/storytest/test_map/@ohos.test.d.ts @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +declare namespace napitest { + interface TestClass1 { + map1 : {[key: string]: number} ; + map2 : {[key: string]: string} ; + map3 : {[key: string]: boolean} ; + } + + interface TestClass2 { + fun1(v: {[key: string]: string}): {[key: string]: string}; + fun1(v: {[key: string]: number}): {[key: string]: number}; + fun1(v: {[key: string]: boolean}): {[key: string]: boolean}; + } +} +export default napitest; \ No newline at end of file diff --git a/test/storytest/test_map/test.js b/test/storytest/test_map/test.js new file mode 100644 index 0000000000000000000000000000000000000000..7ed0fa72abb846b55fb12f2ea7dd673819fd0584 --- /dev/null +++ b/test/storytest/test_map/test.js @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const { TestClass1,TestClass2 } = require("./out/build/Release/napitest") +var assert = require("assert"); + +describe('Map', function () { + + it('test fun1', function () { + let testMap1 = {"name":"jonas","age":"18"}; + let ret = fun1(testMap1); + assert.strictEqual(ret, {}); + }); + + it('test fun2', function () { + let testMap2 = {"name": 666,"age": 18}; + let ret = fun1(testMap2); + assert.strictEqual(ret, {}); + }); + + it('test fun3', function () { + let testMap3 = {"name": true,"age": false}; + let ret = fun1(testMap3); + assert.strictEqual(ret, {}); + }); + +}); \ No newline at end of file