You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool/nfs/finder/matcher.go

139 lines
2.8 KiB
Go

package finder
import (
"bytes"
"git.noahlan.cn/noahlan/ntool/nfs"
)
// Matcher for match file path.
type Matcher interface {
// Apply check find elem. return False will skip this file.
Apply(elem Elem) bool
}
// MatcherFunc for match file info, return False will skip this file
type MatcherFunc func(elem Elem) bool
// Apply check file path. return False will skip this file.
func (fn MatcherFunc) Apply(elem Elem) bool {
return fn(elem)
}
// ------------------ Multi matcher wrapper ------------------
// MultiFilter wrapper for multi matchers
type MultiFilter struct {
Before Matcher
Filters []Matcher
}
// Add matchers
func (mf *MultiFilter) Add(fls ...Matcher) {
mf.Filters = append(mf.Filters, fls...)
}
// Apply check file path. return False will filter this file.
func (mf *MultiFilter) Apply(el Elem) bool {
if mf.Before != nil && !mf.Before.Apply(el) {
return false
}
for _, fl := range mf.Filters {
if !fl.Apply(el) {
return false
}
}
return true
}
// NewDirFilters create a new dir matchers
func NewDirFilters(fls ...Matcher) *MultiFilter {
return &MultiFilter{
Before: MatchDir,
Filters: fls,
}
}
// NewFileFilters create a new dir matchers
func NewFileFilters(fls ...Matcher) *MultiFilter {
return &MultiFilter{
Before: MatchFile,
Filters: fls,
}
}
// ------------------ Body Matcher ------------------
// BodyFilter for filter file contents.
type BodyFilter interface {
Apply(filePath string, buf *bytes.Buffer) bool
}
// BodyMatcherFunc for filter file contents.
type BodyMatcherFunc func(filePath string, buf *bytes.Buffer) bool
// Apply for filter file contents.
func (fn BodyMatcherFunc) Apply(filePath string, buf *bytes.Buffer) bool {
return fn(filePath, buf)
}
// BodyFilters multi body matchers as Matcher
type BodyFilters struct {
Filters []BodyFilter
}
// NewBodyFilters create a new body matchers
//
// Usage:
//
// bf := finder.NewBodyFilters(
// finder.BodyMatcherFunc(func(filePath string, buf *bytes.Buffer) bool {
// // filter file contents
// return true
// }),
// )
//
// es := finder.NewFinder('path/to/dir').Add(bf).Elems()
// for el := range es {
// fmt.Println(el.Path())
// }
func NewBodyFilters(fls ...BodyFilter) *BodyFilters {
return &BodyFilters{
Filters: fls,
}
}
// AddFilter add matchers
func (mf *BodyFilters) AddFilter(fls ...BodyFilter) {
mf.Filters = append(mf.Filters, fls...)
}
// Apply check file path. return False will filter this file.
func (mf *BodyFilters) Apply(el Elem) bool {
if el.IsDir() {
return false
}
// read file contents
buf := bytes.NewBuffer(nil)
file, err := nfs.OpenReadFile(el.Path())
if err != nil {
return false
}
_, err = buf.ReadFrom(file)
if err != nil {
file.Close()
return false
}
file.Close()
// apply matchers
for _, fl := range mf.Filters {
if !fl.Apply(el.Path(), buf) {
return false
}
}
return true
}