Skip to content

Commit 6134083

Browse files
committed
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
1 parent df756f8 commit 6134083

File tree

1 file changed

+103
-13
lines changed

1 file changed

+103
-13
lines changed

stdlib/public/SDK/Foundation/Data.swift

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#if DEPLOYMENT_RUNTIME_SWIFT
14+
15+
#if os(OSX) || os(iOS)
16+
import Darwin
17+
#elseif os(Linux)
18+
import Glibc
19+
#endif
20+
21+
import CoreFoundation
22+
23+
internal func __NSDataInvokeDeallocatorUnmap(_ mem: UnsafeMutableRawPointer, _ length: Int) -> Void {
24+
munmap(mem, length)
25+
}
26+
27+
internal func __NSDataInvokeDeallocatorFree(_ mem: UnsafeMutableRawPointer, _ length: Int) -> Void {
28+
free(mem)
29+
}
30+
31+
#else
32+
1333
@_exported import Foundation // Clang module
1434

1535
@_silgen_name("__NSDataInvokeDeallocatorVM")
@@ -24,6 +44,8 @@ internal func __NSDataInvokeDeallocatorFree(_ mem: UnsafeMutableRawPointer, _ le
2444
@_silgen_name("_NSWriteDataToFile_Swift")
2545
internal func _NSWriteDataToFile_Swift(url: NSURL, data: NSData, options: UInt, error: NSErrorPointer) -> Bool
2646

47+
#endif
48+
2749
public final class _DataStorage {
2850
public enum Backing {
2951
// A mirror of the objective-c implementation that is suitable to inline in swift
@@ -583,6 +605,31 @@ public final class _DataStorage {
583605
_needToZero = true
584606
}
585607

608+
public init(bytes: UnsafeRawPointer?, length: Int) {
609+
precondition(length < _DataStorage.maxSize)
610+
if length == 0 {
611+
_capacity = 0
612+
_length = 0
613+
_needToZero = false
614+
_bytes = nil
615+
} else if _DataStorage.vmOpsThreshold <= length {
616+
_capacity = length
617+
_length = length
618+
_needToZero = true
619+
_bytes = _DataStorage.allocate(length, false)!
620+
_DataStorage.move(_bytes!, bytes, length)
621+
} else {
622+
var capacity = length
623+
if (_DataStorage.vmOpsThreshold <= capacity) {
624+
capacity = NSRoundUpToMultipleOfPageSize(capacity)
625+
}
626+
_length = length
627+
_bytes = _DataStorage.allocate(capacity, false)!
628+
_capacity = capacity
629+
_needToZero = true
630+
_DataStorage.move(_bytes!, bytes, length)
631+
}
632+
}
586633

587634
public init(bytes: UnsafeMutableRawPointer?, length: Int, copy: Bool, deallocator: ((UnsafeMutableRawPointer, Int) -> Void)?) {
588635
precondition(length < _DataStorage.maxSize)
@@ -687,7 +734,8 @@ public final class _DataStorage {
687734
public func withInteriorPointerReference<T>(_ work: (NSData) throws -> T) rethrows -> T {
688735
switch _backing {
689736
case .swift:
690-
return try work(NSData(bytesNoCopy: _bytes!, length: _length, freeWhenDone: false))
737+
let d = _bytes == nil ? NSData() : NSData(bytesNoCopy: _bytes!, length: _length, freeWhenDone: false)
738+
return try work(d)
691739
case .immutable(let d):
692740
return try work(d)
693741
case .mutable(let d):
@@ -829,15 +877,23 @@ internal class _NSSwiftData : NSData {
829877
return NSData(bytes: _backing.bytes, length: _backing.length)
830878
}
831879

880+
#if !DEPLOYMENT_RUNTIME_SWIFT
832881
@objc
833882
func _isCompact() -> Bool {
834883
return true
835884
}
885+
#endif
836886

887+
#if DEPLOYMENT_RUNTIME_SWIFT
888+
override func _providesConcreteBacking() -> Bool {
889+
return true
890+
}
891+
#else
837892
@objc(_providesConcreteBacking)
838893
func _providesConcreteBacking() -> Bool {
839894
return true
840895
}
896+
#endif
841897
}
842898

843899
public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection {
@@ -859,7 +915,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
859915
/// 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.
860916
public enum Deallocator {
861917
/// Use a virtual memory deallocator.
918+
#if !DEPLOYMENT_RUNTIME_SWIFT
862919
case virtualMemory
920+
#endif
863921

864922
/// Use `munmap`.
865923
case unmap
@@ -874,6 +932,20 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
874932
case custom((UnsafeMutableRawPointer, Int) -> Void)
875933

876934
fileprivate var _deallocator : ((UnsafeMutableRawPointer, Int) -> Void)? {
935+
#if DEPLOYMENT_RUNTIME_SWIFT
936+
switch self {
937+
case .unmap:
938+
return { __NSDataInvokeDeallocatorUnmap($0, $1) }
939+
case .free:
940+
return { __NSDataInvokeDeallocatorFree($0, $1) }
941+
case .none:
942+
return nil
943+
case .custom(let b):
944+
return { (ptr, len) in
945+
b(ptr, len)
946+
}
947+
}
948+
#else
877949
switch self {
878950
case .virtualMemory:
879951
return { __NSDataInvokeDeallocatorVM($0, $1) }
@@ -888,6 +960,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
888960
b(ptr, len)
889961
}
890962
}
963+
#endif
891964
}
892965
}
893966

@@ -899,29 +972,29 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
899972
/// - parameter bytes: A pointer to the memory. It will be copied.
900973
/// - parameter count: The number of bytes to copy.
901974
public init(bytes: UnsafeRawPointer, count: Int) {
902-
_backing = _DataStorage(bytes: UnsafeMutableRawPointer(mutating: bytes), length: count, copy: true, deallocator: nil)
975+
_backing = _DataStorage(bytes: bytes, length: count)
903976
}
904977

905978
/// Initialize a `Data` with copied memory content.
906979
///
907980
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
908981
public init<SourceType>(buffer: UnsafeBufferPointer<SourceType>) {
909-
_backing = _DataStorage(bytes: UnsafeMutableRawPointer(mutating: buffer.baseAddress), length: MemoryLayout<SourceType>.stride * buffer.count, copy: true, deallocator: nil)
982+
_backing = _DataStorage(bytes: buffer.baseAddress, length: MemoryLayout<SourceType>.stride * buffer.count)
910983
}
911984

912985
/// Initialize a `Data` with copied memory content.
913986
///
914987
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
915988
public init<SourceType>(buffer: UnsafeMutableBufferPointer<SourceType>) {
916-
_backing = _DataStorage(bytes: buffer.baseAddress, length: MemoryLayout<SourceType>.stride * buffer.count, copy: true, deallocator: nil)
989+
_backing = _DataStorage(bytes: buffer.baseAddress, length: MemoryLayout<SourceType>.stride * buffer.count)
917990
}
918991

919992
/// Initialize a `Data` with the contents of an Array.
920993
///
921994
/// - parameter bytes: An array of bytes to copy.
922995
public init(bytes: Array<UInt8>) {
923996
_backing = bytes.withUnsafeBufferPointer {
924-
return _DataStorage(bytes: UnsafeMutableRawPointer(mutating: $0.baseAddress), length: $0.count, copy: true, deallocator: nil)
997+
return _DataStorage(bytes: $0.baseAddress, length: $0.count)
925998
}
926999
}
9271000

@@ -930,7 +1003,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
9301003
/// - parameter bytes: An array of bytes to copy.
9311004
public init(bytes: ArraySlice<UInt8>) {
9321005
_backing = bytes.withUnsafeBufferPointer {
933-
return _DataStorage(bytes: UnsafeMutableRawPointer(mutating: $0.baseAddress), length: $0.count, copy: true, deallocator: nil)
1006+
return _DataStorage(bytes: $0.baseAddress, length: $0.count)
9341007
}
9351008
}
9361009

@@ -968,7 +1041,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
9681041
/// - parameter deallocator: Specifies the mechanism to free the indicated buffer, or `.none`.
9691042
public init(bytesNoCopy bytes: UnsafeMutableRawPointer, count: Int, deallocator: Deallocator) {
9701043
let whichDeallocator = deallocator._deallocator
971-
_backing = _DataStorage(immutableReference: NSData(bytesNoCopy: bytes, length: count, deallocator: whichDeallocator))
1044+
_backing = _DataStorage(bytes: bytes, length: count, copy: false, deallocator: whichDeallocator)
9721045
}
9731046

9741047
/// Initialize a `Data` with the contents of a `URL`.
@@ -1015,12 +1088,17 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
10151088
///
10161089
/// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
10171090
public init(referencing reference: NSData) {
1091+
#if DEPLOYMENT_RUNTIME_SWIFT
1092+
let providesConcreteBacking = reference._providesConcreteBacking()
1093+
#else
10181094
let providesConcreteBacking = (reference as AnyObject)._providesConcreteBacking?() ?? false
1095+
#endif
10191096
if providesConcreteBacking {
10201097
_backing = _DataStorage(immutableReference: reference.copy() as! NSData)
10211098
} else {
10221099
_backing = _DataStorage(customReference: reference.copy() as! NSData)
10231100
}
1101+
10241102
}
10251103

10261104
// -----------------------------------
@@ -1047,8 +1125,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
10471125
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
10481126
@inline(__always)
10491127
public func withUnsafeBytes<ResultType, ContentType>(_ body: (UnsafePointer<ContentType>) throws -> ResultType) rethrows -> ResultType {
1050-
let bytes = _backing.bytes!
1051-
defer { _fixLifetime(self)}
1128+
let bytes = _backing.bytes ?? UnsafeRawPointer(bitPattern: 0xBAD0)!
10521129
let contentPtr = bytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
10531130
return try body(contentPtr)
10541131
}
@@ -1063,8 +1140,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
10631140
if !isKnownUniquelyReferenced(&_backing) {
10641141
_backing = _backing.mutableCopy()
10651142
}
1066-
let mutableBytes = _backing.mutableBytes!
1067-
defer { _fixLifetime(self)}
1143+
let mutableBytes = _backing.mutableBytes ?? UnsafeMutableRawPointer(bitPattern: 0xBAD0)!
10681144
let contentPtr = mutableBytes.bindMemory(to: ContentType.self, capacity: count / MemoryLayout<ContentType>.stride)
10691145
return try body(UnsafeMutablePointer(contentPtr))
10701146
}
@@ -1079,11 +1155,13 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
10791155
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
10801156
@inline(__always)
10811157
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
1158+
if count == 0 { return }
10821159
memcpy(UnsafeMutableRawPointer(pointer), _backing.bytes!, count)
10831160
}
10841161

10851162
@inline(__always)
10861163
private func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: NSRange) {
1164+
if range.length == 0 { return }
10871165
memcpy(UnsafeMutableRawPointer(pointer), _backing.bytes!.advanced(by: range.location), range.length)
10881166
}
10891167

@@ -1129,7 +1207,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11291207
}
11301208

11311209
// MARK: -
1132-
1210+
#if !DEPLOYMENT_RUNTIME_SWIFT
11331211
@inline(__always)
11341212
private func _shouldUseNonAtomicWriteReimplementation(options: Data.WritingOptions = []) -> Bool {
11351213

@@ -1144,6 +1222,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11441222
return false
11451223
}
11461224
}
1225+
#endif
11471226

11481227
/// Write the contents of the `Data` to a location.
11491228
///
@@ -1152,6 +1231,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11521231
/// - throws: An error in the Cocoa domain, if there is an error writing to the `URL`.
11531232
public func write(to url: URL, options: Data.WritingOptions = []) throws {
11541233
try _backing.withInteriorPointerReference {
1234+
#if DEPLOYMENT_RUNTIME_SWIFT
1235+
try $0.write(to: url, options: WritingOptions(rawValue: options.rawValue))
1236+
#else
11551237
if _shouldUseNonAtomicWriteReimplementation(options: options) {
11561238
var error : NSError?
11571239
if !_NSWriteDataToFile_Swift(url: url._bridgeToObjectiveC(), data: $0, options: options.rawValue, error: &error) {
@@ -1160,6 +1242,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11601242
} else {
11611243
try $0.write(to: url, options: WritingOptions(rawValue: options.rawValue))
11621244
}
1245+
#endif
11631246
}
11641247
}
11651248

@@ -1599,7 +1682,14 @@ extension Data {
15991682
}
16001683

16011684
/// Provides bridging functionality for struct Data to class NSData and vice-versa.
1602-
extension Data : _ObjectiveCBridgeable {
1685+
1686+
#if DEPLOYMENT_RUNTIME_SWIFT
1687+
internal typealias DataBridgeType = _ObjectTypeBridgeable
1688+
#else
1689+
internal typealias DataBridgeType = _ObjectiveCBridgeable
1690+
#endif
1691+
1692+
extension Data : DataBridgeType {
16031693
@_semantics("convertToObjectiveC")
16041694
public func _bridgeToObjectiveC() -> NSData {
16051695
return _backing.bridgedReference()

0 commit comments

Comments
 (0)