Commit 3fe3024e authored by Nigel Tao's avatar Nigel Tao

webdav: have escapeXML perform fewer allocations.

escapeXML was introduced in the previous commit:
https://go-review.googlesource.com/29297

Change-Id: I7d0c982049e495b312b1b8d28ba794444dd605d4
Reviewed-on: https://go-review.googlesource.com/32370Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent dffc95cb
...@@ -335,9 +335,23 @@ loop: ...@@ -335,9 +335,23 @@ loop:
} }
func escapeXML(s string) string { func escapeXML(s string) string {
var buf bytes.Buffer for i := 0; i < len(s); i++ {
xml.EscapeText(&buf, []byte(s)) // As an optimization, if s contains only ASCII letters, digits or a
return buf.String() // few special characters, the escaped value is s itself and we don't
// need to allocate a buffer and convert between string and []byte.
switch c := s[i]; {
case c == ' ' || c == '_' ||
('+' <= c && c <= '9') || // Digits as well as + , - . and /
('A' <= c && c <= 'Z') ||
('a' <= c && c <= 'z'):
continue
}
// Otherwise, go through the full escaping process.
var buf bytes.Buffer
xml.EscapeText(&buf, []byte(s))
return buf.String()
}
return s
} }
func findResourceType(fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) { func findResourceType(fs FileSystem, ls LockSystem, name string, fi os.FileInfo) (string, error) {
......
...@@ -202,6 +202,44 @@ func TestPrefix(t *testing.T) { ...@@ -202,6 +202,44 @@ func TestPrefix(t *testing.T) {
} }
} }
func TestEscapeXML(t *testing.T) {
// These test cases aren't exhaustive, and there is more than one way to
// escape e.g. a quot (as "&#34;" or "&quot;") or an apos. We presume that
// the encoding/xml package tests xml.EscapeText more thoroughly. This test
// here is just a sanity check for this package's escapeXML function, and
// its attempt to provide a fast path (and avoid a bytes.Buffer allocation)
// when escaping filenames is obviously a no-op.
testCases := map[string]string{
"": "",
" ": " ",
"&": "&amp;",
"*": "*",
"+": "+",
",": ",",
"-": "-",
".": ".",
"/": "/",
"0": "0",
"9": "9",
":": ":",
"<": "&lt;",
">": "&gt;",
"A": "A",
"_": "_",
"a": "a",
"~": "~",
"\u0201": "\u0201",
"&amp;": "&amp;amp;",
"foo&<b/ar>baz": "foo&amp;&lt;b/ar&gt;baz",
}
for in, want := range testCases {
if got := escapeXML(in); got != want {
t.Errorf("in=%q: got %q, want %q", in, got, want)
}
}
}
func TestFilenameEscape(t *testing.T) { func TestFilenameEscape(t *testing.T) {
hrefRe := regexp.MustCompile(`<D:href>([^<]*)</D:href>`) hrefRe := regexp.MustCompile(`<D:href>([^<]*)</D:href>`)
displayNameRe := regexp.MustCompile(`<D:displayname>([^<]*)</D:displayname>`) displayNameRe := regexp.MustCompile(`<D:displayname>([^<]*)</D:displayname>`)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment