| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 | package strmatcherimport (	"regexp")// Matcher is the interface to determine a string matches a pattern.type Matcher interface {	// Match returns true if the given string matches a predefined pattern.	Match(string) bool}// Type is the type of the matcher.type Type byteconst (	// Full is the type of matcher that the input string must exactly equal to the pattern.	Full Type = iota	// Substr is the type of matcher that the input string must contain the pattern as a sub-string.	Substr	// Domain is the type of matcher that the input string must be a sub-domain or itself of the pattern.	Domain	// Regex is the type of matcher that the input string must matches the regular-expression pattern.	Regex)// New creates a new Matcher based on the given pattern.func (t Type) New(pattern string) (Matcher, error) {	switch t {	case Full:		return fullMatcher(pattern), nil	case Substr:		return substrMatcher(pattern), nil	case Domain:		return domainMatcher(pattern), nil	case Regex:		r, err := regexp.Compile(pattern)		if err != nil {			return nil, err		}		return ®exMatcher{			pattern: r,		}, nil	default:		panic("Unknown type")	}}// IndexMatcher is the interface for matching with a group of matchers.type IndexMatcher interface {	// Match returns the the index of a matcher that matches the input. It returns 0 if no such matcher exists.	Match(input string) uint32}type matcherEntry struct {	m  Matcher	id uint32}// MatcherGroup is an implementation of IndexMatcher.// Empty initialization works.type MatcherGroup struct {	count         uint32	fullMatcher   FullMatcherGroup	domainMatcher DomainMatcherGroup	otherMatchers []matcherEntry}// Add adds a new Matcher into the MatcherGroup, and returns its index. The index will never be 0.func (g *MatcherGroup) Add(m Matcher) uint32 {	g.count++	c := g.count	switch tm := m.(type) {	case fullMatcher:		g.fullMatcher.addMatcher(tm, c)	case domainMatcher:		g.domainMatcher.addMatcher(tm, c)	default:		g.otherMatchers = append(g.otherMatchers, matcherEntry{			m:  m,			id: c,		})	}	return c}// Match implements IndexMatcher.Match.func (g *MatcherGroup) Match(pattern string) uint32 {	if c := g.fullMatcher.Match(pattern); c > 0 {		return c	}	if c := g.domainMatcher.Match(pattern); c > 0 {		return c	}	for _, e := range g.otherMatchers {		if e.m.Match(pattern) {			return e.id		}	}	return 0}// Size returns the number of matchers in the MatcherGroup.func (g *MatcherGroup) Size() uint32 {	return g.count}
 |