- &aux (total-copied 0))
- (declare (type fd-stream stream))
- (declare (type index start requested total-copied))
- (let ((unread (fd-stream-unread stream)))
- (when unread
- (setf (aref buffer start) unread)
- (setf (fd-stream-unread stream) nil)
- (setf (fd-stream-listen stream) nil)
- (incf total-copied)))
- (do ()
- (nil)
- (let* ((head (fd-stream-ibuf-head stream))
- (tail (fd-stream-ibuf-tail stream))
- (sap (fd-stream-ibuf-sap stream)))
- (declare (type index head tail))
- ;; Copy data from stream buffer into user's buffer.
- (do ((size nil nil))
- ((or (= tail head) (= requested total-copied)))
- (restart-case
- (unless (block character-decode
- (let ((byte (sap-ref-8 sap head)))
- (setq size ,in-size-expr)
- (when (> size (- tail head))
- (return))
- (setf (aref buffer (+ start total-copied))
- ,in-expr)
- (incf total-copied)
- (incf head size)))
- (setf (fd-stream-ibuf-head stream) head)
- (if (plusp total-copied)
- (return-from ,in-function total-copied)
- (stream-decoding-error
- stream
- (if size
- (loop for i from 0 below size
- collect (sap-ref-8 (fd-stream-ibuf-sap
- stream)
- (+ (fd-stream-ibuf-head
- stream)
- i)))
- (list (sap-ref-8 (fd-stream-ibuf-sap stream)
- (fd-stream-ibuf-head stream)))))))
- (attempt-resync ()
- :report (lambda (stream)
- (format stream
- "~@<Attempt to resync the stream at a ~
- character boundary and continue.~@:>"))
- (,resync-function stream)
- (setf head (fd-stream-ibuf-head stream)))
- (force-end-of-file ()
- :report (lambda (stream)
- (format stream "~@<Force an end of file.~@:>"))
- (if eof-error-p
- (error 'end-of-file :stream stream)
- (return-from ,in-function total-copied)))))
- (setf (fd-stream-ibuf-head stream) head)
- ;; Maybe we need to refill the stream buffer.
- (cond ( ;; If there were enough data in the stream buffer, we're done.
- (= total-copied requested)
- (return total-copied))
- ( ;; If EOF, we're done in another way.
- (zerop (refill-fd-stream-buffer stream))
- (if eof-error-p
- (error 'end-of-file :stream stream)
- (return total-copied)))
- ;; Otherwise we refilled the stream buffer, so fall
- ;; through into another pass of the loop.
- ))))
+ &aux (total-copied 0))
+ (declare (type fd-stream stream))
+ (declare (type index start requested total-copied))
+ (declare (type (simple-array character (#.+ansi-stream-in-buffer-length+)) buffer))
+ (let ((unread (fd-stream-unread stream)))
+ (when unread
+ (setf (aref buffer start) unread)
+ (setf (fd-stream-unread stream) nil)
+ (setf (fd-stream-listen stream) nil)
+ (incf total-copied)))
+ (do ()
+ (nil)
+ (let* ((head (fd-stream-ibuf-head stream))
+ (tail (fd-stream-ibuf-tail stream))
+ (sap (fd-stream-ibuf-sap stream))
+ (decode-break-reason nil))
+ (declare (type index head tail))
+ ;; Copy data from stream buffer into user's buffer.
+ (do ((size nil nil))
+ ((or (= tail head) (= requested total-copied)))
+ (setf decode-break-reason
+ (block decode-break-reason
+ (let ((byte (sap-ref-8 sap head)))
+ (declare (ignorable byte))
+ (setq size ,in-size-expr)
+ (when (> size (- tail head))
+ (return))
+ (setf (aref buffer (+ start total-copied)) ,in-expr)
+ (incf total-copied)
+ (incf head size))
+ nil))
+ (setf (fd-stream-ibuf-head stream) head)
+ (when decode-break-reason
+ ;; If we've already read some characters on when the invalid
+ ;; code sequence is detected, we return immediately. The
+ ;; handling of the error is deferred until the next call
+ ;; (where this check will be false). This allows establishing
+ ;; high-level handlers for decode errors (for example
+ ;; automatically resyncing in Lisp comments).
+ (when (plusp total-copied)
+ (return-from ,in-function total-copied))
+ (when (stream-decoding-error-and-handle
+ stream decode-break-reason)
+ (if eof-error-p
+ (error 'end-of-file :stream stream)
+ (return-from ,in-function total-copied)))
+ (setf head (fd-stream-ibuf-head stream))
+ (setf tail (fd-stream-ibuf-tail stream))))
+ (setf (fd-stream-ibuf-head stream) head)
+ ;; Maybe we need to refill the stream buffer.
+ (cond ( ;; If there were enough data in the stream buffer, we're done.
+ (= total-copied requested)
+ (return total-copied))
+ ( ;; If EOF, we're done in another way.
+ (or (eq decode-break-reason 'eof)
+ (null (catch 'eof-input-catcher
+ (refill-buffer/fd stream))))
+ (if eof-error-p
+ (error 'end-of-file :stream stream)
+ (return total-copied)))
+ ;; Otherwise we refilled the stream buffer, so fall
+ ;; through into another pass of the loop.
+ ))))