Skip to content

Commit 45f752a

Browse files
authored
Remove RegexConsumer and fix its dependencies (#617)
* Remove `RegexConsumer` and fix its dependencies This eliminates the RegexConsumer type and rewrites its users to call through to other, existing functionality on Regex or in the Algorithms implementations. RegexConsumer doesn't take account of the dual subranges required for matching, so it can produce results that are inconsistent with matches(of:) and ranges(of:), which were rewritten earlier. rdar://102841216 * Remove remaining from-end algorithm methods This removes methods that are left over from when we were considering from-end algorithms. These aren't tested and may not have the correct semantics, so it's safer to remove them entirely.
1 parent c51e8f2 commit 45f752a

File tree

12 files changed

+63
-666
lines changed

12 files changed

+63
-666
lines changed

Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,6 @@ extension Collection {
2020
}
2121
}
2222

23-
extension BidirectionalCollection {
24-
func _lastRange<S: BackwardCollectionSearcher>(
25-
of searcher: S
26-
) -> Range<Index>? where S.BackwardSearched == Self {
27-
var state = searcher.backwardState(for: self, in: startIndex..<endIndex)
28-
return searcher.searchBack(self, &state)
29-
}
30-
}
31-
3223
// MARK: Fixed pattern algorithms
3324

3425
extension Collection where Element: Equatable {
@@ -78,11 +69,7 @@ extension BidirectionalCollection where SubSequence == Substring {
7869
@_disfavoredOverload
7970
@available(SwiftStdlib 5.7, *)
8071
public func firstRange(of regex: some RegexComponent) -> Range<Index>? {
81-
_firstRange(of: RegexConsumer(regex))
82-
}
83-
84-
@available(SwiftStdlib 5.7, *)
85-
func _lastRange<R: RegexComponent>(of regex: R) -> Range<Index>? {
86-
_lastRange(of: RegexConsumer(regex))
72+
let s = self[...]
73+
return try? regex.regex.firstMatch(in: s)?.range
8774
}
8875
}

Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -115,43 +115,6 @@ extension RangesCollection.Index: Comparable {
115115
}
116116
}
117117

118-
// MARK: `ReversedRangesCollection`
119-
120-
struct ReversedRangesCollection<Searcher: BackwardCollectionSearcher> {
121-
typealias Base = Searcher.BackwardSearched
122-
123-
let base: Base
124-
let searcher: Searcher
125-
126-
init(base: Base, searcher: Searcher) {
127-
self.base = base
128-
self.searcher = searcher
129-
}
130-
}
131-
132-
extension ReversedRangesCollection: Sequence {
133-
public struct Iterator: IteratorProtocol {
134-
let base: Base
135-
let searcher: Searcher
136-
var state: Searcher.BackwardState
137-
138-
init(base: Base, searcher: Searcher) {
139-
self.base = base
140-
self.searcher = searcher
141-
self.state = searcher.backwardState(
142-
for: base, in: base.startIndex..<base.endIndex)
143-
}
144-
145-
public mutating func next() -> Range<Base.Index>? {
146-
searcher.searchBack(base, &state)
147-
}
148-
}
149-
150-
public func makeIterator() -> Iterator {
151-
Iterator(base: base, searcher: searcher)
152-
}
153-
}
154-
155118
// TODO: `Collection` conformance
156119

157120
// MARK: `CollectionSearcher` algorithms
@@ -164,14 +127,6 @@ extension Collection {
164127
}
165128
}
166129

167-
extension BidirectionalCollection {
168-
func _rangesFromBack<S: BackwardCollectionSearcher>(
169-
of searcher: S
170-
) -> ReversedRangesCollection<S> where S.BackwardSearched == Self {
171-
ReversedRangesCollection(base: self, searcher: searcher)
172-
}
173-
}
174-
175130
// MARK: Fixed pattern algorithms
176131

177132
extension Collection where Element: Equatable {
@@ -195,37 +150,6 @@ extension Collection where Element: Equatable {
195150
}
196151
}
197152

