diff --git a/interop/src/cpp/napi/convertors-napi.h b/interop/src/cpp/napi/convertors-napi.h index 1bbd236c9972c214b280880efc0d9746c5ebf21b..4b86ca1eb085bbc8742f2628135a49eff21def6f 100644 --- a/interop/src/cpp/napi/convertors-napi.h +++ b/interop/src/cpp/napi/convertors-napi.h @@ -18,6 +18,7 @@ #ifdef KOALA_NAPI +#include #include #include #include @@ -244,6 +245,49 @@ struct InteropTypeConverter { static inline void release(napi_env env, InteropType value, const KInteropReturnBuffer& converted) = delete; }; +template +ElemType* getTypedElements(napi_env env, napi_value value, size_t& bytes); + +template<> +struct InteropTypeConverter { + using InteropType = napi_value; + using SelfType = InteropTypeConverter; + static constexpr auto LengthByteSize = sizeof(KUInt); + static char* strndup(const void* str, size_t n) + { + char* mem = static_cast(malloc(n + 1)); + interop_memcpy(mem, n + 1, str, n); + mem[n] = 0; + return mem; + } + static size_t decodeLength(const uint8_t* data) + { + return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; + } + static KStringArray convertFrom(napi_env env, InteropType value) + { + size_t bytes = 0; + auto const encoded = getTypedElements(env, value, bytes); + if (!bytes) + return { { nullptr, nullptr }, 0 }; + + size_t const num = decodeLength(encoded); + KStringArray::Holder result(static_cast(malloc(sizeof(char*) * (num + 1))), &free); + + size_t count = 0; + auto const* ptr = encoded + LengthByteSize; + auto const* const end = encoded + bytes; + while (ptr < end) { + auto length = decodeLength(ptr); + result[count++] = SelfType::strndup(ptr + LengthByteSize, length); + ptr += LengthByteSize + length; + } + return { std::move(result), num }; + } + static InteropType convertTo(napi_env env, KStringArray value) = delete; + static void release(napi_env env, InteropType value, const KInteropReturnBuffer& converted) = delete; +}; + #define KOALA_INTEROP_THROW(vmContext, object, ...) \ do { \ napi_env env = (napi_env)vmContext; \ @@ -389,7 +433,7 @@ napi_valuetype getValueTypeChecked(napi_env env, napi_value value); bool isTypedArray(napi_env env, napi_value value); template -inline ElemType* getTypedElements(napi_env env, napi_value value) +inline ElemType* getTypedElements(napi_env env, napi_value value, size_t& bytesLength) { napi_valuetype valueType = getValueTypeChecked(env, value); if (valueType == napi_null) { @@ -401,10 +445,9 @@ inline ElemType* getTypedElements(napi_env env, napi_value value) } napi_value arrayBuffer; void* data = nullptr; - size_t byteLength; size_t byteOffset; napi_typedarray_type type; - napi_status status = napi_get_typedarray_info(env, value, &type, &byteLength, &data, &arrayBuffer, &byteOffset); + napi_status status = napi_get_typedarray_info(env, value, &type, &bytesLength, &data, &arrayBuffer, &byteOffset); KOALA_NAPI_THROW_IF_FAILED(env, status, nullptr); if (type != getNapiType()) { printf("Array type mismatch. Expected %d got %d\n", getNapiType(), type); @@ -414,6 +457,13 @@ inline ElemType* getTypedElements(napi_env env, napi_value value) return reinterpret_cast(data); } +template +inline ElemType* getTypedElements(napi_env env, napi_value value) +{ + size_t dummy; + return getTypedElements(env, value, dummy); +} + template inline ElemType* getTypedElements(const CallbackInfo& info, int index) { @@ -571,6 +621,13 @@ inline KInteropBuffer getArgument(const CallbackInfo& info, int return getArgument((napi_env)info.Env(), (napi_value)info[index]); } +template<> +inline KStringArray getArgument(const CallbackInfo& info, int index) +{ + NAPI_ASSERT_INDEX(info, index, {}); + return getArgument((napi_env)info.Env(), (napi_value)info[index]); +} + template<> inline KFloat getArgument(const CallbackInfo& info, int index) { diff --git a/interop/src/cpp/types/koala-types.h b/interop/src/cpp/types/koala-types.h index dc9102cd247968933d70957eb4a1393a017754fe..d9856c2a848f8e29f4eb62b1ef46bfa0a4dea9b8 100644 --- a/interop/src/cpp/types/koala-types.h +++ b/interop/src/cpp/types/koala-types.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -159,6 +160,36 @@ private: bool _owned; }; +struct KStringArrayImpl { + // Null terminated, [char*, char*, ..., nullptr] + using Holder = std::unique_ptr; + + KStringArrayImpl() : KStringArrayImpl({ nullptr, nullptr }, 0) {} + KStringArrayImpl(Holder strs, size_t num) : _holder(std::move(strs)), _num(num) {} + + ~KStringArrayImpl() + { + for (size_t k = 0; k < _num; k++) { + free(_holder[k]); + } + } + + const char* const* get() const + { + return _holder.get(); + } + + char** release() + { + _num = 0; + return _holder.release(); + } + +private: + Holder _holder; + size_t _num; +}; + struct KInteropNumber { int8_t tag; union { @@ -236,7 +267,7 @@ typedef InteropNativePointer KNativePointer; typedef KStringPtrImpl KStringPtr; typedef KFloat* KFloatArray; -typedef const uint8_t* KStringArray; +typedef KStringArrayImpl KStringArray; typedef KNativePointer* KNativePointerArray; struct KSerializerBufferOpaque { diff --git a/ui2abc/libarkts/native/src/bridges.cc b/ui2abc/libarkts/native/src/bridges.cc index d19ed1a8843237c464fb7475a5d512279d2cee85..77075af1c1e7e72bce5f6ec2468806a87212bd66 100644 --- a/ui2abc/libarkts/native/src/bridges.cc +++ b/ui2abc/libarkts/native/src/bridges.cc @@ -220,21 +220,10 @@ KNativePointer impl_CreateCacheContextFromFile( KOALA_INTEROP_4(CreateCacheContextFromFile, KNativePointer, KNativePointer, KStringPtr, KNativePointer, KBoolean) KNativePointer impl_CreateGlobalContext( - KNativePointer configPtr, KStringArray externalFileListPtr, KUInt fileNum, KBoolean LspUsage) + KNativePointer configPtr, KStringArray& externalFileListPtr, KUInt fileNum, KBoolean LspUsage) { auto config = reinterpret_cast(configPtr); - const int headerLen = 4; - const char** files = StageArena::allocArray(fileNum); - uint8_t* filesPtr = (uint8_t*)externalFileListPtr; - std::size_t position = headerLen; - std::size_t strLen; - for (std::size_t i = 0; i < static_cast(fileNum); ++i) { - strLen = unpackUInt(filesPtr + position); - position += headerLen; - files[i] = StageArena::strdup(std::string(reinterpret_cast(filesPtr + position), strLen).c_str()); - position += strLen; - } - return GetImpl()->CreateGlobalContext(config, files, fileNum, LspUsage); + return GetImpl()->CreateGlobalContext(config, getStringArray(externalFileListPtr), fileNum, LspUsage); } KOALA_INTEROP_4(CreateGlobalContext, KNativePointer, KNativePointer, KStringArray, KUInt, KBoolean) @@ -427,66 +416,37 @@ KNativePointer impl_CreateDiagnosticKind(KNativePointer context, KStringPtr& mes KOALA_INTEROP_3(CreateDiagnosticKind, KNativePointer, KNativePointer, KStringPtr, KInt) KNativePointer impl_CreateDiagnosticInfo( - KNativePointer context, KNativePointer kind, KStringArray argsPtr, KInt argc, KNativePointer pos) + KNativePointer context, KNativePointer kind, KStringArray& argsPtr, KInt argc, KNativePointer pos) { const auto _context = reinterpret_cast(context); const auto _kind = reinterpret_cast(kind); const auto _pos = reinterpret_cast(pos); - const std::size_t headerLen = 4; - const char** _args = new const char*[argc]; - std::size_t position = headerLen; - std::size_t strLen; - for (std::size_t i = 0; i < static_cast(argc); ++i) { - strLen = unpackUInt(argsPtr + position); - position += headerLen; - _args[i] = strdup(std::string(reinterpret_cast(argsPtr + position), strLen).c_str()); - position += strLen; - } - return GetImpl()->CreateDiagnosticInfo(_context, _kind, _args, argc, _pos); + return GetImpl()->CreateDiagnosticInfo(_context, _kind, getStringArray(argsPtr), argc, _pos); } KOALA_INTEROP_5( CreateDiagnosticInfo, KNativePointer, KNativePointer, KNativePointer, KStringArray, KInt, KNativePointer) -KNativePointer impl_CreateSuggestionInfo(KNativePointer context, KNativePointer kind, KStringArray argsPtr, KInt argc, +KNativePointer impl_CreateSuggestionInfo(KNativePointer context, KNativePointer kind, KStringArray& argsPtr, KInt argc, KStringPtr& substitutionCode, KStringPtr& title, KNativePointer range) { const auto _context = reinterpret_cast(context); const auto _kind = reinterpret_cast(kind); const auto _title = getStringCopy(title); const auto _range = reinterpret_cast(range); - const std::size_t headerLen = 4; - const char** _args = new const char*[argc]; - std::size_t position = headerLen; - std::size_t strLen; - for (std::size_t i = 0; i < static_cast(argc); ++i) { - strLen = unpackUInt(argsPtr + position); - position += headerLen; - _args[i] = strdup(std::string(reinterpret_cast(argsPtr + position), strLen).c_str()); - position += strLen; - } const auto _substitutionCode = getStringCopy(substitutionCode); - return GetImpl()->CreateSuggestionInfo(_context, _kind, _args, argc, _substitutionCode, _title, _range); + return GetImpl()->CreateSuggestionInfo( + _context, _kind, getStringArray(argsPtr), argc, _substitutionCode, _title, _range); } KOALA_INTEROP_7(CreateSuggestionInfo, KNativePointer, KNativePointer, KNativePointer, KStringArray, KInt, KStringPtr, KStringPtr, KNativePointer) void impl_LogDiagnostic( - KNativePointer context, KNativePointer kind, KStringArray argvPtr, KInt argc, KNativePointer pos) + KNativePointer context, KNativePointer kind, KStringArray& argvPtr, KInt argc, KNativePointer pos) { auto&& _context_ = reinterpret_cast(context); auto&& _kind_ = reinterpret_cast(kind); auto&& _pos_ = reinterpret_cast(pos); - const std::size_t headerLen = 4; - const char** argv = new const char*[argc]; - std::size_t position = headerLen; - std::size_t strLen; - for (std::size_t i = 0; i < static_cast(argc); ++i) { - strLen = unpackUInt(argvPtr + position); - position += headerLen; - argv[i] = strdup(std::string(reinterpret_cast(argvPtr + position), strLen).c_str()); - position += strLen; - } - GetImpl()->LogDiagnostic(_context_, _kind_, argv, argc, _pos_); + GetImpl()->LogDiagnostic(_context_, _kind_, getStringArray(argvPtr), argc, _pos_); } KOALA_INTEROP_V5(LogDiagnostic, KNativePointer, KNativePointer, KStringArray, KInt, KNativePointer) @@ -510,22 +470,11 @@ KInt impl_GenerateTsDeclarationsFromContext(KNativePointer contextPtr, KStringPt KOALA_INTEROP_7(GenerateTsDeclarationsFromContext, KInt, KNativePointer, KStringPtr, KStringPtr, KBoolean, KBoolean, KStringPtr, KBoolean) -// Improve: simplify KNativePointer impl_CreateContextGenerateAbcForExternalSourceFiles( - KNativePointer configPtr, KInt fileNamesCount, KStringArray fileNames) + KNativePointer configPtr, KInt fileNamesCount, KStringArray& fileNames) { auto config = reinterpret_cast(configPtr); - const std::size_t headerLen = 4; - const char** argv = new const char*[static_cast(fileNamesCount)]; - std::size_t position = headerLen; - std::size_t strLen; - for (std::size_t i = 0; i < static_cast(fileNamesCount); ++i) { - strLen = unpackUInt(fileNames + position); - position += headerLen; - argv[i] = strdup(std::string(reinterpret_cast(fileNames + position), strLen).c_str()); - position += strLen; - } - return GetImpl()->CreateContextGenerateAbcForExternalSourceFiles(config, fileNamesCount, argv); + return GetImpl()->CreateContextGenerateAbcForExternalSourceFiles(config, fileNamesCount, getStringArray(fileNames)); } KOALA_INTEROP_3(CreateContextGenerateAbcForExternalSourceFiles, KNativePointer, KNativePointer, KInt, KStringArray) @@ -552,4 +501,4 @@ KNativePointer impl_CreateTypeNodeFromTsType(KNativePointer context, KNativePoin auto _typeAnnotation = GetImpl()->CreateOpaqueTypeNode(_context, _nodeTsType); return _typeAnnotation; } -KOALA_INTEROP_2(CreateTypeNodeFromTsType, KNativePointer, KNativePointer, KNativePointer) \ No newline at end of file +KOALA_INTEROP_2(CreateTypeNodeFromTsType, KNativePointer, KNativePointer, KNativePointer) diff --git a/ui2abc/libarkts/native/src/common.cc b/ui2abc/libarkts/native/src/common.cc index e8a2cf8680b32f002e965706792348a28619b101..83a6d4ac3727c15572f706eff147f0103471b92a 100644 --- a/ui2abc/libarkts/native/src/common.cc +++ b/ui2abc/libarkts/native/src/common.cc @@ -202,25 +202,19 @@ string getString(KStringPtr ptr) return ptr.data(); } +const char** getStringArray(KStringArray& ptr) +{ + return const_cast(ptr.get()); // release()? +} + char* getStringCopy(KStringPtr& ptr) { return StageArena::strdup(ptr.c_str() ? ptr.c_str() : ""); } -KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) +KNativePointer impl_CreateConfig(KInt argc, KStringArray& argvPtr) { - const std::size_t headerLen = 4; - - const char** argv = StageArena::allocArray(argc); - std::size_t position = headerLen; - std::size_t strLen; - for (std::size_t i = 0; i < static_cast(argc); ++i) { - strLen = unpackUInt(argvPtr + position); - position += headerLen; - argv[i] = StageArena::strdup(std::string(reinterpret_cast(argvPtr + position), strLen).c_str()); - position += strLen; - } - return GetImpl()->CreateConfig(argc, argv); + return GetImpl()->CreateConfig(argc, getStringArray(argvPtr)); } KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray) diff --git a/ui2abc/libarkts/native/src/common.h b/ui2abc/libarkts/native/src/common.h index f2eeeb0e786a117b34eecc2da6e72c96bc98ad90..770d2a2ad3bfb260902ace5243b300d699f20ab2 100644 --- a/ui2abc/libarkts/native/src/common.h +++ b/ui2abc/libarkts/native/src/common.h @@ -55,6 +55,7 @@ inline es2panda_Impl* GetImpl() } string getString(KStringPtr ptr); +const char** getStringArray(KStringArray& ptr); char* getStringCopy(KStringPtr& ptr); @@ -129,4 +130,4 @@ public: void cleanup(); }; -#endif // COMMON_H \ No newline at end of file +#endif // COMMON_H