@@ -73,56 +73,15 @@ internal final class _SwiftNSData : NSData, _SwiftNativeFoundationType {
73
73
releaseWrappedObject ( )
74
74
}
75
75
76
- // Stubs
77
- // -----
78
-
76
+ // MARK: - Funnel overrides
79
77
override var length : Int {
80
78
get {
81
79
return _mapUnmanaged { $0. length }
82
80
}
83
81
}
84
-
85
82
override var bytes : UnsafeRawPointer {
86
83
return _mapUnmanaged { $0. bytes }
87
84
}
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
- // }
126
85
}
127
86
128
87
/**
@@ -197,10 +156,17 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
197
156
_wrapped = _SwiftNSData ( immutableObject: NSData ( bytes: buffer. baseAddress, length: MemoryLayout < SourceType > . stride * buffer. count) )
198
157
}
199
158
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
+
200
166
/// Initialize a `Data` with the contents of an Array.
201
167
///
202
168
/// - parameter bytes: An array of bytes to copy.
203
- public init ( bytes: Array < UInt8 > ) {
169
+ public init ( bytes: [ UInt8 ] ) {
204
170
_wrapped = bytes. withUnsafeBufferPointer {
205
171
return _SwiftNSData ( immutableObject: NSData ( bytes: $0. baseAddress, length: $0. count) )
206
172
}
@@ -226,7 +192,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
226
192
/// - parameter capacity: The size of the data.
227
193
public init ( capacity: Int ) {
228
194
if let d = NSMutableData ( capacity: capacity) {
229
- _wrapped = _SwiftNSData ( immutableObject : d)
195
+ _wrapped = _SwiftNSData ( mutableObject : d)
230
196
} else {
231
197
fatalError ( " Unable to allocate data of the requested capacity " )
232
198
}
@@ -261,7 +227,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
261
227
///
262
228
/// Returns nil when the input is not recognized as valid Base-64.
263
229
/// - parameter base64String: The string to parse.
264
- /// - parameter options: Decoding options. Default value is `[]`.
230
+ /// - parameter options: Encoding options. Default value is `[]`.
265
231
public init ? ( base64Encoded base64String: String , options: Data . Base64DecodingOptions = [ ] ) {
266
232
if let d = NSData ( base64Encoded: base64String, options: Base64DecodingOptions ( rawValue: options. rawValue) ) {
267
233
_wrapped = _SwiftNSData ( immutableObject: d)
@@ -288,16 +254,23 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
288
254
///
289
255
/// - parameter count: The number of bytes the data initially contains.
290
256
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 )
293
259
} else {
294
260
fatalError ( " Unable to allocate data of the requested count " )
295
261
}
296
262
}
263
+
297
264
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
+ _wrapped = _SwiftNSData ( immutableObject: reference. copy ( ) as! AnyObject )
301
274
}
302
275
303
276
// -----------------------------------
@@ -356,7 +329,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
356
329
_mapUnmanaged { $0. getBytes ( pointer, length: count) }
357
330
}
358
331
359
- private func _copyBytesHelper( to pointer: UnsafeMutableRawPointer , from range: NSRange ) {
332
+ private func _copyBytesHelper( to pointer: UnsafeMutablePointer < UInt8 > , from range: NSRange ) {
360
333
_mapUnmanaged { $0. getBytes ( pointer, range: range) }
361
334
}
362
335
@@ -366,7 +339,7 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
366
339
/// - parameter range: The range in the `Data` to copy.
367
340
/// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes.
368
341
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 ) )
342
+ _copyBytesHelper ( to: pointer, from: NSRange ( range) )
370
343
}
371
344
372
345
/// Copy the contents of the data into a buffer.
@@ -397,8 +370,10 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
397
370
guard !copyRange. isEmpty else { return 0 }
398
371
399
372
let nsRange = NSMakeRange ( copyRange. lowerBound, copyRange. upperBound - copyRange. lowerBound)
400
- let pointer = UnsafeMutableRawPointer ( buffer. baseAddress!)
401
- _copyBytesHelper ( to: pointer, from: nsRange)
373
+ let ptr = buffer. baseAddress!
374
+ ptr. withMemoryRebound ( to: UInt8 . self, capacity: buffer. count) {
375
+ _copyBytesHelper ( to: $0, from: nsRange)
376
+ }
402
377
return copyRange. count
403
378
}
404
379
@@ -499,10 +474,13 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
499
474
500
475
/// Replace a region of bytes in the data with new data.
501
476
///
502
- /// - parameter range: The range in the data to replace.
477
+ /// This will resize the data if required, to fit the entire contents of `data`.
478
+ ///
479
+ /// - precondition: The bounds of `subrange` must be valid indices of the collection.
480
+ /// - parameter subrange: The range in the data to replace. If `subrange.lowerBound == data.count && subrange.count == 0` then this operation is an append.
503
481
/// - 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)
482
+ public mutating func replaceSubrange ( _ subrange : Range < Index > , with data: Data ) {
483
+ let nsRange = NSMakeRange ( subrange . lowerBound, subrange . upperBound - subrange . lowerBound)
506
484
let cnt = data. count
507
485
let bytes = data. _getUnsafeBytesPointer ( )
508
486
@@ -511,6 +489,68 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
511
489
}
512
490
}
513
491
492
+ /// Replace a region of bytes in the data with new bytes from a buffer.
493
+ ///
494
+ /// This will resize the data if required, to fit the entire contents of `buffer`.
495
+ ///
496
+ /// - precondition: The bounds of `subrange` must be valid indices of the collection.
497
+ /// - parameter subrange: The range in the data to replace.
498
+ /// - parameter buffer: The replacement bytes.
499
+ public mutating func replaceSubrange< SourceType> ( _ subrange: Range < Index > , with buffer: UnsafeBufferPointer < SourceType > ) {
500
+ let nsRange = NSMakeRange ( subrange. lowerBound, subrange. upperBound - subrange. lowerBound)
501
+ let bufferCount = buffer. count * MemoryLayout< SourceType> . stride
502
+
503
+ _applyUnmanagedMutation {
504
+ $0. replaceBytes ( in: nsRange, withBytes: buffer. baseAddress!, length: bufferCount)
505
+ }
506
+
507
+ }
508
+
509
+ /// Replace a region of bytes in the data with new bytes from a collection.
510
+ ///
511
+ /// This will resize the data if required, to fit the entire contents of `newElements`.
512
+ ///
513
+ /// - precondition: The bounds of `subrange` must be valid indices of the collection.
514
+ /// - parameter subrange: The range in the data to replace.
515
+ /// - parameter newElements: The replacement bytes.
516
+ public mutating func replaceSubrange< ByteCollection : Collection > ( _ subrange: Range < Index > , with newElements: ByteCollection ) where ByteCollection. Iterator. Element == Data . Iterator . Element {
517
+
518
+ // Calculate this once, it may not be O(1)
519
+ let replacementCount : Int = numericCast ( newElements. count)
520
+ let currentCount = self . count
521
+ let subrangeCount = subrange. count
522
+
523
+ if currentCount < subrange. lowerBound + subrangeCount {
524
+ if subrangeCount == 0 {
525
+ preconditionFailure ( " location \( subrange. lowerBound) exceeds data count \( currentCount) " )
526
+ } else {
527
+ preconditionFailure ( " range \( subrange) exceeds data count \( currentCount) " )
528
+ }
529
+ }
530
+
531
+ let resultCount = currentCount - subrangeCount + replacementCount
532
+ if resultCount != currentCount {
533
+ // This may realloc.
534
+ // 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.
535
+ self . count = resultCount
536
+ }
537
+
538
+ let shift = resultCount - currentCount
539
+ let start = subrange. lowerBound
540
+
541
+ self . withUnsafeMutableBytes { ( bytes : UnsafeMutablePointer < UInt8 > ) -> ( ) in
542
+ if shift != 0 {
543
+ let destination = bytes + start + replacementCount
544
+ let source = bytes + start + subrangeCount
545
+ memmove ( destination, source, currentCount - start - subrangeCount)
546
+ }
547
+
548
+ if replacementCount != 0 {
549
+ newElements. _copyContents ( initializing: bytes + start)
550
+ }
551
+ }
552
+ }
553
+
514
554
/// Return a new copy of the data in a specified range.
515
555
///
516
556
/// - parameter range: The range to copy.
@@ -526,16 +566,16 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
526
566
///
527
567
/// - parameter options: The options to use for the encoding. Default value is `[]`.
528
568
/// - returns: The Base-64 encoded string.
529
- public func base64EncodedString( _ options: Data . Base64EncodingOptions = [ ] ) -> String {
530
- return _mapUnmanaged { $0. base64EncodedString ( options) }
569
+ public func base64EncodedString( options: Data . Base64EncodingOptions = [ ] ) -> String {
570
+ return _mapUnmanaged { $0. base64EncodedString ( options: options ) }
531
571
}
532
572
533
573
/// Returns a Base-64 encoded `Data`.
534
574
///
535
575
/// - parameter options: The options to use for the encoding. Default value is `[]`.
536
576
/// - returns: The Base-64 encoded data.
537
- public func base64EncodedData( _ options: Data . Base64EncodingOptions = [ ] ) -> Data {
538
- return _mapUnmanaged { $0. base64EncodedData ( options) }
577
+ public func base64EncodedData( options: Data . Base64EncodingOptions = [ ] ) -> Data {
578
+ return _mapUnmanaged { $0. base64EncodedData ( options: options ) }
539
579
}
540
580
541
581
// MARK: -
@@ -556,7 +596,6 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
556
596
return _mapUnmanaged { $0. debugDescription }
557
597
}
558
598
559
- // MARK: -
560
599
561
600
// MARK: -
562
601
// MARK: Index and Subscript
@@ -577,20 +616,12 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
577
616
}
578
617
}
579
618
580
- public subscript( bounds: Range < Int > ) -> MutableRandomAccessSlice < Data > {
619
+ public subscript( bounds: Range < Index > ) -> MutableRandomAccessSlice < Data > {
581
620
get {
582
621
return MutableRandomAccessSlice ( base: self , bounds: bounds)
583
622
}
584
623
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
- }
624
+ replaceSubrange ( bounds, with: newValue. base)
594
625
}
595
626
}
596
627
@@ -620,12 +651,14 @@ public struct Data : ReferenceConvertible, CustomStringConvertible, Equatable, H
620
651
public func makeIterator( ) -> Data . Iterator {
621
652
return IndexingIterator ( _elements: self )
622
653
}
654
+
655
+ /// Returns `true` if the two `Data` arguments are equal.
656
+ public static func == ( d1 : Data , d2 : Data ) -> Bool {
657
+ return d1. _wrapped. isEqual ( to: d2)
658
+ }
623
659
}
624
660
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
- }
661
+
629
662
630
663
/// Provides bridging functionality for struct Data to class NSData and vice-versa.
631
664
extension Data : _ObjectTypeBridgeable {
@@ -639,11 +672,11 @@ extension Data : _ObjectTypeBridgeable {
639
672
}
640
673
641
674
public static func _forceBridgeFromObjectiveC( _ input: NSData , result: inout Data ? ) {
642
- result = Data ( _bridged : input)
675
+ result = Data ( referencing : input)
643
676
}
644
677
645
678
public static func _conditionallyBridgeFromObjectiveC( _ input: NSData , result: inout Data ? ) -> Bool {
646
- result = Data ( _bridged : input)
679
+ result = Data ( referencing : input)
647
680
return true
648
681
}
649
682
0 commit comments