• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 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 <charconv>
17 #include "ets_handle.h"
18 #include "libpandabase/utils/utf.h"
19 #include "libpandabase/utils/utils.h"
20 #include "plugins/ets/runtime/types/ets_typed_arrays.h"
21 #include "plugins/ets/runtime/types/ets_typed_unsigned_arrays.h"
22 #include "plugins/ets/runtime/intrinsics/helpers/ets_intrinsics_helpers.h"
23 #include "intrinsics.h"
24 #include "cross_values.h"
25 #include "types/ets_object.h"
26 
27 namespace ark::ets::intrinsics {
28 
29 template <typename T>
GetNativeData(T * array)30 static void *GetNativeData(T *array)
31 {
32     auto *arrayBuffer = static_cast<EtsEscompatArrayBuffer *>(&*array->GetBuffer());
33     if (UNLIKELY(arrayBuffer->WasDetached())) {
34         EtsCoroutine *coro = EtsCoroutine::GetCurrent();
35         ThrowEtsException(coro, panda_file_items::class_descriptors::TYPE_ERROR, "ArrayBuffer was detached");
36         return nullptr;
37     }
38 
39     return arrayBuffer->GetData();
40 }
41 
42 template <typename T>
EtsEscompatTypedArraySet(T * thisArray,EtsInt pos,typename T::ElementType val)43 static void EtsEscompatTypedArraySet(T *thisArray, EtsInt pos, typename T::ElementType val)
44 {
45     auto *data = GetNativeData(thisArray);
46     if (UNLIKELY(data == nullptr)) {
47         return;
48     }
49 
50     if (UNLIKELY(pos < 0 || pos >= thisArray->GetLengthInt())) {
51         EtsCoroutine *coro = EtsCoroutine::GetCurrent();
52         ThrowEtsException(coro, panda_file_items::class_descriptors::RANGE_ERROR, "invalid index");
53         return;
54     }
55     ObjectAccessor::SetPrimitive(
56         data, pos * sizeof(typename T::ElementType) + static_cast<EtsInt>(thisArray->GetByteOffset()), val);
57 }
58 
59 template <typename T>
EtsEscompatTypedArrayGet(T * thisArray,EtsInt pos)60 typename T::ElementType EtsEscompatTypedArrayGet(T *thisArray, EtsInt pos)
61 {
62     auto *data = GetNativeData(thisArray);
63     if (UNLIKELY(data == nullptr)) {
64         return 0;
65     }
66 
67     if (UNLIKELY(pos < 0 || pos >= thisArray->GetLengthInt())) {
68         EtsCoroutine *coro = EtsCoroutine::GetCurrent();
69         ThrowEtsException(coro, panda_file_items::class_descriptors::RANGE_ERROR, "invalid index");
70         return 0;
71     }
72     return ObjectAccessor::GetPrimitive<typename T::ElementType>(
73         data, pos * sizeof(typename T::ElementType) + static_cast<EtsInt>(thisArray->GetByteOffset()));
74 }
75 
76 template <typename T>
EtsEscompatTypedArrayGetUnsafe(T * thisArray,EtsInt pos)77 typename T::ElementType EtsEscompatTypedArrayGetUnsafe(T *thisArray, EtsInt pos)
78 {
79     ASSERT(pos >= 0 && pos < thisArray->GetLengthInt());
80 
81     auto *data = GetNativeData(thisArray);
82     if (UNLIKELY(data == nullptr)) {
83         return 0;
84     }
85 
86     return ObjectAccessor::GetPrimitive<typename T::ElementType>(
87         data, pos * sizeof(typename T::ElementType) + static_cast<EtsInt>(thisArray->GetByteOffset()));
88 }
89 
EtsEscompatInt8ArraySetInt(ark::ets::EtsEscompatInt8Array * thisArray,EtsInt pos,EtsInt val)90 extern "C" void EtsEscompatInt8ArraySetInt(ark::ets::EtsEscompatInt8Array *thisArray, EtsInt pos, EtsInt val)
91 {
92     EtsEscompatTypedArraySet(thisArray, pos, val);
93 }
94 
EtsEscompatInt8ArraySetByte(ark::ets::EtsEscompatInt8Array * thisArray,EtsInt pos,EtsByte val)95 extern "C" void EtsEscompatInt8ArraySetByte(ark::ets::EtsEscompatInt8Array *thisArray, EtsInt pos, EtsByte val)
96 {
97     EtsEscompatTypedArraySet(thisArray, pos, val);
98 }
99 
EtsEscompatInt8ArrayGet(ark::ets::EtsEscompatInt8Array * thisArray,EtsInt pos)100 extern "C" EtsDouble EtsEscompatInt8ArrayGet(ark::ets::EtsEscompatInt8Array *thisArray, EtsInt pos)
101 {
102     return EtsEscompatTypedArrayGet(thisArray, pos);
103 }
104 
EtsEscompatInt8ArrayGetUnsafe(ark::ets::EtsEscompatInt8Array * thisArray,EtsInt pos)105 extern "C" EtsByte EtsEscompatInt8ArrayGetUnsafe(ark::ets::EtsEscompatInt8Array *thisArray, EtsInt pos)
106 {
107     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
108 }
109 
110 template <typename T>
EtsEscompatTypedArraySetValuesImpl(T * thisArray,T * srcArray,EtsInt pos)111 static void EtsEscompatTypedArraySetValuesImpl(T *thisArray, T *srcArray, EtsInt pos)
112 {
113     auto *dstData = GetNativeData(thisArray);
114     if (UNLIKELY(dstData == nullptr)) {
115         return;
116     }
117     auto *srcData = GetNativeData(srcArray);
118     if (UNLIKELY(srcData == nullptr)) {
119         return;
120     }
121 
122     using ElementType = typename T::ElementType;
123     if (UNLIKELY(pos < 0 || pos + srcArray->GetLengthInt() > thisArray->GetLengthInt())) {
124         EtsCoroutine *coro = EtsCoroutine::GetCurrent();
125         ThrowEtsException(coro, panda_file_items::class_descriptors::RANGE_ERROR, "offset is out of bounds");
126         return;
127     }
128     auto *dst = ToVoidPtr(ToUintPtr(dstData) + thisArray->GetByteOffset() + pos * sizeof(ElementType));
129     auto *src = ToVoidPtr(ToUintPtr(srcData) + srcArray->GetByteOffset());
130     [[maybe_unused]] auto error = memmove_s(dst, (thisArray->GetLengthInt() - pos) * sizeof(ElementType), src,
131                                             srcArray->GetLengthInt() * sizeof(ElementType));
132     ASSERT(error == EOK);
133 }
134 
EtsEscompatInt8ArraySetValues(ark::ets::EtsEscompatInt8Array * thisArray,ark::ets::EtsEscompatInt8Array * srcArray)135 extern "C" void EtsEscompatInt8ArraySetValues(ark::ets::EtsEscompatInt8Array *thisArray,
136                                               ark::ets::EtsEscompatInt8Array *srcArray)
137 {
138     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
139 }
140 
EtsEscompatInt8ArraySetValuesWithOffset(ark::ets::EtsEscompatInt8Array * thisArray,ark::ets::EtsEscompatInt8Array * srcArray,EtsDouble pos)141 extern "C" void EtsEscompatInt8ArraySetValuesWithOffset(ark::ets::EtsEscompatInt8Array *thisArray,
142                                                         ark::ets::EtsEscompatInt8Array *srcArray, EtsDouble pos)
143 {
144     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
145 }
146 
147 template <typename T, typename V>
EtsEscompatTypedArrayFillInternal(T * thisArray,V val,EtsInt begin,EtsInt end)148 static void EtsEscompatTypedArrayFillInternal(T *thisArray, V val, EtsInt begin, EtsInt end)
149 {
150     static_assert(sizeof(V) == sizeof(typename T::ElementType));
151     auto *data = GetNativeData(thisArray);
152     if (UNLIKELY(data == nullptr)) {
153         return;
154     }
155     auto offset = static_cast<EtsInt>(thisArray->GetByteOffset()) + begin * sizeof(V);
156     for (auto i = begin; i < end; ++i) {
157         ObjectAccessor::SetPrimitive(data, offset, val);
158         offset += sizeof(V);
159     }
160 }
161 
EtsEscompatInt8ArrayFillInternal(ark::ets::EtsEscompatInt8Array * thisArray,EtsByte val,EtsInt begin,EtsInt end)162 extern "C" void EtsEscompatInt8ArrayFillInternal(ark::ets::EtsEscompatInt8Array *thisArray, EtsByte val, EtsInt begin,
163                                                  EtsInt end)
164 {
165     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
166 }
167 
EtsEscompatInt16ArraySetInt(ark::ets::EtsEscompatInt16Array * thisArray,EtsInt pos,EtsInt val)168 extern "C" void EtsEscompatInt16ArraySetInt(ark::ets::EtsEscompatInt16Array *thisArray, EtsInt pos, EtsInt val)
169 {
170     EtsEscompatTypedArraySet(thisArray, pos, val);
171 }
172 
EtsEscompatInt16ArraySetShort(ark::ets::EtsEscompatInt16Array * thisArray,EtsInt pos,EtsShort val)173 extern "C" void EtsEscompatInt16ArraySetShort(ark::ets::EtsEscompatInt16Array *thisArray, EtsInt pos, EtsShort val)
174 {
175     EtsEscompatTypedArraySet(thisArray, pos, val);
176 }
177 
EtsEscompatInt16ArrayGet(ark::ets::EtsEscompatInt16Array * thisArray,EtsInt pos)178 extern "C" EtsDouble EtsEscompatInt16ArrayGet(ark::ets::EtsEscompatInt16Array *thisArray, EtsInt pos)
179 {
180     return EtsEscompatTypedArrayGet(thisArray, pos);
181 }
182 
EtsEscompatInt16ArrayGetUnsafe(ark::ets::EtsEscompatInt16Array * thisArray,EtsInt pos)183 extern "C" EtsShort EtsEscompatInt16ArrayGetUnsafe(ark::ets::EtsEscompatInt16Array *thisArray, EtsInt pos)
184 {
185     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
186 }
187 
EtsEscompatInt16ArraySetValues(ark::ets::EtsEscompatInt16Array * thisArray,ark::ets::EtsEscompatInt16Array * srcArray)188 extern "C" void EtsEscompatInt16ArraySetValues(ark::ets::EtsEscompatInt16Array *thisArray,
189                                                ark::ets::EtsEscompatInt16Array *srcArray)
190 {
191     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
192 }
193 
EtsEscompatInt16ArraySetValuesWithOffset(ark::ets::EtsEscompatInt16Array * thisArray,ark::ets::EtsEscompatInt16Array * srcArray,EtsDouble pos)194 extern "C" void EtsEscompatInt16ArraySetValuesWithOffset(ark::ets::EtsEscompatInt16Array *thisArray,
195                                                          ark::ets::EtsEscompatInt16Array *srcArray, EtsDouble pos)
196 {
197     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
198 }
199 
EtsEscompatInt16ArrayFillInternal(ark::ets::EtsEscompatInt16Array * thisArray,EtsShort val,EtsInt begin,EtsInt end)200 extern "C" void EtsEscompatInt16ArrayFillInternal(ark::ets::EtsEscompatInt16Array *thisArray, EtsShort val,
201                                                   EtsInt begin, EtsInt end)
202 {
203     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
204 }
205 
EtsEscompatInt32ArraySetInt(ark::ets::EtsEscompatInt32Array * thisArray,EtsInt pos,EtsInt val)206 extern "C" void EtsEscompatInt32ArraySetInt(ark::ets::EtsEscompatInt32Array *thisArray, EtsInt pos, EtsInt val)
207 {
208     EtsEscompatTypedArraySet(thisArray, pos, val);
209 }
210 
EtsEscompatInt32ArrayGet(ark::ets::EtsEscompatInt32Array * thisArray,EtsInt pos)211 extern "C" EtsDouble EtsEscompatInt32ArrayGet(ark::ets::EtsEscompatInt32Array *thisArray, EtsInt pos)
212 {
213     return EtsEscompatTypedArrayGet(thisArray, pos);
214 }
215 
EtsEscompatInt32ArrayGetUnsafe(ark::ets::EtsEscompatInt32Array * thisArray,EtsInt pos)216 extern "C" EtsInt EtsEscompatInt32ArrayGetUnsafe(ark::ets::EtsEscompatInt32Array *thisArray, EtsInt pos)
217 {
218     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
219 }
220 
EtsEscompatInt32ArraySetValues(ark::ets::EtsEscompatInt32Array * thisArray,ark::ets::EtsEscompatInt32Array * srcArray)221 extern "C" void EtsEscompatInt32ArraySetValues(ark::ets::EtsEscompatInt32Array *thisArray,
222                                                ark::ets::EtsEscompatInt32Array *srcArray)
223 {
224     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
225 }
226 
EtsEscompatInt32ArraySetValuesWithOffset(ark::ets::EtsEscompatInt32Array * thisArray,ark::ets::EtsEscompatInt32Array * srcArray,EtsDouble pos)227 extern "C" void EtsEscompatInt32ArraySetValuesWithOffset(ark::ets::EtsEscompatInt32Array *thisArray,
228                                                          ark::ets::EtsEscompatInt32Array *srcArray, EtsDouble pos)
229 {
230     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
231 }
232 
EtsEscompatInt32ArrayFillInternal(ark::ets::EtsEscompatInt32Array * thisArray,EtsInt val,EtsInt begin,EtsInt end)233 extern "C" void EtsEscompatInt32ArrayFillInternal(ark::ets::EtsEscompatInt32Array *thisArray, EtsInt val, EtsInt begin,
234                                                   EtsInt end)
235 {
236     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
237 }
238 
EtsEscompatBigInt64ArraySetLong(ark::ets::EtsEscompatBigInt64Array * thisArray,EtsInt pos,EtsLong val)239 extern "C" void EtsEscompatBigInt64ArraySetLong(ark::ets::EtsEscompatBigInt64Array *thisArray, EtsInt pos, EtsLong val)
240 {
241     EtsEscompatTypedArraySet(thisArray, pos, val);
242 }
243 
EtsEscompatBigInt64ArrayGet(ark::ets::EtsEscompatBigInt64Array * thisArray,EtsInt pos)244 extern "C" EtsLong EtsEscompatBigInt64ArrayGet(ark::ets::EtsEscompatBigInt64Array *thisArray, EtsInt pos)
245 {
246     return EtsEscompatTypedArrayGet(thisArray, pos);
247 }
248 
EtsEscompatBigInt64ArrayGetUnsafe(ark::ets::EtsEscompatBigInt64Array * thisArray,EtsInt pos)249 extern "C" EtsLong EtsEscompatBigInt64ArrayGetUnsafe(ark::ets::EtsEscompatBigInt64Array *thisArray, EtsInt pos)
250 {
251     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
252 }
253 
EtsEscompatBigInt64ArraySetValues(ark::ets::EtsEscompatBigInt64Array * thisArray,ark::ets::EtsEscompatBigInt64Array * srcArray)254 extern "C" void EtsEscompatBigInt64ArraySetValues(ark::ets::EtsEscompatBigInt64Array *thisArray,
255                                                   ark::ets::EtsEscompatBigInt64Array *srcArray)
256 {
257     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
258 }
259 
EtsEscompatBigInt64ArraySetValuesWithOffset(ark::ets::EtsEscompatBigInt64Array * thisArray,ark::ets::EtsEscompatBigInt64Array * srcArray,EtsDouble pos)260 extern "C" void EtsEscompatBigInt64ArraySetValuesWithOffset(ark::ets::EtsEscompatBigInt64Array *thisArray,
261                                                             ark::ets::EtsEscompatBigInt64Array *srcArray, EtsDouble pos)
262 {
263     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
264 }
265 
EtsEscompatBigInt64ArrayFillInternal(ark::ets::EtsEscompatBigInt64Array * thisArray,EtsLong val,EtsInt begin,EtsInt end)266 extern "C" void EtsEscompatBigInt64ArrayFillInternal(ark::ets::EtsEscompatBigInt64Array *thisArray, EtsLong val,
267                                                      EtsInt begin, EtsInt end)
268 {
269     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
270 }
271 
EtsEscompatFloat32ArraySetFloat(ark::ets::EtsEscompatFloat32Array * thisArray,EtsInt pos,EtsFloat val)272 extern "C" void EtsEscompatFloat32ArraySetFloat(ark::ets::EtsEscompatFloat32Array *thisArray, EtsInt pos, EtsFloat val)
273 {
274     EtsEscompatTypedArraySet(thisArray, pos, val);
275 }
276 
EtsEscompatFloat32ArrayGet(ark::ets::EtsEscompatFloat32Array * thisArray,EtsInt pos)277 extern "C" EtsDouble EtsEscompatFloat32ArrayGet(ark::ets::EtsEscompatFloat32Array *thisArray, EtsInt pos)
278 {
279     return EtsEscompatTypedArrayGet(thisArray, pos);
280 }
281 
EtsEscompatFloat32ArrayGetUnsafe(ark::ets::EtsEscompatFloat32Array * thisArray,EtsInt pos)282 extern "C" EtsFloat EtsEscompatFloat32ArrayGetUnsafe(ark::ets::EtsEscompatFloat32Array *thisArray, EtsInt pos)
283 {
284     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
285 }
286 
EtsEscompatFloat32ArraySetValues(ark::ets::EtsEscompatFloat32Array * thisArray,ark::ets::EtsEscompatFloat32Array * srcArray)287 extern "C" void EtsEscompatFloat32ArraySetValues(ark::ets::EtsEscompatFloat32Array *thisArray,
288                                                  ark::ets::EtsEscompatFloat32Array *srcArray)
289 {
290     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
291 }
292 
EtsEscompatFloat32ArraySetValuesWithOffset(ark::ets::EtsEscompatFloat32Array * thisArray,ark::ets::EtsEscompatFloat32Array * srcArray,EtsDouble pos)293 extern "C" void EtsEscompatFloat32ArraySetValuesWithOffset(ark::ets::EtsEscompatFloat32Array *thisArray,
294                                                            ark::ets::EtsEscompatFloat32Array *srcArray, EtsDouble pos)
295 {
296     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
297 }
298 
EtsEscompatFloat32ArrayFillInternal(ark::ets::EtsEscompatFloat32Array * thisArray,EtsFloat val,EtsInt begin,EtsInt end)299 extern "C" void EtsEscompatFloat32ArrayFillInternal(ark::ets::EtsEscompatFloat32Array *thisArray, EtsFloat val,
300                                                     EtsInt begin, EtsInt end)
301 {
302     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
303 }
304 
EtsEscompatFloat32ArrayFillInternalInt(ark::ets::EtsEscompatFloat32Array * thisArray,int32_t val,EtsInt begin,EtsInt end)305 extern "C" void EtsEscompatFloat32ArrayFillInternalInt(ark::ets::EtsEscompatFloat32Array *thisArray, int32_t val,
306                                                        EtsInt begin, EtsInt end)
307 {
308     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
309 }
310 
EtsEscompatFloat64ArraySetDouble(ark::ets::EtsEscompatFloat64Array * thisArray,EtsInt pos,EtsDouble val)311 extern "C" void EtsEscompatFloat64ArraySetDouble(ark::ets::EtsEscompatFloat64Array *thisArray, EtsInt pos,
312                                                  EtsDouble val)
313 {
314     EtsEscompatTypedArraySet(thisArray, pos, val);
315 }
316 
EtsEscompatFloat64ArrayGet(ark::ets::EtsEscompatFloat64Array * thisArray,EtsInt pos)317 extern "C" EtsDouble EtsEscompatFloat64ArrayGet(ark::ets::EtsEscompatFloat64Array *thisArray, EtsInt pos)
318 {
319     return EtsEscompatTypedArrayGet(thisArray, pos);
320 }
321 
EtsEscompatFloat64ArrayGetUnsafe(ark::ets::EtsEscompatFloat64Array * thisArray,EtsInt pos)322 extern "C" EtsDouble EtsEscompatFloat64ArrayGetUnsafe(ark::ets::EtsEscompatFloat64Array *thisArray, EtsInt pos)
323 {
324     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
325 }
326 
EtsEscompatFloat64ArraySetValues(ark::ets::EtsEscompatFloat64Array * thisArray,ark::ets::EtsEscompatFloat64Array * srcArray)327 extern "C" void EtsEscompatFloat64ArraySetValues(ark::ets::EtsEscompatFloat64Array *thisArray,
328                                                  ark::ets::EtsEscompatFloat64Array *srcArray)
329 {
330     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
331 }
332 
EtsEscompatFloat64ArraySetValuesWithOffset(ark::ets::EtsEscompatFloat64Array * thisArray,ark::ets::EtsEscompatFloat64Array * srcArray,EtsDouble pos)333 extern "C" void EtsEscompatFloat64ArraySetValuesWithOffset(ark::ets::EtsEscompatFloat64Array *thisArray,
334                                                            ark::ets::EtsEscompatFloat64Array *srcArray, EtsDouble pos)
335 {
336     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
337 }
338 
EtsEscompatFloat64ArrayFillInternal(ark::ets::EtsEscompatFloat64Array * thisArray,EtsDouble val,EtsInt begin,EtsInt end)339 extern "C" void EtsEscompatFloat64ArrayFillInternal(ark::ets::EtsEscompatFloat64Array *thisArray, EtsDouble val,
340                                                     EtsInt begin, EtsInt end)
341 {
342     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
343 }
344 
EtsEscompatFloat64ArrayFillInternalInt(ark::ets::EtsEscompatFloat64Array * thisArray,int64_t val,EtsInt begin,EtsInt end)345 extern "C" void EtsEscompatFloat64ArrayFillInternalInt(ark::ets::EtsEscompatFloat64Array *thisArray, int64_t val,
346                                                        EtsInt begin, EtsInt end)
347 {
348     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
349 }
350 
EtsEscompatUInt8ClampedArraySetInt(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,EtsInt pos,EtsInt val)351 extern "C" void EtsEscompatUInt8ClampedArraySetInt(ark::ets::EtsEscompatUInt8ClampedArray *thisArray, EtsInt pos,
352                                                    EtsInt val)
353 {
354     if (val > ark::ets::EtsEscompatUInt8ClampedArray::MAX) {
355         val = ark::ets::EtsEscompatUInt8ClampedArray::MAX;
356     } else if (val < ark::ets::EtsEscompatUInt8ClampedArray::MIN) {
357         val = ark::ets::EtsEscompatUInt8ClampedArray::MIN;
358     }
359     EtsEscompatTypedArraySet(thisArray, pos, val);
360 }
361 
EtsEscompatUInt8ClampedArrayGet(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,EtsInt pos)362 extern "C" EtsDouble EtsEscompatUInt8ClampedArrayGet(ark::ets::EtsEscompatUInt8ClampedArray *thisArray, EtsInt pos)
363 {
364     return EtsEscompatTypedArrayGet(thisArray, pos);
365 }
366 
EtsEscompatUInt8ClampedArrayGetUnsafe(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,EtsInt pos)367 extern "C" EtsInt EtsEscompatUInt8ClampedArrayGetUnsafe(ark::ets::EtsEscompatUInt8ClampedArray *thisArray, EtsInt pos)
368 {
369     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
370 }
371 
EtsEscompatUInt8ClampedArraySetValues(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,ark::ets::EtsEscompatUInt8ClampedArray * srcArray)372 extern "C" void EtsEscompatUInt8ClampedArraySetValues(ark::ets::EtsEscompatUInt8ClampedArray *thisArray,
373                                                       ark::ets::EtsEscompatUInt8ClampedArray *srcArray)
374 {
375     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
376 }
377 
EtsEscompatUInt8ClampedArraySetValuesWithOffset(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,ark::ets::EtsEscompatUInt8ClampedArray * srcArray,EtsDouble pos)378 extern "C" void EtsEscompatUInt8ClampedArraySetValuesWithOffset(ark::ets::EtsEscompatUInt8ClampedArray *thisArray,
379                                                                 ark::ets::EtsEscompatUInt8ClampedArray *srcArray,
380                                                                 EtsDouble pos)
381 {
382     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
383 }
384 
EtsEscompatUInt8ClampedArrayFillInternal(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,EtsInt val,EtsInt begin,EtsInt end)385 extern "C" void EtsEscompatUInt8ClampedArrayFillInternal(ark::ets::EtsEscompatUInt8ClampedArray *thisArray, EtsInt val,
386                                                          EtsInt begin, EtsInt end)
387 {
388     using ElementType = ark::ets::EtsEscompatUInt8ClampedArray::ElementType;
389     EtsEscompatTypedArrayFillInternal(thisArray, static_cast<ElementType>(val), begin, end);
390 }
391 
EtsEscompatUInt8ArraySetInt(ark::ets::EtsEscompatUInt8Array * thisArray,EtsInt pos,EtsInt val)392 extern "C" void EtsEscompatUInt8ArraySetInt(ark::ets::EtsEscompatUInt8Array *thisArray, EtsInt pos, EtsInt val)
393 {
394     EtsEscompatTypedArraySet(thisArray, pos, val);
395 }
396 
EtsEscompatUInt8ArrayGet(ark::ets::EtsEscompatUInt8Array * thisArray,EtsInt pos)397 extern "C" EtsDouble EtsEscompatUInt8ArrayGet(ark::ets::EtsEscompatUInt8Array *thisArray, EtsInt pos)
398 {
399     return EtsEscompatTypedArrayGet(thisArray, pos);
400 }
401 
EtsEscompatUInt8ArrayGetUnsafe(ark::ets::EtsEscompatUInt8Array * thisArray,EtsInt pos)402 extern "C" EtsInt EtsEscompatUInt8ArrayGetUnsafe(ark::ets::EtsEscompatUInt8Array *thisArray, EtsInt pos)
403 {
404     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
405 }
406 
EtsEscompatUInt8ArraySetValues(ark::ets::EtsEscompatUInt8Array * thisArray,ark::ets::EtsEscompatUInt8Array * srcArray)407 extern "C" void EtsEscompatUInt8ArraySetValues(ark::ets::EtsEscompatUInt8Array *thisArray,
408                                                ark::ets::EtsEscompatUInt8Array *srcArray)
409 {
410     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
411 }
412 
EtsEscompatUInt8ArraySetValuesWithOffset(ark::ets::EtsEscompatUInt8Array * thisArray,ark::ets::EtsEscompatUInt8Array * srcArray,EtsDouble pos)413 extern "C" void EtsEscompatUInt8ArraySetValuesWithOffset(ark::ets::EtsEscompatUInt8Array *thisArray,
414                                                          ark::ets::EtsEscompatUInt8Array *srcArray, EtsDouble pos)
415 {
416     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
417 }
418 
EtsEscompatUInt8ArrayFillInternal(ark::ets::EtsEscompatUInt8Array * thisArray,EtsInt val,EtsInt begin,EtsInt end)419 extern "C" void EtsEscompatUInt8ArrayFillInternal(ark::ets::EtsEscompatUInt8Array *thisArray, EtsInt val, EtsInt begin,
420                                                   EtsInt end)
421 {
422     using ElementType = ark::ets::EtsEscompatUInt8Array::ElementType;
423     EtsEscompatTypedArrayFillInternal(thisArray, static_cast<ElementType>(val), begin, end);
424 }
425 
EtsEscompatUInt16ArraySetInt(ark::ets::EtsEscompatUInt16Array * thisArray,EtsInt pos,EtsInt val)426 extern "C" void EtsEscompatUInt16ArraySetInt(ark::ets::EtsEscompatUInt16Array *thisArray, EtsInt pos, EtsInt val)
427 {
428     EtsEscompatTypedArraySet(thisArray, pos, val);
429 }
430 
EtsEscompatUInt16ArrayGet(ark::ets::EtsEscompatUInt16Array * thisArray,EtsInt pos)431 extern "C" EtsDouble EtsEscompatUInt16ArrayGet(ark::ets::EtsEscompatUInt16Array *thisArray, EtsInt pos)
432 {
433     return EtsEscompatTypedArrayGet(thisArray, pos);
434 }
435 
EtsEscompatUInt16ArrayGetUnsafe(ark::ets::EtsEscompatUInt16Array * thisArray,EtsInt pos)436 extern "C" EtsInt EtsEscompatUInt16ArrayGetUnsafe(ark::ets::EtsEscompatUInt16Array *thisArray, EtsInt pos)
437 {
438     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
439 }
440 
EtsEscompatUInt16ArraySetValues(ark::ets::EtsEscompatUInt16Array * thisArray,ark::ets::EtsEscompatUInt16Array * srcArray)441 extern "C" void EtsEscompatUInt16ArraySetValues(ark::ets::EtsEscompatUInt16Array *thisArray,
442                                                 ark::ets::EtsEscompatUInt16Array *srcArray)
443 {
444     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
445 }
446 
EtsEscompatUInt16ArraySetValuesWithOffset(ark::ets::EtsEscompatUInt16Array * thisArray,ark::ets::EtsEscompatUInt16Array * srcArray,EtsDouble pos)447 extern "C" void EtsEscompatUInt16ArraySetValuesWithOffset(ark::ets::EtsEscompatUInt16Array *thisArray,
448                                                           ark::ets::EtsEscompatUInt16Array *srcArray, EtsDouble pos)
449 {
450     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
451 }
452 
EtsEscompatUInt16ArrayFillInternal(ark::ets::EtsEscompatUInt16Array * thisArray,EtsInt val,EtsInt begin,EtsInt end)453 extern "C" void EtsEscompatUInt16ArrayFillInternal(ark::ets::EtsEscompatUInt16Array *thisArray, EtsInt val,
454                                                    EtsInt begin, EtsInt end)
455 {
456     using ElementType = ark::ets::EtsEscompatUInt16Array::ElementType;
457     EtsEscompatTypedArrayFillInternal(thisArray, static_cast<ElementType>(val), begin, end);
458 }
459 
EtsEscompatUInt32ArraySetInt(ark::ets::EtsEscompatUInt32Array * thisArray,EtsInt pos,EtsInt val)460 extern "C" void EtsEscompatUInt32ArraySetInt(ark::ets::EtsEscompatUInt32Array *thisArray, EtsInt pos, EtsInt val)
461 {
462     EtsEscompatTypedArraySet(thisArray, pos, val);
463 }
464 
EtsEscompatUInt32ArraySetLong(ark::ets::EtsEscompatUInt32Array * thisArray,EtsInt pos,EtsLong val)465 extern "C" void EtsEscompatUInt32ArraySetLong(ark::ets::EtsEscompatUInt32Array *thisArray, EtsInt pos, EtsLong val)
466 {
467     EtsEscompatTypedArraySet(thisArray, pos, val);
468 }
469 
EtsEscompatUInt32ArrayGet(ark::ets::EtsEscompatUInt32Array * thisArray,EtsInt pos)470 extern "C" EtsDouble EtsEscompatUInt32ArrayGet(ark::ets::EtsEscompatUInt32Array *thisArray, EtsInt pos)
471 {
472     return EtsEscompatTypedArrayGet(thisArray, pos);
473 }
474 
EtsEscompatUInt32ArrayGetUnsafe(ark::ets::EtsEscompatUInt32Array * thisArray,EtsInt pos)475 extern "C" EtsLong EtsEscompatUInt32ArrayGetUnsafe(ark::ets::EtsEscompatUInt32Array *thisArray, EtsInt pos)
476 {
477     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
478 }
479 
EtsEscompatUInt32ArraySetValues(ark::ets::EtsEscompatUInt32Array * thisArray,ark::ets::EtsEscompatUInt32Array * srcArray)480 extern "C" void EtsEscompatUInt32ArraySetValues(ark::ets::EtsEscompatUInt32Array *thisArray,
481                                                 ark::ets::EtsEscompatUInt32Array *srcArray)
482 {
483     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
484 }
485 
EtsEscompatUInt32ArraySetValuesWithOffset(ark::ets::EtsEscompatUInt32Array * thisArray,ark::ets::EtsEscompatUInt32Array * srcArray,EtsDouble pos)486 extern "C" void EtsEscompatUInt32ArraySetValuesWithOffset(ark::ets::EtsEscompatUInt32Array *thisArray,
487                                                           ark::ets::EtsEscompatUInt32Array *srcArray, EtsDouble pos)
488 {
489     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
490 }
491 
EtsEscompatUInt32ArrayFillInternal(ark::ets::EtsEscompatUInt32Array * thisArray,EtsLong val,EtsInt begin,EtsInt end)492 extern "C" void EtsEscompatUInt32ArrayFillInternal(ark::ets::EtsEscompatUInt32Array *thisArray, EtsLong val,
493                                                    EtsInt begin, EtsInt end)
494 {
495     using ElementType = ark::ets::EtsEscompatUInt32Array::ElementType;
496     EtsEscompatTypedArrayFillInternal(thisArray, static_cast<ElementType>(val), begin, end);
497 }
498 
EtsEscompatBigUInt64ArraySetInt(ark::ets::EtsEscompatBigUInt64Array * thisArray,EtsInt pos,EtsInt val)499 extern "C" void EtsEscompatBigUInt64ArraySetInt(ark::ets::EtsEscompatBigUInt64Array *thisArray, EtsInt pos, EtsInt val)
500 {
501     EtsEscompatTypedArraySet(thisArray, pos, val);
502 }
503 
EtsEscompatBigUInt64ArraySetLong(ark::ets::EtsEscompatBigUInt64Array * thisArray,EtsInt pos,EtsLong val)504 extern "C" void EtsEscompatBigUInt64ArraySetLong(ark::ets::EtsEscompatBigUInt64Array *thisArray, EtsInt pos,
505                                                  EtsLong val)
506 {
507     EtsEscompatTypedArraySet(thisArray, pos, val);
508 }
509 
EtsEscompatBigUInt64ArrayGet(ark::ets::EtsEscompatBigUInt64Array * thisArray,EtsInt pos)510 extern "C" EtsLong EtsEscompatBigUInt64ArrayGet(ark::ets::EtsEscompatBigUInt64Array *thisArray, EtsInt pos)
511 {
512     return EtsEscompatTypedArrayGet(thisArray, pos);
513 }
514 
EtsEscompatBigUInt64ArrayGetUnsafe(ark::ets::EtsEscompatBigUInt64Array * thisArray,EtsInt pos)515 extern "C" EtsLong EtsEscompatBigUInt64ArrayGetUnsafe(ark::ets::EtsEscompatBigUInt64Array *thisArray, EtsInt pos)
516 {
517     return EtsEscompatTypedArrayGetUnsafe(thisArray, pos);
518 }
519 
EtsEscompatBigUInt64ArraySetValues(ark::ets::EtsEscompatBigUInt64Array * thisArray,ark::ets::EtsEscompatBigUInt64Array * srcArray)520 extern "C" void EtsEscompatBigUInt64ArraySetValues(ark::ets::EtsEscompatBigUInt64Array *thisArray,
521                                                    ark::ets::EtsEscompatBigUInt64Array *srcArray)
522 {
523     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, 0);
524 }
525 
EtsEscompatBigUInt64ArraySetValuesWithOffset(ark::ets::EtsEscompatBigUInt64Array * thisArray,ark::ets::EtsEscompatBigUInt64Array * srcArray,EtsDouble pos)526 extern "C" void EtsEscompatBigUInt64ArraySetValuesWithOffset(ark::ets::EtsEscompatBigUInt64Array *thisArray,
527                                                              ark::ets::EtsEscompatBigUInt64Array *srcArray,
528                                                              EtsDouble pos)
529 {
530     EtsEscompatTypedArraySetValuesImpl(thisArray, srcArray, static_cast<EtsInt>(pos));
531 }
532 
EtsEscompatBigUInt64ArrayFillInternal(ark::ets::EtsEscompatBigUInt64Array * thisArray,EtsLong val,EtsInt begin,EtsInt end)533 extern "C" void EtsEscompatBigUInt64ArrayFillInternal(ark::ets::EtsEscompatBigUInt64Array *thisArray, EtsLong val,
534                                                       EtsInt begin, EtsInt end)
535 {
536     EtsEscompatTypedArrayFillInternal(thisArray, val, begin, end);
537 }
538 
539 /*
540  * Typed Arrays: Reverse Implementation
541  */
542 template <typename T>
EtsEscompatTypedArrayReverseImpl(T * thisArray)543 static T *EtsEscompatTypedArrayReverseImpl(T *thisArray)
544 {
545     auto *arrData = GetNativeData(thisArray);
546     if (UNLIKELY(arrData == nullptr)) {
547         return nullptr;
548     }
549     using ElementType = typename T::ElementType;
550     auto *ptrFirst = reinterpret_cast<ElementType *>(ToVoidPtr(ToUintPtr(arrData) + thisArray->GetByteOffset()));
551     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
552     auto *ptrLast = ptrFirst + thisArray->GetLengthInt();
553     std::reverse(ptrFirst, ptrLast);
554     return thisArray;
555 }
556 
557 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
558 #define REVERSE_CALL_DECL(Type)                                                     \
559     /* CC-OFFNXT(G.PRE.02) name part */                                             \
560     extern "C" ark::ets::EtsEscompat##Type##Array *EtsEscompat##Type##ArrayReverse( \
561         ark::ets::EtsEscompat##Type##Array *thisArray)                              \
562     {                                                                               \
563         /* CC-OFFNXT(G.PRE.05) function gen */                                      \
564         return EtsEscompatTypedArrayReverseImpl(thisArray);                         \
565     }  // namespace ark::ets::intrinsics
566 
567 REVERSE_CALL_DECL(Int8)
REVERSE_CALL_DECL(Int16)568 REVERSE_CALL_DECL(Int16)
569 REVERSE_CALL_DECL(Int32)
570 REVERSE_CALL_DECL(BigInt64)
571 REVERSE_CALL_DECL(Float32)
572 REVERSE_CALL_DECL(Float64)
573 
574 REVERSE_CALL_DECL(UInt8)
575 REVERSE_CALL_DECL(UInt8Clamped)
576 REVERSE_CALL_DECL(UInt16)
577 REVERSE_CALL_DECL(UInt32)
578 REVERSE_CALL_DECL(BigUInt64)
579 
580 #undef REVERSE_CALL_DECL
581 
582 /*
583  * Typed Arrays: ToReversed Implementation
584  */
585 template <typename T>
586 static T *EtsEscompatTypedArrayToReversedImpl(T *thisArray)
587 {
588     EtsCoroutine *coro = EtsCoroutine::GetCurrent();
589     [[maybe_unused]] EtsHandleScope scope(coro);
590 
591     size_t elementSize = static_cast<size_t>(thisArray->GetBytesPerElement()) * sizeof(EtsByte);
592     EtsInt arrayLength = thisArray->GetLengthInt();
593     size_t byteLength = static_cast<size_t>(arrayLength) * elementSize;
594 
595     // Clone src array to dest array. Alloc new buffer. Assign new buffer to dest array.
596     EtsHandle<EtsObject> srcArray(coro, thisArray);
597     ASSERT(srcArray.GetPtr() != nullptr);
598 
599     auto *srcData = GetNativeData(static_cast<T *>(srcArray.GetPtr()));
600     void *dstData = nullptr;
601     EtsHandle<EtsEscompatArrayBuffer> newBuffer(coro, EtsEscompatArrayBuffer::Create(coro, byteLength, &dstData));
602     auto dstArray = static_cast<T *>(srcArray->Clone());
603 
604     ASSERT(newBuffer.GetPtr() != nullptr);
605     ASSERT(dstArray != nullptr);
606     dstArray->SetBuffer(newBuffer.GetPtr());
607 
608     // Copy data from src array to dst array in reversed order.
609     ASSERT(srcData != nullptr);
610     ASSERT(dstData != nullptr);
611 
612     using ElementType = typename T::ElementType;
613     auto *src = static_cast<ElementType *>(srcData);
614     auto *dst = static_cast<ElementType *>(dstData);
615     ASSERT(src != nullptr);
616     ASSERT(dst != nullptr);
617 
618     for (int i = 0; i < arrayLength; i++) {
619         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic, clang-analyzer-core.NullDereference)
620         dst[i] = src[(arrayLength - 1) - i];
621     }
622     return dstArray;
623 }
624 
625 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
626 #define TO_REVERSED_CALL_DECL(Type)                                                    \
627     /* CC-OFFNXT(G.PRE.02) name part */                                                \
628     extern "C" ark::ets::EtsEscompat##Type##Array *EtsEscompat##Type##ArrayToReversed( \
629         ark::ets::EtsEscompat##Type##Array *thisArray)                                 \
630     {                                                                                  \
631         /* CC-OFFNXT(G.PRE.05) function gen */                                         \
632         return EtsEscompatTypedArrayToReversedImpl(thisArray);                         \
633     }
634 
635 TO_REVERSED_CALL_DECL(Int8)
TO_REVERSED_CALL_DECL(Int16)636 TO_REVERSED_CALL_DECL(Int16)
637 TO_REVERSED_CALL_DECL(Int32)
638 TO_REVERSED_CALL_DECL(BigInt64)
639 TO_REVERSED_CALL_DECL(Float32)
640 TO_REVERSED_CALL_DECL(Float64)
641 
642 TO_REVERSED_CALL_DECL(UInt8)
643 TO_REVERSED_CALL_DECL(UInt8Clamped)
644 TO_REVERSED_CALL_DECL(UInt16)
645 TO_REVERSED_CALL_DECL(UInt32)
646 TO_REVERSED_CALL_DECL(BigUInt64)
647 
648 #undef TO_REVERSED_CALL_DECL
649 
650 int32_t NormalizeIndex(int32_t idx, int32_t arrayLength)
651 {
652     if (idx < -arrayLength) {
653         return 0;
654     }
655     if (idx < 0) {
656         return arrayLength + idx;
657     }
658     if (idx > arrayLength) {
659         return arrayLength;
660     }
661     return idx;
662 }
663 
664 template <typename T>
EtsEscompatTypedArrayCopyWithinImpl(T * thisArray,EtsInt target,EtsInt start,EtsInt end)665 T *EtsEscompatTypedArrayCopyWithinImpl(T *thisArray, EtsInt target, EtsInt start, EtsInt end)
666 {
667     auto *data = GetNativeData(thisArray);
668     if (UNLIKELY(data == nullptr)) {
669         return nullptr;
670     }
671 
672     auto arrayLength = thisArray->GetLengthInt();
673     target = NormalizeIndex(target, arrayLength);
674     start = NormalizeIndex(start, arrayLength);
675     end = NormalizeIndex(end, arrayLength);
676 
677     int32_t count = end - start;
678     if (count > (arrayLength - target)) {
679         count = arrayLength - target;
680     }
681     if (count <= 0) {
682         return thisArray;
683     }
684 
685     using ElementType = typename T::ElementType;
686     auto *targetAddress = ToVoidPtr(ToUintPtr(data) + thisArray->GetByteOffset() + target * sizeof(ElementType));
687     auto *startAddress = ToVoidPtr(ToUintPtr(data) + thisArray->GetByteOffset() + start * sizeof(ElementType));
688     [[maybe_unused]] auto error = memmove_s(targetAddress, (arrayLength - start) * sizeof(ElementType), startAddress,
689                                             count * sizeof(ElementType));
690     ASSERT(error == EOK);
691     return thisArray;
692 }
693 
694 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
695 #define ETS_ESCOMPAT_COPY_WITHIN(Type)                                                          \
696     /* CC-OFFNXT(G.PRE.02) name part */                                                         \
697     extern "C" ark::ets::EtsEscompat##Type##Array *EtsEscompat##Type##ArrayCopyWithin(          \
698         ark::ets::EtsEscompat##Type##Array *thisArray, EtsInt target, EtsInt start, EtsInt end) \
699     {                                                                                           \
700         /* CC-OFFNXT(G.PRE.05) function gen */                                                  \
701         return EtsEscompatTypedArrayCopyWithinImpl(thisArray, target, start, end);              \
702     }  // namespace ark::ets::intrinsics
703 
704 ETS_ESCOMPAT_COPY_WITHIN(Int8)
ETS_ESCOMPAT_COPY_WITHIN(Int16)705 ETS_ESCOMPAT_COPY_WITHIN(Int16)
706 ETS_ESCOMPAT_COPY_WITHIN(Int32)
707 ETS_ESCOMPAT_COPY_WITHIN(BigInt64)
708 ETS_ESCOMPAT_COPY_WITHIN(Float32)
709 ETS_ESCOMPAT_COPY_WITHIN(Float64)
710 ETS_ESCOMPAT_COPY_WITHIN(UInt8)
711 ETS_ESCOMPAT_COPY_WITHIN(UInt16)
712 ETS_ESCOMPAT_COPY_WITHIN(UInt32)
713 ETS_ESCOMPAT_COPY_WITHIN(BigUInt64)
714 ETS_ESCOMPAT_COPY_WITHIN(UInt8Clamped)
715 
716 #undef ETS_ESCOMPAT_COPY_WITHIN
717 
718 template <typename T>
719 T *EtsEscompatTypedArraySort(T *thisArray)
720 {
721     using ElementType = typename T::ElementType;
722 
723     auto nBytes = static_cast<size_t>(thisArray->GetByteLength());
724     ASSERT(nBytes == (static_cast<size_t>(thisArray->GetLengthInt()) * sizeof(ElementType)));
725     // If it's an empty or one-element array then nothing to sort.
726     if (UNLIKELY(nBytes <= sizeof(ElementType))) {
727         return thisArray;
728     }
729 
730     auto *arrayBuffer = static_cast<EtsEscompatArrayBuffer *>(&*thisArray->GetBuffer());
731     if (UNLIKELY(arrayBuffer->WasDetached())) {
732         auto coro = EtsCoroutine::GetCurrent();
733         [[maybe_unused]] EtsHandleScope scope(coro);
734         EtsHandle<EtsObject> handle(coro, thisArray);
735         ThrowEtsException(coro, panda_file_items::class_descriptors::TYPE_ERROR, "ArrayBuffer was detached");
736         return static_cast<T *>(handle.GetPtr());
737     }
738     void *dataPtr = arrayBuffer->GetData();
739     ASSERT(dataPtr != nullptr);
740 
741     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
742     Span<EtsByte> data(static_cast<EtsByte *>(dataPtr) + static_cast<size_t>(thisArray->GetByteOffset()), nBytes);
743     std::sort(reinterpret_cast<typename T::ElementType *>(data.begin()),
744               reinterpret_cast<typename T::ElementType *>(data.end()));
745     return thisArray;
746 }
747 
EtsEscompatInt8ArraySort(ark::ets::EtsEscompatInt8Array * thisArray)748 extern "C" ark::ets::EtsEscompatInt8Array *EtsEscompatInt8ArraySort(ark::ets::EtsEscompatInt8Array *thisArray)
749 {
750     return EtsEscompatTypedArraySort(thisArray);
751 }
752 
EtsEscompatInt16ArraySort(ark::ets::EtsEscompatInt16Array * thisArray)753 extern "C" ark::ets::EtsEscompatInt16Array *EtsEscompatInt16ArraySort(ark::ets::EtsEscompatInt16Array *thisArray)
754 {
755     return EtsEscompatTypedArraySort(thisArray);
756 }
757 
EtsEscompatInt32ArraySort(ark::ets::EtsEscompatInt32Array * thisArray)758 extern "C" ark::ets::EtsEscompatInt32Array *EtsEscompatInt32ArraySort(ark::ets::EtsEscompatInt32Array *thisArray)
759 {
760     return EtsEscompatTypedArraySort(thisArray);
761 }
762 
EtsEscompatBigInt64ArraySort(ark::ets::EtsEscompatBigInt64Array * thisArray)763 extern "C" ark::ets::EtsEscompatBigInt64Array *EtsEscompatBigInt64ArraySort(
764     ark::ets::EtsEscompatBigInt64Array *thisArray)
765 {
766     return EtsEscompatTypedArraySort(thisArray);
767 }
768 
EtsEscompatFloat32ArraySort(ark::ets::EtsEscompatFloat32Array * thisArray)769 extern "C" ark::ets::EtsEscompatFloat32Array *EtsEscompatFloat32ArraySort(ark::ets::EtsEscompatFloat32Array *thisArray)
770 {
771     return EtsEscompatTypedArraySort(thisArray);
772 }
773 
EtsEscompatFloat64ArraySort(ark::ets::EtsEscompatFloat64Array * thisArray)774 extern "C" ark::ets::EtsEscompatFloat64Array *EtsEscompatFloat64ArraySort(ark::ets::EtsEscompatFloat64Array *thisArray)
775 {
776     return EtsEscompatTypedArraySort(thisArray);
777 }
778 
EtsEscompatUInt8ClampedArraySort(ark::ets::EtsEscompatUInt8ClampedArray * thisArray)779 extern "C" ark::ets::EtsEscompatUInt8ClampedArray *EtsEscompatUInt8ClampedArraySort(
780     ark::ets::EtsEscompatUInt8ClampedArray *thisArray)
781 {
782     return EtsEscompatTypedArraySort(thisArray);
783 }
784 
EtsEscompatUInt8ArraySort(ark::ets::EtsEscompatUInt8Array * thisArray)785 extern "C" ark::ets::EtsEscompatUInt8Array *EtsEscompatUInt8ArraySort(ark::ets::EtsEscompatUInt8Array *thisArray)
786 {
787     return EtsEscompatTypedArraySort(thisArray);
788 }
789 
EtsEscompatUInt16ArraySort(ark::ets::EtsEscompatUInt16Array * thisArray)790 extern "C" ark::ets::EtsEscompatUInt16Array *EtsEscompatUInt16ArraySort(ark::ets::EtsEscompatUInt16Array *thisArray)
791 {
792     return EtsEscompatTypedArraySort(thisArray);
793 }
794 
EtsEscompatUInt32ArraySort(ark::ets::EtsEscompatUInt32Array * thisArray)795 extern "C" ark::ets::EtsEscompatUInt32Array *EtsEscompatUInt32ArraySort(ark::ets::EtsEscompatUInt32Array *thisArray)
796 {
797     return EtsEscompatTypedArraySort(thisArray);
798 }
799 
EtsEscompatBigUInt64ArraySort(ark::ets::EtsEscompatBigUInt64Array * thisArray)800 extern "C" ark::ets::EtsEscompatBigUInt64Array *EtsEscompatBigUInt64ArraySort(
801     ark::ets::EtsEscompatBigUInt64Array *thisArray)
802 {
803     return EtsEscompatTypedArraySort(thisArray);
804 }
805 
806 #define INVALID_INDEX (-1.0)
807 
808 template <typename T1, typename T2>
EtsEscompatArrayIndexOfLong(T1 * thisArray,T2 searchElement,EtsInt fromIndex)809 static EtsDouble EtsEscompatArrayIndexOfLong(T1 *thisArray, T2 searchElement, EtsInt fromIndex)
810 {
811     auto *data = GetNativeData(thisArray);
812     if (UNLIKELY(data == nullptr)) {
813         return INVALID_INDEX;
814     }
815 
816     using ElementType = typename T1::ElementType;
817     auto *array = reinterpret_cast<ElementType *>(ToUintPtr(data) + static_cast<int>(thisArray->GetByteOffset()));
818     auto arrayLength = thisArray->GetLengthInt();
819     fromIndex = NormalizeIndex(fromIndex, arrayLength);
820     auto element = static_cast<ElementType>(searchElement);
821     for (int i = fromIndex; i < arrayLength; i++) {
822         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
823         if (array[i] == element) {
824             return static_cast<double>(i);
825         }
826     }
827     return INVALID_INDEX;
828 }
829 
830 template <typename T>
EtsEscompatArrayIndexOfNumber(T * thisArray,double searchElement,EtsInt fromIndex)831 static EtsDouble EtsEscompatArrayIndexOfNumber(T *thisArray, double searchElement, EtsInt fromIndex)
832 {
833     if (std::isnan(searchElement)) {
834         return INVALID_INDEX;
835     }
836 
837     auto *data = GetNativeData(thisArray);
838     if (UNLIKELY(data == nullptr)) {
839         return INVALID_INDEX;
840     }
841 
842     using ElementType = typename T::ElementType;
843     auto *array = reinterpret_cast<ElementType *>(ToUintPtr(data) + static_cast<int>(thisArray->GetByteOffset()));
844     auto arrayLength = thisArray->GetLengthInt();
845     fromIndex = NormalizeIndex(fromIndex, arrayLength);
846     for (int i = fromIndex; i < arrayLength; i++) {
847         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
848         if (static_cast<double>(array[i]) == searchElement) {
849             return static_cast<double>(i);
850         }
851     }
852     return INVALID_INDEX;
853 }
854 
855 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
856 #define ETS_ESCOMPAT_INDEX_OF_NUMBER(Type)                                                                    \
857     /* CC-OFFNXT(G.PRE.02) name part */                                                                       \
858     extern "C" EtsDouble EtsEscompat##Type##ArrayIndexOfNumber(ark::ets::EtsEscompat##Type##Array *thisArray, \
859                                                                EtsDouble searchElement, EtsInt fromIndex)     \
860     {                                                                                                         \
861         /* CC-OFFNXT(G.PRE.05) function gen */                                                                \
862         return EtsEscompatArrayIndexOfNumber(thisArray, searchElement, fromIndex);                            \
863     }  // namespace ark::ets::intrinsics
864 
865 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
866 #define ETS_ESCOMPAT_INDEX_OF_LONG(Type)                                                                    \
867     /* CC-OFFNXT(G.PRE.02) name part */                                                                     \
868     extern "C" EtsDouble EtsEscompat##Type##ArrayIndexOfLong(ark::ets::EtsEscompat##Type##Array *thisArray, \
869                                                              EtsLong searchElement, EtsInt fromIndex)       \
870     {                                                                                                       \
871         /* CC-OFFNXT(G.PRE.05) function gen */                                                              \
872         return EtsEscompatArrayIndexOfLong(thisArray, searchElement, fromIndex);                            \
873     }  // namespace ark::ets::intrinsics
874 
875 ETS_ESCOMPAT_INDEX_OF_NUMBER(Int8)
ETS_ESCOMPAT_INDEX_OF_NUMBER(Int16)876 ETS_ESCOMPAT_INDEX_OF_NUMBER(Int16)
877 ETS_ESCOMPAT_INDEX_OF_NUMBER(Int32)
878 ETS_ESCOMPAT_INDEX_OF_NUMBER(BigInt64)
879 ETS_ESCOMPAT_INDEX_OF_NUMBER(Float32)
880 ETS_ESCOMPAT_INDEX_OF_NUMBER(Float64)
881 ETS_ESCOMPAT_INDEX_OF_NUMBER(UInt8)
882 ETS_ESCOMPAT_INDEX_OF_NUMBER(UInt16)
883 ETS_ESCOMPAT_INDEX_OF_NUMBER(UInt32)
884 ETS_ESCOMPAT_INDEX_OF_NUMBER(BigUInt64)
885 ETS_ESCOMPAT_INDEX_OF_NUMBER(UInt8Clamped)
886 ETS_ESCOMPAT_INDEX_OF_LONG(Int8)
887 ETS_ESCOMPAT_INDEX_OF_LONG(Int16)
888 ETS_ESCOMPAT_INDEX_OF_LONG(Int32)
889 ETS_ESCOMPAT_INDEX_OF_LONG(BigInt64)
890 ETS_ESCOMPAT_INDEX_OF_LONG(Float32)
891 ETS_ESCOMPAT_INDEX_OF_LONG(Float64)
892 ETS_ESCOMPAT_INDEX_OF_LONG(UInt8)
893 ETS_ESCOMPAT_INDEX_OF_LONG(UInt16)
894 ETS_ESCOMPAT_INDEX_OF_LONG(UInt32)
895 ETS_ESCOMPAT_INDEX_OF_LONG(BigUInt64)
896 ETS_ESCOMPAT_INDEX_OF_LONG(UInt8Clamped)
897 
898 template <typename T1, typename T2>
899 static EtsDouble EtsEscompatArrayLastIndexOfLong(T1 *thisArray, T2 searchElement, EtsInt fromIndex)
900 {
901     auto *data = GetNativeData(thisArray);
902     if (UNLIKELY(data == nullptr)) {
903         return INVALID_INDEX;
904     }
905 
906     int arrayLength = thisArray->GetLengthInt();
907     if (arrayLength == 0) {
908         return INVALID_INDEX;
909     }
910 
911     int startIndex = arrayLength + fromIndex;
912     if (fromIndex >= 0) {
913         startIndex = (arrayLength - 1 < fromIndex) ? arrayLength - 1 : fromIndex;
914     }
915 
916     using ElementType = typename T1::ElementType;
917     auto *array = reinterpret_cast<ElementType *>(ToUintPtr(data) + static_cast<int>(thisArray->GetByteOffset()));
918     auto element = static_cast<ElementType>(searchElement);
919     for (int i = startIndex; i >= 0; i--) {
920         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
921         if (array[i] == element) {
922             return static_cast<double>(i);
923         }
924     }
925 
926     return INVALID_INDEX;
927 }
928 
929 template <typename T>
EtsEscompatArrayLastIndexOfNumber(T * thisArray,double searchElement,EtsInt fromIndex)930 static EtsDouble EtsEscompatArrayLastIndexOfNumber(T *thisArray, double searchElement, EtsInt fromIndex)
931 {
932     if (std::isnan(searchElement)) {
933         return INVALID_INDEX;
934     }
935 
936     auto *data = GetNativeData(thisArray);
937     if (UNLIKELY(data == nullptr)) {
938         return INVALID_INDEX;
939     }
940 
941     int arrayLength = thisArray->GetLengthInt();
942     if (arrayLength == 0) {
943         return INVALID_INDEX;
944     }
945 
946     int startIndex = arrayLength + fromIndex;
947     if (fromIndex >= 0) {
948         startIndex = (arrayLength - 1 < fromIndex) ? arrayLength - 1 : fromIndex;
949     }
950 
951     using ElementType = typename T::ElementType;
952     auto *array = reinterpret_cast<ElementType *>(ToUintPtr(data) + static_cast<int>(thisArray->GetByteOffset()));
953     for (int i = startIndex; i >= 0; i--) {
954         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
955         if (static_cast<double>(array[i]) == searchElement) {
956             return static_cast<double>(i);
957         }
958     }
959 
960     return INVALID_INDEX;
961 }
962 
963 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
964 #define ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Type)                                                                   \
965     /* CC-OFFNXT(G.PRE.02) name part */                                                                           \
966     extern "C" EtsDouble EtsEscompat##Type##ArrayLastIndexOfNumber(ark::ets::EtsEscompat##Type##Array *thisArray, \
967                                                                    EtsDouble searchElement, EtsInt fromIndex)     \
968     {                                                                                                             \
969         /* CC-OFFNXT(G.PRE.05) function gen */                                                                    \
970         return EtsEscompatArrayLastIndexOfNumber(thisArray, searchElement, fromIndex);                            \
971     }  // namespace ark::ets::intrinsics
972 
973 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
974 #define ETS_ESCOMPAT_LAST_INDEX_OF_LONG(Type)                                                                   \
975     /* CC-OFFNXT(G.PRE.02) name part */                                                                         \
976     extern "C" EtsDouble EtsEscompat##Type##ArrayLastIndexOfLong(ark::ets::EtsEscompat##Type##Array *thisArray, \
977                                                                  EtsLong searchElement, EtsInt fromIndex)       \
978     {                                                                                                           \
979         /* CC-OFFNXT(G.PRE.05) function gen */                                                                  \
980         return EtsEscompatArrayLastIndexOfLong(thisArray, searchElement, fromIndex);                            \
981     }  // namespace ark::ets::intrinsics
982 
983 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Int8)
ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Int16)984 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Int16)
985 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Int32)
986 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(BigInt64)
987 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Float32)
988 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(Float64)
989 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(UInt8)
990 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(UInt16)
991 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(UInt32)
992 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(BigUInt64)
993 ETS_ESCOMPAT_LAST_INDEX_OF_NUMBER(UInt8Clamped)
994 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(Int8)
995 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(Int16)
996 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(Int32)
997 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(BigInt64)
998 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(Float32)
999 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(Float64)
1000 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(UInt8)
1001 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(UInt16)
1002 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(UInt32)
1003 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(BigUInt64)
1004 ETS_ESCOMPAT_LAST_INDEX_OF_LONG(UInt8Clamped)
1005 
1006 #undef INVALID_INDEX
1007 
1008 /* Compute a max size in chars required for not null-terminated string
1009  * representation of the specified integral or floating point type.
1010  */
1011 template <typename T>
1012 constexpr size_t MaxChars()
1013 {
1014     static_assert(std::numeric_limits<T>::radix == 2U);
1015     if constexpr (std::is_integral_v<T>) {
1016         auto bits = std::numeric_limits<T>::digits;
1017         auto digitPerBit = std::log10(std::numeric_limits<T>::radix);
1018         auto digits = std::ceil(bits * digitPerBit) + static_cast<int>(std::is_signed_v<T>);
1019         return digits;
1020     } else {
1021         static_assert(std::is_floating_point_v<T>);
1022         // Forced to treat T as double
1023         auto bits = std::numeric_limits<double>::digits;
1024         auto digitPerBit = std::log10(std::numeric_limits<double>::radix);
1025         auto digits = std::ceil(bits * digitPerBit) + static_cast<int>(std::is_signed_v<double>);
1026         // digits + point + "+e308"
1027         return digits + 1U + std::char_traits<char>::length("+e308");
1028     }
1029 }
1030 
1031 template <typename T>
NumberToU8Chars(PandaVector<char> & buf,size_t pos,T number)1032 size_t NumberToU8Chars(PandaVector<char> &buf, size_t pos, T number)
1033 {
1034     if constexpr (std::is_integral_v<T>) {
1035         auto [strEnd, result] = std::to_chars(&buf[pos], &buf[pos + MaxChars<T>()], number);
1036         ASSERT(result == std::errc());
1037         return strEnd - &buf[pos];
1038     } else {
1039         static_assert(std::is_floating_point_v<T>);
1040         // Forced to treat T as double
1041         auto asDouble = static_cast<double>(number);
1042         return intrinsics::helpers::FpToStringDecimalRadix(asDouble, [&buf, &pos](std::string_view str) {
1043             ASSERT(str.length() <= MaxChars<T>());
1044             auto err = memcpy_s(&buf[pos], MaxChars<T>(), str.data(), str.length());
1045             if (err != EOK) {
1046                 UNREACHABLE();
1047             }
1048             return str.length();
1049         });
1050     }
1051 }
1052 
1053 template <typename T>
NumberToU16Chars(PandaVector<EtsChar> & buf,size_t pos,T number)1054 size_t NumberToU16Chars(PandaVector<EtsChar> &buf, size_t pos, T number)
1055 {
1056     if constexpr (std::is_integral_v<T>) {
1057         auto num = number < 0 ? -static_cast<uint64_t>(number) : static_cast<uint64_t>(number);
1058         auto nDigits = (CountDigits(num) + static_cast<uint32_t>(number < 0));
1059         ASSERT(pos + nDigits <= buf.size());
1060         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1061         utf::UInt64ToUtf16Array(num, buf.data() + pos, nDigits, number < 0);
1062         return nDigits;
1063     } else {
1064         static_assert(std::is_floating_point_v<T>);
1065         static_assert(std::is_unsigned_v<EtsChar>);
1066         // Forced to treat T as double
1067         auto asDouble = static_cast<double>(number);
1068         return intrinsics::helpers::FpToStringDecimalRadix(asDouble, [&buf, &pos](std::string_view str) {
1069             ASSERT(str.length() <= MaxChars<T>());
1070             for (size_t i = 0; i < str.length(); i++) {
1071                 buf[pos + i] = static_cast<EtsChar>(str[i]);
1072             }
1073             return str.length();
1074         });
1075     }
1076 }
1077 
1078 template <typename T>
TypedArrayJoinUtf16(Span<T> & data,ark::ets::EtsString * separator)1079 static ark::ets::EtsString *TypedArrayJoinUtf16(Span<T> &data, ark::ets::EtsString *separator)
1080 {
1081     ASSERT(!data.empty());
1082     ASSERT(separator->IsUtf16());
1083 
1084     const size_t sepSize = separator->GetUtf16Length();
1085     PandaVector<EtsChar> buf(data.Size() * (MaxChars<T>() + sepSize));
1086     size_t strSize = 0;
1087     auto n = data.Size() - 1;
1088     if (sepSize == 1) {
1089         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1090         auto sep = separator->GetDataUtf16()[0];
1091         for (auto i = 0U; i < n; i++) {
1092             strSize += NumberToU16Chars(buf, strSize, static_cast<T>(data[i]));
1093             buf[strSize] = sep;
1094             strSize += 1;
1095         }
1096     } else {
1097         for (auto i = 0U; i < n; i++) {
1098             strSize += NumberToU16Chars(buf, strSize, static_cast<T>(data[i]));
1099             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1100             separator->CopyDataUtf16(buf.data() + strSize, sepSize);
1101             strSize += sepSize;
1102         }
1103     }
1104     strSize += NumberToU16Chars(buf, strSize, static_cast<T>(data[n]));
1105     return EtsString::CreateFromUtf16(reinterpret_cast<EtsChar *>(buf.data()), strSize);
1106 }
1107 
1108 template <typename T>
TypedArrayJoinUtf8(Span<T> & data)1109 static ark::ets::EtsString *TypedArrayJoinUtf8(Span<T> &data)
1110 {
1111     ASSERT(!data.empty());
1112     PandaVector<char> buf(data.Size() * MaxChars<T>());
1113     size_t strSize = 0;
1114     auto n = data.Size();
1115     for (auto i = 0U; i < n; i++) {
1116         strSize += NumberToU8Chars(buf, strSize, data[i]);
1117     }
1118     return EtsString::CreateFromUtf8(buf.data(), strSize);
1119 }
1120 
1121 template <typename T>
TypedArrayJoinUtf8(Span<T> & data,ark::ets::EtsString * separator)1122 static ark::ets::EtsString *TypedArrayJoinUtf8(Span<T> &data, ark::ets::EtsString *separator)
1123 {
1124     ASSERT(!data.empty());
1125     ASSERT(!separator->IsUtf16() && !separator->IsEmpty());
1126     const size_t sepSize = separator->GetUtf8Length();
1127     PandaVector<char> buf(data.Size() * (MaxChars<T>() + sepSize));
1128     size_t strSize = 0;
1129     auto n = data.Size() - 1;
1130     if (sepSize == 1) {
1131         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1132         auto sep = separator->GetDataUtf8()[0];
1133         for (auto i = 0U; i < n; i++) {
1134             strSize += NumberToU8Chars(buf, strSize, data[i]);
1135             buf[strSize] = sep;
1136             strSize += 1;
1137         }
1138     } else {
1139         for (auto i = 0U; i < n; i++) {
1140             strSize += NumberToU8Chars(buf, strSize, data[i]);
1141             separator->CopyDataMUtf8(&buf[strSize], sepSize, false);
1142             strSize += sepSize;
1143         }
1144     }
1145     strSize += NumberToU8Chars(buf, strSize, data[n]);
1146     return EtsString::CreateFromUtf8(buf.data(), strSize);
1147 }
1148 
1149 template <typename T>
TypedArrayJoin(T * thisArray,ark::ets::EtsString * separator)1150 static ark::ets::EtsString *TypedArrayJoin(T *thisArray, ark::ets::EtsString *separator)
1151 {
1152     using ElementType = typename T::ElementType;
1153 
1154     auto length = thisArray->GetLengthInt();
1155     if (UNLIKELY(length <= 0)) {
1156         return EtsString::CreateNewEmptyString();
1157     }
1158 
1159     void *dataPtr = GetNativeData(thisArray);
1160     if (UNLIKELY(dataPtr == nullptr)) {
1161         return nullptr;
1162     }
1163 
1164     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1165     auto *tyDataPtr = reinterpret_cast<ElementType *>(static_cast<EtsByte *>(dataPtr) +
1166                                                       static_cast<size_t>(thisArray->GetByteOffset()));
1167     Span<ElementType> data(tyDataPtr, length);
1168     if (separator->IsEmpty()) {
1169         return TypedArrayJoinUtf8(data);
1170     }
1171     if (!separator->IsUtf16()) {
1172         return TypedArrayJoinUtf8(data, separator);
1173     }
1174     return TypedArrayJoinUtf16(data, separator);
1175 }
1176 
EtsEscompatInt8ArrayJoin(ark::ets::EtsEscompatInt8Array * thisArray,ark::ets::EtsString * separator)1177 extern "C" ark::ets::EtsString *EtsEscompatInt8ArrayJoin(ark::ets::EtsEscompatInt8Array *thisArray,
1178                                                          ark::ets::EtsString *separator)
1179 {
1180     return TypedArrayJoin(thisArray, separator);
1181 }
1182 
EtsEscompatUint8ArrayJoin(ark::ets::EtsEscompatUInt8Array * thisArray,ark::ets::EtsString * separator)1183 extern "C" ark::ets::EtsString *EtsEscompatUint8ArrayJoin(ark::ets::EtsEscompatUInt8Array *thisArray,
1184                                                           ark::ets::EtsString *separator)
1185 {
1186     return TypedArrayJoin(thisArray, separator);
1187 }
1188 
EtsEscompatUint8ClampedArrayJoin(ark::ets::EtsEscompatUInt8ClampedArray * thisArray,ark::ets::EtsString * separator)1189 extern "C" ark::ets::EtsString *EtsEscompatUint8ClampedArrayJoin(ark::ets::EtsEscompatUInt8ClampedArray *thisArray,
1190                                                                  ark::ets::EtsString *separator)
1191 {
1192     return TypedArrayJoin(thisArray, separator);
1193 }
1194 
EtsEscompatInt16ArrayJoin(ark::ets::EtsEscompatInt16Array * thisArray,ark::ets::EtsString * separator)1195 extern "C" ark::ets::EtsString *EtsEscompatInt16ArrayJoin(ark::ets::EtsEscompatInt16Array *thisArray,
1196                                                           ark::ets::EtsString *separator)
1197 {
1198     return TypedArrayJoin(thisArray, separator);
1199 }
1200 
EtsEscompatUint16ArrayJoin(ark::ets::EtsEscompatUInt16Array * thisArray,ark::ets::EtsString * separator)1201 extern "C" ark::ets::EtsString *EtsEscompatUint16ArrayJoin(ark::ets::EtsEscompatUInt16Array *thisArray,
1202                                                            ark::ets::EtsString *separator)
1203 {
1204     return TypedArrayJoin(thisArray, separator);
1205 }
1206 
EtsEscompatInt32ArrayJoin(ark::ets::EtsEscompatInt32Array * thisArray,ark::ets::EtsString * separator)1207 extern "C" ark::ets::EtsString *EtsEscompatInt32ArrayJoin(ark::ets::EtsEscompatInt32Array *thisArray,
1208                                                           ark::ets::EtsString *separator)
1209 {
1210     return TypedArrayJoin(thisArray, separator);
1211 }
1212 
EtsEscompatUint32ArrayJoin(ark::ets::EtsEscompatUInt32Array * thisArray,ark::ets::EtsString * separator)1213 extern "C" ark::ets::EtsString *EtsEscompatUint32ArrayJoin(ark::ets::EtsEscompatUInt32Array *thisArray,
1214                                                            ark::ets::EtsString *separator)
1215 {
1216     return TypedArrayJoin(thisArray, separator);
1217 }
1218 
EtsEscompatBigInt64ArrayJoin(ark::ets::EtsEscompatBigInt64Array * thisArray,ark::ets::EtsString * separator)1219 extern "C" ark::ets::EtsString *EtsEscompatBigInt64ArrayJoin(ark::ets::EtsEscompatBigInt64Array *thisArray,
1220                                                              ark::ets::EtsString *separator)
1221 {
1222     return TypedArrayJoin(thisArray, separator);
1223 }
1224 
EtsEscompatBigUint64ArrayJoin(ark::ets::EtsEscompatBigUInt64Array * thisArray,ark::ets::EtsString * separator)1225 extern "C" ark::ets::EtsString *EtsEscompatBigUint64ArrayJoin(ark::ets::EtsEscompatBigUInt64Array *thisArray,
1226                                                               ark::ets::EtsString *separator)
1227 {
1228     return TypedArrayJoin(thisArray, separator);
1229 }
1230 
EtsEscompatFloat32ArrayJoin(ark::ets::EtsEscompatFloat32Array * thisArray,ark::ets::EtsString * separator)1231 extern "C" ark::ets::EtsString *EtsEscompatFloat32ArrayJoin(ark::ets::EtsEscompatFloat32Array *thisArray,
1232                                                             ark::ets::EtsString *separator)
1233 {
1234     return TypedArrayJoin(thisArray, separator);
1235 }
1236 
EtsEscompatFloat64ArrayJoin(ark::ets::EtsEscompatFloat64Array * thisArray,ark::ets::EtsString * separator)1237 extern "C" ark::ets::EtsString *EtsEscompatFloat64ArrayJoin(ark::ets::EtsEscompatFloat64Array *thisArray,
1238                                                             ark::ets::EtsString *separator)
1239 {
1240     return TypedArrayJoin(thisArray, separator);
1241 }
1242 
1243 }  // namespace ark::ets::intrinsics
1244