forked from stellar/go
-
Notifications
You must be signed in to change notification settings - Fork 6
/
range.go
120 lines (101 loc) · 2.25 KB
/
range.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
// Copyright 2016 Stellar Development Foundation and contributors. Licensed
// under the Apache License, Version 2.0. See the COPYING file at the root
// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0
package historyarchive
import (
"fmt"
"sort"
"strings"
)
const CheckpointFreq = uint32(64)
type Range struct {
Low uint32
High uint32
}
func PrevCheckpoint(i uint32) uint32 {
freq := CheckpointFreq
if i < freq {
return freq - 1
}
return ((i / freq) * freq) - 1
}
func NextCheckpoint(i uint32) uint32 {
if i == 0 {
return CheckpointFreq - 1
}
freq := uint64(CheckpointFreq)
v := uint64(i)
n := (((v + freq - 1) / freq) * freq) - 1
if n >= 0xffffffff {
return 0xffffffff
}
return uint32(n)
}
func MakeRange(low uint32, high uint32) Range {
if high < low {
high = low
}
return Range{
Low: PrevCheckpoint(low),
High: NextCheckpoint(high),
}
}
func (r Range) clamp(other Range) Range {
low := r.Low
high := r.High
if low < other.Low {
low = other.Low
}
if high > other.High {
high = other.High
}
return MakeRange(low, high)
}
func (r Range) String() string {
return fmt.Sprintf("[0x%8.8x, 0x%8.8x]", r.Low, r.High)
}
func (r Range) Checkpoints() chan uint32 {
ch := make(chan uint32)
go func() {
for i := uint64(r.Low); i < uint64(r.High); i += uint64(CheckpointFreq) {
ch <- uint32(i)
}
close(ch)
}()
return ch
}
func (r Range) Size() int {
return int(r.High-r.Low) / int(CheckpointFreq)
}
func (r Range) collapsedString() string {
if r.Low == r.High {
return fmt.Sprintf("0x%8.8x", r.Low)
} else {
return fmt.Sprintf("[0x%8.8x-0x%8.8x]", r.Low, r.High)
}
}
type byUint32 []uint32
func (a byUint32) Len() int { return len(a) }
func (a byUint32) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byUint32) Less(i, j int) bool { return a[i] < a[j] }
func fmtRangeList(vs []uint32) string {
sort.Sort(byUint32(vs))
s := make([]string, 0, 10)
var curr *Range
for _, t := range vs {
if curr != nil {
if curr.High+CheckpointFreq == t {
curr.High = t
continue
} else {
s = append(s, curr.collapsedString())
curr = nil
}
}
curr = &Range{Low: t, High: t}
}
if curr != nil {
s = append(s, curr.collapsedString())
}
return strings.Join(s, ", ")
}