package match import ( "fmt" "unicode/utf8" ) type BTree struct { Value Primitive Left, Right Matcher } func (self BTree) Kind() Kind { return KindBTree } func (self BTree) len() (l, v, r int, ok bool) { v = self.Value.Len() if self.Left != nil { l = self.Left.Len() } if self.Right != nil { r = self.Right.Len() } ok = l > -1 && v > -1 && r > -1 return } func (self BTree) Len() int { l, v, r, ok := self.len() if ok { return l + v + r } return -1 } func (self BTree) Match(s string) bool { inputLen := len(s) lLen, vLen, rLen, ok := self.len() if ok && lLen+vLen+rLen > inputLen { return false } var offset, limit int if lLen >= 0 { offset = lLen } if rLen >= 0 { limit = inputLen - rLen } else { limit = inputLen } for offset < limit { index, segments := self.Value.Index(s[offset:limit]) if index == -1 { return false } l := string(s[:offset+index]) var left bool if self.Left != nil { left = self.Left.Match(l) } else { left = l == "" } if left { for i := len(segments) - 1; i >= 0; i-- { length := segments[i] if rLen >= 0 && inputLen-(offset+index+length) != rLen { continue } var right bool var r string // if there is no string for the right branch if inputLen <= offset+index+length { r = "" } else { r = s[offset+index+length:] } if self.Right != nil { right = self.Right.Match(r) } else { right = r == "" } if right { return true } } } _, step := utf8.DecodeRuneInString(s[offset+index:]) offset += index + step } return false } func (self BTree) String() string { return fmt.Sprintf("[btree:%s<-%s->%s]", self.Left, self.Value, self.Right) }