Skip to content
Snippets Groups Projects
scanner.go 1.01 KiB
Newer Older
  • Learn to ignore specific revisions
  • package dns
    
    // Implement a simple scanner, return a byte stream from an io reader.
    
    import (
    	"bufio"
    
    ale's avatar
    ale committed
    	"context"
    
    	"io"
    	"text/scanner"
    )
    
    type scan struct {
    	src      *bufio.Reader
    	position scanner.Position
    	eof      bool // Have we just seen a eof
    
    ale's avatar
    ale committed
    	ctx      context.Context
    
    ale's avatar
    ale committed
    func scanInit(r io.Reader) (*scan, context.CancelFunc) {
    
    	s := new(scan)
    	s.src = bufio.NewReader(r)
    	s.position.Line = 1
    
    ale's avatar
    ale committed
    
    	ctx, cancel := context.WithCancel(context.Background())
    	s.ctx = ctx
    
    	return s, cancel
    
    }
    
    // tokenText returns the next byte from the input
    func (s *scan) tokenText() (byte, error) {
    	c, err := s.src.ReadByte()
    	if err != nil {
    		return c, err
    	}
    
    ale's avatar
    ale committed
    	select {
    	case <-s.ctx.Done():
    		return c, context.Canceled
    	default:
    		break
    	}
    
    
    	// delay the newline handling until the next token is delivered,
    	// fixes off-by-one errors when reporting a parse error.
    	if s.eof == true {
    		s.position.Line++
    		s.position.Column = 0
    		s.eof = false
    	}
    	if c == '\n' {
    		s.eof = true
    		return c, nil
    	}
    	s.position.Column++
    	return c, nil
    }