src/bits.lisp @ 84fa1724b747 default tip
More work on the Huffman encoder and basic project skeleton
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Sun, 26 Jul 2020 16:49:17 -0400 |
| parents | 716d1110c12f |
| children | (none) |
(in-package :tdcb) ;;;; Struct ------------------------------------------------------------------- (defstruct (bits (:constructor make-bits% (underlying-stream)) (:conc-name nil)) (underlying-stream nil :type stream :read-only t) (rack 0 :type (unsigned-byte 8)) (mask #b10000000 :type (unsigned-byte 8))) (declaim (inline write-bit% read-bit%)) ;;;; Write -------------------------------------------------------------------- (defun write-bit% (b bit) (declare (type bits b)) (when (plusp bit) (logiorf (rack b) (mask b))) (when (zerop (ashf (mask b) -1)) (write-byte (rack b) (underlying-stream b)) (setf (rack b) 0 (mask b) #b10000000))) (defun write-bit (b bit) (write-bit% b bit) bit) (defun write-bits (b byte count) (loop :with mask = (ash 1 (1- count)) :until (zerop mask) :do (progn (write-bit% b (logand mask byte)) (ashf mask -1))) byte) (defun write-octet (b octet) (write-bits b octet 8)) (defun write-octets (b sequence) (map nil (lambda (octet) (write-bits b octet 8)) sequence)) (defun flush (b) (unless (= (mask b) #x80) (write-byte (rack b) (underlying-stream b)))) ;;;; Read --------------------------------------------------------------------- (defun read-bit% (b) (declare (type bits b)) (when (= (mask b) #b10000000) (setf (rack b) (read-byte (underlying-stream b)))) (prog1 (if (zerop (logand (mask b) (rack b))) 0 1) (when (zerop (ashf (mask b) -1)) (setf (mask b) #b10000000)))) (defun read-bit (b) (read-bit% b)) (defun read-bits (b count) (loop :with result = 0 :with mask = (ash 1 (1- count)) :until (zerop mask) :do (progn (when (plusp (read-bit b)) (logiorf result mask)) (ashf mask -1)) :finally (return result))) (defun read-octet (b) (read-bits b 8)) (defun read-octets (b count) (iterate (with result = (make-array count)) (for i :from 0 :below count) (setf (aref result i) (read-octet b)) (returning result))) ;;;; Create ------------------------------------------------------------------- (defmacro with-bits-output ((var stream) &body body) `(let ((,var (make-bits% ,stream))) (unwind-protect (progn ,@body) (flush ,var)))) (defmacro with-bits-input ((var stream) &body body) `(let ((,var (make-bits% ,stream))) ,@body))