198-
extension BidirectionalCollection where Element: Equatable {
199-
// FIXME
200-
// public func rangesFromBack<S: Sequence>(
201-
// of other: S
202-
// ) -> ReversedRangesCollection<ZSearcher<SubSequence>>
203-
// where S.Element == Element
204-
// {
205-
// fatalError()
206-
// }
207-
}
208-
209-
extension BidirectionalCollection where Element: Comparable {
210-
func _ranges<C: Collection>(
211-
of other: C
212-
) -> RangesCollection<PatternOrEmpty<TwoWaySearcher<Self>>>
213-
where C.Element == Element
214-
{
215-
_ranges(of: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other))))
216-
}
217-
218-
// FIXME
219-
// public func rangesFromBack<S: Sequence>(
220-
// of other: S
221-
// ) -> ReversedRangesCollection<PatternOrEmpty<TwoWaySearcher<SubSequence>>>
222-
// where S.Element == Element
223-
// {
224-
// rangesFromBack(
225-
// of: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other))))
226-
// }
227-
}
228-
229153
@available(SwiftStdlib 5.7, *)
230154
struct RegexRangesCollection<Output> {
231155
let base: RegexMatchesCollection<Output>
@@ -299,13 +223,6 @@ extension Collection where SubSequence == Substring {
299223
}
300224

301225
extension BidirectionalCollection where SubSequence == Substring {
302-
@available(SwiftStdlib 5.7, *)
303-
func _rangesFromBack<R: RegexComponent>(
304-
of regex: R
305-
) -> ReversedRangesCollection<RegexConsumer<R, Self>> {
306-
_rangesFromBack(of: RegexConsumer(regex))
307-
}
308-
309226
// FIXME: Return `some Collection<Range<Index>>` for SE-0346
310227
/// Finds and returns the ranges of the all occurrences of a given sequence
311228
/// within the collection.

Sources/_StringProcessing/Algorithms/Algorithms/Split.swift

Lines changed: 29 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -106,121 +106,6 @@ extension SplitCollection: Sequence {
106106
}
107107
}
108108

109-
//extension SplitCollection: Collection {
110-
// public struct Index {
111-
// var start: Base.Index
112-
// var base: RangesCollection<Searcher>.Index
113-
// var isEndIndex: Bool
114-
// }
115-
//
116-
// public var startIndex: Index {
117-
// let base = ranges.startIndex
118-
// return Index(start: ranges.base.startIndex, base: base, isEndIndex: false)
119-
// }
120-
//
121-
// public var endIndex: Index {
122-
// Index(start: ranges.base.endIndex, base: ranges.endIndex, isEndIndex: true)
123-
// }
124-
//
125-
// public func formIndex(after index: inout Index) {
126-
// guard !index.isEndIndex else { fatalError("Cannot advance past endIndex") }
127-
//
128-
// if let range = index.base.range {
129-
// let newStart = range.upperBound
130-
// ranges.formIndex(after: &index.base)
131-
// index.start = newStart
132-
// } else {
133-
// index.isEndIndex = true
134-
// }
135-
// }
136-
//
137-
// public func index(after index: Index) -> Index {
138-
// var index = index
139-
// formIndex(after: &index)
140-
// return index
141-
// }
142-
//
143-
// public subscript(index: Index) -> Base.SubSequence {
144-
// guard !index.isEndIndex else {
145-
// fatalError("Cannot subscript using endIndex")
146-
// }
147-
// let end = index.base.range?.lowerBound ?? ranges.base.endIndex
148-
// return ranges.base[index.start..<end]
149-
// }
150-
//}
151-
//
152-
//extension SplitCollection.Index: Comparable {
153-
// static func == (lhs: Self, rhs: Self) -> Bool {
154-
// switch (lhs.isEndIndex, rhs.isEndIndex) {
155-
// case (false, false):
156-
// return lhs.start == rhs.start
157-
// case (let lhs, let rhs):
158-
// return lhs == rhs
159-
// }
160-
// }
161-
//
162-
// static func < (lhs: Self, rhs: Self) -> Bool {
163-
// switch (lhs.isEndIndex, rhs.isEndIndex) {
164-
// case (true, _):
165-
// return false
166-
// case (_, true):
167-
// return true
168-
// case (false, false):
169-
// return lhs.start < rhs.start
170-
// }
171-
// }
172-
//}
173-
174-
// MARK: `ReversedSplitCollection`
175-
176-
struct ReversedSplitCollection<Searcher: BackwardCollectionSearcher> {
177-
public typealias Base = Searcher.BackwardSearched
178-
179-
let ranges: ReversedRangesCollection<Searcher>
180-
181-
init(ranges: ReversedRangesCollection<Searcher>) {
182-
self.ranges = ranges
183-
}
184-
185-
init(base: Base, searcher: Searcher) {
186-
self.ranges = base._rangesFromBack(of: searcher)
187-
}
188-
}
189-
190-
extension ReversedSplitCollection: Sequence {
191-
public struct Iterator: IteratorProtocol {
192-
let base: Base
193-
var index: Base.Index
194-
var ranges: ReversedRangesCollection<Searcher>.Iterator
195-
var isDone: Bool
196-
197-
init(ranges: ReversedRangesCollection<Searcher>) {
198-
self.base = ranges.base
199-
self.index = base.endIndex
200-
self.ranges = ranges.makeIterator()
201-
self.isDone = false
202-
}
203-
204-
public mutating func next() -> Base.SubSequence? {
205-
guard !isDone else { return nil }
206-
207-
guard let range = ranges.next() else {
208-
isDone = true
209-
return base[..<index]
210-
}
211-
212-
defer { index = range.lowerBound }
213-
return base[range.upperBound..<index]
214-
}
215-
}
216-
217-
public func makeIterator() -> Iterator {
218-
Iterator(ranges: ranges)
219-
}
220-
}
221-
222-
// TODO: `Collection` conformance
223-
224109
// MARK: `CollectionSearcher` algorithms
225110

226111
extension Collection {
@@ -237,16 +122,6 @@ extension Collection {
237122
}
238123
}
239124

240-
extension BidirectionalCollection {
241-
func splitFromBack<Searcher: BackwardCollectionSearcher>(
242-
by separator: Searcher
243-
) -> ReversedSplitCollection<Searcher>
244-
where Searcher.BackwardSearched == Self
245-
{
246-
ReversedSplitCollection(base: self, searcher: separator)
247-
}
248-
}
249-
250125
// MARK: Predicate algorithms
251126

252127
extension Collection {
@@ -260,14 +135,6 @@ extension Collection {
260135
}
261136
}
262137

263-
extension BidirectionalCollection where Element: Equatable {
264-
func splitFromBack(
265-
whereSeparator predicate: @escaping (Element) -> Bool
266-
) -> ReversedSplitCollection<PredicateConsumer<Self>> {
267-
splitFromBack(by: PredicateConsumer(predicate: predicate))
268-
}
269-
}
270-
271138
// MARK: Single element algorithms
272139

273140
extension Collection where Element: Equatable {
@@ -280,14 +147,6 @@ extension Collection where Element: Equatable {
280147
}
281148
}
282149

283-
extension BidirectionalCollection where Element: Equatable {
284-
func splitFromBack(
285-
by separator: Element
286-
) -> ReversedSplitCollection<PredicateConsumer<Self>> {
287-
splitFromBack(whereSeparator: { $0 == separator })
288-
}
289-
}
290-
291150
// MARK: Fixed pattern algorithms
292151

293152
extension Collection where Element: Equatable {
@@ -399,21 +258,6 @@ extension StringProtocol where SubSequence == Substring {
399258

400259
@available(SwiftStdlib 5.7, *)
401260
extension BidirectionalCollection where SubSequence == Substring {
402-
@_disfavoredOverload
403-
func split<R: RegexComponent>(
404-
by separator: R,
405-
maxSplits: Int,
406-
omittingEmptySubsequences: Bool
407-
) -> SplitCollection<RegexConsumer<R, Self>> {
408-
split(by: RegexConsumer(separator), maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences)
409-
}
410-
411-
func splitFromBack<R: RegexComponent>(
412-
by separator: R
413-
) -> ReversedSplitCollection<RegexConsumer<R, Self>> {
414-
splitFromBack(by: RegexConsumer(separator))
415-
}
416-
417261
// TODO: Is this @_disfavoredOverload necessary?
418262
// It prevents split(separator: String) from choosing this overload instead
419263
// of the collection-based version when String has RegexComponent conformance
@@ -431,9 +275,34 @@ extension BidirectionalCollection where SubSequence == Substring {
431275
maxSplits: Int = .max,
432276
omittingEmptySubsequences: Bool = true
433277
) -> [SubSequence] {
434-
Array(split(
435-
by: RegexConsumer(separator),
436-
maxSplits: maxSplits,
437-
omittingEmptySubsequences: omittingEmptySubsequences))
278+
var result: [SubSequence] = []
279+
var subSequenceStart = startIndex
280+
281+
func appendSubsequence(end: Index) -> Bool {
282+
if subSequenceStart == end && omittingEmptySubsequences {
283+
return false
284+
}
285+
result.append(self[subSequenceStart..<end])
286+
return true
287+
}
288+
289+
guard maxSplits > 0 && !isEmpty else {
290+
_ = appendSubsequence(end: endIndex)
291+
return result
292+
}
293+
294+
for match in _matches(of: separator) {
295+
defer { subSequenceStart = match.range.upperBound }
296+
let didAppend = appendSubsequence(end: match.range.lowerBound)
297+
if didAppend && result.count == maxSplits {
298+
break
299+
}
300+
}
301+
302+
if subSequenceStart != endIndex || !omittingEmptySubsequences {
303+
result.append(self[subSequenceStart..<endIndex])
304+
}
305+
306+
return result
438307
}
439308
}

0 commit comments

Comments
 (0)