jolt/stdlib/clojure/string.clj
Yogthos e93006b4be Dead-code removal, perf fixes, deterministic seed emission
Round 1 (correctness + dead code):
- Fix duplicate java.util.HashMap registration in host-static.ss: the alist
  impl shadowed the hashtable ctor while leaving the hashtable methods bound,
  so .keySet/.values/.remove/.clear crashed. Drop the alist version.
- Delete jolt-core/jolt/reader.clj: a 463-line dead duplicate reader, never
  required or compiled (the live reader is host/chez/reader.ss) and drifted.
- Remove dead defs: ir/rt + :rt op + unused ir/op; the Janet branch in
  clojure.edn/drain-reader; a shadowed first clojure.string/trim-newline;
  io.ss jolt-char-array + the reader def-var (both shadowed by natives-array);
  concurrency.ss jolt-future-done?*; compile-eval.ss jolt-analyze-emit.

Round 2 (perf + determinism):
- emit-quoted-map-value / quoted sets now emit sorted by emitted text instead
  of host-hash order, which isn't stable across Chez versions (jolt-8479).
- jolt-into folds through a transient, so into/vec/mapv/filterv onto a vector
  are O(n) instead of O(n^2).
- deps resolve-deps walks its queue with an index cursor (was subvec-per-pop).
- async channel and agent action queues use amortized-O(1) FIFOs; ArrayList is
  backed by a growable vector (O(1) add/get) instead of a list.
2026-06-23 01:05:45 -04:00

148 lines
3.3 KiB
Clojure

; Jolt Standard Library: clojure.string
; String manipulation functions using Jolt core string interop.
(defn blank?
[s]
(if (nil? s) true
(= 0 (count (str-trim s)))))
(defn capitalize
[s]
(if (< 1 (count s))
(str (str-upper (subs s 0 1))
(str-lower (subs s 1)))
(str-upper s)))
(defn lower-case
[s]
(str-lower s))
(defn upper-case
[s]
(str-upper s))
(defn includes?
[s substr]
(not (nil? (str-find substr s))))
(defn join
([coll] (str-join coll))
([separator coll] (str-join coll separator)))
(defn replace
[s match replacement]
(str-replace-all match replacement s))
(defn replace-first
[s match replacement]
(str-replace match replacement s))
(defn reverse
[s]
(str-reverse-b s))
(defn str-reverse
[s]
(str-reverse-b s))
(defn split
([s re] (split s re 0))
([s re limit]
;; Java Pattern.split semantics: limit > 0 caps the parts (trailing empties
;; kept); limit < 0 splits fully and keeps trailing empties; limit 0 (the
;; default) splits fully then drops trailing empty strings — but a no-match
;; result ([input], the only 1-element case) is returned as-is.
(let [parts (vec (str-split re s (if (pos? limit) limit nil)))]
(if (and (zero? limit) (> (count parts) 1))
(loop [v parts] (if (and (seq v) (= "" (peek v))) (recur (pop v)) v))
parts))))
(defn split-lines
"Split s on \\n or \\r\\n, returning a vector of lines."
[s]
(vec (str-split #"\r?\n" s)))
(defn starts-with?
[s substr]
(let [slen (count s) slen2 (count substr)]
(and (>= slen slen2)
(= (subs s 0 slen2) substr))))
(defn ends-with?
[s substr]
(let [slen (count s) slen2 (count substr)]
(and (>= slen slen2)
(= (subs s (- slen slen2)) substr))))
(defn trim
[s]
(str-trim s))
(defn triml
[s]
(str-triml s))
(defn trimr
[s]
(str-trimr s))
(defn escape
[s cmap]
(apply str
(map (fn [ch]
(if-let [rep (cmap ch)] rep (str ch)))
s)))
(defn index-of
"0-based index of the first occurrence of value in s, or nil."
([s value]
(str-find value s))
([s value from]
(let [idx (str-find value (subs s from))]
(when idx (+ from idx)))))
(defn last-index-of
([s value]
(let [r (str-reverse-b s) sval (str-reverse-b value)
idx (str-find sval r)]
(when idx (- (count s) (+ idx (count value))))))
([s value from]
(let [sub (subs s 0 from) r (str-reverse-b sub) sval (str-reverse-b value)
idx (str-find sval r)]
(when idx (- from (+ idx (count value)))))))
(defn re-quote-replacement
"Escape special characters (backslash and dollar) in a regex replacement
string so it is used literally rather than interpreted."
[replacement]
(apply str
(map (fn [ch]
(let [c (str ch)]
(if (or (= c "\\") (= c "$")) (str "\\" c) c)))
(seq replacement))))
;; Ported from clojure.string/trim-newline (CharSequence interop replaced with
;; portable count/subs). Removes all trailing \n or \r characters.
(defn trim-newline
"Removes all trailing newline \\n or return \\r characters from
string. Similar to Perl's chomp."
[s]
(loop [index (count s)]
(if (zero? index)
""
(let [c (subs s (dec index) index)]
(if (or (= c "\n") (= c "\r"))
(recur (dec index))
(subs s 0 index))))))