String/char-array interop: getChars, String(char[]), str of StringBuilder, append(csq,start,end)

- String.getChars copies into a char-array; String. builds from a char[]
  (whole or offset/count slice); subSequence returns the substring.
- str of a StringBuilder returns its content (was the opaque host object;
  .toString already worked).
- Appendable.append gains the 3-arg subsequence form append(csq,start,end)
  on StringBuilder/StringWriter/file/port writers.
- reader combines a \uXXXX surrogate pair into the one Unicode scalar
  (😃) instead of crashing on the lone high surrogate; a stray surrogate
  maps to U+FFFD. (A high-plane char re-escaped as \uXXXXX stays the
  irreducible UTF-16/scalar divergence.)
- TimeZone/getDefault.

These let clojure.data.json read and write JSON; its own suite goes from
not loading to 97/133 assertions passing (remainder: per-type writer
dispatch for uuid/bigdec/date, EOFException, niche date interop).
This commit is contained in:
Yogthos 2026-06-24 14:36:13 -04:00
parent c6b8f31608
commit 8bd781e6a8
5 changed files with 59 additions and 7 deletions

View file

@ -177,7 +177,21 @@
((#\0) (loop (+ i 2) (cons #\nul acc)))
((#\u)
(let-values (((cp j) (rdr-hex->int s (+ i 2) 4)))
(loop j (cons (integer->char cp) acc))))
;; A \u escape is a UTF-16 code unit. jolt chars are Unicode scalars,
;; so combine a high+low surrogate pair (😃 -> U+1F603) into
;; the one scalar char. A lone surrogate has no scalar — emit U+FFFD
;; rather than crash (the irreducible UTF-16/scalar divergence).
(cond
((and (fx>=? cp #xD800) (fx<=? cp #xDBFF)
(fx<? (fx+ j 1) end)
(char=? (string-ref s j) #\\) (char=? (string-ref s (fx+ j 1)) #\u))
(let-values (((lo k) (rdr-hex->int s (+ j 2) 4)))
(if (and (fx>=? lo #xDC00) (fx<=? lo #xDFFF))
(loop k (cons (integer->char
(fx+ #x10000 (fx* (fx- cp #xD800) 1024) (fx- lo #xDC00))) acc))
(loop j (cons #\xFFFD acc)))))
((and (fx>=? cp #xD800) (fx<=? cp #xDFFF)) (loop j (cons #\xFFFD acc)))
(else (loop j (cons (integer->char cp) acc))))))
(else (loop (+ i 2) (cons e acc))))))
(else (loop (+ i 1) (cons c acc)))))))