From 73e5f3d12960fc034de0c7474d44d55ca3c379cf Mon Sep 17 00:00:00 2001 From: liuycag Date: Tue, 9 Aug 2022 10:13:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Eany=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liuycag --- src/gen/extend/x_napi_tool.js | 254 ++++++++++++++++++++++++ src/gen/generate.js | 1 + src/gen/generate/interface.js | 9 + src/gen/generate/param_generate.js | 59 ++++-- src/gen/generate/return_generate.js | 19 ++ test/storytest/test_any/@ohos.test.d.ts | 23 +++ test/storytest/test_any/test.js | 45 +++++ 7 files changed, 393 insertions(+), 17 deletions(-) create mode 100644 test/storytest/test_any/@ohos.test.d.ts create mode 100644 test/storytest/test_any/test.js diff --git a/src/gen/extend/x_napi_tool.js b/src/gen/extend/x_napi_tool.js index 2967ac7f..9f431f1a 100644 --- a/src/gen/extend/x_napi_tool.js +++ b/src/gen/extend/x_napi_tool.js @@ -23,6 +23,7 @@ let xNapiToolH = `\ #include #include #include +#include #include #include @@ -86,6 +87,10 @@ public: napi_value GetMapElementValue(napi_value value, const char * p); napi_value SetMapElement(napi_value &value, const char * ele_key, napi_value ele_value); + std::string GetAnyType(napi_value object); + void SetAnyValue(std::string &any_type, napi_value argv, std::any &any); + void GetAnyValue (std::string any_type, napi_value &result, std::any any); + napi_value SyncCallBack(napi_value func, size_t argc, napi_value *args); napi_value StartAsync(CallbackFunction pe, void *data, CallbackFunction pc, napi_value func = nullptr); @@ -331,6 +336,255 @@ napi_value XNapiTool::SetMapElement(napi_value &value, const char * ele_key, nap return value; } +std::string XNapiTool::GetAnyType(napi_value object){ + napi_valuetype result; + napi_typeof(env_, object, &result); + if (result == napi_string) { + return "string"; + } else if (result == napi_number) { + return "number"; + } else if (result == napi_boolean) { + return "boolean"; + } else if (result == napi_object) { + bool is_array; + napi_is_array(env_, object, &is_array); + if (is_array) { + napi_value arr_value_result; + napi_valuetype arr_type_result; + napi_get_element (env_, object, 0, &arr_value_result); + napi_typeof(env_, arr_value_result, &arr_type_result); + if (arr_type_result == napi_string) { + return "arr_string"; + } else if (arr_type_result == napi_number) { + return "arr_number"; + } else if (arr_type_result == napi_boolean) { + return "arr_boolean"; + } + } + napi_value obj_name_value; + napi_value obj_name_result; + napi_valuetype obj_name_type; + std::string obj_name_string; + napi_get_property_names (env_, object, &obj_name_value); + napi_get_element (env_, obj_name_value, 0, &obj_name_result); + napi_typeof(env_, obj_name_result, &obj_name_type); + if (obj_name_type == napi_string) { + napi_value obj_value; + napi_valuetype obj_value_type; + SwapJs2CUtf8(obj_name_result, obj_name_string); + napi_get_named_property (env_, object, obj_name_string.c_str(), &obj_value); + napi_typeof(env_, obj_value, &obj_value_type); + if (obj_value_type == napi_string) { + return "map_string"; + } else if (obj_value_type == napi_number) { + return "map_number"; + } else if (obj_value_type == napi_boolean) { + return "map_boolean"; + } + } + } else { + return nullptr; + } +} + +void XNapiTool::SetAnyValue(std::string &any_type, napi_value argv, std::any &any) +{ + if (any_type == "string") { + std::string any_string; + SwapJs2CUtf8(argv, any_string); + any = any_string; + return; + } else if (any_type == "boolean") { + bool any_bool; + any_bool = SwapJs2CBool(argv); + any = any_bool; + return; + } else if (any_type == "number") { + std::uint32_t any_number; + any_number = SwapJs2CInt32(argv); + any = any_number; + return; + } else if (any_type.substr(0,3) == "arr") { + uint32_t len=GetArrayLength(argv); + if (any_type == "arr_string") { + std::vector any_arr_string; + for(uint32_t i=0;i any_arr_number; + for(uint32_t i=0;i any_arr_boolean; + for(uint32_t i=0;i any_map_string; + for(uint32_t i=0;i any_map_number; + for(uint32_t i=0;i any_map_boolean; + for(uint32_t i=0;i(any); + result = SwapC2JsUtf8(any_string.c_str()); + return; + } else if (any_type == "boolean") { + bool any_bool = std::any_cast(any); + result = SwapC2JsBool(any_bool); + return; + } else if (any_type == "number") { + std::uint32_t any_number = std::any_cast(any); + if (typeid(any_number) == typeid(int32_t)) + result = SwapC2JsInt32(any_number); + else if (typeid(any_number) == typeid(uint32_t)) + result = SwapC2JsUint32(any_number); + else if (typeid(any_number) == typeid(int64_t)) + result = SwapC2JsInt64(any_number); + else if (typeid(any_number) == typeid(double_t)) + result = SwapC2JsDouble(any_number); + return; + } else if (any_type.substr(0,3) == "arr") { + result = nullptr; + if (any_type == "arr_string") { + std::vector any_arr_string = std::any_cast>(any); + uint32_t len=any_arr_string.size(); + for(uint32_t i=0;i any_arr_number = std::any_cast>(any); + uint32_t len=any_arr_number.size(); + for(uint32_t i=0;i any_arr_boolean = std::any_cast>(any); + uint32_t len=any_arr_boolean.size(); + for(uint32_t i=0;i any_map_string = std::any_cast>(any); + for (auto i = any_map_string.begin(); i != any_map_string.end(); i++) + { + const char * tnv1; + napi_value tnv2 = nullptr; + tnv1 = (i -> first).c_str(); + tnv2 = SwapC2JsUtf8(i->second.c_str()); + SetMapElement(result, tnv1, tnv2); + } + return; + } else if (any_type == "map_number") { + std::map any_map_number = std::any_cast>(any); + for (auto i = any_map_number.begin(); i != any_map_number.end(); i++) + { + const char * tnv1; + napi_value tnv2 = nullptr; + tnv1 = (i -> first).c_str(); + if (typeid(i->second) == typeid(int32_t)){ + tnv2 = SwapC2JsInt32(i->second); + } + else if (typeid(i->second) == typeid(uint32_t)){ + tnv2 = SwapC2JsUint32(i->second); + } + else if (typeid(i->second) == typeid(int64_t)){ + tnv2 = SwapC2JsInt64(i->second); + } + else if (typeid(i->second) == typeid(double_t)){ + tnv2 = SwapC2JsDouble(i->second); + } + SetMapElement(result, tnv1, tnv2); + } + return; + } else if (any_type == "map_boolean") { + std::map any_map_boolean = std::any_cast>(any); + for (auto i = any_map_boolean.begin(); i != any_map_boolean.end(); i++) + { + const char * tnv1; + napi_value tnv2 = nullptr; + tnv1 = (i -> first).c_str(); + tnv2 = SwapC2JsBool(i->second); + SetMapElement(result, tnv1, tnv2); + } + return; + } + } +} + bool XNapiTool::CheckFailed(bool b, const char *errStr) { if (bFailed_) { diff --git a/src/gen/generate.js b/src/gen/generate.js index 22c964f5..758c0d52 100644 --- a/src/gen/generate.js +++ b/src/gen/generate.js @@ -120,6 +120,7 @@ let implHTemplete = `\ #include #include #include +#include [numberUsing] diff --git a/src/gen/generate/interface.js b/src/gen/generate/interface.js index 3f7c2e43..29a0fadc 100644 --- a/src/gen/generate/interface.js +++ b/src/gen/generate/interface.js @@ -59,6 +59,8 @@ function generateVariable(name, type, variable, className) { variable.hDefine += "\n std::vector<%s> %s;".format(type, name) } else if (type.substring(0, 4) == "Map<" || type.indexOf("{") == 0) { variable.hDefine += mapTypeString(type, name) + } else if (type == "any") { + variable.hDefine += anyTypeString(type, name) } else { NapiLog.logError(` @@ -113,6 +115,13 @@ function mapTypeString(type, name) { return "\n std::map<%s> %s;".format(mapTypeString, name); } +function anyTypeString (type, name) { + let anyType = `\n std::string %s_type; + std::any %s;` + + return anyType.format(name, 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 fd5865e4..b973345f 100644 --- a/src/gen/generate/param_generate.js +++ b/src/gen/generate/param_generate.js @@ -43,23 +43,7 @@ function jsToC(dest, napiVn, type, enumType = 0) { } else if (type.substring(type.length - 2) == "[]") { return arrTemplete(dest, napiVn, type); } else if (type.substring(0, 12) == "NUMBER_TYPE_") { - if (enumType) { - if (napiVn.indexOf("GetValueProperty") >= 0) { - let lt = LenIncrease.getAndIncrease() - return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){NUMBER_JS_2_C_ENUM(tnv%d,%s,%s,%s);}` - .format(lt, napiVn, lt, lt, type, dest, enumType) - } else { - return `NUMBER_JS_2_C_ENUM(%s,%s,%s,%s);`.format(napiVn, type, dest, enumType) - } - } else { - if (napiVn.indexOf("GetValueProperty") >= 0) { - let lt = LenIncrease.getAndIncrease() - return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){NUMBER_JS_2_C(tnv%d,%s,%s);}` - .format(lt, napiVn, lt, lt, type, dest) - } else { - return `NUMBER_JS_2_C(%s,%s,%s);`.format(napiVn, type, dest) - } - } + return numTempleteFunc (enumType, napiVn, type, dest) } else if (InterfaceList.getValue(type)) { let tt = "" let ifl = InterfaceList.getValue(type) @@ -77,6 +61,8 @@ function jsToC(dest, napiVn, type, enumType = 0) { return `BOOLEAN_JS_2_C(%s,%s,%s);`.format(napiVn, "bool", dest) } else if (type.substring(0, 4) == "Map<" || type.indexOf("{") == 0) { return mapTempleteFunc(dest, napiVn, type); + } else if (type == "any") { + return anyTempleteFunc(dest, napiVn, type); } else { NapiLog.logError(`do not support to generate jsToC %s,%s,%s`.format(dest, napiVn, type)); } @@ -163,6 +149,26 @@ function arrTemplete(dest, napiVn, type) { return arrTemplete } +function numTempleteFunc(enumType, napiVn, type, dest) { + if (enumType) { + if (napiVn.indexOf("GetValueProperty") >= 0) { + let lt = LenIncrease.getAndIncrease() + return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){NUMBER_JS_2_C_ENUM(tnv%d,%s,%s,%s);}` + .format(lt, napiVn, lt, lt, type, dest, enumType) + } else { + return `NUMBER_JS_2_C_ENUM(%s,%s,%s,%s);`.format(napiVn, type, dest, enumType) + } + } else { + if (napiVn.indexOf("GetValueProperty") >= 0) { + let lt = LenIncrease.getAndIncrease() + return `napi_value tnv%d = %s;\n if(tnv%d!=nullptr){NUMBER_JS_2_C(tnv%d,%s,%s);}` + .format(lt, napiVn, lt, lt, type, dest) + } else { + return `NUMBER_JS_2_C(%s,%s,%s);`.format(napiVn, type, dest) + } + } +} + function getMapValueCode(arrayType) { let valueTypeOut = arrayType.substring(22, arrayType.length-1) let strTypeOut = "%s".format(valueTypeOut) @@ -250,6 +256,14 @@ function paramGenerateArray(p, funcValue, param) { } } +function paramGenerateAny(p, name, type, param) { + param.valueIn += `\n std::any in%d; + std::string in%d_type;`.format(p, 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::any &%s".format(param.valueDefine.length > 0 ? ", " : "", name) +} + function paramGenerateEnum(data, funcValue, param, p) { let index = enumIndex(funcValue.type, data) if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) { @@ -311,6 +325,15 @@ function mapTempleteFunc(dest, napiVn, type) { return mapTemplete } +function anyTempleteFunc(dest, napiVn, type) { + + let anyTemplete = `%s_type = pxt->GetAnyType(pxt->GetArgv(0)); + pxt->SetAnyValue(%s_type, pxt->GetArgv(0), %s);` + .format(dest, dest, dest) + + return anyTemplete +} + let mapValueTemplete = `\ uint32_t len[replace_lt]=pxt->GetMapLength(%s); for(uint32_t i[replace_lt]=0;i[replace_lt]GetAnyValue(%s_type, result, %s);` + .format(value, value) + + return anyTemplete +} + function mapInterface(value, lt, tnv, mapType) { let ret let tnvdefInterface = `result = nullptr; @@ -369,6 +380,9 @@ function generateType(type){ else if (type.substring(0, 4) == "Map<" || type.indexOf("{") == 0) { return true } + else if (type == "any") { + return true + } else { return false } @@ -401,6 +415,11 @@ function returnGenerate2(returnInfo, param, data){ else if (type.substring(0, 4) == "Map<" || type.indexOf("{") == 0) { returnGenerateMap(returnInfo, param) } + else if (type == "any") { + param.valueOut = `std::any out; + std::string out_type;` + param.valueDefine += "%sstd::any &out".format(param.valueDefine.length > 0 ? ", " : "") + } } function returnGenerateEnum(data, returnInfo, param) { diff --git a/test/storytest/test_any/@ohos.test.d.ts b/test/storytest/test_any/@ohos.test.d.ts new file mode 100644 index 00000000..7abe544b --- /dev/null +++ b/test/storytest/test_any/@ohos.test.d.ts @@ -0,0 +1,23 @@ +/* +* 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 { + any1: any; + } + + function fun1(v: any): number; +} + +export default napitest; \ No newline at end of file diff --git a/test/storytest/test_any/test.js b/test/storytest/test_any/test.js new file mode 100644 index 00000000..44c6f745 --- /dev/null +++ b/test/storytest/test_any/test.js @@ -0,0 +1,45 @@ +/* +* 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 { fun1 } = require("./out/build/Release/napitest") +var assert = require("assert"); + +describe('Any', function () { + + it('test fun1', function () { + let ret = fun1("1"); + assert.strictEqual(ret, 0); + }); + + it('test fun1', function () { + let ret = fun1(45678); + assert.strictEqual(ret, 0); + }); + + it('test fun1', function () { + let ret = fun1(true); + assert.strictEqual(ret, 0); + }); + + it('test fun1', function () { + let ret = fun1([1,2,3,4,5,6,7,8,9]); + assert.strictEqual(ret, 0); + }); + + it('test fun1', function () { + let ret = fun1({"test":"okay","test1":"res"}); + assert.strictEqual(ret, 0); + }); + +}); \ No newline at end of file -- Gitee