mirror of
				https://github.com/GayPizzaSpecifications/darwin-apk.git
				synced 2025-11-04 07:59:38 +00:00 
			
		
		
		
	refactor glob matcher (& improve performance)
This commit is contained in:
		@ -7,32 +7,48 @@ import Foundation
 | 
			
		||||
import ArgumentParser
 | 
			
		||||
 | 
			
		||||
struct GlobMatcher: PatternMatcher {
 | 
			
		||||
  private let _patterns: [String]
 | 
			
		||||
  private let _patterns: [Pattern]
 | 
			
		||||
  private let _flags: Int32
 | 
			
		||||
 | 
			
		||||
  init(patterns: [String], ignoreCase: Bool) throws(ArgumentParser.ExitCode) {
 | 
			
		||||
    self._patterns = patterns
 | 
			
		||||
    // Quick hack to make matching without explicit globs easier
 | 
			
		||||
    let globChars = CharacterSet(charactersIn: "*?[]")
 | 
			
		||||
    self._patterns = patterns.map { pattern in
 | 
			
		||||
      if pattern.unicodeScalars.contains(where: globChars.contains) {
 | 
			
		||||
        .wildcard(glob: pattern)
 | 
			
		||||
      } else {
 | 
			
		||||
        .globless(match: pattern)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    self._flags = ignoreCase ? FNM_CASEFOLD : 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  func match(_ field: String) -> Bool {
 | 
			
		||||
    for pattern in self._patterns {
 | 
			
		||||
      // Quick hack to make matching without explicit globs easier
 | 
			
		||||
      if pattern.rangeOfCharacter(from: .init(charactersIn: "*?[]")) == nil {
 | 
			
		||||
      switch pattern {
 | 
			
		||||
      case .globless(let match):
 | 
			
		||||
        if self._flags & FNM_CASEFOLD != 0 {
 | 
			
		||||
          return field.localizedCaseInsensitiveContains(pattern)
 | 
			
		||||
          return field.localizedCaseInsensitiveContains(match)
 | 
			
		||||
        } else {
 | 
			
		||||
          return field.contains(pattern)
 | 
			
		||||
          return field.contains(match)
 | 
			
		||||
        }
 | 
			
		||||
      case .wildcard(let glob):
 | 
			
		||||
        let res = fnmatch(glob, field, self._flags)
 | 
			
		||||
        if res == FNM_NOMATCH {
 | 
			
		||||
          continue
 | 
			
		||||
        } else if res == 0 {
 | 
			
		||||
          return true
 | 
			
		||||
        }
 | 
			
		||||
        fatalError("fnmatch error \(res)")
 | 
			
		||||
      }
 | 
			
		||||
      let res = fnmatch(pattern, field, self._flags)
 | 
			
		||||
      if res == FNM_NOMATCH {
 | 
			
		||||
        continue
 | 
			
		||||
      } else if res == 0 {
 | 
			
		||||
        return true
 | 
			
		||||
      }
 | 
			
		||||
      fatalError("fnmatch error \(res)")
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private extension GlobMatcher {
 | 
			
		||||
  enum Pattern {
 | 
			
		||||
    case wildcard(glob: String)
 | 
			
		||||
    case globless(match: String)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user