0.9.6.3:
authorJuho Snellman <jsnell@iki.fi>
Thu, 27 Oct 2005 22:30:26 +0000 (22:30 +0000)
committerJuho Snellman <jsnell@iki.fi>
Thu, 27 Oct 2005 22:30:26 +0000 (22:30 +0000)
Faster READ-LINE.

        * Peek directly into the FAST-READ-CHAR buffer at the start of
          READ-LINE. If it contains a newline, just copy the data directly
          from the buffer to the result string instead of doing a
          character-by-character copy.

src/code/stream.lisp
src/code/sysmacs.lisp
version.lisp-expr

index a8a1350..b2ea43d 100644 (file)
 (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)
index bcb8255..a7e98dd 100644 (file)
@@ -119,6 +119,9 @@ waits until gc is enabled in this thread."
 ;;; This macro sets up some local vars for use by the
 ;;; FAST-READ-CHAR macro within the enclosed lexical scope. The stream
 ;;; is assumed to be a ANSI-STREAM.
+;;;
+;;; KLUDGE: Some functions (e.g. ANSI-STREAM-READ-LINE) use these variables
+;;; directly, instead of indirecting through FAST-READ-CHAR.
 (defmacro prepare-for-fast-read-char (stream &body forms)
   `(let* ((%frc-stream% ,stream)
           (%frc-method% (ansi-stream-in %frc-stream%))
@@ -134,7 +137,7 @@ waits until gc is enabled in this thread."
   `(setf (ansi-stream-in-index %frc-stream%) %frc-index%))
 
 ;;; a macro with the same calling convention as READ-CHAR, to be used
-;;; within the scope of a PREPARE-FOR-FAST-READ-CHAR
+;;; within the scope of a PREPARE-FOR-FAST-READ-CHAR.
 (defmacro fast-read-char (&optional (eof-error-p t) (eof-value ()))
   `(cond
     ((not %frc-buffer%)
index 364ce11..98bb3bd 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.6.2"
+"0.9.6.3"