• 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 #ifndef ECMASCRIPT_STRING_H
17 #define ECMASCRIPT_STRING_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstring>
22 
23 #include "ecmascript/base/utf_helper.h"
24 #include "ecmascript/ecma_macros.h"
25 #include "ecmascript/js_tagged_value.h"
26 #include "ecmascript/mem/barriers.h"
27 #include "ecmascript/mem/space.h"
28 #include "ecmascript/mem/tagged_object.h"
29 
30 #include "libpandabase/macros.h"
31 #include "securec.h"
32 #include "unicode/locid.h"
33 
34 namespace panda {
35 namespace ecmascript {
36 template<typename T>
37 class JSHandle;
38 class EcmaVM;
39 class EcmaString : public TaggedObject {
40 public:
41     friend class EcmaStringAccessor;
42 
43     CAST_CHECK(EcmaString, IsString);
44 
45     static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1;
46     static constexpr uint32_t STRING_INTERN_BIT = 0x2;
47 
48     static constexpr size_t MIX_LENGTH_OFFSET = TaggedObjectSize();
49     // In last bit of mix_length we store if this string is compressed or not.
50     ACCESSORS_PRIMITIVE_FIELD(MixLength, uint32_t, MIX_LENGTH_OFFSET, HASHCODE_OFFSET)
51     ACCESSORS_PRIMITIVE_FIELD(RawHashcode, uint32_t, HASHCODE_OFFSET, SIZE)
52     // DATA_OFFSET: the string data stored after the string header.
53     // Data can be stored in utf8 or utf16 form according to compressed bit.
54     static constexpr size_t DATA_OFFSET = SIZE;  // DATA_OFFSET equal to Empty String size
55 
56     enum CompressedStatus {
57         STRING_COMPRESSED,
58         STRING_UNCOMPRESSED,
59     };
60 
61     enum TrimMode : uint8_t {
62         TRIM,
63         TRIM_START,
64         TRIM_END,
65     };
66 
67 private:
68     static EcmaString *CreateEmptyString(const EcmaVM *vm);
69     static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress,
70                                       MemSpaceType type = MemSpaceType::SEMI_SPACE);
71     static EcmaString *CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len,
72                                        bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE);
73     static EcmaString *Concat(const EcmaVM *vm,
74         const JSHandle<EcmaString> &str1Handle, const JSHandle<EcmaString> &str2Handle);
75     static EcmaString *FastSubString(const EcmaVM *vm,
76         const JSHandle<EcmaString> &src, uint32_t start, uint32_t length);
77 
78     template<bool verify = true>
79     uint16_t At(int32_t index) const;
80 
81     static int32_t Compare(EcmaString *lhs, EcmaString *rhs);
82 
IsUtf16()83     bool IsUtf16() const
84     {
85         return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_UNCOMPRESSED;
86     }
87 
IsUtf8()88     bool IsUtf8() const
89     {
90         return (GetMixLength() & STRING_COMPRESSED_BIT) == STRING_COMPRESSED;
91     }
92 
ComputeDataSizeUtf16(uint32_t length)93     static size_t ComputeDataSizeUtf16(uint32_t length)
94     {
95         return length * sizeof(uint16_t);
96     }
97 
98     /**
99      * Methods for uncompressed strings (UTF16):
100      */
ComputeSizeUtf16(uint32_t utf16Len)101     static size_t ComputeSizeUtf16(uint32_t utf16Len)
102     {
103         return DATA_OFFSET + ComputeDataSizeUtf16(utf16Len);
104     }
105 
GetData()106     inline uint16_t *GetData() const
107     {
108         return reinterpret_cast<uint16_t *>(ToUintPtr(this) + DATA_OFFSET);
109     }
110 
GetDataUtf16()111     const uint16_t *GetDataUtf16() const
112     {
113         LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
114         return GetData();
115     }
116 
117     /**
118      * Methods for compresses strings (UTF8 or LATIN1):
119      */
ComputeSizeUtf8(uint32_t utf8Len)120     static size_t ComputeSizeUtf8(uint32_t utf8Len)
121     {
122         return DATA_OFFSET + utf8Len;
123     }
124 
125     /**
126      * It's Utf8 format, but without 0 in the end.
127      */
GetDataUtf8()128     const uint8_t *GetDataUtf8() const
129     {
130         ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
131         return reinterpret_cast<uint8_t *>(GetData());
132     }
133 
134     size_t GetUtf8Length(bool modify = true) const
135     {
136         if (!IsUtf16()) {
137             return GetLength() + 1;  // add place for zero in the end
138         }
139         return base::utf_helper::Utf16ToUtf8Size(GetData(), GetLength(), modify);
140     }
141 
GetUtf16Length()142     size_t GetUtf16Length() const
143     {
144         return GetLength();
145     }
146 
147     inline size_t CopyDataUtf8(uint8_t *buf, size_t maxLength, bool modify = true) const
148     {
149         if (maxLength == 0) {
150             return 1; // maxLength was -1 at napi
151         }
152         size_t length = GetLength();
153         if (length > maxLength) {
154             return 0;
155         }
156         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
157         buf[maxLength - 1] = '\0';
158         // Put comparison here so that internal usage and napi can use the same CopyDataRegionUtf8
159         return CopyDataRegionUtf8(buf, 0, length, maxLength, modify) + 1;  // add place for zero in the end
160     }
161 
162     // It allows user to copy into buffer even if maxLength < length
WriteUtf8(uint8_t * buf,size_t maxLength)163     inline size_t WriteUtf8(uint8_t *buf, size_t maxLength) const
164     {
165         if (maxLength == 0) {
166             return 1; // maxLength was -1 at napi
167         }
168         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
169         buf[maxLength - 1] = '\0';
170         return CopyDataRegionUtf8(buf, 0, GetLength(), maxLength) + 1;  // add place for zero in the end
171     }
172 
173     size_t CopyDataRegionUtf8(uint8_t *buf, size_t start, size_t length, size_t maxLength, bool modify = true) const
174     {
175         uint32_t len = GetLength();
176         if (start + length > len) {
177             return 0;
178         }
179         if (!IsUtf16()) {
180             if (length > std::numeric_limits<size_t>::max() / 2 - 1) {  // 2: half
181                 LOG_FULL(FATAL) << " length is higher than half of size_t::max";
182                 UNREACHABLE();
183             }
184             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
185             // Only memcpy_s maxLength number of chars into buffer if length > maxLength
186             if (length > maxLength) {
187                 if (memcpy_s(buf, maxLength, GetDataUtf8() + start, maxLength) != EOK) {
188                     LOG_FULL(FATAL) << "memcpy_s failed when length > maxlength";
189                     UNREACHABLE();
190                 }
191                 return maxLength;
192             }
193             if (memcpy_s(buf, maxLength, GetDataUtf8() + start, length) != EOK) {
194                 LOG_FULL(FATAL) << "memcpy_s failed when length <= maxlength";
195                 UNREACHABLE();
196             }
197             return length;
198         }
199         if (length > maxLength) {
200             return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, maxLength, maxLength, start, modify);
201         }
202         return base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf, length, maxLength, start, modify);
203     }
204 
CopyDataUtf16(uint16_t * buf,uint32_t maxLength)205     inline uint32_t CopyDataUtf16(uint16_t *buf, uint32_t maxLength) const
206     {
207         return CopyDataRegionUtf16(buf, 0, GetLength(), maxLength);
208     }
209 
CopyDataRegionUtf16(uint16_t * buf,uint32_t start,uint32_t length,uint32_t maxLength)210     uint32_t CopyDataRegionUtf16(uint16_t *buf, uint32_t start, uint32_t length, uint32_t maxLength) const
211     {
212         if (length > maxLength) {
213             return 0;
214         }
215         uint32_t len = GetLength();
216         if (start + length > len) {
217             return 0;
218         }
219         if (IsUtf16()) {
220             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
221             if (memcpy_s(buf, ComputeDataSizeUtf16(maxLength), GetDataUtf16() + start, ComputeDataSizeUtf16(length)) !=
222                 EOK) {
223                 LOG_FULL(FATAL) << "memcpy_s failed";
224                 UNREACHABLE();
225             }
226             return length;
227         }
228         return base::utf_helper::ConvertRegionUtf8ToUtf16(GetDataUtf8(), buf, len, maxLength, start);
229     }
230 
231     std::u16string ToU16String(uint32_t len = 0);
232 
ToOneByteDataForced()233     std::unique_ptr<uint8_t[]> ToOneByteDataForced()
234     {
235         uint8_t *buf = nullptr;
236         auto length = GetLength();
237         if (IsUtf16()) {
238             auto size = ComputeDataSizeUtf16(length);
239             buf = new uint8_t[size]();
240             CopyDataUtf16(reinterpret_cast<uint16_t *>(buf), length);
241         } else {
242             buf = new uint8_t[length + 1]();
243             CopyDataUtf8(buf, length + 1);
244         }
245         return std::unique_ptr<uint8_t[]>(buf);
246     }
247 
248     Span<const uint8_t> ToUtf8Span([[maybe_unused]] CVector<uint8_t> &buf, bool modify = true)
249     {
250         Span<const uint8_t> str;
251         uint32_t strLen = GetLength();
252         if (UNLIKELY(IsUtf16())) {
253             size_t len = base::utf_helper::Utf16ToUtf8Size(GetDataUtf16(), strLen, modify) - 1;
254             buf.reserve(len);
255             len = base::utf_helper::ConvertRegionUtf16ToUtf8(GetDataUtf16(), buf.data(), strLen, len, 0, modify);
256             str = Span<const uint8_t>(buf.data(), len);
257         } else {
258             str = Span<const uint8_t>(GetDataUtf8(), strLen);
259         }
260         return str;
261     }
262 
WriteData(EcmaString * src,uint32_t start,uint32_t destSize,uint32_t length)263     void WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
264     {
265         if (IsUtf8()) {
266             ASSERT(src->IsUtf8());
267             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
268             if (length != 0 && memcpy_s(GetDataUtf8Writable() + start, destSize, src->GetDataUtf8(), length) != EOK) {
269                 LOG_FULL(FATAL) << "memcpy_s failed";
270                 UNREACHABLE();
271             }
272         } else if (src->IsUtf8()) {
273             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
274             Span<uint16_t> to(GetDataUtf16Writable() + start, length);
275             Span<const uint8_t> from(src->GetDataUtf8(), length);
276             for (uint32_t i = 0; i < length; i++) {
277                 to[i] = from[i];
278             }
279         } else {
280             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
281             if (length != 0 && memcpy_s(GetDataUtf16Writable() + start,
282                 ComputeDataSizeUtf16(destSize), src->GetDataUtf16(), ComputeDataSizeUtf16(length)) != EOK) {
283                 LOG_FULL(FATAL) << "memcpy_s failed";
284                 UNREACHABLE();
285             }
286         }
287     }
288 
WriteData(uint16_t src,uint32_t start)289     inline void WriteData(uint16_t src, uint32_t start)
290     {
291         if (IsUtf8()) {
292             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
293             *(GetDataUtf8Writable() + start) = static_cast<uint8_t>(src);
294         } else {
295             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
296             *(GetDataUtf16Writable() + start) = src;
297         }
298     }
299 
GetLength()300     uint32_t GetLength() const
301     {
302         return GetMixLength() >> 2U;
303     }
304 
SetIsInternString()305     void SetIsInternString()
306     {
307         SetMixLength(GetMixLength() | STRING_INTERN_BIT);
308     }
309 
IsInternString()310     bool IsInternString() const
311     {
312         return (GetMixLength() & STRING_INTERN_BIT) != 0;
313     }
314 
ClearInternStringFlag()315     void ClearInternStringFlag()
316     {
317         SetMixLength(GetMixLength() & ~STRING_INTERN_BIT);
318     }
319 
ObjectSize()320     size_t ObjectSize() const
321     {
322         uint32_t length = GetLength();
323         return IsUtf16() ? ComputeSizeUtf16(length) : ComputeSizeUtf8(length);
324     }
325 
GetHashcode()326     uint32_t PUBLIC_API GetHashcode()
327     {
328         uint32_t hashcode = GetRawHashcode();
329         // GetLength() == 0 means it's an empty array.No need to computeHashCode again when hashseed is 0.
330         if (hashcode == 0 && GetLength() != 0) {
331             hashcode = ComputeHashcode(0);
332             SetRawHashcode(hashcode);
333         }
334         return hashcode;
335     }
336 
337     uint32_t PUBLIC_API ComputeHashcode(uint32_t hashSeed) const;
338 
339     static int32_t IndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0);
340 
341     static int32_t LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0);
342 
GetStringCompressionMask()343     static constexpr uint32_t GetStringCompressionMask()
344     {
345         return STRING_COMPRESSED_BIT;
346     }
347 
348     /**
349      * Compares string1 + string2 by bytes, It doesn't check canonical unicode equivalence.
350      */
351     bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2);
352     /**
353      * Compares strings by bytes, It doesn't check canonical unicode equivalence.
354      */
355     static bool StringsAreEqual(EcmaString *str1, EcmaString *str2);
356     /**
357      * Two strings have the same type of utf encoding format.
358      */
359     static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2);
360     /**
361      * Compares strings by bytes, It doesn't check canonical unicode equivalence.
362      */
363     static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len,
364                                     bool canBeCompress);
365     /**
366      * Compares strings by bytes, It doesn't check canonical unicode equivalence.
367      */
368     static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len);
369     static uint32_t ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress);
370     static uint32_t ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length);
371 
372     static EcmaString *AllocStringObject(const EcmaVM *vm, size_t length, bool compressed);
373     static EcmaString *AllocStringObjectWithSpaceType(const EcmaVM *vm, size_t length, bool compressed,
374                                                       MemSpaceType type);
375 
376     static bool CanBeCompressed(const uint8_t *utf8Data, uint32_t utf8Len);
377     static bool CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len);
378     static bool CanBeCompressed(const EcmaString *string);
379 
380     static inline EcmaString *FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
381                                                 uint32_t length);
382     static inline EcmaString *FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
383                                                  uint32_t length);
384 
385     bool ToElementIndex(uint32_t *index);
386 
387     bool ToTypedArrayIndex(uint32_t *index);
388 
389     static EcmaString *ToLower(const EcmaVM *vm, const JSHandle<EcmaString> &src);
390 
391     static EcmaString *ToUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src);
392 
393     static EcmaString *ToLocaleLower(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale);
394 
395     static EcmaString *ToLocaleUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale);
396 
397     template<typename T>
398     static EcmaString *TrimBody(const JSThread *thread, const JSHandle<EcmaString> &src, Span<T> &data, TrimMode mode);
399 
400     static EcmaString *Trim(const JSThread *thread, const JSHandle<EcmaString> &src, TrimMode mode = TrimMode::TRIM);
401 
402     void SetLength(uint32_t length, bool compressed = false)
403     {
404         ASSERT(length < 0x40000000U);
405         // Use 0u for compressed/utf8 expression
406         SetMixLength((length << 2U) | (compressed ? STRING_COMPRESSED : STRING_UNCOMPRESSED));
407     }
408 
GetDataUtf16Writable()409     uint16_t *GetDataUtf16Writable()
410     {
411         LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
412         return GetData();
413     }
414 
GetDataUtf8Writable()415     uint8_t *GetDataUtf8Writable()
416     {
417         ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
418         return reinterpret_cast<uint8_t *>(GetData());
419     }
420 
421     static void CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len);
422 
IsASCIICharacter(uint16_t data)423     static bool IsASCIICharacter(uint16_t data)
424     {
425         // \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000']
426         return data - 1U < base::utf_helper::UTF8_1B_MAX;
427     }
428 
429     /**
430      * str1 should have the same length as utf16_data.
431      * Converts utf8Data to utf16 and compare it with given utf16_data.
432      */
433     static bool IsUtf8EqualsUtf16(const uint8_t *utf8Data, size_t utf8Len, const uint16_t *utf16Data,
434                                   uint32_t utf16Len);
435 
436     template<typename T>
437     /**
438      * Check that two spans are equal. Should have the same length.
439      */
440     static bool StringsAreEquals(Span<const T> &str1, Span<const T> &str2);
441 
442     template<typename T>
443     /**
444      * Copy String from src to dst
445      * */
446     static bool StringCopy(Span<T> &dst, size_t dstMax, Span<const T> &src, size_t count);
447 
448     template<typename T1, typename T2>
449     static int32_t IndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, int32_t pos, int32_t max);
450 
451     template<typename T1, typename T2>
452     static int32_t LastIndexOf(Span<const T1> &lhsSp, Span<const T2> &rhsSp, int32_t pos);
453 };
454 
455 static_assert((EcmaString::DATA_OFFSET % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
456 
457 // if you want to use functions of EcmaString, please not use directly,
458 // and use functions of EcmaStringAccessor alternatively.
459 // eg: EcmaString *str = ***; str->GetLength() ----->  EcmaStringAccessor(str).GetLength()
460 class PUBLIC_API EcmaStringAccessor {
461 public:
462     explicit EcmaStringAccessor(EcmaString *string);
463 
464     explicit EcmaStringAccessor(TaggedObject *obj);
465 
466     explicit EcmaStringAccessor(JSTaggedValue value);
467 
468     explicit EcmaStringAccessor(const JSHandle<EcmaString> &strHandle);
469 
AllocStringObject(const EcmaVM * vm,size_t length,bool compressed)470     static EcmaString *AllocStringObject(const EcmaVM *vm, size_t length, bool compressed)
471     {
472         return EcmaString::AllocStringObject(vm, length, compressed);
473     }
474 
CreateEmptyString(const EcmaVM * vm)475     static EcmaString *CreateEmptyString(const EcmaVM *vm)
476     {
477         return EcmaString::CreateEmptyString(vm);
478     }
479 
480     static EcmaString *CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress,
481                                       MemSpaceType type = MemSpaceType::SEMI_SPACE)
482     {
483         return EcmaString::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, type);
484     }
485 
486     static EcmaString *CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len,
487                                        bool canBeCompress, MemSpaceType type = MemSpaceType::SEMI_SPACE)
488     {
489         return EcmaString::CreateFromUtf16(vm, utf16Data, utf16Len, canBeCompress, type);
490     }
491 
Concat(const EcmaVM * vm,const JSHandle<EcmaString> & str1Handle,const JSHandle<EcmaString> & str2Handle)492     static EcmaString *Concat(const EcmaVM *vm,
493         const JSHandle<EcmaString> &str1Handle, const JSHandle<EcmaString> &str2Handle)
494     {
495         return EcmaString::Concat(vm, str1Handle, str2Handle);
496     }
497 
FastSubString(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)498     static EcmaString *FastSubString(const EcmaVM *vm,
499         const JSHandle<EcmaString> &src, uint32_t start, uint32_t length)
500     {
501         return EcmaString::FastSubString(vm, src, start, length);
502     }
503 
IsUtf8()504     bool IsUtf8() const
505     {
506         return string_->IsUtf8();
507     }
508 
IsUtf16()509     bool IsUtf16() const
510     {
511         return string_->IsUtf16();
512     }
513 
GetLength()514     uint32_t GetLength() const
515     {
516         return string_->GetLength();
517     }
518 
GetUtf8Length()519     size_t GetUtf8Length() const
520     {
521         return string_->GetUtf8Length();
522     }
523 
ObjectSize()524     size_t ObjectSize() const
525     {
526         return string_->ObjectSize();
527     }
528 
IsInternString()529     bool IsInternString() const
530     {
531         return string_->IsInternString();
532     }
533 
SetInternString()534     void SetInternString()
535     {
536         string_->SetIsInternString();
537     }
538 
ClearInternString()539     void ClearInternString()
540     {
541         string_->ClearInternStringFlag();
542     }
543 
GetDataUtf8()544     const uint8_t *GetDataUtf8()
545     {
546         return string_->GetDataUtf8();
547     }
548 
GetDataUtf16()549     const uint16_t *GetDataUtf16()
550     {
551         return string_->GetDataUtf16();
552     }
553 
554     std::u16string ToU16String(uint32_t len = 0)
555     {
556         return string_->ToU16String(len);
557     }
558 
ToOneByteDataForced()559     std::unique_ptr<uint8_t[]> ToOneByteDataForced()
560     {
561         return string_->ToOneByteDataForced();
562     }
563 
ToUtf8Span(CVector<uint8_t> & buf)564     Span<const uint8_t> ToUtf8Span([[maybe_unused]] CVector<uint8_t> &buf)
565     {
566         return string_->ToUtf8Span(buf);
567     }
568 
569     std::string ToStdString(StringConvertedUsage usage = StringConvertedUsage::PRINT);
570 
571     CString ToCString(StringConvertedUsage usage = StringConvertedUsage::LOGICOPERATION);
572 
WriteToFlatUtf8(uint8_t * buf,uint32_t maxLength)573     uint32_t WriteToFlatUtf8(uint8_t *buf, uint32_t maxLength)
574     {
575         return string_->WriteUtf8(buf, maxLength);
576     }
577 
WriteToFlatUtf16(uint16_t * buf,uint32_t maxLength)578     uint32_t WriteToFlatUtf16(uint16_t *buf, uint32_t maxLength) const
579     {
580         return string_->CopyDataUtf16(buf, maxLength);
581     }
582 
ReadData(EcmaString * dst,EcmaString * src,uint32_t start,uint32_t destSize,uint32_t length)583     static void ReadData(EcmaString * dst, EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
584     {
585         dst->WriteData(src, start, destSize, length);
586     }
587 
588     template<bool verify = true>
Get(uint32_t index)589     uint16_t Get(uint32_t index) const
590     {
591         return string_->At<verify>(index);
592     }
593 
Set(uint32_t index,uint16_t src)594     void Set(uint32_t index, uint16_t src)
595     {
596         return string_->WriteData(src, index);
597     }
598 
GetHashcode()599     uint32_t GetHashcode()
600     {
601         return string_->GetHashcode();
602     }
603 
ComputeHashcode(uint32_t hashSeed)604     uint32_t ComputeHashcode(uint32_t hashSeed)
605     {
606         return string_->ComputeHashcode(hashSeed);
607     }
608 
ComputeHashcodeUtf8(const uint8_t * utf8Data,size_t utf8Len,bool canBeCompress)609     static uint32_t ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress)
610     {
611         return EcmaString::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress);
612     }
613 
ComputeHashcodeUtf16(const uint16_t * utf16Data,uint32_t length)614     static uint32_t ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length)
615     {
616         return EcmaString::ComputeHashcodeUtf16(utf16Data, length);
617     }
618 
619     static int32_t IndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0)
620     {
621         return EcmaString::IndexOf(lhs, rhs, pos);
622     }
623 
624     static int32_t LastIndexOf(EcmaString *lhs, EcmaString *rhs, int pos = 0)
625     {
626         return EcmaString::LastIndexOf(lhs, rhs, pos);
627     }
628 
Compare(EcmaString * lhs,EcmaString * rhs)629     static int32_t Compare(EcmaString *lhs, EcmaString *rhs)
630     {
631         return EcmaString::Compare(lhs, rhs);
632     }
633 
StringsAreEqual(EcmaString * str1,EcmaString * str2)634     static bool StringsAreEqual(EcmaString *str1, EcmaString *str2)
635     {
636         return EcmaString::StringsAreEqual(str1, str2);
637     }
638 
StringsAreEqualSameUtfEncoding(EcmaString * str1,EcmaString * str2)639     static bool StringsAreEqualSameUtfEncoding(EcmaString *str1, EcmaString *str2)
640     {
641         return EcmaString::StringsAreEqualSameUtfEncoding(str1, str2);
642     }
643 
StringsAreEqualUtf8(const EcmaString * str1,const uint8_t * utf8Data,uint32_t utf8Len,bool canBeCompress)644     static bool StringsAreEqualUtf8(const EcmaString *str1, const uint8_t *utf8Data, uint32_t utf8Len,
645                                     bool canBeCompress)
646     {
647         return EcmaString::StringsAreEqualUtf8(str1, utf8Data, utf8Len, canBeCompress);
648     }
649 
StringsAreEqualUtf16(const EcmaString * str1,const uint16_t * utf16Data,uint32_t utf16Len)650     static bool StringsAreEqualUtf16(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len)
651     {
652         return EcmaString::StringsAreEqualUtf16(str1, utf16Data, utf16Len);
653     }
654 
EqualToSplicedString(const EcmaString * str1,const EcmaString * str2)655     bool EqualToSplicedString(const EcmaString *str1, const EcmaString *str2)
656     {
657         return string_->EqualToSplicedString(str1, str2);
658     }
659 
CanBeCompressed(const uint8_t * utf8Data,uint32_t utf8Len)660     static bool CanBeCompressed(const uint8_t *utf8Data, uint32_t utf8Len)
661     {
662         return EcmaString::CanBeCompressed(utf8Data, utf8Len);
663     }
664 
CanBeCompressed(const uint16_t * utf16Data,uint32_t utf16Len)665     static bool CanBeCompressed(const uint16_t *utf16Data, uint32_t utf16Len)
666     {
667         return EcmaString::CanBeCompressed(utf16Data, utf16Len);
668     }
669 
CanBeCompressed(const EcmaString * string)670     static bool CanBeCompressed(const EcmaString *string)
671     {
672         return EcmaString::CanBeCompressed(string);
673     }
674 
ToElementIndex(uint32_t * index)675     bool ToElementIndex(uint32_t *index)
676     {
677         return string_->ToElementIndex(index);
678     }
679 
ToTypedArrayIndex(uint32_t * index)680     bool ToTypedArrayIndex(uint32_t *index)
681     {
682         return string_->ToTypedArrayIndex(index);
683     }
684 
ToLower(const EcmaVM * vm,const JSHandle<EcmaString> & src)685     static EcmaString *ToLower(const EcmaVM *vm, const JSHandle<EcmaString> &src)
686     {
687         return EcmaString::ToLower(vm, src);
688     }
689 
ToUpper(const EcmaVM * vm,const JSHandle<EcmaString> & src)690     static EcmaString *ToUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src)
691     {
692         return EcmaString::ToUpper(vm, src);
693     }
694 
ToLocaleLower(const EcmaVM * vm,const JSHandle<EcmaString> & src,const icu::Locale & locale)695     static EcmaString *ToLocaleLower(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale)
696     {
697         return EcmaString::ToLocaleLower(vm, src, locale);
698     }
699 
ToLocaleUpper(const EcmaVM * vm,const JSHandle<EcmaString> & src,const icu::Locale & locale)700     static EcmaString *ToLocaleUpper(const EcmaVM *vm, const JSHandle<EcmaString> &src, const icu::Locale &locale)
701     {
702         return EcmaString::ToLocaleUpper(vm, src, locale);
703     }
704 
705     static EcmaString *Trim(const JSThread *thread,
706         const JSHandle<EcmaString> &src, EcmaString::TrimMode mode = EcmaString::TrimMode::TRIM)
707     {
708         return EcmaString::Trim(thread, src, mode);
709     }
710 
711 private:
712     EcmaString *string_ {nullptr};
713 };
714 }  // namespace ecmascript
715 }  // namespace panda
716 #endif  // ECMASCRIPT_STRING_H