r10388: more sbcl fix
[kmrcl.git] / byte-stream.lisp
1 ;;; -*- Syntax: Ansi-Common-Lisp; Base: 10; Mode: lisp; Package: kmrcl -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          byte-stream.lisp
6 ;;;; Purpose:       Byte array input/output streams
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  June 2003
9 ;;;;
10 ;;;; $Id$
11 ;;;;
12 ;;;; Works for CMUCL, SBCL, and AllergoCL only
13 ;;;;
14 ;;;; This file, part of KMRCL, is Copyright (c) 2003 by Kevin M. Rosenberg
15 ;;;; and by onShore Development, Inc.
16 ;;;;
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 ;;;; *************************************************************************
21
22 (in-package #:kmrcl)
23
24 ;; Intial CMUCL version by OnShored. Ported to SBCL by Kevin Rosenberg
25
26 #+(or cmu sbcl)
27 (progn
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))
39
40 (defun %print-byte-array-output-stream (s stream d)
41   (declare (ignore s d))
42   (write-string "#<Byte-Array-Output Stream>" stream))
43
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.")
47
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))))
58
59 (defun byte-array-out-misc (stream operation &optional arg1 arg2)
60   (declare (ignore arg2))
61   (case operation
62     (:file-position
63      (if (null arg1)
64          (byte-array-output-stream-index stream)))
65     (:element-type '(unsigned-byte 8))))
66
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
70 clears buffer."
71   (declare (type byte-array-output-stream stream))
72     (prog1 
73         (dump-output-stream-data stream)
74       (setf (byte-array-output-stream-index stream) 0)))
75
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))
83     result))
84
85 ) ; progn
86
87
88 #+sbcl
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)
95                                      0))
96  (defconstant *system-copy-multiplier* (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL"))
97                                            sb-vm:n-byte-bits
98                                          1)))
99
100 #+(or cmu sbcl)
101 (progn
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)
111                                         ;(:constructor nil)
112              (:constructor internal-make-byte-array-input-stream
113                            (byte-array current end)))
114   (byte-array nil :type vector)
115   (current nil)
116   (end nil))
117
118   
119 (defun %print-byte-array-input-stream (s stream d)
120   (declare (ignore s d))
121   (write-string "#<Byte-Array-Input Stream>" stream))
122
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))
127            #+cmu
128            (eof-or-lose stream eof-errorp eof-value)
129            #+sbcl
130            (sb-impl::eof-or-lose stream eof-errorp eof-value)
131            )
132           (t
133            (setf (byte-array-input-stream-current stream) (1+ index))
134            (aref byte-array index)))))
135
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))
140            #+cmu
141            (eof-or-lose stream eof-errorp eof-value)
142            #+sbcl
143            (sb-impl::eof-or-lose stream eof-errorp eof-value)
144            )
145           (t
146            (setf (byte-array-input-stream-current stream) (1+ index))
147            (aref byte-array index)))))
148
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)))
155     (when (plusp copy)
156       (setf (byte-array-input-stream-current stream)
157         (+ index copy))
158       #+cmu
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)
163                              buffer
164                              (system:vector-sap buffer))
165                          (* start vm:byte-bits)
166                          (* copy vm:byte-bits)))
167       #+sbcl
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)
172                              buffer
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)
178         copy)))
179
180 (defun byte-array-in-misc (stream operation &optional arg1 arg2)
181   (declare (ignore arg2))
182   (case operation
183     (:file-position
184      (if arg1
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)))
191                  :eof))
192     (:element-type 'base-char)))
193   
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))
198
199 ) ;; progn
200
201
202 ;;; Simple streams implementation by Kevin Rosenberg
203
204 #+allegro
205 (progn
206
207   (defclass extendable-buffer-output-stream (excl:buffer-output-simple-stream)
208     ()
209     )
210
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))
217
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
221 and clears buffer."
222     (prog1 
223         (dump-output-stream-data stream)
224       (file-position stream 0)))
225   
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))
233       result))
234   
235   (defmethod excl:device-extend ((stream extendable-buffer-output-stream)
236                                  need action)
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)))
244       (dotimes (i len)
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)
248       )
249     t)
250   
251 )
252
253 #+allegro
254 (progn
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))
258   ) ;; progn