|
12 | 12 | [clojure.core :as core]) |
13 | 13 | (:refer-clojure :exclude [assoc! dissoc! transient persistent! get assoc])) |
14 | 14 |
|
15 | | -(defn transient [{:keys [u->ps p->u]}] |
16 | | - (core/assoc! (core/transient {}) |
17 | | - :p->u (core/transient p->u) |
18 | | - :u->ps (core/transient u->ps))) |
| 15 | +(def prefix-map :p->u) |
| 16 | +(def uri-map :u->ps) |
| 17 | + |
| 18 | +;; TODO replace this with a deftype for memory savings |
| 19 | +(def EMPTY {:u->ps {name/xml-uri ["xml"] |
| 20 | + name/xmlns-uri ["xmlns"]} |
| 21 | + :p->u {"xml" name/xml-uri |
| 22 | + "xmlns" name/xmlns-uri}}) |
| 23 | + |
| 24 | +;; TODO implement valid? with internal consistency check |
| 25 | + |
| 26 | +(defn transient [pu] |
| 27 | + (let [{:keys [u->ps p->u] :as pu*} |
| 28 | + (or pu EMPTY)] |
| 29 | + (assert (and u->ps p->u) (str "Not a pu-map " (pr-str pu*))) |
| 30 | + (core/assoc! (core/transient {}) |
| 31 | + :p->u (core/transient p->u) |
| 32 | + :u->ps (core/transient u->ps)))) |
19 | 33 |
|
20 | 34 | (defn persistent! [put] |
21 | 35 | (core/persistent! |
|
35 | 49 | (core/dissoc! u->ps uri))) |
36 | 50 |
|
37 | 51 | (defn assoc! [{:as put :keys [p->u u->ps]} prefix uri] |
38 | | - (when (or (core/get #{"xml" "xmlns"} prefix) |
39 | | - (core/get #{name/xml-uri name/xmlns-uri} uri)) |
40 | | - (throw (ex-info "Mapping for xml: and xmlns: prefixes are fixed by the standard" |
41 | | - {:attempted-mapping {:prefix prefix |
42 | | - :uri uri}}))) |
43 | | - (let [prev-uri (core/get p->u prefix)] |
| 52 | + (name/legal-xmlns-binding! prefix uri) |
| 53 | + (let [prefix* (str prefix) |
| 54 | + prev-uri (core/get p->u prefix*)] |
44 | 55 | (core/assoc! put |
45 | 56 | :p->u (if (str/blank? uri) |
46 | | - (core/dissoc! p->u prefix) |
47 | | - (core/assoc! p->u prefix uri)) |
| 57 | + (core/dissoc! p->u prefix*) |
| 58 | + (core/assoc! p->u prefix* uri)) |
48 | 59 | :u->ps (if (str/blank? uri) |
49 | | - (dissoc-uri! u->ps prev-uri prefix) |
| 60 | + (dissoc-uri! u->ps prev-uri prefix*) |
50 | 61 | (cond |
51 | 62 | (= uri prev-uri) u->ps |
52 | | - (not prev-uri) (assoc-uri! u->ps uri prefix) |
| 63 | + (not prev-uri) (assoc-uri! u->ps uri prefix*) |
53 | 64 | :else (-> u->ps |
54 | | - (dissoc-uri! prev-uri prefix) |
55 | | - (assoc-uri! uri prefix))))))) |
| 65 | + (dissoc-uri! prev-uri prefix*) |
| 66 | + (assoc-uri! uri prefix*))))))) |
56 | 67 |
|
57 | 68 | (defn get [{:keys [p->u]} prefix] |
58 | | - (core/get p->u prefix)) |
| 69 | + (core/get p->u (str prefix))) |
59 | 70 |
|
60 | 71 | (defn get-prefixes [{:keys [u->ps]} uri] |
61 | 72 | (core/get u->ps uri)) |
|
66 | 77 | (persistent! |
67 | 78 | (reduce-kv assoc! (transient put) kvs))) |
68 | 79 |
|
69 | | - |
70 | | -;; TODO replace this with a deftype for memory savings |
71 | | -(def EMPTY {:u->ps {name/xml-uri ["xml"] |
72 | | - name/xmlns-uri ["xmlns"]} |
73 | | - :p->u {"xml" name/xml-uri |
74 | | - "xmlns" name/xmlns-uri}}) |
75 | | - |
76 | 80 | (defn reduce-diff |
77 | 81 | "A high-performance diffing operation, that reduces f over changed and removed prefixes" |
78 | 82 | [f s |
|
87 | 91 | s (f s p u))) |
88 | 92 | s pu)] |
89 | 93 | s)) |
| 94 | + |
| 95 | +(defn merge-prefix-map |
| 96 | + "Merge a prefix map into pu-map" |
| 97 | + [pu pm] |
| 98 | + (persistent! (reduce-kv assoc! (transient pu) pm))) |
| 99 | + |
| 100 | +(defn merge |
| 101 | + "Merge two pu-maps, left to right" |
| 102 | + [pu {:keys [:p->u]}] |
| 103 | + (merge-prefix-map pu p->u)) |
0 commit comments