Note: This is taken from the Chicken Wiki, where a more recent version could be available.



Simple parsing of binary data.


Oleg Kiselyov






If you want bignum support (ie, if the numbers egg is available), you can use:

 (require-extension big-binary-parse)

Otherwise, the following can be used:

 (require-extension binary-parse)


<procedure>(make-bit-reader BYTE-READER)</procedure>

Given a BYTE-READER (a thunk), construct and return a function (bit-reader N) that reads N bits from a byte-stream represented by the BYTE-READER. The BYTE-READER is a function that takes no arguments and returns the current byte as an exact integer [0-255]. The byte reader should return #f on EOF.

The bit reader returns N bits as an exact unsigned integer, 0 -... (no limit). N must be a positive integer, otherwise the bit reader returns #f. There is no upper limit on N – other than the size of the input stream itself and the amount of (virtual) memory an OS is willing to give to your process. If you want to read 1M of _bits_, go ahead.

It is assumed that the bit order is the most-significant bit first.

Note the bit reader keeps the following condition true at all times:

 (= current-inport-pos (ceiling (/ no-bits-read 8)))

That is, no byte is read until the very moment we really need (some of) its bits. The bit reader does not "byte read ahead". Therefore, it can be used to handle a concatenation of different bit/byte streams strictly sequentially, without "backing up a char", "unreading-char" etc. tricks.

Thus careful attention to byte-buffering and optimization are the features of this bit reader.

Usage example

<example> <init>(use binary-parse)</init> (define bit-reader (make-bit-reader (lambda () #b11000101)))

<expr>(bit-reader 3)</expr> <result>6</result> <expr>(bit-reader 4)</expr> <result>2</result> </example>

Notes on the algorithm.

The function recognizes and handles the following special cases: