func convertCFStringToString(cfStr C.CFStringRef) string { cstrPtr := C.CFStringGetCStringPtr(cfStr, C.kCFStringEncodingUTF8) if cstrPtr != nil { return C.GoString(cstrPtr) } // quick path doesn't work, so copy the bytes out to a buffer length := C.CFStringGetLength(cfStr) if length == 0 { // short-cut for empty strings return "" } cfRange := C.CFRange{0, length} enc := C.CFStringEncoding(C.kCFStringEncodingUTF8) // first find the buffer size necessary var usedBufLen C.CFIndex if C.CFStringGetBytes(cfStr, cfRange, enc, 0, C.false, nil, 0, &usedBufLen) > 0 { bytes := make([]byte, usedBufLen) buffer := (*C.UInt8)(unsafe.Pointer(&bytes[0])) if C.CFStringGetBytes(cfStr, cfRange, enc, 0, C.false, buffer, usedBufLen, nil) > 0 { // bytes is now filled up // convert it to a string header := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) strHeader := &reflect.StringHeader{ Data: header.Data, Len: header.Len, } return *(*string)(unsafe.Pointer(strHeader)) } } // we failed to convert, for some reason. Too bad there's no nil string return "" }
func NSStringToString(inString Object) string { cr := C.CFStringRef(unsafe.Pointer(inString)) var usedBufLen C.CFIndex rng := C.CFRange{C.CFIndex(0), C.CFStringGetLength(cr)} n := int(C.CFStringGetBytes(cr, rng, C.kCFStringEncodingUTF8, 0, 0, nil, 0, &usedBufLen)) if n <= 0 { return "" } buf := make([]byte, int(usedBufLen)) C.CFStringGetBytes(cr, rng, C.kCFStringEncodingUTF8, 0, 0, (*C.UInt8)(unsafe.Pointer(&buf[0])), C.CFIndex(len(buf)), &usedBufLen) sh := &reflect.StringHeader{ Data: uintptr(unsafe.Pointer(&buf[0])), Len: int(usedBufLen), } return *(*string)(unsafe.Pointer(sh)) }
// CFStringToString converts a CFStringRef to a string. func CFStringToString(s C.CFStringRef) string { p := C.CFStringGetCStringPtr(s, C.kCFStringEncodingUTF8) if p != nil { return C.GoString(p) } length := C.CFStringGetLength(s) if length == 0 { return "" } maxBufLen := C.CFStringGetMaximumSizeForEncoding(length, C.kCFStringEncodingUTF8) if maxBufLen == 0 { return "" } buf := make([]byte, maxBufLen) var usedBufLen C.CFIndex _ = C.CFStringGetBytes(s, C.CFRange{0, length}, C.kCFStringEncodingUTF8, C.UInt8(0), C.false, (*C.UInt8)(&buf[0]), maxBufLen, &usedBufLen) return string(buf[:usedBufLen]) }
// cfstringGo creates a Go string for a CoreFoundation string using the CoreFoundation UTF-8 converter. // For short strings this is an efficiency nightmare! In this package this function is not currently used // in any critical path. func cfstringGo(cfs C.CFStringRef) string { var usedBufLen C.CFIndex n := C.cfstring_utf8_length(cfs, &usedBufLen) if n <= 0 { return "" } rng := C.CFRange{location: C.CFIndex(0), length: n} buf := make([]byte, int(usedBufLen)) bufp := unsafe.Pointer(&buf[0]) C.CFStringGetBytes(cfs, rng, C.kCFStringEncodingUTF8, 0, 0, (*C.UInt8)(bufp), C.CFIndex(len(buf)), &usedBufLen) sh := &reflect.StringHeader{ Data: uintptr(bufp), Len: int(usedBufLen), } return *(*string)(unsafe.Pointer(sh)) }
// Converts a CGStringRef object to a Go string. func CFStringToGoString(s C.CFStringRef) string { ptr := C.CFStringGetCStringPtr(s, C.kCFStringEncodingUTF8) if ptr != nil { return C.GoString(ptr) } n := C.CFStringGetLength(s) b := make([]byte, int(4*n)) C.CFStringGetBytes( s, C.CFRangeMake(0, n), C.kCFStringEncodingUTF8, '?', 0, (*C.UInt8)(unsafe.Pointer(&b[0])), C.CFIndex(len(b)), &n, ) return string(b[:n]) }