Skip to content

Instantly share code, notes, and snippets.

@cosinekitty
Created April 28, 2020 21:52
Show Gist options
  • Select an option

  • Save cosinekitty/5730ba897400e8b7d9cf3952433c6b69 to your computer and use it in GitHub Desktop.

Select an option

Save cosinekitty/5730ba897400e8b7d9cf3952433c6b69 to your computer and use it in GitHub Desktop.
BitBuffer class for converting variable-length bit strings to Base64 on the fly
class BitBuffer:
def __init__(self):
self.buf = bytearray()
self.accum = 0
self.nbits = 0
self.column = 0
def Append(self, pattern):
data, dbits = pattern
while self.nbits + dbits >= 6:
# We can emit a complete base64 character to represent a chunk of 6 bits.
grab = 6 - self.nbits
mask = (1 << grab) - 1
self.accum = (self.accum << grab) | (mask & (data >> (dbits - grab)))
dbits -= grab
self.buf.append(b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'[self.accum])
self.accum = 0
self.nbits = 0
self.column += 1
if self.column == 80:
self.buf.append(ord('\n'))
self.column = 0
# Transfer any residual data bits into the accumulator.
if dbits >= 0:
mask = (1 << dbits) - 1
self.accum = (self.accum << dbits) | (mask & data)
self.nbits += dbits
def Format(self):
# Flush any remaining bits left in the accumulator.
if self.nbits > 0:
self.Append((0, (6 - self.nbits)))
# Always end on a newline.
if self.column > 0:
self.buf.append(ord('\n'))
self.column = 0
# Convert the bytes to utf-8 text.
return self.buf.decode('utf-8')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment