/** * Tae Won Ha - http://taewon.de - @hataewon * See LICENSE */ import Foundation fileprivate let whitespaceCharSet = CharacterSet.whitespaces class FileItemIgnorePattern: Hashable, CustomStringConvertible { static func ==(lhs: FileItemIgnorePattern, rhs: FileItemIgnorePattern) -> Bool { return lhs.pattern == rhs.pattern } static func from(string str: String) -> Set { if str.trimmingCharacters(in: whitespaceCharSet).characters.count == 0 { return Set() } let patterns: [FileItemIgnorePattern] = str .components(separatedBy: ",") .flatMap { let trimmed = $0.trimmingCharacters(in: whitespaceCharSet) if trimmed.characters.count == 0 { return nil } return FileItemIgnorePattern(pattern: trimmed) } return Set(patterns) } static func toString(_ set: Set) -> String { return Array(set) .map { $0.pattern } .sorted() .joined(separator: ", ") } var hashValue: Int { return self.pattern.hashValue } var description: String { return "" } let folderPattern: Bool let pattern: String fileprivate let patternAsFileSysRep: UnsafeMutablePointer init(pattern: String) { self.pattern = pattern self.folderPattern = pattern.hasPrefix("*/") let fileSysRep = (pattern as NSString).fileSystemRepresentation let len = Int(strlen(fileSysRep)) self.patternAsFileSysRep = UnsafeMutablePointer.allocate(capacity: len + 1) memcpy(self.patternAsFileSysRep, fileSysRep, len) self.patternAsFileSysRep[len] = 0 } deinit { let len = Int(strlen(self.patternAsFileSysRep)) self.patternAsFileSysRep.deallocate(capacity: len + 1) } func match(absolutePath path: String) -> Bool { let matches: Int32 let absolutePath = path as NSString if self.folderPattern { matches = fnmatch(self.patternAsFileSysRep, absolutePath.fileSystemRepresentation, FNM_LEADING_DIR | FNM_NOESCAPE) } else { matches = fnmatch(self.patternAsFileSysRep, (absolutePath.lastPathComponent as NSString).fileSystemRepresentation, FNM_NOESCAPE) } return matches != FNM_NOMATCH } }