mirror of
https://github.com/lux-tel/session-ios.git
synced 2026-10-30 20:38:32 +00:00
78 lines
3.3 KiB
Swift
78 lines
3.3 KiB
Swift
// Copyright © 2025 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import Foundation
|
|
|
|
public extension Collection where Element == String {
|
|
func withUnsafeCStrArray<R>(
|
|
_ body: (UnsafeBufferPointer<UnsafePointer<CChar>?>) throws -> R
|
|
) throws -> R {
|
|
let pointerArray = UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>.allocate(capacity: self.count)
|
|
var allocatedCStrings: [UnsafeMutablePointer<CChar>?] = []
|
|
allocatedCStrings.reserveCapacity(self.count)
|
|
defer {
|
|
for ptr in allocatedCStrings {
|
|
free(ptr) /// Need to use `free` for memory allocated by `strdup`
|
|
}
|
|
pointerArray.deallocate()
|
|
}
|
|
|
|
var currentPtr: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> = pointerArray
|
|
for element in self {
|
|
/// `strdup` allocates memory and copies the C string (inc. null terminator), it returns NULL on allocation failure.
|
|
guard let cString: UnsafeMutablePointer<CChar> = strdup(element) else {
|
|
throw LibSessionError.invalidCConversion
|
|
}
|
|
|
|
allocatedCStrings.append(cString) /// Track for cleanup
|
|
currentPtr.pointee = cString /// Store pointer in the array
|
|
currentPtr += 1 /// Move to next slot in pointer array
|
|
}
|
|
|
|
let mutableBuffer = UnsafeBufferPointer(start: pointerArray, count: self.count)
|
|
|
|
return try mutableBuffer.withMemoryRebound(to: UnsafePointer<CChar>?.self) { immutableBuffer in
|
|
try body(immutableBuffer)
|
|
}
|
|
}
|
|
}
|
|
|
|
public extension Collection where Element == [UInt8]? {
|
|
func withUnsafeUInt8CArray<R>(
|
|
_ body: (UnsafeBufferPointer<UnsafePointer<UInt8>?>) throws -> R
|
|
) throws -> R {
|
|
let pointerArray = UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?>.allocate(capacity: self.count)
|
|
var allocatedByteArrays: [UnsafeMutableRawPointer?] = []
|
|
allocatedByteArrays.reserveCapacity(self.count)
|
|
|
|
defer {
|
|
for ptr in allocatedByteArrays {
|
|
free(ptr) /// Need to use `free` for memory allocated by `malloc`
|
|
}
|
|
|
|
pointerArray.deallocate()
|
|
}
|
|
|
|
var currentPtr: UnsafeMutablePointer<UnsafeMutablePointer<UInt8>?> = pointerArray
|
|
for maybeBytes in self {
|
|
if let bytes = maybeBytes {
|
|
guard let allocatedMemory: UnsafeMutableRawPointer = malloc(bytes.count) else {
|
|
throw LibSessionError.invalidCConversion
|
|
}
|
|
|
|
allocatedByteArrays.append(allocatedMemory) /// Track for cleanup
|
|
memcpy(allocatedMemory, bytes, bytes.count) /// Copy bytes into the allocated memory
|
|
currentPtr.pointee = allocatedMemory.assumingMemoryBound(to: UInt8.self) /// Store in array
|
|
} else {
|
|
currentPtr.pointee = nil /// Store nil in array
|
|
}
|
|
currentPtr += 1 /// Move to next slot in pointer array
|
|
}
|
|
|
|
let mutableBuffer = UnsafeBufferPointer(start: pointerArray, count: self.count)
|
|
|
|
return try mutableBuffer.withMemoryRebound(to: UnsafePointer<UInt8>?.self) { immutableBuffer in
|
|
try body(immutableBuffer)
|
|
}
|
|
}
|
|
}
|