1 /*
2 * Copyright (c) 2021 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_native_string.h"
17 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
18 #include "ohos/init_data.h"
19 #else
20 #include "unicode/putil.h"
21 #endif
22 #include "securec.h"
23 #include "unicode/ucnv.h"
24 #include "utils/log.h"
25
26 using panda::StringRef;
27 using panda::ObjectRef;
ArkNativeString(ArkNativeEngine * engine,const char * value,size_t length)28 ArkNativeString::ArkNativeString(ArkNativeEngine* engine, const char* value, size_t length)
29 : ArkNativeString(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
30 {
31 auto vm = engine->GetEcmaVm();
32 LocalScope scope(vm);
33 Local<StringRef> object = StringRef::NewFromUtf8(vm, value, length);
34 value_ = Global<StringRef>(vm, object);
35 }
ArkNativeString(ArkNativeEngine * engine,Local<JSValueRef> value)36 ArkNativeString::ArkNativeString(ArkNativeEngine* engine, Local<JSValueRef> value) : ArkNativeValue(engine, value) {}
37
~ArkNativeString()38 ArkNativeString::~ArkNativeString() {}
39
GetInterface(int interfaceId)40 void* ArkNativeString::GetInterface(int interfaceId)
41 {
42 return (NativeString::INTERFACE_ID == interfaceId) ? (NativeString*)this : nullptr;
43 }
44
GetCString(char * buffer,size_t size,size_t * length)45 void ArkNativeString::GetCString(char* buffer, size_t size, size_t* length)
46 {
47 if (length == nullptr) {
48 return;
49 }
50 auto vm = engine_->GetEcmaVm();
51 LocalScope scope(vm);
52 Global<StringRef> val = value_;
53 if (buffer == nullptr) {
54 *length = val->Utf8Length() - 1;
55 } else if (size != 0) {
56 int copied = val->WriteUtf8(buffer, size - 1) - 1;
57 buffer[copied] = '\0';
58 *length = copied;
59 } else {
60 *length = 0;
61 }
62 }
63
GetCString16(char16_t * buffer,size_t size,size_t * length)64 void ArkNativeString::GetCString16(char16_t* buffer, size_t size, size_t* length) {}
65
GetLength()66 size_t ArkNativeString::GetLength()
67 {
68 auto vm = engine_->GetEcmaVm();
69 LocalScope scope(vm);
70 Global<StringRef> value = value_;
71 return value->Utf8Length() - 1;
72 }
73
EncodeWriteUtf8(char * buffer,size_t bufferSize,int32_t * nchars)74 size_t ArkNativeString::EncodeWriteUtf8(char* buffer, size_t bufferSize, int32_t* nchars)
75 {
76 if (buffer == nullptr || nchars == nullptr) {
77 HILOG_ERROR("buffer is null or nchars is null");
78 return 0;
79 }
80
81 auto vm = engine_->GetEcmaVm();
82 LocalScope scope(vm);
83 Global<StringRef> val = value_;
84 int32_t length = val->Length();
85
86 int32_t pos = 0;
87 int32_t writableSize = static_cast<int32_t>(bufferSize);
88 int32_t i = 0;
89 Local<ObjectRef> strObj = Local<ObjectRef>(val.ToLocal(vm));
90 for (; i < length; i++) {
91 Local<StringRef> str = Local<StringRef>(strObj->Get(vm, i));
92 int32_t len = str->Utf8Length() - 1;
93 if (len > writableSize) {
94 break;
95 }
96
97 str->WriteUtf8((buffer + pos), writableSize);
98 writableSize -= len;
99 pos += len;
100 }
101
102 *nchars = i;
103 HILOG_DEBUG("EncodeWriteUtf8 the result of buffer: %{public}s", buffer);
104 return pos;
105 }
106
EncodeWriteChinese(std::string & buffer,const char * encoding)107 void ArkNativeString::EncodeWriteChinese(std::string& buffer, const char* encoding)
108 {
109 if (encoding == nullptr) {
110 HILOG_ERROR("encoding is nullptr");
111 return;
112 }
113 auto vm = engine_->GetEcmaVm();
114 LocalScope scope(vm);
115 Global<StringRef> val = value_;
116 int32_t length = val->Length();
117 Local<ObjectRef> strObj = Local<ObjectRef>(val.ToLocal(vm));
118
119 int32_t pos = 0;
120 const int32_t writableSize = 22; // 22 : encode max bytes of the ucnv_convent function;
121
122 std::string tempBuf = "";
123 tempBuf.resize(writableSize + 1);
124
125 UErrorCode ErrorCode = U_ZERO_ERROR;
126 const char* encFrom = "utf8";
127 for (int32_t i = 0; i < length; i++) {
128 Local<StringRef> str = Local<StringRef>(strObj->Get(vm, i));
129 int32_t len = str->Utf8Length() - 1;
130 if ((pos + len) >= writableSize) {
131 char outBuf[writableSize] = {0};
132 ucnv_convert(encoding, encFrom, outBuf, writableSize, tempBuf.c_str(), pos, &ErrorCode);
133 if (ErrorCode != U_ZERO_ERROR) {
134 HILOG_ERROR("ucnv_convert is failed : ErrorCode = %{public}d", static_cast<int32_t>(ErrorCode));
135 return;
136 }
137 buffer += outBuf;
138 tempBuf.clear();
139 pos = 0;
140 }
141 str->WriteUtf8((tempBuf.data() + pos), writableSize);
142 pos += len;
143 }
144 if (pos > 0) {
145 char outBuf[writableSize] = {0};
146 ucnv_convert(encoding, encFrom, outBuf, writableSize, tempBuf.c_str(), pos, &ErrorCode);
147 if (ErrorCode != U_ZERO_ERROR) {
148 HILOG_ERROR("ucnv_convert is failed : ErrorCode = %{public}d", static_cast<int32_t>(ErrorCode));
149 return;
150 }
151 buffer += outBuf;
152 }
153 }
154