gitlab.com/greut/eclint@v0.5.2-0.20240402114752-14681fe6e0bf/scanner.go (about)

     1  package eclint
     2  
     3  import (
     4  	"bufio"
     5  	"io"
     6  )
     7  
     8  // LineFunc is the callback for a line.
     9  //
    10  // It returns the line number starting from zero.
    11  type LineFunc func(int, []byte, bool) error
    12  
    13  // SplitLines works like bufio.ScanLines while keeping the line endings.
    14  func SplitLines(data []byte, atEOF bool) (int, []byte, error) {
    15  	i := 0
    16  	for i < len(data) {
    17  		if data[i] == cr {
    18  			i++
    19  
    20  			if i < len(data) && !atEOF {
    21  				// Request more data
    22  				return 0, nil, nil
    23  			}
    24  
    25  			if i < len(data) && data[i] == lf {
    26  				i++
    27  			}
    28  
    29  			return i, data[0:i], nil
    30  		} else if data[i] == lf {
    31  			i++
    32  
    33  			return i, data[0:i], nil
    34  		}
    35  
    36  		i++
    37  	}
    38  
    39  	if !atEOF {
    40  		// Request more data
    41  		return 0, nil, nil
    42  	}
    43  
    44  	if atEOF && i != 0 {
    45  		return 0, data, bufio.ErrFinalToken
    46  	}
    47  
    48  	return 0, nil, io.EOF
    49  }
    50  
    51  // ReadLines consumes the reader and emit each line via the LineFunc
    52  //
    53  // Line numbering starts at 0. Scanner is pretty smart an will reuse
    54  // its memory structure. This is something we explicitly avoid by copying
    55  // the content to a new slice.
    56  func ReadLines(r io.Reader, fileSize int64, fn LineFunc) []error {
    57  	errs := make([]error, 0)
    58  	sc := bufio.NewScanner(r)
    59  	sc.Split(SplitLines)
    60  
    61  	var read int64
    62  
    63  	i := 0
    64  
    65  	for sc.Scan() {
    66  		l := sc.Bytes()
    67  		line := make([]byte, len(l))
    68  
    69  		copy(line, l)
    70  
    71  		read += int64(len(line))
    72  
    73  		if err := fn(i, line, read == fileSize); err != nil {
    74  			errs = append(errs, err)
    75  		}
    76  
    77  		i++
    78  	}
    79  
    80  	return errs
    81  }