Skip to content

Commit a573ec6

Browse files
thinkerouappleboy
andauthored
chore: update tree (#2371)
Co-authored-by: Bo-Yi Wu <[email protected]>
1 parent 3b5e861 commit a573ec6

File tree

1 file changed

+127
-128
lines changed

1 file changed

+127
-128
lines changed

Diff for: tree.go

+127-128
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ func (n *node) incrementChildPrio(pos int) int {
119119
for ; newPos > 0 && cs[newPos-1].priority < prio; newPos-- {
120120
// Swap node positions
121121
cs[newPos-1], cs[newPos] = cs[newPos], cs[newPos-1]
122-
123122
}
124123

125124
// Build new index char string
@@ -559,8 +558,8 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) ([]by
559558
// Use a static sized buffer on the stack in the common case.
560559
// If the path is too long, allocate a buffer on the heap instead.
561560
buf := make([]byte, 0, stackBufSize)
562-
if l := len(path) + 1; l > stackBufSize {
563-
buf = make([]byte, 0, l)
561+
if length := len(path) + 1; length > stackBufSize {
562+
buf = make([]byte, 0, length)
564563
}
565564

566565
ciPath := n.findCaseInsensitivePathRec(
@@ -600,163 +599,163 @@ walk: // Outer loop for walking the tree
600599
path = path[npLen:]
601600
ciPath = append(ciPath, n.path...)
602601

603-
if len(path) > 0 {
604-
// If this node does not have a wildcard (param or catchAll) child,
605-
// we can just look up the next child node and continue to walk down
606-
// the tree
607-
if !n.wildChild {
608-
// Skip rune bytes already processed
609-
rb = shiftNRuneBytes(rb, npLen)
602+
if len(path) == 0 {
603+
// We should have reached the node containing the handle.
604+
// Check if this node has a handle registered.
605+
if n.handlers != nil {
606+
return ciPath
607+
}
610608

611-
if rb[0] != 0 {
612-
// Old rune not finished
613-
idxc := rb[0]
614-
for i, c := range []byte(n.indices) {
615-
if c == idxc {
616-
// continue with child node
617-
n = n.children[i]
618-
npLen = len(n.path)
619-
continue walk
609+
// No handle found.
610+
// Try to fix the path by adding a trailing slash
611+
if fixTrailingSlash {
612+
for i, c := range []byte(n.indices) {
613+
if c == '/' {
614+
n = n.children[i]
615+
if (len(n.path) == 1 && n.handlers != nil) ||
616+
(n.nType == catchAll && n.children[0].handlers != nil) {
617+
return append(ciPath, '/')
620618
}
619+
return nil
621620
}
622-
} else {
623-
// Process a new rune
624-
var rv rune
625-
626-
// Find rune start.
627-
// Runes are up to 4 byte long,
628-
// -4 would definitely be another rune.
629-
var off int
630-
for max := min(npLen, 3); off < max; off++ {
631-
if i := npLen - off; utf8.RuneStart(oldPath[i]) {
632-
// read rune from cached path
633-
rv, _ = utf8.DecodeRuneInString(oldPath[i:])
634-
break
635-
}
621+
}
622+
}
623+
return nil
624+
}
625+
626+
// If this node does not have a wildcard (param or catchAll) child,
627+
// we can just look up the next child node and continue to walk down
628+
// the tree
629+
if !n.wildChild {
630+
// Skip rune bytes already processed
631+
rb = shiftNRuneBytes(rb, npLen)
632+
633+
if rb[0] != 0 {
634+
// Old rune not finished
635+
idxc := rb[0]
636+
for i, c := range []byte(n.indices) {
637+
if c == idxc {
638+
// continue with child node
639+
n = n.children[i]
640+
npLen = len(n.path)
641+
continue walk
642+
}
643+
}
644+
} else {
645+
// Process a new rune
646+
var rv rune
647+
648+
// Find rune start.
649+
// Runes are up to 4 byte long,
650+
// -4 would definitely be another rune.
651+
var off int
652+
for max := min(npLen, 3); off < max; off++ {
653+
if i := npLen - off; utf8.RuneStart(oldPath[i]) {
654+
// read rune from cached path
655+
rv, _ = utf8.DecodeRuneInString(oldPath[i:])
656+
break
636657
}
658+
}
659+
660+
// Calculate lowercase bytes of current rune
661+
lo := unicode.ToLower(rv)
662+
utf8.EncodeRune(rb[:], lo)
637663

638-
// Calculate lowercase bytes of current rune
639-
lo := unicode.ToLower(rv)
640-
utf8.EncodeRune(rb[:], lo)
664+
// Skip already processed bytes
665+
rb = shiftNRuneBytes(rb, off)
641666

642-
// Skip already processed bytes
667+
idxc := rb[0]
668+
for i, c := range []byte(n.indices) {
669+
// Lowercase matches
670+
if c == idxc {
671+
// must use a recursive approach since both the
672+
// uppercase byte and the lowercase byte might exist
673+
// as an index
674+
if out := n.children[i].findCaseInsensitivePathRec(
675+
path, ciPath, rb, fixTrailingSlash,
676+
); out != nil {
677+
return out
678+
}
679+
break
680+
}
681+
}
682+
683+
// If we found no match, the same for the uppercase rune,
684+
// if it differs
685+
if up := unicode.ToUpper(rv); up != lo {
686+
utf8.EncodeRune(rb[:], up)
643687
rb = shiftNRuneBytes(rb, off)
644688

645689
idxc := rb[0]
646690
for i, c := range []byte(n.indices) {
647-
// Lowercase matches
691+
// Uppercase matches
648692
if c == idxc {
649-
// must use a recursive approach since both the
650-
// uppercase byte and the lowercase byte might exist
651-
// as an index
652-
if out := n.children[i].findCaseInsensitivePathRec(
653-
path, ciPath, rb, fixTrailingSlash,
654-
); out != nil {
655-
return out
656-
}
657-
break
658-
}
659-
}
660-
661-
// If we found no match, the same for the uppercase rune,
662-
// if it differs
663-
if up := unicode.ToUpper(rv); up != lo {
664-
utf8.EncodeRune(rb[:], up)
665-
rb = shiftNRuneBytes(rb, off)
666-
667-
idxc := rb[0]
668-
for i, c := range []byte(n.indices) {
669-
// Uppercase matches
670-
if c == idxc {
671-
// Continue with child node
672-
n = n.children[i]
673-
npLen = len(n.path)
674-
continue walk
675-
}
693+
// Continue with child node
694+
n = n.children[i]
695+
npLen = len(n.path)
696+
continue walk
676697
}
677698
}
678699
}
679-
680-
// Nothing found. We can recommend to redirect to the same URL
681-
// without a trailing slash if a leaf exists for that path
682-
if fixTrailingSlash && path == "/" && n.handlers != nil {
683-
return ciPath
684-
}
685-
return nil
686700
}
687701

688-
n = n.children[0]
689-
switch n.nType {
690-
case param:
691-
// Find param end (either '/' or path end)
692-
end := 0
693-
for end < len(path) && path[end] != '/' {
694-
end++
695-
}
702+
// Nothing found. We can recommend to redirect to the same URL
703+
// without a trailing slash if a leaf exists for that path
704+
if fixTrailingSlash && path == "/" && n.handlers != nil {
705+
return ciPath
706+
}
707+
return nil
708+
}
696709

697-
// Add param value to case insensitive path
698-
ciPath = append(ciPath, path[:end]...)
710+
n = n.children[0]
711+
switch n.nType {
712+
case param:
713+
// Find param end (either '/' or path end)
714+
end := 0
715+
for end < len(path) && path[end] != '/' {
716+
end++
717+
}
699718

700-
// We need to go deeper!
701-
if end < len(path) {
702-
if len(n.children) > 0 {
703-
// Continue with child node
704-
n = n.children[0]
705-
npLen = len(n.path)
706-
path = path[end:]
707-
continue
708-
}
719+
// Add param value to case insensitive path
720+
ciPath = append(ciPath, path[:end]...)
709721

710-
// ... but we can't
711-
if fixTrailingSlash && len(path) == end+1 {
712-
return ciPath
713-
}
714-
return nil
722+
// We need to go deeper!
723+
if end < len(path) {
724+
if len(n.children) > 0 {
725+
// Continue with child node
726+
n = n.children[0]
727+
npLen = len(n.path)
728+
path = path[end:]
729+
continue
715730
}
716731

717-
if n.handlers != nil {
732+
// ... but we can't
733+
if fixTrailingSlash && len(path) == end+1 {
718734
return ciPath
719735
}
720-
721-
if fixTrailingSlash && len(n.children) == 1 {
722-
// No handle found. Check if a handle for this path + a
723-
// trailing slash exists
724-
n = n.children[0]
725-
if n.path == "/" && n.handlers != nil {
726-
return append(ciPath, '/')
727-
}
728-
}
729-
730736
return nil
731-
732-
case catchAll:
733-
return append(ciPath, path...)
734-
735-
default:
736-
panic("invalid node type")
737737
}
738-
} else {
739-
// We should have reached the node containing the handle.
740-
// Check if this node has a handle registered.
738+
741739
if n.handlers != nil {
742740
return ciPath
743741
}
744742

745-
// No handle found.
746-
// Try to fix the path by adding a trailing slash
747-
if fixTrailingSlash {
748-
for i, c := range []byte(n.indices) {
749-
if c == '/' {
750-
n = n.children[i]
751-
if (len(n.path) == 1 && n.handlers != nil) ||
752-
(n.nType == catchAll && n.children[0].handlers != nil) {
753-
return append(ciPath, '/')
754-
}
755-
return nil
756-
}
743+
if fixTrailingSlash && len(n.children) == 1 {
744+
// No handle found. Check if a handle for this path + a
745+
// trailing slash exists
746+
n = n.children[0]
747+
if n.path == "/" && n.handlers != nil {
748+
return append(ciPath, '/')
757749
}
758750
}
751+
759752
return nil
753+
754+
case catchAll:
755+
return append(ciPath, path...)
756+
757+
default:
758+
panic("invalid node type")
760759
}
761760
}
762761

0 commit comments

Comments
 (0)