• 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_INL_H
17 #define ECMASCRIPT_STRING_INL_H
18 
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/object_factory-inl.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_tagged_value-inl.h"
24 
25 namespace panda::ecmascript {
26 /* static */
Cast(ObjectHeader * object)27 inline EcmaString *EcmaString::Cast(ObjectHeader *object)
28 {
29     ASSERT(JSTaggedValue(object).IsString());
30     return static_cast<EcmaString *>(object);
31 }
32 
33 /* static */
ConstCast(const TaggedObject * object)34 inline const EcmaString *EcmaString::ConstCast(const TaggedObject *object)
35 {
36     ASSERT(JSTaggedValue(object).IsString());
37     return static_cast<const EcmaString *>(object);
38 }
39 
40 /* static */
CreateEmptyString(const EcmaVM * vm)41 inline EcmaString *EcmaString::CreateEmptyString(const EcmaVM *vm)
42 {
43     auto string = vm->GetFactory()->AllocNonMovableStringObject(EcmaString::SIZE);
44     string->SetLength(0, GetCompressedStringsEnabled());
45     string->SetRawHashcode(0);
46     return string;
47 }
48 
49 /* static */
CreateFromUtf8(const uint8_t * utf8Data,uint32_t utf8Len,const EcmaVM * vm,bool canBeCompress)50 inline EcmaString *EcmaString::CreateFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len, const EcmaVM *vm,
51                                               bool canBeCompress)
52 {
53     if (utf8Len == 0) {
54         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
55     }
56     EcmaString *string = nullptr;
57     if (canBeCompress) {
58         string = AllocStringObject(utf8Len, true, vm);
59         ASSERT(string != nullptr);
60 
61         if (memcpy_s(string->GetDataUtf8Writable(), utf8Len, utf8Data, utf8Len) != EOK) {
62             LOG_ECMA(FATAL) << "memcpy_s failed";
63             UNREACHABLE();
64         }
65     } else {
66         auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
67         string = AllocStringObject(utf16Len, false, vm);
68         ASSERT(string != nullptr);
69 
70         [[maybe_unused]] auto len =
71             base::utf_helper::ConvertRegionUtf8ToUtf16(utf8Data, string->GetDataUtf16Writable(), utf8Len, utf16Len, 0);
72         ASSERT(len == utf16Len);
73     }
74 
75     ASSERT_PRINT(canBeCompress == CanBeCompressed(string), "Bad input canBeCompress!");
76     return string;
77 }
78 
CreateFromUtf16(const uint16_t * utf16Data,uint32_t utf16Len,const EcmaVM * vm,bool canBeCompress)79 inline EcmaString *EcmaString::CreateFromUtf16(const uint16_t *utf16Data, uint32_t utf16Len, const EcmaVM *vm,
80                                                bool canBeCompress)
81 {
82     if (utf16Len == 0) {
83         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
84     }
85     auto string = AllocStringObject(utf16Len, canBeCompress, vm);
86     ASSERT(string != nullptr);
87 
88     if (canBeCompress) {
89         CopyUtf16AsUtf8(utf16Data, string->GetDataUtf8Writable(), utf16Len);
90     } else {
91         uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t));
92         if (memcpy_s(string->GetDataUtf16Writable(), len, utf16Data, len) != EOK) {
93             LOG_ECMA(FATAL) << "memcpy_s failed";
94             UNREACHABLE();
95         }
96     }
97 
98     ASSERT_PRINT(canBeCompress == CanBeCompressed(string), "Bad input canBeCompress!");
99     return string;
100 }
101 
102 template<bool verify>
At(int32_t index)103 inline uint16_t EcmaString::At(int32_t index) const
104 {
105     int32_t length = GetLength();
106     if (verify) {
107         if ((index < 0) || (index >= length)) {
108             return 0;
109         }
110     }
111     if (!IsUtf16()) {
112         Span<const uint8_t> sp(GetDataUtf8(), length);
113         return sp[index];
114     }
115     Span<const uint16_t> sp(GetDataUtf16(), length);
116     return sp[index];
117 }
118 
119 /* static */
AllocStringObject(size_t length,bool compressed,const EcmaVM * vm)120 inline EcmaString *EcmaString::AllocStringObject(size_t length, bool compressed, const EcmaVM *vm)
121 {
122     size_t size = compressed ? ComputeSizeUtf8(length) : ComputeSizeUtf16(length);
123     auto string = reinterpret_cast<EcmaString *>(vm->GetFactory()->AllocStringObject(size));
124     string->SetLength(length, compressed);
125     string->SetRawHashcode(0);
126     return reinterpret_cast<EcmaString *>(string);
127 }
128 
WriteData(EcmaString * src,uint32_t start,uint32_t destSize,uint32_t length)129 void EcmaString::WriteData(EcmaString *src, uint32_t start, uint32_t destSize, uint32_t length)
130 {
131     if (IsUtf8()) {
132         ASSERT(src->IsUtf8());
133         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
134         if (length != 0 && memcpy_s(GetDataUtf8Writable() + start, destSize, src->GetDataUtf8(), length) != EOK) {
135             LOG_ECMA(FATAL) << "memcpy_s failed";
136             UNREACHABLE();
137         }
138     } else if (src->IsUtf8()) {
139         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
140         Span<uint16_t> to(GetDataUtf16Writable() + start, length);
141         Span<const uint8_t> from(src->GetDataUtf8(), length);
142         for (uint32_t i = 0; i < length; i++) {
143             to[i] = from[i];
144         }
145     } else {
146         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
147         if (length != 0 && memcpy_s(GetDataUtf16Writable() + start, ComputeDataSizeUtf16(destSize), src->GetDataUtf16(),
148                                     ComputeDataSizeUtf16(length)) != EOK) {
149             LOG_ECMA(FATAL) << "memcpy_s failed";
150             UNREACHABLE();
151         }
152     }
153 }
154 
WriteData(char src,uint32_t start)155 void EcmaString::WriteData(char src, uint32_t start)
156 {
157     if (IsUtf8()) {
158         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
159         *(GetDataUtf8Writable() + start) = src;
160     } else {
161         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
162         *(GetDataUtf16Writable() + start) = src;
163     }
164 }
165 
166 /* static */
FastSubUtf8String(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)167 EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
168                                           uint32_t length)
169 {
170     if (length == 0) {
171         return *vm->GetFactory()->GetEmptyString();
172     }
173     auto string = AllocStringObject(length, true, vm);
174     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
175     Span<uint8_t> dst(string->GetDataUtf8Writable(), length);
176     Span<const uint8_t> source(src->GetDataUtf8() + start, length);
177     EcmaString::StringCopy(dst, length, source, length);
178 
179     ASSERT_PRINT(CanBeCompressed(string), "canBeCompresse does not match the real value!");
180     return string;
181 }
182 
183 /* static */
FastSubUtf16String(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)184 EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
185                                            uint32_t length)
186 {
187     if (length == 0) {
188         return *vm->GetFactory()->GetEmptyString();
189     }
190     bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, length);
191     auto string = AllocStringObject(length, canBeCompressed, vm);
192     if (canBeCompressed) {
193         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
194         CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), length);
195     } else {
196         uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t));
197         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
198         Span<uint16_t> dst(string->GetDataUtf16Writable(), length);
199         Span<const uint16_t> source(src->GetDataUtf16() + start, length);
200         EcmaString::StringCopy(dst, len, source, len);
201     }
202     ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!");
203     return string;
204 }
205 }  // namespace panda::ecmascript
206 
207 #endif
208