@@ -271,11 +271,13 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
271
271
272
272
/// The number of bytes contained by the data object.
273
273
open var length : Int {
274
+ requireFunnelOverridden ( )
274
275
return CFDataGetLength ( _cfObject)
275
276
}
276
277
277
278
/// A pointer to the data object's contents.
278
279
open var bytes : UnsafeRawPointer {
280
+ requireFunnelOverridden ( )
279
281
guard let bytePtr = CFDataGetBytePtr ( _cfObject) else {
280
282
//This could occure on empty data being encoded.
281
283
//TODO: switch with nil when signature is fixed
@@ -517,14 +519,29 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
517
519
// MARK: - Bytes
518
520
/// Copies a number of bytes from the start of the data object into a given buffer.
519
521
open func getBytes( _ buffer: UnsafeMutableRawPointer , length: Int ) {
520
- let bytePtr = buffer. bindMemory ( to: UInt8 . self, capacity: length)
521
- CFDataGetBytes ( _cfObject, CFRangeMake ( 0 , length) , bytePtr)
522
+ if funnelsAreAbstract {
523
+ let actualCount = Swift . min ( length, self . length)
524
+ let sourceBuffer = UnsafeRawBufferPointer ( start: bytes, count: actualCount)
525
+ let destinationBuffer = UnsafeMutableRawBufferPointer ( start: buffer, count: actualCount)
526
+ sourceBuffer. copyBytes ( to: destinationBuffer)
527
+ } else {
528
+ let bytePtr = buffer. bindMemory ( to: UInt8 . self, capacity: length)
529
+ CFDataGetBytes ( _cfObject, CFRangeMake ( 0 , length) , bytePtr)
530
+ }
522
531
}
523
532
524
533
/// Copies a range of bytes from the data object into a given buffer.
525
534
open func getBytes( _ buffer: UnsafeMutableRawPointer , range: NSRange ) {
526
- let bytePtr = buffer. bindMemory ( to: UInt8 . self, capacity: range. length)
527
- CFDataGetBytes ( _cfObject, CFRangeMake ( range. location, range. length) , bytePtr)
535
+ if funnelsAreAbstract {
536
+ precondition ( range. location >= 0 && range. length >= 0 )
537
+ let actualCount = Swift . min ( range. length, self . length - range. location)
538
+ let sourceBuffer = UnsafeRawBufferPointer ( start: bytes. advanced ( by: range. location) , count: actualCount)
539
+ let destinationBuffer = UnsafeMutableRawBufferPointer ( start: buffer, count: actualCount)
540
+ sourceBuffer. copyBytes ( to: destinationBuffer)
541
+ } else {
542
+ let bytePtr = buffer. bindMemory ( to: UInt8 . self, capacity: range. length)
543
+ CFDataGetBytes ( _cfObject, CFRangeMake ( range. location, range. length) , bytePtr)
544
+ }
528
545
}
529
546
530
547
/// Returns a new data object containing the data object's bytes that fall within the limits specified by a given range.
@@ -927,15 +944,18 @@ open class NSMutableData : NSData {
927
944
// MARK: - Funnel Methods
928
945
/// A pointer to the data contained by the mutable data object.
929
946
open var mutableBytes : UnsafeMutableRawPointer {
947
+ requireFunnelOverridden ( )
930
948
return UnsafeMutableRawPointer ( CFDataGetMutableBytePtr ( _cfMutableObject) )
931
949
}
932
950
933
951
/// The number of bytes contained in the mutable data object.
934
952
open override var length : Int {
935
953
get {
954
+ requireFunnelOverridden ( )
936
955
return CFDataGetLength ( _cfObject)
937
956
}
938
957
set {
958
+ requireFunnelOverridden ( )
939
959
CFDataSetLength ( _cfMutableObject, newValue)
940
960
}
941
961
}
@@ -948,8 +968,15 @@ open class NSMutableData : NSData {
948
968
// MARK: - Mutability
949
969
/// Appends to the data object a given number of bytes from a given buffer.
950
970
open func append( _ bytes: UnsafeRawPointer , length: Int ) {
951
- let bytePtr = bytes. bindMemory ( to: UInt8 . self, capacity: length)
952
- CFDataAppendBytes ( _cfMutableObject, bytePtr, length)
971
+ guard length > 0 else { return }
972
+
973
+ if funnelsAreAbstract {
974
+ self . length += length
975
+ UnsafeRawBufferPointer ( start: bytes, count: length) . copyBytes ( to: UnsafeMutableRawBufferPointer ( start: mutableBytes, count: length) )
976
+ } else {
977
+ let bytePtr = bytes. bindMemory ( to: UInt8 . self, capacity: length)
978
+ CFDataAppendBytes ( _cfMutableObject, bytePtr, length)
979
+ }
953
980
}
954
981
955
982
/// Appends the content of another data object to the data object.
@@ -962,13 +989,21 @@ open class NSMutableData : NSData {
962
989
963
990
/// Increases the length of the data object by a given number of bytes.
964
991
open func increaseLength( by extraLength: Int ) {
965
- CFDataSetLength ( _cfMutableObject, CFDataGetLength ( _cfObject) + extraLength)
992
+ if funnelsAreAbstract {
993
+ self . length += extraLength
994
+ } else {
995
+ CFDataSetLength ( _cfMutableObject, CFDataGetLength ( _cfObject) + extraLength)
996
+ }
966
997
}
967
998
968
999
/// Replaces with a given set of bytes a given range within the contents of the data object.
969
1000
open func replaceBytes( in range: NSRange , withBytes bytes: UnsafeRawPointer ) {
970
- let bytePtr = bytes. bindMemory ( to: UInt8 . self, capacity: length)
971
- CFDataReplaceBytes ( _cfMutableObject, CFRangeMake ( range. location, range. length) , bytePtr, length)
1001
+ if funnelsAreAbstract {
1002
+ replaceBytes ( in: range, withBytes: bytes, length: range. length)
1003
+ } else {
1004
+ let bytePtr = bytes. bindMemory ( to: UInt8 . self, capacity: length)
1005
+ CFDataReplaceBytes ( _cfMutableObject, CFRangeMake ( range. location, range. length) , bytePtr, length)
1006
+ }
972
1007
}
973
1008
974
1009
/// Replaces with zeroes the contents of the data object in a given range.
@@ -986,8 +1021,22 @@ open class NSMutableData : NSData {
986
1021
987
1022
/// Replaces with a given set of bytes a given range within the contents of the data object.
988
1023
open func replaceBytes( in range: NSRange , withBytes replacementBytes: UnsafeRawPointer ? , length replacementLength: Int ) {
989
- let bytePtr = replacementBytes? . bindMemory ( to: UInt8 . self, capacity: replacementLength)
990
- CFDataReplaceBytes ( _cfMutableObject, CFRangeMake ( range. location, range. length) , bytePtr, replacementLength)
1024
+ precondition ( range. location + range. length <= self . length)
1025
+ if funnelsAreAbstract {
1026
+ let delta = replacementLength - range. length
1027
+ if delta != 0 {
1028
+ let originalLength = self . length
1029
+ self . length += delta
1030
+
1031
+ if delta > 0 {
1032
+ UnsafeRawBufferPointer ( start: mutableBytes. advanced ( by: range. location) , count: originalLength) . copyBytes ( to: UnsafeMutableRawBufferPointer ( start: mutableBytes. advanced ( by: range. location + range. length) , count: originalLength) )
1033
+ }
1034
+ }
1035
+ UnsafeRawBufferPointer ( start: replacementBytes, count: replacementLength) . copyBytes ( to: UnsafeMutableRawBufferPointer ( start: mutableBytes. advanced ( by: range. location) , count: replacementLength) )
1036
+ } else {
1037
+ let bytePtr = replacementBytes? . bindMemory ( to: UInt8 . self, capacity: replacementLength)
1038
+ CFDataReplaceBytes ( _cfMutableObject, CFRangeMake ( range. location, range. length) , bytePtr, replacementLength)
1039
+ }
991
1040
}
992
1041
}
993
1042
@@ -1046,3 +1095,15 @@ internal func _CFSwiftDataAppendBytes(_ data: CFTypeRef, _ buffer: UnsafeRawPoin
1046
1095
internal func _CFSwiftDataReplaceBytes( _ data: CFTypeRef , _ range: CFRange , _ buffer: UnsafeRawPointer ? , _ count: CFIndex ) {
1047
1096
( data as! NSMutableData ) . replaceBytes ( in: NSMakeRange ( range. location, range. length) , withBytes: buffer, length: count)
1048
1097
}
1098
+
1099
+ extension NSData {
1100
+ var funnelsAreAbstract : Bool {
1101
+ return type ( of: self ) != NSData . self && type ( of: self ) != NSMutableData . self
1102
+ }
1103
+
1104
+ func requireFunnelOverridden( ) {
1105
+ if funnelsAreAbstract {
1106
+ NSRequiresConcreteImplementation ( )
1107
+ }
1108
+ }
1109
+ }
0 commit comments