Skip to content

Commit 206fa28

Browse files
committed
#46 added MSB0_DIRECT mode to read and write bit fields without reverse
1 parent 4daea78 commit 206fa28

File tree

6 files changed

+351
-125
lines changed

6 files changed

+351
-125
lines changed

jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitInputStream.java

+52-23
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,8 @@ public byte readBitField(final JBBPBitNumber numOfBitsToRead) throws IOException
951951
* @throws IOException it will be thrown for transport errors to be read
952952
* @throws NullPointerException if number of bits to be read is null
953953
*/
954-
public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
954+
public int readBits(final JBBPBitNumber numOfBitsToRead)
955+
throws IOException {
955956
int result;
956957

957958
final int numOfBitsAsNumber = numOfBitsToRead.getBitNumber();
@@ -961,12 +962,14 @@ public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
961962
if (result >= 0) {
962963
this.byteCounter++;
963964
}
964-
return result;
965965
} else {
966966
result = 0;
967967

968968
if (numOfBitsAsNumber == this.bitsInBuffer) {
969969
result = this.bitBuffer;
970+
if (this.bitOrderMode == JBBPBitOrder.MSB0_DIRECT) {
971+
result >>>= this.bitsInBuffer;
972+
}
970973
this.bitBuffer = 0;
971974
this.bitsInBuffer = 0;
972975
this.byteCounter++;
@@ -979,37 +982,63 @@ public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
979982

980983
final boolean doIncCounter = theBitBufferCounter != 0;
981984

982-
while (i > 0) {
983-
if (theBitBufferCounter == 0) {
984-
if (doIncCounter) {
985-
this.byteCounter++;
986-
}
987-
final int nextByte = this.readByteFromStream();
988-
if (nextByte < 0) {
989-
if (i == numOfBitsAsNumber) {
990-
return nextByte;
985+
if (this.bitOrderMode == JBBPBitOrder.MSB0_DIRECT) {
986+
while (i > 0) {
987+
if (theBitBufferCounter == 0) {
988+
if (doIncCounter) {
989+
this.byteCounter++;
990+
}
991+
final int nextByte = this.readByteFromStream();
992+
if (nextByte < 0) {
993+
if (i == numOfBitsAsNumber) {
994+
return nextByte;
995+
} else {
996+
break;
997+
}
991998
} else {
992-
break;
999+
theBitBuffer = nextByte;
1000+
theBitBufferCounter = 8;
9931001
}
994-
} else {
995-
theBitBuffer = nextByte;
996-
theBitBufferCounter = 8;
9971002
}
1003+
1004+
result = (result << 1) | ((theBitBuffer >>> 7) & 1);
1005+
theBitBuffer = (theBitBuffer << 1) & 0xFF;
1006+
theBitBufferCounter--;
1007+
i--;
9981008
}
1009+
} else {
1010+
while (i > 0) {
1011+
if (theBitBufferCounter == 0) {
1012+
if (doIncCounter) {
1013+
this.byteCounter++;
1014+
}
1015+
final int nextByte = this.readByteFromStream();
1016+
if (nextByte < 0) {
1017+
if (i == numOfBitsAsNumber) {
1018+
return nextByte;
1019+
} else {
1020+
break;
1021+
}
1022+
} else {
1023+
theBitBuffer = nextByte;
1024+
theBitBufferCounter = 8;
1025+
}
1026+
}
9991027

1000-
result = (result << 1) | (theBitBuffer & 1);
1001-
theBitBuffer >>= 1;
1002-
theBitBufferCounter--;
1003-
i--;
1028+
result = (result << 1) | (theBitBuffer & 1);
1029+
theBitBuffer >>= 1;
1030+
theBitBufferCounter--;
1031+
i--;
1032+
}
1033+
result = JBBPUtils.reverseBitsInByte(JBBPBitNumber.decode(numOfBitsAsNumber - i),
1034+
(byte) result) &
1035+
0xFF;
10041036
}
10051037

10061038
this.bitBuffer = theBitBuffer;
10071039
this.bitsInBuffer = theBitBufferCounter;
1008-
1009-
return
1010-
JBBPUtils.reverseBitsInByte(JBBPBitNumber.decode(numOfBitsAsNumber - i), (byte) result) &
1011-
0xFF;
10121040
}
1041+
return result;
10131042
}
10141043

10151044
/**

jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOrder.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,12 @@ public enum JBBPBitOrder {
3131
* Least Significant Bit First means that the least significant bit will arrive first, the 0th bit will be read as the first one.
3232
* It is default order for Java.
3333
*/
34-
LSB0
34+
LSB0,
35+
/**
36+
* Most Significant Bit First means that the most significant bit will arrive first, the 7th bit will be read as the first one.
37+
* <b>In opposite to MSB0 it doesn't make reverse for data during read and write.</b>
38+
*
39+
* @since 3.0.1
40+
*/
41+
MSB0_DIRECT
3542
}

jbbp/src/main/java/com/igormaznitsa/jbbp/io/JBBPBitOutputStream.java

+46-28
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ public class JBBPBitOutputStream extends FilterOutputStream implements JBBPCount
3434
*/
3535
private final JBBPBitOrder bitOrderMode;
3636
/**
37-
* Inside bit buffer.
37+
* Internal bit buffer.
3838
*/
3939
private int bitBuffer;
4040
/**
41-
* Number of bits inside the bit buffer.
41+
* Number of bits buffered by the bit buffer.
4242
*/
4343
private int bitBufferCount;
4444
/**
@@ -58,7 +58,7 @@ public JBBPBitOutputStream(final OutputStream out) {
5858
/**
5959
* A Constructor.
6060
*
61-
* @param out an output stream to be filtered.
61+
* @param out an output stream to be filtered.
6262
* @param bitOrderMode a bit writing mode to used for writing operations.
6363
* @see JBBPBitOrder#LSB0
6464
* @see JBBPBitOrder#MSB0
@@ -211,17 +211,17 @@ public long getCounter() {
211211
}
212212

213213
/**
214-
* Get the inside bit buffer value.
214+
* Get the internal bit buffer value.
215215
*
216-
* @return the inside bit buffer value
216+
* @return the internal bit buffer value
217217
*/
218218
@Override
219219
public int getBitBuffer() {
220220
return this.bitBuffer;
221221
}
222222

223223
/**
224-
* Get the number of bits cached in the inside bit buffer.
224+
* Get the number of bits cached in the internal bit buffer.
225225
*
226226
* @return the number of cached bits in the bit buffer
227227
*/
@@ -278,29 +278,47 @@ public void write(final byte[] b) throws IOException {
278278
*/
279279
public void writeBits(final int value, final JBBPBitNumber bitNumber) throws IOException {
280280
if (this.bitBufferCount == 0 && bitNumber == JBBPBitNumber.BITS_8) {
281-
write(value);
281+
this.write(value);
282282
} else {
283-
final int initialMask;
284283
int mask;
285-
initialMask = 1;
286-
mask = initialMask << this.bitBufferCount;
287-
288284
int accumulator = value;
289285
int i = bitNumber.getBitNumber();
290286

291-
while (i > 0) {
292-
this.bitBuffer = this.bitBuffer | ((accumulator & 1) == 0 ? 0 : mask);
293-
accumulator >>= 1;
294-
295-
mask = mask << 1;
296-
297-
i--;
298-
this.bitBufferCount++;
299-
if (this.bitBufferCount == 8) {
300-
this.bitBufferCount = 0;
301-
writeByte(this.bitBuffer);
302-
mask = initialMask;
303-
this.bitBuffer = 0;
287+
if (this.bitOrderMode == JBBPBitOrder.MSB0_DIRECT) {
288+
final int initialMask = 0x80;
289+
mask = initialMask >> this.bitBufferCount;
290+
final int accumulatorMask = 1 << (bitNumber.getBitNumber() - 1);
291+
while (i > 0) {
292+
this.bitBuffer = this.bitBuffer | ((accumulator & accumulatorMask) == 0 ? 0 : mask);
293+
accumulator <<= 1;
294+
mask >>= 1;
295+
296+
i--;
297+
this.bitBufferCount++;
298+
if (this.bitBufferCount == 8) {
299+
this.bitBufferCount = 0;
300+
writeByte(this.bitBuffer);
301+
mask = initialMask;
302+
this.bitBuffer = 0;
303+
}
304+
}
305+
} else {
306+
final int initialMask = 1;
307+
mask = initialMask << this.bitBufferCount;
308+
while (i > 0) {
309+
this.bitBuffer = this.bitBuffer | ((accumulator & 1) == 0 ? 0 : mask);
310+
311+
accumulator >>= 1;
312+
mask = mask << 1;
313+
314+
i--;
315+
this.bitBufferCount++;
316+
if (this.bitBufferCount == 8) {
317+
this.bitBufferCount = 0;
318+
writeByte(this.bitBuffer);
319+
mask = initialMask;
320+
this.bitBuffer = 0;
321+
}
304322
}
305323
}
306324
}
@@ -328,7 +346,7 @@ public void align(final long alignByteNumber) throws IOException {
328346
}
329347

330348
/**
331-
* Inside method to write a byte into wrapped stream.
349+
* Internal method to write a byte into wrapped stream.
332350
*
333351
* @param value a byte value to be written
334352
* @throws IOException it will be thrown for transport problems
@@ -350,9 +368,9 @@ public void close() throws IOException {
350368
@Override
351369
public void write(final int value) throws IOException {
352370
if (this.bitBufferCount == 0) {
353-
writeByte(value);
371+
this.writeByte(value);
354372
} else {
355-
writeBits(value, JBBPBitNumber.BITS_8);
373+
this.writeBits(value, JBBPBitNumber.BITS_8);
356374
}
357375
}
358376

@@ -379,7 +397,7 @@ public void writeBytes(final byte[] array, final int length, final JBBPByteOrder
379397
}
380398

381399
/**
382-
* Reset the byte counter for the stream. The Inside bit buffer will be reset also.
400+
* Reset the byte counter for the stream. The internal bit buffer will be reset also.
383401
*/
384402
@Override
385403
public void resetCounter() {

0 commit comments

Comments
 (0)