forked from ClickHouse/clickhouse-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwrite_buffer.go
More file actions
90 lines (79 loc) · 1.81 KB
/
write_buffer.go
File metadata and controls
90 lines (79 loc) · 1.81 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
package clickhouse
import "io"
func wb(cap int) *writeBuffer {
return &writeBuffer{
chunks: [][]byte{
make([]byte, 0, cap),
},
}
}
type writeBuffer struct{ chunks [][]byte }
func (wb *writeBuffer) Write(data []byte) (int, error) {
var (
chunkIdx = len(wb.chunks) - 1
dataSize = len(data)
)
for {
freeSize := cap(wb.chunks[chunkIdx]) - len(wb.chunks[chunkIdx])
if freeSize >= len(data) {
wb.chunks[chunkIdx] = append(wb.chunks[chunkIdx], data...)
return dataSize, nil
}
wb.chunks[chunkIdx] = append(wb.chunks[chunkIdx], data[:freeSize]...)
data = data[freeSize:]
wb.chunks = append(wb.chunks, make([]byte, 0, wb.calcCap(dataSize)))
chunkIdx++
}
}
func (wb *writeBuffer) alloc(size int) []byte {
var (
chunkIdx = len(wb.chunks) - 1
chunkLen = len(wb.chunks[chunkIdx])
)
if (cap(wb.chunks[chunkIdx]) - chunkLen) < size {
wb.chunks = append(wb.chunks, make([]byte, size, wb.calcCap(size)))
return wb.chunks[chunkIdx+1]
}
wb.chunks[chunkIdx] = wb.chunks[chunkIdx][:chunkLen+size]
return wb.chunks[chunkIdx][chunkLen : chunkLen+size]
}
func (wb *writeBuffer) writeTo(w io.Writer) error {
defer wb.free()
for _, chunk := range wb.chunks {
if _, err := w.Write(chunk); err != nil {
return err
}
}
return nil
}
func (wb *writeBuffer) bytes() []byte {
if len(wb.chunks) == 1 {
return wb.chunks[0]
}
bytes := make([]byte, 0, wb.len())
for _, chunk := range wb.chunks {
bytes = append(bytes, chunk...)
}
return bytes
}
func (wb *writeBuffer) len() int {
var v int
for _, chunk := range wb.chunks {
v += len(chunk)
}
return v
}
func (wb *writeBuffer) calcCap(dataSize int) int {
return max(dataSize, (wb.len()/len(wb.chunks))*2)
}
func (wb *writeBuffer) free() {
wb.chunks = [][]byte{
wb.chunks[0][0:0],
}
}
func max(a, b int) int {
if b > a {
return b
}
return a
}