Skip to content

Commit

Permalink
name match ends with any non-alnum char
Browse files Browse the repository at this point in the history
  • Loading branch information
kr committed Jul 12, 2012
1 parent 93b1a48 commit 9f33f46
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 13 deletions.
42 changes: 31 additions & 11 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import (
// Pattern matching attempts each pattern in the order in which they were
// registered.
//
// Patterns may contain literals or captures. Captures start with a colon and
// end with the last character or the first slash encountered.
// Patterns may contain literals or captures. Capture names start with a colon
// and consist of letters A-Z, a-z, _, and 0-9. The rest of the pattern
// matches literally. The portion of the URL matching each name ends with the
// first occurrence of the character in the pattern immediately following the
// name. It is possible for a name to match the empty string.
//
// Example pattern with one capture:
// /hello/:name
Expand Down Expand Up @@ -189,8 +192,9 @@ func Tail(pat, path string) string {
}
return ""
case pat[j] == ':':
_, j = find(pat, '/', j)
_, i = find(path, '/', i)
var nextc byte
_, nextc, j = match(pat, isAlnum, j+1)
_, _, i = match(path, func(c byte) bool { return c != nextc }, i)
case path[i] == pat[j]:
i++
j++
Expand Down Expand Up @@ -218,9 +222,10 @@ func (ph *patHandler) try(path string) (url.Values, bool) {
return nil, false
case ph.pat[j] == ':':
var name, val string
name, j = find(ph.pat, '/', j)
val, i = find(path, '/', i)
p.Add(name, val)
var nextc byte
name, nextc, j = match(ph.pat, isAlnum, j+1)
val, _, i = match(path, func(c byte) bool { return c != nextc }, i)
p.Add(":"+name, val)
case path[i] == ph.pat[j]:
i++
j++
Expand All @@ -234,10 +239,25 @@ func (ph *patHandler) try(path string) (url.Values, bool) {
return p, true
}

func find(s string, c byte, i int) (string, int) {
j := i
for j < len(s) && s[j] != c {
func match(s string, f func(byte) bool, i int) (matched string, next byte, j int) {
j = i
for j < len(s) && f(s[j]) {
j++
}
return s[i:j], j
if j < len(s) {
next = s[j]
}
return s[i:j], next, j
}

func isAlpha(ch byte) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}

func isDigit(ch byte) bool {
return '0' <= ch && ch <= '9'
}

func isAlnum(ch byte) bool {
return isAlpha(ch) || isDigit(ch)
}
28 changes: 26 additions & 2 deletions mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,33 @@ func TestPatMatch(t *testing.T) {
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":name": {"bar", "123"}}, params)

params, ok = (&patHandler{"/foo/::name", nil}).try("/foo/bar")
params, ok = (&patHandler{"/foo/:name.txt", nil}).try("/foo/bar.txt")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{"::name": {"bar"}}, params)
assert.Equal(t, url.Values{":name": {"bar"}}, params)

params, ok = (&patHandler{"/foo/:name", nil}).try("/foo/:bar")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":name": {":bar"}}, params)

params, ok = (&patHandler{"/foo/:a:b", nil}).try("/foo/val1:val2")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":a": {"val1"}, ":b": {":val2"}}, params)

params, ok = (&patHandler{"/foo/:a.", nil}).try("/foo/.")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":a": {""}}, params)

params, ok = (&patHandler{"/foo/:a:b", nil}).try("/foo/:bar")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":a": {""}, ":b": {":bar"}}, params)

params, ok = (&patHandler{"/foo/:a:b:c", nil}).try("/foo/:bar")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":a": {""}, ":b": {""}, ":c": {":bar"}}, params)

params, ok = (&patHandler{"/foo/::name", nil}).try("/foo/val1:val2")
assert.Equal(t, true, ok)
assert.Equal(t, url.Values{":": {"val1"}, ":name": {":val2"}}, params)

params, ok = (&patHandler{"/foo/x:name", nil}).try("/foo/bar")
assert.Equal(t, false, ok)
Expand Down

0 comments on commit 9f33f46

Please sign in to comment.