diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/java/com/jogamp/common/util/Bitstream.java | 555 | ||||
-rw-r--r-- | src/junit/com/jogamp/common/util/TestBitstream00.java | 132 | ||||
-rw-r--r-- | src/junit/com/jogamp/common/util/TestBitstream01.java | 164 | ||||
-rw-r--r-- | src/junit/com/jogamp/common/util/TestBitstream02.java | 14 | ||||
-rw-r--r-- | src/junit/com/jogamp/common/util/TestBitstream03.java | 21 | ||||
-rw-r--r-- | src/junit/com/jogamp/common/util/TestBitstream04.java | 20 |
6 files changed, 586 insertions, 320 deletions
diff --git a/src/java/com/jogamp/common/util/Bitstream.java b/src/java/com/jogamp/common/util/Bitstream.java index a242faf..e75d820 100644 --- a/src/java/com/jogamp/common/util/Bitstream.java +++ b/src/java/com/jogamp/common/util/Bitstream.java @@ -91,6 +91,28 @@ public class Bitstream<T> { long position(); /** + * Sets this stream's position. + * <p> + * A set mark is cleared if > new position. + * </p> + * <p> + * Returns {@link Bitstream#EOS} is end-of-stream is reached, + * otherwise the new position. + * </p> + * <p> + * Known supporting implementation is {@link ByteBufferStream} and {@link ByteArrayStream}. + * </p> + * + * @param newPosition The new positive position. + * + * @return The new set position or {@link Bitstream#EOS} if end-of-stream is reached. + * + * @throws UnsupportedOperationException if not supported, i.e. {@link ByteInputStream} or {@link ByteOutputStream} + * @throws IllegalArgumentException If the {@code newPosition} is negative + */ + long position(long newPosition) throws UnsupportedOperationException, IllegalArgumentException; + + /** * It is implementation dependent, whether backward skip giving a negative number is supported or not. * @param n number of bytes to skip * @return actual skipped bytes @@ -99,9 +121,9 @@ public class Bitstream<T> { long skip(final long n) throws IOException; /** - * Set <i>markpos</i> to current position, allowing the stream to be {@link #reset()}. - * @param readLimit - * @throws UnsupportedOperationException is not supported, i.e. if stream is not an {@link #canInput() input stream}. + * Set {@code markpos} to current position, allowing the stream to be {@link #reset()}. + * @param readlimit maximum number of bytes able to read before invalidating the {@code markpos}. + * @throws UnsupportedOperationException if not supported, i.e. if stream is not an {@link #canInput() input stream}. */ void mark(final int readLimit) throws UnsupportedOperationException; @@ -110,7 +132,7 @@ public class Bitstream<T> { * <p> * <i>markpos</i> is kept, hence {@link #reset()} can be called multiple times. * </p> - * @throws UnsupportedOperationException is not supported, i.e. if stream is not an {@link #canInput() input stream}. + * @throws UnsupportedOperationException if not supported, i.e. if stream is not an {@link #canInput() input stream}. * @throws IllegalStateException if <i>markpos</i> has not been set via {@link #mark(int)} or reset operation failed. * @throws IOException if reset operation failed. */ @@ -123,7 +145,7 @@ public class Bitstream<T> { * otherwise the resulting value. * </p> * @throws IOException - * @throws UnsupportedOperationException is not supported, i.e. if stream is not an {@link #canInput() input stream}. + * @throws UnsupportedOperationException if not supported, i.e. if stream is not an {@link #canInput() input stream}. */ int read() throws UnsupportedOperationException, IOException; @@ -134,7 +156,7 @@ public class Bitstream<T> { * otherwise the written value. * </p> * @throws IOException - * @throws UnsupportedOperationException is not supported, i.e. if stream is not an {@link #canOutput() output stream}. + * @throws UnsupportedOperationException if not supported, i.e. if stream is not an {@link #canOutput() output stream}. */ int write(final byte val) throws UnsupportedOperationException, IOException; } @@ -183,6 +205,18 @@ public class Bitstream<T> { public long position() { return pos; } @Override + public long position(final long newPosition) throws UnsupportedOperationException, IllegalArgumentException { + if( newPosition >= media.length ) { + return Bitstream.EOS; + } + pos = (int)newPosition; + if( posMark > pos ) { + posMark = -1; + } + return pos; + } + + @Override public long skip(final long n) { final long skip; if( n >= 0 ) { @@ -220,7 +254,7 @@ public class Bitstream<T> { } if( DEBUG ) { if( EOS != r ) { - System.err.println("u8["+(pos-1)+"] -> "+toHexBinString(r, 8)); + System.err.println("u8["+(pos-1)+"] -> "+toHexBinString(true, r, 8)); } else { System.err.println("u8["+(pos-0)+"] -> EOS"); } @@ -239,7 +273,7 @@ public class Bitstream<T> { } if( DEBUG ) { if( EOS != r ) { - System.err.println("u8["+(pos-1)+"] <- "+toHexBinString(r, 8)); + System.err.println("u8["+(pos-1)+"] <- "+toHexBinString(true, r, 8)); } else { System.err.println("u8["+(pos-0)+"] <- EOS"); } @@ -292,6 +326,19 @@ public class Bitstream<T> { public long position() { return pos; } @Override + public long position(final long newPosition) throws UnsupportedOperationException, IllegalArgumentException { + if( newPosition >= media.limit() ) { + return Bitstream.EOS; + } + media.position((int)newPosition); + pos = (int)newPosition; + if( posMark > pos ) { + posMark = -1; + } + return pos; + } + + @Override public long skip(final long n) { final long skip; if( n >= 0 ) { @@ -330,7 +377,7 @@ public class Bitstream<T> { } if( DEBUG ) { if( EOS != r ) { - System.err.println("u8["+(pos-1)+"] -> "+toHexBinString(r, 8)); + System.err.println("u8["+(pos-1)+"] -> "+toHexBinString(true, r, 8)); } else { System.err.println("u8["+(pos-0)+"] -> EOS"); } @@ -349,7 +396,7 @@ public class Bitstream<T> { } if( DEBUG ) { if( EOS != r ) { - System.err.println("u8["+(pos-1)+"] <- "+toHexBinString(r, 8)); + System.err.println("u8["+(pos-1)+"] <- "+toHexBinString(true, r, 8)); } else { System.err.println("u8["+(pos-0)+"] <- EOS"); } @@ -411,6 +458,11 @@ public class Bitstream<T> { public long position() { return pos; } @Override + public long position(final long newPosition) throws UnsupportedOperationException, IllegalArgumentException { + throw new UnsupportedOperationException("N/a for "+getClass().getCanonicalName()); + } + + @Override public long skip(final long n) throws IOException { final long skip = media.skip(n); pos += skip; @@ -438,7 +490,7 @@ public class Bitstream<T> { final int r = media.read(); if(DEBUG) { if( EOS != r ) { - System.err.println("u8["+pos+"] -> "+toHexBinString(r, 8)); + System.err.println("u8["+pos+"] -> "+toHexBinString(true, r, 8)); } else { System.err.println("u8["+pos+"] -> EOS"); } @@ -505,6 +557,11 @@ public class Bitstream<T> { public long position() { return pos; } @Override + public long position(final long newPosition) throws UnsupportedOperationException, IllegalArgumentException { + throw new UnsupportedOperationException("N/a for "+getClass().getCanonicalName()); + } + + @Override public long skip(final long n) throws IOException { long i = n; while(i > 0) { @@ -539,7 +596,7 @@ public class Bitstream<T> { final int r = 0xff & val; media.write(r); if(DEBUG) { - System.err.println("u8["+pos+"] <- "+toHexBinString(r, 8)); + System.err.println("u8["+pos+"] <- "+toHexBinString(true, r, 8)); } pos++; return r; @@ -685,8 +742,8 @@ public class Bitstream<T> { public final boolean canOutput() { return null != bytes ? bytes.canOutput() : false; } /** - * Set <i>markpos</i> to current position, allowing the stream to be {@link #reset()}. - * @param readLimit + * Set {@code markpos} to current position, allowing the stream to be {@link #reset()}. + * @param readlimit maximum number of bytes able to read before invalidating the {@code markpos}. * @throws IllegalStateException if not in input mode or stream closed */ public final void mark(final int readLimit) throws IllegalStateException { @@ -779,46 +836,68 @@ public class Bitstream<T> { } /** + * Sets this stream's bit position. + * <p> + * A set mark is cleared. + * </p> + * <p> + * Returns {@link Bitstream#EOS} is end-of-stream is reached, + * otherwise the new position. + * </p> + * <p> + * Known supporting implementation is {@link ByteBufferStream} and {@link ByteArrayStream}. + * </p> + * + * @param newPosition The new positive position. + * + * @return The new set position or {@link Bitstream#EOS} if end-of-stream is reached. + * + * @throws UnsupportedOperationException if not supported, i.e. {@link ByteInputStream} or {@link ByteOutputStream} + * @throws IllegalArgumentException If the {@code newPosition} is negative + * @throws IOException if read error occurs or EOS is reached and {@link #setThrowIOExceptionOnEOF(boolean)} is set to true. + * @throws IllegalStateException + */ + public final long position(final long newPosition) throws UnsupportedOperationException, IllegalArgumentException, IllegalStateException, IOException { + if( 0 > newPosition ) { + throw new IllegalArgumentException("new position not positive: "+newPosition); + } + bytes.position(0); // throws UnsupportedOperationException + resetLocal(); + if( newPosition > skip(newPosition) ) { + return EOS; + } + return newPosition; + } + + /** * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. * @return the read bit or {@link #EOS} if end-of-stream is reached. * @throws IOException * @throws IllegalStateException if not in input mode or stream closed */ - public final int readBit(final boolean msbFirst) throws IllegalStateException, IOException { + public final int readBit(final boolean msbFirst) throws UnsupportedOperationException, IllegalStateException, IOException { if( outputMode || null == bytes ) { throw new IllegalStateException("not in input-mode: "+this); } - if( msbFirst ) { - // MSB - if ( 0 < bitCount ) { - bitCount--; + if ( 0 < bitCount ) { + bitCount--; + if( msbFirst ) { return ( bitBuffer >>> bitCount ) & 0x01; } else { - bitBuffer = bytes.read(); - if( EOS == bitBuffer ) { - if( throwIOExceptionOnEOF ) { - throw new IOException("EOS "+this); - } - return EOS; - } else { - bitCount=7; - return bitBuffer >>> 7; - } + return ( bitBuffer >>> ( 7 - bitCount ) ) & 0x01; } } else { - // LSB - if ( 0 < bitCount ) { - bitCount--; - return ( bitBuffer >>> ( 7 - bitCount ) ) & 0x01; + bitBuffer = bytes.read(); + if( EOS == bitBuffer ) { + if( throwIOExceptionOnEOF ) { + throw new IOException("EOS "+this); + } + return EOS; } else { - bitBuffer = bytes.read(); - if( EOS == bitBuffer ) { - if( throwIOExceptionOnEOF ) { - throw new IOException("EOS "+this); - } - return EOS; + bitCount=7; + if( msbFirst ) { + return bitBuffer >>> 7; } else { - bitCount=7; return bitBuffer & 0x01; } } @@ -836,36 +915,25 @@ public class Bitstream<T> { if( !outputMode || null == bytes ) { throw new IllegalStateException("not in output-mode: "+this); } - if( msbFirst ) { - // MSB - if ( 0 < bitCount ) { - bitCount--; + if ( 0 < bitCount ) { + bitCount--; + if( msbFirst ) { bitBuffer |= ( 0x01 & bit ) << bitCount; - if( 0 == bitCount ) { - final int r = bytes.write((byte)bitBuffer); - if( throwIOExceptionOnEOF && EOS == r ) { - throw new IOException("EOS "+this); - } - return r; - } } else { - bitCount = 7; - bitBuffer = ( 0x01 & bit ) << 7; - } - } else { - // LSB - if ( 0 < bitCount ) { - bitCount--; bitBuffer |= ( 0x01 & bit ) << ( 7 - bitCount ); - if( 0 == bitCount ) { - final int r = bytes.write((byte)bitBuffer); - if( throwIOExceptionOnEOF && EOS == r ) { - throw new IOException("EOS "+this); - } - return r; + } + if( 0 == bitCount ) { + final int r = bytes.write((byte)bitBuffer); + if( throwIOExceptionOnEOF && EOS == r ) { + throw new IOException("EOS "+this); } + return r; + } + } else { + bitCount = 7; + if( msbFirst ) { + bitBuffer = ( 0x01 & bit ) << 7; } else { - bitCount = 7; bitBuffer = 0x01 & bit; } } @@ -877,7 +945,7 @@ public class Bitstream<T> { * * @param n number of bits to skip * @return actual skipped bits - * @throws IOException + * @throws IOException if read error occurs or EOS is reached and {@link #setThrowIOExceptionOnEOF(boolean)} is set to true. * @throws IllegalStateException if closed */ public long skip(final long n) throws IllegalStateException, IOException { @@ -939,85 +1007,96 @@ public class Bitstream<T> { return nX - notReadBits; } } else { - // FIXME: Backward skip + // Zero skip or backward skip + // FIXME: Backward skip n < 0 return 0; } } + private static final boolean useFastPathStream = true; + private static final boolean useFastPathTypes = true; + /** - * Return incoming bits as read via {@link #readBit(boolean)}. + * Return incoming bits as read via {@link #readBit(boolean)} LSB-first as little-endian. * <p> - * The incoming bits are stored in MSB-first order, i.e. first on highest position and last bit on lowest position. - * Hence reading w/ <i>lsbFirst</i>, the bit order will be reversed! + * The incoming bit order is from low- to most-significant-bit, maintaining bit LSB-first order. * </p> - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. * @param n number of bits, maximum 31 bits * @return the read bits from 0-n in the given order or {@link #EOS}. * @throws IllegalStateException if not in input mode or stream closed * @throws IllegalArgumentException if n > 31 * @throws IOException */ - public int readBits31(final boolean msbFirst, final int n) throws IllegalArgumentException, IOException { + public int readBits31(final int n) throws IllegalArgumentException, IOException { if( 31 < n ) { throw new IllegalArgumentException("n > 31: "+n); } if( outputMode || null == bytes ) { throw new IllegalStateException("not in input-mode: "+this); } - if( !msbFirst || 0 == n ) { - // Slow path - int r = 0; - int c = n; - while(--c >= 0) { - final int b = readBit(msbFirst); - if( EOS == b ) { - return EOS; - } - r |= b << c; - } - return r; + if( 0 == n ) { + return 0; } else { - // fast path: MSB - int c = n; - final int n1 = Math.min(c, bitCount); // remaining portion - int r; - if( 0 < n1 ) { - final int m1 = ( 1 << n1 ) - 1; - bitCount -= n1; - c -= n1; - r = ( m1 & ( bitBuffer >>> bitCount ) ) << c; - if( 0 == c ) { - return r; + if( !useFastPathStream ) { + // Slow path + int r = 0; + for(int i=0; i < n; i++) { + final int b = readBit(false /* msbFirst */); + if( EOS == b ) { + if( throwIOExceptionOnEOF ) { + throw new IOException("EOS "+this); + } + return EOS; + } + r |= b << i; } + return r; } else { - r = 0; - } - assert( 0 == bitCount ); - do { - bitBuffer = bytes.read(); - if( EOS == bitBuffer ) { - if( throwIOExceptionOnEOF ) { - throw new IOException("EOS "+this); + // fast path + int c = n; + final int n1 = Math.min(n, bitCount); // remaining portion + int r; + if( 0 < n1 ) { + final int m1 = ( 1 << n1 ) - 1; + final int s1 = 7 - bitCount + 1; // LSBfirst: right-shift to new bits + bitCount -= n1; + c -= n1; + // MSBfirst: r = ( m1 & ( bitBuffer >>> bitCount ) ) << c; + r = ( m1 & ( bitBuffer >>> s1 ) ); // LSBfirst + if( 0 == c ) { + return r; } - return EOS; + } else { + r = 0; } - final int n2 = Math.min(c, 8); // full portion - final int m2 = ( 1 << n2 ) - 1; - bitCount = 8 - n2; - c -= n2; - r |= ( m2 & ( bitBuffer >>> bitCount ) ) << c; - } while ( 0 < c ); - return r; + assert( 0 == bitCount ); + int s = n1; // LSBfirst: left shift for additional elements + do { + bitBuffer = bytes.read(); + if( EOS == bitBuffer ) { + if( throwIOExceptionOnEOF ) { + throw new IOException("EOS "+this); + } + return EOS; + } + final int n2 = Math.min(c, 8); // full portion + final int m2 = ( 1 << n2 ) - 1; + bitCount = 8 - n2; + c -= n2; + // MSBfirst: r |= ( m2 & ( bitBuffer >>> bitCount ) ) << c; + r |= ( m2 & bitBuffer ) << s; // LSBfirst on new bits + s += n2; + } while ( 0 < c ); + return r; + } } } /** - * Write the given bits via {@link #writeBit(boolean, int)}. + * Write the given bits via {@link #writeBit(boolean, int)} LSB-first as little-endian. * <p> - * The given bits are scanned from LSB-first order. - * Hence reading w/ <i>msbFirst</i>, the bit order will be reversed! + * The outgoing bit order is from low- to most-significant-bit, maintaining bit LSB-first order. * </p> - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. * @param n number of bits, maximum 31 bits * @param bits the bits to write * @return the written bits or {@link #EOS}. @@ -1025,76 +1104,81 @@ public class Bitstream<T> { * @throws IllegalArgumentException if n > 31 * @throws IOException */ - public int writeBits31(final boolean msbFirst, final int n, final int bits) throws IllegalStateException, IllegalArgumentException, IOException { + public int writeBits31(final int n, final int bits) throws IllegalStateException, IllegalArgumentException, IOException { if( 31 < n ) { throw new IllegalArgumentException("n > 31: "+n); } if( !outputMode || null == bytes ) { throw new IllegalStateException("not in output-mode: "+this); } - if( !msbFirst || 0 == n ) { - // Slow path - int c = n; - while(--c >= 0) { - final int b = writeBit(msbFirst, ( bits >>> c ) & 0x1); - if( EOS == b ) { - return EOS; - } - } - } else { - // fast path: MSB - int c = n; - final int n1 = Math.min(c, bitCount); // remaining portion - if( 0 < n1 ) { - final int m1 = ( 1 << n1 ) - 1; - bitCount -= n1; - c -= n1; - bitBuffer |= ( m1 & ( bits >> c ) ) << bitCount; - if( 0 == bitCount ) { - if( EOS == bytes.write((byte)bitBuffer) ) { - if( throwIOExceptionOnEOF ) { - throw new IOException("EOS "+this); - } + if( 0 < n ) { + if( !useFastPathStream ) { + // Slow path + for(int i=0; i < n; i++) { + final int b = writeBit(false /* msbFirst */, ( bits >>> i ) & 0x1); + if( EOS == b ) { return EOS; } } - if( 0 == c ) { - return bits; - } - } - assert( 0 == bitCount ); - do { - final int n2 = Math.min(c, 8); // full portion - final int m2 = ( 1 << n2 ) - 1; - bitCount = 8 - n2; - c -= n2; - bitBuffer = ( m2 & ( bits >> c ) ) << bitCount; - if( 0 == bitCount ) { - if( EOS == bytes.write((byte)bitBuffer) ) { - if( throwIOExceptionOnEOF ) { - throw new IOException("EOS "+this); + } else { + // fast path + int c = n; + final int n1 = Math.min(n, bitCount); // remaining portion + if( 0 < n1 ) { + final int m1 = ( 1 << n1 ) - 1; + final int s1 = 7 - bitCount + 1; // LSBfirst: left-shift to free bit-pos + bitCount -= n1; + c -= n1; + // MSBfirst: bitBuffer |= ( m1 & ( bits >>> c ) ) << bitCount; + bitBuffer |= ( m1 & bits ) << s1 ; // LSBfirst + if( 0 == bitCount ) { + if( EOS == bytes.write((byte)bitBuffer) ) { + if( throwIOExceptionOnEOF ) { + throw new IOException("EOS "+this); + } + return EOS; } - return EOS; + } + if( 0 == c ) { + return bits; } } - } while ( 0 < c ); + assert( 0 == bitCount ); + int s = n1; // LSBfirst: left shift for additional elements + do { + final int n2 = Math.min(c, 8); // full portion + final int m2 = ( 1 << n2 ) - 1; + bitCount = 8 - n2; + c -= n2; + // MSBfirst: bitBuffer = ( m2 & ( bits >>> c ) ) << bitCount; + bitBuffer = ( m2 & ( bits >>> s ) ); // LSBfirst + s += n2; + if( 0 == bitCount ) { + if( EOS == bytes.write((byte)bitBuffer) ) { + if( throwIOExceptionOnEOF ) { + throw new IOException("EOS "+this); + } + return EOS; + } + } + } while ( 0 < c ); + } } return bits; } /** - * Return incoming <code>uint8_t</code> as read via {@link #readBits31(boolean, int)}. + * Return incoming <code>uint8_t</code> as read via {@link #readBits31(int)}. * <p> * In case of a <code>int8_t</code> 2-complement signed value, simply cast the result to <code>byte</code> * after checking for {@link #EOS}. * </p> - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. * @return {@link #EOS} or the 8bit unsigned value within the lower bits. * @throws IllegalStateException if not in input mode or stream closed * @throws IOException */ - public final int readUInt8(final boolean msbFirst) throws IllegalStateException, IOException { - if( 0 == bitCount && msbFirst ) { + public final int readUInt8() throws IllegalStateException, IOException { + if( 0 == bitCount && useFastPathTypes ) { // fast path if( outputMode || null == bytes ) { throw new IllegalStateException("not in input-mode: "+this); @@ -1105,19 +1189,18 @@ public class Bitstream<T> { } return r; } else { - return readBits31(msbFirst, 8); + return readBits31(8); } } /** - * Write the given 8 bits via {@link #writeBits31(boolean, int, int)}. - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. + * Write the given 8 bits via {@link #writeBits31(int, int)}. * @return {@link #EOS} or the written 8bit value. * @throws IllegalStateException if not in output mode or stream closed * @throws IOException */ - public final int writeInt8(final boolean msbFirst, final byte int8) throws IllegalStateException, IOException { - if( 0 == bitCount && msbFirst ) { + public final int writeInt8(final byte int8) throws IllegalStateException, IOException { + if( 0 == bitCount && useFastPathTypes ) { // fast path if( !outputMode || null == bytes ) { throw new IllegalStateException("not in output-mode: "+this); @@ -1128,25 +1211,24 @@ public class Bitstream<T> { } return r; } else { - return this.writeBits31(msbFirst, 8, int8); + return this.writeBits31(8, int8); } } /** - * Return incoming <code>uint16_t</code> as read via {@link #readBits31(boolean, int)} - * and swap bytes if !bigEndian. + * Return incoming <code>uint16_t</code> as read via {@link #readBits31(int)} LSB-first as little-endian, + * hence bytes are swapped if bigEndian. * <p> * In case of a <code>int16_t</code> 2-complement signed value, simply cast the result to <code>short</code> * after checking for {@link #EOS}. * </p> - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. - * @param bigEndian if false, swap incoming bytes to little-endian, otherwise leave them as big-endian. + * @param bigEndian if true, swap incoming bytes to little-endian, otherwise leave them as little-endian. * @return {@link #EOS} or the 16bit unsigned value within the lower bits. * @throws IllegalStateException if not in input mode or stream closed * @throws IOException */ - public final int readUInt16(final boolean msbFirst, final boolean bigEndian) throws IllegalStateException, IOException { - if( 0 == bitCount && msbFirst ) { + public final int readUInt16(final boolean bigEndian) throws IllegalStateException, IOException { + if( 0 == bitCount && useFastPathTypes ) { // fast path if( outputMode || null == bytes ) { throw new IllegalStateException("not in input-mode: "+this); @@ -1164,21 +1246,21 @@ public class Bitstream<T> { return b2 << 8 | b1; } } else { - final int i16 = readBits31(msbFirst, 16); + final int i16 = readBits31(16); if( EOS == i16 ) { return EOS; } else if( bigEndian ) { - return i16; - } else { final int b1 = 0xff & ( i16 >>> 8 ); final int b2 = 0xff & i16; return b2 << 8 | b1; + } else { + return i16; } } } /** - * Return incoming <code>uint16_t</code> value and swap bytes if !bigEndian. + * Return incoming <code>uint16_t</code> value and swap bytes according to bigEndian. * <p> * In case of a <code>int16_t</code> 2-complement signed value, simply cast the result to <code>short</code>. * </p> @@ -1199,16 +1281,15 @@ public class Bitstream<T> { } /** - * Write the given 16 bits via {@link #writeBits31(boolean, int, int)}, - * while swapping bytes if !bigEndian beforehand. - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. - * @param bigEndian if false, swap given bytes to little-endian, otherwise leave them as big-endian. + * Write the given 16 bits via {@link #writeBits31(int, int)} LSB-first as little-endian, + * hence bytes are swapped if bigEndian. + * @param bigEndian if true, swap given bytes to little-endian, otherwise leave them as little-endian. * @return {@link #EOS} or the written 16bit value. * @throws IllegalStateException if not in output mode or stream closed * @throws IOException */ - public final int writeInt16(final boolean msbFirst, final boolean bigEndian, final short int16) throws IllegalStateException, IOException { - if( 0 == bitCount && msbFirst ) { + public final int writeInt16(final boolean bigEndian, final short int16) throws IllegalStateException, IOException { + if( 0 == bitCount && useFastPathTypes ) { // fast path if( !outputMode || null == bytes ) { throw new IllegalStateException("not in output-mode: "+this); @@ -1233,29 +1314,28 @@ public class Bitstream<T> { } return EOS; } else if( bigEndian ) { - return writeBits31(msbFirst, 16, int16); - } else { final int b1 = 0xff & ( int16 >>> 8 ); final int b2 = 0xff & int16; - return writeBits31(msbFirst, 16, b2 << 8 | b1); + return writeBits31(16, b2 << 8 | b1); + } else { + return writeBits31(16, int16); } } /** - * Return incoming <code>uint32_t</code> as read via {@link #readBits31(boolean, int)} - * and swap bytes if !bigEndian. + * Return incoming <code>uint32_t</code> as read via {@link #readBits31(int)} LSB-first as little-endian, + * hence bytes are swapped if bigEndian. * <p> * In case of a <code>int32_t</code> 2-complement signed value, simply cast the result to <code>int</code> * after checking for {@link #EOS}. * </p> - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. - * @param bigEndian if false, swap incoming bytes to little-endian, otherwise leave them as big-endian. + * @param bigEndian if true, swap incoming bytes to little-endian, otherwise leave them as little-endian. * @return {@link #EOS} or the 32bit unsigned value within the lower bits. * @throws IllegalStateException if not in input mode or stream closed * @throws IOException */ - public final long readUInt32(final boolean msbFirst, final boolean bigEndian) throws IllegalStateException, IOException { - if( 0 == bitCount && msbFirst ) { + public final long readUInt32(final boolean bigEndian) throws IllegalStateException, IOException { + if( 0 == bitCount && useFastPathTypes ) { // fast path if( outputMode || null == bytes ) { throw new IllegalStateException("not in input-mode: "+this); @@ -1275,24 +1355,24 @@ public class Bitstream<T> { return 0xffffffffL & ( b4 << 24 | b3 << 16 | b2 << 8 | b1 ); } } else { - final int i16a = readBits31(msbFirst, 16); - final int i16b = EOS != i16a ? readBits31(msbFirst, 16) : EOS; + final int i16a = readBits31(16); + final int i16b = EOS != i16a ? readBits31(16) : EOS; if( EOS == i16b ) { return EOS; } else if( bigEndian ) { - return 0xffffffffL & ( i16a << 16 | i16b ); - } else { - final int b1 = 0xff & ( i16a >>> 8 ); - final int b2 = 0xff & i16a; - final int b3 = 0xff & ( i16b >>> 8 ); - final int b4 = 0xff & i16b; + final int b1 = 0xff & ( i16b >>> 8 ); + final int b2 = 0xff & i16b; + final int b3 = 0xff & ( i16a >>> 8 ); + final int b4 = 0xff & i16a; return 0xffffffffL & ( b4 << 24 | b3 << 16 | b2 << 8 | b1 ); + } else { + return 0xffffffffL & ( i16b << 16 | i16a ); } } } /** - * Return incoming <code>uint32_t</code> and swap bytes if !bigEndian. + * Return incoming <code>uint32_t</code> and swap bytes according to bigEndian. * <p> * In case of a <code>int32_t</code> 2-complement signed value, simply cast the result to <code>int</code>. * </p> @@ -1314,16 +1394,15 @@ public class Bitstream<T> { } /** - * Write the given 32 bits via {@link #writeBits31(boolean, int, int)}, - * while swapping bytes if !bigEndian beforehand. - * @param msbFirst if true incoming stream bit order is MSB to LSB, otherwise LSB to MSB. - * @param bigEndian if false, swap given bytes to little-endian, otherwise leave them as little-endian. + * Write the given 32 bits via {@link #writeBits31(int, int)} LSB-first as little-endian, + * hence bytes are swapped if bigEndian. + * @param bigEndian if true, swap given bytes to little-endian, otherwise leave them as little-endian. * @return {@link #EOS} or the written 32bit value. * @throws IllegalStateException if not in output mode or stream closed * @throws IOException */ - public final int writeInt32(final boolean msbFirst, final boolean bigEndian, final int int32) throws IllegalStateException, IOException { - if( 0 == bitCount && msbFirst ) { + public final int writeInt32(final boolean bigEndian, final int int32) throws IllegalStateException, IOException { + if( 0 == bitCount && useFastPathTypes ) { // fast path if( !outputMode || null == bytes ) { throw new IllegalStateException("not in output-mode: "+this); @@ -1358,21 +1437,21 @@ public class Bitstream<T> { } return EOS; } else if( bigEndian ) { - final int hi = 0x0000ffff & ( int32 >>> 16 ); - final int lo = 0x0000ffff & int32 ; - if( EOS != writeBits31(msbFirst, 16, hi) ) { - if( EOS != writeBits31(msbFirst, 16, lo) ) { + final int p1 = 0xff & ( int32 >>> 24 ); + final int p2 = 0xff & ( int32 >>> 16 ); + final int p3 = 0xff & ( int32 >>> 8 ); + final int p4 = 0xff & int32 ; + if( EOS != writeBits31(16, p2 << 8 | p1) ) { + if( EOS != writeBits31(16, p4 << 8 | p3) ) { return int32; } } return EOS; } else { - final int p1 = 0xff & ( int32 >>> 24 ); - final int p2 = 0xff & ( int32 >>> 16 ); - final int p3 = 0xff & ( int32 >>> 8 ); - final int p4 = 0xff & int32 ; - if( EOS != writeBits31(msbFirst, 16, p4 << 8 | p3) ) { - if( EOS != writeBits31(msbFirst, 16, p2 << 8 | p1) ) { + final int hi = 0x0000ffff & ( int32 >>> 16 ); + final int lo = 0x0000ffff & int32 ; + if( EOS != writeBits31(16, lo) ) { + if( EOS != writeBits31(16, hi) ) { return int32; } } @@ -1429,22 +1508,52 @@ public class Bitstream<T> { bpos = bytes.position(); } return String.format("%s, pos %d [byteP %d, bitCnt %d], bitbuf %s", - mode, position(), bpos, bitCount, toHexBinString(bitBuffer, 8)); + mode, position(), bpos, bitCount, toHexBinString(true, bitBuffer, 8)); } private static final String strZeroPadding= "0000000000000000000000000000000000000000000000000000000000000000"; // 64 - public static String toBinString(final int v, final int bitCount) { + public static String toBinString(final boolean msbFirst, final int v, final int bitCount) { if( 0 == bitCount ) { return ""; } - final int mask = (int) ( ( 1L << bitCount ) - 1L ); - final String s0 = Integer.toBinaryString( mask & v ); - return strZeroPadding.substring(0, bitCount-s0.length())+s0; + if( msbFirst ) { + final int mask = (int) ( ( 1L << bitCount ) - 1L ); + final String s0 = Integer.toBinaryString( mask & v ); + return strZeroPadding.substring(0, bitCount-s0.length())+s0; + } else { + final char[] c = new char[32]; + for(int i=0; i<bitCount; i++) { + c[i] = 0 != ( v & ( 1 << i ) ) ? '1' : '0'; + } + final String s0 = new String(c, 0, bitCount); + return s0+strZeroPadding.substring(0, bitCount-s0.length()); + } } - public static String toHexBinString(final int v, final int bitCount) { + public static String toHexBinString(final boolean msbFirst, final int v, final int bitCount) { final int nibbles = 0 == bitCount ? 2 : ( bitCount + 3 ) / 4; - return String.format("[%0"+nibbles+"X, %s]", v, toBinString(v, bitCount)); + return String.format("[0x%0"+nibbles+"X, msbFirst %b, %s]", v, msbFirst, toBinString(msbFirst, v, bitCount)); + } + public static final String toHexBinString(final boolean msbFirst, final byte[] data, final int offset, final int len) { + final StringBuilder sb = new StringBuilder(); + sb.append("["); + for(int i=0; i<len; i++) { + final int v = 0xFF & data[offset+i]; + sb.append(toHexBinString(msbFirst, v, 8)).append(", "); + } + sb.append("]"); + return sb.toString(); } + public static final String toHexBinString(final boolean msbFirst, final ByteBuffer data, final int offset, final int len) { + final StringBuilder sb = new StringBuilder(); + sb.append("["); + for(int i=0; i<len; i++) { + final int v = 0xFF & data.get(offset+i); + sb.append(toHexBinString(msbFirst, v, 8)).append(", "); + } + sb.append("]"); + return sb.toString(); + } + public static void checkBounds(final byte[] sb, final int offset, final int remaining) throws IndexOutOfBoundsException { if( offset + remaining > sb.length ) { throw new IndexOutOfBoundsException("Buffer of size "+sb.length+" cannot hold offset "+offset+" + remaining "+remaining); diff --git a/src/junit/com/jogamp/common/util/TestBitstream00.java b/src/junit/com/jogamp/common/util/TestBitstream00.java index fa9c75d..920363b 100644 --- a/src/junit/com/jogamp/common/util/TestBitstream00.java +++ b/src/junit/com/jogamp/common/util/TestBitstream00.java @@ -129,6 +129,138 @@ public class TestBitstream00 extends SingletonJunitCase { } } + @Test + public void test10ReadWrite_13() throws UnsupportedOperationException, IllegalStateException, IOException { + // H->L : 00000011 00000010 00000001 000000110000001000000001 + // H->L rev: 10000000 01000000 11000000 100000000100000011000000 + // + // L->H : 00000001 00000010 00000011 000000010000001000000011 + // L->H rev: 11000000 01000000 10000000 110000000100000010000000 + test10ReadWrite1_31Impl(8, 8, 8, 0x030201, "000000110000001000000001"); + + // H->L: 00011 000010 00001 0001100001000001 + // L->H: 10000 010000 11000 1000001000011000 + test10ReadWrite1_31Impl(5, 6, 5, 0x1841, "0001100001000001"); + } + void test10ReadWrite1_31Impl(final int c1, final int c2, final int c3, final int v, final String vStrHigh2LowExp) + throws UnsupportedOperationException, IllegalStateException, IOException + { + // final Bitstream<ByteBuffer> source = new Bitstream<ByteBuffer>(); + final int bitCount = c1+c2+c3; + final int byteCount = ( bitCount + 7 ) / 8; + final String vStrHigh2Low0 = Bitstream.toBinString(true, v, bitCount); + System.err.printf("test10ReadWrite31 bits %d:%d:%d = %d = %d bytes%n", + c1, c2, c3, bitCount, byteCount); + System.err.printf("test10ReadWrite31 %s%n", Bitstream.toHexBinString(true, v, bitCount)); + System.err.printf("test10ReadWrite31 %s%n", Bitstream.toHexBinString(false, v, bitCount)); + Assert.assertEquals(vStrHigh2LowExp, vStrHigh2Low0); + + final ByteBuffer bbRead = ByteBuffer.allocate(byteCount); + for(int i=0; i<byteCount; i++) { + final int b = ( v >>> 8*i ) & 0xff; + bbRead.put(i, (byte) b); + System.err.printf("testBytes[%d]: %s%n", i, Bitstream.toHexBinString(true, b, 8)); + } + final Bitstream.ByteBufferStream bbsRead = new Bitstream.ByteBufferStream(bbRead); + final Bitstream<ByteBuffer> bsRead = new Bitstream<ByteBuffer>(bbsRead, false /* outputMode */); + + String vStrHigh2Low1C1 = ""; + String vStrHigh2Low1C2 = ""; + String vStrHigh2Low1C3 = ""; + String vStrHigh2Low1 = ""; + { + bsRead.mark(byteCount); + System.err.println("readBit (msbFirst false): "); + int b; + int i=0; + String vStrHigh2Low1T = ""; // OK for LSB, MSB segmented + while( Bitstream.EOS != ( b = bsRead.readBit(false /* msbFirst */) ) ) { + vStrHigh2Low1T = b + vStrHigh2Low1T; + if(i < c1) { + vStrHigh2Low1C1 = b + vStrHigh2Low1C1; + } else if(i < c1+c2) { + vStrHigh2Low1C2 = b + vStrHigh2Low1C2; + } else { + vStrHigh2Low1C3 = b + vStrHigh2Low1C3; + } + i++; + } + vStrHigh2Low1 = vStrHigh2Low1C3 + vStrHigh2Low1C2 + vStrHigh2Low1C1; + System.err.printf("readBit.1 %s, 0x%s%n", vStrHigh2Low1C1, Integer.toHexString(Integer.valueOf(vStrHigh2Low1C1, 2))); + System.err.printf("readBit.2 %s, 0x%s%n", vStrHigh2Low1C2, Integer.toHexString(Integer.valueOf(vStrHigh2Low1C2, 2))); + System.err.printf("readBit.3 %s, 0x%s%n", vStrHigh2Low1C3, Integer.toHexString(Integer.valueOf(vStrHigh2Low1C3, 2))); + System.err.printf("readBit.T %s, ok %b%n%n", vStrHigh2Low1T, vStrHigh2LowExp.equals(vStrHigh2Low1T)); + System.err.printf("readBit.X %s, ok %b%n%n", vStrHigh2Low1, vStrHigh2LowExp.equals(vStrHigh2Low1)); + bsRead.reset(); + } + + { + String vStrHigh2Low3T = ""; // OK for LSB, MSB segmented + System.err.println("readBits32: "); + final int b = bsRead.readBits31(bitCount); + vStrHigh2Low3T = Bitstream.toBinString(true, b, bitCount); + System.err.printf("readBits31.T %s, ok %b, %s%n%n", vStrHigh2Low3T, vStrHigh2LowExp.equals(vStrHigh2Low3T), Bitstream.toHexBinString(true, b, bitCount)); + bsRead.reset(); + } + + String vStrHigh2Low2 = ""; + { + System.err.println("readBits32: "); + final int bC1 = bsRead.readBits31(c1); + System.err.printf("readBits31.1 %s%n", Bitstream.toHexBinString(true, bC1, c1)); + final int bC2 = bsRead.readBits31(c2); + System.err.printf("readBits31.2 %s%n", Bitstream.toHexBinString(true, bC2, c2)); + final int bC3 = bsRead.readBits31(c3); + System.err.printf("readBits31.3 %s%n", Bitstream.toHexBinString(true, bC3, c3)); + final int b = bC3 << (c1+c2) | bC2 << c1 | bC1; + vStrHigh2Low2 = Bitstream.toBinString(true, b, bitCount); + System.err.printf("readBits31.X %s, ok %b, %s%n%n", vStrHigh2Low2, vStrHigh2LowExp.equals(vStrHigh2Low2), Bitstream.toHexBinString(true, b, bitCount)); + bsRead.reset(); + } + + Assert.assertEquals(vStrHigh2LowExp, vStrHigh2Low1); + Assert.assertEquals(vStrHigh2LowExp, vStrHigh2Low2); + + boolean ok = true; + { + final ByteBuffer bbWrite = ByteBuffer.allocate(byteCount); + final Bitstream.ByteBufferStream bbsWrite = new Bitstream.ByteBufferStream(bbWrite); + final Bitstream<ByteBuffer> bsWrite = new Bitstream<ByteBuffer>(bbsWrite, true /* outputMode */); + { + int b; + while( Bitstream.EOS != ( b = bsRead.readBit(false)) ) { + bsWrite.writeBit(false, b); + } + } + bsRead.reset(); + for(int i=0; i<byteCount; i++) { + final int bR = bbWrite.get(i); + final int bW = bbWrite.get(i); + System.err.printf("readWriteBit [%d]: read %s, write %s, ok %b%n", + i, Bitstream.toHexBinString(true, bR, 8), Bitstream.toHexBinString(true, bW, 8), bR==bW); + ok = ok && bR==bW; + } + Assert.assertTrue(ok); + } + { + final ByteBuffer bbWrite = ByteBuffer.allocate(byteCount); + final Bitstream.ByteBufferStream bbsWrite = new Bitstream.ByteBufferStream(bbWrite); + final Bitstream<ByteBuffer> bsWrite = new Bitstream<ByteBuffer>(bbsWrite, true /* outputMode */); + { + bsWrite.writeBits31(bitCount, bsRead.readBits31(bitCount)); + } + bsRead.reset(); + for(int i=0; i<byteCount; i++) { + final int bR = bbWrite.get(i); + final int bW = bbWrite.get(i); + System.err.printf("readWriteBits31[%d]: read %s, write %s, ok %b%n", + i, Bitstream.toHexBinString(true, bR, 8), Bitstream.toHexBinString(true, bW, 8), bR==bW); + ok = ok && bR==bW; + } + Assert.assertTrue(ok); + } + } + public static void main(final String args[]) throws IOException { final String tstname = TestBitstream00.class.getName(); org.junit.runner.JUnitCore.main(tstname); diff --git a/src/junit/com/jogamp/common/util/TestBitstream01.java b/src/junit/com/jogamp/common/util/TestBitstream01.java index 99116e6..49931a3 100644 --- a/src/junit/com/jogamp/common/util/TestBitstream01.java +++ b/src/junit/com/jogamp/common/util/TestBitstream01.java @@ -48,44 +48,67 @@ import org.junit.runners.MethodSorters; * <li>{@link Bitstream#mark(int)}</li> * <li>{@link Bitstream#reset()}</li> * <li>{@link Bitstream#flush()}</li> - * <li>{@link Bitstream#readBits31(boolean, int)}</li> - * <li>{@link Bitstream#writeBits31(boolean, int, int)}</li> + * <li>{@link Bitstream#readBits31(int)}</li> + * <li>{@link Bitstream#writeBits31(int, int)}</li> * </ul> */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestBitstream01 extends SingletonJunitCase { - Bitstream<ByteBuffer> getTestStream(final boolean msbFirst, final int preBits, final int skipBits, final int postBits) throws IOException { - final int byteCount = ( preBits + skipBits + postBits + 7 ) / 8; + Bitstream<ByteBuffer> getTestStream(final boolean msbFirstData, final boolean msbFirstWrite, + final int preBits, final int skipBits, final int postBits) throws IOException { + final int bitCount = preBits+skipBits+postBits; + final int byteCount = ( bitCount + 7 ) / 8; final ByteBuffer bbTest = ByteBuffer.allocate(byteCount); final Bitstream.ByteBufferStream bbsTest = new Bitstream.ByteBufferStream(bbTest); final Bitstream<ByteBuffer> bsTest = new Bitstream<ByteBuffer>(bbsTest, true /* outputMode */); final String sTest0; - if( msbFirst ) { + if( msbFirstData ) { sTest0 = testStringMSB.substring(0, preBits+skipBits+postBits); } else { sTest0 = testStringLSB.substring(0, preBits+skipBits+postBits); } - for(int i=0; i<preBits+skipBits+postBits; i++) { - final int bit = Integer.valueOf(sTest0.substring(i, i+1)); - bsTest.writeBit(msbFirst, bit); + if( msbFirstData == msbFirstWrite ) { + for(int i=0; i<bitCount; i++) { + final int bit = Integer.valueOf(sTest0.substring(i, i+1)); + bsTest.writeBit(msbFirstWrite, bit); + } + } else { + for(int i=bitCount-1; i >= 0; i--) { + final int bit = Integer.valueOf(sTest0.substring(i, i+1)); + bsTest.writeBit(msbFirstWrite, bit); + } } + System.err.printf("TestData: msbFirst[data %b, write %b], bits[pre %d, skip %d, post %d = %d]: <%s>%n", + msbFirstData, msbFirstWrite, preBits, skipBits, postBits, bitCount, sTest0); Assert.assertEquals(preBits+skipBits+postBits, bsTest.position()); bsTest.setStream(bsTest.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() + dumpData("TestData: ", bsTest.getSubStream(), 0, bsTest.getSubStream().limit()); return bsTest; } - String getTestStreamResultAsString(final boolean msbFirst, final int preBits, final int skipBits, final int postBits) { + String getTestStreamResultAsString(final boolean msbFirstData, final boolean msbFirstAssemble, + final int preBits, final int skipBits, final int postBits) { final String pre, post; - if( msbFirst ) { - pre = testStringMSB.substring(0, preBits); - post = testStringMSB.substring(preBits+skipBits, preBits+skipBits+postBits); + if( msbFirstData ) { + if( msbFirstAssemble ) { + pre = testStringMSB.substring(0, preBits); + post = testStringMSB.substring(preBits+skipBits, preBits+skipBits+postBits); + } else { + pre = testStringMSB.substring(postBits+skipBits, preBits+skipBits+postBits); + post = testStringMSB.substring(0, postBits); + } } else { - pre = testStringLSB.substring(0, preBits); - post = testStringLSB.substring(preBits+skipBits, preBits+skipBits+postBits); + if( msbFirstAssemble ) { + pre = testStringLSB.substring(0, preBits); + post = testStringLSB.substring(preBits+skipBits, preBits+skipBits+postBits); + } else { + pre = testStringMSB.substring(postBits+skipBits, preBits+skipBits+postBits); + post = testStringMSB.substring(0, postBits); + } } - final String r = pre + post; - System.err.println("Test: <"+pre+"> + <"+post+"> = <"+r+">"); + final String r = msbFirstAssemble ? pre + post : post + pre; + System.err.println("ResultExp: <"+pre+"> + <"+post+"> = <"+r+">"); return r; } @@ -155,9 +178,8 @@ public class TestBitstream01 extends SingletonJunitCase { // prepare bitstream System.err.println("Prepare bitstream"); - final Bitstream<ByteBuffer> bsTest = getTestStream(msbFirst, preBits, skipBits, postBits); - dumpData("Test", bsTest.getSubStream(), 0, bsTest.getSubStream().limit()); - final String sTest = getTestStreamResultAsString(msbFirst, preBits, skipBits, postBits); + final Bitstream<ByteBuffer> bsTest = getTestStream(msbFirst, msbFirst, preBits, skipBits, postBits); + final String sTest = getTestStreamResultAsString(msbFirst, true, preBits, skipBits, postBits); // init copy-bitstream final int byteCount = ( totalBits + 7 ) / 8; @@ -219,50 +241,48 @@ public class TestBitstream01 extends SingletonJunitCase { } @Test - public void test03BulkBitsMSBFirst() throws IOException { - testBulkBitsImpl(true); - } - @Test - public void test04BulkBitsLSBFirst() throws IOException { - testBulkBitsImpl(false); - } - void testBulkBitsImpl(final boolean msbFirst) throws IOException { - testBulkBitsImpl(msbFirst, 0, 0, 1); - testBulkBitsImpl(msbFirst, 0, 0, 3); - testBulkBitsImpl(msbFirst, 0, 0, 8); - testBulkBitsImpl(msbFirst, 0, 0, 10); - testBulkBitsImpl(msbFirst, 0, 0, 30); - testBulkBitsImpl(msbFirst, 0, 0, 31); - - testBulkBitsImpl(msbFirst, 3, 0, 3); - testBulkBitsImpl(msbFirst, 8, 0, 3); - testBulkBitsImpl(msbFirst, 9, 0, 3); - - testBulkBitsImpl(msbFirst, 0, 1, 1); - testBulkBitsImpl(msbFirst, 0, 1, 3); - testBulkBitsImpl(msbFirst, 0, 2, 8); - testBulkBitsImpl(msbFirst, 0, 8, 10); - testBulkBitsImpl(msbFirst, 0, 12, 20); - testBulkBitsImpl(msbFirst, 0, 23, 9); - testBulkBitsImpl(msbFirst, 0, 1, 31); - - testBulkBitsImpl(msbFirst, 1, 1, 1); - testBulkBitsImpl(msbFirst, 2, 1, 3); - testBulkBitsImpl(msbFirst, 7, 2, 8); - testBulkBitsImpl(msbFirst, 8, 8, 8); - testBulkBitsImpl(msbFirst, 15, 12, 5); - testBulkBitsImpl(msbFirst, 16, 11, 5); + public void test03BulkBits() throws IOException { + testBulkBitsImpl(0, 0, 1); + testBulkBitsImpl(0, 0, 3); + testBulkBitsImpl(0, 0, 8); + testBulkBitsImpl(0, 0, 10); + testBulkBitsImpl(0, 0, 30); + testBulkBitsImpl(0, 0, 31); + + testBulkBitsImpl(3, 0, 3); + testBulkBitsImpl(8, 0, 3); + testBulkBitsImpl(9, 0, 3); + testBulkBitsImpl(5, 0, 6); + testBulkBitsImpl(5, 0, 8); + + testBulkBitsImpl(0, 1, 1); + testBulkBitsImpl(3, 6, 4); + + testBulkBitsImpl(0, 1, 3); + testBulkBitsImpl(0, 2, 8); + testBulkBitsImpl(0, 8, 10); + testBulkBitsImpl(0, 12, 20); + testBulkBitsImpl(0, 23, 9); + testBulkBitsImpl(0, 1, 31); + + testBulkBitsImpl(1, 1, 1); + testBulkBitsImpl(2, 1, 3); + testBulkBitsImpl(7, 2, 8); + testBulkBitsImpl(8, 8, 8); + testBulkBitsImpl(15, 12, 5); + testBulkBitsImpl(16, 11, 5); + testBulkBitsImpl(5, 6, 5); + testBulkBitsImpl(5, 6, 8); } - void testBulkBitsImpl(final boolean msbFirst, final int preBits, final int skipBits, final int postBits) throws IOException { + void testBulkBitsImpl(final int preBits, final int skipBits, final int postBits) throws IOException { final int totalBits = preBits+skipBits+postBits; - System.err.println("XXX TestBulkBits: msbFirst "+msbFirst+", preBits "+preBits+", skipBits "+skipBits+", postBits "+postBits+", totalBits "+totalBits); + System.err.println("XXX TestBulkBits: preBits "+preBits+", skipBits "+skipBits+", postBits "+postBits+", totalBits "+totalBits); // prepare bitstream System.err.println("Prepare bitstream"); - final Bitstream<ByteBuffer> bsTest = getTestStream(msbFirst, preBits, skipBits, postBits); - dumpData("Test", bsTest.getSubStream(), 0, bsTest.getSubStream().limit()); - final String sTest = getTestStreamResultAsString(msbFirst, preBits, skipBits, postBits); + final Bitstream<ByteBuffer> bsTest = getTestStream(true, false, preBits, skipBits, postBits); + final String sTest = getTestStreamResultAsString(true, false, preBits, skipBits, postBits); // init copy-bitstream final int byteCount = ( totalBits + 7 ) / 8; @@ -273,18 +293,18 @@ public class TestBitstream01 extends SingletonJunitCase { // read-bitstream .. and copy bits while reading System.err.println("Reading bitstream: "+bsTest); { - final int readBitsPre = bsTest.readBits31(msbFirst, preBits); - Assert.assertEquals(readBitsPre, bsCopy.writeBits31(msbFirst, preBits, readBitsPre)); + final int readBitsPre = bsTest.readBits31(preBits); + Assert.assertEquals(readBitsPre, bsCopy.writeBits31(preBits, readBitsPre)); final int skippedReadBits = (int) bsTest.skip(skipBits); final int skippedBitsCopy = (int) bsCopy.skip(skipBits); - final int readBitsPost = bsTest.readBits31(msbFirst, postBits); - Assert.assertEquals(readBitsPost, bsCopy.writeBits31(msbFirst, postBits, readBitsPost)); - final String sReadPre = toBinaryString(readBitsPre, preBits); - final String sReadPost = toBinaryString(readBitsPost, postBits); - final String sRead = sReadPre + sReadPost; - System.err.println("Read.Test: <"+sReadPre+"> + <"+sReadPost+"> = <"+sRead+">"); + final int readBitsPost = bsTest.readBits31(postBits); + Assert.assertEquals(readBitsPost, bsCopy.writeBits31(postBits, readBitsPost)); + final String sReadPreLo = toBinaryString(readBitsPre, preBits); + final String sReadPostHi = toBinaryString(readBitsPost, postBits); + final String sRead = sReadPostHi + sReadPreLo; + System.err.println("Read.Test: <"+sReadPreLo+"> + <"+sReadPostHi+"> = <"+sRead+">"); Assert.assertEquals(skipBits, skippedReadBits); Assert.assertEquals(sTest, sRead); @@ -298,15 +318,15 @@ public class TestBitstream01 extends SingletonJunitCase { System.err.println("Reading copy-bitstream: "+bsCopy); Assert.assertEquals(0, bsCopy.position()); { - final int copyBitsPre = bsCopy.readBits31(msbFirst, preBits); + final int copyBitsPre = bsCopy.readBits31(preBits); final int skippedCopyBits = (int) bsCopy.skip(skipBits); - final int copyBitsPost = bsCopy.readBits31(msbFirst, postBits); - final String sCopyPre = toBinaryString(copyBitsPre, preBits); - final String sCopyPost = toBinaryString(copyBitsPost, postBits); - final String sCopy = sCopyPre + sCopyPost; - System.err.println("Copy.Test: <"+sCopyPre+"> + <"+sCopyPost+"> = <"+sCopy+">"); + final int copyBitsPost = bsCopy.readBits31(postBits); + final String sCopyPreLo = toBinaryString(copyBitsPre, preBits); + final String sCopyPostHi = toBinaryString(copyBitsPost, postBits); + final String sCopy = sCopyPostHi + sCopyPreLo; + System.err.println("Copy.Test: <"+sCopyPreLo+"> + <"+sCopyPostHi+"> = <"+sCopy+">"); Assert.assertEquals(skipBits, skippedCopyBits); Assert.assertEquals(sTest, sCopy); @@ -317,7 +337,7 @@ public class TestBitstream01 extends SingletonJunitCase { @Test public void test05ErrorHandling() throws IOException { // prepare bitstream - final Bitstream<ByteBuffer> bsTest = getTestStream(false, 0, 0, 0); + final Bitstream<ByteBuffer> bsTest = getTestStream(false, false, 0, 0, 0); System.err.println("01a: "+bsTest); bsTest.close(); System.err.println("01b: "+bsTest); diff --git a/src/junit/com/jogamp/common/util/TestBitstream02.java b/src/junit/com/jogamp/common/util/TestBitstream02.java index 3fb4cce..16904a2 100644 --- a/src/junit/com/jogamp/common/util/TestBitstream02.java +++ b/src/junit/com/jogamp/common/util/TestBitstream02.java @@ -71,17 +71,17 @@ public class TestBitstream02 extends SingletonJunitCase { final Bitstream.ByteBufferStream bbs = new Bitstream.ByteBufferStream(bb); final Bitstream<ByteBuffer> bs = new Bitstream<ByteBuffer>(bbs, false /* outputMode */); { - final byte r8 = (byte) bs.readUInt8(true /* msbFirst */); + final byte r8 = (byte) bs.readUInt8(); System.err.println("Read8.1 "+r8+", "+toHexBinaryString(r8, 8)); Assert.assertEquals(val8, r8); } // Test with written bitstream value bs.setStream(bs.getSubStream(), true /* outputMode */); - bs.writeInt8(true /* msbFirst */, val8); + bs.writeInt8(val8); bs.setStream(bs.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() { - final byte r8 = (byte) bs.readUInt8(true /* msbFirst */); + final byte r8 = (byte) bs.readUInt8(); System.err.println("Read8.2 "+r8+", "+toHexBinaryString(r8, 8)); Assert.assertEquals(val8, r8); } @@ -114,12 +114,12 @@ public class TestBitstream02 extends SingletonJunitCase { // Test with written bitstream value final Bitstream.ByteBufferStream bbs = new Bitstream.ByteBufferStream(bb); final Bitstream<ByteBuffer> bs = new Bitstream<ByteBuffer>(bbs, true /* outputMode */); - bs.writeBits31(true /* msbFirst */, preBits, 0); - bs.writeInt8(true /* msbFirst */, val8); + bs.writeBits31(preBits, 0); + bs.writeInt8(val8); bs.setStream(bs.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() - final int rPre = (short) bs.readBits31(true /* msbFirst */, preBits); - final byte r8 = (byte) bs.readUInt8(true /* msbFirst */); + final int rPre = (short) bs.readBits31(preBits); + final byte r8 = (byte) bs.readUInt8(); System.err.println("ReadPre "+rPre+", "+toBinaryString(rPre, preBits)); System.err.println("Read8 "+r8+", "+toHexBinaryString(r8, 8)); Assert.assertEquals(val8, r8); diff --git a/src/junit/com/jogamp/common/util/TestBitstream03.java b/src/junit/com/jogamp/common/util/TestBitstream03.java index 4dfb3d7..a6129d8 100644 --- a/src/junit/com/jogamp/common/util/TestBitstream03.java +++ b/src/junit/com/jogamp/common/util/TestBitstream03.java @@ -47,8 +47,8 @@ import org.junit.runners.MethodSorters; * Test {@link Bitstream} w/ int16 read/write access w/ semantics * as well as with aligned and unaligned access. * <ul> - * <li>{@link Bitstream#readUInt16(boolean, boolean)}</li> - * <li>{@link Bitstream#writeInt16(boolean, boolean, short)}</li> + * <li>{@link Bitstream#readUInt16(boolean)}</li> + * <li>{@link Bitstream#writeInt16(boolean, short)}</li> * </ul> */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -78,21 +78,23 @@ public class TestBitstream03 extends SingletonJunitCase { final boolean bigEndian = ByteOrder.BIG_ENDIAN == bb.order(); System.err.println("XXX Test01Int16BitsAligned: byteOrder "+byteOrder+" (bigEndian "+bigEndian+"), value "+val16+", "+toHexBinaryString(val16, 16)); bb.putShort(0, val16); + dumpData("TestData.1: ", bb, 0, 2); final Bitstream.ByteBufferStream bbs = new Bitstream.ByteBufferStream(bb); final Bitstream<ByteBuffer> bs = new Bitstream<ByteBuffer>(bbs, false /* outputMode */); { - final short r16 = (short) bs.readUInt16(true /* msbFirst */, bigEndian); + final short r16 = (short) bs.readUInt16(bigEndian); System.err.println("Read16.1 "+r16+", "+toHexBinaryString(r16, 16)); Assert.assertEquals(val16, r16); } // Test with written bitstream value bs.setStream(bs.getSubStream(), true /* outputMode */); - bs.writeInt16(true /* msbFirst */, bigEndian, val16); + bs.writeInt16(bigEndian, val16); bs.setStream(bs.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() + dumpData("TestData.2: ", bb, 0, 2); { - final short r16 = (short) bs.readUInt16(true /* msbFirst */, bigEndian); + final short r16 = (short) bs.readUInt16(bigEndian); System.err.println("Read16.2 "+r16+", "+toHexBinaryString(r16, 16)); Assert.assertEquals(val16, r16); } @@ -135,12 +137,13 @@ public class TestBitstream03 extends SingletonJunitCase { // Test with written bitstream value final Bitstream.ByteBufferStream bbs = new Bitstream.ByteBufferStream(bb); final Bitstream<ByteBuffer> bs = new Bitstream<ByteBuffer>(bbs, true /* outputMode */); - bs.writeBits31(true /* msbFirst */, preBits, 0); - bs.writeInt16(true /* msbFirst */, bigEndian, val16); + bs.writeBits31(preBits, 0); + bs.writeInt16(bigEndian, val16); bs.setStream(bs.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() + dumpData("TestData.1: ", bb, 0, byteCount); - final int rPre = (short) bs.readBits31(true /* msbFirst */, preBits); - final short r16 = (short) bs.readUInt16(true /* msbFirst */, bigEndian); + final int rPre = (short) bs.readBits31(preBits); + final short r16 = (short) bs.readUInt16(bigEndian); System.err.println("ReadPre "+rPre+", "+toBinaryString(rPre, preBits)); System.err.println("Read16 "+r16+", "+toHexBinaryString(r16, 16)); Assert.assertEquals(val16, r16); diff --git a/src/junit/com/jogamp/common/util/TestBitstream04.java b/src/junit/com/jogamp/common/util/TestBitstream04.java index 277510e..47be38d 100644 --- a/src/junit/com/jogamp/common/util/TestBitstream04.java +++ b/src/junit/com/jogamp/common/util/TestBitstream04.java @@ -47,8 +47,8 @@ import org.junit.runners.MethodSorters; * Test {@link Bitstream} w/ int32 read/write access w/ semantics * as well as with aligned and unaligned access. * <ul> - * <li>{@link Bitstream#readUInt32(boolean, boolean)}</li> - * <li>{@link Bitstream#writeInt32(boolean, boolean, int)}</li> + * <li>{@link Bitstream#readUInt32(boolean)}</li> + * <li>{@link Bitstream#writeInt32(boolean, int)}</li> * </ul> */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -82,11 +82,12 @@ public class TestBitstream04 extends SingletonJunitCase { System.err.println("XXX Test01Int32BitsAligned: "+val32+", "+val32_hs); bb.putInt(0, val32); + dumpData("TestData.1: ", bb, 0, 4); final Bitstream.ByteBufferStream bbs = new Bitstream.ByteBufferStream(bb); final Bitstream<ByteBuffer> bs = new Bitstream<ByteBuffer>(bbs, false /* outputMode */); { - final long uint32_l = bs.readUInt32(true /* msbFirst */, bigEndian); + final long uint32_l = bs.readUInt32(bigEndian); final int int32_l = (int)uint32_l; final String uint32_l_hs = toHexString(uint32_l); final int uint32_i = Bitstream.uint32LongToInt(uint32_l); @@ -99,10 +100,11 @@ public class TestBitstream04 extends SingletonJunitCase { // Test with written bitstream value bs.setStream(bs.getSubStream(), true /* outputMode */); - bs.writeInt32(true /* msbFirst */, bigEndian, val32); + bs.writeInt32(bigEndian, val32); bs.setStream(bs.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() + dumpData("TestData.2: ", bb, 0, 4); { - final long uint32_l = bs.readUInt32(true /* msbFirst */, bigEndian); + final long uint32_l = bs.readUInt32(bigEndian); final int int32_l = (int)uint32_l; final String uint32_l_hs = toHexString(uint32_l); final int uint32_i = Bitstream.uint32LongToInt(uint32_l); @@ -154,12 +156,12 @@ public class TestBitstream04 extends SingletonJunitCase { // Test with written bitstream value final Bitstream.ByteBufferStream bbs = new Bitstream.ByteBufferStream(bb); final Bitstream<ByteBuffer> bs = new Bitstream<ByteBuffer>(bbs, true /* outputMode */); - bs.writeBits31(true /* msbFirst */, preBits, 0); - bs.writeInt32(true /* msbFirst */, bigEndian, val32); + bs.writeBits31(preBits, 0); + bs.writeInt32(bigEndian, val32); bs.setStream(bs.getSubStream(), false /* outputMode */); // switch to input-mode, implies flush() - final int rPre = bs.readBits31(true /* msbFirst */, preBits); - final long uint32_l = bs.readUInt32(true /* msbFirst */, bigEndian); + final int rPre = bs.readBits31(preBits); + final long uint32_l = bs.readUInt32(bigEndian); final int int32_l = (int)uint32_l; final String uint32_l_hs = toHexString(uint32_l); final int uint32_i = Bitstream.uint32LongToInt(uint32_l); |