• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 #ifndef PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_STRING_H
17 #define PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_STRING_H
18 
19 #include "runtime/include/runtime.h"
20 #include "runtime/include/coretypes/string-inl.h"
21 #include "plugins/ets/runtime/types/ets_array.h"
22 #include "plugins/ets/runtime/types/ets_object.h"
23 #include "plugins/ets/runtime/napi/ets_napi.h"
24 
25 namespace panda::ets {
26 
27 // Private inheritance, because need to disallow implicit conversion to core type
28 class EtsString : private coretypes::String {
29 public:
CreateFromMUtf8(const char * mutf8)30     static EtsString *CreateFromMUtf8(const char *mutf8)
31     {
32         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
33         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
34         if (mutf8 == nullptr) {
35             ThrowNullPointerException(ctx, ManagedThread::GetCurrent());
36             return nullptr;
37         }
38         const auto *data = reinterpret_cast<const uint8_t *>(mutf8);
39         coretypes::String *s = coretypes::String::CreateFromMUtf8(data, ctx, Runtime::GetCurrent()->GetPandaVM());
40         return reinterpret_cast<EtsString *>(s);
41     }
42 
CreateFromMUtf8(const char * mutf8,uint32_t length)43     static EtsString *CreateFromMUtf8(const char *mutf8, uint32_t length)
44     {
45         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
46         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
47         if (length == 0) {
48             return reinterpret_cast<EtsString *>(
49                 coretypes::String::CreateEmptyString(ctx, Runtime::GetCurrent()->GetPandaVM()));
50         }
51         if (mutf8 == nullptr) {
52             ThrowNullPointerException(ctx, ManagedThread::GetCurrent());
53             return nullptr;
54         }
55         const auto *data = reinterpret_cast<const uint8_t *>(mutf8);
56         coretypes::String *s =
57             coretypes::String::CreateFromMUtf8(data, length, ctx, Runtime::GetCurrent()->GetPandaVM());
58         return reinterpret_cast<EtsString *>(s);
59     }
60 
CreateFromUtf8(const char * utf8,uint32_t length)61     static EtsString *CreateFromUtf8(const char *utf8, uint32_t length)
62     {
63         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
64         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
65         if (length == 0) {
66             return reinterpret_cast<EtsString *>(
67                 coretypes::String::CreateEmptyString(ctx, Runtime::GetCurrent()->GetPandaVM()));
68         }
69         if (utf8 == nullptr) {
70             ThrowNullPointerException(ctx, ManagedThread::GetCurrent());
71             return nullptr;
72         }
73         const auto *data = reinterpret_cast<const uint8_t *>(utf8);
74         return reinterpret_cast<EtsString *>(
75             coretypes::String::CreateFromUtf8(data, length, ctx, Runtime::GetCurrent()->GetPandaVM()));
76     }
77 
CreateFromUtf16(const ets_char * utf16,ets_int length)78     static EtsString *CreateFromUtf16(const ets_char *utf16, ets_int length)
79     {
80         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
81         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
82         if (length == 0) {
83             return reinterpret_cast<EtsString *>(
84                 coretypes::String::CreateEmptyString(ctx, Runtime::GetCurrent()->GetPandaVM()));
85         }
86         if (utf16 == nullptr) {
87             ThrowNullPointerException(ctx, ManagedThread::GetCurrent());
88             return nullptr;
89         }
90         coretypes::String *s =
91             coretypes::String::CreateFromUtf16(utf16, length, ctx, Runtime::GetCurrent()->GetPandaVM());
92         return reinterpret_cast<EtsString *>(s);
93     }
94 
CreateNewStringFromChars(uint32_t offset,uint32_t length,EtsArray * chararray)95     static EtsString *CreateNewStringFromChars(uint32_t offset, uint32_t length, EtsArray *chararray)
96     {
97         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
98         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
99         return reinterpret_cast<EtsString *>(coretypes::String::CreateNewStringFromChars(
100             offset, length, reinterpret_cast<coretypes::Array *>(chararray), ctx, Runtime::GetCurrent()->GetPandaVM()));
101     }
102 
CreateNewStringFromBytes(EtsArray * bytearray,ets_int high,ets_int offset,ets_int length)103     static EtsString *CreateNewStringFromBytes(EtsArray *bytearray, ets_int high, ets_int offset, ets_int length)
104     {
105         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
106         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
107         if (length == 0) {
108             return reinterpret_cast<EtsString *>(
109                 coretypes::String::CreateEmptyString(ctx, Runtime::GetCurrent()->GetPandaVM()));
110         }
111         if (bytearray == nullptr) {
112             ThrowNullPointerException(ctx, ManagedThread::GetCurrent());
113             return nullptr;
114         }
115         if (offset < 0 || length < 0 || bytearray->GetLength() < static_cast<uint32_t>(offset + length)) {
116             ThrowArrayIndexOutOfBoundsException(static_cast<uint32_t>(offset + length), bytearray->GetLength(), ctx,
117                                                 ManagedThread::GetCurrent());
118             return nullptr;
119         }
120         return reinterpret_cast<EtsString *>(coretypes::String::CreateNewStringFromBytes(
121             offset, length, static_cast<uint32_t>(high), reinterpret_cast<coretypes::Array *>(bytearray), ctx,
122             Runtime::GetCurrent()->GetPandaVM()));
123     }
124 
CreateNewStringFromString(EtsString * etsString)125     static EtsString *CreateNewStringFromString(EtsString *etsString)
126     {
127         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
128         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
129         if (etsString == nullptr) {
130             ThrowNullPointerException(ctx, ManagedThread::GetCurrent());
131             return nullptr;
132         }
133         coretypes::String *string = etsString->GetCoreType();
134         return reinterpret_cast<EtsString *>(
135             coretypes::String::CreateFromString(string, ctx, Runtime::GetCurrent()->GetPandaVM()));
136     }
137 
CreateNewEmptyString()138     static EtsString *CreateNewEmptyString()
139     {
140         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
141         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
142         return reinterpret_cast<EtsString *>(
143             coretypes::String::CreateEmptyString(ctx, Runtime::GetCurrent()->GetPandaVM()));
144     }
145 
Resolve(const uint8_t * mutf8,uint32_t length)146     static EtsString *Resolve(const uint8_t *mutf8, uint32_t length)
147     {
148         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
149         return reinterpret_cast<EtsString *>(
150             Runtime::GetCurrent()->ResolveString(Runtime::GetCurrent()->GetPandaVM(), mutf8, length, ctx));
151     }
152 
Concat(EtsString * etsString1,EtsString * etsString2)153     static EtsString *Concat(EtsString *etsString1, EtsString *etsString2)
154     {
155         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
156         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
157         coretypes::String *string3 = coretypes::String::Concat(etsString1->GetCoreType(), etsString2->GetCoreType(),
158                                                                ctx, Runtime::GetCurrent()->GetPandaVM());
159         return reinterpret_cast<EtsString *>(string3);
160     }
161 
Compare(EtsString * rhs)162     int32_t Compare(EtsString *rhs)
163     {
164         return GetCoreType()->Compare(rhs->GetCoreType());
165     }
166 
At(int32_t index)167     uint16_t At(int32_t index)
168     {
169         return GetCoreType()->At(index);
170     }
171 
DoReplace(EtsString * src,ets_char oldC,ets_char newC)172     static EtsString *DoReplace(EtsString *src, ets_char oldC, ets_char newC)
173     {
174         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
175         if (src->GetLength() == 0) {
176             return reinterpret_cast<EtsString *>(
177                 coretypes::String::CreateEmptyString(ctx, Runtime::GetCurrent()->GetPandaVM()));
178         }
179         coretypes::String *result = coretypes::String::DoReplace(reinterpret_cast<coretypes::String *>(src), oldC, newC,
180                                                                  ctx, Runtime::GetCurrent()->GetPandaVM());
181         return reinterpret_cast<EtsString *>(result);
182     }
183 
FastSubString(EtsString * src,uint32_t start,uint32_t length)184     static EtsString *FastSubString(EtsString *src, uint32_t start, uint32_t length)
185     {
186         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
187         coretypes::String *string1 = src->GetCoreType();
188         coretypes::String *string2 =
189             coretypes::String::FastSubString(string1, start, length, ctx, Runtime::GetCurrent()->GetPandaVM());
190         return reinterpret_cast<EtsString *>(string2);
191     }
192 
ToCharArray()193     EtsArray *ToCharArray()
194     {
195         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
196         auto *ret = GetCoreType()->ToCharArray(ctx);
197         if (UNLIKELY(ret == nullptr)) {
198             return nullptr;
199         }
200         return reinterpret_cast<EtsArray *>(ret);
201     }
202 
IsUtf16()203     bool IsUtf16()
204     {
205         return GetCoreType()->IsUtf16();
206     }
207 
GetLength()208     ets_int GetLength()
209     {
210         return GetCoreType()->GetLength();
211     }
212 
CopyDataMUtf8(void * buf,size_t maxLength,bool isCString)213     size_t CopyDataMUtf8(void *buf, size_t maxLength, bool isCString)
214     {
215         return GetCoreType()->CopyDataMUtf8(reinterpret_cast<uint8_t *>(buf), maxLength, isCString);
216     }
217 
CopyDataRegionMUtf8(void * buf,size_t start,size_t length,size_t maxLength)218     size_t CopyDataRegionMUtf8(void *buf, size_t start, size_t length, size_t maxLength)
219     {
220         return GetCoreType()->CopyDataRegionMUtf8(reinterpret_cast<uint8_t *>(buf), start, length, maxLength);
221     }
222 
CopyDataUtf16(void * buf,uint32_t maxLength)223     uint32_t CopyDataUtf16(void *buf, uint32_t maxLength)
224     {
225         return GetCoreType()->CopyDataUtf16(reinterpret_cast<uint16_t *>(buf), maxLength);
226     }
227 
CopyDataRegionUtf16(void * buf,uint32_t start,uint32_t length,uint32_t maxLength)228     uint32_t CopyDataRegionUtf16(void *buf, uint32_t start, uint32_t length, uint32_t maxLength)
229     {
230         return GetCoreType()->CopyDataRegionUtf16(reinterpret_cast<uint16_t *>(buf), start, length, maxLength);
231     }
232 
ConvertToStringView(PandaVector<uint8_t> * buf)233     std::string_view ConvertToStringView(PandaVector<uint8_t> *buf)
234     {
235         if (IsUtf16()) {
236             size_t len = utf::Utf16ToMUtf8Size(GetDataUtf16(), GetUtf16Length()) - 1;
237             buf->reserve(len);
238             utf::ConvertRegionUtf16ToMUtf8(GetDataUtf16(), buf->data(), GetUtf16Length(), len, 0);
239             return {utf::Mutf8AsCString(buf->data()), len};
240         }
241         return {utf::Mutf8AsCString(GetDataMUtf8()), static_cast<size_t>(GetLength())};
242     }
243 
GetMUtf8Length()244     uint32_t GetMUtf8Length()
245     {
246         return GetCoreType()->GetMUtf8Length();
247     }
248 
GetUtf16Length()249     uint32_t GetUtf16Length()
250     {
251         return GetCoreType()->GetUtf16Length();
252     }
253 
IsEqual(const char * str)254     bool IsEqual(const char *str)
255     {
256         auto *mutf8Str = utf::CStringAsMutf8(str);
257         return coretypes::String::StringsAreEqualMUtf8(GetCoreType(), mutf8Str, utf::Mutf8Size(mutf8Str));
258     }
259 
GetMutf8()260     PandaString GetMutf8()
261     {
262         size_t len = GetMUtf8Length() - 1;
263         PandaString out;
264         out.resize(len);
265         CopyDataMUtf8(out.data(), len, false);
266         return out;
267     }
268 
GetDataMUtf8()269     uint8_t *GetDataMUtf8()
270     {
271         return GetCoreType()->GetDataMUtf8();
272     }
273 
GetDataUtf16()274     uint16_t *GetDataUtf16()
275     {
276         return GetCoreType()->GetDataUtf16();
277     }
278 
IsEmpty()279     bool IsEmpty()
280     {
281         return GetCoreType()->IsEmpty();
282     }
283 
StringsAreEqual(EtsObject * obj)284     bool StringsAreEqual(EtsObject *obj)
285     {
286         return coretypes::String::StringsAreEqual(GetCoreType(), FromEtsObject(obj)->GetCoreType());
287     }
288 
GetCoreType()289     coretypes::String *GetCoreType()
290     {
291         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
292         return reinterpret_cast<coretypes::String *>(this);
293     }
294 
AsObject()295     EtsObject *AsObject()
296     {
297         return reinterpret_cast<EtsObject *>(this);
298     }
299 
AsObject()300     const EtsObject *AsObject() const
301     {
302         return reinterpret_cast<const EtsObject *>(this);
303     }
304 
FromCoreType(coretypes::String * str)305     static EtsString *FromCoreType(coretypes::String *str)
306     {
307         return reinterpret_cast<EtsString *>(str);
308     }
309 
FromEtsObject(EtsObject * obj)310     static EtsString *FromEtsObject(EtsObject *obj)
311     {
312         ASSERT(obj->GetClass()->GetRuntimeClass() == Runtime::GetCurrent()
313                                                          ->GetClassLinker()
314                                                          ->GetExtension(panda_file::SourceLang::ETS)
315                                                          ->GetClassRoot(ClassRoot::STRING));
316         return reinterpret_cast<EtsString *>(obj);
317     }
318 
319     EtsString() = delete;
320     ~EtsString() = delete;
321 
322     NO_COPY_SEMANTIC(EtsString);
323     NO_MOVE_SEMANTIC(EtsString);
324 
325 private:
326     friend EtsString *StringBuilderToString(ObjectHeader *sb);
327 
AllocateNonInitializedString(uint32_t length,bool compressed)328     static EtsString *AllocateNonInitializedString(uint32_t length, bool compressed)
329     {
330         ASSERT(length != 0);
331         ASSERT_HAVE_ACCESS_TO_MANAGED_OBJECTS();
332         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS);
333         return reinterpret_cast<EtsString *>(
334             coretypes::String::AllocStringObject(length, compressed, ctx, Runtime::GetCurrent()->GetPandaVM()));
335     }
336 };
337 
338 }  // namespace panda::ets
339 
340 #endif  // PANDA_PLUGINS_ETS_RUNTIME_FFI_CLASSES_ETS_STRING_H
341