[swift-users] changes to pointer data types in Xcode 8 beta 6
Andrew Trick
atrick at apple.com
Sat Aug 20 02:33:30 CDT 2016
> On Aug 15, 2016, at 3:05 PM, Dave Reed via swift-users <swift-users at swift.org> wrote:
>
> I'm trying to convert the following code (from the Big Nerd Ranch's Freddy JSON parser) that works in Xcode 8 beta 5 and convert it to work with beta 6. Essentially it appears it needs to take a Data object and convert it to a UnsafeBufferPointer<UInt8> if I understand it correctly.
>
>
> /// Creates a `JSONParser` ready to parse UTF-8 encoded `NSData`.
> ///
> /// If the data is mutable, it is copied before parsing. The data's lifetime
> /// is extended for the duration of parsing.
> init(utf8Data inData: Data) {
> let data = (inData as NSData).copy() as! Data
> let buffer = UnsafeBufferPointer(start: UnsafePointer<UInt8>((data as NSData).bytes), count: data.count)
> self.init(buffer: buffer, owner: data)
> }
>
> And this case appears to be going from a String to UnsafeBufferPointer<Uint8>
>
>
> /// Creates a `JSONParser` from the code units represented by the `string`.
> ///
> /// The synthesized string is lifetime-extended for the duration of parsing.
> init(string: String) {
> let codePoints = string.nulTerminatedUTF8
> let buffer = codePoints.withUnsafeBufferPointer { nulTerminatedBuffer in
> // don't want to include the nul termination in the buffer - trim it off
> UnsafeBufferPointer(start: nulTerminatedBuffer.baseAddress, count: nulTerminatedBuffer.count - 1)
> }
> self.init(buffer: buffer, owner: codePoints)
> }
>
> }
>
>
> I understand pointers from my C/C++/Objective-C days but I don't yet understand the various Swift pointer types. Any help is appreciated.
>
> Note: I don't work for Big Nerd Ranch. I'm just trying to use the code and better understand the various Swift pointer types.
>
> Thanks,
> Dave Reed
I'm too late to help, but just to follow up...
If you're wondering how to migrate pointer conversion like this to 3.0:
UnsafePointer<UInt8>(data.bytes)
UnsafeBufferPointer(start: nulTerminatedBuffer.baseAddress,
count: nulTerminatedBuffer.count - 1)
then there's a quick explanation here <https://gist.github.com/atrick/0283ae0e284610fd21ad6ed3f454a585>.
The proposal that Zach posted has more background:
https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md
You can get something working easily enough with pointer bitcasts or binding memory, but converting UnsafePointers is not something you should be doing here.
If the JSON parser has its own copy of the data, then it should simply have its own array:
private let input: [UInt8]
//deleted private let owner: Any?
init(utf8Data inData: Data) {
input = [UInt8](inData)
}
init(string: String) {
input = [UInt8](string.utf8)
}
If the JSON parser wanted to operate on data that is owned by someone else, then we need something like the UnsafeBytes type proposed here:
https://github.com/atrick/swift-evolution/blob/unsafebytes/proposals/NNNN-UnsafeBytes.md#detailed-design
private let input: UnsafeBytes
private let owner: Any?
init(utf8Data inData: Data) {
// Data should directly provide a
// withUnsafeBytes<T>(_ body: (UnsafeBytes) -> R)
input = inData.withUnsafeBytes { (p: UnsafePointer<UInt8>) in
UnsafeBytes(start: UnsafeRawPointer(p), count: inData.count) }
owner = inData
}
Although, in the case of String input you still need to create a copy:
init(string: String) {
let utf8Array = [UInt8](string.utf8)
input = utf8Array.withUnsafeBytes { $0 }
owner = utf8Array
}
Note that passing a String as an argument of type UnsafePointer<UInt8> works, but should never be done when calling Swift code. The lifetime of that pointer doesn't outlive the call.
-Andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160820/69e6862a/attachment.html>
More information about the swift-users
mailing list