1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
/// Wraps a searcher that searches for a given pattern. If the pattern is empty, falls back on matching every empty index range exactly once.
struct PatternOrEmpty<Searcher: CollectionSearcher> {
let searcher: Searcher?
}
extension PatternOrEmpty: CollectionSearcher {
typealias Searched = Searcher.Searched
struct State {
enum Representation {
case state(Searcher.State)
case empty(index: Searched.Index, end: Searched.Index)
case emptyDone
}
let representation: Representation
}
func state(
for searched: Searcher.Searched,
in range: Range<Searched.Index>
) -> State {
if let searcher = searcher {
return State(
representation: .state(searcher.state(for: searched, in: range)))
} else {
return State(
representation: .empty(index: range.lowerBound, end: range.upperBound))
}
}
func search(
_ searched: Searched,
_ state: inout State
) -> Range<Searched.Index>? {
switch state.representation {
case .state(var s):
// TODO: Avoid a potential copy-on-write copy here
let result = searcher!.search(searched, &s)
state = State(representation: .state(s))
return result
case .empty(let index, let end):
if index == end {
state = State(representation: .emptyDone)
} else {
state = State(
representation: .empty(index: searched.index(after: index), end: end))
}
return index..<index
case .emptyDone:
return nil
}
}
}
|