| /* | |
| * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* @test | |
| * @summary Binary data and view tests for byte buffers | |
| * @bug 8159257 8258955 | |
| * @run testng ByteBufferViews | |
| */ | |
| import org.testng.annotations.DataProvider; | |
| import org.testng.annotations.Test; | |
| import java.nio.Buffer; | |
| import java.nio.ByteBuffer; | |
| import java.nio.ByteOrder; | |
| import java.nio.CharBuffer; | |
| import java.nio.DoubleBuffer; | |
| import java.nio.FloatBuffer; | |
| import java.nio.IntBuffer; | |
| import java.nio.LongBuffer; | |
| import java.nio.ShortBuffer; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.function.Function; | |
| import java.util.function.IntFunction; | |
| import java.util.function.IntUnaryOperator; | |
| import java.util.function.UnaryOperator; | |
| import java.util.stream.Collectors; | |
| import static org.testng.Assert.*; | |
| public class ByteBufferViews { | |
| static final int SIZE = 32; | |
| // List of buffer allocator functions | |
| static final List<Map.Entry<String, IntFunction<ByteBuffer>>> BYTE_BUFFER_ALLOCATE_FUNCTIONS = List.of( | |
| // Heap | |
| Map.entry("ByteBuffer.allocate(ba)", | |
| size -> ByteBuffer.allocate(size)), | |
| // Aligned | |
| Map.entry("ByteBuffer.allocate(size).position(8)", | |
| size -> ByteBuffer.allocate(size).position(8)), | |
| Map.entry("ByteBuffer.allocate(size).position(8).slice()", | |
| size -> ByteBuffer.allocate(size).position(8).slice()), | |
| Map.entry("ByteBuffer.allocate(size).position(8).slice().duplicate()", | |
| size -> ByteBuffer.allocate(size).position(8).slice().duplicate()), | |
| Map.entry("ByteBuffer.allocate(size).slice(8,size-8)", | |
| size -> ByteBuffer.allocate(size).slice(8,size-8)), | |
| // Unaligned | |
| Map.entry("ByteBuffer.allocate(size).position(1)", | |
| size -> ByteBuffer.allocate(size).position(1)), | |
| Map.entry("ByteBuffer.allocate(size).position(1).slice()", | |
| size -> ByteBuffer.allocate(size).position(1).slice()), | |
| Map.entry("ByteBuffer.allocate(size).position(1).slice().duplicate()", | |
| size -> ByteBuffer.allocate(size).position(1).slice().duplicate()), | |
| Map.entry("ByteBuffer.allocate(size).slice(1,size-1)", | |
| size -> ByteBuffer.allocate(size).slice(1,size-1)), | |
| // Off-heap | |
| Map.entry("ByteBuffer.allocateDirect(size)", | |
| size -> ByteBuffer.allocateDirect(size)), | |
| // Aligned | |
| Map.entry("ByteBuffer.allocateDirect(size).position(8)", | |
| size -> ByteBuffer.allocateDirect(size).position(8)), | |
| Map.entry("ByteBuffer.allocateDirect(size).position(8).slice()", | |
| size -> ByteBuffer.allocateDirect(size).position(8).slice()), | |
| Map.entry("ByteBuffer.allocateDirect(size).position(8).slice().duplicate()", | |
| size -> ByteBuffer.allocateDirect(size).position(8).slice().duplicate()), | |
| Map.entry("ByteBuffer.allocateDirect(size).slice(8,size-8)", | |
| size -> ByteBuffer.allocateDirect(size).slice(8,size-8)), | |
| // Unaligned | |
| Map.entry("ByteBuffer.allocateDirect(size).position(1)", | |
| size -> ByteBuffer.allocateDirect(size).position(1)), | |
| Map.entry("ByteBuffer.allocateDirect(size).position(1).slice()", | |
| size -> ByteBuffer.allocateDirect(size).position(1).slice()), | |
| Map.entry("ByteBuffer.allocateDirect(size).position(1).slice().duplicate()", | |
| size -> ByteBuffer.allocateDirect(size).position(1).slice().duplicate()), | |
| Map.entry("ByteBuffer.allocateDirect(size).slice(1,size-1)", | |
| size -> ByteBuffer.allocateDirect(size).slice(1,size-1)) | |
| ); | |
| // List of buffer byte order functions | |
| static final List<Map.Entry<String, UnaryOperator<ByteBuffer>>> BYTE_BUFFER_ORDER_FUNCTIONS = List.of( | |
| Map.entry("order(ByteOrder.BIG_ENDIAN)", | |
| (ByteBuffer bb) -> bb.order(ByteOrder.BIG_ENDIAN)), | |
| Map.entry("order(ByteOrder.LITTLE_ENDIAN)", | |
| (ByteBuffer bb) -> bb.order(ByteOrder.LITTLE_ENDIAN)) | |
| ); | |
| // Produce a composition of allocation and byte order buffer functions | |
| static List<Map.Entry<String, IntFunction<ByteBuffer>>> composeBufferFunctions( | |
| List<Map.Entry<String, IntFunction<ByteBuffer>>> af, | |
| List<Map.Entry<String, UnaryOperator<ByteBuffer>>> of) { | |
| return af.stream().flatMap(afe -> of.stream(). | |
| map(ofe -> { | |
| String s = afe.getKey() + "." + ofe.getKey(); | |
| IntFunction<ByteBuffer> f = size -> ofe.getValue(). | |
| apply(afe.getValue().apply(size)); | |
| return Map.entry(s, f); | |
| }) | |
| ).collect(Collectors.toList()); | |
| } | |
| // List of buffer allocator functions to test | |
| static final List<Map.Entry<String, IntFunction<ByteBuffer>>> BYTE_BUFFER_FUNCTIONS = | |
| composeBufferFunctions(BYTE_BUFFER_ALLOCATE_FUNCTIONS, BYTE_BUFFER_ORDER_FUNCTIONS); | |
| // Creates a cross product of test arguments for | |
| // buffer allocator functions and buffer view functions | |
| static Object[][] product(List<? extends Map.Entry<String, ?>> la, | |
| List<? extends Map.Entry<String, ?>> lb) { | |
| return la.stream().flatMap(lae -> lb.stream(). | |
| map(lbe -> List.of( | |
| lae.getKey() + " -> " + lbe.getKey(), | |
| lae.getValue(), | |
| lbe.getValue()).toArray() | |
| )).toArray(Object[][]::new); | |
| } | |
| static void assertValues(int i, Object bValue, Object bbValue, ByteBuffer bb) { | |
| if (!bValue.equals(bbValue)) { | |
| fail(String.format("Values %s and %s differ at index %d for %s", | |
| bValue, bbValue, i, bb)); | |
| } | |
| } | |
| static void assertValues(int i, Object bbValue, Object bvValue, ByteBuffer bb, Buffer bv) { | |
| if (!bbValue.equals(bvValue)) { | |
| fail(String.format("Values %s and %s differ at index %d for %s and %s", | |
| bbValue, bvValue, i, bb, bv)); | |
| } | |
| } | |
| static ByteBuffer allocate(IntFunction<ByteBuffer> f) { | |
| return allocate(f, i -> i); | |
| } | |
| static ByteBuffer allocate(IntFunction<ByteBuffer> f, IntUnaryOperator o) { | |
| return fill(f.apply(SIZE), o); | |
| } | |
| static ByteBuffer fill(ByteBuffer bb, IntUnaryOperator o) { | |
| for (int i = 0; i < bb.limit(); i++) { | |
| bb.put(i, (byte) o.applyAsInt(i)); | |
| } | |
| return bb; | |
| } | |
| @DataProvider | |
| public static Object[][] shortViewProvider() { | |
| List<Map.Entry<String, Function<ByteBuffer, ShortBuffer>>> bfs = List.of( | |
| Map.entry("bb.asShortBuffer()", | |
| bb -> bb.asShortBuffer()), | |
| Map.entry("bb.asShortBuffer().slice()", | |
| bb -> bb.asShortBuffer().slice()), | |
| Map.entry("bb.asShortBuffer().slice(index,length)", | |
| bb -> { var sb = bb.asShortBuffer(); | |
| sb = sb.slice(1, sb.limit() - 1); | |
| bb.position(bb.position() + 2); | |
| return sb; }), | |
| Map.entry("bb.asShortBuffer().slice().duplicate()", | |
| bb -> bb.asShortBuffer().slice().duplicate()) | |
| ); | |
| return product(BYTE_BUFFER_FUNCTIONS, bfs); | |
| } | |
| @Test(dataProvider = "shortViewProvider") | |
| public void testShortGet(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, ShortBuffer> fbi) { | |
| ByteBuffer bb = allocate(fbb); | |
| ShortBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| short fromBytes = getShortFromBytes(bb, o + i * 2); | |
| short fromMethodView = bb.getShort(o + i * 2); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| short fromBufferView = vb.get(i); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| short v = getShortFromBytes(bb, o + i * 2); | |
| short a = bb.getShort(); | |
| assertValues(i, v, a, bb); | |
| short b = vb.get(); | |
| assertValues(i, a, b, bb, vb); | |
| } | |
| } | |
| @Test(dataProvider = "shortViewProvider") | |
| public void testShortPut(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, ShortBuffer> fbi) { | |
| ByteBuffer bbfilled = allocate(fbb); | |
| ByteBuffer bb = allocate(fbb, i -> 0); | |
| ShortBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| short fromFilled = bbfilled.getShort(o + i * 2); | |
| vb.put(i, fromFilled); | |
| short fromMethodView = bb.getShort(o + i * 2); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| short fromFilled = bbfilled.getShort(o + i * 2); | |
| vb.put(fromFilled); | |
| short fromMethodView = bb.getShort(); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| fill(bb, i -> 0); | |
| bb.clear().position(o); | |
| vb.clear(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| short fromFilled = bbfilled.getShort(o + i * 2); | |
| bb.putShort(o + i * 2, fromFilled); | |
| short fromBufferView = vb.get(i); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| short fromFilled = bbfilled.getShort(o + i * 2); | |
| bb.putShort(fromFilled); | |
| short fromBufferView = vb.get(); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| } | |
| static short getShortFromBytes(ByteBuffer bb, int i) { | |
| int a = bb.get(i) & 0xFF; | |
| int b = bb.get(i + 1) & 0xFF; | |
| if (bb.order() == ByteOrder.BIG_ENDIAN) { | |
| return (short) ((a << 8) | b); | |
| } | |
| else { | |
| return (short) ((b << 8) | a); | |
| } | |
| } | |
| @DataProvider | |
| public static Object[][] charViewProvider() { | |
| List<Map.Entry<String, Function<ByteBuffer, CharBuffer>>> bfs = List.of( | |
| Map.entry("bb.asCharBuffer()", | |
| bb -> bb.asCharBuffer()), | |
| Map.entry("bb.asCharBuffer().slice()", | |
| bb -> bb.asCharBuffer().slice()), | |
| Map.entry("bb.asCharBuffer().slice(index,length)", | |
| bb -> { var cb = bb.asCharBuffer(); | |
| cb = cb.slice(1, cb.limit() - 1); | |
| bb.position(bb.position() + 2); | |
| return cb; }), | |
| Map.entry("bb.asCharBuffer().slice().duplicate()", | |
| bb -> bb.asCharBuffer().slice().duplicate()) | |
| ); | |
| return product(BYTE_BUFFER_FUNCTIONS, bfs); | |
| } | |
| @Test(dataProvider = "charViewProvider") | |
| public void testCharGet(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, CharBuffer> fbi) { | |
| ByteBuffer bb = allocate(fbb); | |
| CharBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| char fromBytes = getCharFromBytes(bb, o + i * 2); | |
| char fromMethodView = bb.getChar(o + i * 2); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| char fromBufferView = vb.get(i); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| char fromBytes = getCharFromBytes(bb, o + i * 2); | |
| char fromMethodView = bb.getChar(); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| char fromBufferView = vb.get(); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| } | |
| @Test(dataProvider = "charViewProvider") | |
| public void testCharPut(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, CharBuffer> fbi) { | |
| ByteBuffer bbfilled = allocate(fbb); | |
| ByteBuffer bb = allocate(fbb, i -> 0); | |
| CharBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| char fromFilled = bbfilled.getChar(o + i * 2); | |
| vb.put(i, fromFilled); | |
| char fromMethodView = bb.getChar(o + i * 2); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| char fromFilled = bbfilled.getChar(o + i * 2); | |
| vb.put(fromFilled); | |
| char fromMethodView = bb.getChar(); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| fill(bb, i -> 0); | |
| bb.clear().position(o); | |
| vb.clear(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| char fromFilled = bbfilled.getChar(o + i * 2); | |
| bb.putChar(o + i * 2, fromFilled); | |
| char fromBufferView = vb.get(i); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| char fromFilled = bbfilled.getChar(o + i * 2); | |
| bb.putChar(fromFilled); | |
| char fromBufferView = vb.get(); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| } | |
| static char getCharFromBytes(ByteBuffer bb, int i) { | |
| return (char) getShortFromBytes(bb, i); | |
| } | |
| @DataProvider | |
| public static Object[][] intViewProvider() { | |
| List<Map.Entry<String, Function<ByteBuffer, IntBuffer>>> bfs = List.of( | |
| Map.entry("bb.asIntBuffer()", | |
| bb -> bb.asIntBuffer()), | |
| Map.entry("bb.asIntBuffer().slice()", | |
| bb -> bb.asIntBuffer().slice()), | |
| Map.entry("bb.asIntBuffer().slice(index,length)", | |
| bb -> { var ib = bb.asIntBuffer(); | |
| ib = ib.slice(1, ib.limit() - 1); | |
| bb.position(bb.position() + 4); | |
| return ib; }), | |
| Map.entry("bb.asIntBuffer().slice().duplicate()", | |
| bb -> bb.asIntBuffer().slice().duplicate()) | |
| ); | |
| return product(BYTE_BUFFER_FUNCTIONS, bfs); | |
| } | |
| @Test(dataProvider = "intViewProvider") | |
| public void testIntGet(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, IntBuffer> fbi) { | |
| ByteBuffer bb = allocate(fbb); | |
| IntBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| int fromBytes = getIntFromBytes(bb, o + i * 4); | |
| int fromMethodView = bb.getInt(o + i * 4); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| int fromBufferView = vb.get(i); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| int v = getIntFromBytes(bb, o + i * 4); | |
| int a = bb.getInt(); | |
| assertValues(i, v, a, bb); | |
| int b = vb.get(); | |
| assertValues(i, a, b, bb, vb); | |
| } | |
| } | |
| @Test(dataProvider = "intViewProvider") | |
| public void testIntPut(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, IntBuffer> fbi) { | |
| ByteBuffer bbfilled = allocate(fbb); | |
| ByteBuffer bb = allocate(fbb, i -> 0); | |
| IntBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| int fromFilled = bbfilled.getInt(o + i * 4); | |
| vb.put(i, fromFilled); | |
| int fromMethodView = bb.getInt(o + i * 4); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| int fromFilled = bbfilled.getInt(o + i * 4); | |
| vb.put(fromFilled); | |
| int fromMethodView = bb.getInt(); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| fill(bb, i -> 0); | |
| bb.clear().position(o); | |
| vb.clear(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| int fromFilled = bbfilled.getInt(o + i * 4); | |
| bb.putInt(o + i * 4, fromFilled); | |
| int fromBufferView = vb.get(i); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| int fromFilled = bbfilled.getInt(o + i * 4); | |
| bb.putInt(fromFilled); | |
| int fromBufferView = vb.get(); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| } | |
| static int getIntFromBytes(ByteBuffer bb, int i) { | |
| int a = bb.get(i) & 0xFF; | |
| int b = bb.get(i + 1) & 0xFF; | |
| int c = bb.get(i + 2) & 0xFF; | |
| int d = bb.get(i + 3) & 0xFF; | |
| if (bb.order() == ByteOrder.BIG_ENDIAN) { | |
| return ((a << 24) | (b << 16) | (c << 8) | d); | |
| } | |
| else { | |
| return ((d << 24) | (c << 16) | (b << 8) | a); | |
| } | |
| } | |
| @DataProvider | |
| public static Object[][] longViewProvider() { | |
| List<Map.Entry<String, Function<ByteBuffer, LongBuffer>>> bfs = List.of( | |
| Map.entry("bb.asLongBuffer()", | |
| bb -> bb.asLongBuffer()), | |
| Map.entry("bb.asLongBuffer().slice()", | |
| bb -> bb.asLongBuffer().slice()), | |
| Map.entry("bb.asLongBuffer().slice(index,length)", | |
| bb -> { var lb = bb.asLongBuffer(); | |
| lb = lb.slice(1, lb.limit() - 1); | |
| bb.position(bb.position() + 8); | |
| return lb; }), | |
| Map.entry("bb.asLongBuffer().slice().duplicate()", | |
| bb -> bb.asLongBuffer().slice().duplicate()) | |
| ); | |
| return product(BYTE_BUFFER_FUNCTIONS, bfs); | |
| } | |
| @Test(dataProvider = "longViewProvider") | |
| public void testLongGet(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, LongBuffer> fbi) { | |
| ByteBuffer bb = allocate(fbb); | |
| LongBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| long fromBytes = getLongFromBytes(bb, o + i * 8); | |
| long fromMethodView = bb.getLong(o + i * 8); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| long fromBufferView = vb.get(i); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| long v = getLongFromBytes(bb, o + i * 8); | |
| long a = bb.getLong(); | |
| assertValues(i, v, a, bb); | |
| long b = vb.get(); | |
| assertValues(i, a, b, bb, vb); | |
| } | |
| } | |
| @Test(dataProvider = "longViewProvider") | |
| public void testLongPut(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, LongBuffer> fbi) { | |
| ByteBuffer bbfilled = allocate(fbb); | |
| ByteBuffer bb = allocate(fbb, i -> 0); | |
| LongBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| long fromFilled = bbfilled.getLong(o + i * 8); | |
| vb.put(i, fromFilled); | |
| long fromMethodView = bb.getLong(o + i * 8); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| long fromFilled = bbfilled.getLong(o + i * 8); | |
| vb.put(fromFilled); | |
| long fromMethodView = bb.getLong(); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| fill(bb, i -> 0); | |
| bb.clear().position(o); | |
| vb.clear(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| long fromFilled = bbfilled.getLong(o + i * 8); | |
| bb.putLong(o + i * 8, fromFilled); | |
| long fromBufferView = vb.get(i); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| long fromFilled = bbfilled.getLong(o + i * 8); | |
| bb.putLong(fromFilled); | |
| long fromBufferView = vb.get(); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| } | |
| static long getLongFromBytes(ByteBuffer bb, int i) { | |
| long a = bb.get(i) & 0xFF; | |
| long b = bb.get(i + 1) & 0xFF; | |
| long c = bb.get(i + 2) & 0xFF; | |
| long d = bb.get(i + 3) & 0xFF; | |
| long e = bb.get(i + 4) & 0xFF; | |
| long f = bb.get(i + 5) & 0xFF; | |
| long g = bb.get(i + 6) & 0xFF; | |
| long h = bb.get(i + 7) & 0xFF; | |
| if (bb.order() == ByteOrder.BIG_ENDIAN) { | |
| return ((a << 56) | (b << 48) | (c << 40) | (d << 32) | | |
| (e << 24) | (f << 16) | (g << 8) | h); | |
| } | |
| else { | |
| return ((h << 56) | (g << 48) | (f << 40) | (e << 32) | | |
| (d << 24) | (c << 16) | (b << 8) | a); | |
| } | |
| } | |
| @DataProvider | |
| public static Object[][] floatViewProvider() { | |
| List<Map.Entry<String, Function<ByteBuffer, FloatBuffer>>> bfs = List.of( | |
| Map.entry("bb.asFloatBuffer()", | |
| bb -> bb.asFloatBuffer()), | |
| Map.entry("bb.asFloatBuffer().slice()", | |
| bb -> bb.asFloatBuffer().slice()), | |
| Map.entry("bb.asFloatBuffer().slice(index,length)", | |
| bb -> { var fb = bb.asFloatBuffer(); | |
| fb = fb.slice(1, fb.limit() - 1); | |
| bb.position(bb.position() + 4); | |
| return fb; }), | |
| Map.entry("bb.asFloatBuffer().slice().duplicate()", | |
| bb -> bb.asFloatBuffer().slice().duplicate()) | |
| ); | |
| return product(BYTE_BUFFER_FUNCTIONS, bfs); | |
| } | |
| @Test(dataProvider = "floatViewProvider") | |
| public void testFloatGet(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, FloatBuffer> fbi) { | |
| ByteBuffer bb = allocate(fbb); | |
| FloatBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| float fromBytes = getFloatFromBytes(bb, o + i * 4); | |
| float fromMethodView = bb.getFloat(o + i * 4); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| float fromBufferView = vb.get(i); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| float v = getFloatFromBytes(bb, o + i * 4); | |
| float a = bb.getFloat(); | |
| assertValues(i, v, a, bb); | |
| float b = vb.get(); | |
| assertValues(i, a, b, bb, vb); | |
| } | |
| } | |
| @Test(dataProvider = "floatViewProvider") | |
| public void testFloatPut(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, FloatBuffer> fbi) { | |
| ByteBuffer bbfilled = allocate(fbb); | |
| ByteBuffer bb = allocate(fbb, i -> 0); | |
| FloatBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| float fromFilled = bbfilled.getFloat(o + i * 4); | |
| vb.put(i, fromFilled); | |
| float fromMethodView = bb.getFloat(o + i * 4); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| float fromFilled = bbfilled.getFloat(o + i * 4); | |
| vb.put(fromFilled); | |
| float fromMethodView = bb.getFloat(); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| fill(bb, i -> 0); | |
| bb.clear().position(o); | |
| vb.clear(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| float fromFilled = bbfilled.getFloat(o + i * 4); | |
| bb.putFloat(o + i * 4, fromFilled); | |
| float fromBufferView = vb.get(i); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| float fromFilled = bbfilled.getFloat(o + i * 4); | |
| bb.putFloat(fromFilled); | |
| float fromBufferView = vb.get(); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| } | |
| static float getFloatFromBytes(ByteBuffer bb, int i) { | |
| return Float.intBitsToFloat(getIntFromBytes(bb, i)); | |
| } | |
| @DataProvider | |
| public static Object[][] doubleViewProvider() { | |
| List<Map.Entry<String, Function<ByteBuffer, DoubleBuffer>>> bfs = List.of( | |
| Map.entry("bb.asDoubleBuffer()", | |
| bb -> bb.asDoubleBuffer()), | |
| Map.entry("bb.asDoubleBuffer().slice()", | |
| bb -> bb.asDoubleBuffer().slice()), | |
| Map.entry("bb.asDoubleBuffer().slice(index,length)", | |
| bb -> { var db = bb.asDoubleBuffer(); | |
| db = db.slice(1, db.limit() - 1); | |
| bb.position(bb.position() + 8); | |
| return db; }), | |
| Map.entry("bb.asDoubleBuffer().slice().duplicate()", | |
| bb -> bb.asDoubleBuffer().slice().duplicate()) | |
| ); | |
| return product(BYTE_BUFFER_FUNCTIONS, bfs); | |
| } | |
| @Test(dataProvider = "doubleViewProvider") | |
| public void testDoubleGet(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, DoubleBuffer> fbi) { | |
| ByteBuffer bb = allocate(fbb); | |
| DoubleBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| double fromBytes = getDoubleFromBytes(bb, o + i * 8); | |
| double fromMethodView = bb.getDouble(o + i * 8); | |
| assertValues(i, fromBytes, fromMethodView, bb); | |
| double fromBufferView = vb.get(i); | |
| assertValues(i, fromMethodView, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| double v = getDoubleFromBytes(bb, o + i * 8); | |
| double a = bb.getDouble(); | |
| assertValues(i, v, a, bb); | |
| double b = vb.get(); | |
| assertValues(i, a, b, bb, vb); | |
| } | |
| } | |
| @Test(dataProvider = "doubleViewProvider") | |
| public void testDoublePut(String desc, IntFunction<ByteBuffer> fbb, | |
| Function<ByteBuffer, DoubleBuffer> fbi) { | |
| ByteBuffer bbfilled = allocate(fbb); | |
| ByteBuffer bb = allocate(fbb, i -> 0); | |
| DoubleBuffer vb = fbi.apply(bb); | |
| int o = bb.position(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| double fromFilled = bbfilled.getDouble(o + i * 8); | |
| vb.put(i, fromFilled); | |
| double fromMethodView = bb.getDouble(o + i * 8); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| double fromFilled = bbfilled.getDouble(o + i * 8); | |
| vb.put(fromFilled); | |
| double fromMethodView = bb.getDouble(); | |
| assertValues(i, fromFilled, fromMethodView, bb, vb); | |
| } | |
| fill(bb, i -> 0); | |
| bb.clear().position(o); | |
| vb.clear(); | |
| for (int i = 0; i < vb.limit(); i++) { | |
| double fromFilled = bbfilled.getDouble(o + i * 8); | |
| bb.putDouble(o + i * 8, fromFilled); | |
| double fromBufferView = vb.get(i); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| for (int i = 0; i < vb.limit(); i++) { | |
| double fromFilled = bbfilled.getDouble(o + i * 8); | |
| bb.putDouble(fromFilled); | |
| double fromBufferView = vb.get(); | |
| assertValues(i, fromFilled, fromBufferView, bb, vb); | |
| } | |
| } | |
| static double getDoubleFromBytes(ByteBuffer bb, int i) { | |
| return Double.longBitsToDouble(getLongFromBytes(bb, i)); | |
| } | |
| } |