|
|
@ -24,6 +24,7 @@
|
|
|
|
package io.nayuki.fastqrcodegen;
|
|
|
|
package io.nayuki.fastqrcodegen;
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final class BitBuffer {
|
|
|
|
final class BitBuffer {
|
|
|
@ -54,6 +55,16 @@ final class BitBuffer {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public byte[] getBytes() {
|
|
|
|
|
|
|
|
if (bitLength % 8 != 0)
|
|
|
|
|
|
|
|
throw new IllegalStateException("Data is not a whole number of bytes");
|
|
|
|
|
|
|
|
byte[] result = new byte[bitLength / 8];
|
|
|
|
|
|
|
|
for (int i = 0; i < result.length; i++)
|
|
|
|
|
|
|
|
result[i] = (byte)(data[i >>> 2] >>> (~i << 3));
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void appendBits(int val, int len) {
|
|
|
|
public void appendBits(int val, int len) {
|
|
|
|
if (len < 0 || len > 31 || val >>> len != 0)
|
|
|
|
if (len < 0 || len > 31 || val >>> len != 0)
|
|
|
|
throw new IllegalArgumentException("Value out of range");
|
|
|
|
throw new IllegalArgumentException("Value out of range");
|
|
|
@ -76,4 +87,35 @@ final class BitBuffer {
|
|
|
|
bitLength += len;
|
|
|
|
bitLength += len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void appendBits(int[] vals, int len) {
|
|
|
|
|
|
|
|
Objects.requireNonNull(vals);
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (len < 0 || len > vals.length * 32)
|
|
|
|
|
|
|
|
throw new IllegalArgumentException("Value out of range");
|
|
|
|
|
|
|
|
int wholeWords = len / 32;
|
|
|
|
|
|
|
|
int tailBits = len % 32;
|
|
|
|
|
|
|
|
if (tailBits > 0 && vals[wholeWords] << tailBits != 0)
|
|
|
|
|
|
|
|
throw new IllegalArgumentException("Last word must have low bits clear");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (bitLength + len > data.length * 32)
|
|
|
|
|
|
|
|
data = Arrays.copyOf(data, data.length * 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int shift = bitLength % 32;
|
|
|
|
|
|
|
|
if (shift == 0) {
|
|
|
|
|
|
|
|
System.arraycopy(vals, 0, data, bitLength / 32, (len + 31) / 32);
|
|
|
|
|
|
|
|
bitLength += len;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
for (int i = 0; i < wholeWords; i++) {
|
|
|
|
|
|
|
|
int word = vals[i];
|
|
|
|
|
|
|
|
data[bitLength >>> 5] |= word >>> shift;
|
|
|
|
|
|
|
|
bitLength += 32;
|
|
|
|
|
|
|
|
data[bitLength >>> 5] = word << (32 - shift);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tailBits > 0)
|
|
|
|
|
|
|
|
appendBits(vals[wholeWords] >>> (32 - tailBits), tailBits);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|