• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,const char16_t * value,size_t length)36 ArkNativeString::ArkNativeString(ArkNativeEngine* engine, const char16_t* value, size_t length)
37     : ArkNativeString(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
38 {
39     auto vm = engine->GetEcmaVm();
40     LocalScope scope(vm);
41     Local<StringRef> object = StringRef::NewFromUtf16(vm, value, length);
42     value_ = Global<StringRef>(vm, object);
43 }
ArkNativeString(ArkNativeEngine * engine,Local<JSValueRef> value)44 ArkNativeString::ArkNativeString(ArkNativeEngine* engine, Local<JSValueRef> value) : ArkNativeValue(engine, value) {}
45 
~ArkNativeString()46 ArkNativeString::~ArkNativeString() {}
47 
GetInterface(int interfaceId)48 void* ArkNativeString::GetInterface(int interfaceId)
49 {
50     return (NativeString::INTERFACE_ID == interfaceId) ? (NativeString*)this : nullptr;
51 }
52 
GetCString(char * buffer,size_t size,size_t * length)53 void ArkNativeString::GetCString(char* buffer, size_t size, size_t* length)
54 {
55     if (length == nullptr) {
56         return;
57     }
58     auto vm = engine_->GetEcmaVm();
59     LocalScope scope(vm);
60     Global<StringRef> val = value_;
61     if (buffer == nullptr) {
62         *length = val->Utf8Length(vm) - 1;
63     } else if (size != 0) {
64         int copied = val->WriteUtf8(buffer, size - 1, true) - 1;
65         buffer[copied] = '\0';
66         *length = copied;
67     } else {
68         *length = 0;
69     }
70 }
71 
GetCStringLatin1(char * buffer,size_t size,size_t * length)72 void ArkNativeString::GetCStringLatin1(char* buffer, size_t size, size_t* length)
73 {
74     if (length == nullptr) {
75         return;
76     }
77     auto vm = engine_->GetEcmaVm();
78     LocalScope scope(vm);
79     Global<StringRef> val = value_;
80     if (buffer == nullptr) {
81         *length = val->Length();
82     } else if (size != 0) {
83         int copied = val->WriteLatin1(buffer, size);
84         buffer[copied] = '\0';
85         *length = copied;
86     } else {
87         *length = 0;
88     }
89 }
90 
GetCString16(char16_t * buffer,size_t bufSize,size_t * copyLength)91 void ArkNativeString::GetCString16(char16_t* buffer, size_t bufSize, size_t* copyLength)
92 {
93     if (copyLength == nullptr) {
94         return;
95     }
96     auto vm = engine_->GetEcmaVm();
97     LocalScope scope(vm);
98     Global<StringRef> val = value_;
99     if (buffer == nullptr) {
100         *copyLength = val->Length();
101     } else if (bufSize == 1) {
102         buffer[0] = '\0';
103         *copyLength = 0;
104     } else if (bufSize != 0) {
105         int copied = val->WriteUtf16(buffer, bufSize - 1); // bufSize - 1 :reserve the position of buffer "\0"
106         buffer[copied] = '\0';
107         *copyLength = copied;
108     } else {
109         *copyLength = 0;
110     }
111 }
112 
GetLength()113 size_t ArkNativeString::GetLength()
114 {
115     auto vm = engine_->GetEcmaVm();
116     LocalScope scope(vm);
117     Global<StringRef> value = value_;
118     return value->Utf8Length(vm) - 1;
119 }
120 
EncodeWriteUtf8(char * buffer,size_t bufferSize,int32_t * nchars)121 size_t ArkNativeString::EncodeWriteUtf8(char* buffer, size_t bufferSize, int32_t* nchars)
122 {
123     if (buffer == nullptr || nchars == nullptr) {
124         HILOG_ERROR("buffer is null or nchars is null");
125         return 0;
126     }
127 
128     auto vm = engine_->GetEcmaVm();
129     LocalScope scope(vm);
130     Global<StringRef> val = value_;
131     int32_t length = val->Length();
132 
133     int32_t pos = 0;
134     int32_t writableSize = static_cast<int32_t>(bufferSize);
135     int32_t i = 0;
136     Local<ObjectRef> strObj = Local<ObjectRef>(val.ToLocal(vm));
137     for (; i < length; i++) {
138         Local<StringRef> str = Local<StringRef>(strObj->Get(vm, i));
139         int32_t len = str->Utf8Length(vm) - 1;
140         if (len > writableSize) {
141             break;
142         }
143 
144         str->WriteUtf8((buffer + pos), writableSize);
145         writableSize -= len;
146         pos += len;
147     }
148 
149     *nchars = i;
150     HILOG_DEBUG("EncodeWriteUtf8 the result of buffer: %{public}s", buffer);
151     return pos;
152 }
153 
EncodeWriteChinese(std::string & buffer,const char * encoding)154 void ArkNativeString::EncodeWriteChinese(std::string& buffer, const char* encoding)
155 {
156     if (encoding == nullptr) {
157         HILOG_ERROR("encoding is nullptr");
158         return;
159     }
160     auto vm = engine_->GetEcmaVm();
161     LocalScope scope(vm);
162     Global<StringRef> val = value_;
163     int32_t length = val->Length();
164     Local<ObjectRef> strObj = Local<ObjectRef>(val.ToLocal(vm));
165 
166     int32_t pos = 0;
167     const int32_t writableSize = 22; // 22 : encode max bytes of the ucnv_convent function;
168 
169     std::string tempBuf = "";
170     tempBuf.resize(writableSize + 1);
171 
172     UErrorCode ErrorCode = U_ZERO_ERROR;
173     const char* encFrom = "utf8";
174     for (int32_t i = 0; i < length; i++) {
175         Local<StringRef> str = Local<StringRef>(strObj->Get(vm, i));
176         int32_t len = str->Utf8Length(vm) - 1;
177         if ((pos + len) >= writableSize) {
178             char outBuf[writableSize] = {0};
179             ucnv_convert(encoding, encFrom, outBuf, writableSize, tempBuf.c_str(), pos, &ErrorCode);
180             if (ErrorCode != U_ZERO_ERROR) {
181                 HILOG_ERROR("ucnv_convert is failed : ErrorCode = %{public}d", static_cast<int32_t>(ErrorCode));
182                 return;
183             }
184             buffer += outBuf;
185             tempBuf.clear();
186             pos = 0;
187         }
188         str->WriteUtf8((tempBuf.data() + pos), writableSize);
189         pos += len;
190     }
191     if (pos > 0) {
192         char outBuf[writableSize] = {0};
193         ucnv_convert(encoding, encFrom, outBuf, writableSize, tempBuf.c_str(), pos, &ErrorCode);
194         if (ErrorCode != U_ZERO_ERROR) {
195             HILOG_ERROR("ucnv_convert is failed : ErrorCode = %{public}d", static_cast<int32_t>(ErrorCode));
196             return;
197         }
198         buffer += outBuf;
199     }
200 }
201