~ chicken-core (master) 9d2dc48f52afa26f77a20c849377a831504767df
commit 9d2dc48f52afa26f77a20c849377a831504767df
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Sun Oct 5 19:48:45 2025 +0200
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Sun Oct 5 19:48:45 2025 +0200
overhaul copy-port to default to bytevector-oriented I/O
diff --git a/port.scm b/port.scm
index 83e49fef..8cad547f 100644
--- a/port.scm
+++ b/port.scm
@@ -190,51 +190,66 @@ char *ttyname(int fd) {
(define copy-port
(let ((read-char read-char)
- (write-char write-char))
- (define (read-buf port writer)
- (let ((buf (make-string +buf-size+)))
- (let loop ()
- (let ((n (read-string! +buf-size+ buf port)))
- (unless (eq? n 0)
- (writer buf n)
- (loop))))))
- (define (write-buf buf n port writer)
- (do ((i 0 (fx+ i 1)))
- ((fx>= i n))
- (writer (string-ref buf i) port)))
- (define (read-and-write reader writer)
+ (write-char write-char))
+ (define (read-and-write src dest)
+ (##sys#check-port src 'copy-port)
+ (##sys#check-port dest 'copy-port)
+ (let ((buf (##sys#make-bytevector +buf-size+)))
+ (let loop ()
+ (let ((n (chicken.io#read-bytevector!/port +buf-size+
+ buf src 0)))
+ (unless (eq? n 0)
+ (chicken.io#write-bytevector buf dest 0 n)
+ (loop))))))
+ (define (read-and-delegate src dest writer)
+ (##sys#check-port src 'copy-port)
+ (let ((buf (##sys#make-bytevector +buf-size+)))
+ (let loop ((p 0))
+ (let* ((n (chicken.io#read-bytevector!/port
+ (fx- +buf-size+ p)
+ buf src p))
+ (fc (##core#inline "C_utf_fragment_counts" buf 0 n))
+ (full (fxshr fc 4))
+ (part (fxand fc 7))
+ (str (##sys#buffer->string buf 0 (fx- n part))))
+ (unless (eq? n 0)
+ (do ((i 0 (fx+ i 1)))
+ ((fx>= i full))
+ (writer (string-ref str i) dest))
+ ;; overlaps, buf source will be at end of buffer
+ (##core#inline "C_copy_memory_with_offset"
+ buf buf
+ (fx- (fx- (##sys#size (##sys#slot str 0)) 1) part)
+ 0 part)
+ (loop part))))))
+ (define (delegate src reader dest writer)
(let loop ()
- (let ((x (reader)))
- (unless (eof-object? x)
- (writer x)
- (loop)))))
- (define (read-and-write-buf src dest reader)
- (let ((buf (make-string +buf-size+)))
- (let loop ((n 0))
- (when (fx>= n +buf-size+)
- (scheme#write-string buf dest 0 +buf-size+)
- (set! n 0))
- (let ((c (reader src)))
- (cond ((eof-object? c)
- (when (fx>= n 0)
- (scheme#write-string buf dest 0 n)))
- (else
- (string-set! buf n c)
- (loop (fx+ n 1))))))))
+ (let ((x (reader src)))
+ (unless (eof-object? x)
+ (writer x dest)
+ (loop)))))
+ (define (delegate-and-write src reader dest)
+ (##sys#check-port dest 'copy-port)
+ (let ((buf (##sys#make-bytevector (fx+ 4 +buf-size+))))
+ (let loop ((n 0))
+ (when (fx>= n +buf-size+)
+ (chicken.io#write-bytevector buf dest 0 n)
+ (set! n 0))
+ (let ((c (reader src)))
+ (cond ((eof-object? c)
+ (when (fx>= n 0)
+ (chicken.io#write-bytevector buf dest 0 n)))
+ (else
+ (loop (##core#inline "C_utf_insert" buf n c))))))))
(lambda (src dest #!optional (read read-char) (write write-char))
;; does not check port args intentionally
(cond ((eq? read read-char)
- (read-buf
- src
- (if (eq? write write-char)
- (lambda (buf n) (scheme#write-string buf dest 0 n))
- (lambda (buf n) (write-buf buf n dest write)))))
- ((eq? write write-char)
- (read-and-write-buf src dest read))
- (else
- (read-and-write
- (lambda () (read src))
- (lambda (x) (write x dest))))))))
+ (if (eq? write write-char)
+ (read-and-write src dest)
+ (read-and-delegate src dest write)))
+ ((eq? write write-char)
+ (delegate-and-write src read dest))
+ (else (delegate src read dest write))))))
;;;; funky-ports
Trap