-
Notifications
You must be signed in to change notification settings - Fork 7
/
argv.go
executable file
·139 lines (114 loc) · 2.78 KB
/
argv.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
129
130
131
132
133
134
135
136
137
138
139
// thanks https://www.quasilyte.dev/blog/post/pathfinding/#the-priority-queue
package client
import "math/bits"
type PriorityQueue[T any] struct {
buckets [128][]T
mask uint64
forward int
back int
own int
}
func NewQueue[T any]() *PriorityQueue[T] {
own := 64 / 2
return &PriorityQueue[T]{
forward: own,
back: own - 1,
own: own,
}
}
func (q *PriorityQueue[T]) Push(priority int, value T) {
// A q.buckets[i] boundcheck is removed due to this &-masking.
i := uint(priority) & 0b111111
q.buckets[i] = append(q.buckets[i], value)
q.mask |= 1 << i
}
func (q *PriorityQueue[T]) Pop() T {
// The TrailingZeros64 on amd64 is a couple of
// machine instructions (BSF and CMOV).
//
// We only need to execute these two to
// get an index of a non-empty bucket.
i := uint(bits.TrailingZeros64(q.mask))
// This explicit length check is needed to remove
// the q.buckets[i] bound checks below.
if i < uint(len(q.buckets)) {
// These two lines perform a pop operation.
e := q.buckets[i][len(q.buckets[i])-1]
q.buckets[i] = q.buckets[i][:len(q.buckets[i])-1]
if len(q.buckets[i]) == 0 {
// If this bucket is empty now, clear the associated bit.
// This preserves the invariant.
q.mask &^= 1 << i
}
return e
}
// If the queue is empty, return a zero value.
var x T
return x
}
func (q *PriorityQueue[T]) Reset() {
mask := q.mask
// The first bucket to clear is the first non-empty one.
// Skip all empty buckets "to the right".
offset := uint(bits.TrailingZeros64(mask))
mask >>= offset
i := offset
// When every bucket "to the left" is empty, the mask will be
// equal to 0 and this loop will terminate.
for mask != 0 {
q.buckets[i] = q.buckets[i][:0]
mask >>= 1
i++
}
q.mask = 0
}
func (q *PriorityQueue[T]) IsEmpty() bool {
return q.mask == 0
}
func (q *PriorityQueue[T]) Len() int {
return bits.OnesCount64(q.mask)
}
func (q *PriorityQueue[T]) Peek() T {
i := uint(bits.TrailingZeros64(q.mask))
return q.buckets[i][len(q.buckets[i])-1]
}
func (q *PriorityQueue[T]) Add(value T) {
if q.forward == q.Len() {
panic("queue is full")
}
q.Push(q.forward, value)
q.forward++
}
func (q *PriorityQueue[T]) Back(value T) {
if q.back == q.own {
panic("queue is full")
}
q.Push(q.back, value)
q.back--
}
type ByteQueue struct {
*PriorityQueue[[]byte]
batch bool
command []byte
}
func NewByteQueue() *ByteQueue {
return &ByteQueue{PriorityQueue: NewQueue[[]byte]()}
}
func (q *ByteQueue) Glue() []byte {
var glued []byte
if q.batch {
glued = append(glued, []byte("[[BATCH]]")...)
}
for !q.IsEmpty() {
if q.command != nil {
glued = append(glued, q.command...)
glued = append(glued, ' ')
}
glued = append(glued, q.Pop()...)
glued = append(glued, ';')
}
if len(glued) > 0 {
return glued[:len(glued)-1]
}
return glued
}