Blame vendor/github.com/gobwas/glob/match/btree.go

Packit Service 4d2de5
package match
Packit Service 4d2de5
Packit Service 4d2de5
import (
Packit Service 4d2de5
	"fmt"
Packit Service 4d2de5
	"unicode/utf8"
Packit Service 4d2de5
)
Packit Service 4d2de5
Packit Service 4d2de5
type BTree struct {
Packit Service 4d2de5
	Value            Matcher
Packit Service 4d2de5
	Left             Matcher
Packit Service 4d2de5
	Right            Matcher
Packit Service 4d2de5
	ValueLengthRunes int
Packit Service 4d2de5
	LeftLengthRunes  int
Packit Service 4d2de5
	RightLengthRunes int
Packit Service 4d2de5
	LengthRunes      int
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
func NewBTree(Value, Left, Right Matcher) (tree BTree) {
Packit Service 4d2de5
	tree.Value = Value
Packit Service 4d2de5
	tree.Left = Left
Packit Service 4d2de5
	tree.Right = Right
Packit Service 4d2de5
Packit Service 4d2de5
	lenOk := true
Packit Service 4d2de5
	if tree.ValueLengthRunes = Value.Len(); tree.ValueLengthRunes == -1 {
Packit Service 4d2de5
		lenOk = false
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	if Left != nil {
Packit Service 4d2de5
		if tree.LeftLengthRunes = Left.Len(); tree.LeftLengthRunes == -1 {
Packit Service 4d2de5
			lenOk = false
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	if Right != nil {
Packit Service 4d2de5
		if tree.RightLengthRunes = Right.Len(); tree.RightLengthRunes == -1 {
Packit Service 4d2de5
			lenOk = false
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	if lenOk {
Packit Service 4d2de5
		tree.LengthRunes = tree.LeftLengthRunes + tree.ValueLengthRunes + tree.RightLengthRunes
Packit Service 4d2de5
	} else {
Packit Service 4d2de5
		tree.LengthRunes = -1
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	return tree
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
func (self BTree) Len() int {
Packit Service 4d2de5
	return self.LengthRunes
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// todo?
Packit Service 4d2de5
func (self BTree) Index(s string) (int, []int) {
Packit Service 4d2de5
	return -1, nil
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
func (self BTree) Match(s string) bool {
Packit Service 4d2de5
	inputLen := len(s)
Packit Service 4d2de5
Packit Service 4d2de5
	// self.Length, self.RLen and self.LLen are values meaning the length of runes for each part
Packit Service 4d2de5
	// here we manipulating byte length for better optimizations
Packit Service 4d2de5
	// but these checks still works, cause minLen of 1-rune string is 1 byte.
Packit Service 4d2de5
	if self.LengthRunes != -1 && self.LengthRunes > inputLen {
Packit Service 4d2de5
		return false
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// try to cut unnecessary parts
Packit Service 4d2de5
	// by knowledge of length of right and left part
Packit Service 4d2de5
	var offset, limit int
Packit Service 4d2de5
	if self.LeftLengthRunes >= 0 {
Packit Service 4d2de5
		offset = self.LeftLengthRunes
Packit Service 4d2de5
	}
Packit Service 4d2de5
	if self.RightLengthRunes >= 0 {
Packit Service 4d2de5
		limit = inputLen - self.RightLengthRunes
Packit Service 4d2de5
	} else {
Packit Service 4d2de5
		limit = inputLen
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	for offset < limit {
Packit Service 4d2de5
		// search for matching part in substring
Packit Service 4d2de5
		index, segments := self.Value.Index(s[offset:limit])
Packit Service 4d2de5
		if index == -1 {
Packit Service 4d2de5
			releaseSegments(segments)
Packit Service 4d2de5
			return false
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		l := s[:offset+index]
Packit Service 4d2de5
		var left bool
Packit Service 4d2de5
		if self.Left != nil {
Packit Service 4d2de5
			left = self.Left.Match(l)
Packit Service 4d2de5
		} else {
Packit Service 4d2de5
			left = l == ""
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		if left {
Packit Service 4d2de5
			for i := len(segments) - 1; i >= 0; i-- {
Packit Service 4d2de5
				length := segments[i]
Packit Service 4d2de5
Packit Service 4d2de5
				var right bool
Packit Service 4d2de5
				var r string
Packit Service 4d2de5
				// if there is no string for the right branch
Packit Service 4d2de5
				if inputLen <= offset+index+length {
Packit Service 4d2de5
					r = ""
Packit Service 4d2de5
				} else {
Packit Service 4d2de5
					r = s[offset+index+length:]
Packit Service 4d2de5
				}
Packit Service 4d2de5
Packit Service 4d2de5
				if self.Right != nil {
Packit Service 4d2de5
					right = self.Right.Match(r)
Packit Service 4d2de5
				} else {
Packit Service 4d2de5
					right = r == ""
Packit Service 4d2de5
				}
Packit Service 4d2de5
Packit Service 4d2de5
				if right {
Packit Service 4d2de5
					releaseSegments(segments)
Packit Service 4d2de5
					return true
Packit Service 4d2de5
				}
Packit Service 4d2de5
			}
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		_, step := utf8.DecodeRuneInString(s[offset+index:])
Packit Service 4d2de5
		offset += index + step
Packit Service 4d2de5
Packit Service 4d2de5
		releaseSegments(segments)
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	return false
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
func (self BTree) String() string {
Packit Service 4d2de5
	const n string = "<nil>"
Packit Service 4d2de5
	var l, r string
Packit Service 4d2de5
	if self.Left == nil {
Packit Service 4d2de5
		l = n
Packit Service 4d2de5
	} else {
Packit Service 4d2de5
		l = self.Left.String()
Packit Service 4d2de5
	}
Packit Service 4d2de5
	if self.Right == nil {
Packit Service 4d2de5
		r = n
Packit Service 4d2de5
	} else {
Packit Service 4d2de5
		r = self.Right.String()
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	return fmt.Sprintf("<btree:[%s<-%s->%s]>", l, self.Value, r)
Packit Service 4d2de5
}