|
10 | 10 | [yamlscript.common]) |
11 | 11 | (:import |
12 | 12 | (java.util Optional) |
| 13 | + (java.nio ByteBuffer) |
13 | 14 | (java.nio.charset StandardCharsets) |
14 | 15 | (org.rapidyaml Evt Rapidyaml) |
15 | 16 | (org.snakeyaml.engine.v2.api LoadSettings) |
|
31 | 32 |
|
32 | 33 | (declare parse-fn) |
33 | 34 |
|
| 35 | +(defn TIMER [] (System/getenv "YS_TIMER")) |
| 36 | + |
34 | 37 | (def shebang-ys #"^#!.*/env ys-0(?:\.d+\.\d+)?\n") |
35 | 38 | (def shebang-bash #"^#!.*[/ ]bash\n+source +<\(") |
| 39 | + |
36 | 40 | (defn parse |
37 | 41 | "Parse a YAML string into a sequence of event objects." |
38 | 42 | [yaml-string] |
39 | 43 | (let [has-code-mode-shebang (or |
40 | 44 | (re-find shebang-ys yaml-string) |
41 | 45 | (re-find shebang-bash yaml-string)) |
42 | | - events (if (System/getenv "YS_PARSER_TIME") |
43 | | - (time (parse-fn yaml-string)) |
44 | | - (parse-fn yaml-string)) |
| 46 | + events (if (TIMER) |
| 47 | + (time ((parse-fn) yaml-string)) |
| 48 | + ((parse-fn) yaml-string)) |
45 | 49 | [first-event & rest-events] events |
46 | 50 | first-event-tag (:! first-event) |
47 | 51 | first-event (if (and has-code-mode-shebang |
|
184 | 188 | (defn parse-rapidyaml [^String yaml-string] |
185 | 189 | (rest |
186 | 190 | (let [parser ^Rapidyaml (new Rapidyaml) |
| 191 | + _ (when (TIMER) |
| 192 | + (.timingEnabled parser true)) |
187 | 193 | buffer (.getBytes yaml-string StandardCharsets/UTF_8) |
188 | 194 | masks (int-array 5) |
189 | 195 | needed (.parseYsToEvt parser buffer masks) |
190 | 196 | buffer (.getBytes yaml-string StandardCharsets/UTF_8) |
191 | 197 | masks (int-array needed) |
192 | 198 | _ (.parseYsToEvt parser buffer masks) |
| 199 | + ;; TODO: aget slow? |
| 200 | + ;; https://stackoverflow.com/questions/10133094/clojure-why-is-aget-so-slow |
193 | 201 | get-str (fn [i] |
194 | 202 | (let [off (aget masks (inc i)) |
195 | 203 | len (aget masks (+ i 2))] |
|
228 | 236 | (recur i tag anchor events))) |
229 | 237 | events))))) |
230 | 238 |
|
231 | | -(def parse-fn (if-let [parser-name (System/getenv "YS_PARSER")] |
232 | | - (condp = parser-name |
233 | | - "" parse-snakeyaml |
234 | | - "snake" parse-snakeyaml |
235 | | - "rapid" parse-rapidyaml |
236 | | - "ryml" parse-rapidyaml |
237 | | - ; TODO: |
238 | | - ;"rapid-buf" parse-rapidyaml-buf |
239 | | - ;"ryml-buf" parse-rapidyaml-buf |
240 | | - (die "Unknown YS_PARSER value: " parser-name)) |
241 | | - parse-snakeyaml)) |
| 239 | +(defn parse-rapidyaml-buf [^String yaml-string] |
| 240 | + (rest |
| 241 | + (let [parser (new Rapidyaml) |
| 242 | + _ (when (TIMER) |
| 243 | + (.timingEnabled parser true)) |
| 244 | + srcbytes (.getBytes yaml-string StandardCharsets/UTF_8) |
| 245 | + srcbuffer (ByteBuffer/allocateDirect (alength srcbytes)) |
| 246 | + _ (.put srcbuffer srcbytes) |
| 247 | + masks (Rapidyaml/mkIntBuffer 5) |
| 248 | + needed (.parseYsToEvtBuf parser srcbuffer masks) |
| 249 | + _ (.position srcbuffer 0) |
| 250 | + _ (.put srcbuffer srcbytes) |
| 251 | + masks (Rapidyaml/mkIntBuffer needed) |
| 252 | + _ (.parseYsToEvtBuf parser srcbuffer masks) |
| 253 | + get-str (fn [i] |
| 254 | + (let [off (.get masks ^Long (inc i)) |
| 255 | + len (.get masks ^Long (+ i 2))] |
| 256 | + (reduce |
| 257 | + (fn [slice i] (str slice |
| 258 | + (char (.get srcbuffer ^Long i)))) |
| 259 | + "" (range off (+ off len)))))] |
| 260 | + |
| 261 | + (loop [i 0, tag nil, anchor nil, events []] |
| 262 | + (if (< i needed) |
| 263 | + (let [mask (.get masks i) |
| 264 | + type (event-type mask) |
| 265 | + ; _ (WWW (Integer/toString mask 2) type) |
| 266 | + sval (when (flag? HAS_STR mask) (get-str i)) |
| 267 | + tag (if (flag? TAG_ mask) sval tag) |
| 268 | + anchor (if (flag? ANCH mask) sval anchor) |
| 269 | + event (when type |
| 270 | + (let [event {:+ type} |
| 271 | + event (if (flag? FLOW mask) |
| 272 | + (assoc event :flow true) event) |
| 273 | + event (if anchor (assoc event :& anchor) event) |
| 274 | + event (if tag |
| 275 | + (let [tag (str/replace tag |
| 276 | + #"^!!" |
| 277 | + "tag:yaml.org,2002:")] |
| 278 | + (assoc event :! tag)) event) |
| 279 | + event (if sval (assoc event |
| 280 | + (get-skey mask) sval) event) |
| 281 | + event (if (= type "=ALI") |
| 282 | + {:+ "=ALI" :* sval} |
| 283 | + event)] |
| 284 | + event)) |
| 285 | + events (if event (conj events event) events) |
| 286 | + i (+ i (if sval 3 1))] |
| 287 | + (if event |
| 288 | + (recur i nil nil events) |
| 289 | + (recur i tag anchor events))) |
| 290 | + events))))) |
| 291 | + |
| 292 | +(defn parse-fn [] |
| 293 | + (if-let [parser-name (System/getenv "YS_PARSER")] |
| 294 | + (condp = parser-name |
| 295 | + "" parse-snakeyaml |
| 296 | + "snake" parse-snakeyaml |
| 297 | + "rapid" parse-rapidyaml |
| 298 | + "rapid-buf" parse-rapidyaml-buf |
| 299 | + "ryml" parse-rapidyaml |
| 300 | + "ryml-buf" parse-rapidyaml-buf |
| 301 | + (die "Unknown YS_PARSER value: " parser-name)) |
| 302 | + parse-snakeyaml)) |
242 | 303 |
|
243 | 304 | (comment |
244 | 305 | ) |
0 commit comments