Recursive edge traversal by checking all nodeTyp groups along the way. It's like searching through a multi-dimensional radix trie.
(rctx *Context, method methodTyp, path string)
| 399 | // Recursive edge traversal by checking all nodeTyp groups along the way. |
| 400 | // It's like searching through a multi-dimensional radix trie. |
| 401 | func (n *node) findRoute(rctx *Context, method methodTyp, path string) *node { |
| 402 | nn := n |
| 403 | search := path |
| 404 | |
| 405 | for t, nds := range nn.children { |
| 406 | ntyp := nodeTyp(t) |
| 407 | if len(nds) == 0 { |
| 408 | continue |
| 409 | } |
| 410 | |
| 411 | var xn *node |
| 412 | xsearch := search |
| 413 | |
| 414 | var label byte |
| 415 | if search != "" { |
| 416 | label = search[0] |
| 417 | } |
| 418 | |
| 419 | switch ntyp { |
| 420 | case ntStatic: |
| 421 | xn = nds.findEdge(label) |
| 422 | if xn == nil || !strings.HasPrefix(xsearch, xn.prefix) { |
| 423 | continue |
| 424 | } |
| 425 | xsearch = xsearch[len(xn.prefix):] |
| 426 | |
| 427 | case ntParam, ntRegexp: |
| 428 | // short-circuit and return no matching route for empty param values |
| 429 | if xsearch == "" { |
| 430 | continue |
| 431 | } |
| 432 | |
| 433 | // serially loop through each node grouped by the tail delimiter |
| 434 | for _, xn = range nds { |
| 435 | // label for param nodes is the delimiter byte |
| 436 | p := strings.IndexByte(xsearch, xn.tail) |
| 437 | |
| 438 | if p < 0 { |
| 439 | if xn.tail == '/' { |
| 440 | p = len(xsearch) |
| 441 | } else { |
| 442 | continue |
| 443 | } |
| 444 | } else if ntyp == ntRegexp && p == 0 { |
| 445 | continue |
| 446 | } |
| 447 | |
| 448 | if ntyp == ntRegexp && xn.rex != nil { |
| 449 | if !xn.rex.MatchString(xsearch[:p]) { |
| 450 | continue |
| 451 | } |
| 452 | } else if strings.IndexByte(xsearch[:p], '/') != -1 { |
| 453 | // avoid a match across path segments |
| 454 | continue |
| 455 | } |
| 456 | |
| 457 | prevlen := len(rctx.routeParams.Values) |
| 458 | rctx.routeParams.Values = append(rctx.routeParams.Values, xsearch[:p]) |