Source file src/cmd/compile/internal/ssa/_gen/multiscanner.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bufio"
     9  	"io"
    10  )
    11  
    12  // NamedScanner is a simple struct to pair a name with a Scanner.
    13  type NamedScanner struct {
    14  	Name    string
    15  	Scanner *bufio.Scanner
    16  }
    17  
    18  // NamedReader is a simple struct to pair a name with a Reader,
    19  // which will be converted to a Scanner using bufio.NewScanner.
    20  type NamedReader struct {
    21  	Name   string
    22  	Reader io.Reader
    23  }
    24  
    25  // MultiScanner scans over multiple bufio.Scanners as if they were a single stream.
    26  // It also keeps track of the name of the current scanner and the line number.
    27  type MultiScanner struct {
    28  	scanners   []NamedScanner
    29  	scannerIdx int
    30  	line       int
    31  	totalLine  int
    32  	err        error
    33  }
    34  
    35  // NewMultiScanner creates a new MultiScanner from slice of NamedScanners.
    36  func NewMultiScanner(scanners []NamedScanner) *MultiScanner {
    37  	return &MultiScanner{
    38  		scanners:   scanners,
    39  		scannerIdx: -1, // Start before the first scanner
    40  	}
    41  }
    42  
    43  // MultiScannerFromReaders creates a new MultiScanner from a slice of NamedReaders.
    44  func MultiScannerFromReaders(readers []NamedReader) *MultiScanner {
    45  	var scanners []NamedScanner
    46  	for _, r := range readers {
    47  		scanners = append(scanners, NamedScanner{
    48  			Name:    r.Name,
    49  			Scanner: bufio.NewScanner(r.Reader),
    50  		})
    51  	}
    52  	return NewMultiScanner(scanners)
    53  }
    54  
    55  // Scan advances the scanner to the next token, which will then be
    56  // available through the Text method. It returns false when the scan stops,
    57  // either by reaching the end of the input or an error.
    58  // After Scan returns false, the Err method will return any error that
    59  // occurred during scanning, except that if it was io.EOF, Err
    60  // will return nil.
    61  func (ms *MultiScanner) Scan() bool {
    62  	if ms.scannerIdx == -1 {
    63  		ms.scannerIdx = 0
    64  	}
    65  
    66  	for ms.scannerIdx < len(ms.scanners) {
    67  		current := ms.scanners[ms.scannerIdx]
    68  		if current.Scanner.Scan() {
    69  			ms.line++
    70  			ms.totalLine++
    71  			return true
    72  		}
    73  		if err := current.Scanner.Err(); err != nil {
    74  			ms.err = err
    75  			return false
    76  		}
    77  		// Move to the next scanner
    78  		ms.scannerIdx++
    79  		ms.line = 0
    80  	}
    81  
    82  	return false
    83  }
    84  
    85  // Text returns the most recent token generated by a call to Scan.
    86  func (ms *MultiScanner) Text() string {
    87  	if ms.scannerIdx < 0 || ms.scannerIdx >= len(ms.scanners) {
    88  		return ""
    89  	}
    90  	return ms.scanners[ms.scannerIdx].Scanner.Text()
    91  }
    92  
    93  // Err returns the first non-EOF error that was encountered by the MultiScanner.
    94  func (ms *MultiScanner) Err() error {
    95  	return ms.err
    96  }
    97  
    98  // Name returns the name of the current scanner.
    99  func (ms *MultiScanner) Name() string {
   100  	if ms.scannerIdx < 0 {
   101  		return "<before first>"
   102  	}
   103  	if ms.scannerIdx >= len(ms.scanners) {
   104  		return "<after last>"
   105  	}
   106  	return ms.scanners[ms.scannerIdx].Name
   107  }
   108  
   109  // Line returns the current line number within the current scanner.
   110  func (ms *MultiScanner) Line() int {
   111  	return ms.line
   112  }
   113  
   114  // TotalLine returns the total number of lines scanned across all scanners.
   115  func (ms *MultiScanner) TotalLine() int {
   116  	return ms.totalLine
   117  }
   118  

View as plain text