r5238: *** empty log message ***
[kmrcl.git] / byte-stream.lisp
diff --git a/byte-stream.lisp b/byte-stream.lisp
new file mode 100644 (file)
index 0000000..36f77e7
--- /dev/null
@@ -0,0 +1,230 @@
+;;; -*- Syntax: Ansi-Common-Lisp; Base: 10; Mode: lisp; Package: kmrcl -*-
+;;;; *************************************************************************
+;;;; FILE IDENTIFICATION
+;;;;
+;;;; Name:          byte-stream.lisp
+;;;; Purpose:       Byte array input/output streams
+;;;; Programmer:    Kevin M. Rosenberg
+;;;; Date Started:  June 2003
+;;;;
+;;;; $Id: byte-stream.lisp,v 1.1 2003/07/05 02:32:08 kevin Exp $
+;;;;
+;;;; Works for CMUCL, SBCL, and AllergoCL only
+;;;;
+;;;; This file, part of KMRCL, is Copyright (c) 2003 by Kevin M. Rosenberg
+;;;; and by onShore Development, Inc.
+;;;;
+;;;; KMRCL users are granted the rights to distribute and use this software
+;;;; as governed by the terms of the Lisp Lesser GNU Public License
+;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
+;;;; *************************************************************************
+
+(in-package #:kmrcl)
+
+#+(or cmu sbcl)
+(progn
+(defstruct (byte-array-output-stream
+             (:include #+cmu system:lisp-stream
+                      #+sbcl sb-impl::file-stream
+                       (bout #'byte-array-bout)
+                       (misc #'byte-array-out-misc))
+             (:print-function %print-byte-array-output-stream)
+             (:constructor make-byte-array-output-stream ()))
+  ;; The buffer we throw stuff in.
+  (buffer (make-array 128 :element-type '(unsigned-byte 8)))
+  ;; Index of the next location to use.
+  (index 0 :type fixnum))
+
+(defun %print-byte-array-output-stream (s stream d)
+  (declare (ignore s d))
+  (write-string "#<Byte-Array-Output Stream>" stream))
+
+(setf (documentation 'make-binary-output-stream 'function)
+  "Returns an Output stream which will accumulate all output given it for
+   the benefit of the function Get-Output-Stream-Data.")
+
+(defun byte-array-bout (stream byte)
+  (let ((current (byte-array-output-stream-index stream))
+       (workspace (byte-array-output-stream-buffer stream)))
+    (if (= current (length workspace))
+       (let ((new-workspace (make-array (* current 2) :element-type '(unsigned-byte 8))))
+         (replace new-workspace workspace)
+         (setf (aref new-workspace current) byte)
+         (setf (byte-array-output-stream-buffer stream) new-workspace))
+       (setf (aref workspace current) byte))
+    (setf (byte-array-output-stream-index stream) (1+ current))))
+
+(defun byte-array-out-misc (stream operation &optional arg1 arg2)
+  (declare (ignore arg2))
+  (case operation
+    (:file-position
+     (if (null arg1)
+        (byte-array-output-stream-index stream)))
+    (:element-type '(unsigned-byte 8))))
+
+(defun get-output-stream-data (stream)
+  "Returns an array of all data sent to a stream made by
+Make-Byte-Array-Output-Stream since the last call to this function and
+clears buffer."
+  (declare (type byte-array-output-stream stream))
+    (prog1 
+       (dump-output-stream-data stream)
+      (setf (byte-array-output-stream-index stream) 0)))
+
+(defun dump-output-stream-data (stream)
+  "Returns an array of all data sent to a stream made by
+Make-Byte-Array-Output-Stream since the last call to this function."
+  (declare (type byte-array-output-stream stream))
+  (let* ((length (byte-array-output-stream-index stream))
+        (result (make-array length :element-type '(unsigned-byte 8))))
+    (replace result (byte-array-output-stream-buffer stream))
+    result))
+
+) ; progn
+
+
+#+(or cmu sbcl)
+(progn
+  (defstruct (byte-array-input-stream
+            (:include #+cmu system:lisp-stream
+                      #+sbcl sb-impl::file-stream
+                      (in #'byte-array-inch)
+                      (bin #'byte-array-binch)
+                      (n-bin #'byte-array-stream-read-n-bytes)
+                      (misc #'byte-array-in-misc))
+            (:print-function %print-byte-array-input-stream)
+                                       ;(:constructor nil)
+            (:constructor internal-make-byte-array-input-stream
+                          (byte-array current end)))
+  (byte-array nil :type vector)
+  (current nil)
+  (end nil))
+
+(defun %print-byte-array-input-stream (s stream d)
+  (declare (ignore s d))
+  (write-string "#<Byte-Array-Input Stream>" stream))
+  
+(defun byte-array-inch (stream eof-errorp eof-value)
+  (let ((byte-array (byte-array-input-stream-byte-array stream))
+       (index (byte-array-input-stream-current stream)))
+    (cond ((= index (byte-array-input-stream-end stream))
+          (eof-or-lose stream eof-errorp eof-value))
+         (t
+          (setf (byte-array-input-stream-current stream) (1+ index))
+          (aref byte-array index)))))
+
+(defun byte-array-binch (stream eof-errorp eof-value)
+  (let ((byte-array (byte-array-input-stream-byte-array stream))
+       (index (byte-array-input-stream-current stream)))
+    (cond ((= index (byte-array-input-stream-end stream))
+          (eof-or-lose stream eof-errorp eof-value))
+         (t
+          (setf (byte-array-input-stream-current stream) (1+ index))
+          (aref byte-array index)))))
+
+(defun byte-array-stream-read-n-bytes (stream buffer start requested eof-errorp)
+  (declare (type byte-array-input-stream stream))
+  (let* ((byte-array (byte-array-input-stream-byte-array stream))
+        (index (byte-array-input-stream-current stream))
+        (available (- (byte-array-input-stream-end stream) index))
+        (copy (min available requested)))
+    (when (plusp copy)
+      (setf (byte-array-input-stream-current stream)
+       (+ index copy))
+      #+cmu
+      (system:without-gcing
+       (system::system-area-copy (system:vector-sap byte-array)
+                        (* index vm:byte-bits)
+                        (if (typep buffer 'system::system-area-pointer)
+                            buffer
+                            (system:vector-sap buffer))
+                        (* start vm:byte-bits)
+                        (* copy vm:byte-bits)))
+      #+sbcl
+      (sb-sys:without-gcing
+       (sb-kernel:system-area-copy (sb-sys:vector-sap byte-array)
+                        (* index sb-vm:n-byte-bits)
+                        (if (typep buffer 'sb-sys::system-area-pointer)
+                            buffer
+                            (sb-sys:vector-sap buffer))
+                        (* start sb-vm:n-byte-bits)
+                        (* copy sb-vm:n-byte-bits))))
+    (if (and (> requested copy) eof-errorp)
+       (error 'end-of-file :stream stream)
+       copy)))
+
+(defun byte-array-in-misc (stream operation &optional arg1 arg2)
+  (declare (ignore arg2))
+  (case operation
+    (:file-position
+     (if arg1
+        (setf (byte-array-input-stream-current stream) arg1)
+        (byte-array-input-stream-current stream)))
+    (:file-length (length (byte-array-input-stream-byte-array stream)))
+    (:unread (decf (byte-array-input-stream-current stream)))
+    (:listen (or (/= (the fixnum (byte-array-input-stream-current stream))
+                    (the fixnum (byte-array-input-stream-end stream)))
+                :eof))
+    (:element-type 'base-char)))
+  
+(defun make-byte-array-input-stream (buffer &optional (start 0) (end (length buffer)))
+  "Returns an input stream which will supply the bytes of BUFFER between
+  Start and End in order."
+  (internal-make-byte-array-input-stream buffer start end))
+
+) ;; progn
+
+#+allegro
+(progn
+
+  (defclass extendable-buffer-output-stream (excl:buffer-output-simple-stream)
+    ()
+    )
+
+  (defun make-byte-array-output-stream ()
+    "Returns an Output stream which will accumulate all output given it for
+   the benefit of the function Get-Output-Stream-Data."
+    (make-instance 'extendable-buffer-output-stream
+      :buffer (make-array 128 :element-type '(unsigned-byte 8))
+      :external-form :octets))
+
+  (defun get-output-stream-data (stream)
+    "Returns an array of all data sent to a stream made by
+Make-Byte-Array-Output-Stream since the last call to this function
+and clears buffer."
+    (prog1 
+       (dump-output-stream-data stream)
+      (file-position stream 0)))
+  
+  (defun dump-output-stream-data (stream)
+    "Returns an array of all data sent to a stream made by
+Make-Byte-Array-Output-Stream since the last call to this function."
+    (force-output stream)
+    (let* ((length (file-position stream))
+          (result (make-array length :element-type '(unsigned-byte 8))))
+      (replace result (slot-value stream 'excl::buffer))
+      result))
+  
+  (defmethod excl:device-extend ((stream extendable-buffer-output-stream)
+                                need action)
+    (let* ((len (file-position stream))
+          (new-len (max (+ len need) (* 2 len)))
+          (old-buf (slot-value stream 'excl::buffer))
+          (new-buf (make-array new-len :element-type '(unsigned-byte 8))))
+      (declare (fixnum len)
+              (optimize (speed 3) (safety 0)))
+      (dotimes (i len)
+       (setf (aref new-buf i) (aref old-buf i)))
+      (setf (slot-value stream 'excl::buffer) new-buf)
+      (setf (slot-value stream 'excl::buffer-ptr) new-len)
+      )
+    t)
+  
+)
+
+#+allegro
+(progn
+  (defun make-byte-array-input-stream (buffer &optional (start 0)
+                                                       (end (length buffer)))
+    (excl:make-buffer-input-stream buffer start end :octets))
+  ) ;; progn