/* The "debug" description, used by CFCopyDescription and -[NSObject description]. */ CFStringRef _CFErrorCreateDebugDescription(CFErrorRef err) { CFMutableStringRef result = CFStringCreateMutable( kCFAllocatorSystemDefault, 0); CFStringAppendFormat( result, NULL, CFSTR("Error Domain=%@ Code=%d"), CFErrorGetDomain(err), (int)CFErrorGetCode(err)); CFDictionaryRef userInfo = _CFErrorGetUserInfo(err); if (userInfo) { CFStringAppendFormat(result, NULL, CFSTR(" UserInfo=%p"), userInfo); } CFStringRef desc = CFErrorCopyDescription(err); if (desc) { CFStringAppendFormat(result, NULL, CFSTR(" \"%@\""), desc); CFRelease(desc); } CFStringRef debugDesc = _CFErrorCopyUserInfoKey(err, kCFErrorDebugDescriptionKey); if (debugDesc) { if (CFStringGetLength(debugDesc) > 0) { CFStringAppendFormat(result, NULL, CFSTR(" (%@)"), debugDesc); } CFRelease(debugDesc); } return result; }
/* This function retrieves the value of the specified key from the userInfo, or from the callback. It works with a CF or NSError. */ static CFStringRef _CFErrorCopyUserInfoKey(CFErrorRef err, CFStringRef key) { CFStringRef result = NULL; // First consult the userInfo dictionary CFDictionaryRef userInfo = _CFErrorGetUserInfo(err); if (userInfo) result = (CFStringRef)CFDictionaryGetValue(userInfo, key); // If that doesn't work, consult the callback if (result) { CFRetain(result); } else { CFErrorUserInfoKeyCallBack callBack = CFErrorGetCallBackForDomain(CFErrorGetDomain(err)); if (callBack) result = (CFStringRef)callBack(err, key); } return result; }
CFStringRef _CFErrorCreateDebugDescription(CFErrorRef err) { CFStringRef desc = CFErrorCopyDescription(err); CFStringRef debugDesc = _CFErrorCopyUserInfoKey(err, kCFErrorDebugDescriptionKey); CFDictionaryRef userInfo = _CFErrorGetUserInfo(err); CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); CFStringAppendFormat(result, NULL, CFSTR("Error Domain=%@ Code=%d"), CFErrorGetDomain(err), (long)CFErrorGetCode(err)); CFStringAppendFormat(result, NULL, CFSTR(" \"%@\""), desc); if (debugDesc && CFStringGetLength(debugDesc) > 0) CFStringAppendFormat(result, NULL, CFSTR(" (%@)"), debugDesc); if (userInfo) { CFStringAppendFormat(result, NULL, CFSTR(" UserInfo=%p {"), userInfo); CFDictionaryApplyFunction(userInfo, userInfoKeyValueShow, (void *)result); CFIndex commaLength = (CFStringHasSuffix(result, CFSTR(", "))) ? 2 : 0; CFStringReplace(result, CFRangeMake(CFStringGetLength(result)-commaLength, commaLength), CFSTR("}")); } if (debugDesc) CFRelease(debugDesc); if (desc) CFRelease(desc); return result; }
/* This accessor never returns NULL. For usage inside this file, consider __CFErrorGetUserInfo(). */ CFDictionaryRef CFErrorCopyUserInfo(CFErrorRef err) { CFDictionaryRef userInfo = _CFErrorGetUserInfo(err); return userInfo ? (CFDictionaryRef)CFRetain(userInfo) : _CFErrorCreateEmptyDictionary(CFGetAllocator(err)); }