A bit input stream is backed by an array of bytes. There are a handful of methods that read from that byte array into various coerced primitive arrays.
There is duplicated code. Java lacks generics on primitive types, so perhaps the repetition is unavoidable.
The repetitious code is apparent in the following methods:
@Override
public long readBytes(final byte[] out, final int offset, final int count, final int bits) {
final int total = offset + count;
assert out != null;
assert total <= out.length;
final long startPosition = position();
for (int i = offset; i < total; i++) {
out[i] = readByte(bits);
}
return position() - startPosition;
}
@Override
public long readShorts(final short[] out, final int offset, final int count, final int bits) {
final int total = offset + count;
assert out != null;
assert total <= out.length;
final long startPosition = position();
for (int i = offset; i < total; i++) {
out[i] = readShort(bits);
}
return position() - startPosition;
}
Note how final byte[] out
relates to readByte(bits)
just as final short[] out
relates to readShort(bits)
. These relations are the crux of the problem.
How can the duplication be eliminated, if at all, without incurring a significant performance hit (e.g., by autoboxing)?
If you're reading bulk primitives like your code seems to indicate, using ByteBuffer methods like asDoubleBuffer() or asShortBuffer() will offload some of the lowest level work.
Example:
public void readBytes( final byte[] out, final int offset, final int count, final ByteBuffer buffer ) {
buffer.get( out, offset, count ); // udates ByteBuffer `position` automatically
}
public void readShorts( final short[] out, final int offset, final int count, final ByteBuffer buffer ) {
ShortBuffer sb = buffer.asShortBuffer();
sb.get( out, offset, count ); // note that `count` reads two bytes for each `short`
}
(Code compiles but not tested!)