github.com/TeaOSLab/EdgeNode@v1.3.8/internal/re/rune_tree.go (about)

     1  // Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
     2  
     3  package re
     4  
     5  type RuneMap map[rune]*RuneTree
     6  
     7  func (this RuneMap) Lookup(s string, caseInsensitive bool) bool {
     8  	return this.lookup([]rune(s), caseInsensitive, 0)
     9  }
    10  
    11  func (this RuneMap) lookup(runes []rune, caseInsensitive bool, depth int) bool {
    12  	if len(runes) == 0 {
    13  		return false
    14  	}
    15  	for i, r := range runes {
    16  		tree, ok := this[r]
    17  		if !ok {
    18  			if caseInsensitive {
    19  				if r >= 'a' && r <= 'z' {
    20  					r -= 32
    21  					tree, ok = this[r]
    22  				} else if r >= 'A' && r <= 'Z' {
    23  					r += 32
    24  					tree, ok = this[r]
    25  				}
    26  			}
    27  			if !ok {
    28  				if depth > 0 {
    29  					return false
    30  				}
    31  				continue
    32  			}
    33  		}
    34  		if tree.IsEnd {
    35  			return true
    36  		}
    37  		b := tree.Children.lookup(runes[i+1:], caseInsensitive, depth+1)
    38  		if b {
    39  			return true
    40  		}
    41  	}
    42  	return false
    43  }
    44  
    45  type RuneTree struct {
    46  	Children RuneMap
    47  	IsEnd    bool
    48  }
    49  
    50  func NewRuneTree(list []string) RuneMap {
    51  	var rootMap = RuneMap{}
    52  	for _, s := range list {
    53  		if len(s) == 0 {
    54  			continue
    55  		}
    56  
    57  		var lastMap = rootMap
    58  		var runes = []rune(s)
    59  		for index, r := range runes {
    60  			tree, ok := lastMap[r]
    61  			if !ok {
    62  				tree = &RuneTree{
    63  					Children: RuneMap{},
    64  				}
    65  				lastMap[r] = tree
    66  			}
    67  			if index == len(runes)-1 {
    68  				tree.IsEnd = true
    69  			}
    70  			lastMap = tree.Children
    71  		}
    72  	}
    73  	return rootMap
    74  }