-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbuilder_buffer.go
131 lines (118 loc) · 3.25 KB
/
builder_buffer.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
//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//
package velocypack
// builderBuffer is a byte slice used for building slices.
type builderBuffer []byte
const (
minGrowDelta = 128 // Minimum amount of extra bytes to add to a buffer when growing
maxGrowDelta = 1024 * 1024 // Maximum amount of extra bytes to add to a buffer when growing
)
// IsEmpty returns 0 if there are no values in the buffer.
func (b builderBuffer) IsEmpty() bool {
l := len(b)
return l == 0
}
// Len returns the length of the buffer.
func (b builderBuffer) Len() ValueLength {
l := len(b)
return ValueLength(l)
}
// Bytes returns the bytes written to the buffer.
// The returned slice is only valid until the next modification.
func (b *builderBuffer) Bytes() []byte {
return *b
}
// WriteByte appends a single byte to the buffer.
func (b *builderBuffer) WriteByte(v byte) {
off := len(*b)
b.growCapacity(1)
*b = (*b)[:off+1]
(*b)[off] = v
}
// WriteBytes appends a series of identical bytes to the buffer.
func (b *builderBuffer) WriteBytes(v byte, count uint) {
if count == 0 {
return
}
off := uint(len(*b))
b.growCapacity(count)
*b = (*b)[:off+count]
for i := uint(0); i < count; i++ {
(*b)[off+i] = v
}
}
// Write appends a series of bytes to the buffer.
func (b *builderBuffer) Write(v []byte) {
l := uint(len(v))
if l > 0 {
off := uint(len(*b))
b.growCapacity(l)
*b = (*b)[:off+l]
copy((*b)[off:], v)
}
}
// ReserveSpace ensures that at least n bytes can be added to the buffer without allocating new memory.
func (b *builderBuffer) ReserveSpace(n uint) {
if n > 0 {
b.growCapacity(n)
}
}
// Shrink reduces the length of the buffer by n elements (removing the last elements).
func (b *builderBuffer) Shrink(n uint) {
if n > 0 {
newLen := uint(len(*b)) - n
if newLen < 0 {
newLen = 0
}
*b = (*b)[:newLen]
}
}
// Grow adds n elements to the buffer, returning a slice where the added elements start.
func (b *builderBuffer) Grow(n uint) []byte {
l := uint(len(*b))
if n > 0 {
b.growCapacity(n)
*b = (*b)[:l+n]
}
return (*b)[l:]
}
// growCapacity ensures that there is enough capacity in the buffer to add n elements.
func (b *builderBuffer) growCapacity(n uint) {
_b := *b
curLen := uint(len(_b))
curCap := uint(cap(_b))
newCap := curLen + n
if newCap <= curCap {
// No need to do anything
return
}
// Increase the capacity
extra := newCap // Grow a bit more to avoid copying all the time
if extra < minGrowDelta {
extra = minGrowDelta
} else if extra > maxGrowDelta {
extra = maxGrowDelta
}
newBuffer := make(builderBuffer, curLen, newCap+extra)
copy(newBuffer, _b)
*b = newBuffer
}