@@ -217,7 +217,9 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
217
217
return nil
218
218
}
219
219
super. init ( )
220
- _init ( bytes: & decodedBytes, length: decodedBytes. count, copy: true )
220
+ _init ( bytes: decodedBytes. baseAddress!, length: decodedBytes. count, copy: false , deallocator: { ( ptr, length) in
221
+ ptr. deallocate ( )
222
+ } )
221
223
}
222
224
223
225
/// Initializes a data object with the given Base64 encoded data.
@@ -226,7 +228,9 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
226
228
return nil
227
229
}
228
230
super. init ( )
229
- _init ( bytes: & decodedBytes, length: decodedBytes. count, copy: true )
231
+ _init ( bytes: decodedBytes. baseAddress!, length: decodedBytes. count, copy: false , deallocator: { ( ptr, length) in
232
+ ptr. deallocate ( )
233
+ } )
230
234
}
231
235
232
236
deinit {
@@ -647,7 +651,7 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
647
651
- parameter options: Options for handling invalid input
648
652
- returns: The decoded bytes.
649
653
*/
650
- private static func base64DecodeBytes< T: Collection > ( _ bytes: T , options: Base64DecodingOptions = [ ] ) -> [ UInt8 ] ? where T. Element == UInt8 {
654
+ private static func base64DecodeBytes< T: Collection > ( _ bytes: T , options: Base64DecodingOptions = [ ] ) -> UnsafeMutableRawBufferPointer ? where T. Element == UInt8 {
651
655
652
656
// This table maps byte values 0-127, input bytes >127 are always invalid.
653
657
// Map the ASCII characters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -> 0...63
@@ -672,14 +676,21 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
672
676
return nil
673
677
}
674
678
675
- var decodedBytes : [ UInt8 ] = [ ]
676
679
let capacity = ( bytes. count * 3 ) / 4 // Every 4 valid ASCII bytes maps to 3 output bytes.
677
- decodedBytes. reserveCapacity ( capacity)
680
+ let buffer = UnsafeMutableRawPointer . allocate ( byteCount: capacity, alignment: 1 )
681
+ var outputIndex = 0
682
+
683
+ func append( _ byte: UInt8 ) {
684
+ assert ( outputIndex < capacity)
685
+ buffer. storeBytes ( of: byte, toByteOffset: outputIndex, as: UInt8 . self)
686
+ outputIndex += 1
687
+ }
678
688
679
689
var currentByte : UInt8 = 0
680
690
var validCharacterCount = 0
681
691
var paddingCount = 0
682
692
var index = 0
693
+ var error = false
683
694
684
695
for base64Char in bytes {
685
696
var value : UInt8 = 0
@@ -703,30 +714,32 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
703
714
if ignoreUnknown {
704
715
continue
705
716
} else {
706
- return nil
717
+ error = true
718
+ break
707
719
}
708
720
}
709
721
validCharacterCount += 1
710
722
711
723
// Padding found in the middle of the sequence is invalid.
712
724
if paddingCount > 0 {
713
- return nil
725
+ error = true
726
+ break
714
727
}
715
728
716
729
switch index {
717
730
case 0 :
718
731
currentByte = ( value << 2 )
719
732
case 1 :
720
733
currentByte |= ( value >> 4 )
721
- decodedBytes . append ( currentByte)
734
+ append ( currentByte)
722
735
currentByte = ( value << 4 )
723
736
case 2 :
724
737
currentByte |= ( value >> 2 )
725
- decodedBytes . append ( currentByte)
738
+ append ( currentByte)
726
739
currentByte = ( value << 6 )
727
740
case 3 :
728
741
currentByte |= value
729
- decodedBytes . append ( currentByte)
742
+ append ( currentByte)
730
743
index = - 1
731
744
default :
732
745
fatalError ( )
@@ -735,11 +748,12 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
735
748
index += 1
736
749
}
737
750
738
- guard ( validCharacterCount + paddingCount) % 4 == 0 else {
751
+ guard error == false && ( validCharacterCount + paddingCount) % 4 == 0 else {
739
752
// Invalid character count of valid input characters.
753
+ buffer. deallocate ( )
740
754
return nil
741
755
}
742
- return decodedBytes
756
+ return UnsafeMutableRawBufferPointer ( start : buffer , count : outputIndex )
743
757
}
744
758
745
759
/**
0 commit comments