Skip to content

Commit

Permalink
Cannot use nil for CFType (Go 1.10+)
Browse files Browse the repository at this point in the history
fixes #40

Cannot use nil for CFType (Go 1.10+), round 2

reducing code changes between Go versions

conversions can occur in older Go versions too

extract eventIDSinceNow constant to other files

Go-version specific files.

reworks #34 which resolves int overflow #31

minimize code differences between Go versions

Work around bizarre bugs in 1.10.3 (not 1.10.4)

golang/go#24161

use C.kCFAllocatorDefault instead of C.CFAllocatorRef(0)

thanks to @havoc-io for the tip

reduce duplication between go 1.10 before/after

thanks to C.kCFAllocatorDefault change
  • Loading branch information
nathany committed Sep 5, 2018
1 parent 9aeb189 commit 0739535
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 296 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ os: osx
go:
- "stable"
- "1.10.4"
- "1.10.3" # 1.10.3 (and earlier 1.10.x) have unique bugs to work around.
- "1.9.7"
- "1.8.7"

Expand Down
27 changes: 27 additions & 0 deletions go_1_10_after.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// +build darwin,go1.10

package fsevents

/*
#include <CoreServices/CoreServices.h>
*/
import "C"

const (
nullCFStringRef = C.CFStringRef(0)
nullCFUUIDRef = C.CFUUIDRef(0)
)

// NOTE: The following code is identical between go_1_10_after and go_1_10_before,
// however versions of Go 1.10.x prior to 1.10.4 fail to compile when the code utilizing
// the above constants is in a different file (wrap.go).

// GetDeviceUUID retrieves the UUID required to identify an EventID
// in the FSEvents database
func GetDeviceUUID(deviceID int32) string {
uuid := C.FSEventsCopyUUIDForDevice(C.dev_t(deviceID))
if uuid == nullCFUUIDRef {
return ""
}
return cfStringToGoString(C.CFUUIDCreateString(C.kCFAllocatorDefault, uuid))
}
25 changes: 25 additions & 0 deletions go_1_10_before.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// +build darwin,!go1.10

package fsevents

/*
#include <CoreServices/CoreServices.h>
*/
import "C"

var (
nullCFStringRef = C.CFStringRef(nil)
nullCFUUIDRef = C.CFUUIDRef(nil)
)

// NOTE: The following code is identical between go_1_10_after and go_1_10_before.

// GetDeviceUUID retrieves the UUID required to identify an EventID
// in the FSEvents database
func GetDeviceUUID(deviceID int32) string {
uuid := C.FSEventsCopyUUIDForDevice(C.dev_t(deviceID))
if uuid == nullCFUUIDRef {
return ""
}
return cfStringToGoString(C.CFUUIDCreateString(C.kCFAllocatorDefault, uuid))
}
11 changes: 11 additions & 0 deletions go_1_9_2_after.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// +build darwin,go1.9.2

package fsevents

/*
#include <CoreServices/CoreServices.h>
*/
import "C"

// eventIDSinceNow is a sentinel to begin watching events "since now".
const eventIDSinceNow = uint64(C.kFSEventStreamEventIdSinceNow)
13 changes: 13 additions & 0 deletions go_1_9_2_before.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// +build darwin,!go1.9.2

package fsevents

// Prior to Go 1.9.2, converting C.kFSEventStreamEventIdSinceNow to a uint64
// results in the error: "constant -1 overflows uint64".
// Related Go issue: https://github.com/golang/go/issues/21708

// Hardcoding the value here from FSEvents.h:
// kFSEventStreamEventIdSinceNow = 0xFFFFFFFFFFFFFFFFULL

// eventIDSinceNow is a sentinel to begin watching events "since now".
const eventIDSinceNow = uint64(0xFFFFFFFFFFFFFFFF)
36 changes: 16 additions & 20 deletions wrap.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build darwin,go1.10
// +build darwin

package fsevents

Expand Down Expand Up @@ -34,9 +34,6 @@ import (
"unsafe"
)

// eventIDSinceNow is a sentinel to begin watching events "since now".
const eventIDSinceNow = uint64(C.kFSEventStreamEventIdSinceNow)

// LatestEventID returns the most recently generated event ID, system-wide.
func LatestEventID() uint64 {
return uint64(C.FSEventsGetCurrentEventId())
Expand Down Expand Up @@ -105,21 +102,11 @@ func GetStreamRefPaths(f FSEventStreamRef) []string {
return ss
}

// GetDeviceUUID retrieves the UUID required to identify an EventID
// in the FSEvents database
func GetDeviceUUID(deviceID int32) string {
uuid := C.FSEventsCopyUUIDForDevice(C.dev_t(deviceID))
if uuid == C.CFUUIDRef(0) {
return ""
}
return cfStringToGoString(C.CFUUIDCreateString(nil, uuid))
}

func cfStringToGoString(cfs C.CFStringRef) string {
if cfs == 0 {
if cfs == nullCFStringRef {
return ""
}
cfStr := C.CFStringCreateCopy(nil, cfs)
cfStr := copyCFString(cfs)
length := C.CFStringGetLength(cfStr)
if length == 0 {
// short-cut for empty strings
Expand Down Expand Up @@ -148,6 +135,11 @@ func cfStringToGoString(cfs C.CFStringRef) string {
return *(*string)(unsafe.Pointer(strHeader))
}

// copyCFString makes an immutable copy of a string with CFStringCreateCopy.
func copyCFString(cfs C.CFStringRef) C.CFStringRef {
return C.CFStringCreateCopy(C.kCFAllocatorDefault, cfs)
}

// CFRunLoopRef wraps C.CFRunLoopRef
type CFRunLoopRef C.CFRunLoopRef

Expand All @@ -169,10 +161,7 @@ func createPaths(paths []string) (C.CFArrayRef, error) {
// because of them
errs = append(errs, err)
}
cpath := C.CString(p)
defer C.free(unsafe.Pointer(cpath))

str := C.CFStringCreateWithCString(nil, cpath, C.kCFStringEncodingUTF8)
str := makeCFString(p)
C.CFArrayAppendValue(C.CFMutableArrayRef(cPaths), unsafe.Pointer(str))
}
var err error
Expand All @@ -182,6 +171,13 @@ func createPaths(paths []string) (C.CFArrayRef, error) {
return cPaths, err
}

// makeCFString makes an immutable string with CFStringCreateWithCString.
func makeCFString(str string) C.CFStringRef {
s := C.CString(str)
defer C.free(unsafe.Pointer(s))
return C.CFStringCreateWithCString(C.kCFAllocatorDefault, s, C.kCFStringEncodingUTF8)
}

// CFArrayLen retrieves the length of CFArray type
// See https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFArrayRef/#//apple_ref/c/func/CFArrayGetCount
func cfArrayLen(ref C.CFArrayRef) int {
Expand Down
Loading

0 comments on commit 0739535

Please sign in to comment.