3 ;;; **********************************************************************
4 ;;; This code was written by Paul Foley and has been placed in the public
8 ;;; Sbcl port by Rudi Schlatte.
10 (in-package "SB-SIMPLE-STREAMS")
13 ;;; **********************************************************************
15 ;;; Implementations of standard Common Lisp functions for simple-streams
17 (defun %uninitialized (stream)
18 (error "~S has not been initialized." stream))
20 (defun %check (stream kind)
21 (declare (type simple-stream stream)
22 (optimize (speed 3) (space 1) (debug 0) (safety 0)))
23 (with-stream-class (simple-stream stream)
24 (cond ((not (any-stream-instance-flags stream :simple))
25 (%uninitialized stream))
27 (not (any-stream-instance-flags stream :input :output)))
28 (sb-kernel:closed-flame stream))
29 ((and (or (eq kind :input) (eq kind :io))
30 (not (any-stream-instance-flags stream :input)))
31 (sb-kernel:ill-in stream))
32 ((and (or (eq kind :output) (eq kind :io))
33 (not (any-stream-instance-flags stream :output)))
34 (sb-kernel:ill-out stream)))))
36 (defmethod input-stream-p ((stream simple-stream))
37 (any-stream-instance-flags stream :input))
39 (defmethod output-stream-p ((stream simple-stream))
40 (any-stream-instance-flags stream :output))
42 (defmethod open-stream-p ((stream simple-stream))
43 (any-stream-instance-flags stream :input :output))
45 ;;; From the simple-streams documentation: "A generic function implies
46 ;;; a specialization capability that does not exist for
47 ;;; simple-streams; simple-stream specializations should be on
48 ;;; device-close." So don't do it.
49 (defmethod close ((stream simple-stream) &key abort)
50 (device-close stream abort))
52 (defun %file-position (stream position)
53 (declare (type simple-stream stream)
54 (type (or (integer 0 *) (member nil :start :end)) position))
55 (with-stream-class (simple-stream stream)
58 ;; Adjust current position
59 (let ((position (case position (:start 0) (:end -1)
60 (otherwise position))))
62 (single-channel-simple-stream
63 (when (sc-dirty-p stream)
64 (flush-buffer stream t)))
65 (dual-channel-simple-stream
66 (with-stream-class (dual-channel-simple-stream stream)
67 (when (> (sm outpos stream) 0)
68 (device-write stream :flush 0 nil t))))
72 (setf (sm last-char-read-size stream) 0)
73 (setf (sm buffpos stream) 0 ; set pointer to 0 to force a read
74 (sm buffer-ptr stream) 0)
75 (setf (sm charpos stream) nil)
76 (remove-stream-instance-flags stream :eof)
77 (setf (device-file-position stream) position))
78 ;; Just report current position
79 (let ((posn (device-file-position stream)))
81 (when (sm handler stream)
82 (dolist (queued (sm pending stream))
83 (incf posn (- (the sb-int:index (third queued))
84 (the sb-int:index (second queued))))))
86 (single-channel-simple-stream
87 (case (sm mode stream)
88 ((0 3) ; read, read-modify
89 ;; Note that posn can increase here if we wrote
90 ;; past the end of previously-read data
91 (decf posn (- (sm buffer-ptr stream) (sm buffpos stream))))
93 (incf posn (sm buffpos stream)))))
94 (dual-channel-simple-stream
95 (with-stream-class (dual-channel-simple-stream stream)
96 (incf posn (sm outpos stream))
97 (when (>= (sm buffer-ptr stream) 0)
98 (decf posn (- (sm buffer-ptr stream) (sm buffpos stream))))))
103 (defun %file-length (stream)
104 (declare (type simple-stream stream))
105 (%check stream :open)
106 (device-file-length stream))
109 (defun %file-name (stream)
110 (declare (type simple-stream stream))
114 (with-stream-class (file-simple-stream stream)
115 (sm pathname stream)))
117 (with-stream-class (probe-simple-stream stream)
118 (sm pathname stream)))
123 (defun %file-rename (stream new-name)
124 (declare (type simple-stream stream))
126 (if (typep stream 'file-simple-stream)
127 (with-stream-class (file-simple-stream stream)
128 (setf (sm pathname stream) new-name)
129 (setf (sm filename stream) (sb-int:unix-namestring new-name nil))
134 (defun %file-string-length (stream object)
135 (declare (type simple-stream stream))
136 (with-stream-class (simple-stream stream)
137 (%check stream :output)
138 ;; FIXME: need to account for compositions on the stream...
141 (declare (ignore octet))
146 (char-to-octets (sm external-format stream) object x #'fn)))
149 (ef (sm external-format stream)))
150 (dotimes (i (length object))
151 (declare (type sb-int:index i))
152 (char-to-octets ef (char object i) x #'fn))))))
156 (defun %read-line (stream eof-error-p eof-value recursive-p)
157 (declare (optimize (speed 3) (space 1) (safety 0) (debug 0))
158 (type simple-stream stream)
159 (ignore recursive-p))
160 (with-stream-class (simple-stream stream)
161 (%check stream :input)
162 (when (any-stream-instance-flags stream :eof)
163 (return-from %read-line
164 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
165 ;; for interactive streams, finish output first to force prompt
166 (when (and (any-stream-instance-flags stream :output)
167 (any-stream-instance-flags stream :interactive))
168 (%finish-output stream))
169 (let* ((encap (sm melded-stream stream)) ; encapsulating stream
170 (cbuf (make-string 80)) ; current buffer
171 (bufs (list cbuf)) ; list of buffers
172 (tail bufs) ; last cons of bufs list
173 (index 0) ; current index in current buffer
174 (total 0)) ; total characters
175 (declare (type simple-stream encap)
176 (type simple-base-string cbuf)
177 (type cons bufs tail)
178 (type sb-int:index index total))
180 (multiple-value-bind (chars done)
181 (funcall-stm-handler j-read-chars encap cbuf
182 #\Newline index (length cbuf) t)
183 (declare (type sb-int:index chars))
186 (when (and (eq done :eof) (zerop total))
188 (error 'end-of-file :stream stream)
189 (return (values eof-value t))))
191 ;; If there's only one buffer in use, return it directly
192 (when (null (cdr bufs))
193 (return (values (sb-kernel:shrink-vector cbuf total)
195 ;; If total fits in final buffer, use it
196 (when (<= total (length cbuf))
197 (replace cbuf cbuf :start1 (- total index) :end2 index)
199 (declare (type sb-int:index idx))
200 (do ((list bufs (cdr list)))
202 (let ((buf (car list)))
203 (declare (type simple-base-string buf))
204 (replace cbuf buf :start1 idx)
205 (incf idx (length buf)))))
206 (return (values (sb-kernel:shrink-vector cbuf total)
208 ;; Allocate new string of appropriate length
209 (let ((string (make-string total))
211 (declare (type sb-int:index index))
213 (declare (type simple-base-string buf))
214 (replace string buf :start1 index)
215 (incf index (length buf)))
216 (return (values string (eq done :eof)))))
217 (when (>= index (length cbuf))
218 (setf cbuf (make-string (the sb-int:index (* 2 index))))
220 (setf (cdr tail) (cons cbuf nil))
221 (setf tail (cdr tail))))))))
223 (defun %read-char (stream eof-error-p eof-value recursive-p blocking-p)
224 (declare (type simple-stream stream)
225 (ignore recursive-p))
226 (with-stream-class (simple-stream stream)
227 (%check stream :input)
228 (when (any-stream-instance-flags stream :eof)
229 (return-from %read-char
230 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
231 ;; for interactive streams, finish output first to force prompt
232 (when (and (any-stream-instance-flags stream :output)
233 (any-stream-instance-flags stream :interactive))
234 (%finish-output stream))
235 (funcall-stm-handler j-read-char (sm melded-stream stream)
236 eof-error-p eof-value blocking-p)))
239 (defun %unread-char (stream character)
240 (declare (type simple-stream stream) (ignore character))
241 (with-stream-class (simple-stream stream)
242 (%check stream :input)
243 (if (zerop (sm last-char-read-size stream))
244 (error "Nothing to unread.")
246 (funcall-stm-handler j-unread-char (sm melded-stream stream) nil)
247 (remove-stream-instance-flags stream :eof)
248 (setf (sm last-char-read-size stream) 0)))))
251 (defun %peek-char (stream peek-type eof-error-p eof-value recursive-p)
252 (declare (type simple-stream stream)
253 (ignore recursive-p))
254 (with-stream-class (simple-stream stream)
255 (%check stream :input)
256 (when (any-stream-instance-flags stream :eof)
257 (return-from %peek-char
258 (sb-impl::eof-or-lose stream eof-error-p eof-value)))
259 (let* ((encap (sm melded-stream stream))
260 (char (funcall-stm-handler j-read-char encap
261 eof-error-p stream t)))
262 (cond ((eq char stream) eof-value)
263 ((characterp peek-type)
264 (do ((char char (funcall-stm-handler j-read-char encap
267 ((or (eq char stream) (char= char peek-type))
268 (unless (eq char stream)
269 (funcall-stm-handler j-unread-char encap t))
270 (if (eq char stream) eof-value char))))
272 (do ((char char (funcall-stm-handler j-read-char encap
275 ((or (eq char stream)
276 (not (sb-impl::whitespacep char)))
277 (unless (eq char stream)
278 (funcall-stm-handler j-unread-char encap t))
279 (if (eq char stream) eof-value char))))
281 (funcall-stm-handler j-unread-char encap t)
284 (defun %listen (stream width)
285 (declare (type simple-stream stream))
286 ;; WIDTH is number of octets which must be available; any value
287 ;; other than 1 is treated as 'character.
288 (with-stream-class (simple-stream stream)
289 (%check stream :input)
290 (when (any-stream-instance-flags stream :eof)
291 (return-from %listen nil))
292 (if (not (or (eql width 1) (null width)))
293 (funcall-stm-handler j-listen (sm melded-stream stream))
294 (or (< (sm buffpos stream) (sm buffer-ptr stream))
295 (when (or (not (any-stream-instance-flags stream :dual :string))
296 (>= (sm mode stream) 0)) ;; device-connected @@ single-channel
297 (let ((lcrs (sm last-char-read-size stream)))
300 (setf (sm last-char-read-size stream) (1+ lcrs))
301 (plusp (refill-buffer stream nil)))
302 (setf (sm last-char-read-size stream) lcrs))))))))
304 (defun %clear-input (stream buffer-only)
305 (declare (type simple-stream stream))
306 (with-stream-class (simple-stream stream)
307 (%check stream :input)
308 (setf (sm buffpos stream) 0
309 (sm buffer-ptr stream) 0
310 (sm last-char-read-size stream) 0
311 #|(sm unread-past-soft-eof stream) nil|#)
312 #| (setf (sm reread-count stream) 0) on dual-channel streams? |#
314 (device-clear-input stream buffer-only))
317 (defun %read-byte (stream eof-error-p eof-value)
318 (declare (type simple-stream stream))
319 (with-stream-class (simple-stream stream)
320 (%check stream :input)
321 (if (any-stream-instance-flags stream :eof)
322 (sb-impl::eof-or-lose stream eof-error-p eof-value)
324 (single-channel-simple-stream
325 (read-byte-internal stream eof-error-p eof-value t))
326 (dual-channel-simple-stream
327 (read-byte-internal stream eof-error-p eof-value t))
328 (string-simple-stream
329 (with-stream-class (string-simple-stream stream)
330 (let ((encap (sm input-handle stream)))
332 (error 'simple-type-error
334 :expected-type 'stream
335 :format-control "Can't read-byte on string streams"
336 :format-arguments '()))
338 (read-byte encap eof-error-p eof-value)
339 (setf (sm last-char-read-size stream) 0
340 (sm encapsulated-char-read-size stream) 0)))))))))
343 (defun %write-char (stream character)
344 (declare (type simple-stream stream))
345 (with-stream-class (simple-stream stream)
346 (%check stream :output)
347 (funcall-stm-handler-2 j-write-char character (sm melded-stream stream))))
350 (defun %fresh-line (stream)
351 (declare (type simple-stream stream))
352 (with-stream-class (simple-stream stream)
353 (%check stream :output)
354 (when (/= (or (sm charpos stream) 1) 0)
355 (funcall-stm-handler-2 j-write-char #\Newline (sm melded-stream stream))
359 (defun %write-string (stream string start end)
360 (declare (type simple-stream stream))
361 (with-stream-class (simple-stream stream)
362 (%check stream :output)
363 (funcall-stm-handler-2 j-write-chars string (sm melded-stream stream)
367 (defun %line-length (stream)
368 (declare (type simple-stream stream))
369 (%check stream :output)
374 (defun %finish-output (stream)
375 (declare (type simple-stream stream))
376 (with-stream-class (simple-stream stream)
377 (%check stream :output)
378 (when (sm handler stream)
380 ((null (sm pending stream)))
381 (sb-sys:serve-all-events)))
383 (single-channel-simple-stream
384 ;(when (and (> (sm mode stream) 0) (> (sm buffer-ptr stream) 0))
385 ; (setf (device-file-position stream)
386 ; (- (device-file-position stream) (sm buffer-ptr stream))))
387 ;(device-write stream :flush 0 nil t)
388 (flush-buffer stream t)
389 (setf (sm buffpos stream) 0))
390 (dual-channel-simple-stream
391 (with-stream-class (dual-channel-simple-stream stream)
392 (device-write stream :flush 0 nil t)
393 (setf (sm outpos stream) 0)))
394 (string-simple-stream
395 (device-write stream :flush 0 nil t))))
399 (defun %force-output (stream)
400 (declare (type simple-stream stream))
401 (with-stream-class (simple-stream stream)
402 (%check stream :output)
404 (single-channel-simple-stream
405 ;(when (> (sm buffer-ptr stream) 0)
406 ; (setf (device-file-position stream)
407 ; (- (device-file-position stream) (sm buffer-ptr stream))))
408 ;(device-write stream :flush 0 nil nil)
409 (flush-buffer stream nil)
410 (setf (sm buffpos stream) 0))
411 (dual-channel-simple-stream
412 (with-stream-class (dual-channel-simple-stream stream)
413 (device-write stream :flush 0 nil nil)
414 (setf (sm outpos stream) 0)))
415 (string-simple-stream
416 (device-write stream :flush 0 nil nil))))
420 (defun %clear-output (stream)
421 (declare (type simple-stream stream))
422 (with-stream-class (simple-stream stream)
423 (%check stream :output)
424 (when (sm handler stream)
425 (sb-sys:remove-fd-handler (sm handler stream))
426 (setf (sm handler stream) nil
427 (sm pending stream) nil))
429 (single-channel-simple-stream
430 (with-stream-class (single-channel-simple-stream stream)
431 (case (sm mode stream)
432 (1 (setf (sm buffpos stream) 0))
433 (3 (setf (sm mode stream) 0)))))
434 (dual-channel-simple-stream
435 (setf (sm outpos stream) 0))
436 (string-simple-stream
438 (device-clear-output stream)))
441 (defun %write-byte (stream integer)
442 (declare (type simple-stream stream))
443 (with-stream-class (simple-stream stream)
444 (%check stream :output)
446 (single-channel-simple-stream
447 (with-stream-class (single-channel-simple-stream stream)
448 (let ((ptr (sm buffpos stream)))
449 (when (>= ptr (sm buf-len stream))
450 (setf ptr (flush-buffer stream t)))
451 (setf (sm buffpos stream) (1+ ptr))
452 (setf (sm charpos stream) nil)
453 (setf (bref (sm buffer stream) ptr) integer)
454 (sc-set-dirty stream))))
455 (dual-channel-simple-stream
456 (with-stream-class (dual-channel-simple-stream stream)
457 (let ((ptr (sm outpos stream)))
458 (when (>= ptr (sm max-out-pos stream))
459 (setf ptr (flush-out-buffer stream t)))
460 (setf (sm outpos stream) (1+ ptr))
461 (setf (sm charpos stream) nil)
462 (setf (bref (sm out-buffer stream) ptr) integer))))
463 (string-simple-stream
464 (with-stream-class (string-simple-stream stream)
465 (let ((encap (sm output-handle stream)))
467 (error 'simple-type-error
469 :expected-type 'stream
470 :format-control "Can't write-byte on string streams."
471 :format-arguments '()))
472 (write-byte integer encap)))))))
475 (defun %read-sequence (stream seq start end partial-fill)
476 (declare (type simple-stream stream)
478 (type sb-int:index start end)
479 (type boolean partial-fill))
480 (with-stream-class (simple-stream stream)
481 (%check stream :input)
482 (when (any-stream-instance-flags stream :eof)
483 (return-from %read-sequence 0))
484 (when (and (not (any-stream-instance-flags stream :dual :string))
486 (flush-buffer stream t))
489 (funcall-stm-handler j-read-chars (sm melded-stream stream) seq nil
491 (if partial-fill :bnb t)))
492 ((or (simple-array (unsigned-byte 8) (*))
493 (simple-array (signed-byte 8) (*)))
494 (when (any-stream-instance-flags stream :string)
495 (error "Can't read into byte sequence from a string stream."))
496 ;; "read-vector" equivalent, but blocking if partial-fill is NIL
497 ;; FIXME: this could be implemented faster via buffer-copy
498 (loop with encap = (sm melded-stream stream)
499 for index from start below end
500 for byte = (read-byte-internal encap nil nil t)
501 then (read-byte-internal encap nil nil partial-fill)
503 do (setf (bref seq index) byte)
504 finally (return index)))
505 ;; extend to work on other sequences: repeated read-byte
508 (defun %write-sequence (stream seq start end)
509 (declare (type simple-stream stream)
511 (type sb-int:index start end))
512 (with-stream-class (simple-stream stream)
513 (%check stream :output)
516 (funcall-stm-handler-2 j-write-chars seq (sm melded-stream stream)
518 ((or (simple-array (unsigned-byte 8) (*))
519 (simple-array (signed-byte 8) (*)))
520 ;; "write-vector" equivalent
521 (setf (sm charpos stream) nil)
523 (single-channel-simple-stream
524 (with-stream-class (single-channel-simple-stream stream)
525 (loop with max-ptr fixnum = (sm buf-len stream)
526 for src-pos fixnum = start then (+ src-pos count)
527 for src-rest fixnum = (- end src-pos)
528 while (> src-rest 0) ; FIXME: this is non-ANSI
529 for ptr fixnum = (let ((ptr (sm buffpos stream)))
531 (flush-buffer stream t)
533 for buf-rest fixnum = (- max-ptr ptr)
534 for count fixnum = (min buf-rest src-rest)
535 do (progn (setf (sm mode stream) 1)
536 (setf (sm buffpos stream) (+ ptr count))
537 (buffer-copy seq src-pos (sm buffer stream) ptr count)))))
538 (dual-channel-simple-stream
539 (with-stream-class (dual-channel-simple-stream stream)
540 (loop with max-ptr fixnum = (sm max-out-pos stream)
541 for src-pos fixnum = start then (+ src-pos count)
542 for src-rest fixnum = (- end src-pos)
543 while (> src-rest 0) ; FIXME: this is non-ANSI
544 for ptr fixnum = (let ((ptr (sm outpos stream)))
546 (flush-out-buffer stream t)
548 for buf-rest fixnum = (- max-ptr ptr)
549 for count fixnum = (min buf-rest src-rest)
550 do (progn (setf (sm outpos stream) (+ ptr count))
551 (buffer-copy seq src-pos (sm out-buffer stream) ptr count)))))
552 (string-simple-stream
553 (error 'simple-type-error
555 :expected-type 'stream
556 :format-control "Can't write a byte sequence to a string stream."
557 :format-arguments '())))
559 ;; extend to work on other sequences: repeated write-byte
564 (defun read-vector (vector stream &key (start 0) end (endian-swap :byte-8))
565 (declare (type (sb-kernel:simple-unboxed-array (*)) vector)
566 (type stream stream))
567 ;; START and END are octet offsets, not vector indices! [Except for strings]
568 ;; Return value is index of next octet to be read into (i.e., start+count)
571 (with-stream-class (simple-stream stream)
572 (cond ((stringp vector)
573 (let* ((start (or start 0))
574 (end (or end (length vector)))
575 (encap (sm melded-stream stream))
576 (char (funcall-stm-handler j-read-char encap nil nil t)))
578 (setf (schar vector start) char)
580 (+ start (funcall-stm-handler j-read-chars encap vector nil
582 ((any-stream-instance-flags stream :string)
583 (error "Can't READ-BYTE on string streams."))
585 (do* ((encap (sm melded-stream stream))
586 (index (or start 0) (1+ index))
587 (end (or end (* (length vector) (vector-elt-width vector))))
588 (endian-swap (endian-swap-value vector endian-swap))
589 (byte (read-byte-internal encap nil nil t)
590 (read-byte-internal encap nil nil nil)))
591 ((or (null byte) (>= index end)) index)
592 (setf (bref vector (logxor index endian-swap)) byte))))))
593 ((or ansi-stream fundamental-stream)
594 (unless (typep vector '(or string
595 (simple-array (signed-byte 8) (*))
596 (simple-array (unsigned-byte 8) (*))))
597 (error "Wrong vector type for read-vector on stream not of type simple-stream."))
598 (read-sequence vector stream :start (or start 0) :end end))))
600 ;;; Basic functionality for ansi-streams. These are separate
601 ;;; functions because they are called in places where we already know
602 ;;; we operate on an ansi-stream (as opposed to a simple- or
603 ;;; gray-stream, or the symbols t or nil), so we can evade typecase
604 ;;; and (in|out)-synonym-of calls.
606 (declaim (inline %ansi-stream-read-byte %ansi-stream-read-char
607 %ansi-stream-unread-char %ansi-stream-read-line
608 %ansi-stream-read-sequence))
610 (defun %ansi-stream-read-byte (stream eof-error-p eof-value blocking)
611 (declare (ignore blocking))
613 (sb-kernel:ansi-stream-read-byte stream eof-error-p eof-value)
614 (sb-int:prepare-for-fast-read-byte stream
616 (sb-int:fast-read-byte eof-error-p eof-value t)
617 (sb-int:done-with-fast-read-byte))))
619 (defun %ansi-stream-read-char (stream eof-error-p eof-value blocking)
620 (declare (ignore blocking))
622 (sb-kernel:ansi-stream-read-char stream eof-error-p eof-value)
623 (sb-int:prepare-for-fast-read-char stream
625 (sb-int:fast-read-char eof-error-p eof-value)
626 (sb-int:done-with-fast-read-char))))
628 (defun %ansi-stream-unread-char (character stream)
629 (let ((index (1- (sb-kernel:ansi-stream-in-index stream)))
630 (buffer (sb-kernel:ansi-stream-in-buffer stream)))
631 (declare (fixnum index))
632 (when (minusp index) (error "nothing to unread"))
634 (setf (aref buffer index) (char-code character))
635 (setf (sb-kernel:ansi-stream-in-index stream) index))
637 (funcall (sb-kernel:ansi-stream-misc stream) stream
638 :unread character)))))
640 (defun %ansi-stream-read-line (stream eof-error-p eof-value)
641 (sb-int:prepare-for-fast-read-char stream
642 (let ((res (make-string 80))
646 (let ((ch (sb-int:fast-read-char nil nil)))
648 (when (char= ch #\newline)
649 (sb-int:done-with-fast-read-char)
650 (return (values (sb-kernel:shrink-vector res index) nil)))
653 (let ((new (make-string len)))
656 (setf (schar res index) ch)
659 (sb-int:done-with-fast-read-char)
660 (return (values (sb-impl::eof-or-lose stream eof-error-p
663 ;; Since FAST-READ-CHAR already hit the eof char, we
664 ;; shouldn't do another READ-CHAR.
666 (sb-int:done-with-fast-read-char)
667 (return (values (sb-kernel:shrink-vector res index) t)))))))))
669 (defun %ansi-stream-read-sequence (seq stream start %end)
670 (declare (type sequence seq)
671 (type sb-kernel:ansi-stream stream)
672 (type sb-int:index start)
673 (type sb-kernel:sequence-end %end)
674 (values sb-int:index))
675 (let ((end (or %end (length seq))))
676 (declare (type sb-int:index end))
680 (if (subtypep (stream-element-type stream) 'character)
681 #'%ansi-stream-read-char
682 #'%ansi-stream-read-byte)))
683 (do ((rem (nthcdr start seq) (rest rem))
685 ((or (endp rem) (>= i end)) i)
686 (declare (type list rem)
687 (type sb-int:index i))
688 (let ((el (funcall read-function stream nil :eof nil)))
691 (setf (first rem) el)))))
693 (sb-kernel:with-array-data ((data seq) (offset-start start)
696 ((or (simple-array (unsigned-byte 8) (*))
697 (simple-array (signed-byte 8) (*))
699 (let* ((numbytes (- end start))
700 (bytes-read (sb-sys:read-n-bytes stream
705 (if (< bytes-read numbytes)
710 (if (subtypep (stream-element-type stream) 'character)
711 #'%ansi-stream-read-char
712 #'%ansi-stream-read-byte)))
713 (do ((i offset-start (1+ i)))
714 ((>= i offset-end) end)
715 (declare (type sb-int:index i))
716 (let ((el (funcall read-function stream nil :eof nil)))
718 (return (+ start (- i offset-start))))
719 (setf (aref data i) el)))))))))))
722 (defun %ansi-stream-write-string (string stream start end)
723 (declare (type string string)
724 (type sb-kernel:ansi-stream stream)
725 (type sb-int:index start end))
727 ;; Note that even though you might expect, based on the behavior of
728 ;; things like AREF, that the correct upper bound here is
729 ;; (ARRAY-DIMENSION STRING 0), the ANSI glossary definitions for
730 ;; "bounding index" and "length" indicate that in this case (i.e.
731 ;; for the ANSI-specified functions WRITE-STRING and WRITE-LINE
732 ;; which are implemented in terms of this function), (LENGTH STRING)
733 ;; is the required upper bound. A foolish consistency is the
734 ;; hobgoblin of lesser languages..
735 (unless (<= 0 start end (length string))
736 (error "~@<bad bounding indices START=~W END=~W for ~2I~_~S~:>"
741 (if (sb-kernel:array-header-p string)
742 (sb-kernel:with-array-data ((data string) (offset-start start)
744 (funcall (sb-kernel:ansi-stream-sout stream)
745 stream data offset-start offset-end))
746 (funcall (sb-kernel:ansi-stream-sout stream) stream string start end))
749 (defun %ansi-stream-write-sequence (seq stream start %end)
750 (declare (type sequence seq)
751 (type sb-kernel:ansi-stream stream)
752 (type sb-int:index start)
753 (type sb-kernel:sequence-end %end)
755 (let ((end (or %end (length seq))))
756 (declare (type sb-int:index end))
759 (let ((write-function
760 (if (subtypep (stream-element-type stream) 'character)
761 ;; TODO: Replace these with ansi-stream specific
765 (do ((rem (nthcdr start seq) (rest rem))
767 ((or (endp rem) (>= i end)) seq)
768 (declare (type list rem)
769 (type sb-int:index i))
770 (funcall write-function (first rem) stream))))
772 (%ansi-stream-write-string seq stream start end))
774 (let ((write-function
775 (if (subtypep (stream-element-type stream) 'character)
776 ;; TODO: Replace these with ansi-stream specific
780 (do ((i start (1+ i)))
782 (declare (type sb-int:index i))
783 (funcall write-function (aref seq i) stream)))))))
787 ;;; USER-LEVEL FUNCTIONS
790 (defmethod open-stream-p ((stream simple-stream))
791 (any-stream-instance-flags stream :input :output))
793 (defmethod input-stream-p ((stream simple-stream))
794 (any-stream-instance-flags stream :input))
796 (defmethod output-stream-p ((stream simple-stream))
797 (any-stream-instance-flags stream :output))
799 (defmethod stream-element-type ((stream simple-stream))
802 (defun interactive-stream-p (stream)
803 "Return true if Stream does I/O on a terminal or other interactive device."
806 (%check stream :open)
807 (any-stream-instance-flags stream :interactive))
809 (funcall (sb-kernel:ansi-stream-misc stream) stream :interactive-p))
813 (defun (setf interactive-stream-p) (flag stream)
816 (%check stream :open)
818 (add-stream-instance-flags stream :interactive)
819 (remove-stream-instance-flags stream :interactive)))
821 (error 'simple-type-error
823 :expected-type 'simple-stream
824 :format-control "Can't set interactive flag on ~S."
825 :format-arguments (list stream)))))
827 (defun file-string-length (stream object)
828 (declare (type (or string character) object) (type stream stream))
829 "Return the delta in STREAM's FILE-POSITION that would be caused by writing
830 OBJECT to STREAM. Non-trivial only in implementations that support
831 international character sets."
833 (simple-stream (%file-string-length stream object))
837 (string (length object))))))
839 (defun stream-external-format (stream)
840 "Returns Stream's external-format."
843 (with-stream-class (simple-stream)
844 (%check stream :open)
845 (sm external-format stream)))
851 (defun open (filename &rest options
852 &key (direction :input)
853 (element-type 'character element-type-given)
854 if-exists if-does-not-exist
855 (external-format :default)
856 class mapped input-handle output-handle
858 "Return a stream which reads from or writes to Filename.
860 :direction - one of :input, :output, :io, or :probe
861 :element-type - type of object to read or write, default BASE-CHAR
862 :if-exists - one of :error, :new-version, :rename, :rename-and-delete,
863 :overwrite, :append, :supersede or NIL
864 :if-does-not-exist - one of :error, :create or NIL
865 :external-format - :default
866 See the manual for details.
868 The following are simple-streams-specific additions:
869 :class - class of stream object to be created
870 :mapped - T to open a memory-mapped file
871 :input-handle - a stream or Unix file descriptor to read from
872 :output-handle - a stream or Unix file descriptor to write to"
873 (declare (ignore element-type external-format input-handle output-handle
874 if-exists if-does-not-exist))
875 (let ((class (or class 'sb-sys::file-stream))
876 (options (copy-list options))
877 (filespec (merge-pathnames filename)))
878 (cond ((eq class 'sb-sys::file-stream)
879 (remf options :class)
880 (remf options :mapped)
881 (remf options :input-handle)
882 (remf options :output-handle)
883 (apply #'open-fd-stream filespec options))
884 ((subtypep class 'simple-stream)
885 (when element-type-given
886 (cerror "Do it anyway."
887 "Can't create simple-streams with an element-type."))
888 (when (and (eq class 'file-simple-stream) mapped)
889 (setq class 'mapped-file-simple-stream)
890 (setf (getf options :class) 'mapped-file-simple-stream))
891 (when (subtypep class 'file-simple-stream)
892 (when (eq direction :probe)
893 (setq class 'probe-simple-stream)))
894 (apply #'make-instance class :filename filespec options))
895 ((subtypep class 'sb-gray:fundamental-stream)
896 (remf options :class)
897 (remf options :mapped)
898 (remf options :input-handle)
899 (remf options :output-handle)
900 (make-instance class :lisp-stream
901 (apply #'open-fd-stream filespec options))))))
904 (declaim (inline read-byte read-char read-char-no-hang unread-char))
906 (defun read-byte (stream &optional (eof-error-p t) eof-value)
907 "Returns the next byte of the Stream."
908 (let ((stream (sb-impl::in-synonym-of stream)))
911 (%read-byte stream eof-error-p eof-value))
913 (%ansi-stream-read-byte stream eof-error-p eof-value t))
915 (let ((char (sb-gray:stream-read-byte stream)))
917 (sb-impl::eof-or-lose stream eof-error-p eof-value)
920 (defun read-char (&optional (stream *standard-input*) (eof-error-p t)
921 eof-value recursive-p)
922 "Inputs a character from Stream and returns it."
923 (let ((stream (sb-impl::in-synonym-of stream)))
926 (%read-char stream eof-error-p eof-value recursive-p t))
928 (%ansi-stream-read-char stream eof-error-p eof-value t))
930 (let ((char (sb-gray:stream-read-char stream)))
932 (sb-impl::eof-or-lose stream eof-error-p eof-value)
935 (defun read-char-no-hang (&optional (stream *standard-input*) (eof-error-p t)
936 eof-value recursive-p)
937 "Returns the next character from the Stream if one is availible, or nil."
938 (declare (ignore recursive-p))
939 (let ((stream (sb-impl::in-synonym-of stream)))
942 (%check stream :input)
943 (with-stream-class (simple-stream)
944 (funcall-stm-handler j-read-char stream eof-error-p eof-value nil)))
946 (if (funcall (sb-kernel:ansi-stream-misc stream) stream :listen)
947 (%ansi-stream-read-char stream eof-error-p eof-value t)
950 (let ((char (sb-gray:stream-read-char-no-hang stream)))
952 (sb-impl::eof-or-lose stream eof-error-p eof-value)
955 (defun unread-char (character &optional (stream *standard-input*))
956 "Puts the Character back on the front of the input Stream."
957 (let ((stream (sb-impl::in-synonym-of stream)))
960 (%unread-char stream character))
962 (%ansi-stream-unread-char character stream))
964 (sb-gray:stream-unread-char stream character))))
967 (declaim (notinline read-byte read-char read-char-no-hang unread-char))
969 (defun peek-char (&optional (peek-type nil) (stream *standard-input*)
970 (eof-error-p t) eof-value recursive-p)
971 "Peeks at the next character in the input Stream. See manual for details."
972 (let ((stream (sb-impl::in-synonym-of stream)))
975 (%peek-char stream peek-type eof-error-p eof-value recursive-p))
976 ;; FIXME: Broken on ECHO-STREAM (cf internal implementation?) --
979 (let ((char (%ansi-stream-read-char stream eof-error-p eof-value t)))
980 (cond ((eq char eof-value) char)
981 ((characterp peek-type)
982 (do ((char char (%ansi-stream-read-char stream eof-error-p
984 ((or (eq char eof-value) (char= char peek-type))
985 (unless (eq char eof-value)
986 (%ansi-stream-unread-char char stream))
989 (do ((char char (%ansi-stream-read-char stream eof-error-p
991 ((or (eq char eof-value)
992 (not (sb-impl::whitespacep char)))
993 (unless (eq char eof-value)
994 (%ansi-stream-unread-char char stream))
997 (%ansi-stream-unread-char char stream)
1000 (cond ((characterp peek-type)
1001 (do ((char (sb-gray:stream-read-char stream)
1002 (sb-gray:stream-read-char stream)))
1003 ((or (eq char :eof) (char= char peek-type))
1004 (cond ((eq char :eof)
1005 (sb-impl::eof-or-lose stream eof-error-p eof-value))
1007 (sb-gray:stream-unread-char stream char)
1010 (do ((char (sb-gray:stream-read-char stream)
1011 (sb-gray:stream-read-char stream)))
1012 ((or (eq char :eof) (not (sb-impl::whitespacep char)))
1013 (cond ((eq char :eof)
1014 (sb-impl::eof-or-lose stream eof-error-p eof-value))
1016 (sb-gray:stream-unread-char stream char)
1019 (let ((char (sb-gray:stream-peek-char stream)))
1021 (sb-impl::eof-or-lose stream eof-error-p eof-value)
1024 (defun listen (&optional (stream *standard-input*) (width 1))
1025 "Returns T if Width octets are available on the given Stream. If Width
1026 is given as 'character, check for a character."
1027 ;; WIDTH is number of octets which must be available; any value
1028 ;; other than 1 is treated as 'character.
1029 (let ((stream (sb-impl::in-synonym-of stream)))
1032 (%listen stream width))
1034 (or (/= (the fixnum (sb-kernel:ansi-stream-in-index stream))
1035 sb-impl::+ansi-stream-in-buffer-length+)
1036 ;; Test for T explicitly since misc methods return :EOF sometimes.
1037 (eq (funcall (sb-kernel:ansi-stream-misc stream) stream :listen)
1040 (sb-gray:stream-listen stream)))))
1043 (defun read-line (&optional (stream *standard-input*) (eof-error-p t)
1044 eof-value recursive-p)
1045 "Returns a line of text read from the Stream as a string, discarding the
1047 (let ((stream (sb-impl::in-synonym-of stream)))
1050 (%read-line stream eof-error-p eof-value recursive-p))
1052 (%ansi-stream-read-line stream eof-error-p eof-value))
1054 (multiple-value-bind (string eof) (sb-gray:stream-read-line stream)
1055 (if (and eof (zerop (length string)))
1056 (values (sb-impl::eof-or-lose stream eof-error-p eof-value) t)
1057 (values string eof)))))))
1059 (defun read-sequence (seq stream &key (start 0) (end nil) partial-fill)
1060 "Destructively modify SEQ by reading elements from STREAM.
1061 SEQ is bounded by START and END. SEQ is destructively modified by
1062 copying successive elements into it from STREAM. If the end of file
1063 for STREAM is reached before copying all elements of the subsequence,
1064 then the extra elements near the end of sequence are not updated, and
1065 the index of the next element is returned."
1066 (let ((stream (sb-impl::in-synonym-of stream))
1067 (end (or end (length seq))))
1070 (with-stream-class (simple-stream stream)
1071 (%read-sequence stream seq start end partial-fill)))
1073 (%ansi-stream-read-sequence seq stream start end))
1075 (sb-gray:stream-read-sequence stream seq start end)))))
1077 (defun clear-input (&optional (stream *standard-input*) buffer-only)
1078 "Clears any buffered input associated with the Stream."
1079 (let ((stream (sb-impl::in-synonym-of stream)))
1082 (%clear-input stream buffer-only))
1084 (setf (sb-kernel:ansi-stream-in-index stream)
1085 sb-impl::+ansi-stream-in-buffer-length+)
1086 (funcall (sb-kernel:ansi-stream-misc stream) stream :clear-input))
1088 (sb-gray:stream-clear-input stream))))
1091 (defun write-byte (integer stream)
1092 "Outputs an octet to the Stream."
1093 (let ((stream (sb-impl::out-synonym-of stream)))
1096 (%write-byte stream integer))
1098 (funcall (sb-kernel:ansi-stream-bout stream) stream integer))
1100 (sb-gray:stream-write-byte stream integer))))
1103 (defun write-char (character &optional (stream *standard-output*))
1104 "Outputs the Character to the Stream."
1105 (let ((stream (sb-impl::out-synonym-of stream)))
1108 (%write-char stream character))
1110 (funcall (sb-kernel:ansi-stream-out stream) stream character))
1112 (sb-gray:stream-write-char stream character))))
1115 (defun write-string (string &optional (stream *standard-output*)
1116 &key (start 0) (end nil))
1117 "Outputs the String to the given Stream."
1118 (let ((stream (sb-impl::out-synonym-of stream))
1119 (end (or end (length string))))
1122 (%write-string stream string start end)
1125 (%ansi-stream-write-string string stream start end))
1127 (sb-gray:stream-write-string stream string start end)))))
1129 (defun write-line (string &optional (stream *standard-output*)
1131 (declare (type string string))
1132 ;; FIXME: Why is there this difference between the treatments of the
1133 ;; STREAM argument in WRITE-STRING and WRITE-LINE?
1134 (let ((stream (sb-impl::out-synonym-of stream))
1135 (end (or end (length string))))
1138 (%check stream :output)
1139 (with-stream-class (simple-stream stream)
1140 (funcall-stm-handler-2 j-write-chars string stream start end)
1141 (funcall-stm-handler-2 j-write-char #\Newline stream)))
1143 (%ansi-stream-write-string string stream start end)
1144 (funcall (sb-kernel:ansi-stream-out stream) stream #\Newline))
1146 (sb-gray:stream-write-string stream string start end)
1147 (sb-gray:stream-terpri stream))))
1150 (defun write-sequence (seq stream &key (start 0) (end nil))
1151 "Write the elements of SEQ bounded by START and END to STREAM."
1152 (let ((stream (sb-impl::out-synonym-of stream))
1153 (end (or end (length seq))))
1156 (%write-sequence stream seq start end))
1158 (%ansi-stream-write-sequence seq stream start end))
1160 (sb-gray:stream-write-sequence stream seq start end)))))
1162 (defun terpri (&optional (stream *standard-output*))
1163 "Outputs a new line to the Stream."
1164 (let ((stream (sb-impl::out-synonym-of stream)))
1167 (%check stream :output)
1168 (with-stream-class (simple-stream stream)
1169 (funcall-stm-handler-2 j-write-char #\Newline stream)))
1171 (funcall (sb-kernel:ansi-stream-out stream) stream #\Newline))
1173 (sb-gray:stream-terpri stream))))
1176 (defun fresh-line (&optional (stream *standard-output*))
1177 "Outputs a new line to the Stream if it is not positioned at the beginning of
1178 a line. Returns T if it output a new line, nil otherwise."
1179 (let ((stream (sb-impl::out-synonym-of stream)))
1182 (%fresh-line stream))
1184 (when (/= (or (sb-kernel:charpos stream) 1) 0)
1185 (funcall (sb-kernel:ansi-stream-out stream) stream #\Newline)
1188 (sb-gray:stream-fresh-line stream)))))
1190 (defun finish-output (&optional (stream *standard-output*))
1191 "Attempts to ensure that all output sent to the Stream has reached its
1192 destination, and only then returns."
1193 (let ((stream (sb-impl::out-synonym-of stream)))
1196 (%finish-output stream))
1198 (funcall (sb-kernel:ansi-stream-misc stream) stream :finish-output))
1200 (sb-gray:stream-finish-output stream))))
1203 (defun force-output (&optional (stream *standard-output*))
1204 "Attempts to force any buffered output to be sent."
1205 (let ((stream (sb-impl::out-synonym-of stream)))
1208 (%force-output stream))
1210 (funcall (sb-kernel:ansi-stream-misc stream) stream :force-output))
1212 (sb-gray:stream-force-output stream))))
1215 (defun clear-output (&optional (stream *standard-output*))
1216 "Clears the given output Stream."
1217 (let ((stream (sb-impl::out-synonym-of stream)))
1220 (%clear-output stream))
1222 (funcall (sb-kernel:ansi-stream-misc stream) stream :clear-output))
1224 (sb-gray:stream-clear-output stream))))
1228 (defun file-position (stream &optional position)
1229 "With one argument returns the current position within the file
1230 File-Stream is open to. If the second argument is supplied, then
1231 this becomes the new file position. The second argument may also
1232 be :start or :end for the start and end of the file, respectively."
1233 (declare (type (or (integer 0 *) (member nil :start :end)) position))
1236 (%file-position stream position))
1240 (setf (sb-kernel:ansi-stream-in-index stream)
1241 sb-impl::+ansi-stream-in-buffer-length+)
1242 (funcall (sb-kernel:ansi-stream-misc stream)
1243 stream :file-position position))
1245 (let ((res (funcall (sb-kernel:ansi-stream-misc stream)
1246 stream :file-position nil)))
1249 (- sb-impl::+ansi-stream-in-buffer-length+
1250 (sb-kernel:ansi-stream-in-index stream))))))))))
1252 (defun file-length (stream)
1253 "This function returns the length of the file that File-Stream is open to."
1256 (%file-length stream))
1258 (progn (sb-impl::stream-must-be-associated-with-file stream)
1259 (funcall (sb-kernel:ansi-stream-misc stream) stream :file-length)))))
1261 (defun charpos (&optional (stream *standard-output*))
1262 "Returns the number of characters on the current line of output of the given
1263 Stream, or Nil if that information is not availible."
1264 (let ((stream (sb-impl::out-synonym-of stream)))
1267 (with-stream-class (simple-stream stream)
1268 (%check stream :open)
1269 (sm charpos stream)))
1271 (funcall (sb-kernel:ansi-stream-misc stream) stream :charpos))
1273 (sb-gray:stream-line-column stream)))))
1275 (defun line-length (&optional (stream *standard-output*))
1276 "Returns the number of characters in a line of output of the given
1277 Stream, or Nil if that information is not availible."
1278 (let ((stream (sb-impl::out-synonym-of stream)))
1281 (%check stream :output)
1282 ;; TODO (sat 2003-04-02): a way to specify a line length would
1283 ;; be good, I suppose. Returning nil here means
1284 ;; sb-pretty::default-line-length is used.
1287 (funcall (sb-kernel:ansi-stream-misc stream) stream :line-length))
1289 (sb-gray:stream-line-length stream)))))
1291 (defun wait-for-input-available (stream &optional timeout)
1292 "Waits for input to become available on the Stream and returns T. If
1293 Timeout expires, Nil is returned."
1294 (let ((stream (sb-impl::in-synonym-of stream)))
1297 (sb-sys:wait-until-fd-usable stream :input timeout))
1299 (%check stream :input)
1300 (with-stream-class (simple-stream stream)
1301 (or (< (sm buffpos stream) (sm buffer-ptr stream))
1302 (wait-for-input-available (sm input-handle stream) timeout))))
1304 (wait-for-input-available (two-way-stream-input-stream stream) timeout))
1306 (wait-for-input-available (symbol-value (synonym-stream-symbol stream))
1308 (sb-sys::file-stream
1309 (or (< (sb-impl::fd-stream-in-index stream)
1310 (length (sb-impl::fd-stream-in-buffer stream)))
1311 (wait-for-input-available (sb-sys:fd-stream-fd stream) timeout))))))
1313 ;; Make PATHNAME and NAMESTRING work
1314 (defun sb-int:file-name (stream &optional new-name)
1317 (with-stream-class (file-simple-stream stream)
1319 (%file-rename stream new-name))
1321 (%file-name stream)))))
1322 (sb-sys::file-stream
1324 (setf (sb-impl::fd-stream-pathname stream) new-name)
1325 (setf (sb-impl::fd-stream-file stream)
1326 (sb-int:unix-namestring new-name nil))
1329 (sb-impl::fd-stream-pathname stream))))))