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
|
// RUN: %empty-directory(%t)
// RUN: %target-run-stdlib-swift %S/Inputs/
// REQUIRES: executable_test
// REQUIRES: objc_interop
// REQUIRES: optimized_stdlib
// rdar://124539686
// UNSUPPORTED: CPU=arm64e, CPU=arm64
import StdlibUnittest
import StdlibUnicodeUnittest
import Foundation
let StringGraphemeBreaking = TestSuite("StringGraphemeBreaking")
defer { runAllTests() }
extension String {
var forwardPieces: [[Unicode.Scalar]] {
var i = startIndex
var r: [[Unicode.Scalar]] = []
while i < endIndex {
let j = self.index(after: i)
r.append(Array(self[i..<j].unicodeScalars))
i = j
}
return r
}
var backwardPieces: [[Unicode.Scalar]] {
var j = endIndex
var r: [[Unicode.Scalar]] = []
while j > startIndex {
let i = self.index(before: j)
r.append(Array(self[i..<j].unicodeScalars))
j = i
}
r.reverse()
return r
}
}
func check(
_ string: String,
_ pieces: [[Unicode.Scalar]],
file: String = #file, line: UInt = #line
) {
expectEqual(
string.forwardPieces, pieces,
"string: \(String(reflecting: string)) (forward)",
file: file, line: line)
expectEqual(
string.backwardPieces, pieces,
"string: \(String(reflecting: string)) (backward)",
file: file, line: line)
}
if #available(SwiftStdlib 5.9, *) {
StringGraphemeBreaking.test("grapheme breaking") {
for test in graphemeBreakTests {
check(test.string, test.pieces)
}
}
}
// The most simple subclass of NSString that CoreFoundation does not know
// about.
class NonContiguousNSString: NSString {
required init(coder aDecoder: NSCoder) {
fatalError("don't call this initializer")
}
required init(itemProviderData data: Data, typeIdentifier: String) throws {
fatalError("don't call this initializer")
}
override init() {
_value = []
super.init()
}
init(_ value: some Sequence<UInt16>) {
_value = Array(value)
super.init()
}
@objc(copyWithZone:) override func copy(with zone: NSZone?) -> Any {
// Ensure that copying this string produces a class that CoreFoundation
// does not know about.
return self
}
@objc override var length: Int {
return _value.count
}
@objc override func character(at index: Int) -> unichar {
return _value[index]
}
var _value: [UInt16]
}
extension _StringGuts {
@_silgen_name("$ss11_StringGutsV9isForeignSbvg")
func _isForeign() -> Bool
}
if #available(SwiftStdlib 5.9, *) {
StringGraphemeBreaking.test("grapheme breaking foreign") {
for test in graphemeBreakTests {
let foreign = NonContiguousNSString(test.string.utf16)
let string = foreign as String
expectTrue(string._guts._isForeign())
check(string, test.pieces)
}
}
}
if #available(SwiftStdlib 5.8, *) {
StringGraphemeBreaking.test("GB11") {
// MAN, ZERO WIDTH JOINER, ZERO WIDTH JOINER, GIRL
let string = "\u{1f468}\u{200d}\u{200d}\u{1f467}"
let pieces: [[Unicode.Scalar]] = [
["\u{1f468}", "\u{200d}", "\u{200d}"],
["\u{1f467}"]
]
check(string, pieces)
let foreign = NonContiguousNSString(string.utf16) as String
expectTrue(foreign._guts._isForeign())
check(foreign, pieces)
}
}
|