X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fstream.lisp;h=5d339b7c061873d4580ca69189ed69c4b70a0cfb;hb=25fe91bf63fd473d9316675b0e0ca9be0079e9eb;hp=a8a13503bed01f1cecc3b5ae5b56884cce4f3414;hpb=4c4635c16dc6fb5fcc6adbaea9fba756083c04a2;p=sbcl.git diff --git a/src/code/stream.lisp b/src/code/stream.lisp index a8a1350..5d339b7 100644 --- a/src/code/stream.lisp +++ b/src/code/stream.lisp @@ -157,9 +157,24 @@ (t (let ((res (funcall (ansi-stream-misc stream) stream :file-position nil))) (when res + #!-sb-unicode (- res (- +ansi-stream-in-buffer-length+ - (ansi-stream-in-index stream)))))))) + (ansi-stream-in-index stream))) + #!+sb-unicode + (let* ((external-format (stream-external-format stream)) + (ef-entry (find-external-format external-format)) + (variable-width-p (variable-width-external-format-p ef-entry)) + (char-len (bytes-for-char-fun ef-entry))) + (- res + (if variable-width-p + (loop with buffer = (ansi-stream-cin-buffer stream) + with start = (ansi-stream-in-index stream) + for i from start below +ansi-stream-in-buffer-length+ + sum (funcall char-len (aref buffer i))) + (* (funcall char-len #\x) ; arbitrary argument + (- +ansi-stream-in-buffer-length+ + (ansi-stream-in-index stream))))))))))) (defun file-position (stream &optional position) @@ -223,33 +238,50 @@ (defun ansi-stream-read-line (stream eof-error-p eof-value recursive-p) (declare (ignore recursive-p)) (prepare-for-fast-read-char stream - (let ((res (make-string 80)) - (len 80) - (index 0)) - (loop - (let ((ch (fast-read-char nil nil))) - (cond (ch - (when (char= ch #\newline) - (done-with-fast-read-char) - (return (values (shrink-vector res index) nil))) - (when (= index len) - (setq len (* len 2)) - (let ((new (make-string len))) - (replace new res) - (setq res new))) - (setf (schar res index) ch) - (incf index)) - ((zerop index) - (done-with-fast-read-char) - (return (values (eof-or-lose stream - eof-error-p - eof-value) - t))) - ;; Since FAST-READ-CHAR already hit the eof char, we - ;; shouldn't do another READ-CHAR. - (t - (done-with-fast-read-char) - (return (values (shrink-vector res index) t))))))))) + ;; Check whether the FAST-READ-CHAR buffer contains a newline. If it + ;; does, we can do things quickly by just copying the line from the + ;; buffer instead of doing repeated calls to FAST-READ-CHAR. + (when %frc-buffer% + (locally + ;; For %FIND-POSITION transform + (declare (optimize (speed 2))) + (let ((pos (position #\Newline %frc-buffer% + :test #'char= + :start %frc-index%))) + (when pos + (let* ((len (- pos %frc-index%)) + (res (make-string len))) + (replace res %frc-buffer% :start2 %frc-index% :end2 pos) + (setf %frc-index% (1+ pos)) + (done-with-fast-read-char) + (return-from ansi-stream-read-line res)))))) + (let ((res (make-string 80)) + (len 80) + (index 0)) + (loop + (let ((ch (fast-read-char nil nil))) + (cond (ch + (when (char= ch #\newline) + (done-with-fast-read-char) + (return (values (%shrink-vector res index) nil))) + (when (= index len) + (setq len (* len 2)) + (let ((new (make-string len))) + (replace new res) + (setq res new))) + (setf (schar res index) ch) + (incf index)) + ((zerop index) + (done-with-fast-read-char) + (return (values (eof-or-lose stream + eof-error-p + eof-value) + t))) + ;; Since FAST-READ-CHAR already hit the eof char, we + ;; shouldn't do another READ-CHAR. + (t + (done-with-fast-read-char) + (return (values (%shrink-vector res index) t))))))))) (defun read-line (&optional (stream *standard-input*) (eof-error-p t) eof-value recursive-p)