glob/match/match.go

200 lines
3.1 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"
2016-02-02 22:03:37 +03:00
"sync"
2016-01-08 20:14:31 +03:00
)
2016-01-14 18:29:13 +03:00
const lenOne = 1
2016-01-15 19:50:12 +03:00
const lenZero = 0
2016-01-14 18:29:13 +03:00
const lenNo = -1
2015-12-24 17:54:54 +03:00
type Matcher interface {
Match(string) bool
2016-02-02 22:03:37 +03:00
Index(string, []int) (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))
}
2016-01-13 01:26:48 +03:00
return fmt.Sprintf("%s", strings.Join(s, ","))
2016-01-08 20:14:31 +03:00
}
2016-01-12 14:06:59 +03:00
2016-02-02 22:03:37 +03:00
var segmentsPools [1024]sync.Pool
func toPowerOfTwo(v int) int {
v--
v |= v >> 1
v |= v >> 2
v |= v >> 4
v |= v >> 8
v |= v >> 16
v++
return v
}
func init() {
for i := 1024; i >= 1; i >>= 1 {
func(i int) {
segmentsPools[i-1] = sync.Pool{
New: func() interface{} {
return make([]int, 0, i)
},
}
}(i)
}
}
var segmentsPool = sync.Pool{
New: func() interface{} {
return make([]int, 0, 64)
},
}
func getIdx(c int) int {
p := toPowerOfTwo(c)
switch {
case p >= 1024:
return 1023
case p < 1:
return 0
default:
return p - 1
}
}
func acquireSegments(c int) []int {
return segmentsPools[getIdx(c)].Get().([]int)[:0]
}
func releaseSegments(s []int) {
segmentsPools[getIdx(cap(s))].Put(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)
}
2016-02-02 22:03:37 +03:00
func appendMerge(target, sub []int) []int {
lt, ls := len(target), len(sub)
out := acquireSegments(lt + ls)
for x, y := 0, 0; x < lt || y < ls; {
if x >= lt {
out = append(out, sub[y:]...)
break
}
if y >= ls {
out = append(out, target[x:]...)
break
}
xValue := target[x]
yValue := sub[y]
switch {
case xValue == yValue:
out = append(out, xValue)
x++
y++
case xValue < yValue:
out = append(out, xValue)
x++
case yValue < xValue:
out = append(out, yValue)
y++
}
}
target = append(target[:0], out...)
releaseSegments(out)
return target
}
2016-01-12 14:06:59 +03:00
// mergeSegments merges and sorts given already SORTED and UNIQUE segments.
2016-02-02 22:03:37 +03:00
func mergeSegments(list [][]int, out []int) []int {
2016-01-12 14:06:59 +03:00
var current []int
2016-02-02 22:03:37 +03:00
switch len(list) {
case 0:
return out
case 1:
return list[0]
default:
current = acquireSegments(len(list[0]))
current = append(current, list[0]...)
// releaseSegments(list[0])
}
2016-01-12 14:06:59 +03:00
2016-02-02 22:03:37 +03:00
for _, s := range list[1:] {
next := acquireSegments(len(current) + len(s))
2016-01-12 14:06:59 +03:00
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++
}
}
2016-02-02 22:03:37 +03:00
releaseSegments(current)
2016-01-12 14:06:59 +03:00
current = next
}
2016-02-02 22:03:37 +03:00
out = append(out, current...)
releaseSegments(current)
return out
}
func reverseSegments(input []int) {
l := len(input)
m := l / 2
for i := 0; i < m; i++ {
input[i], input[l-i-1] = input[l-i-1], input[i]
}
2016-01-12 14:06:59 +03:00
}