Skip to content

Commit 7a01bde

Browse files
lorenteymilseman
authored andcommitted
Add support for compiling without the Objective-C runtime. (swiftlang#17)
* Restore Linux support On Linux, Cocoa strings aren't supported; however, we still support opaque strings via the new _OpaqueString protocol, whose requirements approximate a minimal NSString API. (One use of this would be to allow NSString from the open source Foundation lib to be bridged directly. This isn't implemented yet.) _OpaqueString's interface is not a subset of NSString; in particular, the method getCharacters(_:, range:) is replaced with copyCodeUnits(from:,into:), to get around dealing with _SwiftNSRange. _OpaqueString is not yet supported on Apple platforms. * _NSStringCore: Fix length requirement Be consistent with Foundation; NSString.length is imported/defined as `var length: Int`, not `func length() -> UInt`. * _StringGuts: Add file header * _StringGuts: Add _objectIdentifier property, for testing allocation behavior Also, update tests that used to rely on _underlyingCocoaString -- it is only available with the Objective-C runtime. * Fix lowercased()/uppercased() on Linux. * [test] Relax check for realloc behavior on widening String storage Widening a String from single-byte to two-byte storage may increase available capacity. * Add deprecated compatibility definitions for SPI used by swift-corelibs-foundation
1 parent 7d05b28 commit 7a01bde

File tree

11 files changed

+451
-176
lines changed

11 files changed

+451
-176
lines changed

stdlib/public/core/String.swift

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -958,16 +958,14 @@ extension String {
958958
into processCodeUnit: (Encoding.CodeUnit) -> Void
959959
) {
960960
if _slowPath(_guts._isOpaque) {
961-
#if _runtime(_ObjC)
962961
let opaque = _guts._asOpaque()
963962
var i = opaque.makeIterator()
964963
Unicode.UTF16.ForwardParser._parse(&i) {
965964
Encoding._transcode($0, from: UTF16.self).forEach(processCodeUnit)
966965
}
967-
#else
968-
_sanityCheckFailure("encode: non-native string without objc runtime")
969-
#endif
970-
} else if _guts.isASCII {
966+
return
967+
}
968+
if _guts.isASCII {
971969
let ascii = _guts._unmanagedASCIIView
972970
if encoding == Unicode.ASCII.self
973971
|| encoding == Unicode.UTF8.self
@@ -983,12 +981,12 @@ extension String {
983981
Unicode.Scalar(_unchecked: UInt32(b))).forEach(processCodeUnit)
984982
}
985983
}
986-
} else {
987-
let utf16 = _guts._unmanagedUTF16View
988-
var i = utf16.makeIterator()
989-
Unicode.UTF16.ForwardParser._parse(&i) {
990-
Encoding._transcode($0, from: UTF16.self).forEach(processCodeUnit)
991-
}
984+
return
985+
}
986+
let utf16 = _guts._unmanagedUTF16View
987+
var i = utf16.makeIterator()
988+
Unicode.UTF16.ForwardParser._parse(&i) {
989+
Encoding._transcode($0, from: UTF16.self).forEach(processCodeUnit)
992990
}
993991
}
994992
}
@@ -1021,14 +1019,16 @@ extension String {
10211019
self = other
10221020
return
10231021
}
1022+
defer { _fixLifetime(other) }
1023+
if _slowPath(other._guts._isOpaque) {
1024+
self._guts.append(other._guts._asOpaque())
1025+
return
1026+
}
10241027
if other._guts.isASCII {
10251028
self._guts.append(other._guts._unmanagedASCIIView)
1026-
} else if _slowPath(other._guts._isOpaque) {
1027-
self._guts.append(other._guts._asOpaque())
1028-
} else {
1029-
self._guts.append(other._guts._unmanagedUTF16View)
1029+
return
10301030
}
1031-
_fixLifetime(other)
1031+
self._guts.append(other._guts._unmanagedUTF16View)
10321032
}
10331033

