github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/filter/classes/classes.go (about) 1 // Copyright (c) 2019-2022, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package classes 6 7 import ( 8 "bufio" 9 "fmt" 10 "os" 11 "regexp" 12 "sort" 13 "strings" 14 ) 15 16 // Logger provides logging facilities 17 type Logger interface { 18 Warnf(format string, args ...any) 19 } 20 21 func Match(needles []string, classes []string) bool { 22 matched := 0 23 failed := 0 24 25 for _, needle := range needles { 26 if strings.HasPrefix(needle, "/") && strings.HasSuffix(needle, "/") { 27 needle = strings.TrimPrefix(needle, "/") 28 needle = strings.TrimSuffix(needle, "/") 29 30 needle = fmt.Sprintf("(?i)%s", needle) 31 32 if hasClassMatching(needle, classes) { 33 matched++ 34 } else { 35 failed++ 36 } 37 38 continue 39 } 40 41 if hasClass(needle, classes) { 42 matched++ 43 } else { 44 failed++ 45 } 46 } 47 48 return failed == 0 && matched > 0 49 } 50 51 // MatchFile classes on a AND basis 52 func MatchFile(needles []string, source string, log Logger) bool { 53 classes, err := ReadClasses(source) 54 if err != nil { 55 log.Warnf("Could not parse classes file %s: %s", source, err) 56 return false 57 } 58 59 return Match(needles, classes) 60 } 61 62 func hasClassMatching(needle string, stack []string) bool { 63 for _, class := range stack { 64 if match, _ := regexp.MatchString(needle, class); match { 65 return true 66 } 67 } 68 69 return false 70 } 71 72 func hasClass(needle string, stack []string) bool { 73 lneedle := strings.ToLower(needle) 74 for _, class := range stack { 75 if class == lneedle { 76 return true 77 } 78 } 79 80 return false 81 } 82 83 // ReadClasses reads a given file and attempts to parse it as a typical classes file 84 func ReadClasses(file string) ([]string, error) { 85 classes := []string{} 86 87 fh, err := os.Open(file) 88 if err != nil { 89 return classes, err 90 } 91 92 defer fh.Close() 93 94 scanner := bufio.NewScanner(fh) 95 for scanner.Scan() { 96 classes = append(classes, scanner.Text()) 97 } 98 99 sort.Strings(classes) 100 101 return classes, nil 102 }