0

I'm trying to adapt code found here to make parsing dates more performant. Doing the following and then attempting to print the values is giving me massive numbers, rather than the underlying real value (I'm assuming it is a memory address).

private static var components = DateComponents()

private static var year = UnsafeMutablePointer<Int>.allocate(capacity: 1)
private static let month = UnsafeMutablePointer<Int>.allocate(capacity: 1)
private static let day = UnsafeMutablePointer<Int>.allocate(capacity: 1)
private static let hour = UnsafeMutablePointer<Int>.allocate(capacity: 1)
private static let minute = UnsafeMutablePointer<Int>.allocate(capacity: 1)
private static let second = UnsafeMutablePointer<Float>.allocate(capacity: 1)
private static let hourOffset = UnsafeMutablePointer<Int>.allocate(capacity: 1)
private static let minuteOffset = UnsafeMutablePointer<Int>.allocate(capacity: 1)

let parseCount = withVaList(
            [year, month, day, hour, minute, second, hourOffset, minuteOffset],
            { pointer -> Int32 in
                vsscanf("2022-09-21T09:01:00+01:00", "%d-%d-%dT%d:%d:%f%d:%dZ", pointer)
            }
        )

        components.year = year.pointee
        components.minute = minute.pointee
        components.day = day.pointee
        components.hour = hour.pointee
        components.month = month.pointee
        components.second = Int(second.pointee)
dump(components)

The resulting dump looks like this:

year: 5764607523034236902 month: 5764607523034234889 day: 5764607523034234901 hour: 5764607523034234889 minute: 5764607523034234881 second: 0 isLeapMonth: false 

Now keep in mind that this actually works for dates that have the correct formatter passed in (i.e. it can create the date from the from the components). However, where the formatter is incorrect, I cannot see what the current value is for each UnsafeMutablePointer. This makes debugging the formatter really difficult. Anyone got any ideas why I can't see the value of the pointee?

Note: Casting the other values as Int() does not work, unfortunately.

Update: I've even played around with this in C++ here. The parsing does seem to work. I just want to inspect what the value of val6 and val7 are - but in the Xcode debugger rather than using a playpen for C++.

Karim
  • 271
  • 2
  • 11
  • If the parse fails, there IS no current value. Right? What does `parseCount` return? – Tim Roberts Sep 21 '22 at 16:56
  • Hi @TimRoberts - parseCount is returning a value of 8 successfully parsed arguments. – Karim Sep 21 '22 at 17:00
  • But `vsscanf` returns whether it was successful. You should check that value and deal with it, right? – Rob Napier Sep 21 '22 at 17:01
  • @RobNapier according to C++ docs, `vsscanf` returns only an integer value representing the number of successfully filled varargs https://cplusplus.com/reference/cstdio/vsscanf/ – Karim Sep 21 '22 at 17:03
  • 1
    Right; so if that isn't 8, there was an error, right? So you know where the problem is. (Or am I missing something deeper here?) – Rob Napier Sep 21 '22 at 17:05
  • Don't worry, this is not production code (yet). I just want to see it working before I clean it up. Thanks for the tip re: `&value`. You're right in saying the correct number of values should be `7`. I'm not entirely sure why it's parsing out 8 values. In the string formatter, we can see 7 `%` values `"%d-%d-%dT%d:%d:%f%d:%dZ"` – Karim Sep 21 '22 at 17:08
  • @Karim Like Rob, I count 8: `%d`, `%d`, `%d`, `%d`, `%d`, `%f`, `%d`, `%d`. `%f%d` looks like the odd one out – Itai Ferber Sep 21 '22 at 17:11
  • Looking at the date again, it looks like 8 might actually be the correct value? `"%2022-%09-%21T%09:%01:%00%+01:%00"` I've tagged the corresponding values that should be parsed in the date string. – Karim Sep 21 '22 at 17:14
  • There's no literal `"Z"` in your timestamp. – Tim Roberts Sep 21 '22 at 17:25
  • Removing the `%f` did seem to make it work. Interesting. – Karim Sep 21 '22 at 17:27
  • @TimRoberts you're right! Don't know what I was thinking. Thanks for pointing that out. – Karim Sep 21 '22 at 17:47
  • I think you may need to change from `UnsafeMutablePointer` to `UnsafeMutablePointer` (aka. `UnsafeMutablePointer`). `Int` is defined to be the efficient word size for the machine and on most platforms (maybe even all now) its 64-bits, whereas in C, `int` is usually 32 bits for historical reasons though it can be 64 (or on really old machines 16).. – Chip Jarred Sep 21 '22 at 17:52
  • 1
    @ChipJarred thank you! That helped me to debug my dates :) Much appreciated. – Karim Sep 23 '22 at 09:16
  • You're welcome! In this case you likely could have also just initialized your allocated `Int`s to 0. I'm pretty sure the reason your `Date` components were wonky was that `vsscanf` was parsing into the lower 32-bits, while the upper-32 bits just remained whatever random value happened to be in that allocated, but uninitialized memory location. Initializing the thing you're scanning into is a good idea, but passing the right sized thing is more important. If you were passing pointers to things that were too small instead of too large, `vsscanf` would stomp over memory beyond their size. – Chip Jarred Sep 23 '22 at 17:40

0 Answers0