Skip to content

Commit ded493c

Browse files
committed
Add string-specific implementation for replacing
1 parent 714c2a0 commit ded493c

File tree

1 file changed

+62
-17
lines changed

1 file changed

+62
-17
lines changed

Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,34 @@
1111

1212
// MARK: `CollectionSearcher` algorithms
1313

14+
extension Substring {
15+
func _replacingSubstring(
16+
_ other: Substring,
17+
with replacement: Substring,
18+
maxReplacements: Int = .max
19+
) -> String {
20+
precondition(maxReplacements >= 0)
21+
22+
var result = String()
23+
var index = startIndex
24+
25+
// `maxRanges` is a workaround for https://github.com/apple/swift/issues/59522
26+
var rangeIterator = SubstringSearcher(text: self, pattern: other)
27+
var replacementCount = 0
28+
while let range = rangeIterator.next() {
29+
result.append(contentsOf: self[index..<range.lowerBound])
30+
result.append(contentsOf: replacement)
31+
index = range.upperBound
32+
33+
replacementCount += 1
34+
if replacementCount == maxReplacements { break }
35+
}
36+
37+
result.append(contentsOf: self[index...])
38+
return result
39+
}
40+
}
41+
1442
extension RangeReplaceableCollection {
1543
func _replacing<Ranges: Collection, Replacement: Collection>(
1644
_ ranges: Ranges,
@@ -35,19 +63,6 @@ extension RangeReplaceableCollection {
3563
result.append(contentsOf: self[index...])
3664
return result
3765
}
38-
39-
mutating func _replace<
40-
Ranges: Collection, Replacement: Collection
41-
>(
42-
_ ranges: Ranges,
43-
with replacement: Replacement,
44-
maxReplacements: Int = .max
45-
) where Ranges.Element == Range<Index>, Replacement.Element == Element {
46-
self = _replacing(
47-
ranges,
48-
with: replacement,
49-
maxReplacements: maxReplacements)
50-
}
5166
}
5267

5368
// MARK: Fixed pattern algorithms
@@ -70,10 +85,40 @@ extension RangeReplaceableCollection where Element: Equatable {
7085
subrange: Range<Index>,
7186
maxReplacements: Int = .max
7287
) -> Self where C.Element == Element, Replacement.Element == Element {
73-
_replacing(
74-
self[subrange]._ranges(of: other),
75-
with: replacement,
76-
maxReplacements: maxReplacements)
88+
switch (self, other, replacement) {
89+
case (let str as String, let other as String, let repl as String):
90+
return str[...]._replacingSubstring(other[...], with: repl[...],
91+
maxReplacements: maxReplacements) as! Self
92+
case (let str as Substring, let other as Substring, let repl as Substring):
93+
return str._replacingSubstring(other, with: repl,
94+
maxReplacements: maxReplacements) as! Self
95+
96+
case (let str as Substring, let other as String, let repl as String):
97+
return str[...]._replacingSubstring(other[...], with: repl[...],
98+
maxReplacements: maxReplacements) as! Self
99+
case (let str as String, let other as Substring, let repl as String):
100+
return str[...]._replacingSubstring(other[...], with: repl[...],
101+
maxReplacements: maxReplacements) as! Self
102+
case (let str as String, let other as String, let repl as Substring):
103+
return str[...]._replacingSubstring(other[...], with: repl[...],
104+
maxReplacements: maxReplacements) as! Self
105+
106+
case (let str as String, let other as Substring, let repl as Substring):
107+
return str[...]._replacingSubstring(other[...], with: repl[...],
108+
maxReplacements: maxReplacements) as! Self
109+
case (let str as Substring, let other as String, let repl as Substring):
110+
return str[...]._replacingSubstring(other[...], with: repl[...],
111+
maxReplacements: maxReplacements) as! Self
112+
case (let str as Substring, let other as Substring, let repl as String):
113+
return str[...]._replacingSubstring(other[...], with: repl[...],
114+
maxReplacements: maxReplacements) as! Self
115+
116+
default:
117+
return _replacing(
118+
self[subrange]._ranges(of: other),
119+
with: replacement,
120+
maxReplacements: maxReplacements)
121+
}
77122
}
78123

79124
/// Returns a new collection in which all occurrences of a target sequence

0 commit comments

Comments
 (0)