mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8162458: Buffer view implementations use incorrect offset for Unsafe access
Reviewed-by: alanb
This commit is contained in:
parent
9be5fdfe94
commit
8dc58ab506
4 changed files with 781 additions and 35 deletions
|
@ -40,7 +40,6 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
private static final Unsafe unsafe = Bits.unsafe();
|
||||
|
||||
protected final ByteBuffer bb;
|
||||
protected final int offset;
|
||||
|
||||
#end[rw]
|
||||
|
||||
|
@ -55,7 +54,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
this.limit(cap);
|
||||
int pos = this.position();
|
||||
assert (pos <= cap);
|
||||
offset = pos;
|
||||
address = bb.address;
|
||||
#else[rw]
|
||||
super(bb);
|
||||
#end[rw]
|
||||
|
@ -63,14 +62,15 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
|
||||
ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
|
||||
int mark, int pos, int lim, int cap,
|
||||
int off)
|
||||
long addr)
|
||||
{
|
||||
#if[rw]
|
||||
super(mark, pos, lim, cap);
|
||||
this.bb = bb;
|
||||
offset = off;
|
||||
address = addr;
|
||||
assert address >= bb.address;
|
||||
#else[rw]
|
||||
super(bb, mark, pos, lim, cap, off);
|
||||
super(bb, mark, pos, lim, cap, addr);
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
|
@ -79,9 +79,8 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
int lim = this.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
int off = (pos << $LG_BYTES_PER_VALUE$) + offset;
|
||||
assert (off >= 0);
|
||||
return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, off);
|
||||
long addr = byteOffset(pos);
|
||||
return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, addr);
|
||||
}
|
||||
|
||||
public $Type$Buffer duplicate() {
|
||||
|
@ -90,7 +89,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
this.position(),
|
||||
this.limit(),
|
||||
this.capacity(),
|
||||
offset);
|
||||
address);
|
||||
}
|
||||
|
||||
public $Type$Buffer asReadOnlyBuffer() {
|
||||
|
@ -100,7 +99,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
this.position(),
|
||||
this.limit(),
|
||||
this.capacity(),
|
||||
offset);
|
||||
address);
|
||||
#else[rw]
|
||||
return duplicate();
|
||||
#end[rw]
|
||||
|
@ -108,12 +107,13 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
|
||||
#if[rw]
|
||||
|
||||
protected int ix(int i) {
|
||||
return (i << $LG_BYTES_PER_VALUE$) + offset;
|
||||
private int ix(int i) {
|
||||
int off = (int) (address - bb.address);
|
||||
return (i << $LG_BYTES_PER_VALUE$) + off;
|
||||
}
|
||||
|
||||
private long byteOffset(long i) {
|
||||
return (i << $LG_BYTES_PER_VALUE$) + bb.address + offset;
|
||||
protected long byteOffset(long i) {
|
||||
return (i << $LG_BYTES_PER_VALUE$) + address;
|
||||
}
|
||||
|
||||
public $type$ get() {
|
||||
|
@ -226,7 +226,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
|
|||
pos + start,
|
||||
pos + end,
|
||||
capacity(),
|
||||
offset);
|
||||
address);
|
||||
}
|
||||
|
||||
#end[char]
|
||||
|
|
|
@ -88,13 +88,13 @@ class XXX {
|
|||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
address + off))
|
||||
: ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
address + off)));
|
||||
} else {
|
||||
return (nativeByteOrder
|
||||
? ($Type$Buffer)(new Direct$Type$Buffer$RW$U(this,
|
||||
|
|
|
@ -325,20 +325,20 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public CharBuffer asCharBuffer() {
|
||||
int size = this.remaining() >> 1;
|
||||
int off = offset + position();
|
||||
long addr = address + position();
|
||||
return (bigEndian
|
||||
? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
addr))
|
||||
: (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
addr)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -376,20 +376,20 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public ShortBuffer asShortBuffer() {
|
||||
int size = this.remaining() >> 1;
|
||||
int off = offset + position();
|
||||
long addr = address + position();
|
||||
return (bigEndian
|
||||
? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
addr))
|
||||
: (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
addr)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,20 +427,20 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public IntBuffer asIntBuffer() {
|
||||
int size = this.remaining() >> 2;
|
||||
int off = offset + position();
|
||||
long addr = address + position();
|
||||
return (bigEndian
|
||||
? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
addr))
|
||||
: (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
addr)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -478,20 +478,20 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public LongBuffer asLongBuffer() {
|
||||
int size = this.remaining() >> 3;
|
||||
int off = offset + position();
|
||||
long addr = address + position();
|
||||
return (bigEndian
|
||||
? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
addr))
|
||||
: (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
addr)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -533,20 +533,20 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public FloatBuffer asFloatBuffer() {
|
||||
int size = this.remaining() >> 2;
|
||||
int off = offset + position();
|
||||
long addr = address + position();
|
||||
return (bigEndian
|
||||
? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
addr))
|
||||
: (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
addr)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -588,20 +588,20 @@ class Heap$Type$Buffer$RW$
|
|||
|
||||
public DoubleBuffer asDoubleBuffer() {
|
||||
int size = this.remaining() >> 3;
|
||||
int off = offset + position();
|
||||
long addr = address + position();
|
||||
return (bigEndian
|
||||
? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off))
|
||||
addr))
|
||||
: (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
|
||||
-1,
|
||||
0,
|
||||
size,
|
||||
size,
|
||||
off)));
|
||||
addr)));
|
||||
}
|
||||
|
||||
|
||||
|
|
746
jdk/test/java/nio/Buffer/ByteBufferViews.java
Normal file
746
jdk/test/java/nio/Buffer/ByteBufferViews.java
Normal file
|
@ -0,0 +1,746 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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
|
||||
* @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()),
|
||||
// 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()),
|
||||
|
||||
// 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()),
|
||||
// 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())
|
||||
);
|
||||
|
||||
// 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().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().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().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().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().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().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));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue