(in-package "SB!IMPL")
-(deftype string-stream ()
- '(or string-input-stream string-output-stream
- fill-pointer-output-stream))
-
;;;; standard streams
;;; The initialization of these streams is performed by
\f
;;; stream manipulation functions
-(defun input-stream-p (stream)
- (declare (type stream stream))
+(declaim (inline ansi-stream-input-stream-p))
+(defun ansi-stream-input-stream-p (stream)
+ (declare (type ansi-stream stream))
#!+high-security
(when (synonym-stream-p stream)
(setf stream
(symbol-value (synonym-stream-symbol stream))))
- (and (ansi-stream-p stream)
- (not (eq (ansi-stream-in stream) #'closed-flame))
+ (and (not (eq (ansi-stream-in stream) #'closed-flame))
;;; KLUDGE: It's probably not good to have EQ tests on function
;;; values like this. What if someone's redefined the function?
;;; Is there a better way? (Perhaps just VALID-FOR-INPUT and
(or (not (eq (ansi-stream-in stream) #'ill-in))
(not (eq (ansi-stream-bin stream) #'ill-bin)))))
-(defun output-stream-p (stream)
+(defun input-stream-p (stream)
(declare (type stream stream))
+ (and (ansi-stream-p stream)
+ (ansi-stream-input-stream-p stream)))
+
+(declaim (inline ansi-stream-output-stream-p))
+(defun ansi-stream-output-stream-p (stream)
+ (declare (type ansi-stream stream))
#!+high-security
(when (synonym-stream-p stream)
(setf stream (symbol-value
(synonym-stream-symbol stream))))
- (and (ansi-stream-p stream)
- (not (eq (ansi-stream-in stream) #'closed-flame))
+ (and (not (eq (ansi-stream-in stream) #'closed-flame))
(or (not (eq (ansi-stream-out stream) #'ill-out))
(not (eq (ansi-stream-bout stream) #'ill-bout)))))
-(defun open-stream-p (stream)
+(defun output-stream-p (stream)
(declare (type stream stream))
+
+ (and (ansi-stream-p stream)
+ (ansi-stream-output-stream-p stream)))
+
+(declaim (inline ansi-stream-open-stream-p))
+(defun ansi-stream-open-stream-p (stream)
+ (declare (type ansi-stream stream))
(not (eq (ansi-stream-in stream) #'closed-flame)))
-(defun stream-element-type (stream)
- (declare (type stream stream))
+(defun open-stream-p (stream)
+ (ansi-stream-open-stream-p stream))
+
+(declaim (inline ansi-stream-element-type))
+(defun ansi-stream-element-type (stream)
+ (declare (type ansi-stream stream))
(funcall (ansi-stream-misc stream) stream :element-type))
+(defun stream-element-type (stream)
+ (ansi-stream-element-type stream))
+
(defun interactive-stream-p (stream)
(declare (type stream stream))
(funcall (ansi-stream-misc stream) stream :interactive-p))
-(defun close (stream &key abort)
- (declare (type stream stream))
+(declaim (inline ansi-stream-close))
+(defun ansi-stream-close (stream abort)
+ (declare (type ansi-stream stream))
(when (open-stream-p stream)
(funcall (ansi-stream-misc stream) stream :close abort))
t)
+(defun close (stream &key abort)
+ (ansi-stream-close stream abort))
+
(defun set-closed-flame (stream)
(setf (ansi-stream-in stream) #'closed-flame)
(setf (ansi-stream-bin stream) #'closed-flame)
(stream-fresh-line stream))))
(defun write-string (string &optional (stream *standard-output*)
- &key (start 0) (end nil))
- (%write-string string stream start (or end (length string)))
- string)
-
-(defun %write-string (string stream start end)
+ &key (start 0) end)
(declare (type string string))
- (declare (type streamlike stream))
- (declare (type index start end))
-
;; Note that even though you might expect, based on the behavior of
;; things like AREF, that the correct upper bound here is
;; (ARRAY-DIMENSION STRING 0), the ANSI glossary definitions for
;; "bounding index" and "length" indicate that in this case (i.e.
- ;; for the ANSI-specified functions WRITE-STRING and WRITE-LINE
- ;; which are implemented in terms of this function), (LENGTH STRING)
- ;; is the required upper bound. A foolish consistency is the
- ;; hobgoblin of lesser languages..
- (unless (<= 0 start end (length string))
- (error "~@<bad bounding indices START=~W END=~W for ~2I~_~S~:>"
- start
- end
- string))
+ ;; for the ANSI-specified functions WRITE-STRING [and WRITE-LINE]),
+ ;; (LENGTH STRING) is the required upper bound. A foolish
+ ;; consistency is the hobgoblin of lesser languages..
+ (%write-string string stream start (%check-vector-sequence-bounds
+ string start end))
+ string)
+(defun %write-string (string stream start end)
+ (declare (type string string))
+ (declare (type streamlike stream))
+ (declare (type index start end))
(let ((stream (out-synonym-of stream)))
(cond ((ansi-stream-p stream)
(if (array-header-p string)
(stream-write-string stream string start end)))))
(defun write-line (string &optional (stream *standard-output*)
- &key (start 0) (end nil))
- (let ((defaulted-stream (out-synonym-of stream))
- (defaulted-end (or end (length string))))
- (%write-string string defaulted-stream start defaulted-end)
+ &key (start 0) end)
+ (declare (type string string))
+ ;; FIXME: Why is there this difference between the treatments of the
+ ;; STREAM argument in WRITE-STRING and WRITE-LINE?
+ (let ((defaulted-stream (out-synonym-of stream)))
+ (%write-string string defaulted-stream start (%check-vector-sequence-bounds
+ string start end))
(write-char #\newline defaulted-stream))
string)
(let* ((stream (car current))
(result (,fun stream nil nil)))
(when result (return result)))
- (setf (concatenated-stream-current stream) current)))))
+ (pop (concatenated-stream-current stream))))))
(in-fun concatenated-in read-char)
(in-fun concatenated-bin read-byte))
(in-fun echo-bin read-byte ansi-stream-bout stream-write-byte
eof-error-p eof-value))
-
(defun echo-misc (stream operation &optional arg1 arg2)
(let* ((in (two-way-stream-input-stream stream))
(out (two-way-stream-output-stream stream)))
(set-closed-flame stream))
(:peek-char
;; For the special case of peeking into an echo-stream
- ;; arg1 is peek-type, arg2 is (eof-error-p eof-value)
+ ;; arg1 is PEEK-TYPE, arg2 is (EOF-ERROR-P EOF-VALUE)
;; returns peeked-char, eof-value, or errors end-of-file
- (flet ((outfn (c)
- (if (ansi-stream-p out)
- (funcall (ansi-stream-out out) out c)
- ;; gray-stream
- (stream-write-char out c))))
- (generalized-peeking-mechanism
- arg1 (second arg2) char
- (read-char in (first arg2) (second arg2))
- (unread-char char in)
- (outfn char))))
+ ;;
+ ;; Note: This code could be moved into PEEK-CHAR if desired.
+ ;; I am unsure whether this belongs with echo-streams because it is
+ ;; echo-stream specific, or PEEK-CHAR because it is peeking code.
+ ;; -- mrd 2002-11-18
+ ;;
+ ;; UNREAD-CHAR-P indicates whether the current character was one
+ ;; that was previously unread. In that case, we need to ensure that
+ ;; the semantics for UNREAD-CHAR are held; the character should
+ ;; not be echoed again.
+ (let ((unread-char-p nil))
+ (flet ((outfn (c)
+ (unless unread-char-p
+ (if (ansi-stream-p out)
+ (funcall (ansi-stream-out out) out c)
+ ;; gray-stream
+ (stream-write-char out c))))
+ (infn ()
+ ;; Obtain input from unread buffer or input stream,
+ ;; and set the flag appropriately.
+ (cond ((not (null (echo-stream-unread-stuff stream)))
+ (setf unread-char-p t)
+ (pop (echo-stream-unread-stuff stream)))
+ (t
+ (setf unread-char-p nil)
+ (read-char in (first arg2) (second arg2))))))
+ (generalized-peeking-mechanism
+ arg1 (second arg2) char
+ (infn)
+ (unread-char char in)
+ (outfn char)))))
(t
(or (if (ansi-stream-p in)
(funcall (ansi-stream-misc in) in operation arg1 arg2)
(if (ansi-stream-p out)
(funcall (ansi-stream-misc out) out operation arg1 arg2)
(stream-misc-dispatch out operation arg1 arg2)))))))
+\f
+;;;; base STRING-STREAM stuff
+(defstruct (string-stream
+ (:include ansi-stream)
+ (:constructor nil)
+ (:copier nil))
+ (string nil :type string))
\f
-;;;; string input streams
+;;;; STRING-INPUT-STREAM stuff
(defstruct (string-input-stream
- (:include ansi-stream
+ (:include string-stream
(in #'string-inch)
(bin #'string-binch)
(n-bin #'string-stream-read-n-bytes)
- (misc #'string-in-misc))
+ (misc #'string-in-misc)
+ (string nil :type simple-string))
(:constructor internal-make-string-input-stream
(string current end))
(:copier nil))
- (string nil :type simple-string)
(current nil :type index)
(end nil :type index))
(:element-type 'base-char)))
(defun make-string-input-stream (string &optional
- (start 0) (end (length string)))
+ (start 0) end)
#!+sb-doc
"Return an input stream which will supply the characters of STRING between
START and END in order."
(declare (type string string)
(type index start)
(type (or index null) end))
-
- #!+high-security
- (when (> end (length string))
- (cerror "Continue with end changed from ~S to ~S"
- "Write-string: end (~S) is larger then the length of the string (~S)"
- end (1- (length string))))
-
- (internal-make-string-input-stream (coerce string 'simple-string)
- start end))
+
+ (internal-make-string-input-stream
+ (coerce string 'simple-string)
+ start
+ (%check-vector-sequence-bounds string start end)))
\f
-;;;; string output streams
+;;;; STRING-OUTPUT-STREAM stuff
(defstruct (string-output-stream
- (:include ansi-stream
+ (:include string-stream
(out #'string-ouch)
(sout #'string-sout)
- (misc #'string-out-misc))
+ (misc #'string-out-misc)
+ ;; The string we throw stuff in.
+ (string (make-string 40) :type simple-string))
(:constructor make-string-output-stream ())
(:copier nil))
- ;; The string we throw stuff in.
- (string (make-string 40) :type simple-string)
;; Index of the next location to use.
(index 0 :type fixnum))
(satisfies array-has-fill-pointer-p)))
(defstruct (fill-pointer-output-stream
- (:include ansi-stream
+ (:include string-stream
(out #'fill-pointer-ouch)
(sout #'fill-pointer-sout)
- (misc #'fill-pointer-misc))
+ (misc #'fill-pointer-misc)
+ ;; a string with a fill pointer where we stuff
+ ;; the stuff we write
+ (string (error "missing argument")
+ :type string-with-fill-pointer
+ :read-only t))
(:constructor make-fill-pointer-output-stream (string))
- (:copier nil))
- ;; a string with a fill pointer where we stuff the stuff we write
- (string (error "missing argument")
- :type string-with-fill-pointer
- :read-only t))
+ (:copier nil)))
(defun fill-pointer-ouch (stream character)
(let* ((buffer (fill-pointer-output-stream-string stream))
\f
;;;; READ-SEQUENCE
-(defun read-sequence (seq stream &key (start 0) (end nil))
+(defun read-sequence (seq stream &key (start 0) end)
#!+sb-doc
"Destructively modify SEQ by reading elements from STREAM.
That part of SEQ bounded by START and END is destructively modified by