-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmdict_record_range_tree.go
More file actions
75 lines (63 loc) · 2.16 KB
/
mdict_record_range_tree.go
File metadata and controls
75 lines (63 loc) · 2.16 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
package mdx
// RecordBlockRangeTreeNode represents a node in the record block range tree.
// This tree is used to efficiently find the record block corresponding to a given offset.
type RecordBlockRangeTreeNode struct {
startRange int64
endRange int64
data *MdictRecordBlockInfoListItem
left *RecordBlockRangeTreeNode
right *RecordBlockRangeTreeNode
}
// BuildRangeTree constructs a range tree from a list of record block info items.
// This tree allows for efficient querying of record blocks based on an offset.
func BuildRangeTree(list []*MdictRecordBlockInfoListItem, root *RecordBlockRangeTreeNode) {
if len(list) == 0 {
return
}
if len(list) == 1 {
root.data = list[0]
root.startRange = list[0].deCompressAccumulatorOffset
root.endRange = list[0].deCompressAccumulatorOffset + list[0].deCompressSize
return
}
if len(list) == 2 {
root.startRange = list[0].deCompressAccumulatorOffset
root.endRange = list[1].deCompressAccumulatorOffset + list[1].deCompressSize
root.left = new(RecordBlockRangeTreeNode)
BuildRangeTree(list[:1], root.left)
root.right = new(RecordBlockRangeTreeNode)
BuildRangeTree(list[1:], root.right)
return
}
root.startRange = list[0].deCompressAccumulatorOffset
root.endRange = list[len(list)-1].deCompressAccumulatorOffset + list[len(list)-1].deCompressSize
mid := (len(list) - 1) / 2
if mid > 0 {
root.left = new(RecordBlockRangeTreeNode)
BuildRangeTree(list[0:mid], root.left)
}
if mid < len(list) {
root.right = new(RecordBlockRangeTreeNode)
BuildRangeTree(list[mid:], root.right)
}
}
// QueryRangeData queries the range tree to find the record block info item
// that contains the given queryRange offset.
func QueryRangeData(root *RecordBlockRangeTreeNode, queryRange int64) *MdictRecordBlockInfoListItem {
if root == nil {
return nil
}
if root.startRange > queryRange || root.endRange < queryRange {
return nil
}
if root.data != nil {
return root.data
}
if root.left != nil && root.left.endRange > queryRange {
return QueryRangeData(root.left, queryRange)
}
if root.right != nil && root.right.startRange <= queryRange {
return QueryRangeData(root.right, queryRange)
}
return nil
}