|
5 | 5 | // Created by Alsey Coleman Miller on 7/4/25. |
6 | 6 | // |
7 | 7 |
|
| 8 | +#if canImport(FoundationEssentials) |
| 9 | +import FoundationEssentials |
| 10 | +#elseif canImport(Foundation) |
8 | 11 | import Foundation |
| 12 | +#endif |
9 | 13 | import CoreModel |
10 | 14 | import SQLite |
11 | 15 |
|
@@ -150,8 +154,8 @@ internal extension FetchRequest.Predicate.Comparison { |
150 | 154 | case .like: |
151 | 155 | // Translate Cocoa-style wildcards (`*`, `?`) to SQL (`%`, `_`). |
152 | 156 | let pattern = try right.likePattern(predicate: predicate) |
153 | | - .replacingOccurrences(of: "*", with: "%") |
154 | | - .replacingOccurrences(of: "?", with: "_") |
| 157 | + .replacing(occurrencesOf: "*", with: "%") |
| 158 | + .replacing(occurrencesOf: "?", with: "_") |
155 | 159 | return .like(column: column, pattern: pattern) |
156 | 160 | case .in: |
157 | 161 | let values = try right.constantBindings(predicate: predicate) |
@@ -308,9 +312,9 @@ private extension FetchRequest.Predicate.Expression { |
308 | 312 | throw SQLiteDatabaseError.invalidPredicate(predicate) |
309 | 313 | } |
310 | 314 | return value |
311 | | - .replacingOccurrences(of: "\\", with: "\\\\") |
312 | | - .replacingOccurrences(of: "%", with: "\\%") |
313 | | - .replacingOccurrences(of: "_", with: "\\_") |
| 315 | + .replacing(occurrencesOf: "\\", with: "\\\\") |
| 316 | + .replacing(occurrencesOf: "%", with: "\\%") |
| 317 | + .replacing(occurrencesOf: "_", with: "\\_") |
314 | 318 | } |
315 | 319 | } |
316 | 320 |
|
@@ -343,6 +347,31 @@ internal extension String { |
343 | 347 |
|
344 | 348 | /// Quote as a SQL identifier. |
345 | 349 | var quotedIdentifier: String { |
346 | | - "\"" + replacingOccurrences(of: "\"", with: "\"\"") + "\"" |
| 350 | + "\"" + replacing(occurrencesOf: "\"", with: "\"\"") + "\"" |
| 351 | + } |
| 352 | + |
| 353 | + /// Replace every occurrence of `target` with `replacement`. |
| 354 | + /// |
| 355 | + /// Pure-stdlib stand-in for Foundation's `replacingOccurrences(of:with:)`, |
| 356 | + /// which `FoundationEssentials` (Android/Linux) does not provide; the |
| 357 | + /// stdlib's own `replacing(_:with:)` requires a newer platform floor than |
| 358 | + /// this package supports on Darwin. |
| 359 | + func replacing(occurrencesOf target: String, with replacement: String) -> String { |
| 360 | + guard target.isEmpty == false else { |
| 361 | + return self |
| 362 | + } |
| 363 | + var result = String() |
| 364 | + result.reserveCapacity(count) |
| 365 | + var index = startIndex |
| 366 | + while index < endIndex { |
| 367 | + if self[index...].hasPrefix(target) { |
| 368 | + result += replacement |
| 369 | + index = self.index(index, offsetBy: target.count) |
| 370 | + } else { |
| 371 | + result.append(self[index]) |
| 372 | + index = self.index(after: index) |
| 373 | + } |
| 374 | + } |
| 375 | + return result |
347 | 376 | } |
348 | 377 | } |
0 commit comments