10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
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
+
13
33
@_exported import Foundation // Clang module
14
34
15
35
@_silgen_name ( " __NSDataInvokeDeallocatorVM " )
@@ -24,6 +44,8 @@ internal func __NSDataInvokeDeallocatorFree(_ mem: UnsafeMutableRawPointer, _ le
24
44
@_silgen_name ( " _NSWriteDataToFile_Swift " )
25
45
internal func _NSWriteDataToFile_Swift( url: NSURL , data: NSData , options: UInt , error: NSErrorPointer ) -> Bool
26
46
47
+ #endif
48
+
27
49
public final class _DataStorage {
28
50
public enum Backing {
29
51
// A mirror of the objective-c implementation that is suitable to inline in swift
@@ -583,6 +605,31 @@ public final class _DataStorage {
583
605
_needToZero = true
584
606
}
585
607
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
+ }
586
633
587
634
public init( bytes: UnsafeMutableRawPointer? , length: Int, copy: Bool, deallocator: ( ( UnsafeMutableRawPointer, Int) - > Void) ? ) {
588
635
precondition ( length < _DataStorage. maxSize)
@@ -687,7 +734,8 @@ public final class _DataStorage {
687
734
public func withInteriorPointerReference< T> ( _ work: ( NSData ) throws -> T ) rethrows -> T {
688
735
switch _backing {
689
736
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)
691
739
case . immutable( let d) :
692
740
return try work ( d)
693
741
case . mutable( let d) :
@@ -829,15 +877,23 @@ internal class _NSSwiftData : NSData {
829
877
return NSData ( bytes: _backing. bytes, length: _backing. length)
830
878
}
831
879
880
+ #if !DEPLOYMENT_RUNTIME_SWIFT
832
881
@objc
833
882
func _isCompact( ) -> Bool {
834
883
return true
835
884
}
885
+ #endif
836
886
887
+ #if DEPLOYMENT_RUNTIME_SWIFT
888
+ override func _providesConcreteBacking( ) -> Bool {
889
+ return true
890
+ }
891
+ #else
837
892
@objc ( _providesConcreteBacking)
838
893
func _providesConcreteBacking( ) -> Bool {
839
894
return true
840
895
}
896
+ #endif
841
897
}
842
898
843
899
public struct Data : ReferenceConvertible , Equatable , Hashable , RandomAccessCollection , MutableCollection , RangeReplaceableCollection {
@@ -859,7 +915,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
859
915
/// 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.
860
916
public enum Deallocator {
861
917
/// Use a virtual memory deallocator.
918
+ #if !DEPLOYMENT_RUNTIME_SWIFT
862
919
case virtualMemory
920
+ #endif
863
921
864
922
/// Use `munmap`.
865
923
case unmap
@@ -874,6 +932,20 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
874
932
case custom( ( UnsafeMutableRawPointer , Int ) -> Void )
875
933
876
934
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
877
949
switch self {
878
950
case . virtualMemory:
879
951
return { __NSDataInvokeDeallocatorVM ( $0, $1) }
@@ -888,6 +960,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
888
960
b ( ptr, len)
889
961
}
890
962
}
963
+ #endif
891
964
}
892
965
}
893
966
@@ -899,29 +972,29 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
899
972
/// - parameter bytes: A pointer to the memory. It will be copied.
900
973
/// - parameter count: The number of bytes to copy.
901
974
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)
903
976
}
904
977
905
978
/// Initialize a `Data` with copied memory content.
906
979
///
907
980
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
908
981
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)
910
983
}
911
984
912
985
/// Initialize a `Data` with copied memory content.
913
986
///
914
987
/// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
915
988
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)
917
990
}
918
991
919
992
/// Initialize a `Data` with the contents of an Array.
920
993
///
921
994
/// - parameter bytes: An array of bytes to copy.
922
995
public init ( bytes: Array < UInt8 > ) {
923
996
_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)
925
998
}
926
999
}
927
1000
@@ -930,7 +1003,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
930
1003
/// - parameter bytes: An array of bytes to copy.
931
1004
public init ( bytes: ArraySlice < UInt8 > ) {
932
1005
_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)
934
1007
}
935
1008
}
936
1009
@@ -968,7 +1041,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
968
1041
/// - parameter deallocator: Specifies the mechanism to free the indicated buffer, or `.none`.
969
1042
public init ( bytesNoCopy bytes: UnsafeMutableRawPointer , count: Int , deallocator: Deallocator ) {
970
1043
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)
972
1045
}
973
1046
974
1047
/// Initialize a `Data` with the contents of a `URL`.
@@ -1015,12 +1088,17 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1015
1088
///
1016
1089
/// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
1017
1090
public init ( referencing reference: NSData ) {
1091
+ #if DEPLOYMENT_RUNTIME_SWIFT
1092
+ let providesConcreteBacking = reference. _providesConcreteBacking ( )
1093
+ #else
1018
1094
let providesConcreteBacking = ( reference as AnyObject ) . _providesConcreteBacking ? ( ) ?? false
1095
+ #endif
1019
1096
if providesConcreteBacking {
1020
1097
_backing = _DataStorage ( immutableReference: reference. copy ( ) as! NSData )
1021
1098
} else {
1022
1099
_backing = _DataStorage ( customReference: reference. copy ( ) as! NSData )
1023
1100
}
1101
+
1024
1102
}
1025
1103
1026
1104
// -----------------------------------
@@ -1047,8 +1125,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1047
1125
/// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
1048
1126
@inline ( __always)
1049
1127
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 ) !
1052
1129
let contentPtr = bytes. bindMemory ( to: ContentType . self, capacity: count / MemoryLayout< ContentType> . stride)
1053
1130
return try body ( contentPtr)
1054
1131
}
@@ -1063,8 +1140,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1063
1140
if !isKnownUniquelyReferenced( & _backing) {
1064
1141
_backing = _backing. mutableCopy ( )
1065
1142
}
1066
- let mutableBytes = _backing. mutableBytes!
1067
- defer { _fixLifetime ( self ) }
1143
+ let mutableBytes = _backing. mutableBytes ?? UnsafeMutableRawPointer ( bitPattern: 0xBAD0 ) !
1068
1144
let contentPtr = mutableBytes. bindMemory ( to: ContentType . self, capacity: count / MemoryLayout< ContentType> . stride)
1069
1145
return try body ( UnsafeMutablePointer ( contentPtr) )
1070
1146
}
@@ -1079,11 +1155,13 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1079
1155
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
1080
1156
@inline ( __always)
1081
1157
public func copyBytes( to pointer: UnsafeMutablePointer < UInt8 > , count: Int ) {
1158
+ if count == 0 { return }
1082
1159
memcpy ( UnsafeMutableRawPointer ( pointer) , _backing. bytes!, count)
1083
1160
}
1084
1161
1085
1162
@inline ( __always)
1086
1163
private func _copyBytesHelper( to pointer: UnsafeMutableRawPointer , from range: NSRange ) {
1164
+ if range. length == 0 { return }
1087
1165
memcpy ( UnsafeMutableRawPointer ( pointer) , _backing. bytes!. advanced ( by: range. location) , range. length)
1088
1166
}
1089
1167
@@ -1129,7 +1207,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1129
1207
}
1130
1208
1131
1209
// MARK: -
1132
-
1210
+ #if !DEPLOYMENT_RUNTIME_SWIFT
1133
1211
@inline ( __always)
1134
1212
private func _shouldUseNonAtomicWriteReimplementation( options: Data . WritingOptions = [ ] ) -> Bool {
1135
1213
@@ -1144,6 +1222,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1144
1222
return false
1145
1223
}
1146
1224
}
1225
+ #endif
1147
1226
1148
1227
/// Write the contents of the `Data` to a location.
1149
1228
///
@@ -1152,6 +1231,9 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1152
1231
/// - throws: An error in the Cocoa domain, if there is an error writing to the `URL`.
1153
1232
public func write( to url: URL , options: Data . WritingOptions = [ ] ) throws {
1154
1233
try _backing. withInteriorPointerReference {
1234
+ #if DEPLOYMENT_RUNTIME_SWIFT
1235
+ try $0. write ( to: url, options: WritingOptions ( rawValue: options. rawValue) )
1236
+ #else
1155
1237
if _shouldUseNonAtomicWriteReimplementation ( options: options) {
1156
1238
var error : NSError ?
1157
1239
if !_NSWriteDataToFile_Swift( url: url. _bridgeToObjectiveC ( ) , data: $0, options: options. rawValue, error: & error) {
@@ -1160,6 +1242,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
1160
1242
} else {
1161
1243
try $0. write ( to: url, options: WritingOptions ( rawValue: options. rawValue) )
1162
1244
}
1245
+ #endif
1163
1246
}
1164
1247
}
1165
1248
@@ -1599,7 +1682,14 @@ extension Data {
1599
1682
}
1600
1683
1601
1684
/// 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 {
1603
1693
@_semantics ( " convertToObjectiveC " )
1604
1694
public func _bridgeToObjectiveC( ) -> NSData {
1605
1695
return _backing. bridgedReference ( )
0 commit comments