Skip to content

Commit 1526228

Browse files
committed
added returnAccumulatedForBitReadInEof flag into JBBPBitInputStream to change default behaviour for missing bit data part in the end of a stream
1 parent d6cf2fd commit 1526228

File tree

2 files changed

+88
-46
lines changed

2 files changed

+88
-46
lines changed

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

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public class JBBPBitInputStream extends FilterInputStream implements JBBPCountab
4040
*/
4141
protected static final int INITIAL_ARRAY_BUFFER_SIZE =
4242
JBBPSystemProperty.PROPERTY_INPUT_INITIAL_ARRAY_BUFFER_SIZE.getAsInteger(32);
43+
/**
44+
* Allow return accumulated data during met end of stream and missing part of bits field data.
45+
* @since 3.1.0
46+
*/
47+
private final boolean returnAccumulatedForBitReadInEof;
4348
/**
4449
* Contains bit mode for bit operations.
4550
*/
@@ -68,7 +73,6 @@ public class JBBPBitInputStream extends FilterInputStream implements JBBPCountab
6873
* Internal temp variable to keep the byte counter temporarily.
6974
*/
7075
private long markedByteCounter;
71-
7276
/**
7377
* Internal flag shows that read stopped for whole stream array read limit reach.
7478
*
@@ -77,48 +81,84 @@ public class JBBPBitInputStream extends FilterInputStream implements JBBPCountab
7781
private boolean detectedArrayLimit;
7882

7983
/**
80-
* Flag shows that read of array was stopped for array limiter restrictions.
81-
*
82-
* @return true if array limiter restrictions detected, false otherwise
83-
* @see JBBPArraySizeLimiter
84-
* @since 2.1.0
85-
*/
86-
public boolean isDetectedArrayLimit() {
87-
return this.detectedArrayLimit;
88-
}
89-
90-
/**
91-
* Set value for array limit detected flag. It is important to set the flag for correct processing of parsing.
84+
* A Constructor, the LSB0 bit order will be used by default.
85+
* <b>By default, if missing part of bit field in the end of stream then current accumulated data will be returned.</b>
9286
*
93-
* @param value true or false.
94-
* @see com.igormaznitsa.jbbp.JBBPParser
95-
* @since 2.1.0
87+
* @param in an input stream to be filtered.
9688
*/
97-
public void setDetectedArrayLimit(final boolean value) {
98-
this.detectedArrayLimit = value;
89+
public JBBPBitInputStream(final InputStream in) {
90+
this(in, JBBPBitOrder.LSB0);
9991
}
10092

10193
/**
10294
* A Constructor, the LSB0 bit order will be used by default.
10395
*
104-
* @param in an input stream to be filtered.
96+
* @param in an input stream to be filtered.
97+
* @param returnAccumulatedForBitReadInEof if true then end of stream during bit read and some data missing returns accumulated data.
10598
*/
106-
public JBBPBitInputStream(final InputStream in) {
107-
this(in, JBBPBitOrder.LSB0);
99+
public JBBPBitInputStream(final InputStream in, final boolean returnAccumulatedForBitReadInEof) {
100+
this(in, JBBPBitOrder.LSB0, returnAccumulatedForBitReadInEof);
108101
}
109102

110103
/**
111104
* A Constructor.
105+
* <b>By default, if missing part of bit field in the end of stream then current accumulated data will be returned.</b>
112106
*
113107
* @param in an input stream to be filtered.
114108
* @param order a bit order mode for the filter.
115109
* @see JBBPBitOrder#LSB0
116110
* @see JBBPBitOrder#MSB0
117111
*/
118112
public JBBPBitInputStream(final InputStream in, final JBBPBitOrder order) {
113+
this(in, order, true);
114+
}
115+
116+
/**
117+
* Create wrapping bit input stream.
118+
*
119+
* @param in the base input stream, must not be null
120+
* @param order a bit order mode for the filter.
121+
* @param returnAccumulatedForBitReadInEof if true then end of stream during bit read and some data missing returns accumulated data.
122+
* @since 3.1.0
123+
*/
124+
public JBBPBitInputStream(final InputStream in, final JBBPBitOrder order,
125+
final boolean returnAccumulatedForBitReadInEof) {
119126
super(in);
120127
this.bitsInBuffer = 0;
121128
this.bitOrderMode = order;
129+
this.returnAccumulatedForBitReadInEof = returnAccumulatedForBitReadInEof;
130+
}
131+
132+
/**
133+
* If true then the bit stream returns currently accumulated data for bit read if end of stream and not whole bit data read, -1 otherwise.
134+
*
135+
* @return boolean flag for the behavior, true if allowed
136+
* @since 3.1.0
137+
*/
138+
public boolean isReturnAccumulatedForBitReadInEof() {
139+
return this.returnAccumulatedForBitReadInEof;
140+
}
141+
142+
/**
143+
* Flag shows that read of array was stopped for array limiter restrictions.
144+
*
145+
* @return true if array limiter restrictions detected, false otherwise
146+
* @see JBBPArraySizeLimiter
147+
* @since 2.1.0
148+
*/
149+
public boolean isDetectedArrayLimit() {
150+
return this.detectedArrayLimit;
151+
}
152+
153+
/**
154+
* Set value for array limit detected flag. It is important to set the flag for correct processing of parsing.
155+
*
156+
* @param value true or false.
157+
* @see com.igormaznitsa.jbbp.JBBPParser
158+
* @since 2.1.0
159+
*/
160+
public void setDetectedArrayLimit(final boolean value) {
161+
this.detectedArrayLimit = value;
122162
}
123163

124164
/**
@@ -198,7 +238,7 @@ public boolean[] readBoolArray(final int items,
198238

199239
@Override
200240
public int read(final byte[] array, final int offset, final int length) throws IOException {
201-
return this.read(array, offset, length, true);
241+
return this.read(array, offset, length, this.returnAccumulatedForBitReadInEof);
202242
}
203243

204244
/**
@@ -210,13 +250,13 @@ public int read(final byte[] array, final int offset, final int length) throws I
210250
* @param array target array
211251
* @param offset offset in the target array
212252
* @param length the length of data portion to be read
213-
* @param allowEofForMissingBitData if true then allow to stop read if missing data for non-complete read bits operation.
253+
* @param returnAccumulatedForBitReadInEof if true then return accumulated data if end of stream during bit read, return -1 otherwise.
214254
* @return number of read bytes from the wrapped input stream
215255
* @throws IOException thrown if any transport error
216-
* @since 3.0.1
256+
* @since 3.1.0
217257
*/
218258
public int read(final byte[] array, final int offset, final int length,
219-
final boolean allowEofForMissingBitData) throws IOException {
259+
final boolean returnAccumulatedForBitReadInEof) throws IOException {
220260
if (this.bitsInBuffer == 0) {
221261
int readBytes = 0;
222262
int tempOffset = offset;
@@ -248,7 +288,7 @@ public int read(final byte[] array, final int offset, final int length,
248288
int count = length;
249289
int i = offset;
250290
while (count > 0) {
251-
final int nextByte = this.readBits(JBBPBitNumber.BITS_8, allowEofForMissingBitData);
291+
final int nextByte = this.readBits(JBBPBitNumber.BITS_8, returnAccumulatedForBitReadInEof);
252292
if (nextByte < 0) {
253293
break;
254294
}
@@ -383,7 +423,7 @@ private byte[] internalReadArray(
383423
byte[] buffer = new byte[INITIAL_ARRAY_BUFFER_SIZE];
384424
// till end
385425
while (true) {
386-
final int next = readByteArray ? read() : this.readBits(bitNumber, true);
426+
final int next = readByteArray ? read() : this.readBits(bitNumber, this.returnAccumulatedForBitReadInEof);
387427
if (next < 0) {
388428
break;
389429
}
@@ -415,7 +455,7 @@ private byte[] internalReadArray(
415455
}
416456
} else {
417457
for (int i = 0; i < items; i++) {
418-
final int next = this.readBits(bitNumber, true);
458+
final int next = this.readBits(bitNumber, this.returnAccumulatedForBitReadInEof);
419459
if (next < 0) {
420460
throw new EOFException("Have read only " + i + " bit portions instead of " + items);
421461
}
@@ -951,7 +991,7 @@ public JBBPBitOrder getBitOrder() {
951991
* @since 1.3.0
952992
*/
953993
public byte readBitField(final JBBPBitNumber numOfBitsToRead) throws IOException {
954-
final int value = this.readBits(numOfBitsToRead, true);
994+
final int value = this.readBits(numOfBitsToRead, this.returnAccumulatedForBitReadInEof);
955995
if (value < 0) {
956996
throw new EOFException("Can't read bits from stream [" + numOfBitsToRead + ']');
957997
}
@@ -971,7 +1011,7 @@ public byte readBitField(final JBBPBitNumber numOfBitsToRead) throws IOException
9711011
* @throws NullPointerException if number of bits to be read is null
9721012
*/
9731013
public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
974-
return this.readBits(numOfBitsToRead, false);
1014+
return this.readBits(numOfBitsToRead, this.returnAccumulatedForBitReadInEof);
9751015
}
9761016

9771017
/**
@@ -980,13 +1020,13 @@ public int readBits(final JBBPBitNumber numOfBitsToRead) throws IOException {
9801020
* Behaviour in case of missing bit data can be tuned by the special argument flag and if it is true then -1 returned otherwise current accumulated bit data returned.
9811021
*
9821022
* @param numOfBitsToRead the number of bits to be read, must be 1..8
983-
* @param allowEofForMissingBitData if false then returned current accumulated data as stream ended with missing bits, -1 otherwise
1023+
* @param returnAccumulatedForBitReadInEof if false then returned current accumulated data as stream ended with missing bits, -1 otherwise
9841024
* @return the read bits as integer, -1 if the end of stream has been reached or if allowed end of stream flag and not all bits read.
9851025
* @throws IOException it will be thrown for transport errors to be read
9861026
* @throws NullPointerException if number of bits to be read is null
9871027
* @since 3.0.1
9881028
*/
989-
public int readBits(final JBBPBitNumber numOfBitsToRead, final boolean allowEofForMissingBitData)
1029+
public int readBits(final JBBPBitNumber numOfBitsToRead, final boolean returnAccumulatedForBitReadInEof)
9901030
throws IOException {
9911031
int result;
9921032

@@ -1028,12 +1068,12 @@ public int readBits(final JBBPBitNumber numOfBitsToRead, final boolean allowEofF
10281068
if (i == numOfBitsAsNumber) {
10291069
return nextByte;
10301070
} else {
1031-
if (allowEofForMissingBitData) {
1071+
if (returnAccumulatedForBitReadInEof) {
1072+
break;
1073+
} else {
10321074
this.bitBuffer = 0;
10331075
this.bitsInBuffer = 0;
10341076
return -1;
1035-
} else {
1036-
break;
10371077
}
10381078
}
10391079
} else {
@@ -1058,12 +1098,12 @@ public int readBits(final JBBPBitNumber numOfBitsToRead, final boolean allowEofF
10581098
if (i == numOfBitsAsNumber) {
10591099
return nextByte;
10601100
} else {
1061-
if (allowEofForMissingBitData) {
1101+
if (returnAccumulatedForBitReadInEof) {
1102+
break;
1103+
} else {
10621104
this.bitBuffer = 0;
10631105
this.bitsInBuffer = 0;
10641106
return -1;
1065-
} else {
1066-
break;
10671107
}
10681108
}
10691109
} else {

jbbp/src/test/java/com/igormaznitsa/jbbp/io/JBBPBitInputStreamTest.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,9 +1614,10 @@ public void testReadBooleanArray_WholeStream() throws Exception {
16141614
}
16151615

16161616
@Test
1617-
public void testReadNotFullByteArrayAfterBitReading() throws Exception {
1617+
public void testReadNotFullByteArrayAfterBitReading_disableAccumulatedBitsOnEof()
1618+
throws Exception {
16181619
final JBBPBitInputStream in = new JBBPBitInputStream(
1619-
new ByteArrayInputStream(str2bin("00010010_00110100_01010110_11011101")));
1620+
new ByteArrayInputStream(str2bin("00010010_00110100_01010110_11011101")), false);
16201621
assertEquals(0x2, in.readBits(BITS_4));
16211622
assertEquals(0, in.getCounter());
16221623

@@ -1634,10 +1635,11 @@ public void testReadNotFullByteArrayAfterBitReading() throws Exception {
16341635
}
16351636

16361637
@Test
1637-
public void testReadNotFullByteArrayAfterBitReading_MSB0() throws Exception {
1638+
public void testReadNotFullByteArrayAfterBitReading_MSB0_disableAccumulatedBitsOnEof()
1639+
throws Exception {
16381640
final JBBPBitInputStream in = new JBBPBitInputStream(
16391641
new ByteArrayInputStream(str2bin("00010010_00110100_01010110_11011101")),
1640-
JBBPBitOrder.MSB0);
1642+
JBBPBitOrder.MSB0, false);
16411643
assertEquals(0x8, in.readBits(BITS_4));
16421644
assertEquals(0, in.getCounter());
16431645

@@ -1655,31 +1657,31 @@ public void testReadNotFullByteArrayAfterBitReading_MSB0() throws Exception {
16551657
}
16561658

16571659
@Test
1658-
public void testReadNotFullByteArrayAfterBitReading_disableEofForMissingBitData()
1660+
public void testReadNotFullByteArrayAfterBitReading()
16591661
throws Exception {
16601662
final JBBPBitInputStream in = new JBBPBitInputStream(
16611663
new ByteArrayInputStream(new byte[] {(byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xDD}));
16621664
assertEquals(0x2, in.readBits(BITS_4));
16631665
assertEquals(0, in.getCounter());
16641666

16651667
final byte[] readarray = new byte[6];
1666-
final int read = in.read(readarray, 0, readarray.length, false);
1668+
final int read = in.read(readarray, 0, readarray.length, true);
16671669
assertEquals(4, read);
16681670
assertEquals(4, in.getCounter());
16691671
assertArrayEquals(new byte[] {(byte) 0x41, (byte) 0x63, (byte) 0xD5, (byte) 0x0D, 0, 0},
16701672
readarray);
16711673
}
16721674

16731675
@Test
1674-
public void testReadNotFullByteArrayAfterBitReading_MSB0_disableEofForMissingBitData()
1676+
public void testReadNotFullByteArrayAfterBitReading_MSB0()
16751677
throws Exception {
16761678
final JBBPBitInputStream in = new JBBPBitInputStream(
16771679
new ByteArrayInputStream(new byte[] {(byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0xDD}),
16781680
JBBPBitOrder.MSB0);
16791681
assertEquals(0x8, in.readBits(BITS_4));
16801682

16811683
final byte[] readarray = new byte[6];
1682-
final int read = in.read(readarray, 0, readarray.length, false);
1684+
final int read = in.read(readarray, 0, readarray.length);
16831685

16841686
assertEquals(4, read);
16851687
assertEquals(4, in.getCounter());

0 commit comments

Comments
 (0)