flan/test/programs/string-owned.flan

91 lines
3.1 KiB
Plaintext

;;;; String: owned, growable, always valid UTF-8. Multi-byte append, insert
;;;; and remove by character position, iteration by runes, the byte length
;;;; beside the character count, a copy, printing inside a structure, and a
;;;; String crossing into dyn as a copy of its text.
(defstruct Named [label String n i32])
(defn as-dyn [d] dyn d)
(defn main [] i32
(let [s (string-new "héllo")]
(append s " wörld")
(append s 0x65e5) ; 日, three bytes
(append s \!)
(println s)
(println (length s) (rune-count s))
;; Positions are characters: 1 is after the h, whatever é takes.
(insert s 1 "→")
(insert s 0 0x1f600) ; four bytes at the front
(println s)
(println (remove s 2)) ; the → that was inserted, as a code point
(println (remove s 0)) ; the emoji
(println s)
;; Appending a String to itself reads the bytes it had before growing.
(let [t (string-new "ab")]
(append t t)
(append t t)
(println t (length t))
(free t))
;; Iteration by runes.
(let [it (runes s)
going true
n 0]
(while going
(match (runes-next (addr it))
(Some c) (do (when (> (i32 c) 127) (print (i32 c) "")) (set n (+ n 1)))
None (set going false)))
(println n))
;; A copy is independent of the original.
(let [c (clone s)]
(append c "?")
(println (length s) (length c))
(free c))
;; The str view and the byte view cost nothing.
(println (= (str s) "héllo wörld日!"))
(println (length (bytes-view s)))
;; Inside a structure it prints quoted, as a str field does.
(let [m (Named {.label (string-new "x") .n 3})]
(println m)
(free (.label m)))
;; Crossing into dyn copies the text, which the dyn side then owns.
(let [d (as-dyn s)]
(append s "tail")
(println d)
(println (type-of d)))
;; The builders answer Strings.
(let [j (join (slice [(bytes-view "a") (bytes-view "b")]) (bytes-view "-"))]
(println j)
(free j))
;; = and != compare bytes, against a String or a str, either side first.
(let [a (string-new "日本")
b (string-new "日")]
(append b 0x672c)
(println (= a b) (!= a b) (= a "日本") (= "日本" a) (= a "日") (!= b "x"))
(println (= a b (to-upper (bytes-view "日本"))))
(free a)
(free b))
;; bytes->string copies: a write through the Vec afterwards, or through a
;; slice taken of it before, does not reach the String.
(let [v (vec-new u8)]
(push v 0xc3)
(push v 0xa9)
(let [early (slice v)
t (bytes->string v)]
(set (at v 0) 0xff)
(set (at early 1) 0xe6)
(println t (length t) (rune-count t))
(free t))
(free v))
;; A remove near the front and an insert at the front, on a long text.
(let [long (string-new "é")]
(dotimes [i 1000] (append long "ab"))
(insert long 0 "x")
(println (remove long 1) (length long))
(free long))
(let [e (string-new)]
(println (length e) (rune-count e))
(free e))
(free s))
0)