@@ -36,16 +36,6 @@ private enum RangeStatus {
3636 case error
3737}
3838
39- private extension StringProtocol {
40- @inline ( __always)
41- func firstIndex( matching characters: Set < Character > ) -> String . Index ? {
42- if characters. isEmpty {
43- return nil
44- }
45- return firstIndex ( where: { characters. contains ( $0) } )
46- }
47- }
48-
4939/// Multi-platform fnmatch implementation. This is intended to be a close match the the POSIX fnmatch of all platforms including Windows (though not all options are supported).
5040///
5141/// - parameter pattern: The pattern to match. When using the ``FnmatchOptions/pathname`` option, any path representation in the pattern is expected to use the POSIX path separator (`/`) to match with the input, and on Windows, the path separator (`/`) will be matched to either separator in the input string ( both `/` and `\` will be matched).
@@ -54,7 +44,7 @@ private extension StringProtocol {
5444/// - returns: `true` if the pattern matches the input, `false` otherwise.
5545///
5646/// - note: On Windows and when using the ``FnmatchOptions/pathname`` option, both separators (`/` and `\`) are recognized (see note on pattern parameter).
57- public func fnmatch( pattern: some StringProtocol , input: some StringProtocol , options: FnmatchOptions = . default, pathSeparators: Set < Character > = Path . pathSeparators ) throws
47+ public func fnmatch( pattern: some StringProtocol , input: some StringProtocol , options: FnmatchOptions = . default, pathSeparators: ( some Collection < Character > ) ? = ( [ Character ] ? ) . none ) throws
5848 -> Bool
5949{
6050 // Use Substrings to avoid String allocations
@@ -76,32 +66,32 @@ public func fnmatch(pattern: some StringProtocol, input: some StringProtocol, op
7666 return false
7767 }
7868 case " ? " :
79- guard let _sc = input. first else {
69+ guard let _sc = input. utf8 . first else {
8070 return false
8171 }
82- if options. contains ( . pathname) && pathSeparators . contains ( _sc) {
72+ if options. contains ( . pathname) && Path . isUTF8PathSeparator ( _sc, separators : pathSeparators ) {
8373 if backtrack ( ) {
8474 return false
8575 }
8676 }
8777 input = input. dropFirst ( )
8878 case " * " :
89- var p = pattern. first
90- while pattern. first == " * " {
79+ var p = pattern. utf8 . first
80+ while pattern. utf8 . first == UInt8 ( ascii : " * " ) {
9181 // consume multiple '*' in pattern
9282 pattern = pattern. dropFirst ( )
93- p = pattern. first
83+ p = pattern. utf8 . first
9484 }
9585 if p == nil {
9686 if options. contains ( . pathname) {
9787 // make sure input does not have any more path separators
98- return input . firstIndex ( matching : pathSeparators) == nil ? true : false
88+ return Path . firstPathSeparatorIndex ( in : input , separators : pathSeparators) == nil
9989 } else {
10090 return true // pattern matched everything else in input
10191 }
102- } else if pattern . first == " / " && options. contains ( . pathname) {
92+ } else if p == UInt8 ( ascii : " / " ) && options. contains ( . pathname) {
10393 // we have a '*/' pattern input must have an path separators to continue
104- guard let newInputIndex = input . firstIndex ( matching : pathSeparators) else {
94+ guard let newInputIndex = Path . firstPathSeparatorIndex ( in : input , separators : pathSeparators) else {
10595 return false
10696 }
10797 input. removeSubrange ( ..< newInputIndex)
@@ -110,14 +100,14 @@ public func fnmatch(pattern: some StringProtocol, input: some StringProtocol, op
110100 bt_pattern = pattern
111101 bt_input = input
112102 case " [ " :
113- guard let _sc = input. first else {
114- return false
115- }
116- if pathSeparators. contains ( _sc) && options. contains ( . pathname) {
103+ if let first = input. utf8. first, Path . isUTF8PathSeparator ( first, separators: pathSeparators) && options. contains ( . pathname) {
117104 if backtrack ( ) {
118105 return false
119106 }
120107 }
108+ guard let _sc = input. first else {
109+ return false
110+ }
121111 var new_input = input. dropFirst ( )
122112 var new_pattern = pattern
123113 switch rangematch ( pattern: & new_pattern, input: & new_input, test: _sc, options: options, pathSeparators: pathSeparators) {
@@ -146,7 +136,7 @@ public func fnmatch(pattern: some StringProtocol, input: some StringProtocol, op
146136 continue
147137 } else {
148138 // windows need to test for both path separators
149- if _pc == " / " && options. contains ( . pathname) && pathSeparators . contains ( _sc) {
139+ if _pc == " / " && options. contains ( . pathname) && Path . isPathSeparator ( _sc, separators : pathSeparators ) {
150140 continue
151141 }
152142 if backtrack ( ) {
@@ -177,15 +167,15 @@ public func fnmatch(pattern: some StringProtocol, input: some StringProtocol, op
177167}
178168
179169@inline ( __always)
180- private func rangematch( pattern: inout Substring , input: inout Substring , test: Character , options: FnmatchOptions , pathSeparators: Set < Character > ) -> RangeStatus {
170+ private func rangematch( pattern: inout Substring , input: inout Substring , test: Character , options: FnmatchOptions , pathSeparators: ( some Collection < Character > ) ? = ( [ Character ] ? ) . none ) -> RangeStatus {
181171 var test = test
182172
183- if !pattern. contains ( " ] " ) {
173+ if !pattern. utf8 . contains ( UInt8 ( ascii : " ] " ) ) {
184174 // unmatched '[' test as literal '['
185175 return " [ " == test ? . match : . noMatch
186176 }
187177
188- let negate = pattern. first == " ! "
178+ let negate = pattern. utf8 . first == UInt8 ( ascii : " ! " )
189179 if negate {
190180 pattern = pattern. dropFirst ( )
191181 }
@@ -198,13 +188,13 @@ private func rangematch(pattern: inout Substring, input: inout Substring, test:
198188 if c == " ] " {
199189 break
200190 }
201- if options. contains ( . pathname) && pathSeparators . contains ( c ) {
191+ if options. contains ( . pathname) && Path . isPathSeparator ( c , separators : pathSeparators ) {
202192 return . noMatch
203193 }
204194 if options. contains ( . caseInsensitive) {
205195 c = Character ( c. lowercased ( ) )
206196 }
207- if pattern. first == " - " {
197+ if pattern. utf8 . first == UInt8 ( ascii : " - " ) {
208198 let subPattern = pattern. dropFirst ( )
209199 if var c2 = subPattern. first {
210200 if c2 != " ] " {
0 commit comments