File: StringGraphemeBreaking.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (134 lines) | stat: -rw-r--r-- 3,227 bytes parent folder | download
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)
  }
}