@@ -73,56 +73,15 @@ internal final class _SwiftNSData : NSData, _SwiftNativeFoundationType {
7373 releaseWrappedObject ( )
7474 }
7575
76- // Stubs
77- // -----
78-
76+ // MARK: - Funnel overrides
7977 override var length : Int {
8078 get {
8179 return _mapUnmanaged { $0. length }
8280 }
8381 }
84-
8582 override var bytes : UnsafeRawPointer {
8683 return _mapUnmanaged { $0. bytes }
8784 }
88-
89- // override func subdata(with range: NSRange) -> Data {
90- // return _mapUnmanaged { $0.subdata(with: range) }
91- // }
92- //
93- // override func getBytes(_ buffer: UnsafeMutableRawPointer, length: Int) {
94- // return _mapUnmanaged { $0.getBytes(buffer, length: length) }
95- // }
96- //
97- // override func getBytes(_ buffer: UnsafeMutableRawPointer, range: NSRange) {
98- // return _mapUnmanaged { $0.getBytes(buffer, range: range) }
99- // }
100- //
101- // override func isEqual(to other: Data) -> Bool {
102- // return _mapUnmanaged { return $0.isEqual(to: other) }
103- // }
104- //
105- // override func write(to url: URL, options: Data.WritingOptions) throws {
106- // return try _mapUnmanaged { try $0.write(to: url, options: options) }
107- // }
108- //
109- // override func range(of data: Data, options: Data.SearchOptions, range: NSRange) -> NSRange {
110- // return _mapUnmanaged {
111- // $0.range(of: data, options: options, in: range)
112- // }
113- // }
114- //
115- // override func enumerateByteRanges(using block: (UnsafeRawPointer, NSRange, UnsafeMutablePointer<ObjCBool>) -> Void) {
116- // return _mapUnmanaged { $0.enumerateBytes(block) }
117- // }
118- //
119- // override func base64EncodedString(options: Data.Base64EncodingOptions) -> String {
120- // return _mapUnmanaged { $0.base64EncodedString(options) }
121- // }
122- //
123- // override func base64EncodedData(options: Data.Base64EncodingOptions) -> Data {
124- // return _mapUnmanaged { $0.base64EncodedData(options) }
125- // }
12685}
12786
12887/**
@@ -197,10 +156,17 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
197156 _wrapped = _SwiftNSData ( immutableObject: NSData ( bytes: buffer. baseAddress, length: MemoryLayout < SourceType > . stride * buffer. count) )
198157 }
199158
159+ /// Initialize a `Data` with copied memory content.
160+ ///
161+ /// - parameter buffer: A buffer pointer to copy. The size is calculated from `SourceType` and `buffer.count`.
162+ public init < SourceType> ( buffer: UnsafeMutableBufferPointer < SourceType > ) {
163+ _wrapped = _SwiftNSData ( immutableObject: NSData ( bytes: UnsafePointer ( buffer. baseAddress) , length: MemoryLayout < SourceType > . stride * buffer. count) )
164+ }
165+
200166 /// Initialize a `Data` with the contents of an Array.
201167 ///
202168 /// - parameter bytes: An array of bytes to copy.
203- public init ( bytes: Array < UInt8 > ) {
169+ public init ( bytes: [ UInt8 ] ) {
204170 _wrapped = bytes. withUnsafeBufferPointer {
205171 return _SwiftNSData ( immutableObject: NSData ( bytes: $0. baseAddress, length: $0. count) )
206172 }
@@ -226,7 +192,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
226192 /// - parameter capacity: The size of the data.
227193 public init ( capacity: Int ) {
228194 if let d = NSMutableData ( capacity: capacity) {
229- _wrapped = _SwiftNSData ( immutableObject : d)
195+ _wrapped = _SwiftNSData ( mutableObject : d)
230196 } else {
231197 fatalError ( " Unable to allocate data of the requested capacity " )
232198 }
@@ -261,7 +227,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
261227 ///
262228 /// Returns nil when the input is not recognized as valid Base-64.
263229 /// - parameter base64String: The string to parse.
264- /// - parameter options: Decoding options. Default value is `[]`.
230+ /// - parameter options: Encoding options. Default value is `[]`.
265231 public init ? ( base64Encoded base64String: String , options: Data . Base64DecodingOptions = [ ] ) {
266232 if let d = NSData ( base64Encoded: base64String, options: Base64DecodingOptions ( rawValue: options. rawValue) ) {
267233 _wrapped = _SwiftNSData ( immutableObject: d)
@@ -288,16 +254,24 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
288254 ///
289255 /// - parameter count: The number of bytes the data initially contains.
290256 public init ( count: Int ) {
291- if let memory = calloc ( 1 , count ) ? . bindMemory ( to : UInt8 . self , capacity : count) {
292- self . init ( bytesNoCopy : memory , count : count , deallocator : . free )
257+ if let d = NSMutableData ( length : count) {
258+ _wrapped = _SwiftNSData ( mutableObject : d )
293259 } else {
294260 fatalError ( " Unable to allocate data of the requested count " )
295261 }
296262 }
263+
297264
298- internal init ( _bridged data: NSData ) {
299- // We must copy the input because it might be mutable; just like storing a value type in ObjC
300- _wrapped = _SwiftNSData ( immutableObject: data. copy ( ) as! NSObject )
265+ /// Initialize a `Data` by adopting a reference type.
266+ ///
267+ /// You can use this initializer to create a `struct Data` that wraps a `class NSData`. `struct Data` will use the `class NSData` for all operations. Other initializers (including casting using `as Data`) may choose to hold a reference or not, based on a what is the most efficient representation.
268+ ///
269+ /// If the resulting value is mutated, then `Data` will invoke the `mutableCopy()` function on the reference to copy the contents. You may customize the behavior of that function if you wish to return a specialized mutable subclass.
270+ ///
271+ /// - parameter reference: The instance of `NSData` that you wish to wrap. This instance will be copied by `struct Data`.
272+ public init ( referencing reference: NSData ) {
273+ // NOTE: don't fix this warning on Darwin -- linux will complain
274+ _wrapped = _SwiftNSData ( immutableObject: reference. copy ( ) as! AnyObject )
301275 }
302276
303277 // -----------------------------------
@@ -356,7 +330,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
356330 _mapUnmanaged { $0. getBytes ( pointer, length: count) }
357331 }
358332
359- private func _copyBytesHelper( to pointer: UnsafeMutableRawPointer , from range: NSRange ) {
333+ private func _copyBytesHelper( to pointer: UnsafeMutablePointer < UInt8 > , from range: NSRange ) {
360334 _mapUnmanaged { $0. getBytes ( pointer, range: range) }
361335 }
362336
@@ -366,7 +340,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
366340 /// - parameter range: The range in the `Data` to copy.
367341 /// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes.
368342 public func copyBytes( to pointer: UnsafeMutablePointer < UInt8 > , from range: Range < Index > ) {
369- _copyBytesHelper ( to: pointer, from: NSRange ( location : range. lowerBound , length : range . upperBound - range . lowerBound ) )
343+ _copyBytesHelper ( to: pointer, from: NSRange ( range) )
370344 }
371345
372346 /// Copy the contents of the data into a buffer.
@@ -397,8 +371,10 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
397371 guard !copyRange. isEmpty else { return 0 }
398372
399373 let nsRange = NSMakeRange ( copyRange. lowerBound, copyRange. upperBound - copyRange. lowerBound)
400- let pointer = UnsafeMutableRawPointer ( buffer. baseAddress!)
401- _copyBytesHelper ( to: pointer, from: nsRange)
374+ let ptr = buffer. baseAddress!
375+ ptr. withMemoryRebound ( to: UInt8 . self, capacity: buffer. count) {
376+ _copyBytesHelper ( to: $0, from: nsRange)
377+ }
402378 return copyRange. count
403379 }
404380
@@ -499,10 +475,13 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
499475
500476 /// Replace a region of bytes in the data with new data.
501477 ///
502- /// - parameter range: The range in the data to replace.
478+ /// This will resize the data if required, to fit the entire contents of `data`.
479+ ///
480+ /// - precondition: The bounds of `subrange` must be valid indices of the collection.
481+ /// - parameter subrange: The range in the data to replace. If `subrange.lowerBound == data.count && subrange.count == 0` then this operation is an append.
503482 /// - parameter data: The replacement data.
504- public mutating func replaceBytes ( in range : Range < Index > , with data: Data ) {
505- let nsRange = NSMakeRange ( range . lowerBound, range . upperBound - range . lowerBound)
483+ public mutating func replaceSubrange ( _ subrange : Range < Index > , with data: Data ) {
484+ let nsRange = NSMakeRange ( subrange . lowerBound, subrange . upperBound - subrange . lowerBound)
506485 let cnt = data. count
507486 let bytes = data. _getUnsafeBytesPointer ( )
508487
@@ -511,6 +490,68 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
511490 }
512491 }
513492
493+ /// Replace a region of bytes in the data with new bytes from a buffer.
494+ ///
495+ /// This will resize the data if required, to fit the entire contents of `buffer`.
496+ ///
497+ /// - precondition: The bounds of `subrange` must be valid indices of the collection.
498+ /// - parameter subrange: The range in the data to replace.
499+ /// - parameter buffer: The replacement bytes.
500+ public mutating func replaceSubrange< SourceType> ( _ subrange: Range < Index > , with buffer: UnsafeBufferPointer < SourceType > ) {
501+ let nsRange = NSMakeRange ( subrange. lowerBound, subrange. upperBound - subrange. lowerBound)
502+ let bufferCount = buffer. count * MemoryLayout< SourceType> . stride
503+
504+ _applyUnmanagedMutation {
505+ $0. replaceBytes ( in: nsRange, withBytes: buffer. baseAddress!, length: bufferCount)
506+ }
507+
508+ }
509+
510+ /// Replace a region of bytes in the data with new bytes from a collection.
511+ ///
512+ /// This will resize the data if required, to fit the entire contents of `newElements`.
513+ ///
514+ /// - precondition: The bounds of `subrange` must be valid indices of the collection.
515+ /// - parameter subrange: The range in the data to replace.
516+ /// - parameter newElements: The replacement bytes.
517+ public mutating func replaceSubrange< ByteCollection : Collection > ( _ subrange: Range < Index > , with newElements: ByteCollection ) where ByteCollection. Iterator. Element == Data . Iterator . Element {
518+
519+ // Calculate this once, it may not be O(1)
520+ let replacementCount : Int = numericCast ( newElements. count)
521+ let currentCount = self . count
522+ let subrangeCount = subrange. count
523+
524+ if currentCount < subrange. lowerBound + subrangeCount {
525+ if subrangeCount == 0 {
526+ preconditionFailure ( " location \( subrange. lowerBound) exceeds data count \( currentCount) " )
527+ } else {
528+ preconditionFailure ( " range \( subrange) exceeds data count \( currentCount) " )
529+ }
530+ }
531+
532+ let resultCount = currentCount - subrangeCount + replacementCount
533+ if resultCount != currentCount {
534+ // This may realloc.
535+ // In the future, if we keep the malloced pointer and count inside this struct/ref instead of deferring to NSData, we may be able to do this more efficiently.
536+ self . count = resultCount
537+ }
538+
539+ let shift = resultCount - currentCount
540+ let start = subrange. lowerBound
541+
542+ self . withUnsafeMutableBytes { ( bytes : UnsafeMutablePointer < UInt8 > ) -> ( ) in
543+ if shift != 0 {
544+ let destination = bytes + start + replacementCount
545+ let source = bytes + start + subrangeCount
546+ memmove ( destination, source, currentCount - start - subrangeCount)
547+ }
548+
549+ if replacementCount != 0 {
550+ newElements. _copyContents ( initializing: bytes + start)
551+ }
552+ }
553+ }
554+
514555 /// Return a new copy of the data in a specified range.
515556 ///
516557 /// - parameter range: The range to copy.
@@ -526,16 +567,16 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
526567 ///
527568 /// - parameter options: The options to use for the encoding. Default value is `[]`.
528569 /// - returns: The Base-64 encoded string.
529- public func base64EncodedString( _ options: Data . Base64EncodingOptions = [ ] ) -> String {
530- return _mapUnmanaged { $0. base64EncodedString ( options) }
570+ public func base64EncodedString( options: Data . Base64EncodingOptions = [ ] ) -> String {
571+ return _mapUnmanaged { $0. base64EncodedString ( options: options ) }
531572 }
532573
533574 /// Returns a Base-64 encoded `Data`.
534575 ///
535576 /// - parameter options: The options to use for the encoding. Default value is `[]`.
536577 /// - returns: The Base-64 encoded data.
537- public func base64EncodedData( _ options: Data . Base64EncodingOptions = [ ] ) -> Data {
538- return _mapUnmanaged { $0. base64EncodedData ( options) }
578+ public func base64EncodedData( options: Data . Base64EncodingOptions = [ ] ) -> Data {
579+ return _mapUnmanaged { $0. base64EncodedData ( options: options ) }
539580 }
540581
541582 // MARK: -
@@ -556,7 +597,6 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
556597 return _mapUnmanaged { $0. debugDescription }
557598 }
558599
559- // MARK: -
560600
561601 // MARK: -
562602 // MARK: Index and Subscript
@@ -577,20 +617,12 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
577617 }
578618 }
579619
580- public subscript( bounds: Range < Int > ) -> MutableRandomAccessSlice < Data > {
620+ public subscript( bounds: Range < Index > ) -> MutableRandomAccessSlice < Data > {
581621 get {
582622 return MutableRandomAccessSlice ( base: self , bounds: bounds)
583623 }
584624 set {
585- // Ideally this would be:
586- // replaceBytes(in: bounds, with: newValue._base)
587- // but we do not have access to _base due to 'internal' protection
588- // TODO: Use a custom Slice type so we have access to the underlying data
589- let arrayOfBytes = newValue. map { $0 }
590- arrayOfBytes. withUnsafeBufferPointer {
591- let otherData = Data ( buffer: $0)
592- replaceBytes ( in: bounds, with: otherData)
593- }
625+ replaceSubrange ( bounds, with: newValue. base)
594626 }
595627 }
596628
@@ -620,12 +652,14 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
620652 public func makeIterator( ) -> Data . Iterator {
621653 return IndexingIterator ( _elements: self )
622654 }
655+
656+ /// Returns `true` if the two `Data` arguments are equal.
657+ public static func == ( d1 : Data , d2 : Data ) -> Bool {
658+ return d1. _wrapped. isEqual ( to: d2)
659+ }
623660}
624661
625- /// Returns `true` if the two `Data` arguments are equal.
626- public func == ( d1 : Data , d2 : Data ) -> Bool {
627- return d1. _wrapped. isEqual ( to: d2)
628- }
662+
629663
630664/// Provides bridging functionality for struct Data to class NSData and vice-versa.
631665extension Data : _ObjectTypeBridgeable {
@@ -639,11 +673,11 @@ extension Data : _ObjectTypeBridgeable {
639673 }
640674
641675 public static func _forceBridgeFromObjectiveC( _ input: NSData , result: inout Data ? ) {
642- result = Data ( _bridged : input)
676+ result = Data ( referencing : input)
643677 }
644678
645679 public static func _conditionallyBridgeFromObjectiveC( _ input: NSData , result: inout Data ? ) -> Bool {
646- result = Data ( _bridged : input)
680+ result = Data ( referencing : input)
647681 return true
648682 }
649683
0 commit comments