1 /*
2 * Copyright (c) 2024 Huawei Device 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 */
15
16 #include "ark_interop_internal.h"
17 #include "ark_interop_napi.h"
18 #include "ark_interop_log.h"
19
20 #include <cstdint>
21 #include <cassert>
22 #include <cstdlib>
23 #include <vector>
24
25 using namespace panda;
26 using namespace panda::ecmascript;
27
28 static constexpr int32_t STRING_TABLE_THRESHOLD = 128;
29
ARKTS_CreateUtf8(ARKTS_Env env,const char * value,int32_t size)30 ARKTS_Value ARKTS_CreateUtf8(ARKTS_Env env, const char* value, int32_t size)
31 {
32 ARKTS_ASSERT_P(env, "env is null");
33 ARKTS_ASSERT_P(value, "value is null");
34
35 auto vm = P_CAST(env, EcmaVM*);
36 Local<JSValueRef> result;
37 if (size < STRING_TABLE_THRESHOLD) {
38 result = StringRef::NewFromUtf8(vm, value, size);
39 } else {
40 result = StringRef::NewFromUtf8WithoutStringTable(vm, value, size);
41 }
42 return ARKTS_FromHandle(result);
43 }
44
ARKTS_IsString(ARKTS_Env env,ARKTS_Value value)45 bool ARKTS_IsString(ARKTS_Env env, ARKTS_Value value)
46 {
47 auto v = BIT_CAST(value, JSValueRef);
48 if (v.IsHole() || !v.IsHeapObject()) {
49 return false;
50 }
51 v = *P_CAST(value, JSValueRef*);
52 auto vm = P_CAST(env, EcmaVM*);
53 return v.IsString(vm);
54 }
55
ARKTS_GetValueUtf8Size(ARKTS_Env env,ARKTS_Value value)56 int32_t ARKTS_GetValueUtf8Size(ARKTS_Env env, ARKTS_Value value)
57 {
58 ARKTS_ASSERT_I(env, "env is null");
59 ARKTS_ASSERT_I(ARKTS_IsString(env, value), "not a string");
60 auto vm = P_CAST(env, EcmaVM*);
61 auto v = BIT_CAST(value, Local<StringRef>);
62 return v->Utf8Length(vm, true);
63 }
64
ARKTS_GetValueUtf8(ARKTS_Env env,ARKTS_Value value,int32_t capacity,char * buffer)65 int32_t ARKTS_GetValueUtf8(ARKTS_Env env, ARKTS_Value value, int32_t capacity, char* buffer)
66 {
67 ARKTS_ASSERT_I(ARKTS_IsString(env, value), "not a string");
68 auto vm = P_CAST(env, EcmaVM*);
69 auto v = BIT_CAST(value, Local<StringRef>);
70 return v->WriteUtf8(vm, buffer, capacity, true);
71 }
72
ARKTS_GetValueCString(ARKTS_Env env,ARKTS_Value value)73 const char* ARKTS_GetValueCString(ARKTS_Env env, ARKTS_Value value)
74 {
75 ARKTS_ASSERT_I(env, "env is null");
76 ARKTS_ASSERT_I(ARKTS_IsString(env, value), "not a string");
77 auto vm = P_CAST(env, EcmaVM*);
78 auto v = BIT_CAST(value, Local<StringRef>);
79 auto size = v->Utf8Length(vm, true);
80 if (size <= 0) {
81 return nullptr;
82 }
83 auto result = (char*) malloc(sizeof(char) * size);
84 if (!result) {
85 LOGE("ARKTS_GetValueCString fail, out of memory");
86 return nullptr;
87 }
88 v->WriteUtf8(vm, result, size, true);
89 return result;
90 }
91
ARKTS_FreeCString(const char * src)92 void ARKTS_FreeCString(const char* src)
93 {
94 free(reinterpret_cast<void*>(const_cast<char*>(src)));
95 }
96
ARKTS_GetStringInfo(ARKTS_Env env,ARKTS_Value value)97 ARKTS_StringInfo ARKTS_GetStringInfo(ARKTS_Env env, ARKTS_Value value)
98 {
99 ARKTS_ASSERT(env, "env is null", {});
100 ARKTS_ASSERT(ARKTS_IsString(env, value), "not a string", {});
101
102 auto vm = P_CAST(env, EcmaVM*);
103 auto string = BIT_CAST(value, Local<StringRef>);
104
105 auto isCompressed = string->IsCompressed(vm);
106 auto length = string->Length(vm);
107
108 return { isCompressed, length };
109 }
110
ARKTS_StringCopy(ARKTS_Env env,ARKTS_Value value,void * dst,uint32_t length)111 void ARKTS_StringCopy(ARKTS_Env env, ARKTS_Value value, void* dst, uint32_t length)
112 {
113 ARKTS_ASSERT_V(env, "env is null");
114 ARKTS_ASSERT_V(ARKTS_IsString(env, value), "not a string");
115 ARKTS_ASSERT_V(dst, "dst is null");
116
117 auto vm = P_CAST(env, EcmaVM*);
118 auto string = BIT_CAST(value, Local<StringRef>);
119 if (string->IsCompressed(vm)) {
120 string->WriteLatin1(vm, reinterpret_cast<char*>(dst), length);
121 } else {
122 string->WriteUtf16(vm, reinterpret_cast<char16_t*>(dst), length);
123 }
124 }
125
ARKTS_CreateString(ARKTS_Env env,bool isCompressed,uint32_t length,const void * data)126 ARKTS_Value ARKTS_CreateString(ARKTS_Env env, bool isCompressed, uint32_t length, const void* data)
127 {
128 ARKTS_ASSERT_P(env, "env is null");
129 ARKTS_ASSERT_P(data, "data is null");
130
131 auto vm = P_CAST(env, EcmaVM*);
132
133 Local<StringRef> result;
134 if (length < STRING_TABLE_THRESHOLD) {
135 if (isCompressed) {
136 result = StringRef::NewFromUtf8(vm, reinterpret_cast<const char *>(data), length);
137 } else {
138 result = StringRef::NewFromUtf16(vm, reinterpret_cast<const char16_t *>(data), length);
139 }
140 } else {
141 if (isCompressed) {
142 result = StringRef::NewFromUtf8WithoutStringTable(vm, reinterpret_cast<const char *>(data), length);
143 } else {
144 result = StringRef::NewFromUtf16WithoutStringTable(vm, reinterpret_cast<const char16_t *>(data), length);
145 }
146 }
147 return ARKTS_FromHandle(result);
148 }
149