Simple parsing of binary data.
If you want bignum support (ie, if the numbers egg is available), you can use:
Otherwise, the following can be used:
make-bit-reader[procedure] (make-bit-reader BYTE-READER)
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.
(use binary-parse) (define bit-reader (make-bit-reader (lambda () #b11000101))) (bit-reader 3) => 6 (bit-reader 4) => 2
Notes on the algorithm.
The function recognizes and handles the following special cases:
- The buffer is empty and 8, 16, 24 bits are to be read
- Reading all bits which are currently in the byte-buffer (and then maybe more)
- Reading only one bit
- 1.2 Port to chicken 4
- 1.1 When numbers extension is available, a bignum-aware version is additionally built
- 1.0 Initial release