725fdf7522c8

Use a struct instead
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 18 Jul 2020 22:46:32 -0400
parents adcbdf9b281a
children 3835748a929e
branches/tags (none)
files src/bit-streams.lisp tdcb.asd

Changes

--- a/src/bit-streams.lisp	Sat Jul 18 22:27:52 2020 -0400
+++ b/src/bit-streams.lisp	Sat Jul 18 22:46:32 2020 -0400
@@ -1,95 +1,72 @@
 (in-package :tdcb)
 
-;;;; Common -------------------------------------------------------------------
-(defclass bit-stream (trivial-gray-streams:fundamental-binary-stream)
-  ((underlying-stream :accessor underlying-stream :initarg :underlying-stream :type stream)
-   (rack :accessor rack :type (unsigned-byte 8) :initform 0)
-   (mask :accessor mask :type (unsigned-byte 8) :initform #b10000000)))
+;;;; 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)))
 
-(defmethod close ((stream bit-stream) &key abort)
-  (when (open-stream-p (underlying-stream stream))
-    (close (underlying-stream stream) :abort abort)))
-
-(defmethod stream-element-type ((stream bit-stream))
-  'bit)
-
-(defmethod stream-file-position ((stream bit-stream))
-  (error "Cannot change position of a bit stream."))
+(declaim (inline write-bit% read-bit%))
 
 
-;;;; Output -------------------------------------------------------------------
-(defclass bit-output-stream (bit-stream trivial-gray-streams:fundamental-binary-output-stream) ())
-
-(defun make-bit-output-stream (stream)
-  (make-instance 'bit-output-stream :underlying-stream stream))
-
+;;;; 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)))
 
-(declaim (inline write-bit%))
-(defun write-bit% (stream bit)
-  (when (plusp bit)
-    (logiorf (rack stream) (mask stream)))
-  (when (zerop (ashf (mask stream) -1))
-    (write-byte (rack stream) (underlying-stream stream))
-    (setf (rack stream) 0
-          (mask stream) #b10000000)))
-(defun write-bits (stream byte &optional (count 1))
+(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% stream (logand mask byte))
+        :do (progn (write-bit% b (logand mask byte))
                    (ashf mask -1)))
   byte)
 
-
-(defmethod trivial-gray-streams:stream-write-byte ((stream bit-output-stream) bit)
-  (write-bit% stream bit))
-
-(defmethod close ((stream bit-output-stream) &key abort)
-  (declare (ignore abort))
-  (unless (= (mask stream) #b10000000)
-    (write-byte (rack stream) (underlying-stream stream)))
-  (call-next-method))
-
-(with-open-stream (s (make-bit-output-stream *standard-output*)) (write-byte #b00101010 s))
+(defun flush (b)
+  (unless (= (mask b) #x80)
+    (write-byte (rack b) (underlying-stream b))))
 
 
-;;;; Input -------------------------------------------------------------------
-(defclass bit-input-stream (bit-stream trivial-gray-streams:fundamental-binary-input-stream) ())
-
-(defun make-bit-input-stream (stream)
-  (make-instance 'bit-input-stream :underlying-stream stream))
-
-
-(declaim (inline read-bit))
-(defun read-bit (stream)
-  (when (= (mask stream) #b10000000)
-    (setf (rack stream) (read-byte (underlying-stream stream))))
-  (prog1 (if (zerop (logand (mask stream) (rack stream)))
+;;;; 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 stream) -1))
-      (setf (mask stream) #b10000000))))
+    (when (zerop (ashf (mask b) -1))
+      (setf (mask b) #b10000000))))
 
-(defun read-bits (stream count)
+(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 stream))
+        :do (progn (when (plusp (read-bit b))
                      (logiorf result mask))
                    (ashf mask -1))
         :finally (return result)))
 
 
-(defmethod trivial-gray-streams:stream-read-byte ((stream bit-input-stream))
-  (read-bit stream))
-
-
-#; Scratch --------------------------------------------------------------------
+;;;; Create -------------------------------------------------------------------
+(defmacro with-bits-output ((var stream) &body body)
+  `(let ((,var (make-bits% ,stream)))
+     (unwind-protect (progn ,@body)
+       (flush ,var))))
 
-(defparameter *o* (make-bit-output-stream *standard-output*))
+(defmacro with-bits-input ((var stream) &body body)
+  `(let ((,var (make-bits% ,stream)))
+     ,@body))
 
-(defparameter *s* (flexi-streams:make-in-memory-input-stream #(#b00101010 #b01010100)))
-(defparameter *i* (make-bit-input-stream *s*))
-
-(losh:bits (read-bits *i* 4))
-
-(read-byte *s*)
--- a/tdcb.asd	Sat Jul 18 22:27:52 2020 -0400
+++ b/tdcb.asd	Sat Jul 18 22:46:32 2020 -0400
@@ -4,7 +4,7 @@
 
   :license "MIT"
 
-  :depends-on (:trivial-gray-streams)
+  :depends-on ()
 
   :serial t
   :components ((:module "src" :serial t