Documentation
¶
Overview ¶
Package buffer contains buffer and wrapper types for byte slices. It is useful for writing lexers or other high-performance byte slice handling.
The `Reader` and `Writer` types implement the `io.Reader` and `io.Writer` respectively and provide a thinner and faster interface than `bytes.Buffer`. The `Shifter` type is useful for building lexers because it keeps track of the start and end position of a byte selection, and shifts the bytes whenever a valid token is found. The `Lexer` is however an improved version of `Shifter`, allowing zero-copy for the parser by using a (kind of) ring buffer underneath.
Index ¶
- Variables
- type Lexer
- func (z *Lexer) Err() error
- func (z *Lexer) Free(n int)
- func (z *Lexer) Lexeme() []byte
- func (z *Lexer) Move(n int)
- func (z *Lexer) Peek(pos int) byte
- func (z *Lexer) PeekRune(pos int) (rune, int)
- func (z *Lexer) Pos() int
- func (z *Lexer) Rewind(pos int)
- func (z *Lexer) Shift() []byte
- func (z *Lexer) ShiftLen() int
- func (z *Lexer) Skip()
- type Reader
- type Shifter
- func (z *Shifter) Bytes() []byte
- func (z *Shifter) Err() error
- func (z *Shifter) IsEOF() bool
- func (z *Shifter) Move(n int)
- func (z *Shifter) MoveTo(n int)
- func (z *Shifter) Peek(end int) byte
- func (z *Shifter) PeekRune(i int) (rune, int)
- func (z *Shifter) Pos() int
- func (z *Shifter) Shift() []byte
- func (z *Shifter) Skip()
- type Writer
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var MinBuf = defaultBufSize
MinBuf specifies the default initial length of internal buffers. Solely here to support old versions of parse.
Functions ¶
This section is empty.
Types ¶
type Lexer ¶
type Lexer struct {
// contains filtered or unexported fields
}
Lexer is a buffered reader that allows peeking forward and shifting, taking an io.Reader. It keeps data in-memory until Free, taking a byte length, is called to move beyond the data.
func NewLexer ¶
NewLexer returns a new Lexer for a given io.Reader with a 4kB estimated buffer size. If the io.Reader implements Bytes, that buffer is used instead.
func NewLexerSize ¶
NewLexerSize returns a new Lexer for a given io.Reader and estimated required buffer size. If the io.Reader implements Bytes, that buffer is used instead.
func (*Lexer) Err ¶
Err returns the error returned from io.Reader. It may still return valid bytes for a while though.
func (*Lexer) Free ¶
Free frees up bytes of length n from previously shifted tokens. Each call to Shift should at one point be followed by a call to Free with a length returned by ShiftLen.
func (*Lexer) Peek ¶
Peek returns the ith byte relative to the end position and possibly does an allocation. Peek returns zero when an error has occurred, Err returns the error. TODO: inline function
func (*Lexer) PeekRune ¶
PeekRune returns the rune and rune length of the ith byte relative to the end position.
func (*Lexer) Shift ¶
Shift returns the bytes of the current selection and collapses the position to the end of the selection. It also returns the number of bytes we moved since the last call to Shift. This can be used in calls to Free.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader implements an io.Reader over a byte slice.
func NewReader ¶
NewReader returns a new Reader for a given byte slice.
Example ¶
r := NewReader([]byte("Lorem ipsum"))
w := &bytes.Buffer{}
io.Copy(w, r)
fmt.Println(w.String())
Output: Lorem ipsum
type Shifter ¶
type Shifter struct {
// contains filtered or unexported fields
}
Shifter is a buffered reader that allows peeking forward and shifting, taking an io.Reader.
func NewShifter ¶
NewShifter returns a new Shifter for a given io.Reader with a 4kB estimated buffer size. If the io.Reader implements Bytes, that buffer is used instead.
Example ¶
b := bytes.NewBufferString("Lorem ipsum")
z := NewShifter(b)
for {
c := z.Peek(0)
if c == ' ' {
break
}
z.Move(1)
}
fmt.Println(string(z.Shift()))
Output: Lorem
func NewShifterSize ¶
NewShifterSize returns a new Shifter for a given io.Reader and estimated required buffer size. If the io.Reader implements Bytes, that buffer is used instead.
func (*Shifter) Err ¶
Err returns the error returned from io.Reader. It may still return valid bytes for a while though.
func (*Shifter) IsEOF ¶
IsEOF returns true when it has encountered EOF meaning that it has loaded the last data in memory (ie. previously returned byte slice will not be overwritten by Peek). Calling IsEOF is faster than checking Err() == io.EOF.
Example ¶
b := bytes.NewBufferString("Lorem ipsum") // bytes.Buffer provides a Bytes function, NewShifter uses that and r.IsEOF() always returns true
z := NewShifter(b)
z.Move(5)
lorem := z.Shift()
if !z.IsEOF() { // required when io.Reader doesn't provide a Bytes function
buf := make([]byte, len(lorem))
copy(buf, lorem)
lorem = buf
}
z.Peek(0) // might reallocate the internal buffer
fmt.Println(string(lorem))
Output: Lorem
func (*Shifter) Peek ¶
Peek returns the ith byte relative to the end position and possibly does an allocation. Calling Peek may invalidate previous returned byte slices by Bytes or Shift, unless IsEOF returns true. Peek returns zero when an error has occurred, Err returns the error.
func (*Shifter) PeekRune ¶
PeekRune returns the rune and rune length of the ith byte relative to the end position.
Example ¶
b := bytes.NewBufferString("† dagger") // † has a byte length of 3
z := NewShifter(b)
c, n := z.PeekRune(0)
fmt.Println(string(c), n)
Output: † 3
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer implements an io.Writer over a byte slice.
func NewWriter ¶
NewWriter returns a new Writer for a given byte slice.
Example ¶
w := NewWriter(make([]byte, 0, 11)) // initial buffer length is 11
w.Write([]byte("Lorem ipsum"))
fmt.Println(string(w.Bytes()))
Output: Lorem ipsum
func (*Writer) Reset ¶
func (w *Writer) Reset()
Reset empties and reuses the current buffer. Subsequent writes will overwrite the buffer, so any reference to the underlying slice is invalidated after this call.
Example ¶
w := NewWriter(make([]byte, 0, 11)) // initial buffer length is 10
w.Write([]byte("garbage that will be overwritten")) // does reallocation
w.Reset()
w.Write([]byte("Lorem ipsum"))
fmt.Println(string(w.Bytes()))
Output: Lorem ipsum