forked from stripe/veneur
-
Notifications
You must be signed in to change notification settings - Fork 0
/
split_bytes.go
56 lines (50 loc) · 1.47 KB
/
split_bytes.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
package samplers
import "bytes"
// SplitBytes iterates over a byte buffer, returning chunks split by a given
// delimiter byte. It does not perform any allocations, and does not modify the
// buffer it is given. It is not safe for use by concurrent goroutines.
//
// sb := NewSplitBytes(buf, '\n')
// for sb.Next() {
// fmt.Printf("%q\n", sb.Chunk())
// }
//
// The sequence of chunks returned by SplitBytes is equivalent to calling
// bytes.Split, except without allocating an intermediate slice.
type SplitBytes struct {
buf []byte
delim byte
currentChunk []byte
lastChunk bool
}
// NewSplitBytes initializes a SplitBytes struct with the provided buffer and delimiter.
func NewSplitBytes(buf []byte, delim byte) *SplitBytes {
return &SplitBytes{
buf: buf,
delim: delim,
}
}
// Next advances SplitBytes to the next chunk, returning true if a new chunk
// actually exists and false otherwise.
func (sb *SplitBytes) Next() bool {
if sb.lastChunk {
// we do not check the length here, this ensures that we return the
// last chunk in the sequence (even if it's empty)
return false
}
next := bytes.IndexByte(sb.buf, sb.delim)
if next == -1 {
// no newline, consume the entire buffer
sb.currentChunk = sb.buf
sb.buf = nil
sb.lastChunk = true
} else {
sb.currentChunk = sb.buf[:next]
sb.buf = sb.buf[next+1:]
}
return true
}
// Chunk returns the current chunk.
func (sb *SplitBytes) Chunk() []byte {
return sb.currentChunk
}