File: StringDeconstruction.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-- 4,665 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: %target-run-simple-swift
// REQUIRES: executable_test
// UNSUPPORTED: freestanding

import StdlibUnittest
defer { runAllTests() }

var StringDeconstructTests = TestSuite("StringDeconstructTests")

enum ExpectedDeconstruction {
  case scratchIfAvailable
  case interiorPointer
  case extraAllocation
}

func expectDeconstruct(
  _ str: String,
  _ expectDeconstruct: ExpectedDeconstruction,
  stackTrace: SourceLocStack = SourceLocStack(),
  showFrame: Bool = true,
  file: String = #file, line: UInt = #line
) {
  var stackTrace = stackTrace.pushIf(showFrame, file: file, line: line)
  let expectBytes = Array(str.utf8)

  _ = Array<UInt8>(unsafeUninitializedCapacity: 16) {
    buffer, initializedCount in
    // Deconstruct with a provided scratch space

    // WS == with scratch, N == nil
    let scratch = UnsafeMutableRawBufferPointer(buffer)
    let (ownerWS, ptrWS, lengthWS, usedScratchWS, allocatedMemoryWS)
      : (AnyObject?, UnsafePointer<UInt8>, Int, Bool, Bool)
      = str._deconstructUTF8(scratch: scratch)
    let (ownerN, ptrN, lengthN, usedScratchN, allocatedMemoryN)
      : (AnyObject?, UnsafePointer<UInt8>, Int, Bool, Bool)
      = str._deconstructUTF8(scratch: nil)

    let rawBytesWS = UnsafeRawBufferPointer(start: ptrWS, count: lengthWS)
    let rawBytesN = UnsafeRawBufferPointer(start: ptrN, count: lengthN)

    expectEqualSequence(expectBytes, rawBytesWS, stackTrace: stackTrace)
    expectEqualSequence(rawBytesWS, rawBytesN, stackTrace: stackTrace)

    switch expectDeconstruct {
      case .scratchIfAvailable:
        expectNil(ownerWS, stackTrace: stackTrace)
        expectNotNil(ownerN, stackTrace: stackTrace)

        expectEqual(scratch.baseAddress, rawBytesWS.baseAddress,
          stackTrace: stackTrace)
        expectNotEqual(scratch.baseAddress, rawBytesN.baseAddress,
          stackTrace: stackTrace)

        expectTrue(lengthWS < scratch.count, stackTrace: stackTrace)
        expectTrue(lengthN < scratch.count, stackTrace: stackTrace)

        expectTrue(usedScratchWS, stackTrace: stackTrace)
        expectFalse(usedScratchN, stackTrace: stackTrace)

        expectFalse(allocatedMemoryWS, stackTrace: stackTrace)
        expectTrue(allocatedMemoryN, stackTrace: stackTrace)

      case .interiorPointer:
        // TODO: owner == (immortal ? nil : StringObject.largeAddress)
        expectTrue(str.isContiguousUTF8, stackTrace: stackTrace)
        var copy = str
        copy.withUTF8 {
          expectEqual($0.baseAddress, ptrWS, stackTrace: stackTrace)
          expectEqual($0.baseAddress, ptrN, stackTrace: stackTrace)
          expectEqual($0.count, lengthWS, stackTrace: stackTrace)
          expectEqual($0.count, lengthN, stackTrace: stackTrace)
        }

        expectFalse(usedScratchWS, stackTrace: stackTrace)
        expectFalse(usedScratchN, stackTrace: stackTrace)
        expectFalse(allocatedMemoryWS, stackTrace: stackTrace)
        expectFalse(allocatedMemoryN, stackTrace: stackTrace)
      case .extraAllocation:
        expectFalse(str.isContiguousUTF8, stackTrace: stackTrace)
        expectNotNil(ownerWS, stackTrace: stackTrace)
        expectNotNil(ownerN, stackTrace: stackTrace)
        expectFalse(usedScratchWS, stackTrace: stackTrace)
        expectFalse(usedScratchN, stackTrace: stackTrace)
        expectTrue(allocatedMemoryWS, stackTrace: stackTrace)
        expectTrue(allocatedMemoryN, stackTrace: stackTrace)
    }
  }
}

@inline(never)
func id<T>(_ a: T) -> T { a }

StringDeconstructTests.test("deconstruct") {
  let smallASCII = "abcd"

#if _pointerBitWidth(_32)
  let smallUTF8 = "ジッパ"
#else
  let smallUTF8 = "ジッパー"
#endif

  let large = "the quick fox jumped over the lazy brown dog"

  var largeMortal = large
  largeMortal.append(id("🧟‍♀️"))
  largeMortal.append(id(largeMortal.last!))

  expectDeconstruct(smallASCII, .scratchIfAvailable)
  expectDeconstruct(smallUTF8, .scratchIfAvailable)
  expectDeconstruct(large, .interiorPointer)
  expectDeconstruct(largeMortal, .interiorPointer)
}

#if _runtime(_ObjC)
import Foundation
StringDeconstructTests.test("deconstruct cocoa") {
  let smallCocoa: NSString = "aaa"
  let largeASCIICocoa: NSString = "the quick fox jumped over the lazy brown dog"
  let largeCocoa: NSString = "the quick 🧟‍♀️ ate the slow 🧠"

#if _pointerBitWidth(_32)
  expectDeconstruct(smallCocoa as String, .interiorPointer)
#elseif _pointerBitWidth(_64)
  expectDeconstruct(smallCocoa as String, .scratchIfAvailable)
#else
#error("Unknown platform")
#endif

  expectDeconstruct(largeASCIICocoa as String, .interiorPointer)
  expectDeconstruct(largeCocoa as String, .extraAllocation)
}
#endif