Inlined BitBuffer.getBytes() into its single usage (with simplification because the bit length is a multiple of 8) in most language versions, synchronized comment and variable name in Rust version.

This commit is contained in:
Project Nayuki 2018-10-06 04:44:03 +00:00
parent 8c262c00dd
commit c7bc281e18
9 changed files with 40 additions and 69 deletions

View File

@ -31,14 +31,6 @@ BitBuffer::BitBuffer()
: std::vector<bool>() {}
std::vector<std::uint8_t> BitBuffer::getBytes() const {
std::vector<std::uint8_t> result(size() / 8 + (size() % 8 == 0 ? 0 : 1));
for (std::size_t i = 0; i < size(); i++)
result[i >> 3] |= (*this)[i] ? 1 << (7 - (i & 7)) : 0;
return result;
}
void BitBuffer::appendBits(std::uint32_t val, int len) {
if (len < 0 || len > 31 || val >> len != 0)
throw std::domain_error("Value out of range");

View File

@ -41,12 +41,7 @@ class BitBuffer final : public std::vector<bool> {
/*---- Methods ----*/
// Returns a vector representing this buffer's bits packed into bytes in big endian. If the
// bit length isn't a multiple of 8, then the remaining bits of the final byte are all '0'.
public: std::vector<std::uint8_t> getBytes() const;
/*---- Method ----*/
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and val < 2^len.

View File

@ -109,8 +109,13 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
// Pack bits into bytes in big endian
vector<uint8_t> dataCodewords(bb.size() / 8);
for (size_t i = 0; i < bb.size(); i++)
dataCodewords[i >> 3] |= (bb.at(i) ? 1 : 0) << (7 - (i & 7));
// Create the QR Code object
return QrCode(version, ecl, bb.getBytes(), mask);
return QrCode(version, ecl, dataCodewords, mask);
}

View File

@ -77,21 +77,6 @@ public final class BitBuffer implements Cloneable {
}
/**
* Returns an array representing this buffer's bits packed into bytes in big endian. If the
* bit length isn't a multiple of 8, then the remaining bits of the final byte are all '0'.
* @return a new byte array (not {@code null}) representing this bit sequence
*/
public byte[] getBytes() {
byte[] result = new byte[(bitLength + 7) >>> 3]; // Round up to whole byte, won't overflow
for (int i = 0; i < bitLength; i++) {
if (data.get(i))
result[i >>> 3] |= 1 << (7 - (i & 7));
}
return result;
}
/**
* Appends the specified number of low-order bits of the specified value to this
* buffer. Requires 0 &#x2264; len &#x2264; 31 and 0 &#x2264; val &lt; 2<sup>len</sup>.

View File

@ -184,8 +184,13 @@ public final class QrCode {
for (int padByte = 0xEC; bb.bitLength() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
// Pack bits into bytes in big endian
byte[] dataCodewords = new byte[bb.bitLength() / 8];
for (int i = 0; i < bb.bitLength(); i++)
dataCodewords[i >>> 3] |= bb.getBit(i) << (7 - (i & 7));
// Create the QR Code object
return new QrCode(version, ecl, bb.getBytes(), mask);
return new QrCode(version, ecl, dataCodewords, mask);
}

View File

@ -617,8 +617,16 @@ var qrcodegen = new function() {
for (var padByte = 0xEC; bb.length < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
// Pack bits into bytes in big endian
var dataCodewords = [];
while (dataCodewords.length * 8 < bb.length)
dataCodewords.push(0);
bb.forEach(function(bit, i) {
dataCodewords[i >>> 3] |= bit << (7 - (i & 7));
});
// Create the QR Code object
return new this(version, ecl, bb.getBytes(), mask);
return new this(version, ecl, dataCodewords, mask);
};
@ -996,18 +1004,6 @@ var qrcodegen = new function() {
function BitBuffer() {
Array.call(this);
// Returns a new array representing this buffer's bits packed into bytes in big endian. If the
// bit length isn't a multiple of 8, then the remaining bits of the final byte are all '0'.
this.getBytes = function() {
var result = [];
while (result.length * 8 < this.length)
result.push(0);
this.forEach(function(bit, i) {
result[i >>> 3] |= bit << (7 - (i & 7));
});
return result;
};
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
this.appendBits = function(val, len) {

View File

@ -154,8 +154,13 @@ class QrCode(object):
break
bb.append_bits(padbyte, 8)
# Pack bits into bytes in big endian
datacodewords = [0] * (len(bb) // 8)
for (i, bit) in enumerate(bb):
datacodewords[i >> 3] |= bit << (7 - (i & 7))
# Create the QR Code object
return QrCode(version, ecl, bb.get_bytes(), mask)
return QrCode(version, ecl, datacodewords, mask)
# ---- Constructor (low level) ----
@ -872,14 +877,6 @@ class _ReedSolomonGenerator(object):
class _BitBuffer(list):
"""An appendable sequence of bits (0s and 1s). Mainly used by QrSegment."""
def get_bytes(self):
"""Returns a new list representing this buffer's bits packed into bytes in big endian. If the
bit length isn't a multiple of 8, then the remaining bits of the final byte are all '0'."""
result = [0] * ((len(self) + 7) // 8)
for (i, bit) in enumerate(self):
result[i >> 3] |= bit << (7 - (i & 7))
return result
def append_bits(self, val, n):
"""Appends the given number of low-order bits of the given
value to this buffer. Requires n >= 0 and 0 <= val < 2^n."""

View File

@ -182,13 +182,14 @@ impl QrCode {
bb.append_bits(*padbyte, 8);
}
let mut bytes = vec![0u8; bb.0.len() / 8];
// Pack bits into bytes in big endian
let mut datacodewords = vec![0u8; bb.0.len() / 8];
for (i, bit) in bb.0.iter().enumerate() {
bytes[i >> 3] |= (*bit as u8) << (7 - (i & 7));
datacodewords[i >> 3] |= (*bit as u8) << (7 - (i & 7));
}
// Create the QR Code object
Some(QrCode::encode_codewords(version, ecl, &bytes, mask))
Some(QrCode::encode_codewords(version, ecl, &datacodewords, mask))
}

View File

@ -137,8 +137,15 @@ namespace qrcodegen {
for (let padByte = 0xEC; bb.length < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
// Pack bits into bytes in big endian
let dataCodewords: Array<byte> = [];
while (dataCodewords.length * 8 < bb.length)
dataCodewords.push(0);
bb.forEach((b: bit, i: int) =>
dataCodewords[i >>> 3] |= b << (7 - (i & 7)));
// Create the QR Code object
return new QrCode(version, ecl, bb.getBytes(), mask);
return new QrCode(version, ecl, dataCodewords, mask);
}
@ -928,18 +935,6 @@ namespace qrcodegen {
*/
class BitBuffer extends Array<bit> {
// Returns a new array representing this buffer's bits packed into bytes in big endian. If the
// bit length isn't a multiple of 8, then the remaining bits of the final byte are all '0'.
public getBytes(): Array<byte> {
let result: Array<byte> = [];
while (result.length * 8 < this.length)
result.push(0);
this.forEach((b: bit, i: int) =>
result[i >>> 3] |= b << (7 - (i & 7)));
return result;
}
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
public appendBits(val: int, len: int): void {