mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
216 lines
6.5 KiB
Swift
216 lines
6.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if _runtime(_ObjC)
|
|
// Swift's String bridges NSString via this protocol and these
|
|
// variables, allowing the core stdlib to remain decoupled from
|
|
// Foundation.
|
|
|
|
/// Effectively a proxy for NSString that doesn't mention it by
|
|
/// name. NSString's conformance to this protocol is declared in
|
|
/// Foundation.
|
|
@objc public protocol _CocoaStringType {}
|
|
|
|
@asmname("swift_stdlib_CFStringCreateCopy")
|
|
func _stdlib_CFStringCreateCopy(source: _CocoaStringType) -> _CocoaStringType
|
|
|
|
@asmname("swift_stdlib_CFStringGetLength")
|
|
func _stdlib_CFStringGetLength(source: _CocoaStringType)
|
|
-> Int
|
|
|
|
@asmname("swift_stdlib_CFStringGetCharactersPtr")
|
|
func _stdlib_CFStringGetCharactersPtr(source: _CocoaStringType)
|
|
-> UnsafeMutablePointer<UTF16.CodeUnit>
|
|
|
|
/// Bridges a `source` to `Swift.String`, assuming that `source` has non-ASCII
|
|
/// characters (does not apply ASCII optimizations).
|
|
func _cocoaStringToSwiftString_NonASCII(source: _CocoaStringType) -> String {
|
|
let cfImmutableValue = _stdlib_CFStringCreateCopy(source)
|
|
let length = _stdlib_CFStringGetLength(cfImmutableValue)
|
|
let start = _stdlib_CFStringGetCharactersPtr(cfImmutableValue)
|
|
|
|
return String(_StringCore(
|
|
baseAddress: COpaquePointer(start),
|
|
count: length,
|
|
elementShift: 1,
|
|
hasCocoaBuffer: true,
|
|
owner: unsafeBitCast(cfImmutableValue, Optional<AnyObject>.self)))
|
|
}
|
|
|
|
/// Loading Foundation initializes these function variables
|
|
/// with useful values
|
|
|
|
/// Produces a `_StringBuffer` from a given subrange of a source
|
|
/// `_CocoaStringType`, having the given minimum capacity.
|
|
public var _cocoaStringToContiguous: (
|
|
source: _CocoaStringType, range: Range<Int>, minimumCapacity: Int
|
|
) -> _StringBuffer = _cocoaStringToContiguousNotInitialized
|
|
|
|
func _cocoaStringToContiguousNotInitialized(
|
|
source: _CocoaStringType, range: Range<Int>, minimumCapacity: Int
|
|
) -> _StringBuffer {
|
|
_sanityCheckFailure("_cocoaStringToContiguous not initialized")
|
|
}
|
|
|
|
/// Reads the entire contents of a _CocoaStringType into contiguous
|
|
/// storage of sufficient capacity.
|
|
public var _cocoaStringReadAll: (
|
|
source: _CocoaStringType, destination: UnsafeMutablePointer<UTF16.CodeUnit>
|
|
) -> Void = _cocoaStringReadAllNotInitialized
|
|
|
|
func _cocoaStringReadAllNotInitialized(
|
|
source: _CocoaStringType, destination: UnsafeMutablePointer<UTF16.CodeUnit>
|
|
) -> Void {
|
|
_sanityCheckFailure("_cocoaStringReadAll not initialized")
|
|
}
|
|
|
|
public var _cocoaStringLength: (
|
|
source: _CocoaStringType
|
|
) -> Int = _cocoaStringLengthNotInitialized
|
|
|
|
func _cocoaStringLengthNotInitialized(
|
|
source: _CocoaStringType
|
|
) -> Int {
|
|
_sanityCheckFailure("_cocoaStringLength not initialized")
|
|
}
|
|
|
|
public var _cocoaStringSlice: (
|
|
target: _StringCore, subRange: Range<Int>
|
|
) -> _StringCore = _cocoaStringSliceNotInitialized
|
|
|
|
func _cocoaStringSliceNotInitialized(
|
|
target: _StringCore, subRange: Range<Int>
|
|
) -> _StringCore {
|
|
_sanityCheckFailure("_cocoaStringSlice not initialized")
|
|
}
|
|
|
|
public var _cocoaStringSubscript: (
|
|
target: _StringCore, position: Int
|
|
) -> UTF16.CodeUnit = _cocoaStringSubscriptNotInitialized
|
|
|
|
func _cocoaStringSubscriptNotInitialized(
|
|
target: _StringCore, position: Int
|
|
) -> UTF16.CodeUnit {
|
|
_sanityCheckFailure("_cocoaStringSubscript not initialized")
|
|
}
|
|
|
|
import SwiftShims
|
|
|
|
/// This class is derived from `_SwiftNativeNSStringBase` (through runtime magic),
|
|
/// which is derived from `NSString`.
|
|
///
|
|
/// This allows us to subclass an Objective-C class and use the fast Swift
|
|
/// memory allocator.
|
|
@objc
|
|
public class _SwiftNativeNSString {}
|
|
|
|
@objc
|
|
public protocol _NSStringCoreType :
|
|
_NSCopyingType, _NSFastEnumerationType {
|
|
|
|
// The following methods should be overridden when implementing an
|
|
// NSString subclass.
|
|
|
|
func length() -> Int
|
|
|
|
func characterAtIndex(index: Int) -> UInt16
|
|
|
|
// We also override the following methods for efficiency.
|
|
}
|
|
|
|
/// An NSString built around a slice of contiguous Swift String storage
|
|
public final class _NSContiguousString : _SwiftNativeNSString {
|
|
public init(_ _core: _StringCore) {
|
|
_sanityCheck(
|
|
_core.hasContiguousStorage,
|
|
"_NSContiguousString requires contiguous storage")
|
|
self._core = _core
|
|
super.init()
|
|
}
|
|
|
|
init(coder aDecoder: AnyObject) {
|
|
_sanityCheckFailure("init(coder:) not implemented for _NSContiguousString")
|
|
}
|
|
|
|
func length() -> Int {
|
|
return _core.count
|
|
}
|
|
|
|
func characterAtIndex(index: Int) -> UInt16 {
|
|
return _core[index]
|
|
}
|
|
|
|
func getCharacters(
|
|
buffer: UnsafeMutablePointer<UInt16>,
|
|
range aRange: _SwiftNSRange) {
|
|
|
|
_precondition(aRange.location + aRange.length <= Int(_core.count))
|
|
|
|
if _core.elementWidth == 2 {
|
|
UTF16._copy(
|
|
_core.startUTF16 + aRange.location,
|
|
destination: UnsafeMutablePointer<UInt16>(buffer),
|
|
count: aRange.length)
|
|
}
|
|
else {
|
|
UTF16._copy(
|
|
_core.startASCII + aRange.location,
|
|
destination: UnsafeMutablePointer<UInt16>(buffer),
|
|
count: aRange.length)
|
|
}
|
|
}
|
|
|
|
@objc
|
|
func _fastCharacterContents() -> UnsafeMutablePointer<UInt16> {
|
|
return _core.elementWidth == 2
|
|
? UnsafeMutablePointer(_core.startUTF16) : nil
|
|
}
|
|
|
|
//
|
|
// Implement sub-slicing without adding layers of wrapping
|
|
//
|
|
func substringFromIndex(start: Int) -> _NSContiguousString {
|
|
return _NSContiguousString(_core[Int(start)..<Int(_core.count)])
|
|
}
|
|
|
|
func substringToIndex(end: Int) -> _NSContiguousString {
|
|
return _NSContiguousString(_core[0..<Int(end)])
|
|
}
|
|
|
|
func substringWithRange(aRange: _SwiftNSRange) -> _NSContiguousString {
|
|
return _NSContiguousString(
|
|
_core[Int(aRange.location)..<Int(aRange.location + aRange.length)])
|
|
}
|
|
|
|
func copy() -> AnyObject {
|
|
// Since this string is immutable we can just return ourselves.
|
|
return self
|
|
}
|
|
|
|
public let _core: _StringCore
|
|
}
|
|
|
|
extension String {
|
|
/// Same as `_bridgeToObjectiveC()`, but located inside the core standard
|
|
/// library.
|
|
public func _bridgeToObjectiveCImpl() -> AnyObject {
|
|
if let ns = _core.cocoaBuffer {
|
|
if _cocoaStringLength(source: ns) == _core.count {
|
|
return ns
|
|
}
|
|
}
|
|
_sanityCheck(_core.hasContiguousStorage)
|
|
return _NSContiguousString(_core)
|
|
}
|
|
}
|
|
#endif
|