+45
@@ -0,0 +1,45 @@
|
||||
package segments
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
func NewIndex(segments LengthIter) (ret Index) {
|
||||
var start Length
|
||||
for l, ok := segments(); ok; l, ok = segments() {
|
||||
ret.segments = append(ret.segments, Extent{start, l})
|
||||
start += l
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Index struct {
|
||||
segments []Extent
|
||||
}
|
||||
|
||||
func (me Index) iterSegments() func() (Length, bool) {
|
||||
return func() (Length, bool) {
|
||||
if len(me.segments) == 0 {
|
||||
return 0, false
|
||||
} else {
|
||||
l := me.segments[0].Length
|
||||
me.segments = me.segments[1:]
|
||||
return l, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (me Index) Locate(e Extent, output Callback) bool {
|
||||
first := sort.Search(len(me.segments), func(i int) bool {
|
||||
_e := me.segments[i]
|
||||
return _e.End() > e.Start
|
||||
})
|
||||
if first == len(me.segments) {
|
||||
return false
|
||||
}
|
||||
e.Start -= me.segments[first].Start
|
||||
me.segments = me.segments[first:]
|
||||
return Scan(me.iterSegments(), e, func(i int, e Extent) bool {
|
||||
return output(i+first, e)
|
||||
})
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package segments
|
||||
|
||||
type Int = int64
|
||||
|
||||
type Length = Int
|
||||
|
||||
func min(i Int, rest ...Int) Int {
|
||||
ret := i
|
||||
for _, i := range rest {
|
||||
if i < ret {
|
||||
ret = i
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type Extent struct {
|
||||
Start, Length Int
|
||||
}
|
||||
|
||||
func (e Extent) End() Int {
|
||||
return e.Start + e.Length
|
||||
}
|
||||
|
||||
type (
|
||||
Callback = func(int, Extent) bool
|
||||
LengthIter = func() (Length, bool)
|
||||
)
|
||||
|
||||
func Scan(haystack LengthIter, needle Extent, callback Callback) bool {
|
||||
i := 0
|
||||
for needle.Length != 0 {
|
||||
l, ok := haystack()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if needle.Start < l || needle.Start == l && l == 0 {
|
||||
e1 := Extent{
|
||||
Start: needle.Start,
|
||||
Length: min(l, needle.End()) - needle.Start,
|
||||
}
|
||||
if e1.Length >= 0 {
|
||||
if !callback(i, e1) {
|
||||
return true
|
||||
}
|
||||
needle.Start = 0
|
||||
needle.Length -= e1.Length
|
||||
}
|
||||
} else {
|
||||
needle.Start -= l
|
||||
}
|
||||
i++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func LocaterFromLengthIter(li LengthIter) Locater {
|
||||
return func(e Extent, c Callback) bool {
|
||||
return Scan(li, e, c)
|
||||
}
|
||||
}
|
||||
|
||||
type Locater func(Extent, Callback) bool
|
||||
Reference in New Issue
Block a user