-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathStringGraphemeBreaking.swift
132 lines (112 loc) · 3.11 KB
/
StringGraphemeBreaking.swift
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
// 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)
}
}
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)
}
}