diff --git a/Sources/FoundationEssentials/Data/Data+Deprecated.swift b/Sources/FoundationEssentials/Data/Data+Deprecated.swift index 9df11f2a8..d48caff15 100644 --- a/Sources/FoundationEssentials/Data/Data+Deprecated.swift +++ b/Sources/FoundationEssentials/Data/Data+Deprecated.swift @@ -33,7 +33,7 @@ extension Data { /// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure. @available(swift, deprecated: 5, message: "use `withUnsafeBytes(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead") public func withUnsafeBytes(_ body: (UnsafePointer) throws -> ResultType) rethrows -> ResultType { - return try _representation.withUnsafeBytes { + return try self.withUnsafeBytes { return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafePointer(bitPattern: 0xBAD0)!) } } @@ -44,7 +44,7 @@ extension Data { /// - warning: The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure. @available(swift, deprecated: 5, message: "use `withUnsafeMutableBytes(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R` instead") public mutating func withUnsafeMutableBytes(_ body: (UnsafeMutablePointer) throws -> ResultType) rethrows -> ResultType { - return try _representation.withUnsafeMutableBytes { + return try self.withUnsafeMutableBytes { return try body($0.baseAddress?.assumingMemoryBound(to: ContentType.self) ?? UnsafeMutablePointer(bitPattern: 0xBAD0)!) } } @@ -55,6 +55,9 @@ extension Data { /// - parameter block: The closure to invoke for each region of data. You may stop the enumeration by setting the `stop` parameter to `true`. @available(swift, deprecated: 5, message: "use `regions` or `for-in` instead") public func enumerateBytes(_ block: (_ buffer: UnsafeBufferPointer, _ byteIndex: Index, _ stop: inout Bool) -> Void) { - _representation.enumerateBytes(block) + self.withUnsafeBytes { + var stop = false + block($0.assumingMemoryBound(to: UInt8.self), 0, &stop) + } } } diff --git a/Sources/FoundationEssentials/Data/Data.swift b/Sources/FoundationEssentials/Data/Data.swift index 2cd254dca..d9b6f5047 100644 --- a/Sources/FoundationEssentials/Data/Data.swift +++ b/Sources/FoundationEssentials/Data/Data.swift @@ -106,25 +106,10 @@ internal func _withStackOrHeapBuffer(capacity: Int, _ body: (UnsafeMutableBuffer body(UnsafeMutableBufferPointer(start: nil, count: 0)) return } - typealias InlineBuffer = ( // 32 bytes - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, - UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8 - ) - let inlineCount = MemoryLayout.size - if capacity <= inlineCount { - var buffer: InlineBuffer = ( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - ) - withUnsafeMutableBytes(of: &buffer) { buffer in - assert(buffer.count == inlineCount) - buffer.withMemoryRebound(to: UInt8.self) { - body(UnsafeMutableBufferPointer(start: $0.baseAddress, count: capacity)) - } + // Use an inline allocation for 32 bytes or fewer + if capacity <= 32 { + withUnsafeTemporaryAllocation(of: UInt8.self, capacity: capacity) { buffer in + body(buffer) } return } @@ -493,63 +478,6 @@ public struct Data : RandomAccessCollection, MutableCollection, RangeReplaceable return try _representation.withUnsafeMutableBytes(body) } - // MARK: - - // MARK: Copy Bytes - - /// Copy the contents of the data to a pointer. - /// - /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. - /// - parameter count: The number of bytes to copy. - /// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes. - @inlinable // This is @inlinable as trivially forwarding. - public func copyBytes(to pointer: UnsafeMutablePointer, count: Int) { - precondition(count >= 0, "count of bytes to copy must not be negative") - if count == 0 { return } - _copyBytesHelper(to: UnsafeMutableRawPointer(pointer), from: startIndex..<(startIndex + count)) - } - - @inlinable // This is @inlinable as trivially forwarding. - internal func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: Range) { - if range.isEmpty { return } - _representation.copyBytes(to: pointer, from: range) - } - - /// Copy a subset of the contents of the data to a pointer. - /// - /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. - /// - parameter range: The range in the `Data` to copy. - /// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes. - @inlinable // This is @inlinable as trivially forwarding. - public func copyBytes(to pointer: UnsafeMutablePointer, from range: Range) { - _copyBytesHelper(to: pointer, from: range) - } - - // Copy the contents of the data into a buffer. - /// - /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout.stride * buffer.count` then the first N bytes will be copied into the buffer. - /// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called. - /// - parameter buffer: A buffer to copy the data into. - /// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied. - /// - returns: Number of bytes copied into the destination buffer. - @inlinable // This is @inlinable as generic and reasonably small. - public func copyBytes(to buffer: UnsafeMutableBufferPointer, from range: Range? = nil) -> Int { - let cnt = count - guard cnt > 0 else { return 0 } - - let copyRange : Range - if let r = range { - guard !r.isEmpty else { return 0 } - copyRange = r.lowerBound..<(r.lowerBound + Swift.min(buffer.count * MemoryLayout.stride, r.upperBound - r.lowerBound)) - } else { - copyRange = startIndex..<(startIndex + Swift.min(buffer.count * MemoryLayout.stride, cnt)) - } - - guard !copyRange.isEmpty else { return 0 } - - _copyBytesHelper(to: buffer.baseAddress!, from: copyRange) - return copyRange.upperBound - copyRange.lowerBound - } - // MARK: - @inlinable // This is @inlinable as a generic, trivially forwarding function. @@ -887,7 +815,8 @@ extension Data : Equatable { } // Compare the contents - return memcmp(b1Address, b2Address, b2.count) == 0 + assert(length1 == b2.count) + return memcmp(b1Address, b2Address, length1) == 0 } } } @@ -917,8 +846,8 @@ extension Data : CustomStringConvertible, CustomDebugStringConvertible, CustomRe } // Minimal size data is output as an array - if nBytes < 64 { - children.append((label: "bytes", value: Array(self[startIndex.. { return CollectionOfOne(self) } + + /// Copy the contents of the data to a pointer. + /// + /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. + /// - parameter count: The number of bytes to copy. + /// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes. + @inlinable // This is @inlinable as trivially forwarding. + public func copyBytes(to pointer: UnsafeMutablePointer, count: Int) { + precondition(count >= 0, "count of bytes to copy must not be negative") + if count == 0 { return } + _copyBytesHelper(to: UnsafeMutableRawPointer(pointer), from: startIndex..<(startIndex + count)) + } + + @inlinable // This is @inlinable as trivially forwarding. + internal func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: Range) { + if range.isEmpty { return } + _representation.copyBytes(to: pointer, from: range) + } + + /// Copy a subset of the contents of the data to a pointer. + /// + /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. + /// - parameter range: The range in the `Data` to copy. + /// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes. + @inlinable // This is @inlinable as trivially forwarding. + public func copyBytes(to pointer: UnsafeMutablePointer, from range: Range) { + _copyBytesHelper(to: pointer, from: range) + } + + // Copy the contents of the data into a buffer. + /// + /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout.stride * buffer.count` then the first N bytes will be copied into the buffer. + /// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called. + /// - parameter buffer: A buffer to copy the data into. + /// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied. + /// - returns: Number of bytes copied into the destination buffer. + @inlinable // This is @inlinable as generic and reasonably small. + public func copyBytes(to buffer: UnsafeMutableBufferPointer, from range: Range? = nil) -> Int { + let cnt = count + guard cnt > 0 else { return 0 } + + let copyRange : Range + if let r = range { + guard !r.isEmpty else { return 0 } + copyRange = r.lowerBound..<(r.lowerBound + Swift.min(buffer.count * MemoryLayout.stride, r.upperBound - r.lowerBound)) + } else { + copyRange = startIndex..<(startIndex + Swift.min(buffer.count * MemoryLayout.stride, cnt)) + } + + guard !copyRange.isEmpty else { return 0 } + + _copyBytesHelper(to: buffer.baseAddress!, from: copyRange) + return copyRange.upperBound - copyRange.lowerBound + } } //===--- DataProtocol Conditional Conformances ----------------------------===// diff --git a/Sources/FoundationEssentials/Data/Representations/Data+Inline.swift b/Sources/FoundationEssentials/Data/Representations/Data+Inline.swift index 5981f0a6d..b71eb7a0b 100644 --- a/Sources/FoundationEssentials/Data/Representations/Data+Inline.swift +++ b/Sources/FoundationEssentials/Data/Representations/Data+Inline.swift @@ -10,7 +10,9 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) @preconcurrency import Glibc #elseif canImport(Musl) @preconcurrency import Musl diff --git a/Sources/FoundationEssentials/Data/Representations/DataStorage.swift b/Sources/FoundationEssentials/Data/Representations/DataStorage.swift index 0ef9506cc..9e11f7b4d 100644 --- a/Sources/FoundationEssentials/Data/Representations/DataStorage.swift +++ b/Sources/FoundationEssentials/Data/Representations/DataStorage.swift @@ -10,7 +10,9 @@ // //===----------------------------------------------------------------------===// -#if canImport(Glibc) +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) @preconcurrency import Glibc #elseif canImport(Musl) @preconcurrency import Musl