Bit Reader

Most data sent over the wire, is formated in bits, but given as bytes.

Implementing the bit stream boils down to four simple statements:

  • You keep a buffer, no smaller than 32 bits
  • When filling the buffer, you write to the left
  • When filling the buffer, you fill byte by byte.
  • When consuming from the buffer, you read from the right.

Pseudo Code

def fill
    while offset < N
        buffer |= next() << offset
        offset += 8
        
def consume
    if offset < N then fill
    
    mask = (2 ^ N) - 1
    value = buffer & mask
    buffer >>= N
    offset -= N
    
    return value
    

Optimisations

Precompute, (hopefully with constant expressions and compile-time optimization) the masks for consuming.

Reading bytes can be improved by checking if the reader is currently "byte aligned".

  • This can be done by checking if your offset is zero, e.g. no stored bits. (offset == 0)
  • The benefit of which, is skipping the cost of filling then draining the buffer every time.