1.0.2.1: DATA-VECTOR-{REF,SET}-WITH-OFFSET for the x86
[sbcl.git] / src / code / stream.lisp
index b2ea43d..d13c3c5 100644 (file)
     (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)
-  (ansi-stream-file-position stream position))
+  (if (ansi-stream-p stream)
+      (ansi-stream-file-position stream position)
+      (stream-file-position stream position)))
 
 ;;; This is a literal translation of the ANSI glossary entry "stream
 ;;; associated with a file".
            (cond (ch
                   (when (char= ch #\newline)
                     (done-with-fast-read-char)
-                    (return (values (shrink-vector res index) nil)))
+                    (return (values (%shrink-vector res index) nil)))
                   (when (= index len)
                     (setq len (* len 2))
                     (let ((new (make-string len)))
                  ;; shouldn't do another READ-CHAR.
                  (t
                   (done-with-fast-read-char)
-                  (return (values (shrink-vector res index) t)))))))))
+                  (return (values (%shrink-vector res index) t)))))))))
 
 (defun read-line (&optional (stream *standard-input*) (eof-error-p t) eof-value
                             recursive-p)
       ;; must be Gray streams FUNDAMENTAL-STREAM
       (stream-read-sequence stream seq start end)))
 
+(declaim (inline compatible-vector-and-stream-element-types-p))
+(defun compatible-vector-and-stream-element-types-p (vector stream)
+  (declare (type vector vector)
+           (type ansi-stream stream))
+  (or (and (typep vector '(simple-array (unsigned-byte 8) (*)))
+           (subtypep (stream-element-type stream) '(unsigned-byte 8)))
+      (and (typep vector '(simple-array (signed-byte 8) (*)))
+           (subtypep (stream-element-type stream) '(signed-byte 8)))))
+
 (defun ansi-stream-read-sequence (seq stream start %end)
   (declare (type sequence seq)
            (type ansi-stream stream)
              (setf (first rem) el)))))
       (vector
        (with-array-data ((data seq) (offset-start start) (offset-end end))
-         (typecase data
-           ((or (simple-array (unsigned-byte 8) (*))
-                (simple-array (signed-byte 8) (*)))
-            (let* ((numbytes (- end start))
-                   (bytes-read (read-n-bytes stream data offset-start
-                                             numbytes nil)))
-              (if (< bytes-read numbytes)
-                  (+ start bytes-read)
-                  end)))
-           (t
-            (let ((read-function
-                   (if (subtypep (stream-element-type stream) 'character)
-                       #'ansi-stream-read-char
-                       #'ansi-stream-read-byte)))
-              (do ((i offset-start (1+ i)))
-                  ((>= i offset-end) end)
-                (declare (type index i))
-                (let ((el (funcall read-function stream nil :eof nil)))
-                  (when (eq el :eof)
-                    (return (+ start (- i offset-start))))
-                  (setf (aref data i) el)))))))))))
+         (if (compatible-vector-and-stream-element-types-p data stream)
+             (let* ((numbytes (- end start))
+                    (bytes-read (read-n-bytes stream data offset-start
+                                              numbytes nil)))
+               (if (< bytes-read numbytes)
+                   (+ start bytes-read)
+                   end))
+             (let ((read-function
+                    (if (subtypep (stream-element-type stream) 'character)
+                        ;; If the stream-element-type is CHARACTER,
+                        ;; this might be a bivalent stream. If the
+                        ;; sequence is a specialized unsigned-byte
+                        ;; vector, try to read use binary IO. It'll
+                        ;; signal an error if stream is an pure
+                        ;; character stream.
+                        (if (subtypep (array-element-type data)
+                                      'unsigned-byte)
+                            #'ansi-stream-read-byte
+                            #'ansi-stream-read-char)
+                        #'ansi-stream-read-byte)))
+               (do ((i offset-start (1+ i)))
+                   ((>= i offset-end) end)
+                 (declare (type index i))
+                 (let ((el (funcall read-function stream nil :eof nil)))
+                   (when (eq el :eof)
+                     (return (+ start (- i offset-start))))
+                   (setf (aref data i) el))))))))))
 \f
 ;;;; WRITE-SEQUENCE
 
              ((output-seq-in-loop ()
                 (let ((write-function
                        (if (subtypep (stream-element-type stream) 'character)
-                           (ansi-stream-out stream)
+                           (lambda (stream object)
+                             ;; This might be a bivalent stream, so we need
+                             ;; to dispatch on a per-element basis, rather
+                             ;; than just based on the sequence or stream
+                             ;; element types.
+                             (if (characterp object)
+                                 (funcall (ansi-stream-out stream)
+                                          stream object)
+                                 (funcall (ansi-stream-bout stream)
+                                          stream object)))
                            (ansi-stream-bout stream))))
                   (do ((i offset-start (1+ i)))
                       ((>= i offset-end))
                     (declare (type index i))
                     (funcall write-function stream (aref data i))))))
-           (typecase data
-             ((or (simple-array (unsigned-byte 8) (*))
-                  (simple-array (signed-byte 8) (*)))
-              (if (fd-stream-p stream)
-                  (output-raw-bytes stream data offset-start offset-end)
-                  (output-seq-in-loop)))
-             (t
-              (output-seq-in-loop))))))))
+           (if (and (fd-stream-p stream)
+                    (compatible-vector-and-stream-element-types-p data stream))
+               (output-raw-bytes stream data offset-start offset-end)
+               (output-seq-in-loop)))))))
   seq)
 \f
 ;;;; etc.