glob/match/match.go

104 lines
1.6 KiB
Go
Raw Normal View History

2015-12-24 17:54:54 +03:00
package match
2016-01-08 20:14:31 +03:00
import (
"fmt"
"strings"
)
2015-12-24 17:54:54 +03:00
type Kind int
2016-01-08 20:14:31 +03:00
// todo use String for Kind, and self.Kind() in every matcher.String()
const (
2015-12-24 17:54:54 +03:00
KindRaw Kind = iota
2016-01-08 20:14:31 +03:00
KindEveryOf
KindAnyOf
KindAny
KindSuper
2015-12-24 17:54:54 +03:00
KindSingle
2016-01-08 20:14:31 +03:00
KindComposition
2015-12-24 17:54:54 +03:00
KindPrefix
KindSuffix
KindPrefixSuffix
2016-01-08 20:14:31 +03:00
KindRange
KindList
KindMin
KindMax
KindBTree
KindContains
2015-12-24 17:54:54 +03:00
)
type Matcher interface {
Match(string) bool
2016-01-09 02:34:41 +03:00
Index(string) (int, []int)
2016-01-12 14:06:59 +03:00
Len() int
2016-01-12 20:49:12 +03:00
String() string
2016-01-08 20:14:31 +03:00
}
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, ","))
}
2016-01-12 14:06:59 +03:00
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
}