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