Ported over the BitVector bug fix and new unit test from Satoru.

git-svn-id: https://zxing.googlecode.com/svn/trunk@742 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
dswitkin 2008-11-20 17:08:30 +00:00
parent 56f194794b
commit a8d732d084
3 changed files with 44 additions and 4 deletions

View file

@ -52,10 +52,8 @@ public final class BitVector {
}
// Return the number of bytes in the bit vector.
// JAVAPORT: I would have made this ((sizeInBits + 7) >> 3), but apparently users of this class
// depend on the number of bytes being rounded down. I don't see how that works though.
public int num_bytes() {
return sizeInBits >> 3;
return (sizeInBits + 7) >> 3;
}
// Append one bit to the bit vector.

View file

@ -101,11 +101,15 @@ public class BitVectorTestCase extends TestCase {
BitVector v = new BitVector();
assertEquals(0, v.num_bytes());
v.AppendBit(0);
assertEquals(0, v.num_bytes());
// 1 bit was added in the vector, so 1 byte should be consumed.
assertEquals(1, v.num_bytes());
v.AppendBits(0, 7);
assertEquals(1, v.num_bytes());
v.AppendBits(0, 8);
assertEquals(2, v.num_bytes());
v.AppendBits(0, 1);
// We now have 17 bits, so 3 bytes should be consumed.
assertEquals(3, v.num_bytes());
}
public void testAppendBitVector() {

View file

@ -607,4 +607,42 @@ public final class EncoderTestCase extends TestCase {
assertFalse(Encoder.IsValidKanjiSequence(new ByteArray("0123")));
assertFalse(Encoder.IsValidKanjiSequence(new ByteArray("ABC")));
}
public void testBugInBitVectorNumBytes() throws WriterException {
// There was a bug in BitVector::num_bytes() that caused it to return a
// smaller-by-one value (ex. 1465 instead of 1466) if the number of bits
// in the vector is not 8-bit aligned. In QRCodeEncoder::InitQRCode(),
// BitVector::num_bytes() is used for finding the smallest QR Code
// version that can fit the given data. Hence there were corner cases
// where we chose a wrong QR Code version that cannot fit the given
// data. Note that the issue did not occur with MODE_8BIT_BYTE, as the
// bits in the bit vector are always 8-bit aligned.
//
// Before the bug was fixed, the following test didn't pass, because:
//
// - MODE_NUMERIC is chosen as all bytes in the data are '0'
// - The 3518-byte numeric data needs 1466 bytes
// - 3518 / 3 * 10 + 7 = 11727 bits = 1465.875 bytes
// - 3 numeric bytes are encoded in 10 bits, hence the first
// 3516 bytes are encoded in 3516 / 3 * 10 = 11720 bits.
// - 2 numeric bytes can be encoded in 7 bits, hence the last
// 2 bytes are encoded in 7 bits.
// - The version 27 QR Code with the EC level L has 1468 bytes for data.
// - 1828 - 360 = 1468
// - In InitQRCode(), 3 bytes are reserved for a header. Hence 1465 bytes
// (1468 -3) are left for data.
// - Because of the bug in BitVector::num_bytes(), InitQRCode() determines
// the given data can fit in 1465 bytes, despite it needs 1466 bytes.
// - Hence QRCodeEncoder::Encode() failed and returned false.
// - To be precise, it needs 11727 + 4 (mode info) + 14 (length info) =
// 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468
// bytes).
final int arraySize = 3518;
byte[] data_bytes = new byte[arraySize];
for (int x = 0; x < arraySize; x++) {
data_bytes[x] = '0';
}
QRCode qr_code = new QRCode();
Encoder.Encode(new ByteArray(data_bytes), QRCode.EC_LEVEL_L, qr_code);
}
}