Simplified Python code by making BitBuffer subclass list, updated internal usages.

This commit is contained in:
Project Nayuki 2017-08-17 20:03:19 +00:00
parent ac10dc21ce
commit a341901d94
1 changed files with 16 additions and 34 deletions

View File

@ -120,18 +120,18 @@ class QrCode(object):
for seg in segs: for seg in segs:
bb.append_bits(seg.get_mode().get_mode_bits(), 4) bb.append_bits(seg.get_mode().get_mode_bits(), 4)
bb.append_bits(seg.get_num_chars(), seg.get_mode().num_char_count_bits(version)) bb.append_bits(seg.get_num_chars(), seg.get_mode().num_char_count_bits(version))
bb.append_all(seg) bb.extend(seg._bitdata)
# Add terminator and pad up to a byte if applicable # Add terminator and pad up to a byte if applicable
bb.append_bits(0, min(4, datacapacitybits - bb.bit_length())) bb.append_bits(0, min(4, datacapacitybits - len(bb)))
bb.append_bits(0, -bb.bit_length() % 8) # Note: Python's modulo on negative numbers behaves better than C family languages bb.append_bits(0, -len(bb) % 8) # Note: Python's modulo on negative numbers behaves better than C family languages
# Pad with alternate bytes until data capacity is reached # Pad with alternate bytes until data capacity is reached
for padbyte in itertools.cycle((0xEC, 0x11)): for padbyte in itertools.cycle((0xEC, 0x11)):
if bb.bit_length() >= datacapacitybits: if len(bb) >= datacapacitybits:
break break
bb.append_bits(padbyte, 8) bb.append_bits(padbyte, 8)
assert bb.bit_length() % 8 == 0 assert len(bb) % 8 == 0
# Create the QR Code symbol # Create the QR Code symbol
return QrCode(None, bb.get_bytes(), mask, version, ecl) return QrCode(None, bb.get_bytes(), mask, version, ecl)
@ -619,7 +619,7 @@ class QrSegment(object):
bb = _BitBuffer() bb = _BitBuffer()
for b in data: for b in data:
bb.append_bits(b, 8) bb.append_bits(b, 8)
return QrSegment(QrSegment.Mode.BYTE, len(data), bb.get_bits()) return QrSegment(QrSegment.Mode.BYTE, len(data), bb)
@staticmethod @staticmethod
@ -633,7 +633,7 @@ class QrSegment(object):
rem = len(digits) % 3 rem = len(digits) % 3
if rem > 0: # 1 or 2 digits remaining if rem > 0: # 1 or 2 digits remaining
bb.append_bits(int(digits[-rem : ]), rem * 3 + 1) bb.append_bits(int(digits[-rem : ]), rem * 3 + 1)
return QrSegment(QrSegment.Mode.NUMERIC, len(digits), bb.get_bits()) return QrSegment(QrSegment.Mode.NUMERIC, len(digits), bb)
@staticmethod @staticmethod
@ -649,7 +649,7 @@ class QrSegment(object):
bb.append_bits(temp, 11) bb.append_bits(temp, 11)
if len(text) % 2 > 0: # 1 character remaining if len(text) % 2 > 0: # 1 character remaining
bb.append_bits(QrSegment._ALPHANUMERIC_ENCODING_TABLE[text[-1]], 6) bb.append_bits(QrSegment._ALPHANUMERIC_ENCODING_TABLE[text[-1]], 6)
return QrSegment(QrSegment.Mode.ALPHANUMERIC, len(text), bb.get_bits()) return QrSegment(QrSegment.Mode.ALPHANUMERIC, len(text), bb)
@staticmethod @staticmethod
@ -685,7 +685,7 @@ class QrSegment(object):
bb.append_bits(assignval, 21) bb.append_bits(assignval, 21)
else: else:
raise ValueError("ECI assignment value out of range") raise ValueError("ECI assignment value out of range")
return QrSegment(QrSegment.Mode.ECI, 0, bb.get_bits()) return QrSegment(QrSegment.Mode.ECI, 0, bb)
# ---- Constructor ---- # ---- Constructor ----
@ -721,7 +721,7 @@ class QrSegment(object):
# Fail if segment length value doesn't fit in the length field's bit-width # Fail if segment length value doesn't fit in the length field's bit-width
if seg.get_num_chars() >= (1 << ccbits): if seg.get_num_chars() >= (1 << ccbits):
return None return None
result += 4 + ccbits + len(seg.get_bits()) result += 4 + ccbits + len(seg._bitdata)
return result return result
@ -828,25 +828,13 @@ class _ReedSolomonGenerator(object):
class _BitBuffer(object): class _BitBuffer(list):
"""An appendable sequence of bits. Bits are packed in big endian within a byte.""" """An appendable sequence of bits (0's and 1's)."""
def __init__(self):
"""Creates an empty bit buffer (length 0)."""
self.data = [] # Only contains 0s and 1s
def bit_length(self):
"""Returns the number of bits in the buffer, which is a non-negative value."""
return len(self.data)
def get_bits(self):
"""Returns a copy of all bits."""
return list(self.data)
def get_bytes(self): def get_bytes(self):
"""Returns a copy of all bytes, padding up to the nearest byte.""" """Returns a copy of all bytes, padding up to the nearest byte. Bits are packed in big endian within a byte."""
result = [0] * ((len(self.data) + 7) // 8) result = [0] * ((len(self) + 7) // 8)
for (i, bit) in enumerate(self.data): for (i, bit) in enumerate(self):
result[i >> 3] |= bit << (7 - (i & 7)) result[i >> 3] |= bit << (7 - (i & 7))
return result return result
@ -854,10 +842,4 @@ class _BitBuffer(object):
"""Appends the given number of bits of the given value to this sequence. This requires 0 <= val < 2^n.""" """Appends the given number of bits of the given value to this sequence. This requires 0 <= val < 2^n."""
if n < 0 or val >> n != 0: if n < 0 or val >> n != 0:
raise ValueError("Value out of range") raise ValueError("Value out of range")
self.data.extend(((val >> i) & 1) for i in reversed(range(n))) self.extend(((val >> i) & 1) for i in reversed(range(n)))
def append_all(self, seg):
"""Appends the data of the given segment to this bit buffer."""
if not isinstance(seg, QrSegment):
raise TypeError("QrSegment expected")
self.data.extend(seg.get_bits())