lloda pushed a commit to branch main
in repository guile.

commit ee9df40d64749c0e19b14856bc9e25df656bca34
Author: Rob Browning <[email protected]>
AuthorDate: Thu Apr 10 15:35:27 2025 -0500

    make-bytestring(!): only allocate once and and write directly
    
    Change make-bytestring! to write the parts directly to the result rather
    than by way of a bytevector port. Rewrite make-bytestring to compute the
    result length first so it can immediately allocate the result and then
    fill it in via the new make-bytestring!
    
    * module/srfi/srfi-207.scm: add new make-bytestring and make-bytestring!
    * module/srfi/srfi-207/upstream/bytestrings-impl.scm: remove
    make-bytestring and make-bytestring!
---
 module/srfi/srfi-207.scm                           | 42 ++++++++++++++++++++--
 module/srfi/srfi-207/upstream/bytestrings-impl.scm | 14 --------
 2 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/module/srfi/srfi-207.scm b/module/srfi/srfi-207.scm
index b77016f3c..42a42fa97 100644
--- a/module/srfi/srfi-207.scm
+++ b/module/srfi/srfi-207.scm
@@ -30,8 +30,7 @@
                           make-exception-with-irritants))
   #:use-module ((rnrs arithmetic bitwise) #:select (bitwise-and bitwise-ior))
   #:use-module ((rnrs bytevectors)
-                #:select (bytevector->u8-list u8-list->bytevector))
-  #:use-module ((rnrs io ports) #:select (string->bytevector))
+                #:select (bytevector->u8-list string->utf8 
u8-list->bytevector))
   #:use-module ((scheme base)
                 #:select (binary-port?
                           bytevector
@@ -105,6 +104,45 @@
 (include-from-path "srfi/srfi-207/upstream/base64.scm")
 (include-from-path "srfi/srfi-207/upstream/bytestrings-impl.scm")
 
+(define (make-bytestring! bvec at parts)
+  (let lp ((parts parts)
+           (i at))
+    (unless (null? parts)
+      (let ((x (car parts)))
+        (cond
+         ((and (exact-natural? x) (< x 256))
+          (bytevector-u8-set! bvec i x)
+          (lp (cdr parts) (1+ i)))
+         ((and (char? x) (char<=? x #\delete))
+          (bytevector-u8-set! bvec i (char->integer x))
+          (lp (cdr parts) (1+ i)))
+         ((bytevector? x)
+          (bytevector-copy! bvec i x 0 (bytevector-length x))
+          (lp (cdr parts) (+ i (bytevector-length x))))
+         ((string? x)
+          (let ((n (string-length x))
+                (utf8 (string->utf8 x)))
+            (unless (= n (bytevector-length utf8))
+              (bytestring-error "bytestring string part is not ASCII" x))
+            (bytevector-copy! bvec i utf8 0 n)
+            (lp (cdr parts) (+ i (string-length x)))))
+         (else
+          (bytestring-error "invalid bytestring string part" x)))))))
+
+(define (make-bytestring parts)
+  (define (byte-len x)
+    (cond
+     ((and (integer? x) (<= 0 x 255)) 1)
+     ((and (char? x) (char<=? #\delete)) 1)
+     ((bytevector? x) (bytevector-length x))
+     ((and (string? x) (string-every char-set:ascii x)) (string-length x))
+     (else (bytestring-error "invalid bytestring argument" x))))
+  (let* ((n (fold (λ (part total) (+ total (byte-len part)))
+                  0 parts))
+         (result (make-bytevector n)))
+    (make-bytestring! result 0 parts)
+    result))
+
 (define (read-bytestring-content port)
   ;; Must use port, not (peek)/(next).
   (let ((ch (read-char port)))
diff --git a/module/srfi/srfi-207/upstream/bytestrings-impl.scm 
b/module/srfi/srfi-207/upstream/bytestrings-impl.scm
index fb8908b60..f91fbd726 100644
--- a/module/srfi/srfi-207/upstream/bytestrings-impl.scm
+++ b/module/srfi/srfi-207/upstream/bytestrings-impl.scm
@@ -51,20 +51,6 @@
 
 ;;;; Constructors
 
-(define (make-bytestring lis)
-  (assume (or (pair? lis) (null? lis)))
-  (call-with-port
-   (open-output-bytevector)
-   (lambda (out)
-     (for-each (lambda (seg) (%write-bytestring-segment seg out)) lis)
-     (get-output-bytevector out))))
-
-(define (make-bytestring! bvec at lis)
-  (assume (bytevector? bvec))
-  (assume (and (exact-natural? at)
-               (< at (bytevector-length bvec))))
-  (bytevector-copy! bvec at (make-bytestring lis)))
-
 (define (%write-bytestring-segment obj port)
   ((cond ((and (exact-natural? obj) (< obj 256)) write-u8)
          ((and (char? obj) (char<=? obj #\delete)) write-char-binary)

Reply via email to