// Convert converts a CFTypeRef to a go instance. func Convert(ref C.CFTypeRef) (interface{}, error) { typeID := C.CFGetTypeID(ref) if typeID == C.CFStringGetTypeID() { return CFStringToString(C.CFStringRef(ref)), nil } else if typeID == C.CFDictionaryGetTypeID() { return ConvertCFDictionary(C.CFDictionaryRef(ref)) } else if typeID == C.CFArrayGetTypeID() { arr := CFArrayToArray(C.CFArrayRef(ref)) results := make([]interface{}, 0, len(arr)) for _, ref := range arr { v, err := Convert(ref) if err != nil { return nil, err } results = append(results, v) return results, nil } } else if typeID == C.CFDataGetTypeID() { b, err := CFDataToBytes(C.CFDataRef(ref)) if err != nil { return nil, err } return b, nil } else if typeID == C.CFNumberGetTypeID() { return CFNumberToInterface(C.CFNumberRef(ref)), nil } else if typeID == C.CFBooleanGetTypeID() { if C.CFBooleanGetValue(C.CFBooleanRef(ref)) != 0 { return true, nil } return false, nil } return nil, fmt.Errorf("Invalid type: %s", CFTypeDescription(ref)) }
func getCFDictValueCFStringRef(dict C.CFDictionaryRef, key C.CFTypeRef) (C.CFStringRef, error) { val, err := getCFDictValueRef(dict, key) if err != nil { return nil, err } if val == nil { return nil, errors.New("getCFDictValueCFStringRef: Nil value returned") } if C.CFGetTypeID(val) != C.CFStringGetTypeID() { return nil, errors.New("getCFDictValueCFStringRef: value is not a string") } return C.CFStringRef(val), nil }
func convertCFDictionaryToMapHelper(cfDict C.CFDictionaryRef, helper func(key string, value cfTypeRef, count int) error) error { count := int(C.CFDictionaryGetCount(cfDict)) if count == 0 { return nil } cfKeys := make([]cfTypeRef, count) cfVals := make([]cfTypeRef, count) C.CFDictionaryGetKeysAndValues(cfDict, (*unsafe.Pointer)(&cfKeys[0]), (*unsafe.Pointer)(&cfVals[0])) for i := 0; i < count; i++ { cfKey := cfKeys[i] typeId := C.CFGetTypeID(C.CFTypeRef(cfKey)) if typeId != C.CFStringGetTypeID() { return &UnsupportedKeyTypeError{int(typeId)} } key := convertCFStringToString(C.CFStringRef(cfKey)) if err := helper(key, cfVals[i], count); err != nil { return err } } return nil }
// we shouldn't ever get an error from this, but I'd rather not panic func convertCFTypeToInterface(cfType cfTypeRef) (interface{}, error) { typeId := C.CFGetTypeID(C.CFTypeRef(cfType)) switch typeId { case C.CFStringGetTypeID(): return convertCFStringToString(C.CFStringRef(cfType)), nil case C.CFNumberGetTypeID(): return convertCFNumberToInterface(C.CFNumberRef(cfType)), nil case C.CFBooleanGetTypeID(): return convertCFBooleanToBool(C.CFBooleanRef(cfType)), nil case C.CFDataGetTypeID(): return convertCFDataToBytes(C.CFDataRef(cfType)), nil case C.CFDateGetTypeID(): return convertCFDateToTime(C.CFDateRef(cfType)), nil case C.CFArrayGetTypeID(): ary, err := convertCFArrayToSlice(C.CFArrayRef(cfType)) return ary, err case C.CFDictionaryGetTypeID(): dict, err := convertCFDictionaryToMap(C.CFDictionaryRef(cfType)) return dict, err } return nil, &UnknownCFTypeError{typeId} }
} return format, state.err } type unmarshalState struct { err error } var ( cfArrayTypeID = C.CFArrayGetTypeID() cfBooleanTypeID = C.CFBooleanGetTypeID() cfDataTypeID = C.CFDataGetTypeID() cfDateTypeID = C.CFDateGetTypeID() cfDictionaryTypeID = C.CFDictionaryGetTypeID() cfNumberTypeID = C.CFNumberGetTypeID() cfStringTypeID = C.CFStringGetTypeID() ) var cfTypeMap = map[C.CFTypeID]reflect.Type{ cfArrayTypeID: reflect.TypeOf([]interface{}(nil)), cfBooleanTypeID: reflect.TypeOf(false), cfDataTypeID: reflect.TypeOf([]byte(nil)), cfDateTypeID: reflect.TypeOf(time.Time{}), cfDictionaryTypeID: reflect.TypeOf(map[string]interface{}(nil)), cfStringTypeID: reflect.TypeOf(""), } var cfTypeNames = map[C.CFTypeID]string{ cfArrayTypeID: "CFArray", cfBooleanTypeID: "CFBoolean", cfDataTypeID: "CFData",