~ chicken-core (master) 3f4ab3d51cc0f49a3a1b3ce2bdabcb05dbaf3da1
commit 3f4ab3d51cc0f49a3a1b3ce2bdabcb05dbaf3da1
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Mon Aug 31 20:28:45 2026 +0200
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Mon Aug 31 20:28:45 2026 +0200
Convert embedded strings in u8 vectors to UTF-8 instead of cutting of upper bits
Also generalize element type handling.
Bug reported by "klm`")
diff --git a/library.scm b/library.scm
index 145f5d21..31f12cac 100644
--- a/library.scm
+++ b/library.scm
@@ -5385,34 +5385,26 @@ EOF
((#\( #\") (##sys#read port ##sys#default-read-info-hook))
(else (##sys#read-error port "invalid numeric vector syntax" c)))))
-;; This code is too complicated. We try to avoid mapping over
-;; a potentially large list and creating lots of garbage in the
-;; process, therefore the final result list is constructed
-;; via destructive updates and thus rather inelegant yet avoids
-;; any re-consing unless elements are non-numeric.
(define (##sys#canonicalize-number-list! lst1)
(let loop ((lst lst1) (prev #f))
(if (and (##core#inline "C_blockp" lst)
(##core#inline "C_pairp" lst))
(let retry ((x (##sys#slot lst 0)))
(cond ((char? x) (retry (string x)))
- ((string? x)
- (if (zero? (string-length x))
- (loop (##sys#slot lst 1) prev)
- (let loop2 ((ns (string->list x)) (prev prev))
- (let ((n (cons (char->integer (##sys#slot ns 0))
- (##sys#slot lst 1))))
- (if prev
- (##sys#setslot prev 1 n)
- (set! lst1 n))
- (let ((ns2 (##sys#slot ns 1)))
- (if (null? ns2)
- (loop (##sys#slot lst 1) n)
- (loop2 (##sys#slot ns 1) n)))))))
+ ((null? x) (loop (##sys#slot lst 1) prev))
+ ((list? x)
+ (let ((lst (##sys#append x (##sys#slot lst 1))))
+ (if prev
+ (##sys#setslot prev 1 lst)
+ (set! lst1 lst))
+ (loop lst prev)))
+ ((string? x) (retry (chicken.bytevector#string->utf8 x)))
+ ((and (##core#inline "C_blockp" x)
+ (##sys#bytevector? x))
+ (retry (##sys#bytevector->list x)))
+ ((##sys#srfi-4-vector? x) (retry (##sys#slot x 1)))
(else (loop (##sys#slot lst 1) lst))))
- (cond (prev (##sys#setislot prev 1 '())
- lst1)
- (else '())))))
+ lst1)))
;;; Table for specially-handled read-syntax:
;
diff --git a/manual/Module (chicken number-vector) b/manual/Module (chicken number-vector)
index 07058c21..1778aaba 100644
--- a/manual/Module (chicken number-vector)
+++ b/manual/Module (chicken number-vector)
@@ -96,7 +96,7 @@ will set {{x}} to the object {{#u8(1 2 3)}}. Since CHICKEN 4.9.0, literal homoge
`(,x #u8(1 2)) ; legal
`#u8(1 ,x 2) ; illegal
-Elements may also be characters or strings, in that case they are interpreted
+Elements may also be characters, lists, number vectors or strings, in that case they are interpreted
as a sequence of numerical character codes. For example,
'#u8(#\x7f "EL" #\F 2 1)
@@ -107,8 +107,17 @@ is equivalent to
Character literals inside numeric vectors expand into the UTF-8 sequence of
the characters they represent, for strings the contained characters
-are interpreted in whatever encoding is used for the text file or stream
-in which the literal appears.
+are interpreted as UTF-8. Embedded bytevectors or numerical vectors are
+spliced directly into the result, without further translation. Lists are
+spliced as well, recursively, so:
+
+ '#u8(1 (2) ((3)) #u16(0xabcd))
+
+will result in
+
+ #u8(1 2 3 #\xcd #\xab)
+
+on a little endian machine.
Note that {{#u8"..."}} can be used as an abbreviation for the special case
{{#u8("...")}}.
Trap