github.com/Code-Hex/battery@v1.0.0/internal/macos/corefoundation.go (about)

     1  //go:build darwin
     2  
     3  package macOS
     4  
     5  import (
     6  	"errors"
     7  	"reflect"
     8  	"runtime"
     9  	"unsafe"
    10  )
    11  
    12  // Core Foundation linker flags for the external linker. See Issue 42459 in golang/go.
    13  
    14  // CFRef is an opaque reference to a Core Foundation object. It is a pointer,
    15  // but to memory not owned by Go, so not an unsafe.Pointer.
    16  type CFRef uintptr
    17  
    18  // syscall is implemented in the runtime package (runtime/sys_darwin.go)
    19  
    20  //go:linkname syscall crypto/x509/internal/macos.syscall
    21  func syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) uintptr
    22  
    23  // CFStringToString returns a Go string representation of the passed
    24  // in CFString, or an empty string if it's invalid.
    25  func CFStringToString(ref CFRef) string {
    26  	data, err := CFStringCreateExternalRepresentation(ref)
    27  	if err != nil {
    28  		return ""
    29  	}
    30  	b := CFDataToSlice(data)
    31  	CFRelease(data)
    32  	return string(b)
    33  }
    34  
    35  const kCFNumberIntType = 9
    36  
    37  type CFString CFRef
    38  
    39  const kCFAllocatorDefault = 0
    40  const kCFStringEncodingUTF8 = 0x08000100
    41  
    42  //go:cgo_import_dynamic battery_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    43  
    44  func CFStringCreateExternalRepresentation(strRef CFRef) (CFRef, error) {
    45  	ret := syscall(FuncPC(battery_CFStringCreateExternalRepresentation_trampoline), kCFAllocatorDefault, uintptr(strRef), kCFStringEncodingUTF8, 0, 0, 0)
    46  	if ret == 0 {
    47  		return 0, errors.New("string can't be represented as UTF-8")
    48  	}
    49  	return CFRef(ret), nil
    50  }
    51  func battery_CFStringCreateExternalRepresentation_trampoline()
    52  
    53  func CFDataToSlice(data CFRef) []byte {
    54  	length := CFDataGetLength(data)
    55  	ptr := CFDataGetBytePtr(data)
    56  	src := (*[1 << 20]byte)(unsafe.Pointer(ptr))[:length:length]
    57  	out := make([]byte, length)
    58  	copy(out, src)
    59  	return out
    60  }
    61  
    62  //go:cgo_import_dynamic battery_CFDataGetLength CFDataGetLength "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    63  
    64  func CFDataGetLength(data CFRef) int {
    65  	ret := syscall(FuncPC(battery_CFDataGetLength_trampoline), uintptr(data), 0, 0, 0, 0, 0)
    66  	return int(ret)
    67  }
    68  func battery_CFDataGetLength_trampoline()
    69  
    70  //go:cgo_import_dynamic battery_CFDataGetBytePtr CFDataGetBytePtr "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    71  
    72  func CFDataGetBytePtr(data CFRef) uintptr {
    73  	ret := syscall(FuncPC(battery_CFDataGetBytePtr_trampoline), uintptr(data), 0, 0, 0, 0, 0)
    74  	return ret
    75  }
    76  func battery_CFDataGetBytePtr_trampoline()
    77  
    78  //go:cgo_import_dynamic battery_CFRelease CFRelease "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    79  
    80  func CFRelease(ref CFRef) {
    81  	syscall(FuncPC(battery_CFRelease_trampoline), uintptr(ref), 0, 0, 0, 0, 0)
    82  }
    83  func battery_CFRelease_trampoline()
    84  
    85  //go:cgo_import_dynamic battery_CFArrayGetCount CFArrayGetCount "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    86  
    87  func CFArrayGetCount(array CFRef) int {
    88  	ret := syscall(FuncPC(battery_CFArrayGetCount_trampoline), uintptr(array), 0, 0, 0, 0, 0)
    89  	return int(ret)
    90  }
    91  func battery_CFArrayGetCount_trampoline()
    92  
    93  const kCFNumberSInt32Type = 3
    94  
    95  //go:cgo_import_dynamic battery_CFNumberGetValue CFNumberGetValue "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
    96  
    97  func CFNumberGetValue(num CFRef) (int32, error) {
    98  	var value int32
    99  	ret := syscall(FuncPC(battery_CFNumberGetValue_trampoline), uintptr(num), uintptr(kCFNumberSInt32Type),
   100  		uintptr(unsafe.Pointer(&value)), 0, 0, 0)
   101  	if ret == 0 {
   102  		return 0, errors.New("CFNumberGetValue call failed")
   103  	}
   104  	return value, nil
   105  }
   106  func battery_CFNumberGetValue_trampoline()
   107  
   108  //go:cgo_import_dynamic battery_CFDictionaryGetValueIfPresent CFDictionaryGetValueIfPresent "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   109  
   110  func CFDictionaryGetValueIfPresent(dict CFRef, key CFString) (value CFRef, ok bool) {
   111  	ret := syscall(FuncPC(battery_CFDictionaryGetValueIfPresent_trampoline), uintptr(dict), uintptr(key),
   112  		uintptr(unsafe.Pointer(&value)), 0, 0, 0)
   113  	if ret == 0 {
   114  		return 0, false
   115  	}
   116  	return value, true
   117  }
   118  func battery_CFDictionaryGetValueIfPresent_trampoline()
   119  
   120  //go:cgo_import_dynamic battery_CFStringCreateWithBytes CFStringCreateWithBytes "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   121  
   122  // StringToCFString returns a copy of the UTF-8 contents of s as a new CFString.
   123  func StringToCFString(s string) CFString {
   124  	p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
   125  	ret := syscall(FuncPC(battery_CFStringCreateWithBytes_trampoline), kCFAllocatorDefault, uintptr(p),
   126  		uintptr(len(s)), uintptr(kCFStringEncodingUTF8), 0 /* isExternalRepresentation */, 0)
   127  	runtime.KeepAlive(p)
   128  	return CFString(ret)
   129  }
   130  func battery_CFStringCreateWithBytes_trampoline()
   131  
   132  //go:cgo_import_dynamic battery_CFArrayGetValueAtIndex CFArrayGetValueAtIndex "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"
   133  
   134  func CFArrayGetValueAtIndex(array CFRef, index int) CFRef {
   135  	ret := syscall(FuncPC(battery_CFArrayGetValueAtIndex_trampoline), uintptr(array), uintptr(index), 0, 0, 0, 0)
   136  	return CFRef(ret)
   137  }
   138  func battery_CFArrayGetValueAtIndex_trampoline()
   139  
   140  // ReleaseCFArray iterates through an array, releasing its contents, and then
   141  // releases the array itself. This is necessary because we cannot, easily, set the
   142  // CFArrayCallBacks argument when creating CFArrays.
   143  func ReleaseCFArray(array CFRef) {
   144  	for i := 0; i < CFArrayGetCount(array); i++ {
   145  		ref := CFArrayGetValueAtIndex(array, i)
   146  		CFRelease(ref)
   147  	}
   148  	CFRelease(array)
   149  }