github.com/ubuntu/ubuntu-report@v1.7.4-0.20240410144652-96f37d845fac/internal/metrics/filter.go (about)

     1  package metrics
     2  
     3  import (
     4  	"bufio"
     5  	"io"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/pkg/errors"
    10  )
    11  
    12  type filterResult struct {
    13  	r   []string
    14  	err error
    15  }
    16  
    17  func filter(r io.Reader, regex string, getAll bool) <-chan filterResult {
    18  	re := regexp.MustCompile(regex)
    19  	scanner := bufio.NewScanner(r)
    20  	results := make(chan filterResult)
    21  
    22  	go func(r io.Reader) {
    23  		defer close(results)
    24  
    25  		for scanner.Scan() {
    26  			m := re.FindStringSubmatch(scanner.Text())
    27  			if m != nil {
    28  
    29  				if getAll {
    30  					results <- filterResult{r: m[1:]}
    31  					continue
    32  				}
    33  
    34  				// we want the first non empty match (can be null in case of alternative regexp)
    35  				var match string
    36  				for i := 1; match == "" && i < len(m); i++ {
    37  					match = strings.TrimSpace(m[i])
    38  				}
    39  				results <- filterResult{r: []string{match}}
    40  			}
    41  		}
    42  
    43  		if err := scanner.Err(); err != nil {
    44  			results <- filterResult{err: errors.Wrap(err, "error while scanning")}
    45  		}
    46  	}(r)
    47  
    48  	return results
    49  }
    50  
    51  func filterFirst(r io.Reader, regex string, notFoundOk bool) (string, error) {
    52  	result := <-filter(r, regex, false)
    53  	if !notFoundOk && result.err == nil && len(result.r) < 1 {
    54  		result.err = errors.Errorf("couldn't find any line matching %s", regex)
    55  	}
    56  	if len(result.r) < 1 {
    57  		result.r = []string{""}
    58  	}
    59  	return result.r[0], result.err
    60  }
    61  
    62  func filterAll(r io.Reader, regex string) ([]string, error) {
    63  	var results []string
    64  	for result := range filter(r, regex, false) {
    65  		if result.err != nil {
    66  			return nil, result.err
    67  		}
    68  		results = append(results, result.r[0])
    69  	}
    70  
    71  	if len(results) < 1 {
    72  		return nil, errors.Errorf("couldn't find any line matching %s", regex)
    73  	}
    74  
    75  	return results, nil
    76  }