Skip to content
Snippets Groups Projects
Commit bc127deb authored by Sebastian Melzer's avatar Sebastian Melzer Committed by Philipp Marek
Browse files

Unnecessary copies and pitfalls in read-stream-content-into-byte-vector

parent 2f39fbf3
No related branches found
No related tags found
No related merge requests found
...@@ -95,29 +95,35 @@ unless it's NIL, which means the system default." ...@@ -95,29 +95,35 @@ unless it's NIL, which means the system default."
(defun read-stream-content-into-byte-vector (stream &key ((%length length)) (defun read-stream-content-into-byte-vector (stream &key ((%length length))
(initial-size 4096)) (initial-size 4096))
"Return \"content\" of STREAM as freshly allocated (unsigned-byte 8) vector." "Return \"content\" of STREAM as freshly allocated (unsigned-byte 8) vector."
(check-type length (or null non-negative-integer)) (check-type length (or null non-negative-integer)) ; for compatibility
(check-type initial-size positive-integer) (check-type initial-size non-negative-integer)
(do ((buffer (make-array (or length initial-size) (setf initial-size (or length initial-size))
:element-type '(unsigned-byte 8))) (let ((result (make-array initial-size :element-type '(unsigned-byte 8)))
(offset 0) (bytes-read 0))
(offset-wanted 0)) (loop
((or (/= offset-wanted offset) (setf bytes-read (read-sequence result stream :start bytes-read))
(and length (>= offset length))) (when (and length (>= bytes-read length))
(if (= offset (length buffer)) (return))
buffer ;; There is no PEEK-BYTE, so we just try to read a byte.
(subseq buffer 0 offset))) (let ((next-byte (read-byte stream nil nil)))
(unless (zerop offset) (when (null next-byte)
(let ((new-buffer (make-array (* 2 (length buffer)) (return))
:element-type '(unsigned-byte 8)))) (let ((new-result (make-array (if (zerop (length result))
(replace new-buffer buffer) 4096
(setf buffer new-buffer))) (* 2 (length result)))
(setf offset-wanted (length buffer) :element-type '(unsigned-byte 8))))
offset (read-sequence buffer stream :start offset)))) (replace new-result result :end1 bytes-read :end2 bytes-read)
(setf (aref new-result bytes-read) next-byte
result new-result)
(incf bytes-read))))
(if (= bytes-read (length result))
result
(subseq result 0 bytes-read))))
(defun read-file-into-byte-vector (pathname) (defun read-file-into-byte-vector (pathname)
"Read PATHNAME into a freshly allocated (unsigned-byte 8) vector." "Read PATHNAME into a freshly allocated (unsigned-byte 8) vector."
(with-input-from-file (stream pathname :element-type '(unsigned-byte 8)) (with-input-from-file (stream pathname :element-type '(unsigned-byte 8))
(read-stream-content-into-byte-vector stream '%length (file-length stream)))) (read-stream-content-into-byte-vector stream :initial-size (file-length stream))))
(defun write-byte-vector-into-file (bytes pathname &key (if-exists :error) (defun write-byte-vector-into-file (bytes pathname &key (if-exists :error)
if-does-not-exist) if-does-not-exist)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment