1 ;;; -*- Syntax: Ansi-Common-Lisp; Base: 10; Mode: lisp; Package: kmrcl -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
5 ;;;; Name: byte-stream.lisp
6 ;;;; Purpose: Byte array input/output streams
7 ;;;; Programmer: Kevin M. Rosenberg
8 ;;;; Date Started: June 2003
12 ;;;; Works for CMUCL, SBCL, and AllergoCL only
14 ;;;; This file, part of KMRCL, is Copyright (c) 2003 by Kevin M. Rosenberg
15 ;;;; and by onShore Development, Inc.
17 ;;;; KMRCL users are granted the rights to distribute and use this software
18 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
19 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
20 ;;;; *************************************************************************
24 ;; Intial CMUCL version by OnShored. Ported to SBCL by Kevin Rosenberg
28 (defstruct (byte-array-output-stream
29 (:include #+cmu system:lisp-stream
30 #+sbcl sb-sys:fd-stream
31 (bout #'byte-array-bout)
32 (misc #'byte-array-out-misc))
33 (:print-function %print-byte-array-output-stream)
34 (:constructor make-byte-array-output-stream ()))
35 ;; The buffer we throw stuff in.
36 (buffer (make-array 128 :element-type '(unsigned-byte 8)))
37 ;; Index of the next location to use.
38 (index 0 :type fixnum))
40 (defun %print-byte-array-output-stream (s stream d)
41 (declare (ignore s d))
42 (write-string "#<Byte-Array-Output Stream>" stream))
44 (setf (documentation 'make-binary-output-stream 'function)
45 "Returns an Output stream which will accumulate all output given it for
46 the benefit of the function Get-Output-Stream-Data.")
48 (defun byte-array-bout (stream byte)
49 (let ((current (byte-array-output-stream-index stream))
50 (workspace (byte-array-output-stream-buffer stream)))
51 (if (= current (length workspace))
52 (let ((new-workspace (make-array (* current 2) :element-type '(unsigned-byte 8))))
53 (replace new-workspace workspace)
54 (setf (aref new-workspace current) byte)
55 (setf (byte-array-output-stream-buffer stream) new-workspace))
56 (setf (aref workspace current) byte))
57 (setf (byte-array-output-stream-index stream) (1+ current))))
59 (defun byte-array-out-misc (stream operation &optional arg1 arg2)
60 (declare (ignore arg2))
64 (byte-array-output-stream-index stream)))
65 (:element-type '(unsigned-byte 8))))
67 (defun get-output-stream-data (stream)
68 "Returns an array of all data sent to a stream made by
69 Make-Byte-Array-Output-Stream since the last call to this function and
71 (declare (type byte-array-output-stream stream))
73 (dump-output-stream-data stream)
74 (setf (byte-array-output-stream-index stream) 0)))
76 (defun dump-output-stream-data (stream)
77 "Returns an array of all data sent to a stream made by
78 Make-Byte-Array-Output-Stream since the last call to this function."
79 (declare (type byte-array-output-stream stream))
80 (let* ((length (byte-array-output-stream-index stream))
81 (result (make-array length :element-type '(unsigned-byte 8))))
82 (replace result (byte-array-output-stream-buffer stream))
89 (sb-ext:without-package-locks
90 (defvar *system-copy-fn* (if (fboundp (intern "COPY-SYSTEM-AREA" "SB-KERNEL"))
91 (intern "COPY-SYSTEM-AREA" "SB-KERNEL")
92 (intern "COPY-SYSTEM-UB8-AREA" "SB-KERNEL")))
93 (defconstant *system-copy-offset* (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL"))
94 (* sb-vm:vector-data-offset sb-vm:n-word-bits)
96 (defconstant *system-copy-multiplier* (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL"))
102 (defstruct (byte-array-input-stream
103 (:include #+cmu system:lisp-stream
104 ;;#+sbcl sb-impl::file-stream
105 #+sbcl sb-sys:fd-stream
106 (in #'byte-array-inch)
107 (bin #'byte-array-binch)
108 (n-bin #'byte-array-stream-read-n-bytes)
109 (misc #'byte-array-in-misc))
110 (:print-function %print-byte-array-input-stream)
112 (:constructor internal-make-byte-array-input-stream
113 (byte-array current end)))
114 (byte-array nil :type vector)
119 (defun %print-byte-array-input-stream (s stream d)
120 (declare (ignore s d))
121 (write-string "#<Byte-Array-Input Stream>" stream))
123 (defun byte-array-inch (stream eof-errorp eof-value)
124 (let ((byte-array (byte-array-input-stream-byte-array stream))
125 (index (byte-array-input-stream-current stream)))
126 (cond ((= index (byte-array-input-stream-end stream))
128 (eof-or-lose stream eof-errorp eof-value)
130 (sb-impl::eof-or-lose stream eof-errorp eof-value)
133 (setf (byte-array-input-stream-current stream) (1+ index))
134 (aref byte-array index)))))
136 (defun byte-array-binch (stream eof-errorp eof-value)
137 (let ((byte-array (byte-array-input-stream-byte-array stream))
138 (index (byte-array-input-stream-current stream)))
139 (cond ((= index (byte-array-input-stream-end stream))
141 (eof-or-lose stream eof-errorp eof-value)
143 (sb-impl::eof-or-lose stream eof-errorp eof-value)
146 (setf (byte-array-input-stream-current stream) (1+ index))
147 (aref byte-array index)))))
149 (defun byte-array-stream-read-n-bytes (stream buffer start requested eof-errorp)
150 (declare (type byte-array-input-stream stream))
151 (let* ((byte-array (byte-array-input-stream-byte-array stream))
152 (index (byte-array-input-stream-current stream))
153 (available (- (byte-array-input-stream-end stream) index))
154 (copy (min available requested)))
156 (setf (byte-array-input-stream-current stream)
159 (system:without-gcing
160 (system::system-area-copy (system:vector-sap byte-array)
161 (* index vm:byte-bits)
162 (if (typep buffer 'system::system-area-pointer)
164 (system:vector-sap buffer))
165 (* start vm:byte-bits)
166 (* copy vm:byte-bits)))
168 (sb-sys:without-gcing
169 (funcall *system-copy-fn* (sb-sys:vector-sap byte-array)
170 (* index *system-copy-multiplier*)
171 (if (typep buffer 'sb-sys::system-area-pointer)
173 (sb-sys:vector-sap buffer))
174 (* start *system-copy-multiplier*)
175 (* copy *system-copy-multiplier*))))
176 (if (and (> requested copy) eof-errorp)
177 (error 'end-of-file :stream stream)
180 (defun byte-array-in-misc (stream operation &optional arg1 arg2)
181 (declare (ignore arg2))
185 (setf (byte-array-input-stream-current stream) arg1)
186 (byte-array-input-stream-current stream)))
187 (:file-length (length (byte-array-input-stream-byte-array stream)))
188 (:unread (decf (byte-array-input-stream-current stream)))
189 (:listen (or (/= (the fixnum (byte-array-input-stream-current stream))
190 (the fixnum (byte-array-input-stream-end stream)))
192 (:element-type 'base-char)))
194 (defun make-byte-array-input-stream (buffer &optional (start 0) (end (length buffer)))
195 "Returns an input stream which will supply the bytes of BUFFER between
196 Start and End in order."
197 (internal-make-byte-array-input-stream buffer start end))
202 ;;; Simple streams implementation by Kevin Rosenberg
207 (defclass extendable-buffer-output-stream (excl:buffer-output-simple-stream)
211 (defun make-byte-array-output-stream ()
212 "Returns an Output stream which will accumulate all output given it for
213 the benefit of the function Get-Output-Stream-Data."
214 (make-instance 'extendable-buffer-output-stream
215 :buffer (make-array 128 :element-type '(unsigned-byte 8))
216 :external-form :octets))
218 (defun get-output-stream-data (stream)
219 "Returns an array of all data sent to a stream made by
220 Make-Byte-Array-Output-Stream since the last call to this function
223 (dump-output-stream-data stream)
224 (file-position stream 0)))
226 (defun dump-output-stream-data (stream)
227 "Returns an array of all data sent to a stream made by
228 Make-Byte-Array-Output-Stream since the last call to this function."
229 (force-output stream)
230 (let* ((length (file-position stream))
231 (result (make-array length :element-type '(unsigned-byte 8))))
232 (replace result (slot-value stream 'excl::buffer))
235 (defmethod excl:device-extend ((stream extendable-buffer-output-stream)
237 (declare (ignore action))
238 (let* ((len (file-position stream))
239 (new-len (max (+ len need) (* 2 len)))
240 (old-buf (slot-value stream 'excl::buffer))
241 (new-buf (make-array new-len :element-type '(unsigned-byte 8))))
242 (declare (fixnum len)
243 (optimize (speed 3) (safety 0)))
245 (setf (aref new-buf i) (aref old-buf i)))
246 (setf (slot-value stream 'excl::buffer) new-buf)
247 (setf (slot-value stream 'excl::buffer-ptr) new-len)
255 (defun make-byte-array-input-stream (buffer &optional (start 0)
256 (end (length buffer)))
257 (excl:make-buffer-input-stream buffer start end :octets))