/
rchain.go
128 lines (104 loc) · 2.23 KB
/
rchain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright ©2020 The go-hep Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rtree
import (
"fmt"
)
type rchain struct {
ch *chain
rvs []ReadVar
nrab int
beg int64
end int64
ibeg int // first tree to process
iend int // last-1 tree to process
}
var (
_ reader = (*rchain)(nil)
)
func newRChain(ch *chain, rvars []ReadVar, n int, beg, end int64) *rchain {
r := &rchain{
ch: ch,
rvs: rvars,
nrab: n,
beg: beg,
end: end,
}
tbeg, tend := r.findTrees(beg, end)
if tbeg < 0 || tend < 0 {
panic(fmt.Errorf(
"rtree: could not find matching trees in chain for [%d, %d) within [%d, %d)",
beg, end, 0, ch.Entries(),
))
}
r.ibeg = tbeg
r.iend = tend
r.loadRVars()
return r
}
func (r *rchain) Close() error {
return nil
}
func (r *rchain) rvars() []ReadVar { return r.rvs }
func (r *rchain) loadRVars() {
if len(r.ch.trees) == 0 {
return
}
rr := newReader(r.ch.trees[0], r.rvs, r.nrab, 0, 1)
defer rr.Close()
r.rvs = rr.rvars()
}
func (r *rchain) run(off, beg, end int64, f func(RCtx) error) error {
defer r.Close()
trees := r.ch.trees[r.ibeg:r.iend]
if len(trees) == 0 {
return nil
}
err := r.start()
if err != nil {
return err
}
defer r.stop()
for i := r.ibeg; i < r.iend; i++ {
var (
eoff = r.ch.offs[i]
tots = r.ch.tots[i]
ibeg = maxI64(beg-eoff, 0)
iend = minI64(end-eoff, tots-eoff)
err = r.runTree(i, eoff+off, ibeg, iend, f)
)
if err != nil {
return fmt.Errorf("rtree: could not process entry %d: %w", i, err)
}
}
return nil
}
func (r *rchain) findTrees(beg, end int64) (int, int) {
var (
eoff int64
ibeg = -1
iend = -1
)
for i, t := range r.ch.trees {
n := t.Entries()
if ibeg < 0 && eoff <= beg && beg < eoff+n {
ibeg = i
}
if iend < 0 && end <= eoff+n {
iend = i + 1
}
eoff += n
}
if iend < 0 {
iend = len(r.ch.trees)
}
return ibeg, iend
}
func (r *rchain) runTree(itree int, off, beg, end int64, f func(RCtx) error) error {
rr := newReader(r.ch.trees[itree], r.rvs, r.nrab, beg, end)
return rr.run(off, beg, end, f)
}
func (r *rchain) start() error { return nil }
func (r *rchain) stop() {}
func (r *rchain) reset() {}