Skip to content

Update algorithms methods to match proposal #330

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 9 commits into from
Apr 24, 2022
22 changes: 18 additions & 4 deletions Sources/_StringProcessing/Algorithms/Algorithms/Contains.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ extension Collection where Element: Equatable {
/// - Returns: `true` if the collection contains the specified sequence,
/// otherwise `false`.
@available(SwiftStdlib 5.7, *)
public func contains<S: Sequence>(_ other: S) -> Bool
where S.Element == Element
public func contains<C: Collection>(_ other: C) -> Bool
where C.Element == Element
{
firstRange(of: other) != nil
}
}

extension BidirectionalCollection where Element: Comparable {
func contains<S: Sequence>(_ other: S) -> Bool
where S.Element == Element
func contains<C: Collection>(_ other: C) -> Bool
where C.Element == Element
{
if #available(SwiftStdlib 5.7, *) {
return firstRange(of: other) != nil
Expand All @@ -46,6 +46,20 @@ extension BidirectionalCollection where Element: Comparable {
}
}

// Overload breakers

extension StringProtocol {
@available(SwiftStdlib 5.7, *)
public func contains(_ other: String) -> Bool {
firstRange(of: other) != nil
}

@available(SwiftStdlib 5.7, *)
public func contains(_ other: Substring) -> Bool {
firstRange(of: other) != nil
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add these to the proposal?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so - we just need to make sure these are winning the overload resolution vs Foundation's overlay version. However we do that is just an implementation detail.


// MARK: Regex algorithms

extension BidirectionalCollection where SubSequence == Substring {
Expand Down
28 changes: 15 additions & 13 deletions Sources/_StringProcessing/Algorithms/Algorithms/FirstRange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,33 @@ extension BidirectionalCollection {
// MARK: Fixed pattern algorithms

extension Collection where Element: Equatable {
/// Finds and returns the range of the first occurrence of a given sequence
/// within the collection.
/// - Parameter sequence: The sequence to search for.
/// Finds and returns the range of the first occurrence of a given collection
/// within this collection.
///
/// - Parameter other: The collection to search for.
/// - Returns: A range in the collection of the first occurrence of `sequence`.
/// Returns nil if `sequence` is not found.
@available(SwiftStdlib 5.7, *)
public func firstRange<S: Sequence>(
of sequence: S
) -> Range<Index>? where S.Element == Element {
public func firstRange<C: Collection>(
of other: C
) -> Range<Index>? where C.Element == Element {
// TODO: Use a more efficient search algorithm
let searcher = ZSearcher<SubSequence>(pattern: Array(sequence), by: ==)
let searcher = ZSearcher<SubSequence>(pattern: Array(other), by: ==)
return searcher.search(self[...], in: startIndex..<endIndex)
}
}

extension BidirectionalCollection where Element: Comparable {
/// Finds and returns the range of the first occurrence of a given sequence
/// within the collection.
/// - Parameter other: The sequence to search for.
/// Finds and returns the range of the first occurrence of a given collection
/// within this collection.
///
/// - Parameter other: The collection to search for.
/// - Returns: A range in the collection of the first occurrence of `sequence`.
/// Returns `nil` if `sequence` is not found.
@available(SwiftStdlib 5.7, *)
public func firstRange<S: Sequence>(
of other: S
) -> Range<Index>? where S.Element == Element {
public func firstRange<C: Collection>(
of other: C
) -> Range<Index>? where C.Element == Element {
let searcher = PatternOrEmpty(
searcher: TwoWaySearcher<SubSequence>(pattern: Array(other)))
let slice = self[...]
Expand Down
19 changes: 10 additions & 9 deletions Sources/_StringProcessing/Algorithms/Algorithms/Ranges.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ extension BidirectionalCollection {
// MARK: Fixed pattern algorithms

extension Collection where Element: Equatable {
func ranges<S: Sequence>(
of other: S
) -> RangesCollection<ZSearcher<Self>> where S.Element == Element {
func ranges<C: Collection>(
of other: C
) -> RangesCollection<ZSearcher<Self>> where C.Element == Element {
ranges(of: ZSearcher(pattern: Array(other), by: ==))
}

Expand All @@ -188,9 +188,9 @@ extension Collection where Element: Equatable {
/// - 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 {
public func ranges<C: Collection>(
of other: C
) -> [Range<Index>] where C.Element == Element {
ranges(of: ZSearcher(pattern: Array(other), by: ==)).map { $0 }
}
}
Expand All @@ -207,10 +207,10 @@ extension BidirectionalCollection where Element: Equatable {
}

extension BidirectionalCollection where Element: Comparable {
func ranges<S: Sequence>(
of other: S
func ranges<C: Collection>(
of other: C
) -> RangesCollection<PatternOrEmpty<TwoWaySearcher<Self>>>
where S.Element == Element
where C.Element == Element
{
ranges(of: PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other))))
}
Expand Down Expand Up @@ -247,6 +247,7 @@ extension BidirectionalCollection where SubSequence == Substring {
// 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.
Expand Down
36 changes: 18 additions & 18 deletions Sources/_StringProcessing/Algorithms/Algorithms/Replace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ extension RangeReplaceableCollection where Element: Equatable {
/// - Returns: A new collection in which all occurrences of `other` in
/// `subrange` of the collection are replaced by `replacement`.
@available(SwiftStdlib 5.7, *)
public func replacing<S: Sequence, Replacement: Collection>(
_ other: S,
public func replacing<C: Collection, Replacement: Collection>(
_ other: C,
with replacement: Replacement,
subrange: Range<Index>,
maxReplacements: Int = .max
) -> Self where S.Element == Element, Replacement.Element == Element {
) -> Self where C.Element == Element, Replacement.Element == Element {
replacing(
ZSearcher(pattern: Array(other), by: ==),
with: replacement,
Expand All @@ -101,11 +101,11 @@ extension RangeReplaceableCollection where Element: Equatable {
/// - Returns: A new collection in which all occurrences of `other` in
/// `subrange` of the collection are replaced by `replacement`.
@available(SwiftStdlib 5.7, *)
public func replacing<S: Sequence, Replacement: Collection>(
_ other: S,
public func replacing<C: Collection, Replacement: Collection>(
_ other: C,
with replacement: Replacement,
maxReplacements: Int = .max
) -> Self where S.Element == Element, Replacement.Element == Element {
) -> Self where C.Element == Element, Replacement.Element == Element {
replacing(
other,
with: replacement,
Expand All @@ -120,11 +120,11 @@ extension RangeReplaceableCollection where Element: Equatable {
/// - maxReplacements: A number specifying how many occurrences of `other`
/// to replace. Default is `Int.max`.
@available(SwiftStdlib 5.7, *)
public mutating func replace<S: Sequence, Replacement: Collection>(
_ other: S,
public mutating func replace<C: Collection, Replacement: Collection>(
_ other: C,
with replacement: Replacement,
maxReplacements: Int = .max
) where S.Element == Element, Replacement.Element == Element {
) where C.Element == Element, Replacement.Element == Element {
self = replacing(
other,
with: replacement,
Expand All @@ -136,36 +136,36 @@ extension RangeReplaceableCollection where Element: Equatable {
extension RangeReplaceableCollection
where Self: BidirectionalCollection, Element: Comparable
{
func replacing<S: Sequence, Replacement: Collection>(
_ other: S,
func replacing<C: Collection, Replacement: Collection>(
_ other: C,
with replacement: Replacement,
subrange: Range<Index>,
maxReplacements: Int = .max
) -> Self where S.Element == Element, Replacement.Element == Element {
) -> Self where C.Element == Element, Replacement.Element == Element {
replacing(
PatternOrEmpty(searcher: TwoWaySearcher(pattern: Array(other))),
with: replacement,
subrange: subrange,
maxReplacements: maxReplacements)
}

func replacing<S: Sequence, Replacement: Collection>(
_ other: S,
func replacing<C: Collection, Replacement: Collection>(
_ other: C,
with replacement: Replacement,
maxReplacements: Int = .max
) -> Self where S.Element == Element, Replacement.Element == Element {
) -> Self where C.Element == Element, Replacement.Element == Element {
replacing(
other,
with: replacement,
subrange: startIndex..<endIndex,
maxReplacements: maxReplacements)
}

mutating func replace<S: Sequence, Replacement: Collection>(
_ other: S,
mutating func replace<C: Collection, Replacement: Collection>(
_ other: C,
with replacement: Replacement,
maxReplacements: Int = .max
) where S.Element == Element, Replacement.Element == Element {
) where C.Element == Element, Replacement.Element == Element {
self = replacing(
other,
with: replacement,
Expand Down
Loading