1 /*
2 * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @run testng TestArrayCopy
27 */
28
29 import java.lang.foreign.MemorySegment;
30 import java.lang.foreign.ValueLayout;
31 import java.lang.invoke.MethodHandles;
32 import java.lang.invoke.VarHandle;
33 import java.nio.ByteOrder;
34 import java.util.ArrayList;
35 import java.util.List;
36 import org.testng.annotations.DataProvider;
37 import org.testng.annotations.Test;
38
39 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
40 import static java.lang.foreign.ValueLayout.JAVA_INT;
41 import static org.testng.Assert.assertEquals;
42 import static org.testng.Assert.fail;
43
44 /**
45 * These tests exercise the MemoryCopy copyFromArray(...) and copyToArray(...).
46 * To make these tests more challenging the segment is a view of the given array,
47 * which makes the copy operations overlapping self-copies. Thus, this checks the claim:
48 *
49 * <p>If the source (destination) segment is actually a view of the destination (source) array,
50 * and if the copy region of the source overlaps with the copy region of the destination,
51 * the copy of the overlapping region is performed as if the data in the overlapping region
52 * were first copied into a temporary segment before being copied to the destination.</p>
53 */
54 public class TestArrayCopy {
55 private static final ByteOrder NATIVE_ORDER = ByteOrder.nativeOrder();
56 private static final ByteOrder NON_NATIVE_ORDER = NATIVE_ORDER == ByteOrder.LITTLE_ENDIAN
57 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
58
59 private static final int SEG_LENGTH_BYTES = 32;
60 private static final int SEG_OFFSET_BYTES = 8;
61
62 @Test(dataProvider = "copyModesAndHelpers")
63 public void testSelfCopy(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
64 int bytesPerElement = (int)helper.elementLayout.byteSize();
65 int indexShifts = SEG_OFFSET_BYTES / bytesPerElement;
66 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
67 MemorySegment truth = truthSegment(base, helper, indexShifts, mode);
68 ByteOrder bo = mode.swap ? NON_NATIVE_ORDER : NATIVE_ORDER;
69 //CopyFrom
70 Object srcArr = helper.toArray(base);
71 int srcIndex = mode.direction ? 0 : indexShifts;
72 int srcCopyLen = helper.length(srcArr) - indexShifts;
73 MemorySegment dstSeg = helper.fromArray(srcArr);
74 long dstOffsetBytes = mode.direction ? SEG_OFFSET_BYTES : 0;
75 helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo);
76 assertEquals(truth.mismatch(dstSeg), -1);
77 //CopyTo
78 long srcOffsetBytes = mode.direction ? 0 : SEG_OFFSET_BYTES;
79 Object dstArr = helper.toArray(base);
80 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
81 int dstIndex = mode.direction ? indexShifts : 0;
82 int dstCopyLen = helper.length(dstArr) - indexShifts;
83 helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo);
84 MemorySegment result = helper.fromArray(dstArr);
85 assertEquals(truth.mismatch(result), -1);
86 }
87
88 @Test(dataProvider = "copyModesAndHelpers")
89 public void testUnalignedCopy(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
90 int bytesPerElement = (int)helper.elementLayout.byteSize();
91 int indexShifts = SEG_OFFSET_BYTES / bytesPerElement;
92 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
93 ByteOrder bo = mode.swap ? NON_NATIVE_ORDER : NATIVE_ORDER;
94 //CopyFrom
95 Object srcArr = helper.toArray(base);
96 int srcIndex = mode.direction ? 0 : indexShifts;
97 int srcCopyLen = helper.length(srcArr) - indexShifts;
98 MemorySegment dstSeg = helper.fromArray(srcArr);
99 long dstOffsetBytes = mode.direction ? (SEG_OFFSET_BYTES - 1) : 0;
100 helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo);
101 //CopyTo
102 long srcOffsetBytes = mode.direction ? 0 : (SEG_OFFSET_BYTES - 1);
103 Object dstArr = helper.toArray(base);
104 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
105 int dstIndex = mode.direction ? indexShifts : 0;
106 int dstCopyLen = helper.length(dstArr) - indexShifts;
107 helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo);
108 }
109
110 @Test(dataProvider = "copyModesAndHelpers")
111 public void testCopyOobLength(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
112 int bytesPerElement = (int)helper.elementLayout.byteSize();
113 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
114 //CopyFrom
115 Object srcArr = helper.toArray(base);
116 MemorySegment dstSeg = helper.fromArray(srcArr);
117 try {
118 helper.copyFromArray(srcArr, 0, (SEG_LENGTH_BYTES / bytesPerElement) * 2, dstSeg, 0, ByteOrder.nativeOrder());
119 fail();
120 } catch (IndexOutOfBoundsException ex) {
121 //ok
122 }
123 //CopyTo
124 Object dstArr = helper.toArray(base);
125 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
126 try {
127 helper.copyToArray(srcSeg, 0, dstArr, 0, (SEG_LENGTH_BYTES / bytesPerElement) * 2, ByteOrder.nativeOrder());
128 fail();
129 } catch (IndexOutOfBoundsException ex) {
130 //ok
131 }
132 }
133
134 @Test(dataProvider = "copyModesAndHelpers")
135 public void testCopyNegativeIndices(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
136 int bytesPerElement = (int)helper.elementLayout.byteSize();
137 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
138 //CopyFrom
139 Object srcArr = helper.toArray(base);
140 MemorySegment dstSeg = helper.fromArray(srcArr);
141 try {
142 helper.copyFromArray(srcArr, -1, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder());
143 fail();
144 } catch (IndexOutOfBoundsException ex) {
145 //ok
146 }
147 //CopyTo
148 Object dstArr = helper.toArray(base);
149 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
150 try {
151 helper.copyToArray(srcSeg, 0, dstArr, -1, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder());
152 fail();
153 } catch (IndexOutOfBoundsException ex) {
154 //ok
155 }
156 }
157
158 @Test(dataProvider = "copyModesAndHelpers")
159 public void testCopyNegativeOffsets(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
160 int bytesPerElement = (int)helper.elementLayout.byteSize();
161 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
162 //CopyFrom
163 Object srcArr = helper.toArray(base);
164 MemorySegment dstSeg = helper.fromArray(srcArr);
165 try {
166 helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, -1, ByteOrder.nativeOrder());
167 fail();
168 } catch (IndexOutOfBoundsException ex) {
169 //ok
170 }
171 //CopyTo
172 Object dstArr = helper.toArray(base);
173 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
174 try {
175 helper.copyToArray(srcSeg, -1, dstArr, 0, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder());
176 fail();
177 } catch (IndexOutOfBoundsException ex) {
178 //ok
179 }
180 }
181
182 @Test(dataProvider = "copyModesAndHelpers")
183 public void testCopyOobIndices(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
184 int bytesPerElement = (int)helper.elementLayout.byteSize();
185 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
186 //CopyFrom
187 Object srcArr = helper.toArray(base);
188 MemorySegment dstSeg = helper.fromArray(srcArr);
189 try {
190 helper.copyFromArray(srcArr, helper.length(srcArr) + 1, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder());
191 fail();
192 } catch (IndexOutOfBoundsException ex) {
193 //ok
194 }
195 //CopyTo
196 Object dstArr = helper.toArray(base);
197 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
198 try {
199 helper.copyToArray(srcSeg, 0, dstArr, helper.length(dstArr) + 1, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder());
200 fail();
201 } catch (IndexOutOfBoundsException ex) {
202 //ok
203 }
204 }
205
206 @Test(dataProvider = "copyModesAndHelpers")
207 public void testCopyOobOffsets(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
208 int bytesPerElement = (int)helper.elementLayout.byteSize();
209 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
210 //CopyFrom
211 Object srcArr = helper.toArray(base);
212 MemorySegment dstSeg = helper.fromArray(srcArr);
213 try {
214 helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, SEG_LENGTH_BYTES + 1, ByteOrder.nativeOrder());
215 fail();
216 } catch (IndexOutOfBoundsException ex) {
217 //ok
218 }
219 //CopyTo
220 Object dstArr = helper.toArray(base);
221 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly();
222 try {
223 helper.copyToArray(srcSeg, SEG_OFFSET_BYTES + 1, dstArr, 0, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder());
224 fail();
225 } catch (IndexOutOfBoundsException ex) {
226 //ok
227 }
228 }
229
230 @Test(dataProvider = "copyModesAndHelpers")
231 public void testCopyReadOnlyDest(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) {
232 int bytesPerElement = (int)helper.elementLayout.byteSize();
233 MemorySegment base = srcSegment(SEG_LENGTH_BYTES);
234 //CopyFrom
235 Object srcArr = helper.toArray(base);
236 MemorySegment dstSeg = helper.fromArray(srcArr).asReadOnly();
237 try {
238 helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder());
239 fail();
240 } catch (IllegalArgumentException ex) {
241 //ok
242 }
243 }
244
245 @Test(expectedExceptions = IllegalArgumentException.class)
246 public void testNotAnArraySrc() {
247 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4});
248 MemorySegment.copy(segment, JAVA_BYTE, 0, new String[] { "hello" }, 0, 4);
249 }
250
251 @Test(expectedExceptions = IllegalArgumentException.class)
252 public void testNotAnArrayDst() {
253 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4});
254 MemorySegment.copy(new String[] { "hello" }, 0, segment, JAVA_BYTE, 0, 4);
255 }
256
257 @Test(expectedExceptions = IllegalArgumentException.class)
258 public void testCarrierMismatchSrc() {
259 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4});
260 MemorySegment.copy(segment, JAVA_INT, 0, new byte[] { 1, 2, 3, 4 }, 0, 4);
261 }
262
263 @Test(expectedExceptions = IllegalArgumentException.class)
264 public void testCarrierMismatchDst() {
265 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4});
266 MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4);
267 }
268
269 @Test(expectedExceptions = IllegalArgumentException.class)
270 public void testHyperAlignedSrc() {
271 MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
272 MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_BYTE.withByteAlignment(2), 0, 4);
273 }
274
275 @Test(expectedExceptions = IllegalArgumentException.class)
276 public void testHyperAlignedDst() {
277 MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
278 MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, new byte[] { 1, 2, 3, 4 }, 0, 4);
279 }
280
281 /***** Utilities *****/
282
283 public static MemorySegment srcSegment(int bytesLength) {
284 byte[] arr = new byte[bytesLength];
285 for (int i = 0; i < arr.length; i++) {
286 arr[i] = (byte)i;
287 }
288 return MemorySegment.ofArray(arr);
289 }
290
291 private static VarHandle arrayVarHandle(ValueLayout layout) {
292 return MethodHandles.insertCoordinates(layout.arrayElementVarHandle(), 1, 0L);
293 }
294
295 public static MemorySegment truthSegment(MemorySegment srcSeg, CopyHelper<?, ?> helper, int indexShifts, CopyMode mode) {
296 VarHandle indexedHandleNO = arrayVarHandle(helper.elementLayout.withOrder(NATIVE_ORDER));
297 VarHandle indexedHandleNNO = arrayVarHandle(helper.elementLayout.withOrder(NON_NATIVE_ORDER));
298 MemorySegment dstSeg = MemorySegment.ofArray(srcSeg.toArray(JAVA_BYTE));
299 int indexLength = (int) dstSeg.byteSize() / (int)helper.elementLayout.byteSize();
300 if (mode.direction) {
301 if (mode.swap) {
302 for (int i = indexLength - 1; i >= indexShifts; i--) {
303 Object v = indexedHandleNNO.get(dstSeg, i - indexShifts);
304 indexedHandleNO.set(dstSeg, i, v);
305 }
306 } else {
307 for (int i = indexLength - 1; i >= indexShifts; i--) {
308 Object v = indexedHandleNO.get(dstSeg, i - indexShifts);
309 indexedHandleNO.set(dstSeg, i, v);
310 }
311 }
312 } else { //down
313 if (mode.swap) {
314 for (int i = indexShifts; i < indexLength; i++) {
315 Object v = indexedHandleNNO.get(dstSeg, i);
316 indexedHandleNO.set(dstSeg, i - indexShifts, v);
317 }
318 } else {
319 for (int i = indexShifts; i < indexLength; i++) {
320 Object v = indexedHandleNO.get(dstSeg, i);
321 indexedHandleNO.set(dstSeg, i - indexShifts, v);
322 }
323 }
324 }
325 return dstSeg;
326 }
327
328 enum CopyMode {
329 UP_NO_SWAP(true, false),
330 UP_SWAP(true, true),
331 DOWN_NO_SWAP(false, false),
332 DOWN_SWAP(false, true);
333
334 final boolean direction;
335 final boolean swap;
336
337 CopyMode(boolean direction, boolean swap) {
338 this.direction = direction;
339 this.swap = swap;
340 }
341 }
342
343 abstract static class CopyHelper<X, L extends ValueLayout> {
344
345 final L elementLayout;
346 final Class<?> carrier;
347
348 @SuppressWarnings("unchecked")
349 public CopyHelper(L elementLayout, Class<X> carrier) {
350 this.elementLayout = (L)elementLayout.withByteAlignment(1);
351 this.carrier = carrier;
352 }
353
354 abstract void copyFromArray(X srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo);
355 abstract void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, X dstArr, int dstIndex, int dstCopyLen, ByteOrder bo);
356 abstract X toArray(MemorySegment segment);
357 abstract MemorySegment fromArray(X array);
358 abstract int length(X arr);
359
360 @Override
361 public String toString() {
362 return "CopyHelper{" +
363 "elementLayout=" + elementLayout +
364 ", carrier=" + carrier.getName() +
365 '}';
366 }
367
368 static final CopyHelper<byte[], ValueLayout.OfByte> BYTE = new CopyHelper<>(JAVA_BYTE, byte[].class) {
369 @Override
370 void copyFromArray(byte[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
371 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
372 }
373
374 @Override
375 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, byte[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
376 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
377 }
378
379 @Override
380 byte[] toArray(MemorySegment segment) {
381 return segment.toArray(elementLayout);
382 }
383
384 @Override
385 MemorySegment fromArray(byte[] array) {
386 return MemorySegment.ofArray(array);
387 }
388
389 @Override
390 int length(byte[] arr) {
391 return arr.length;
392 }
393 };
394
395 static final CopyHelper<char[], ValueLayout.OfChar> CHAR = new CopyHelper<>(ValueLayout.JAVA_CHAR, char[].class) {
396 @Override
397 void copyFromArray(char[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
398 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
399 }
400
401 @Override
402 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, char[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
403 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
404 }
405
406 @Override
407 char[] toArray(MemorySegment segment) {
408 return segment.toArray(elementLayout);
409 }
410
411 @Override
412 MemorySegment fromArray(char[] array) {
413 return MemorySegment.ofArray(array);
414 }
415
416 @Override
417 int length(char[] arr) {
418 return arr.length;
419 }
420 };
421
422 static final CopyHelper<short[], ValueLayout.OfShort> SHORT = new CopyHelper<>(ValueLayout.JAVA_SHORT, short[].class) {
423 @Override
424 void copyFromArray(short[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
425 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
426 }
427
428 @Override
429 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, short[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
430 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
431 }
432
433 @Override
434 short[] toArray(MemorySegment segment) {
435 return segment.toArray(elementLayout);
436 }
437
438 @Override
439 MemorySegment fromArray(short[] array) {
440 return MemorySegment.ofArray(array);
441 }
442
443 @Override
444 int length(short[] arr) {
445 return arr.length;
446 }
447 };
448
449 static final CopyHelper<int[], ValueLayout.OfInt> INT = new CopyHelper<>(ValueLayout.JAVA_INT, int[].class) {
450 @Override
451 void copyFromArray(int[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
452 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
453 }
454
455 @Override
456 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, int[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
457 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
458 }
459
460 @Override
461 int[] toArray(MemorySegment segment) {
462 return segment.toArray(elementLayout);
463 }
464
465 @Override
466 MemorySegment fromArray(int[] array) {
467 return MemorySegment.ofArray(array);
468 }
469
470 @Override
471 int length(int[] arr) {
472 return arr.length;
473 }
474 };
475
476 static final CopyHelper<float[], ValueLayout.OfFloat> FLOAT = new CopyHelper<>(ValueLayout.JAVA_FLOAT, float[].class) {
477 @Override
478 void copyFromArray(float[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
479 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
480 }
481
482 @Override
483 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, float[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
484 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
485 }
486
487 @Override
488 float[] toArray(MemorySegment segment) {
489 return segment.toArray(elementLayout);
490 }
491
492 @Override
493 MemorySegment fromArray(float[] array) {
494 return MemorySegment.ofArray(array);
495 }
496
497 @Override
498 int length(float[] arr) {
499 return arr.length;
500 }
501 };
502
503 static final CopyHelper<long[], ValueLayout.OfLong> LONG = new CopyHelper<>(ValueLayout.JAVA_LONG, long[].class) {
504 @Override
505 void copyFromArray(long[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
506 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
507 }
508
509 @Override
510 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, long[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
511 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
512 }
513
514 @Override
515 long[] toArray(MemorySegment segment) {
516 return segment.toArray(elementLayout);
517 }
518
519 @Override
520 MemorySegment fromArray(long[] array) {
521 return MemorySegment.ofArray(array);
522 }
523
524 @Override
525 int length(long[] arr) {
526 return arr.length;
527 }
528 };
529
530 static final CopyHelper<double[], ValueLayout.OfDouble> DOUBLE = new CopyHelper<>(ValueLayout.JAVA_DOUBLE, double[].class) {
531 @Override
532 void copyFromArray(double[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) {
533 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen);
534 }
535
536 @Override
537 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, double[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) {
538 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen);
539 }
540
541 @Override
542 double[] toArray(MemorySegment segment) {
543 return segment.toArray(elementLayout);
544 }
545
546 @Override
547 MemorySegment fromArray(double[] array) {
548 return MemorySegment.ofArray(array);
549 }
550
551 @Override
552 int length(double[] arr) {
553 return arr.length;
554 }
555 };
556 }
557
558 @DataProvider
559 Object[][] copyModesAndHelpers() {
560 CopyHelper<?, ?>[] helpers = { CopyHelper.BYTE, CopyHelper.CHAR, CopyHelper.SHORT, CopyHelper.INT,
561 CopyHelper.FLOAT, CopyHelper.LONG, CopyHelper.DOUBLE };
562 List<Object[]> results = new ArrayList<>();
563 for (CopyHelper<?, ?> helper : helpers) {
564 for (CopyMode mode : CopyMode.values()) {
565 results.add(new Object[] { mode, helper, helper.toString() });
566 }
567 }
568 return results.stream().toArray(Object[][]::new);
569 }
570 }