Simplified pieces of code (#601)

* Simplify code in bit-twiddling methods, using APIs introduced in Java 5.

* Align code by adjusting whitespace and adding `+0`.

* Convert qrcode DataMask to enum to reduce source code size, which shouldn't change behavior.

* Simplify lists of character constants using string initializer instead of array.

* Remove redundant `+ 0` operations from a recent change.

* Delete the function DataMask.forReference() and inline the logic into all its callers.
This commit is contained in:
Nayuki 2016-05-25 11:46:44 +00:00 committed by Sean Owen
parent c2eb20d976
commit 7cf49565c2
9 changed files with 110 additions and 160 deletions

View file

@ -64,15 +64,11 @@ final class DecodedBitStreamParser {
private static final int PS = 29;
private static final int PAL = 29;
private static final char[] PUNCT_CHARS = {
';', '<', '>', '@', '[', '\\', ']', '_', '`', '~', '!',
'\r', '\t', ',', ':', '\n', '-', '.', '$', '/', '"', '|', '*',
'(', ')', '?', '{', '}', '\''};
private static final char[] PUNCT_CHARS =
";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'".toCharArray();
private static final char[] MIXED_CHARS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&',
'\r', '\t', ',', ':', '#', '-', '.', '$', '/', '+', '%', '*',
'=', '^'};
private static final char[] MIXED_CHARS =
"0123456789&\r\t,:#-.$/+%*=^".toCharArray();
private static final Charset DEFAULT_ENCODING = Charset.forName("ISO-8859-1");

View file

@ -157,7 +157,7 @@ final class BitMatrixParser {
// Get the data mask for the format used in this QR Code. This will exclude
// some bits from reading as we wind through the bit matrix.
DataMask dataMask = DataMask.forReference(formatInfo.getDataMask());
DataMask dataMask = DataMask.values()[formatInfo.getDataMask()];
int dimension = bitMatrix.getHeight();
dataMask.unmaskBitMatrix(bitMatrix, dimension);
@ -211,7 +211,7 @@ final class BitMatrixParser {
if (parsedFormatInfo == null) {
return; // We have no format information, and have no data mask
}
DataMask dataMask = DataMask.forReference(parsedFormatInfo.getDataMask());
DataMask dataMask = DataMask.values()[parsedFormatInfo.getDataMask()];
int dimension = bitMatrix.getHeight();
dataMask.unmaskBitMatrix(bitMatrix, dimension);
}

View file

@ -29,24 +29,96 @@ import com.google.zxing.common.BitMatrix;
*
* @author Sean Owen
*/
abstract class DataMask {
enum DataMask {
/**
* See ISO 18004:2006 6.8.1
*/
private static final DataMask[] DATA_MASKS = {
new DataMask000(),
new DataMask001(),
new DataMask010(),
new DataMask011(),
new DataMask100(),
new DataMask101(),
new DataMask110(),
new DataMask111(),
/**
* 000: mask bits for which (x + y) mod 2 == 0
*/
DATA_MASK_000() {
@Override
boolean isMasked(int i, int j) {
return ((i + j) & 0x01) == 0;
}
},
/**
* 001: mask bits for which x mod 2 == 0
*/
DATA_MASK_001() {
@Override
boolean isMasked(int i, int j) {
return (i & 0x01) == 0;
}
},
/**
* 010: mask bits for which y mod 3 == 0
*/
DATA_MASK_010() {
@Override
boolean isMasked(int i, int j) {
return j % 3 == 0;
}
},
/**
* 011: mask bits for which (x + y) mod 3 == 0
*/
DATA_MASK_011() {
@Override
boolean isMasked(int i, int j) {
return (i + j) % 3 == 0;
}
},
/**
* 100: mask bits for which (x/2 + y/3) mod 2 == 0
*/
DATA_MASK_100() {
@Override
boolean isMasked(int i, int j) {
return (((i / 2) + (j /3)) & 0x01) == 0;
}
},
/**
* 101: mask bits for which xy mod 2 + xy mod 3 == 0
*/
DATA_MASK_101() {
@Override
boolean isMasked(int i, int j) {
int temp = i * j;
return (temp & 0x01) + (temp % 3) == 0;
}
},
/**
* 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0
*/
DATA_MASK_110() {
@Override
boolean isMasked(int i, int j) {
int temp = i * j;
return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
}
},
/**
* 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0
*/
DATA_MASK_111() {
@Override
boolean isMasked(int i, int j) {
return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0;
}
};
private DataMask() {
}
// End of enum constants.
/**
* <p>Implementations of this method reverse the data masking process applied to a QR Code and
@ -67,97 +139,4 @@ abstract class DataMask {
abstract boolean isMasked(int i, int j);
/**
* @param reference a value between 0 and 7 indicating one of the eight possible
* data mask patterns a QR Code may use
* @return DataMask encapsulating the data mask pattern
*/
static DataMask forReference(int reference) {
if (reference < 0 || reference > 7) {
throw new IllegalArgumentException();
}
return DATA_MASKS[reference];
}
/**
* 000: mask bits for which (x + y) mod 2 == 0
*/
private static final class DataMask000 extends DataMask {
@Override
boolean isMasked(int i, int j) {
return ((i + j) & 0x01) == 0;
}
}
/**
* 001: mask bits for which x mod 2 == 0
*/
private static final class DataMask001 extends DataMask {
@Override
boolean isMasked(int i, int j) {
return (i & 0x01) == 0;
}
}
/**
* 010: mask bits for which y mod 3 == 0
*/
private static final class DataMask010 extends DataMask {
@Override
boolean isMasked(int i, int j) {
return j % 3 == 0;
}
}
/**
* 011: mask bits for which (x + y) mod 3 == 0
*/
private static final class DataMask011 extends DataMask {
@Override
boolean isMasked(int i, int j) {
return (i + j) % 3 == 0;
}
}
/**
* 100: mask bits for which (x/2 + y/3) mod 2 == 0
*/
private static final class DataMask100 extends DataMask {
@Override
boolean isMasked(int i, int j) {
return (((i / 2) + (j /3)) & 0x01) == 0;
}
}
/**
* 101: mask bits for which xy mod 2 + xy mod 3 == 0
*/
private static final class DataMask101 extends DataMask {
@Override
boolean isMasked(int i, int j) {
int temp = i * j;
return (temp & 0x01) + (temp % 3) == 0;
}
}
/**
* 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0
*/
private static final class DataMask110 extends DataMask {
@Override
boolean isMasked(int i, int j) {
int temp = i * j;
return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
}
}
/**
* 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0
*/
private static final class DataMask111 extends DataMask {
@Override
boolean isMasked(int i, int j) {
return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0;
}
}
}

View file

@ -42,12 +42,8 @@ final class DecodedBitStreamParser {
/**
* See ISO 18004:2006, 6.4.4 Table 5
*/
private static final char[] ALPHANUMERIC_CHARS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
' ', '$', '%', '*', '+', '-', '.', '/', ':'
};
private static final char[] ALPHANUMERIC_CHARS =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".toCharArray();
private static final int GB2312_SUBSET = 1;
private DecodedBitStreamParser() {

View file

@ -66,12 +66,6 @@ final class FormatInformation {
{0x2BED, 0x1F},
};
/**
* Offset i holds the number of 1 bits in the binary representation of i
*/
private static final int[] BITS_SET_IN_HALF_BYTE =
{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
private final ErrorCorrectionLevel errorCorrectionLevel;
private final byte dataMask;
@ -83,17 +77,7 @@ final class FormatInformation {
}
static int numBitsDiffering(int a, int b) {
a ^= b; // a now has a 1 bit exactly where its bit differs with b's
// Count bits set quickly with a series of lookups:
return
BITS_SET_IN_HALF_BYTE[a & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 4) & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 8) & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 12) & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 16) & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 20) & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 24) & 0x0F] +
BITS_SET_IN_HALF_BYTE[(a >>> 28) & 0x0F];
return Integer.bitCount(a ^ b);
}
/**

View file

@ -271,12 +271,7 @@ final class MatrixUtil {
// - findMSBSet(1) => 1
// - findMSBSet(255) => 8
static int findMSBSet(int value) {
int numDigits = 0;
while (value != 0) {
value >>>= 1;
++numDigits;
}
return numDigits;
return 32 - Integer.numberOfLeadingZeros(value);
}
// Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH

View file

@ -106,7 +106,7 @@ public final class DataMaskTestCase extends Assert {
}
private static void testMaskAcrossDimensions(int reference, MaskCondition condition) {
DataMask mask = DataMask.forReference(reference);
DataMask mask = DataMask.values()[reference];
for (int version = 1; version <= 40; version++) {
int dimension = 17 + 4 * version;
testMask(mask, dimension, condition);