1package dns 2 3// Implement a simple scanner, return a byte stream from an io reader. 4 5import ( 6 "bufio" 7 "context" 8 "io" 9 "text/scanner" 10) 11 12type scan struct { 13 src *bufio.Reader 14 position scanner.Position 15 eof bool // Have we just seen a eof 16 ctx context.Context 17} 18 19func scanInit(r io.Reader) (*scan, context.CancelFunc) { 20 s := new(scan) 21 s.src = bufio.NewReader(r) 22 s.position.Line = 1 23 24 ctx, cancel := context.WithCancel(context.Background()) 25 s.ctx = ctx 26 27 return s, cancel 28} 29 30// tokenText returns the next byte from the input 31func (s *scan) tokenText() (byte, error) { 32 c, err := s.src.ReadByte() 33 if err != nil { 34 return c, err 35 } 36 select { 37 case <-s.ctx.Done(): 38 return c, context.Canceled 39 default: 40 break 41 } 42 43 // delay the newline handling until the next token is delivered, 44 // fixes off-by-one errors when reporting a parse error. 45 if s.eof == true { 46 s.position.Line++ 47 s.position.Column = 0 48 s.eof = false 49 } 50 if c == '\n' { 51 s.eof = true 52 return c, nil 53 } 54 s.position.Column++ 55 return c, nil 56} 57