Skip to content

Commit

Permalink
refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
Achille Roussel committed Jun 21, 2016
1 parent dec41dc commit 5fbe47b
Show file tree
Hide file tree
Showing 13 changed files with 408 additions and 133 deletions.
31 changes: 0 additions & 31 deletions CF/Base.go

This file was deleted.

27 changes: 0 additions & 27 deletions CF/String_test.go

This file was deleted.

82 changes: 82 additions & 0 deletions CF/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// +build darwin

package CF

// #cgo CFLAGS: -Wno-unused-parameter
// #cgo LDFLAGS: -framework CoreFoundation
//
// #include <CoreFoundation/CFBase.h>
import "C"
import "unsafe"

// The TypeRef type is an untyped reference to any Core Foundation object.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/tdef/CFTypeRef
type TypeRef uintptr

// The TypeID type is used to provide a unique identifier to the type of Core
// Foundation object.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/tdef/CFTypeID
type TypeID uint64

// GetTypeID returns the TypeID representing the type of the Core Foundation
// object passed as argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFGetTypeID
func (obj TypeRef) GetTypeID() TypeID {
return TypeID(C.CFGetTypeID(C.CFTypeRef(obj)))
}

// Retain increases the refence counter of the Core Foundation object passed
// as argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFRetain
func (obj TypeRef) Retain() {
C.CFRetain(C.CFTypeRef(obj))
}

// Release decreases the reference counter of the Core Foundation object
// passed as argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFRelease
func (obj TypeRef) Release() {
C.CFRelease(C.CFTypeRef(obj))
}

// CopyDescription returns a string representation of the object passed as
// argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFCopyDescription
func (obj TypeRef) CopyDescription() StringRef {
return StringRef(unsafe.Pointer(C.CFCopyDescription(C.CFTypeRef(obj))))
}

// String satisfies the fmt.Stringer interface.
func (obj TypeRef) String() string {
s := obj.CopyDescription()
defer s.Release()
return GoString(s)
}

// CopyTypeIDDescription returns a string representation of the type id passed
// as argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFCopyTypeIDDescription
func (id TypeID) CopyTypeIDDescription() StringRef {
return StringRef(unsafe.Pointer(C.CFCopyTypeIDDescription(C.CFTypeID(id))))
}

// String satisfies the fmt.Stringer interface.
func (id TypeID) String() string {
s := id.CopyTypeIDDescription()
defer s.Release()
return GoString(s)
}

// Equal tests two object for equality.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFEqual
func Equal(obj1 TypeRef, obj2 TypeRef) bool {
return C.CFEqual(C.CFTypeRef(obj1), C.CFTypeRef(obj2)) != 0
}
26 changes: 26 additions & 0 deletions CF/base_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package CF

import "testing"

func TestTypeRefString(t *testing.T) {
s1 := StringCreate("Hello World!")
s2 := TypeRef(s1).String()

if len(s2) == 0 {
t.Error("invalid string description:", s2)
}

TypeRef(s1).Release()
}

func TestTypeIDString(t *testing.T) {
s1 := StringCreate("Hello World!")
s2 := TypeRef(s1).GetTypeID().String()

if s2 != "CFString" {
t.Error("invalid string description:", s2)
}

TypeRef(s1).Release()

}
46 changes: 40 additions & 6 deletions CF/String.go → CF/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ package CF
// #include <CoreFoundation/CFString.h>
import "C"
import (
"fmt"
"reflect"
"unsafe"
)

// The StringRef type is a reference to a Core Foundation string object.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFStringRef/index.html#//apple_ref/c/tdef/CFStringRef
type StringRef unsafe.Pointer
type StringRef TypeRef

// StringCreate takes a Go string as argument and creates a String object
// that represents the same content, then returns a reference to the newly
Expand All @@ -24,28 +25,28 @@ type StringRef unsafe.Pointer
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFStringRef/index.html#//apple_ref/c/func/CFStringCreateWithBytes
func StringCreate(s string) StringRef {
h := (*reflect.StringHeader)(unsafe.Pointer(&s))
return StringRef(C.CFStringCreateWithBytes(
return StringRef(unsafe.Pointer(C.CFStringCreateWithBytes(
nil,
(*C.UInt8)(unsafe.Pointer(h.Data)),
C.CFIndex(len(s)),
C.kCFStringEncodingUTF8,
0,
))
)))
}

