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