Skip to content

Commit ca1f491

Browse files
pathmux: use byte-oriented common prefix length calculation (zalando#2017)
Fixes zalando#2016 Signed-off-by: Alexander Yastrebov <[email protected]>
1 parent ebe4ee2 commit ca1f491

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

pathmux/tree.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func (n *node) addPath(path string) (*node, error) {
120120
return nil, fmt.Errorf("* or : in middle of path component %s", path)
121121
}
122122

123-
// Do we have an existing node that starts with the same letter?
123+
// Do we have an existing node that starts with the same byte?
124124
for i, index := range n.staticIndices {
125125
if c == index {
126126
// Yes. Split it based on the common prefix of the existing
@@ -132,7 +132,7 @@ func (n *node) addPath(path string) (*node, error) {
132132
}
133133
}
134134

135-
// No existing node starting with this letter, so create it.
135+
// No existing node starting with this byte, so create it.
136136
child := &node{path: thisToken}
137137

138138
if n.staticIndices == nil {
@@ -158,16 +158,8 @@ func (n *node) splitCommonPrefix(existingNodeIndex int, path string) (*node, int
158158
return childNode, len(childNode.path)
159159
}
160160

161-
var i int
162161
// Find the length of the common prefix of the child node and the new path.
163-
for i = range childNode.path {
164-
if i == len(path) {
165-
break
166-
}
167-
if path[i] != childNode.path[i] {
168-
break
169-
}
170-
}
162+
i := commonPrefixLen(childNode.path, path)
171163

172164
commonPrefix := path[0:i]
173165
childNode.path = childNode.path[i:]
@@ -177,7 +169,7 @@ func (n *node) splitCommonPrefix(existingNodeIndex int, path string) (*node, int
177169
newNode := &node{
178170
path: commonPrefix,
179171
priority: childNode.priority,
180-
// Index is the first letter of the non-common part of the path.
172+
// Index is the first byte of the non-common part of the path.
181173
staticIndices: []byte{childNode.path[0]},
182174
staticChild: []*node{childNode},
183175
}
@@ -186,6 +178,14 @@ func (n *node) splitCommonPrefix(existingNodeIndex int, path string) (*node, int
186178
return newNode, i
187179
}
188180

181+
func commonPrefixLen(x, y string) int {
182+
n := 0
183+
for n < len(x) && n < len(y) && x[n] == y[n] {
184+
n++
185+
}
186+
return n
187+
}
188+
189189
func (n *node) search(path string, m Matcher) (found *node, params []string, value interface{}) {
190190
pathLen := len(path)
191191
if pathLen == 0 {

pathmux/tree_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,20 @@ func TestTree(t *testing.T) {
207207

208208
}
209209

210+
func TestTreeKatakana(t *testing.T) {
211+
const (
212+
ma = "/マ"
213+
ka = "/カ"
214+
)
215+
tree := &node{path: "/"}
216+
217+
addPath(t, tree, ma)
218+
addPath(t, tree, ka)
219+
220+
testPath(t, tree, ma, ma, nil)
221+
testPath(t, tree, ka, ka, nil)
222+
}
223+
210224
func TestPanics(t *testing.T) {
211225
sawPanic := false
212226

0 commit comments

Comments
 (0)