-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiterator.go
More file actions
118 lines (101 loc) · 3 KB
/
iterator.go
File metadata and controls
118 lines (101 loc) · 3 KB
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
package blazedb
import (
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/chunk"
)
// ColumnIterator iterates over a DB's position/column pairs.
//
// When an error is encountered, any call to Next will return false and will
// yield no position/chunk pairs. The error can be queried by calling the Error
// method. Calling Release is still necessary.
//
// An iterator must be released after use, but it is not necessary to read
// an iterator until exhaustion.
type ColumnIterator struct {
db *DB
r *IteratorRange
err error
keys []chunkKey
current int
col *chunk.Column
pos world.ChunkPos
dim world.Dimension
}
// newColumnIterator creates a new column iterator.
func newColumnIterator(db *DB, r *IteratorRange) *ColumnIterator {
iter := &ColumnIterator{
db: db,
r: r,
keys: make([]chunkKey, 0),
current: -1,
}
// Collect all keys that match the range
db.index.iterate(func(key chunkKey, offset, size int64) bool {
if r.within(key.pos(), key.dimension()) {
iter.keys = append(iter.keys, key)
}
return true
})
return iter
}
// Next moves the iterator to the next key/value pair.
// It returns false if the iterator is exhausted.
func (iter *ColumnIterator) Next() bool {
if iter.err != nil {
return false
}
iter.current++
if iter.current >= len(iter.keys) {
iter.col = nil
iter.dim = nil
return false
}
key := iter.keys[iter.current]
iter.pos = key.pos()
iter.dim = key.dimension()
var err error
iter.col, err = iter.db.LoadColumn(iter.pos, iter.dim)
if err != nil {
iter.err = err
return false
}
return true
}
// Column returns the current chunk column, or nil if none.
func (iter *ColumnIterator) Column() *chunk.Column {
return iter.col
}
// Position returns the position of the current column.
func (iter *ColumnIterator) Position() world.ChunkPos {
return iter.pos
}
// Dimension returns the dimension of the current column, or nil if none.
func (iter *ColumnIterator) Dimension() world.Dimension {
return iter.dim
}
// Release releases resources associated with the iterator.
func (iter *ColumnIterator) Release() {
iter.keys = nil
iter.col = nil
}
// Error returns any accumulated error.
func (iter *ColumnIterator) Error() error {
return iter.err
}
// IteratorRange limits what columns are returned by a ColumnIterator.
type IteratorRange struct {
// Min and Max limit what chunk positions are returned.
// A zero value for both causes all positions to be within range.
Min, Max world.ChunkPos
// Dimension specifies what dimension chunks should be from.
// If nil, all dimensions are included.
Dimension world.Dimension
}
// within checks if a position and dimension is within the IteratorRange.
func (r *IteratorRange) within(pos world.ChunkPos, dim world.Dimension) bool {
if dim != r.Dimension && r.Dimension != nil {
return false
}
return ((r.Min == world.ChunkPos{}) && (r.Max == world.ChunkPos{})) ||
pos[0] >= r.Min[0] && pos[0] < r.Max[0] && pos[1] >= r.Min[1] && pos[1] < r.Max[1]
}