Skip to content

Commit 8a75d5a

Browse files
committed
O(n) replacement in NSString.replaceOccurrances
1 parent f013516 commit 8a75d5a

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

Foundation/NSString.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,10 +1423,20 @@ extension NSMutableString {
14231423

14241424
if let findResults = CFStringCreateArrayWithFindResults(kCFAllocatorSystemDefault, _cfObject, target._cfObject, CFRange(searchRange), options._cfValue(true)) {
14251425
let numOccurrences = CFArrayGetCount(findResults)
1426+
let start = _storage.utf16.startIndex
1427+
var newStorage = Substring()
1428+
var sourceStringCurrentIndex = _storage.startIndex
14261429
for cnt in 0..<numOccurrences {
1427-
let rangePtr = CFArrayGetValueAtIndex(findResults, backwards ? cnt : numOccurrences - cnt - 1)
1428-
replaceCharacters(in: NSRange(rangePtr!.load(as: CFRange.self)), with: replacement)
1430+
let rangePtr = CFArrayGetValueAtIndex(findResults, backwards ? numOccurrences - cnt - 1 : cnt)
1431+
let range = NSRange(rangePtr!.load(as: CFRange.self))
1432+
let matchStartIndex = _storage.utf16.index(start, offsetBy: range.location).samePosition(in: _storage)!
1433+
let matchEndIndex = _storage.utf16.index(start, offsetBy: range.location + range.length).samePosition(in: _storage)!
1434+
newStorage += _storage[sourceStringCurrentIndex..<matchStartIndex]
1435+
newStorage += replacement
1436+
sourceStringCurrentIndex = matchEndIndex
14291437
}
1438+
newStorage += _storage[sourceStringCurrentIndex..<_storage.endIndex]
1439+
_storage = String(newStorage)
14301440
return numOccurrences
14311441
} else {
14321442
return 0

0 commit comments

Comments
 (0)