1 /* 2 * Copyright (c) 2019, 2022, 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 * @enablePreview 27 * @run testng TestArrayCopy 28 */ 29 30 import java.lang.foreign.MemorySegment; 31 import java.lang.foreign.ValueLayout; 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 (UnsupportedOperationException 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 public static MemorySegment truthSegment(MemorySegment srcSeg, CopyHelper<?, ?> helper, int indexShifts, CopyMode mode) { 292 VarHandle indexedHandleNO = helper.elementLayout.withOrder(NATIVE_ORDER).arrayElementVarHandle(); 293 VarHandle indexedHandleNNO = helper.elementLayout.withOrder(NON_NATIVE_ORDER).arrayElementVarHandle(); 294 MemorySegment dstSeg = MemorySegment.ofArray(srcSeg.toArray(JAVA_BYTE)); 295 int indexLength = (int) dstSeg.byteSize() / (int)helper.elementLayout.byteSize(); 296 if (mode.direction) { 297 if (mode.swap) { 298 for (int i = indexLength - 1; i >= indexShifts; i--) { 299 Object v = indexedHandleNNO.get(dstSeg, i - indexShifts); 300 indexedHandleNO.set(dstSeg, i, v); 301 } 302 } else { 303 for (int i = indexLength - 1; i >= indexShifts; i--) { 304 Object v = indexedHandleNO.get(dstSeg, i - indexShifts); 305 indexedHandleNO.set(dstSeg, i, v); 306 } 307 } 308 } else { //down 309 if (mode.swap) { 310 for (int i = indexShifts; i < indexLength; i++) { 311 Object v = indexedHandleNNO.get(dstSeg, i); 312 indexedHandleNO.set(dstSeg, i - indexShifts, v); 313 } 314 } else { 315 for (int i = indexShifts; i < indexLength; i++) { 316 Object v = indexedHandleNO.get(dstSeg, i); 317 indexedHandleNO.set(dstSeg, i - indexShifts, v); 318 } 319 } 320 } 321 return dstSeg; 322 } 323 324 enum CopyMode { 325 UP_NO_SWAP(true, false), 326 UP_SWAP(true, true), 327 DOWN_NO_SWAP(false, false), 328 DOWN_SWAP(false, true); 329 330 final boolean direction; 331 final boolean swap; 332 333 CopyMode(boolean direction, boolean swap) { 334 this.direction = direction; 335 this.swap = swap; 336 } 337 } 338 339 abstract static class CopyHelper<X, L extends ValueLayout> { 340 341 final L elementLayout; 342 final Class<?> carrier; 343 344 @SuppressWarnings("unchecked") 345 public CopyHelper(L elementLayout, Class<X> carrier) { 346 this.elementLayout = (L)elementLayout.withByteAlignment(1); 347 this.carrier = carrier; 348 } 349 350 abstract void copyFromArray(X srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo); 351 abstract void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, X dstArr, int dstIndex, int dstCopyLen, ByteOrder bo); 352 abstract X toArray(MemorySegment segment); 353 abstract MemorySegment fromArray(X array); 354 abstract int length(X arr); 355 356 @Override 357 public String toString() { 358 return "CopyHelper{" + 359 "elementLayout=" + elementLayout + 360 ", carrier=" + carrier.getName() + 361 '}'; 362 } 363 364 static final CopyHelper<byte[], ValueLayout.OfByte> BYTE = new CopyHelper<>(JAVA_BYTE, byte[].class) { 365 @Override 366 void copyFromArray(byte[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 367 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 368 } 369 370 @Override 371 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, byte[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 372 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 373 } 374 375 @Override 376 byte[] toArray(MemorySegment segment) { 377 return segment.toArray(elementLayout); 378 } 379 380 @Override 381 MemorySegment fromArray(byte[] array) { 382 return MemorySegment.ofArray(array); 383 } 384 385 @Override 386 int length(byte[] arr) { 387 return arr.length; 388 } 389 }; 390 391 static final CopyHelper<char[], ValueLayout.OfChar> CHAR = new CopyHelper<>(ValueLayout.JAVA_CHAR, char[].class) { 392 @Override 393 void copyFromArray(char[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 394 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 395 } 396 397 @Override 398 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, char[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 399 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 400 } 401 402 @Override 403 char[] toArray(MemorySegment segment) { 404 return segment.toArray(elementLayout); 405 } 406 407 @Override 408 MemorySegment fromArray(char[] array) { 409 return MemorySegment.ofArray(array); 410 } 411 412 @Override 413 int length(char[] arr) { 414 return arr.length; 415 } 416 }; 417 418 static final CopyHelper<short[], ValueLayout.OfShort> SHORT = new CopyHelper<>(ValueLayout.JAVA_SHORT, short[].class) { 419 @Override 420 void copyFromArray(short[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 421 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 422 } 423 424 @Override 425 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, short[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 426 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 427 } 428 429 @Override 430 short[] toArray(MemorySegment segment) { 431 return segment.toArray(elementLayout); 432 } 433 434 @Override 435 MemorySegment fromArray(short[] array) { 436 return MemorySegment.ofArray(array); 437 } 438 439 @Override 440 int length(short[] arr) { 441 return arr.length; 442 } 443 }; 444 445 static final CopyHelper<int[], ValueLayout.OfInt> INT = new CopyHelper<>(ValueLayout.JAVA_INT, int[].class) { 446 @Override 447 void copyFromArray(int[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 448 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 449 } 450 451 @Override 452 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, int[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 453 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 454 } 455 456 @Override 457 int[] toArray(MemorySegment segment) { 458 return segment.toArray(elementLayout); 459 } 460 461 @Override 462 MemorySegment fromArray(int[] array) { 463 return MemorySegment.ofArray(array); 464 } 465 466 @Override 467 int length(int[] arr) { 468 return arr.length; 469 } 470 }; 471 472 static final CopyHelper<float[], ValueLayout.OfFloat> FLOAT = new CopyHelper<>(ValueLayout.JAVA_FLOAT, float[].class) { 473 @Override 474 void copyFromArray(float[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 475 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 476 } 477 478 @Override 479 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, float[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 480 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 481 } 482 483 @Override 484 float[] toArray(MemorySegment segment) { 485 return segment.toArray(elementLayout); 486 } 487 488 @Override 489 MemorySegment fromArray(float[] array) { 490 return MemorySegment.ofArray(array); 491 } 492 493 @Override 494 int length(float[] arr) { 495 return arr.length; 496 } 497 }; 498 499 static final CopyHelper<long[], ValueLayout.OfLong> LONG = new CopyHelper<>(ValueLayout.JAVA_LONG, long[].class) { 500 @Override 501 void copyFromArray(long[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 502 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 503 } 504 505 @Override 506 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, long[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 507 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 508 } 509 510 @Override 511 long[] toArray(MemorySegment segment) { 512 return segment.toArray(elementLayout); 513 } 514 515 @Override 516 MemorySegment fromArray(long[] array) { 517 return MemorySegment.ofArray(array); 518 } 519 520 @Override 521 int length(long[] arr) { 522 return arr.length; 523 } 524 }; 525 526 static final CopyHelper<double[], ValueLayout.OfDouble> DOUBLE = new CopyHelper<>(ValueLayout.JAVA_DOUBLE, double[].class) { 527 @Override 528 void copyFromArray(double[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 529 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 530 } 531 532 @Override 533 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, double[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 534 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 535 } 536 537 @Override 538 double[] toArray(MemorySegment segment) { 539 return segment.toArray(elementLayout); 540 } 541 542 @Override 543 MemorySegment fromArray(double[] array) { 544 return MemorySegment.ofArray(array); 545 } 546 547 @Override 548 int length(double[] arr) { 549 return arr.length; 550 } 551 }; 552 } 553 554 @DataProvider 555 Object[][] copyModesAndHelpers() { 556 CopyHelper<?, ?>[] helpers = { CopyHelper.BYTE, CopyHelper.CHAR, CopyHelper.SHORT, CopyHelper.INT, 557 CopyHelper.FLOAT, CopyHelper.LONG, CopyHelper.DOUBLE }; 558 List<Object[]> results = new ArrayList<>(); 559 for (CopyHelper<?, ?> helper : helpers) { 560 for (CopyMode mode : CopyMode.values()) { 561 results.add(new Object[] { mode, helper, helper.toString() }); 562 } 563 } 564 return results.stream().toArray(Object[][]::new); 565 } 566 }