func (n *node) childLen() (i int) {
	for _, n := range n.childrenNodes {
		i++
		i += n.childLen()
	}
	return
}
childLen returns all the children's and their children's length.
package node
import (
	"sort"
	"strings"
	"github.com/kataras/iris/context"
	"github.com/kataras/iris/core/errors"
)
type Nodes []*node
type node struct {
	s                 string
	routeName         string
	wildcardParamName string    
	paramNames        []string  
	childrenNodes     Nodes
	handlers          context.Handlers
	root              bool
	rootWildcard      bool  
}
var ErrDublicate = errors.New("two or more routes have the same registered path")
func (nodes *Nodes) Add(routeName string, path string, handlers context.Handlers) error {
	var params []string
	var paramStart, paramEnd int
	for {
		paramStart = strings.IndexByte(path[paramEnd:], ':')
		if paramStart == -1 {
			break
		}
		paramStart += paramEnd
		paramStart++
		paramEnd = strings.IndexByte(path[paramStart:], '/')
		if paramEnd == -1 {
			params = append(params, path[paramStart:])
			path = path[:paramStart]
			break
		}
		paramEnd += paramStart
		params = append(params, path[paramStart:paramEnd])
		path = path[:paramStart] + path[paramEnd:]
		paramEnd -= paramEnd - paramStart
	}
	var p []int
	for i := 0; i < len(path); i++ {
		idx := strings.IndexByte(path[i:], ':')
		if idx == -1 {
			break
		}
		p = append(p, idx+i)
		i = idx + i
	}
	for _, idx := range p {
		if err := nodes.add(routeName, path[:idx], nil, nil, true); err != nil {
			return err
		}
		if nidx := idx + 1; len(path) > nidx {
			if err := nodes.add(routeName, path[:nidx], nil, nil, true); err != nil {
				return err
			}
		}
	}
	if err := nodes.add(routeName, path, params, handlers, true); err != nil {
		return err
	}
	nodes.prioritize()
	return nil
}
func (nodes *Nodes) add(routeName, path string, paramNames []string, handlers context.Handlers, root bool) (err error) {
	wildcardIdx := strings.IndexByte(path, '*')
	wildcardParamName := ""
	if wildcardIdx > 0 && len(paramNames) == 0 {  
		wildcardParamName = path[wildcardIdx+1:]
		path = path[0:wildcardIdx-1] + "/"  
		rootWildcard := path == "/"
		if rootWildcard {
			path += "/"  
		}
		n := &node{
			rootWildcard:      rootWildcard,
			s:                 path,
			routeName:         routeName,
			wildcardParamName: wildcardParamName,
			paramNames:        paramNames,
			handlers:          handlers,
			root:              root,
		}
		*nodes = append(*nodes, n)
		return
	}
loop:
	for _, n := range *nodes {
		if n.rootWildcard {
			continue
		}
		if len(n.paramNames) == 0 && n.wildcardParamName != "" {
			continue
		}
		minlen := len(n.s)
		if len(path) < minlen {
			minlen = len(path)
		}
		for i := 0; i < minlen; i++ {
			if n.s[i] == path[i] {
				continue
			}
			if i == 0 {
				continue loop
			}
			*n = node{
				s: n.s[:i],
				childrenNodes: Nodes{
					{
						s:                 n.s[i:],
						routeName:         n.routeName,
						wildcardParamName: n.wildcardParamName,  
						paramNames:        n.paramNames,
						childrenNodes:     n.childrenNodes,
						handlers:          n.handlers,
					},
					{
						s:                 path[i:],
						routeName:         routeName,
						wildcardParamName: wildcardParamName,
						paramNames:        paramNames,
						handlers:          handlers,
					},
				},
				root: n.root,
			}
			return
		}
		if len(path) < len(n.s) {
			*n = node{
				s:                 n.s[:len(path)],
				routeName:         routeName,
				wildcardParamName: wildcardParamName,
				paramNames:        paramNames,
				childrenNodes: Nodes{
					{
						s:                 n.s[len(path):],
						routeName:         n.routeName,
						wildcardParamName: n.wildcardParamName,  
						paramNames:        n.paramNames,
						childrenNodes:     n.childrenNodes,
						handlers:          n.handlers,
					},
				},
				handlers: handlers,
				root:     n.root,
			}
			return
		}
		if len(path) > len(n.s) {
			if n.wildcardParamName != "" {
				n := &node{
					s:                 path,
					routeName:         routeName,
					wildcardParamName: wildcardParamName,
					paramNames:        paramNames,
					handlers:          handlers,
					root:              root,
				}
				*nodes = append(*nodes, n)
				return
			}
			pathToAdd := path[len(n.s):]
			err = n.childrenNodes.add(routeName, pathToAdd, paramNames, handlers, false)
			return err
		}
		if len(handlers) == 0 {  
			return nil
		}
		if len(n.handlers) > 0 {  
			return ErrDublicate
		}
		n.paramNames = paramNames
		n.handlers = handlers
		return
	}
	if wildcardIdx > 0 {
		wildcardParamName = path[wildcardIdx+1:]
		path = path[0:wildcardIdx-1] + "/"
	}
	n := &node{
		s:                 path,
		routeName:         routeName,
		wildcardParamName: wildcardParamName,
		paramNames:        paramNames,
		handlers:          handlers,
		root:              root,
	}
	*nodes = append(*nodes, n)
	return
}
func (nodes Nodes) Find(path string, params *context.RequestParams) (string, context.Handlers) {
	n, paramValues := nodes.findChild(path, nil)
	if n != nil {
		if len(paramValues) > 0 {
			for i, name := range n.paramNames {
				params.Set(name, paramValues[i])
			}
			if len(paramValues) > len(n.paramNames) {
				lastWildcardVal := paramValues[len(paramValues)-1]
				params.Set(n.wildcardParamName, lastWildcardVal)
			}
		}
		return n.routeName, n.handlers
	}
	return "", nil
}
func (nodes Nodes) Exists(path string) bool {
	n, _ := nodes.findChild(path, nil)
	return n != nil && len(n.handlers) > 0
}
func (nodes Nodes) findChild(path string, params []string) (*node, []string) {
	for _, n := range nodes {
		if n.s == ":" {
			paramEnd := strings.IndexByte(path, '/')
			if paramEnd == -1 {
				if len(n.handlers) == 0 {
					return nil, nil
				}
				return n, append(params, path)
			}
			return n.childrenNodes.findChild(path[paramEnd:], append(params, path[:paramEnd]))
		}
		if n.rootWildcard {
			if len(path) < 2 {
				path = "/" + path
			}
			return n, append(params, path[1:])
		}
		if n.wildcardParamName != "" && len(path) > 2 {
			if len(path) == len(n.s)-1 {
				if path == n.s[0:len(n.s)-1] {
					return n, params
				}
			}
			if strings.HasPrefix(path, n.s) {
				if len(path) > len(n.s)+1 {
					return n, append(params, path[len(n.s):])  
				}
			}
		}
		if !strings.HasPrefix(path, n.s) {
			continue
		}
		if len(path) == len(n.s) {
			if len(n.handlers) == 0 {
				return nil, nil
			}
			return n, params
		}
		child, childParamNames := n.childrenNodes.findChild(path[len(n.s):], params)
		if child == nil || len(child.handlers) == 0 {
			if n.s[len(n.s)-1] == '/' && !(n.root && (n.s == "/" || len(n.childrenNodes) > 0)) {
				if len(n.handlers) == 0 {
					return nil, nil
				}
				return n, append(params, path[len(n.s):])
			}
			continue
		}
		return child, childParamNames
	}
	return nil, nil
}