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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2023 - 2024 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
//
//===----------------------------------------------------------------------===//
#if swift(>=5.8)
@available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *)
internal typealias _CharacterRecognizer = Unicode._CharacterRecognizer
@available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *)
extension _CharacterRecognizer {
internal func _isKnownEqual(to other: Self) -> Bool {
// FIXME: Enable when Swift 5.9 ships.
// #if swift(>=5.9)
// if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) { // SwiftStdlib 5.9
// return self == other
// }
// #endif
return false
}
}
@available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *)
extension _CharacterRecognizer {
mutating func firstBreak(
in str: Substring
) -> Range<String.Index>? {
let r = str.utf8.withContiguousStorageIfAvailable { buffer in
self._firstBreak(inUncheckedUnsafeUTF8Buffer: buffer)
}
if let r {
guard let scalarRange = r else { return nil }
let lower = str._utf8Index(at: scalarRange.lowerBound)
let upper = str._utf8Index(at: scalarRange.upperBound)
return lower ..< upper
}
guard !str.isEmpty else { return nil }
var i = str.startIndex
while i < str.endIndex {
let next = str.unicodeScalars.index(after: i)
let scalar = str.unicodeScalars[i]
if self.hasBreak(before: scalar) {
return i ..< next
}
i = next
}
return nil
}
}
@available(macOS 13.3, iOS 16.4, watchOS 9.4, tvOS 16.4, *)
extension _CharacterRecognizer {
init(partialCharacter: Substring.UnicodeScalarView) {
self.init()
var it = partialCharacter.makeIterator()
guard let first = it.next() else { return }
_ = hasBreak(before: first)
while let next = it.next() {
let b = hasBreak(before: next)
assert(!b)
}
}
init(partialCharacter: Substring) {
self.init(partialCharacter: partialCharacter.unicodeScalars)
}
mutating func consumePartialCharacter(_ s: String) {
for scalar in s.unicodeScalars {
let b = hasBreak(before: scalar)
assert(!b)
}
}
mutating func consumePartialCharacter(_ s: Substring) {
for scalar in s.unicodeScalars {
let b = hasBreak(before: scalar)
assert(!b)
}
}
mutating func consumePartialCharacter(_ s: Substring.UnicodeScalarView) {
for scalar in s {
let b = hasBreak(before: scalar)
assert(!b)
}
}
mutating func consumeUntilFirstBreak(
in s: Substring.UnicodeScalarView,
from i: inout String.Index
) -> String.Index? {
while i < s.endIndex {
defer { s.formIndex(after: &i) }
if hasBreak(before: s[i]) {
return i
}
}
return nil
}
init(consuming str: some StringProtocol) {
self.init()
_ = self.consume(str)
}
mutating func consume(
_ s: some StringProtocol
) -> (characters: Int, firstBreak: String.Index, lastBreak: String.Index)? {
consume(Substring(s))
}
mutating func consume(
_ s: Substring
) -> (characters: Int, firstBreak: String.Index, lastBreak: String.Index)? {
consume(s.unicodeScalars)
}
mutating func consume(
_ s: Substring.UnicodeScalarView
) -> (characters: Int, firstBreak: String.Index, lastBreak: String.Index)? {
var i = s.startIndex
guard let first = consumeUntilFirstBreak(in: s, from: &i) else {
return nil
}
var characters = 1
var last = first
while let next = consumeUntilFirstBreak(in: s, from: &i) {
characters += 1
last = next
}
return (characters, first, last)
}
mutating func consume(
_ chunk: BigString._Chunk, upTo index: String.Index
) -> (firstBreak: String.Index, prevBreak: String.Index)? {
let index = chunk.string.unicodeScalars._index(roundingDown: index)
let first = chunk.firstBreak
guard index > first else {
consumePartialCharacter(chunk.string[..<index])
return nil
}
let last = chunk.lastBreak
let prev = index <= last ? chunk.string[first...].index(before: index) : last
consumePartialCharacter(chunk.string[prev..<index])
return (first, prev)
}
mutating func edgeCounts(
consuming s: String
) -> (characters: Int, prefixCount: Int, suffixCount: Int) {
let c = s.utf8.count
guard let (chars, first, last) = consume(s[...]) else {
return (0, c, c)
}
let prefix = s._utf8Offset(of: first)
let suffix = c - s._utf8Offset(of: last)
return (chars, prefix, suffix)
}
}
#endif
|