mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge the swift-corelibs-foundation version of Data in as a single source and correct initializers for copy variants as well as remove defers of _fixLifetime
This commit is contained in:
@@ -10,6 +10,26 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if DEPLOYMENT_RUNTIME_SWIFT
|
||||
|
||||
#if os(OSX) || os(iOS)
|
||||
import Darwin
|
||||
#elseif os(Linux)
|
||||
import Glibc
|
||||
#endif
|
||||
|
||||
import CoreFoundation
|
||||
|
||||
internal func __NSDataInvokeDeallocatorUnmap(_ mem: UnsafeMutableRawPointer, _ length: Int) -> Void {
|
||||
munmap(mem, length)
|
||||
}
|
||||
|
||||
internal func __NSDataInvokeDeallocatorFree(_ mem: UnsafeMutableRawPointer, _ length: Int) -> Void {
|
||||
free(mem)
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@_exported import Foundation // Clang module
|
||||
|
||||
@_silgen_name("__NSDataInvokeDeallocatorVM")
|
||||
@@ -24,6 +44,8 @@ internal func __NSDataInvokeDeallocatorFree(_ mem: UnsafeMutableRawPointer, _ le
|
||||
@_silgen_name("_NSWriteDataToFile_Swift")
|
||||
internal func _NSWriteDataToFile_Swift(url: NSURL, data: NSData, options: UInt, error: NSErrorPointer) -> Bool
|
||||
|
||||
#endif
|
||||
|
||||
public final class _DataStorage {
|
||||
public enum Backing {
|
||||
// A mirror of the objective-c implementation that is suitable to inline in swift
|
||||
@@ -583,6 +605,31 @@ public final class _DataStorage {
|
||||
_needToZero = true
|
||||
}
|
||||
|
||||
public init(bytes: UnsafeRawPointer?, length: Int) {
|
||||
precondition(length < _DataStorage.maxSize)
|
||||
if length == 0 {
|
||||
_capacity = 0
|
||||
_length = 0
|
||||
_needToZero = false
|
||||
_bytes = nil
|
||||
} else if _DataStorage.vmOpsThreshold <= length {
|
||||
_capacity = length
|
||||
_length = length
|
||||
_needToZero = true
|
||||
_bytes = _DataStorage.allocate(length, false)!
|
||||
_DataStorage.move(_bytes!, bytes, length)
|
||||
} else {
|
||||
var capacity = length
|
||||
if (_DataStorage.vmOpsThreshold <= capacity) {
|
||||
capacity = NSRoundUpToMultipleOfPageSize(capacity)
|
||||
}
|
||||
_length = length
|
||||
_bytes = _DataStorage.allocate(capacity, false)!
|
||||
_capacity = capacity
|
||||
_needToZero = true
|
||||
_DataStorage.move(_bytes!, bytes, length)
|
||||
}
|
||||
}
|
||||
|
||||
public init(bytes: UnsafeMutableRawPointer?, length: Int, copy: Bool, deallocator: ((UnsafeMutableRawPointer, Int) -> Void)?) {
|
||||
precondition(length < _DataStorage.maxSize)
|
||||
@@ -687,7 +734,8 @@ public final class _DataStorage {
|
||||
public func withInteriorPointerReference<T>(_ work: (NSData) throws -> T) rethrows -> T {
|
||||
switch _backing {
|
||||
case .swift:
|
||||
return try work(NSData(bytesNoCopy: _bytes!, length: _length, freeWhenDone: false))
|
||||
let d = _bytes == nil ? NSData() : NSData(bytesNoCopy: _bytes!, length: _length, freeWhenDone: false)
|
||||
return try work(d)
|
||||
case .immutable(let d):
|
||||
return try work(d)
|
||||
case .mutable(let d):
|
||||
@@ -829,15 +877,23 @@ internal class _NSSwiftData : NSData {
|
||||
return NSData(bytes: _backing.bytes, length: _backing.length)
|
||||
}
|
||||
|
||||
#if !DEPLOYMENT_RUNTIME_SWIFT
|
||||
@objc
|
||||
func _isCompact() -> Bool {
|
||||
return true
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEPLOYMENT_RUNTIME_SWIFT
|
||||
override func _providesConcreteBacking() -> Bool {
|
||||
return true
|
||||
}
|
||||
#else
|
||||
@objc(_providesConcreteBacking)
|
||||
func _providesConcreteBacking() -> Bool {
|
||||
return true
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
|
||||
@@ -859,7 +915,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// When creating a `Data` with the no-copy initializer, you may specify a `Data.Deallocator` to customize the behavior of how the backing store is deallocated.
|
||||
public enum Deallocator {
|
||||
/// Use a virtual memory deallocator.
|
||||
#if !DEPLOYMENT_RUNTIME_SWIFT
|
||||
case virtualMemory
|
||||
#endif
|
||||
|
||||
/// Use `munmap`.
|
||||
case unmap
|
||||
@@ -874,6 +932,20 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
case custom((UnsafeMutableRawPointer, Int) -> Void)
|
||||
|
||||
fileprivate var _deallocator : ((UnsafeMutableRawPointer, Int) -> Void)? {
|
||||
#if DEPLOYMENT_RUNTIME_SWIFT
|
||||
switch self {
|
||||
case .unmap:
|
||||
return { __NSDataInvokeDeallocatorUnmap($0, $1) }
|
||||
case .free:
|
||||
return { __NSDataInvokeDeallocatorFree($0, $1) }
|
||||
case .none:
|
||||
return nil
|
||||
case .custom(let b):
|
||||
return { (ptr, len) in
|
||||
b(ptr, len)
|
||||
}
|
||||
}
|
||||
#else
|
||||
switch self {
|
||||
case .virtualMemory:
|
||||
return { __NSDataInvokeDeallocatorVM($0, $1) }
|
||||
@@ -888,6 +960,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
b(ptr, len)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -899,21 +972,21 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - parameter bytes: A pointer to the memory. It will be copied.
|
||||
/// - parameter count: The number of bytes to copy.
|
||||
public init(bytes: UnsafeRawPointer, count: Int) {
|
||||
_backing = _DataStorage(bytes: UnsafeMutableRawPointer(mutating: bytes), length: count, copy: true, deallocator: nil)
|
||||
_backing = _DataStorage(bytes: bytes, length: count)
|
||||
}
|
||||
|
||||
/// Initialize a `Data` with copied memory content.
|
||||
///
|
||||
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
|
||||
public init<SourceType>(buffer: UnsafeBufferPointer<SourceType>) {
|
||||
_backing = _DataStorage(bytes: UnsafeMutableRawPointer(mutating: buffer.baseAddress), length: MemoryLayout<SourceType>.stride * buffer.count, copy: true, deallocator: nil)
|
||||
_backing = _DataStorage(bytes: buffer.baseAddress, length: MemoryLayout<SourceType>.stride * buffer.count)
|
||||
}
|
||||
|
||||
/// Initialize a `Data` with copied memory content.
|
||||
///
|
||||
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
|
||||
public init<SourceType>(buffer: UnsafeMutableBufferPointer<SourceType>) {
|
||||
_backing = _DataStorage(bytes: buffer.baseAddress, length: MemoryLayout<SourceType>.stride * buffer.count, copy: true, deallocator: nil)
|
||||
_backing = _DataStorage(bytes: buffer.baseAddress, length: MemoryLayout<SourceType>.stride * buffer.count)
|
||||
}
|
||||
|
||||
/// Initialize a `Data` with the contents of an Array.
|
||||
@@ -921,7 +994,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - parameter bytes: An array of bytes to copy.
|
||||
public init(bytes: Array<UInt8>) {
|
||||
_backing = bytes.withUnsafeBufferPointer {
|
||||
return _DataStorage(bytes: UnsafeMutableRawPointer(mutating: $0.baseAddress), length: $0.count, copy: true, deallocator: nil)
|
||||
return _DataStorage(bytes: $0.baseAddress, length: $0.count)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,7 +1003,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - parameter bytes: An array of bytes to copy.
|
||||
public init(bytes: ArraySlice<UInt8>) {
|
||||
_backing = bytes.withUnsafeBufferPointer {
|
||||
return _DataStorage(bytes: UnsafeMutableRawPointer(mutating: $0.baseAddress), length: $0.count, copy: true, deallocator: nil)
|
||||
return _DataStorage(bytes: $0.baseAddress, length: $0.count)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -968,7 +1041,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - parameter deallocator: Specifies the mechanism to free the indicated buffer, or `.none`.
|
||||
public init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Deallocator) {
|
||||
let whichDeallocator = deallocator._deallocator
|
||||
_backing = _DataStorage(immutableReference: NSData(bytesNoCopy: bytes, length: count, deallocator: whichDeallocator))
|
||||
_backing = _DataStorage(bytes: bytes, length: count, copy: false, deallocator: whichDeallocator)
|
||||
}
|
||||
|
||||
/// Initialize a `Data` with the contents of a `URL`.
|
||||
@@ -1015,12 +1088,17 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
///
|
||||
/// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
|
||||
public init(referencing reference: NSData) {
|
||||
#if DEPLOYMENT_RUNTIME_SWIFT
|
||||
let providesConcreteBacking = reference._providesConcreteBacking()
|
||||
#else
|
||||
let providesConcreteBacking = (reference as AnyObject)._providesConcreteBacking?() ?? false
|
||||
#endif
|
||||
if providesConcreteBacking {
|
||||
_backing = _DataStorage(immutableReference: reference.copy() as! NSData)
|
||||
} else {
|
||||
_backing = _DataStorage(customReference: reference.copy() as! NSData)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------
|
||||
@@ -1047,8 +1125,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
|
||||
@inline(__always)
|
||||
public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
|
||||
let bytes = _backing.bytes!
|
||||
defer { _fixLifetime(self)}
|
||||
let bytes = _backing.bytes ?? UnsafeRawPointer(bitPattern: 0xBAD0)!
|
||||
let contentPtr = bytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
|
||||
return try body(contentPtr)
|
||||
}
|
||||
@@ -1063,8 +1140,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
if !isKnownUniquelyReferenced(&_backing) {
|
||||
_backing = _backing.mutableCopy()
|
||||
}
|
||||
let mutableBytes = _backing.mutableBytes!
|
||||
defer { _fixLifetime(self)}
|
||||
let mutableBytes = _backing.mutableBytes ?? UnsafeMutableRawPointer(bitPattern: 0xBAD0)!
|
||||
let contentPtr = mutableBytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
|
||||
return try body(UnsafeMutablePointer(contentPtr))
|
||||
}
|
||||
@@ -1079,11 +1155,13 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
|
||||
@inline(__always)
|
||||
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
|
||||
if count == 0 { return }
|
||||
memcpy(UnsafeMutableRawPointer(pointer), _backing.bytes!, count)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
private func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: NSRange) {
|
||||
if range.length == 0 { return }
|
||||
memcpy(UnsafeMutableRawPointer(pointer), _backing.bytes!.advanced(by: range.location), range.length)
|
||||
}
|
||||
|
||||
@@ -1129,7 +1207,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
#if !DEPLOYMENT_RUNTIME_SWIFT
|
||||
@inline(__always)
|
||||
private func _shouldUseNonAtomicWriteReimplementation(options: Data.WritingOptions = []) -> Bool {
|
||||
|
||||
@@ -1144,6 +1222,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
return false
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Write the contents of the `Data` to a location.
|
||||
///
|
||||
@@ -1152,6 +1231,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
/// - throws: An error in the Cocoa domain, if there is an error writing to the `URL`.
|
||||
public func write(to url: URL, options: Data.WritingOptions = []) throws {
|
||||
try _backing.withInteriorPointerReference {
|
||||
#if DEPLOYMENT_RUNTIME_SWIFT
|
||||
try $0.write(to: url, options: WritingOptions(rawValue: options.rawValue))
|
||||
#else
|
||||
if _shouldUseNonAtomicWriteReimplementation(options: options) {
|
||||
var error : NSError?
|
||||
if !_NSWriteDataToFile_Swift(url: url._bridgeToObjectiveC(), data: $0, options: options.rawValue, error: &error) {
|
||||
@@ -1160,6 +1242,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
|
||||
} else {
|
||||
try $0.write(to: url, options: WritingOptions(rawValue: options.rawValue))
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1599,7 +1682,14 @@ extension Data {
|
||||
}
|
||||
|
||||
/// Provides bridging functionality for struct Data to class NSData and vice-versa.
|
||||
extension Data : _ObjectiveCBridgeable {
|
||||
|
||||
#if DEPLOYMENT_RUNTIME_SWIFT
|
||||
internal typealias DataBridgeType = _ObjectTypeBridgeable
|
||||
#else
|
||||
internal typealias DataBridgeType = _ObjectiveCBridgeable
|
||||
#endif
|
||||
|
||||
extension Data : DataBridgeType {
|
||||
@_semantics("convertToObjectiveC")
|
||||
public func _bridgeToObjectiveC() -> NSData {
|
||||
return _backing.bridgedReference()
|
||||
|
||||
Reference in New Issue
Block a user