Skip to content

Expose matches, ranges and split #304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,24 @@ extension BidirectionalCollection {
// MARK: Fixed pattern algorithms

extension Collection where Element: Equatable {
// FIXME: Replace `RangesCollection` when SE-0346 is enabled
func ranges<S: Sequence>(
of other: S
) -> RangesCollection<ZSearcher<Self>> where S.Element == Element {
ranges(of: ZSearcher(pattern: Array(other), by: ==))
}

// FIXME: Return `some Collection<Range<Index>>` for SE-0346
/// Finds and returns the ranges of the all occurrences of a given sequence
/// within the collection.
/// - Parameter other: The sequence to search for.
/// - Returns: A collection of ranges of all occurrences of `other`. Returns
/// an empty collection if `other` is not found.
@available(SwiftStdlib 5.7, *)
public func ranges<S: Sequence>(
of other: S
) -> [Range<Index>] where S.Element == Element {
ranges(of: ZSearcher(pattern: Array(other), by: ==)).map { $0 }
}
}

extension BidirectionalCollection where Element: Equatable {
Expand Down Expand Up @@ -217,8 +229,8 @@ extension BidirectionalCollection where Element: Comparable {
// MARK: Regex algorithms

extension BidirectionalCollection where SubSequence == Substring {
// FIXME: Replace `RangesCollection` when SE-0346 is enabled
@available(SwiftStdlib 5.7, *)
@_disfavoredOverload
func ranges<R: RegexComponent>(
of regex: R
) -> RangesCollection<RegexConsumer<R, Self>> {
Expand All @@ -231,4 +243,17 @@ extension BidirectionalCollection where SubSequence == Substring {
) -> ReversedRangesCollection<RegexConsumer<R, Self>> {
rangesFromBack(of: RegexConsumer(regex))
}

// FIXME: Return `some Collection<Range<Index>>` for SE-0346
/// Finds and returns the ranges of the all occurrences of a given sequence
/// within the collection.
/// - Parameter regex: The regex to search for.
/// - Returns: A collection or ranges in the receiver of all occurrences of
/// `regex`. Returns an empty collection if `regex` is not found.
@available(SwiftStdlib 5.7, *)
public func ranges<R: RegexComponent>(
of regex: R
) -> [Range<Index>] {
Array(ranges(of: RegexConsumer(regex)))
}
}
35 changes: 25 additions & 10 deletions Sources/_StringProcessing/Algorithms/Algorithms/Split.swift
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,24 @@ extension BidirectionalCollection where Element: Equatable {
// MARK: Fixed pattern algorithms

extension Collection where Element: Equatable {
// FIXME: Replace `SplitCollection` when SE-0346 is enabled
@_disfavoredOverload
func split<S: Sequence>(
by separator: S
) -> SplitCollection<ZSearcher<Self>> where S.Element == Element {
split(by: ZSearcher(pattern: Array(separator), by: ==))
}

// FIXME: Return `some Collection<SubSequence>` for SE-0346
/// Returns the longest possible subsequences of the collection, in order,
/// around elements equal to the given separator.
/// - Parameter separator: The element to be split upon.
/// - Returns: A collection of subsequences, split from this collection's
/// elements.
func split<S: Sequence>(
@available(SwiftStdlib 5.7, *)
public func split<S: Sequence>(
by separator: S
) -> SplitCollection<ZSearcher<Self>> where S.Element == Element {
split(by: ZSearcher(pattern: Array(separator), by: ==))
) -> [SubSequence] where S.Element == Element {
Array(split(by: ZSearcher(pattern: Array(separator), by: ==)))
}
}

Expand Down Expand Up @@ -282,12 +290,7 @@ extension BidirectionalCollection where Element: Comparable {

@available(SwiftStdlib 5.7, *)
extension BidirectionalCollection where SubSequence == Substring {
// FIXME: Replace `SplitCollection` when SE-0346 is enabled
/// Returns the longest possible subsequences of the collection, in order,
/// around elements equal to the given separator.
/// - Parameter separator: A regex describing elements to be split upon.
/// - Returns: A collection of substrings, split from this collection's
/// elements.
@_disfavoredOverload
func split<R: RegexComponent>(
by separator: R
) -> SplitCollection<RegexConsumer<R, Self>> {
Expand All @@ -299,4 +302,16 @@ extension BidirectionalCollection where SubSequence == Substring {
) -> ReversedSplitCollection<RegexConsumer<R, Self>> {
splitFromBack(by: RegexConsumer(separator))
}

// FIXME: Return `some Collection<Substring>` for SE-0346
/// Returns the longest possible subsequences of the collection, in order,
/// around elements equal to the given separator.
/// - Parameter separator: A regex describing elements to be split upon.
/// - Returns: A collection of substrings, split from this collection's
/// elements.
public func split<R: RegexComponent>(
by separator: R
) -> [SubSequence] {
Array(split(by: RegexConsumer(separator)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ extension RangeReplaceableCollection where SubSequence == Substring {
var result = Self()
result.append(contentsOf: self[..<index])

for match in self[subrange]._matches(of: regex)
for match in self[subrange].matches(of: regex)
.prefix(maxReplacements)
{
result.append(contentsOf: self[index..<match.range.lowerBound])
Expand Down
15 changes: 8 additions & 7 deletions Sources/_StringProcessing/Algorithms/Matching/Matches.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,8 @@ extension BidirectionalCollection {
// MARK: Regex algorithms

extension BidirectionalCollection where SubSequence == Substring {
// FIXME: Replace `MatchesCollection` when SE-0346 is enabled
/// Returns a collection containing all matches of the specified regex.
/// - Parameter regex: The regex to search for.
/// - Returns: A collection of matches of `regex`.
@available(SwiftStdlib 5.7, *)
@_disfavoredOverload
func matches<R: RegexComponent>(
of regex: R
) -> MatchesCollection<RegexConsumer<R, Self>> {
Expand All @@ -202,10 +199,14 @@ extension BidirectionalCollection where SubSequence == Substring {
matchesFromBack(of: RegexConsumer(regex))
}

// FIXME: Replace the returned value as `some Collection<Regex<R.Output>.Match>
// when SE-0346 is enabled
// FIXME: Return `some Collection<Regex<R.Output>.Match> for SE-0346
/// Returns a collection containing all matches of the specified regex.
/// - Parameter regex: The regex to search for.
/// - Returns: A collection of matches of `regex`.
@available(SwiftStdlib 5.7, *)
func _matches<R: RegexComponent>(of r: R) -> [Regex<R.RegexOutput>.Match] {
public func matches<R: RegexComponent>(
of r: R
) -> [Regex<R.RegexOutput>.Match] {
let slice = self[...]
var start = self.startIndex
let end = self.endIndex
Expand Down
12 changes: 5 additions & 7 deletions Tests/RegexBuilderTests/AlgorithmsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@ import _StringProcessing

@available(SwiftStdlib 5.7, *)
class RegexConsumerTests: XCTestCase {
// FIXME: enable this test when we update the return type of `matches(of:)`
// when SE-0346 is available
// func testMatches() {
// let regex = Capture(OneOrMore(.digit)) { 2 * Int($0)! }
// let str = "foo 160 bar 99 baz"
// XCTAssertEqual(str.matches(of: regex).map(\.result.1), [320, 198])
// }
func testMatches() {
let regex = Capture(OneOrMore(.digit)) { 2 * Int($0)! }
let str = "foo 160 bar 99 baz"
XCTAssertEqual(str.matches(of: regex).map(\.output.1), [320, 198])
}

func testMatchReplace() {
func replaceTest<R: RegexComponent>(
Expand Down
6 changes: 3 additions & 3 deletions Tests/RegexTests/AlgorithmsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,13 @@ class RegexConsumerTests: XCTestCase {
XCTAssertEqual(s2.replacing(regex, with: ""), "")

XCTAssertEqual(
s._matches(of: regex).map(\.0),
s.matches(of: regex).map(\.0),
["aaa", "aaaaaa", "aaaaaaaaaa"])
XCTAssertEqual(
s1._matches(of: regex).map(\.0),
s1.matches(of: regex).map(\.0),
["aaaaaa", "aaaaaaaaaa"])
XCTAssertEqual(
s2._matches(of: regex).map(\.0),
s2.matches(of: regex).map(\.0),
["aa"])
}
}