Skip to content

Commit 92a2d66

Browse files
committed
Improve performance of form-decode
1 parent 1aa859f commit 92a2d66

1 file changed

Lines changed: 22 additions & 5 deletions

File tree

src/ring/util/codec.clj

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
"Functions for encoding and decoding data."
33
(:require [clojure.string :as str])
44
(:import java.util.Map
5+
clojure.lang.MapEntry
56
[java.net URLEncoder URLDecoder]
6-
[java.util Base64]))
7+
[java.util Base64 StringTokenizer]))
78

89
(defn assoc-conj
910
"Associate a key with a value in a map. If the key already exists in the map,
@@ -129,6 +130,22 @@
129130
(URLDecoder/decode encoded encoding)
130131
(catch Exception _ nil))))
131132

133+
(defn- tokenized [s delim]
134+
(reify clojure.lang.IReduceInit
135+
(reduce [_ f init]
136+
(let [tokenizer (StringTokenizer. s delim)]
137+
(loop [result init]
138+
(if (.hasMoreTokens tokenizer)
139+
(recur (f result (.nextToken tokenizer)))
140+
result))))))
141+
142+
(defn- split-key-value-pair [^String s]
143+
(let [i (.indexOf s #=(int \=))]
144+
(cond
145+
(pos? i) (MapEntry. (.substring s 0 i) (.substring s (inc i)))
146+
(zero? i) (MapEntry. "" (.substring s (inc i)))
147+
:else (MapEntry. s ""))))
148+
132149
(defn form-decode
133150
"Decode the supplied www-form-urlencoded string using the specified encoding,
134151
or UTF-8 by default. If the encoded value is a string, a string is returned.
@@ -140,11 +157,11 @@
140157
(form-decode-str encoded encoding)
141158
(reduce
142159
(fn [m param]
143-
(let [[k v] (str/split param #"=" 2)
144-
k (form-decode-str k encoding)
145-
v (form-decode-str (or v "") encoding)]
160+
(let [kv (split-key-value-pair param)
161+
k (form-decode-str (key kv) encoding)
162+
v (form-decode-str (val kv) encoding)]
146163
(if (and k v)
147164
(assoc-conj m k v)
148165
m)))
149166
{}
150-
(str/split encoded #"&")))))
167+
(tokenized encoded "&")))))

0 commit comments

Comments
 (0)