// GoString creates a new Go string value with a content equivalent to the
// StringRef object passed as argument.
func GoString(s StringRef) string {
ptr := C.CFStringGetCStringPtr(s, C.kCFStringEncodingUTF8)
ptr := C.CFStringGetCStringPtr(unsafe.Pointer(s), C.kCFStringEncodingUTF8)

if ptr != nil {
return C.GoString(ptr)
}

n := C.CFStringGetLength(s)
n := C.CFStringGetLength(unsafe.Pointer(s))
b := make([]byte, int(4*n))
C.CFStringGetBytes(
s,
unsafe.Pointer(s),
C.CFRange{0, n},
C.kCFStringEncodingUTF8,
'?',
Expand All @@ -57,3 +58,36 @@ func GoString(s StringRef) string {

return string(b[:n])
}

// Retain increases the refence counter of the Core Foundation string passed
// as argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFRetain
func (s StringRef) Retain() {
TypeRef(s).Retain()
}

// Release decreases the reference counter of the Core Foundation string
// passed as argument.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFTypeRef/#//apple_ref/c/func/CFRelease
func (s StringRef) Release() {
TypeRef(s).Release()
}

// Length returns the number of characters in the string it's called on.
//
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFStringRef/#//apple_ref/c/func/CFStringGetLength
func (s StringRef) Length() int {
return int(C.CFStringGetLength(unsafe.Pointer(s)))
}

// String statisfies the fmt.Stringer interface.
func (s StringRef) String() string {
return GoString(s)
}

// GoString satisfies the fmt.GoStringer interface.
func (s StringRef) GoString() string {
return fmt.Sprintf("%v", s.String())
}
112 changes: 112 additions & 0 deletions CF/string_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// +build darwin

package CF

import (
"fmt"
"testing"
)

var strings = []string{
"",
"0123456789",
"Hello World!",
"你好",
"\"abc\"\n",
}

func TestString(t *testing.T) {
for _, test := range strings {
s1 := StringCreate(test)
s1.Retain()
s1.Release()

s2 := GoString(s1)
s1.Release()

if test != s2 {
t.Error(test, "!=", s2)
}
}
}

func TestStringEqualTrue(t *testing.T) {
s1 := StringCreate("Hello World!")
s2 := StringCreate("Hello World!")
defer s1.Release()
defer s2.Release()

if !Equal(TypeRef(s1), TypeRef(s2)) {
t.Error("comparing strings for equality failed")
}
}

func TestStringEqualFalse(t *testing.T) {
s1 := StringCreate("Hello World!")
s2 := StringCreate("A")
defer s1.Release()
defer s2.Release()

if Equal(TypeRef(s1), TypeRef(s2)) {
t.Error("comparing strings for difference failed")
}
}

func TestStringString(t *testing.T) {
for _, test := range strings {
s1 := StringCreate(test)
s2 := s1.String()
s1.Release()

if test != s2 {
t.Error(test, "!=", s2)
}
}
}

func TestStringGoString(t *testing.T) {
for _, test := range strings {
s1 := StringCreate(test)
s2 := s1.GoString()
s1.Release()

if test != fmt.Sprintf("%v", test) {
t.Error(test, "!=", s2)
}
}
}

func TestStringTypeID(t *testing.T) {
s := StringCreate("Hello World!")
id := TypeRef(s).GetTypeID()

if id == 0 {
t.Error("invalid zero type id got from string")
}

TypeRef(s).Release()
}

func TestStringCopyDescription(t *testing.T) {
s1 := StringCreate("Hello World!")
s2 := TypeRef(s1).CopyDescription()

if s2.Length() == 0 {
t.Error("invalid string description:", s2)
}

s1.Release()
s2.Release()
}

func TestStringCopyTypeIDDescription(t *testing.T) {
s1 := StringCreate("Hello World!")
s2 := TypeRef(s1).GetTypeID().CopyTypeIDDescription()

if !Equal(TypeRef(s2), TypeRef(StringCreate("CFString"))) {
t.Error("invalid string description:", s2)
}

s1.Release()
s2.Release()
}
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 5fbe47b

Please sign in to comment.