10341034
/// Appends the given Unicode scalar to the string.
@@ -1205,54 +1205,58 @@ internal func _stdlib_NSStringUppercaseString(_ str: AnyObject) -> _CocoaString
12051205
@_inlineable // FIXME(sil-serialize-all)
12061206
@_versioned // FIXME(sil-serialize-all)
12071207
internal func _nativeUnicodeLowercaseString(_ str: String) -> String {
1208-
defer { _fixLifetime(str) }
1209-
let utf16 = str._guts._unmanagedUTF16View
1208+
let guts = str._guts._extractContiguousUTF16()
1209+
defer { _fixLifetime(guts) }
1210+
let utf16 = guts._unmanagedUTF16View
12101211
var storage = _SwiftStringStorage<UTF16.CodeUnit>.create(
12111212
capacity: utf16.count,
12121213
count: utf16.count)
12131214

12141215
// Try to write it out to the same length.
12151216
let z = _swift_stdlib_unicode_strToLower(
1216-
dest, Int32(utf16.count), // FIXME: handle overflow case
1217+
storage.start, Int32(storage.capacity), // FIXME: handle overflow case
12171218
utf16.start, Int32(utf16.count))
12181219
let correctSize = Int(z)
12191220

12201221
// If more space is needed, do it again with the correct buffer size.
1221-
if correctSize != utf16.count {
1222+
if correctSize > storage.capacity {
12221223
storage = _SwiftStringStorage<UTF16.CodeUnit>.create(
12231224
capacity: correctSize,
12241225
count: correctSize)
12251226
_swift_stdlib_unicode_strToLower(
1226-
dest, Int32(utf16.count), // FIXME: handle overflow case
1227+
storage.start, Int32(storage.capacity), // FIXME: handle overflow case
12271228
utf16.start, Int32(utf16.count))
12281229
}
1230+
storage.count = correctSize
12291231
return String(_storage: storage)
12301232
}
12311233

12321234
@_inlineable // FIXME(sil-serialize-all)
12331235
@_versioned // FIXME(sil-serialize-all)
12341236
internal func _nativeUnicodeUppercaseString(_ str: String) -> String {
1235-
defer { _fixLifetime(str) }
1236-
let utf16 = str._guts._unmanagedUTF16View
1237+
let guts = str._guts._extractContiguousUTF16()
1238+
defer { _fixLifetime(guts) }
1239+
let utf16 = guts._unmanagedUTF16View
12371240
var storage = _SwiftStringStorage<UTF16.CodeUnit>.create(
12381241
capacity: utf16.count,
12391242
count: utf16.count)
12401243

12411244
// Try to write it out to the same length.
12421245
let z = _swift_stdlib_unicode_strToUpper(
1243-
dest, Int32(utf16.count), // FIXME: handle overflow case
1246+
storage.start, Int32(storage.capacity), // FIXME: handle overflow case
12441247
utf16.start, Int32(utf16.count))
12451248
let correctSize = Int(z)
12461249

12471250
// If more space is needed, do it again with the correct buffer size.
1248-
if correctSize != utf16.count {
1251+
if correctSize > storage.capacity {
12491252
storage = _SwiftStringStorage<UTF16.CodeUnit>.create(
12501253
capacity: correctSize,
12511254
count: correctSize)
12521255
_swift_stdlib_unicode_strToUpper(
1253-
dest, Int32(utf16.count), // FIXME: handle overflow case
1256+
storage.start, Int32(storage.capacity), // FIXME: handle overflow case
12541257
utf16.start, Int32(utf16.count))
12551258
}
1259+
storage.count = correctSize
12561260
return String(_storage: storage)
12571261
}
12581262
#endif
@@ -1316,9 +1320,9 @@ extension String {
13161320
_asciiUpperCaseTable &>>
13171321
UInt64(((value &- 1) & 0b0111_1111) &>> 1)
13181322
let add = (isUpper & 0x1) &<< 5
1319-
// Since we are left with either 0x0 or 0x20, we can safely truncate to
1320-
// a UInt8 and add to our ASCII value (this will not overflow numbers in
1321-
// the ASCII range).
1323+
// Since we are left with either 0x0 or 0x20, we can safely truncate
1324+
// to a UInt8 and add to our ASCII value (this will not overflow
1325+
// numbers in the ASCII range).
13221326
storage._value.start[i] = value &+ UInt8(truncatingIfNeeded: add)
13231327
}
13241328
}

stdlib/public/core/StringBridge.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public protocol _NSStringCore : _NSCopying /* _NSFastEnumeration */ {
205205
// NSString subclass.
206206

207207
@objc(length)
208-
func length() -> UInt
208+
var length: Int { get }
209209

210210
@objc(characterAtIndex:)
211211
func character(at index: Int) -> UInt16
@@ -269,8 +269,8 @@ public final class _NSContiguousString : _SwiftNativeNSString, _NSStringCore {
269269

270270
@_inlineable
271271
@objc(length)
272-
public func length() -> UInt {
273-
return UInt(bitPattern: _guts.count)
272+
public var length: Int {
273+
return _guts.count
274274
}
275275

276276
@_inlineable
@@ -366,4 +366,18 @@ extension String {
366366
return _stdlib_binary_bridgeToObjectiveCImpl()
367367
}
368368
}
369+
370+
#else // !_runtime(_ObjC)
371+
372+
@_fixed_layout // FIXME(sil-serialize-all)
373+
public class _SwiftNativeNSString {
374+
@_inlineable // FIXME(sil-serialize-all)
375+
@_versioned // FIXME(sil-serialize-all)
376+
internal init() {}
377+
@_inlineable // FIXME(sil-serialize-all)
378+
deinit {}
379+
}
380+
381+
public protocol _NSStringCore: class {}
382+
369383
#endif

stdlib/public/core/StringComparable.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ extension _StringGuts {
126126
return Int(_stdlib_compareNSStringDeterministicUnicodeCollation(l, r))
127127
}
128128
#else
129-
switch (_guts.isASCII, rhs._guts.isASCII) {
129+
switch (left.isASCII, right.isASCII) {
130130
case (true, false):
131131
let l = left._unmanagedASCIIView[leftRange]
132132
let r = right._unmanagedUTF16View[rightRange]
@@ -135,7 +135,8 @@ extension _StringGuts {
135135
r.start, Int32(r.count)))
136136
case (false, true):
137137
// Just invert it and recurse for this case.
138-
return -rhs._compareDeterministicUnicodeCollation(self)
138+
return -_compareDeterministicUnicodeCollation(
139+
right, rightRange, to: left, leftRange)
139140
case (false, false):
140141
let l = left._unmanagedUTF16View[leftRange]
141142
let r = right._unmanagedUTF16View[rightRange]

0 commit comments

Comments
 (0)