// // SemiCaseSensitiveComparator.swift // Tusker // // Created by Shadowfacts on 11/30/22. // Copyright © 2022 Shadowfacts. All rights reserved. // import Foundation /// A comparator that sorts objects with a string key path case insensitively unless they're the same, in which case uppercase comes after lowercase. struct SemiCaseSensitiveComparator: SortComparator { var order: SortOrder = .forward typealias Compared = String static func keyPath(_ keyPath: KeyPath) -> KeyPathComparator { return KeyPathComparator(keyPath, comparator: SemiCaseSensitiveComparator()) } func compare(_ lhs: String, _ rhs: String) -> ComparisonResult { let result = doCompare(lhs, rhs) if case .reverse = order { switch result { case .orderedDescending: return .orderedAscending case .orderedAscending: return .orderedDescending case .orderedSame: return .orderedSame } } else { return result } } private func doCompare(_ lhs: String, _ rhs: String) -> ComparisonResult { for (l, r) in zip(lhs, rhs) { let lLower = l.lowercased() let rLower = r.lowercased() if lLower < rLower { return .orderedAscending } else if lLower > rLower { return .orderedDescending } else { if l < r { return .orderedDescending } else if l > r { return .orderedAscending } } } if lhs.count > rhs.count { return .orderedDescending } else if lhs.count < rhs.count { return .orderedAscending } else { return .orderedSame } } }