glob/match/match.go

103 lines
1.6 KiB
Go

package match
import (
"fmt"
"strings"
)
type Kind int
// todo use String for Kind, and self.Kind() in every matcher.String()
const (
KindRaw Kind = iota
KindEveryOf
KindAnyOf
KindAny
KindSuper
KindSingle
KindComposition
KindPrefix
KindSuffix
KindPrefixSuffix
KindRange
KindList
KindMin
KindMax
KindBTree
KindContains
)
type Matcher interface {
Match(string) bool
Index(string) (int, []int)
Len() int
}
type Matchers []Matcher
func (m Matchers) String() string {
var s []string
for _, matcher := range m {
s = append(s, fmt.Sprint(matcher))
}
return fmt.Sprintf("matchers[%s]", strings.Join(s, ","))
}
func appendIfNotAsPrevious(target []int, val int) []int {
l := len(target)
if l != 0 && target[l-1] == val {
return target
}
return append(target, val)
}
// mergeSegments merges and sorts given already SORTED and UNIQUE segments.
func mergeSegments(segments [][]int) []int {
var current []int
for _, s := range segments {
if current == nil {
current = s
continue
}
var next []int
for x, y := 0, 0; x < len(current) || y < len(s); {
if x >= len(current) {
next = append(next, s[y:]...)
break
}
if y >= len(s) {
next = append(next, current[x:]...)
break
}
xValue := current[x]
yValue := s[y]
switch {
case xValue == yValue:
x++
y++
next = appendIfNotAsPrevious(next, xValue)
case xValue < yValue:
next = appendIfNotAsPrevious(next, xValue)
x++
case yValue < xValue:
next = appendIfNotAsPrevious(next, yValue)
y++
}
}
current = next
}
return current
}