From d73847987a99375010c6d6ace0abb0a25cb9b034 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 8 Dec 2014 17:18:32 +0000 Subject: [PATCH] CF-1151.16.tar.gz --- CFApplicationPreferences.c | 124 +- CFArray.c | 83 +- CFArray.h | 12 +- CFAvailability.h | 23 +- CFBag.c | 161 ++- CFBag.h | 8 +- CFBase.c | 43 +- CFBase.h | 50 +- CFBasicHash.c | 27 +- CFBasicHash.h | 8 +- CFBasicHashFindBucket.m | 8 +- CFBigNumber.c | 9 +- CFBigNumber.h | 8 +- CFBinaryHeap.c | 42 +- CFBinaryHeap.h | 8 +- CFBinaryPList.c | 74 +- CFBitVector.c | 48 +- CFBitVector.h | 8 +- CFBuiltinConverters.c | 8 +- CFBundle.c | 2308 +++---------------------------- CFBundle.h | 10 +- CFBundlePriv.h | 21 +- CFBundle_Binary.c | 886 ++++++++++++ CFBundle_BinaryTypes.h | 8 +- CFBundle_Grok.c | 1014 ++++++++++++++ CFBundle_InfoPlist.c | 132 +- CFBundle_Internal.h | 46 +- CFBundle_Locale.c | 979 +++++++++++++ CFBundle_Resources.c | 1259 ++--------------- CFBundle_Strings.c | 144 ++ CFBurstTrie.c | 12 +- CFBurstTrie.h | 8 +- CFByteOrder.h | 8 +- CFCalendar.c | 115 +- CFCalendar.h | 12 +- CFCharacterSet.c | 87 +- CFCharacterSet.h | 12 +- CFCharacterSetBitmaps.bitmap | Bin 434391 -> 434391 bytes CFCharacterSetPriv.h | 8 +- CFConcreteStreams.c | 8 +- CFData.c | 48 +- CFData.h | 12 +- CFDate.c | 62 +- CFDate.h | 51 +- CFDateFormatter.c | 301 ++-- CFDateFormatter.h | 10 +- CFDictionary.c | 161 ++- CFDictionary.h | 12 +- CFError.c | 66 +- CFError.h | 10 +- CFError_Private.h | 8 +- CFFileUtilities.c | 18 +- CFICUConverters.c | 8 +- CFICUConverters.h | 8 +- CFICULogging.h | 17 +- CFInternal.h | 158 ++- CFLocale.c | 59 +- CFLocale.h | 12 +- CFLocaleIdentifier.c | 21 +- CFLocaleInternal.h | 10 +- CFLocaleKeys.c | 12 +- CFLogUtilities.h | 8 +- CFMachPort.c | 105 +- CFMachPort.h | 12 +- CFMessagePort.c | 312 +++-- CFMessagePort.h | 12 +- CFNumber.c | 72 +- CFNumber.h | 12 +- CFNumberFormatter.c | 33 +- CFNumberFormatter.h | 10 +- CFOldStylePList.c | 8 +- CFPlatform.c | 8 +- CFPlatformConverters.c | 12 +- CFPlugIn.c | 8 +- CFPlugIn.h | 10 +- CFPlugInCOM.h | 8 +- CFPlugIn_Factory.c | 101 +- CFPlugIn_Factory.h | 8 +- CFPlugIn_Instance.c | 18 +- CFPlugIn_PlugIn.c | 8 +- CFPreferences.c | 39 +- CFPreferences.h | 10 +- CFPriv.h | 8 +- CFPropertyList.c | 96 +- CFPropertyList.h | 26 +- CFRunLoop.c | 254 ++-- CFRunLoop.h | 12 +- CFRuntime.c | 203 ++- CFRuntime.h | 132 +- CFSet.c | 161 ++- CFSet.h | 12 +- CFSocket.c | 309 ++++- CFSocket.h | 10 +- CFSocketStream.c | 24 +- CFSortFunctions.c | 12 +- CFStorage.c | 26 +- CFStorage.h | 8 +- CFStream.c | 54 +- CFStream.h | 12 +- CFStreamAbstract.h | 8 +- CFStreamInternal.h | 6 +- CFStreamPriv.h | 8 +- CFString.c | 549 ++++---- CFString.h | 27 +- CFStringDefaultEncoding.h | 8 +- CFStringEncodingConverter.c | 26 +- CFStringEncodingConverter.h | 8 +- CFStringEncodingConverterExt.h | 8 +- CFStringEncodingConverterPriv.h | 8 +- CFStringEncodingDatabase.c | 20 +- CFStringEncodingDatabase.h | 8 +- CFStringEncodingExt.h | 8 +- CFStringEncodings.c | 8 +- CFStringScanner.c | 8 +- CFStringUtilities.c | 53 +- CFSystemDirectories.c | 8 +- CFTimeZone.c | 44 +- CFTimeZone.h | 8 +- CFTree.c | 58 +- CFTree.h | 8 +- CFURL.c | 712 ++++------ CFURL.h | 165 +-- CFURL.inc.h | 326 ++--- CFURLAccess.c | 10 +- CFURLAccess.h | 36 +- CFURLPriv.h | 107 +- CFUUID.c | 27 +- CFUUID.h | 8 +- CFUniChar.c | 56 +- CFUniChar.h | 8 +- CFUniCharPriv.h | 8 +- CFUniCharPropertyDatabase.data | Bin 31780 -> 31780 bytes CFUnicodeData-B.mapping | Bin 90744 -> 90744 bytes CFUnicodeData-L.mapping | Bin 90744 -> 90744 bytes CFUnicodeDecomposition.c | 24 +- CFUnicodeDecomposition.h | 8 +- CFUnicodePrecomposition.c | 16 +- CFUnicodePrecomposition.h | 8 +- CFUserNotification.c | 21 +- CFUserNotification.h | 10 +- CFUtilities.c | 179 +-- CFUtilities.h | 8 +- CFVersion.c | 12 +- CFWindowsUtilities.c | 8 +- CFXMLInputStream.c | 8 +- CFXMLInputStream.h | 8 +- CFXMLNode.c | 15 +- CFXMLNode.h | 10 +- CFXMLParser.c | 15 +- CFXMLParser.h | 10 +- CFXMLPreferencesDomain.c | 44 +- CFXMLTree.c | 8 +- CoreFoundation.h | 8 +- CoreFoundation_Prefix.h | 31 +- Examples/plconvert.c | 7 +- ForFoundationOnly.h | 27 +- Makefile | 6 +- MakefileVersion | 2 +- SymbolAliases | 2 + TargetConditionals.h | 2 +- plconvert.c | 13 +- 161 files changed, 7121 insertions(+), 6805 deletions(-) create mode 100644 CFBundle_Binary.c create mode 100644 CFBundle_Grok.c create mode 100644 CFBundle_Locale.c create mode 100644 CFBundle_Strings.c diff --git a/CFApplicationPreferences.c b/CFApplicationPreferences.c index 123a75d..43efb30 100644 --- a/CFApplicationPreferences.c +++ b/CFApplicationPreferences.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFApplicationPreferences.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -173,7 +173,7 @@ void CFPreferencesSetAppValue(CFStringRef key, CFTypeRef value, CFStringRef appN } -static CFSpinLock_t __CFApplicationPreferencesLock = CFSpinLockInit; // Locks access to __CFStandardUserPreferences +static CFLock_t __CFApplicationPreferencesLock = CFLockInit; // Locks access to __CFStandardUserPreferences static CFMutableDictionaryRef __CFStandardUserPreferences = NULL; // Mutable dictionary; keys are app names, values are _CFApplicationPreferences Boolean CFPreferencesAppSynchronize(CFStringRef appName) { @@ -182,7 +182,7 @@ Boolean CFPreferencesAppSynchronize(CFStringRef appName) { CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__); // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (__CFStandardUserPreferences) { standardPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName); } else { @@ -190,13 +190,13 @@ Boolean CFPreferencesAppSynchronize(CFStringRef appName) { } result = standardPrefs ? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs) : _CFSynchronizeDomainCache(); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); return result; } void CFPreferencesFlushCaches(void) { CFAllocatorRef alloc = __CFPreferencesAllocator(); - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (__CFStandardUserPreferences) { _CFApplicationPreferences **prefsArray, *prefsBuf[32]; CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences); @@ -207,27 +207,27 @@ void CFPreferencesFlushCaches(void) { } CFDictionaryGetKeysAndValues(__CFStandardUserPreferences, NULL, (const void **)prefsArray); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); // DeallocateApplicationPreferences needs the lock for (idx = 0; idx < count; idx ++) { _CFApplicationPreferences *appPrefs = prefsArray[idx]; _CFApplicationPreferencesSynchronize(appPrefs); _CFDeallocateApplicationPreferences(appPrefs); } - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); CFRelease(__CFStandardUserPreferences); __CFStandardUserPreferences = NULL; if(prefsArray != prefsBuf) CFAllocatorDeallocate(alloc, prefsArray); } - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); _CFPreferencesPurgeDomainCache(); } // quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain. void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain) { CFAllocatorRef alloc = __CFPreferencesAllocator(); - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if(__CFStandardUserPreferences) { // only grovel over the prefs if there's something there to grovel _CFApplicationPreferences **prefsArray, *prefsBuf[32]; CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences); @@ -246,7 +246,7 @@ void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDom } if(prefsArray != prefsBuf) _CFAllocatorDeallocateGC(alloc, prefsArray); } - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } @@ -296,9 +296,9 @@ CFTypeRef _CFApplicationPreferencesSearchDownToDomain(_CFApplicationPreferences void _CFApplicationPreferencesUpdate(_CFApplicationPreferences *self) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); updateDictRep(self); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } CF_EXPORT CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences *self); @@ -312,7 +312,7 @@ CF_PRIVATE CFDictionaryRef __CFApplicationPreferencesCopyCurrentState(void) { // CACHING here - we will only return a value as current as the last time computeDictRep() was called static CFTypeRef _CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences *self, CFStringRef defaultName) { CFTypeRef result; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (!self->_dictRep) { self->_dictRep = computeDictRep(self, true); } @@ -320,7 +320,7 @@ static CFTypeRef _CFApplicationPreferencesCreateValueForKey2(_CFApplicationPrefe if (result) { CFRetain(result); } - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); return result; } @@ -328,7 +328,7 @@ static CFTypeRef _CFApplicationPreferencesCreateValueForKey2(_CFApplicationPrefe void _CFApplicationPreferencesSet(_CFApplicationPreferences *self, CFStringRef defaultName, CFTypeRef value) { CFPreferencesDomainRef applicationDomain; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); applicationDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if(applicationDomain) { _CFPreferencesDomainSet(applicationDomain, defaultName, value); @@ -337,13 +337,13 @@ void _CFApplicationPreferencesSet(_CFApplicationPreferences *self, CFStringRef d updateDictRep(self); } } - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } void _CFApplicationPreferencesRemove(_CFApplicationPreferences *self, CFStringRef defaultName) { CFPreferencesDomainRef appDomain; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); appDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if(appDomain) { _CFPreferencesDomainSet(appDomain, defaultName, NULL); @@ -352,7 +352,7 @@ void _CFApplicationPreferencesRemove(_CFApplicationPreferences *self, CFStringRe updateDictRep(self); } } - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } static Boolean _CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences *self) { @@ -363,9 +363,9 @@ static Boolean _CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferen Boolean _CFApplicationPreferencesSynchronize(_CFApplicationPreferences *self) { Boolean result; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); result = _CFApplicationPreferencesSynchronizeNoLock(self); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); return result; } @@ -439,37 +439,37 @@ void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences *a CF_PRIVATE _CFApplicationPreferences *_CFStandardApplicationPreferences(CFStringRef appName) { _CFApplicationPreferences *appPreferences; // CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication"); - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (!__CFStandardUserPreferences) { __CFStandardUserPreferences = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, & kCFTypeDictionaryKeyCallBacks, NULL); } if (!__CFStandardUserPreferences) { // Couldn't create - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); return NULL; } if ((appPreferences = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName)) == NULL ) { appPreferences = _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser, appName); CFDictionarySetValue(__CFStandardUserPreferences, appName, appPreferences); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); _CFApplicationPreferencesSetStandardSearchList(appPreferences); } else { - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } return appPreferences; } // Exclusively for Foundation's use void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences *appPrefs, CFStringRef appName) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (!__CFStandardUserPreferences) { __CFStandardUserPreferences = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } else { _CFApplicationPreferences *oldPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName); CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); if (oldPrefs) { _CFDeallocateApplicationPreferences(oldPrefs); } @@ -480,7 +480,7 @@ void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences *appPrefs void _CFDeallocateApplicationPreferences(_CFApplicationPreferences *self) { CFAllocatorRef alloc = __CFPreferencesAllocator(); _CFApplicationPreferences *cachedPrefs = NULL; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); // Get us out of the cache before destroying! if (__CFStandardUserPreferences) { @@ -494,14 +494,14 @@ void _CFDeallocateApplicationPreferences(_CFApplicationPreferences *self) { CFRelease(self->_search); CFRelease(self->_appName); CFAllocatorDeallocate(alloc, self); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } CF_EXPORT CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences *self) { CFDictionaryRef dict; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (!self->_dictRep) { self->_dictRep = computeDictRep(self, true); } @@ -509,20 +509,20 @@ CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPrefer CFRetain(self->_dictRep); } dict = self->_dictRep; - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); return dict; } static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences *self, CFArrayRef newSearchList) { CFIndex idx, count; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); CFArrayRemoveAllValues(self->_search); count = CFArrayGetCount(newSearchList); for (idx = 0; idx < count; idx ++) { CFArrayAppendValue(self->_search, CFArrayGetValueAtIndex(newSearchList, idx)); } updateDictRep(self); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } void CFPreferencesAddSuitePreferencesToApp(CFStringRef appName, CFStringRef suiteName) { @@ -538,25 +538,25 @@ void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences *app CFRange range; // Find where to insert the new suite - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(appPrefs->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); range.location = 0; range.length = CFArrayGetCount(appPrefs->_search); idx = domain ? CFArrayGetFirstIndexOfValue(appPrefs->_search, range, domain) : kCFNotFound; - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); idx ++; // We want just below the app domain. Coincidentally, this gives us the top of the list if the app domain has been removed. domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if (domain) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); range.length ++; } domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); if (domain) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); range.length ++; } @@ -580,19 +580,19 @@ void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences *app idx ++; domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesAnyHost); if (domain) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if (domain) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); CFArrayInsertValueAtIndex(appPrefs->_search, idx, domain); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); updateDictRep(appPrefs); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName, CFStringRef suiteName) { @@ -606,36 +606,36 @@ void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName, CFStringRef void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences *appPrefs, CFStringRef suiteName) { CFPreferencesDomainRef domain; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesAnyHost); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); } void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain, Boolean addAtTop) { - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); if (addAtTop) { CFArrayInsertValueAtIndex(self->_search, 0, domain); } else { CFArrayAppendValue(self->_search, domain); } updateDictRep(self); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } Boolean _CFApplicationPreferencesContainsDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) { @@ -645,9 +645,9 @@ Boolean _CFApplicationPreferencesContainsDomain(_CFApplicationPreferences *self, return false; } - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); result = CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), domain); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); return result; } @@ -660,7 +660,7 @@ Boolean _CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) { CFIndex idx; CFRange range; - __CFSpinLock(&__CFApplicationPreferencesLock); + __CFLock(&__CFApplicationPreferencesLock); range.location = 0; range.length = CFArrayGetCount(self->_search); while ((idx = CFArrayGetFirstIndexOfValue(self->_search, range, domain)) != kCFNotFound) { @@ -669,5 +669,5 @@ void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPr range.length = range.length - idx - 1; } updateDictRep(self); - __CFSpinUnlock(&__CFApplicationPreferencesLock); + __CFUnlock(&__CFApplicationPreferencesLock); } diff --git a/CFArray.c b/CFArray.c index e5ab952..ae20352 100644 --- a/CFArray.c +++ b/CFArray.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFArray.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -91,10 +91,11 @@ CF_INLINE bool isWeakMemory(CFTypeRef collection) { CF_INLINE bool hasBeenFinalized(CFTypeRef collection) { return __CFBitfieldGetValue(((const CFRuntimeBase *)collection)->_cfinfo[CF_INFO_BITS], 5, 5) != 0; } - +#if DEPLOYMENT_TARGET_MACOSX CF_INLINE void markFinalized(CFTypeRef collection) { __CFBitfieldSetValue(((CFRuntimeBase *)collection)->_cfinfo[CF_INFO_BITS], 5, 5, 1); } +#endif CF_INLINE CFIndex __CFArrayGetType(CFArrayRef array) { return __CFBitfieldGetValue(((const CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS], 1, 0); @@ -355,11 +356,9 @@ static const CFRuntimeClass __CFArrayClass = { __CFArrayCopyDescription }; -CF_PRIVATE void __CFArrayInitialize(void) { - __kCFArrayTypeID = _CFRuntimeRegisterClass(&__CFArrayClass); -} - CFTypeID CFArrayGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFArrayTypeID = _CFRuntimeRegisterClass(&__CFArrayClass); }); return __kCFArrayTypeID; } @@ -387,7 +386,7 @@ static CFArrayRef __CFArrayInit(CFAllocatorRef allocator, UInt32 flags, CFIndex case __kCFArrayDeque: break; } - memory = (struct __CFArray*)_CFRuntimeCreateInstance(allocator, __kCFArrayTypeID, size, NULL); + memory = (struct __CFArray*)_CFRuntimeCreateInstance(allocator, CFArrayGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -425,7 +424,7 @@ CF_PRIVATE CFArrayRef __CFArrayCreateTransfer(CFAllocatorRef allocator, const vo __CFBitfieldSetValue(flags, 3, 2, __kCFArrayHasCFTypeCallBacks); UInt32 size = __CFArrayGetSizeOfType(flags) - sizeof(CFRuntimeBase); size += numValues * sizeof(struct __CFArrayBucket); - struct __CFArray *memory = (struct __CFArray*)_CFRuntimeCreateInstance(allocator, __kCFArrayTypeID, size, NULL); + struct __CFArray *memory = (struct __CFArray*)_CFRuntimeCreateInstance(allocator, CFArrayGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -481,7 +480,7 @@ CF_PRIVATE CFArrayRef __CFArrayCreateCopy0(CFAllocatorRef allocator, CFArrayRef void* bucketsBase; CFIndex numValues = CFArrayGetCount(array); CFIndex idx; - if (CF_IS_OBJC(__kCFArrayTypeID, array)) { + if (CF_IS_OBJC(CFArrayGetTypeID(), array)) { cb = &kCFTypeArrayCallBacks; } else { cb = __CFArrayGetCallBacks(array); @@ -508,7 +507,7 @@ CF_PRIVATE CFMutableArrayRef __CFArrayCreateMutableCopy0(CFAllocatorRef allocato const CFArrayCallBacks *cb; CFIndex idx, numValues = CFArrayGetCount(array); UInt32 flags; - if (CF_IS_OBJC(__kCFArrayTypeID, array)) { + if (CF_IS_OBJC(CFArrayGetTypeID(), array)) { cb = &kCFTypeArrayCallBacks; } else { @@ -547,8 +546,8 @@ CFMutableArrayRef CFArrayCreateMutableCopy(CFAllocatorRef allocator, CFIndex cap #endif CFIndex CFArrayGetCount(CFArrayRef array) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, CFIndex, (NSArray *)array, count); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), CFIndex, (NSArray *)array, count); + __CFGenericValidateType(array, CFArrayGetTypeID()); CHECK_FOR_MUTATION(array); return __CFArrayGetCount(array); } @@ -556,7 +555,7 @@ CFIndex CFArrayGetCount(CFArrayRef array) { CFIndex CFArrayGetCountOfValue(CFArrayRef array, CFRange range, const void *value) { CFIndex idx, count = 0; - __CFGenericValidateType(array, __kCFArrayTypeID); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); const CFArrayCallBacks *cb = CF_IS_OBJC(CFArrayGetTypeID(), array) ? &kCFTypeArrayCallBacks : __CFArrayGetCallBacks(array); @@ -571,7 +570,7 @@ CFIndex CFArrayGetCountOfValue(CFArrayRef array, CFRange range, const void *valu Boolean CFArrayContainsValue(CFArrayRef array, CFRange range, const void *value) { CFIndex idx; - __CFGenericValidateType(array, __kCFArrayTypeID); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); const CFArrayCallBacks *cb = CF_IS_OBJC(CFArrayGetTypeID(), array) ? &kCFTypeArrayCallBacks : __CFArrayGetCallBacks(array); @@ -585,8 +584,8 @@ Boolean CFArrayContainsValue(CFArrayRef array, CFRange range, const void *value) } const void *CFArrayGetValueAtIndex(CFArrayRef array, CFIndex idx) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, const void *, (NSArray *)array, objectAtIndex:idx); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), const void *, (NSArray *)array, objectAtIndex:idx); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CHECK_FOR_MUTATION(array); return __CFArrayGetBucketAtIndex(array, idx)->_item; @@ -601,8 +600,8 @@ const void *_CFArrayCheckAndGetValueAtIndex(CFArrayRef array, CFIndex idx) { void CFArrayGetValues(CFArrayRef array, CFRange range, const void **values) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSArray *)array, getObjects:(id *)values range:NSMakeRange(range.location, range.length)); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSArray *)array, getObjects:(id *)values range:NSMakeRange(range.location, range.length)); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CFAssert1(NULL != values, __kCFLogAssertion, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); @@ -646,7 +645,7 @@ CF_EXPORT unsigned long _CFArrayFastEnumeration(CFArrayRef array, struct __objcF void CFArrayApplyFunction(CFArrayRef array, CFRange range, CFArrayApplierFunction applier, void *context) { CFIndex idx; FAULT_CALLBACK((void **)&(applier)); - __CFGenericValidateType(array, __kCFArrayTypeID); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CFAssert1(NULL != applier, __kCFLogAssertion, "%s(): pointer to applier function may not be NULL", __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); @@ -658,7 +657,7 @@ void CFArrayApplyFunction(CFArrayRef array, CFRange range, CFArrayApplierFunctio CFIndex CFArrayGetFirstIndexOfValue(CFArrayRef array, CFRange range, const void *value) { CFIndex idx; - __CFGenericValidateType(array, __kCFArrayTypeID); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); const CFArrayCallBacks *cb = CF_IS_OBJC(CFArrayGetTypeID(), array) ? &kCFTypeArrayCallBacks : __CFArrayGetCallBacks(array); @@ -672,7 +671,7 @@ CFIndex CFArrayGetFirstIndexOfValue(CFArrayRef array, CFRange range, const void CFIndex CFArrayGetLastIndexOfValue(CFArrayRef array, CFRange range, const void *value) { CFIndex idx; - __CFGenericValidateType(array, __kCFArrayTypeID); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); const CFArrayCallBacks *cb = CF_IS_OBJC(CFArrayGetTypeID(), array) ? &kCFTypeArrayCallBacks : __CFArrayGetCallBacks(array); @@ -685,17 +684,17 @@ CFIndex CFArrayGetLastIndexOfValue(CFArrayRef array, CFRange range, const void * } void CFArrayAppendValue(CFMutableArrayRef array, const void *value) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, addObject:(id)value); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, addObject:(id)value); - __CFGenericValidateType(array, __kCFArrayTypeID); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); _CFArrayReplaceValues(array, CFRangeMake(__CFArrayGetCount(array), 0), &value, 1); } void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, setObject:(id)value atIndex:(NSUInteger)idx); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, setObject:(id)value atIndex:(NSUInteger)idx); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CHECK_FOR_MUTATION(array); @@ -721,8 +720,8 @@ void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *va } void CFArrayInsertValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, insertObject:(id)value atIndex:(NSUInteger)idx); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, insertObject:(id)value atIndex:(NSUInteger)idx); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CHECK_FOR_MUTATION(array); @@ -734,8 +733,8 @@ void CFArrayInsertValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void void CFArrayExchangeValuesAtIndices(CFMutableArrayRef array, CFIndex idx1, CFIndex idx2) { const void *tmp; struct __CFArrayBucket *bucket1, *bucket2; - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert2(0 <= idx1 && idx1 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #1 (%d) out of bounds", __PRETTY_FUNCTION__, idx1); CFAssert2(0 <= idx2 && idx2 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #2 (%d) out of bounds", __PRETTY_FUNCTION__, idx2); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); @@ -752,8 +751,8 @@ void CFArrayExchangeValuesAtIndices(CFMutableArrayRef array, CFIndex idx1, CFInd } void CFArrayRemoveValueAtIndex(CFMutableArrayRef array, CFIndex idx) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, removeObjectAtIndex:(NSUInteger)idx); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, removeObjectAtIndex:(NSUInteger)idx); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CHECK_FOR_MUTATION(array); @@ -761,8 +760,8 @@ void CFArrayRemoveValueAtIndex(CFMutableArrayRef array, CFIndex idx) { } void CFArrayRemoveAllValues(CFMutableArrayRef array) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, removeAllObjects); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, removeAllObjects); + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CHECK_FOR_MUTATION(array); BEGIN_MUTATION(array); @@ -870,8 +869,8 @@ static void __CFArrayHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) { // This function is for Foundation's benefit; no one else should use it. void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) { - if (CF_IS_OBJC(__kCFArrayTypeID, array)) return; - __CFGenericValidateType(array, __kCFArrayTypeID); + if (CF_IS_OBJC(CFArrayGetTypeID(), array)) return; + __CFGenericValidateType(array, CFArrayGetTypeID()); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert3(__CFArrayGetCount(array) <= cap, __kCFLogAssertion, "%s(): desired capacity (%d) is less than count (%d)", __PRETTY_FUNCTION__, cap, __CFArrayGetCount(array)); CHECK_FOR_MUTATION(array); @@ -909,8 +908,8 @@ void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) { void CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **newValues, CFIndex newCount) { - CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, replaceObjectsInRange:NSMakeRange(range.location, range.length) withObjects:(id *)newValues count:(NSUInteger)newCount); - __CFGenericValidateType(array, __kCFArrayTypeID); + CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID(), void, (NSMutableArray *)array, replaceObjectsInRange:NSMakeRange(range.location, range.length) withObjects:(id *)newValues count:(NSUInteger)newCount); + __CFGenericValidateType(array, CFArrayGetTypeID()); __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__); CFAssert2(0 <= newCount, __kCFLogAssertion, "%s(): newCount (%d) cannot be less than zero", __PRETTY_FUNCTION__, newCount); @@ -1040,7 +1039,7 @@ void CFArraySortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunct __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__); CFAssert1(NULL != comparator, __kCFLogAssertion, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__); Boolean immutable = false; - if (CF_IS_OBJC(__kCFArrayTypeID, array)) { + if (CF_IS_OBJC(CFArrayGetTypeID(), array)) { BOOL result; result = CF_OBJC_CALLV((NSMutableArray *)array, isKindOfClass:[NSMutableArray class]); immutable = !result; @@ -1048,7 +1047,7 @@ void CFArraySortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunct immutable = true; } const CFArrayCallBacks *cb = NULL; - if (CF_IS_OBJC(__kCFArrayTypeID, array)) { + if (CF_IS_OBJC(CFArrayGetTypeID(), array)) { cb = &kCFTypeArrayCallBacks; } else { cb = __CFArrayGetCallBacks(array); diff --git a/CFArray.h b/CFArray.h index b5fdd36..6637cea 100644 --- a/CFArray.h +++ b/CFArray.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFArray.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /*! @@ -128,13 +128,13 @@ typedef void (*CFArrayApplierFunction)(const void *value, void *context); @typedef CFArrayRef This is the type of a reference to immutable CFArrays. */ -typedef const struct __CFArray * CFArrayRef; +typedef const struct CF_BRIDGED_TYPE(NSArray) __CFArray * CFArrayRef; /*! @typedef CFMutableArrayRef This is the type of a reference to mutable CFArrays. */ -typedef struct __CFArray * CFMutableArrayRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMutableArray) __CFArray * CFMutableArrayRef; /*! @function CFArrayGetTypeID diff --git a/CFAvailability.h b/CFAvailability.h index 25042bf..264774b 100644 --- a/CFAvailability.h +++ b/CFAvailability.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,22 +17,22 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFAvailability.h - Copyright (c) 2013-2013, Apple Inc. All rights reserved. + Copyright (c) 2013-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFAVAILABILITY__) #define __COREFOUNDATION_CFAVAILABILITY__ 1 #include +#include #if (TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32) // Even if unused, these must remain here for compatibility, because projects rely on them being included. -#include #include #endif @@ -65,8 +65,11 @@ #define __NSi_6_0 introduced=6.0 #define __NSi_6_1 introduced=6.1 #define __NSi_7_0 introduced=7.0 +#define __NSi_7_1 introduced=7.1 #define __NSi_8_0 introduced=8.0 +#define __NSi_8_1 introduced=8.1 #define __NSi_9_0 introduced=9.0 +#define __NSi_9_1 introduced=9.1 #define __NSi_10_0 introduced=10.0 #define __NSi_10_1 introduced=10.1 #define __NSi_10_2 introduced=10.2 @@ -77,6 +80,7 @@ #define __NSi_10_7 introduced=10.7 #define __NSi_10_8 introduced=10.8 #define __NSi_10_9 introduced=10.9 +#define __NSi_10_10 introduced=10.10 #define __NSd_2_0 ,deprecated=2.0 #define __NSd_2_1 ,deprecated=2.1 @@ -93,8 +97,11 @@ #define __NSd_6_0 ,deprecated=6.0 #define __NSd_6_1 ,deprecated=6.1 #define __NSd_7_0 ,deprecated=7.0 +#define __NSd_7_1 ,deprecated=7.1 #define __NSd_8_0 ,deprecated=8.0 +#define __NSd_8_1 ,deprecated=8.1 #define __NSd_9_0 ,deprecated=9.0 +#define __NSd_9_1 ,deprecated=9.1 #define __NSd_10_0 ,deprecated=10.0 #define __NSd_10_1 ,deprecated=10.1 #define __NSd_10_2 ,deprecated=10.2 @@ -105,6 +112,7 @@ #define __NSd_10_7 ,deprecated=10.7 #define __NSd_10_8 ,deprecated=10.8 #define __NSd_10_9 ,deprecated=10.9 +#define __NSd_10_10 ,deprecated=10.10 #define __NSi_NA unavailable #define __NSd_NA @@ -194,4 +202,9 @@ #define CF_OPTIONS(_type, _name) _type _name; enum #endif +// Extension availability macros +#define CF_EXTENSION_UNAVAILABLE(_msg) __OS_EXTENSION_UNAVAILABLE(_msg) +#define CF_EXTENSION_UNAVAILABLE_MAC(_msg) __OSX_EXTENSION_UNAVAILABLE(_msg) +#define CF_EXTENSION_UNAVAILABLE_IOS(_msg) __IOS_EXTENSION_UNAVAILABLE(_msg) + #endif // __COREFOUNDATION_CFAVAILABILITY__ diff --git a/CFBag.c b/CFBag.c index 629f927..140da78 100644 --- a/CFBag.c +++ b/CFBag.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBag.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane Machine generated from Notes/HashingCode.template */ @@ -47,8 +47,6 @@ const CFBagKeyCallBacks kCFTypeBagKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFBagKeyCallBacks kCFCopyStringBagKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFBagValueCallBacks kCFTypeBagValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; -static const CFBagKeyCallBacks __kCFNullBagKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; -static const CFBagValueCallBacks __kCFNullBagValueCallBacks = {0, NULL, NULL, NULL, NULL}; #define CFHashRef CFDictionaryRef #define CFMutableHashRef CFMutableDictionaryRef @@ -59,14 +57,11 @@ static const CFBagValueCallBacks __kCFNullBagValueCallBacks = {0, NULL, NULL, NU #if CFSet const CFBagCallBacks kCFTypeBagCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFBagCallBacks kCFCopyStringBagCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; -static const CFBagCallBacks __kCFNullBagCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; #define CFBagKeyCallBacks CFBagCallBacks #define CFBagValueCallBacks CFBagCallBacks #define kCFTypeBagKeyCallBacks kCFTypeBagCallBacks #define kCFTypeBagValueCallBacks kCFTypeBagCallBacks -#define __kCFNullBagKeyCallBacks __kCFNullBagCallBacks -#define __kCFNullBagValueCallBacks __kCFNullBagCallBacks #define CFHashRef CFSetRef #define CFMutableHashRef CFMutableSetRef @@ -77,14 +72,11 @@ static const CFBagCallBacks __kCFNullBagCallBacks = {0, NULL, NULL, NULL, NULL, #if CFBag const CFBagCallBacks kCFTypeBagCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFBagCallBacks kCFCopyStringBagCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; -static const CFBagCallBacks __kCFNullBagCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; #define CFBagKeyCallBacks CFBagCallBacks #define CFBagValueCallBacks CFBagCallBacks #define kCFTypeBagKeyCallBacks kCFTypeBagCallBacks #define kCFTypeBagValueCallBacks kCFTypeBagCallBacks -#define __kCFNullBagKeyCallBacks __kCFNullBagCallBacks -#define __kCFNullBagValueCallBacks __kCFNullBagCallBacks #define CFHashRef CFBagRef #define CFMutableHashRef CFMutableBagRef @@ -128,7 +120,8 @@ static const CFRuntimeClass __CFBagClass = { }; CFTypeID CFBagGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFBagTypeID) __kCFBagTypeID = _CFRuntimeRegisterClass(&__CFBagClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFBagTypeID = _CFRuntimeRegisterClass(&__CFBagClass); }); return __kCFBagTypeID; } @@ -368,9 +361,13 @@ CFMutableHashRef CFBagCreateMutableCopy(CFAllocatorRef allocator, CFIndex capaci } CFIndex CFBagGetCount(CFHashRef hc) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSDictionary *)hc, count); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSSet *)hc, count); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSDictionary *)hc, count); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSSet *)hc, count); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); return CFBasicHashGetCount((CFBasicHashRef)hc); } @@ -380,9 +377,13 @@ CFIndex CFBagGetCountOfKey(CFHashRef hc, const_any_pointer_t key) { #if CFSet || CFBag CFIndex CFBagGetCountOfValue(CFHashRef hc, const_any_pointer_t key) { #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSDictionary *)hc, countForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSSet *)hc, countForObject:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key); } @@ -392,24 +393,36 @@ Boolean CFBagContainsKey(CFHashRef hc, const_any_pointer_t key) { #if CFSet || CFBag Boolean CFBagContainsValue(CFHashRef hc, const_any_pointer_t key) { #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, char, (NSDictionary *)hc, containsKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, char, (NSSet *)hc, containsObject:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), char, (NSDictionary *)hc, containsKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), char, (NSSet *)hc, containsObject:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key)); } const_any_pointer_t CFBagGetValue(CFHashRef hc, const_any_pointer_t key) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), const_any_pointer_t, (NSSet *)hc, member:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0); } Boolean CFBagGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); if (0 < bkt.count) { if (value) { @@ -426,19 +439,19 @@ Boolean CFBagGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_ #if CFDictionary CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) { - CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value); - __CFGenericValidateType(hc, __kCFBagTypeID); + CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), CFIndex, (NSDictionary *)hc, countForObject:(id)value); + __CFGenericValidateType(hc, CFBagGetTypeID()); return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value); } Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) { - CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, char, (NSDictionary *)hc, containsObject:(id)value); - __CFGenericValidateType(hc, __kCFBagTypeID); + CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), char, (NSDictionary *)hc, containsObject:(id)value); + __CFGenericValidateType(hc, CFBagGetTypeID()); return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value)); } CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) { - __CFGenericValidateType(hc, __kCFBagTypeID); + __CFGenericValidateType(hc, CFBagGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); if (0 < bkt.count) { if (actualkey) { @@ -461,9 +474,13 @@ void CFBagGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_ void CFBagGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { const_any_pointer_t *valuebuf = 0; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSSet *)hc, getObjects:(id *)keybuf); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); if (kCFUseCollectableAllocator) { CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc); __block const_any_pointer_t *keys = keybuf; @@ -484,9 +501,13 @@ void CFBagGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { void CFBagApplyFunction(CFHashRef hc, CFBagApplierFunction applier, any_pointer_t context) { FAULT_CALLBACK((void **)&(applier)); - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) { #if CFDictionary INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context); @@ -505,22 +526,22 @@ void CFBagApplyFunction(CFHashRef hc, CFBagApplierFunction applier, any_pointer_ // This function is for Foundation's benefit; no one else should use it. CF_EXPORT unsigned long _CFBagFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) { - if (CF_IS_OBJC(__kCFBagTypeID, hc)) return 0; - __CFGenericValidateType(hc, __kCFBagTypeID); + if (CF_IS_OBJC(CFBagGetTypeID(), hc)) return 0; + __CFGenericValidateType(hc, CFBagGetTypeID()); return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count); } // This function is for Foundation's benefit; no one else should use it. CF_EXPORT Boolean _CFBagIsMutable(CFHashRef hc) { - if (CF_IS_OBJC(__kCFBagTypeID, hc)) return false; - __CFGenericValidateType(hc, __kCFBagTypeID); + if (CF_IS_OBJC(CFBagGetTypeID(), hc)) return false; + __CFGenericValidateType(hc, CFBagGetTypeID()); return CFBasicHashIsMutable((CFBasicHashRef)hc); } // This function is for Foundation's benefit; no one else should use it. CF_EXPORT void _CFBagSetCapacity(CFMutableHashRef hc, CFIndex cap) { - if (CF_IS_OBJC(__kCFBagTypeID, hc)) return; - __CFGenericValidateType(hc, __kCFBagTypeID); + if (CF_IS_OBJC(CFBagGetTypeID(), hc)) return; + __CFGenericValidateType(hc, CFBagGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); CFAssert3(CFBagGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFBagGetCount(hc)); CFBasicHashSetCapacity((CFBasicHashRef)hc, cap); @@ -559,9 +580,13 @@ void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_point void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, addObject:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, addObject:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -578,9 +603,13 @@ void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_p void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, replaceObject:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -597,9 +626,13 @@ void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_point void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, setObject:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, setObject:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -611,9 +644,13 @@ void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key) { } void CFBagRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, removeObject:(id)key); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, removeObject:(id)key); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -624,9 +661,13 @@ void CFBagRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { } void CFBagRemoveAllValues(CFMutableHashRef hc) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, removeAllObjects); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, removeAllObjects); - __CFGenericValidateType(hc, __kCFBagTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableDictionary *)hc, removeAllObjects); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFBagGetTypeID(), void, (NSMutableSet *)hc, removeAllObjects); +#endif + __CFGenericValidateType(hc, CFBagGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); diff --git a/CFBag.h b/CFBag.h index 53803f9..1014473 100644 --- a/CFBag.h +++ b/CFBag.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBag.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBAG__) diff --git a/CFBase.c b/CFBase.c index 6398d06..03ab6f3 100644 --- a/CFBase.c +++ b/CFBase.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBase.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -452,25 +452,28 @@ static void _CFAllocatorSetInstanceTypeIDAndIsa(struct __CFAllocator *memory) { } CF_PRIVATE void __CFAllocatorInitialize(void) { - __kCFAllocatorTypeID = _CFRuntimeRegisterClass(&__CFAllocatorClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFAllocatorTypeID = _CFRuntimeRegisterClass(&__CFAllocatorClass); // initOnce covered - _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault); + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - __kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? objc_collectableZone() : malloc_default_zone()); + __kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? objc_collectableZone() : malloc_default_zone()); #endif - __kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault; + __kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault; - _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc); - __kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault; + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc); + __kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone); - __kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault; - __kCFAllocatorMallocZone._context.info = malloc_default_zone(); + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone); + __kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault; + __kCFAllocatorMallocZone._context.info = malloc_default_zone(); #endif - _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull); - __kCFAllocatorNull._allocator = kCFAllocatorSystemDefault; + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull); + __kCFAllocatorNull._allocator = kCFAllocatorSystemDefault; + }); } CFTypeID CFAllocatorGetTypeID(void) { @@ -856,12 +859,12 @@ static const CFRuntimeClass __CFNullClass = { __CFNullCopyDescription }; -CF_PRIVATE void __CFNullInitialize(void) { - __kCFNullTypeID = _CFRuntimeRegisterClass(&__CFNullClass); - _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull, __kCFNullTypeID); -} - CFTypeID CFNullGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFNullTypeID = _CFRuntimeRegisterClass(&__CFNullClass); // initOnce covered + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull, __kCFNullTypeID); + }); return __kCFNullTypeID; } diff --git a/CFBase.h b/CFBase.h index ffddd2b..0d304d0 100644 --- a/CFBase.h +++ b/CFBase.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBase.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBASE__) @@ -249,6 +249,35 @@ CF_EXTERN_C_BEGIN #endif #endif +#if __has_attribute(objc_bridge) + +#ifdef __OBJC__ +@class NSArray; +@class NSAttributedString; +@class NSString; +@class NSNull; +@class NSCharacterSet; +@class NSData; +@class NSDate; +@class NSTimeZone; +@class NSDictionary; +@class NSError; +@class NSLocale; +@class NSNumber; +@class NSNumber; +@class NSSet; +@class NSURL; +#endif + +#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T))) +#define CF_BRIDGED_MUTABLE_TYPE(T) __attribute__((objc_bridge_mutable(T))) +#define CF_RELATED_TYPE(T,C,I) __attribute__((objc_bridge_related(T,C,I))) +#else +#define CF_BRIDGED_TYPE(T) +#define CF_BRIDGED_MUTABLE_TYPE(T) +#define CF_RELATED_TYPE(T,C,I) +#endif + CF_EXPORT double kCFCoreFoundationVersionNumber; @@ -324,10 +353,13 @@ CF_EXPORT double kCFCoreFoundationVersionNumber; #define kCFCoreFoundationVersionNumber10_8_2 744.12 #define kCFCoreFoundationVersionNumber10_8_3 744.18 #define kCFCoreFoundationVersionNumber10_8_4 744.19 +#define kCFCoreFoundationVersionNumber10_9 855.11 +#define kCFCoreFoundationVersionNumber10_9_1 855.11 +#define kCFCoreFoundationVersionNumber10_9_2 855.14 #endif #if TARGET_OS_IPHONE -#define kCFCoreFoundationVersionNumber_iPhoneOS_2_0 478.23 +#define kCFCoreFoundationVersionNumber_iPhoneOS_2_0 478.23 #define kCFCoreFoundationVersionNumber_iPhoneOS_2_1 478.26 #define kCFCoreFoundationVersionNumber_iPhoneOS_2_2 478.29 #define kCFCoreFoundationVersionNumber_iPhoneOS_3_0 478.47 @@ -341,6 +373,8 @@ CF_EXPORT double kCFCoreFoundationVersionNumber; #define kCFCoreFoundationVersionNumber_iOS_5_1 690.10 #define kCFCoreFoundationVersionNumber_iOS_6_0 793.00 #define kCFCoreFoundationVersionNumber_iOS_6_1 793.00 +#define kCFCoreFoundationVersionNumber_iOS_7_0 847.20 +#define kCFCoreFoundationVersionNumber_iOS_7_1 847.24 #endif #if __LLP64__ @@ -358,8 +392,8 @@ typedef signed long CFIndex; /* Base "type" of all "CF objects", and polymorphic functions on them */ typedef const void * CFTypeRef; -typedef const struct __CFString * CFStringRef; -typedef struct __CFString * CFMutableStringRef; +typedef const struct CF_BRIDGED_TYPE(NSString) __CFString * CFStringRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMutableString) __CFString * CFMutableStringRef; /* Type to mean any instance of a property list type; @@ -409,7 +443,7 @@ CFRange __CFRangeMake(CFIndex loc, CFIndex len); /* Null representant */ -typedef const struct __CFNull * CFNullRef; +typedef const struct CF_BRIDGED_TYPE(NSNull) __CFNull * CFNullRef; CF_EXPORT CFTypeID CFNullGetTypeID(void); diff --git a/CFBasicHash.c b/CFBasicHash.c index 3222c96..66b191b 100644 --- a/CFBasicHash.c +++ b/CFBasicHash.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBasicHash.m - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -391,22 +391,6 @@ CF_PRIVATE Boolean CFBasicHashHasStrongKeys(CFConstBasicHashRef ht) { #endif } -CF_INLINE Boolean __CFBasicHashHasWeakValues(CFConstBasicHashRef ht) { -#if DEPLOYMENT_TARGET_MACOSX - return ht->bits.weak_values ? true : false; -#else - return false; -#endif -} - -CF_INLINE Boolean __CFBasicHashHasWeakKeys(CFConstBasicHashRef ht) { -#if DEPLOYMENT_TARGET_MACOSX - return ht->bits.weak_keys ? true : false; -#else - return false; -#endif -} - CF_INLINE Boolean __CFBasicHashHasHashCache(CFConstBasicHashRef ht) { #if DEPLOYMENT_TARGET_MACOSX return ht->bits.hashes_offset ? true : false; @@ -1591,7 +1575,8 @@ static const CFRuntimeClass __CFBasicHashClass = { }; CF_PRIVATE CFTypeID CFBasicHashGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFBasicHashTypeID) __kCFBasicHashTypeID = _CFRuntimeRegisterClass(&__CFBasicHashClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFBasicHashTypeID = _CFRuntimeRegisterClass(&__CFBasicHashClass); }); return __kCFBasicHashTypeID; } diff --git a/CFBasicHash.h b/CFBasicHash.h index 5da451b..40053cb 100644 --- a/CFBasicHash.h +++ b/CFBasicHash.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBasicHash.h - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. */ #include diff --git a/CFBasicHashFindBucket.m b/CFBasicHashFindBucket.m index 6cd272c..e209d7b 100644 --- a/CFBasicHashFindBucket.m +++ b/CFBasicHashFindBucket.m @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBasicHashFindBucket.m - Copyright (c) 2009-2013, Apple Inc. All rights reserved. + Copyright (c) 2009-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ diff --git a/CFBigNumber.c b/CFBigNumber.c index 3ae50ae..fdeb526 100644 --- a/CFBigNumber.c +++ b/CFBigNumber.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBigNumber.c - Copyright (c) 2012-2013, Apple Inc. All rights reserved. + Copyright (c) 2012-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane Original author: Zhi Feng Huang */ @@ -554,6 +554,7 @@ void _CFBigNumFromCString(_CFBigNum *r, const char *string) { size_t length = strlen(working); if (length == 0) { // the number is zero + free(copy); return; } int curDigit = 0; diff --git a/CFBigNumber.h b/CFBigNumber.h index bc03391..67eaa1b 100644 --- a/CFBigNumber.h +++ b/CFBigNumber.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBigNumber.h - Copyright (c) 2012-2013, Apple Inc. All rights reserved. + Copyright (c) 2012-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBIGNUMBER__) diff --git a/CFBinaryHeap.c b/CFBinaryHeap.c index 7abafcf..949954e 100644 --- a/CFBinaryHeap.c +++ b/CFBinaryHeap.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBinaryHeap.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -96,10 +96,6 @@ CF_INLINE bool isStrongMemory_Heap(CFTypeRef collection) { return __CFBitfieldGetValue(((const CFRuntimeBase *)collection)->_cfinfo[CF_INFO_BITS], 4, 4) == 0; } -CF_INLINE bool isWeakMemory_Heap(CFTypeRef collection) { - return __CFBitfieldGetValue(((const CFRuntimeBase *)collection)->_cfinfo[CF_INFO_BITS], 4, 4) != 0; -} - CF_INLINE UInt32 __CFBinaryHeapMutableVariety(const void *cf) { return __CFBitfieldGetValue(((const CFRuntimeBase *)cf)->_cfinfo[CF_INFO_BITS], 3, 2); } @@ -207,11 +203,9 @@ static const CFRuntimeClass __CFBinaryHeapClass = { __CFBinaryHeapCopyDescription }; -CF_PRIVATE void __CFBinaryHeapInitialize(void) { - __kCFBinaryHeapTypeID = _CFRuntimeRegisterClass(&__CFBinaryHeapClass); -} - CFTypeID CFBinaryHeapGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFBinaryHeapTypeID = _CFRuntimeRegisterClass(&__CFBinaryHeapClass); }); return __kCFBinaryHeapTypeID; } @@ -229,7 +223,7 @@ static CFBinaryHeapRef __CFBinaryHeapInit(CFAllocatorRef allocator, UInt32 flags } } - memory = (CFBinaryHeapRef)_CFRuntimeCreateInstance(allocator, __kCFBinaryHeapTypeID, size, NULL); + memory = (CFBinaryHeapRef)_CFRuntimeCreateInstance(allocator, CFBinaryHeapGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -270,12 +264,12 @@ CFBinaryHeapRef CFBinaryHeapCreate(CFAllocatorRef allocator, CFIndex capacity, c } CFBinaryHeapRef CFBinaryHeapCreateCopy(CFAllocatorRef allocator, CFIndex capacity, CFBinaryHeapRef heap) { - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); return __CFBinaryHeapInit(allocator, kCFBinaryHeapMutable, capacity, (const void **)heap->_buckets, __CFBinaryHeapCount(heap), &(heap->_callbacks), &(heap->_context)); } CFIndex CFBinaryHeapGetCount(CFBinaryHeapRef heap) { - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); return __CFBinaryHeapCount(heap); } @@ -283,7 +277,7 @@ CFIndex CFBinaryHeapGetCountOfValue(CFBinaryHeapRef heap, const void *value) { CFComparisonResult (*compare)(const void *, const void *, void *); CFIndex idx; CFIndex cnt = 0, length; - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); compare = heap->_callbacks.compare; length = __CFBinaryHeapCount(heap); for (idx = 0; idx < length; idx++) { @@ -299,7 +293,7 @@ Boolean CFBinaryHeapContainsValue(CFBinaryHeapRef heap, const void *value) { CFComparisonResult (*compare)(const void *, const void *, void *); CFIndex idx; CFIndex length; - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); compare = heap->_callbacks.compare; length = __CFBinaryHeapCount(heap); for (idx = 0; idx < length; idx++) { @@ -312,13 +306,13 @@ Boolean CFBinaryHeapContainsValue(CFBinaryHeapRef heap, const void *value) { } const void *CFBinaryHeapGetMinimum(CFBinaryHeapRef heap) { - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); CFAssert1(0 < __CFBinaryHeapCount(heap), __kCFLogAssertion, "%s(): binary heap is empty", __PRETTY_FUNCTION__); return (0 < __CFBinaryHeapCount(heap)) ? heap->_buckets[0]._item : NULL; } Boolean CFBinaryHeapGetMinimumIfPresent(CFBinaryHeapRef heap, const void **value) { - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); if (0 == __CFBinaryHeapCount(heap)) return false; if (NULL != value) __CFAssignWithWriteBarrier((void **)value, heap->_buckets[0]._item); return true; @@ -328,7 +322,7 @@ void CFBinaryHeapGetValues(CFBinaryHeapRef heap, const void **values) { CFBinaryHeapRef heapCopy; CFIndex idx; CFIndex cnt; - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); CFAssert1(NULL != values, __kCFLogAssertion, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__); cnt = __CFBinaryHeapCount(heap); if (0 == cnt) return; @@ -345,7 +339,7 @@ void CFBinaryHeapGetValues(CFBinaryHeapRef heap, const void **values) { void CFBinaryHeapApplyFunction(CFBinaryHeapRef heap, CFBinaryHeapApplierFunction applier, void *context) { CFBinaryHeapRef heapCopy; CFIndex cnt; - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); CFAssert1(NULL != applier, __kCFLogAssertion, "%s(): pointer to applier function may not be NULL", __PRETTY_FUNCTION__); cnt = __CFBinaryHeapCount(heap); if (0 == cnt) return; @@ -374,7 +368,7 @@ void CFBinaryHeapAddValue(CFBinaryHeapRef heap, const void *value) { CFIndex idx, pidx; CFIndex cnt; CFAllocatorRef allocator = CFGetAllocator(heap); - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); switch (__CFBinaryHeapMutableVariety(heap)) { case kCFBinaryHeapMutable: if (__CFBinaryHeapNumBucketsUsed(heap) == __CFBinaryHeapCapacity(heap)) @@ -406,7 +400,7 @@ void CFBinaryHeapRemoveMinimumValue(CFBinaryHeapRef heap) { CFIndex idx, cidx; CFIndex cnt; CFAllocatorRef allocator; - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); cnt = __CFBinaryHeapCount(heap); if (0 == cnt) return; idx = 0; @@ -438,7 +432,7 @@ void CFBinaryHeapRemoveMinimumValue(CFBinaryHeapRef heap) { void CFBinaryHeapRemoveAllValues(CFBinaryHeapRef heap) { CFIndex idx; CFIndex cnt; - __CFGenericValidateType(heap, __kCFBinaryHeapTypeID); + __CFGenericValidateType(heap, CFBinaryHeapGetTypeID()); cnt = __CFBinaryHeapCount(heap); if (heap->_callbacks.release) for (idx = 0; idx < cnt; idx++) diff --git a/CFBinaryHeap.h b/CFBinaryHeap.h index 6881891..bdd318c 100644 --- a/CFBinaryHeap.h +++ b/CFBinaryHeap.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBinaryHeap.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /*! @header CFBinaryHeap diff --git a/CFBinaryPList.c b/CFBinaryPList.c index 9707cc9..026ec4d 100644 --- a/CFBinaryPList.c +++ b/CFBinaryPList.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBinaryPList.c - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -61,26 +61,12 @@ enum { CF_OVERFLOW_ERROR = (1 << 0), }; -CF_INLINE uint32_t __check_uint32_add_unsigned_unsigned(uint32_t x, uint32_t y, int32_t* err) { - if((UINT_MAX - y) < x) - *err = *err | CF_OVERFLOW_ERROR; - return x + y; -}; - CF_INLINE uint64_t __check_uint64_add_unsigned_unsigned(uint64_t x, uint64_t y, int32_t* err) { if((ULLONG_MAX - y) < x) *err = *err | CF_OVERFLOW_ERROR; return x + y; }; -CF_INLINE uint32_t __check_uint32_mul_unsigned_unsigned(uint32_t x, uint32_t y, int32_t* err) { - uint64_t tmp = (uint64_t) x * (uint64_t) y; - /* If any of the upper 32 bits touched, overflow */ - if(tmp & 0xffffffff00000000ULL) - *err = *err | CF_OVERFLOW_ERROR; - return (uint32_t) tmp; -}; - CF_INLINE uint64_t __check_uint64_mul_unsigned_unsigned(uint64_t x, uint64_t y, int32_t* err) { if(x == 0) return 0; if(ULLONG_MAX/x < y) @@ -92,6 +78,21 @@ CF_INLINE uint64_t __check_uint64_mul_unsigned_unsigned(uint64_t x, uint64_t y, #define check_ptr_add(p, a, err) (const uint8_t *)__check_uint64_add_unsigned_unsigned((uintptr_t)p, (uintptr_t)a, err) #define check_size_t_mul(b, a, err) (size_t)__check_uint64_mul_unsigned_unsigned((size_t)b, (size_t)a, err) #else + +CF_INLINE uint32_t __check_uint32_add_unsigned_unsigned(uint32_t x, uint32_t y, int32_t* err) { + if((UINT_MAX - y) < x) + *err = *err | CF_OVERFLOW_ERROR; + return x + y; +}; + +CF_INLINE uint32_t __check_uint32_mul_unsigned_unsigned(uint32_t x, uint32_t y, int32_t* err) { + uint64_t tmp = (uint64_t) x * (uint64_t) y; + /* If any of the upper 32 bits touched, overflow */ + if(tmp & 0xffffffff00000000ULL) + *err = *err | CF_OVERFLOW_ERROR; + return (uint32_t) tmp; +}; + #define check_ptr_add(p, a, err) (const uint8_t *)__check_uint32_add_unsigned_unsigned((uintptr_t)p, (uintptr_t)a, err) #define check_size_t_mul(b, a, err) (size_t)__check_uint32_mul_unsigned_unsigned((size_t)b, (size_t)a, err) #endif @@ -128,17 +129,15 @@ static const CFRuntimeClass __CFKeyedArchiverUIDClass = { __CFKeyedArchiverUIDCopyDescription }; -CF_PRIVATE void __CFKeyedArchiverUIDInitialize(void) { - __kCFKeyedArchiverUIDTypeID = _CFRuntimeRegisterClass(&__CFKeyedArchiverUIDClass); -} - CFTypeID _CFKeyedArchiverUIDGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFKeyedArchiverUIDTypeID = _CFRuntimeRegisterClass(&__CFKeyedArchiverUIDClass); }); return __kCFKeyedArchiverUIDTypeID; } CFKeyedArchiverUIDRef _CFKeyedArchiverUIDCreate(CFAllocatorRef allocator, uint32_t value) { CFKeyedArchiverUIDRef uid; - uid = (CFKeyedArchiverUIDRef)_CFRuntimeCreateInstance(allocator, __kCFKeyedArchiverUIDTypeID, sizeof(struct __CFKeyedArchiverUID) - sizeof(CFRuntimeBase), NULL); + uid = (CFKeyedArchiverUIDRef)_CFRuntimeCreateInstance(allocator, _CFKeyedArchiverUIDGetTypeID(), sizeof(struct __CFKeyedArchiverUID) - sizeof(CFRuntimeBase), NULL); if (NULL == uid) { return NULL; } @@ -168,10 +167,12 @@ typedef struct { } __CFBinaryPlistWriteBuffer; static void writeBytes(__CFBinaryPlistWriteBuffer *buf, const UInt8 *bytes, CFIndex length) { - if (0 == length) return; + if (length <= 0) return; if (buf->error) return; if (buf->databytes) { - if (buf->datalen < buf->written + length) { + int32_t err = CF_NO_ERROR; + uint64_t tmpSum = __check_uint64_add_unsigned_unsigned(buf->written, (uint64_t)length, &err); + if ((CF_NO_ERROR != err) || buf->datalen < tmpSum) { buf->error = __CFPropertyListCreateError(kCFPropertyListWriteStreamError, CFSTR("Binary property list writing could not be completed because databytes is full.")); return; } @@ -540,11 +541,8 @@ static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFD } static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CFMutableDictionaryRef objtable, CFMutableSetRef uniquingset) { - CFPropertyListRef unique; uint32_t refnum; CFTypeID type = CFGetTypeID(plist); - CFIndex idx; - CFPropertyListRef *list, buffer[256]; // Do not unique dictionaries or arrays, because: they // are slow to compare, and have poor hash codes. @@ -554,7 +552,7 @@ static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CF CFSetAddValue(uniquingset, plist); CFIndex after = CFSetGetCount(uniquingset); if (after == before) { // already in set - unique = CFSetGetValue(uniquingset, plist); + CFPropertyListRef unique = CFSetGetValue(uniquingset, plist); if (unique != plist) { refnum = (uint32_t)(uintptr_t)CFDictionaryGetValue(objtable, unique); CFDictionaryAddValue(objtable, plist, (const void *)(uintptr_t)refnum); @@ -566,18 +564,20 @@ static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CF CFArrayAppendValue(objlist, plist); CFDictionaryAddValue(objtable, plist, (const void *)(uintptr_t)refnum); if (dicttype == type) { - CFIndex count = CFDictionaryGetCount((CFDictionaryRef)plist); - list = (count <= 128) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); + CFIndex count = CFDictionaryGetCount((CFDictionaryRef)plist); + STACK_BUFFER_DECL(CFPropertyListRef, buffer, count <= 128 ? count * 2 : 1); + CFPropertyListRef *list = (count <= 128) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); CFDictionaryGetKeysAndValues((CFDictionaryRef)plist, list, list + count); - for (idx = 0; idx < 2 * count; idx++) { + for (CFIndex idx = 0; idx < 2 * count; idx++) { _flattenPlist(list[idx], objlist, objtable, uniquingset); } if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); } else if (arraytype == type) { - CFIndex count = CFArrayGetCount((CFArrayRef)plist); - list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); + CFIndex count = CFArrayGetCount((CFArrayRef)plist); + STACK_BUFFER_DECL(CFPropertyListRef, buffer, count <= 256 ? count : 1); + CFPropertyListRef *list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); CFArrayGetValues((CFArrayRef)plist, CFRangeMake(0, count), list); - for (idx = 0; idx < count; idx++) { + for (CFIndex idx = 0; idx < count; idx++) { _flattenPlist(list[idx], objlist, objtable, uniquingset); } if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); @@ -1078,7 +1078,7 @@ CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, ui if (startOffset < objectsRangeStart || objectsRangeEnd < startOffset) FAIL_FALSE; uint64_t off; - CFPropertyListRef *list, buffer[256]; + CFPropertyListRef *list; uint8_t marker = *(databytes + startOffset); switch (marker & 0xf0) { @@ -1316,6 +1316,7 @@ CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, ui if (databytes + objectsRangeEnd < extent) FAIL_FALSE; byte_cnt = check_size_t_mul(arrayCount, sizeof(CFPropertyListRef), &err); if (CF_NO_ERROR != err) FAIL_FALSE; + STACK_BUFFER_DECL(CFPropertyListRef, buffer, arrayCount <= 256 ? arrayCount : 1); list = (arrayCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory); if (!list) FAIL_FALSE; Boolean madeSet = false; @@ -1456,6 +1457,7 @@ CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, ui if (databytes + objectsRangeEnd < extent) FAIL_FALSE; byte_cnt = check_size_t_mul(dictionaryCount, sizeof(CFPropertyListRef), &err); if (CF_NO_ERROR != err) FAIL_FALSE; + STACK_BUFFER_DECL(CFPropertyListRef, buffer, dictionaryCount <= 256 ? dictionaryCount : 1); list = (dictionaryCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory); if (!list) FAIL_FALSE; Boolean madeSet = false; diff --git a/CFBitVector.c b/CFBitVector.c index 8c562e8..e5bc14f 100644 --- a/CFBitVector.c +++ b/CFBitVector.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBitVector.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -92,10 +92,6 @@ CF_INLINE void __CFBitVectorSetCapacity(CFMutableBitVectorRef bv, CFIndex v) { bv->_capacity = v; } -CF_INLINE CFIndex __CFBitVectorNumBucketsUsed(CFBitVectorRef bv) { - return bv->_count / __CF_BITS_PER_BUCKET + 1; -} - CF_INLINE void __CFBitVectorSetNumBucketsUsed(CFMutableBitVectorRef bv, CFIndex v) { /* for a CFBitVector, _bucketsUsed == _count / __CF_BITS_PER_BUCKET + 1 */ } @@ -225,11 +221,9 @@ static const CFRuntimeClass __CFBitVectorClass = { __CFBitVectorCopyDescription }; -CF_PRIVATE void __CFBitVectorInitialize(void) { - __kCFBitVectorTypeID = _CFRuntimeRegisterClass(&__CFBitVectorClass); -} - CFTypeID CFBitVectorGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFBitVectorTypeID = _CFRuntimeRegisterClass(&__CFBitVectorClass); }); return __kCFBitVectorTypeID; } @@ -239,7 +233,7 @@ static CFMutableBitVectorRef __CFBitVectorInit(CFAllocatorRef allocator, CFOptio CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFAssert2(0 <= numBits, __kCFLogAssertion, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__, numBits); size = sizeof(struct __CFBitVector) - sizeof(CFRuntimeBase); - memory = (CFMutableBitVectorRef)_CFRuntimeCreateInstance(allocator, __kCFBitVectorTypeID, size, NULL); + memory = (CFMutableBitVectorRef)_CFRuntimeCreateInstance(allocator, CFBitVectorGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -271,17 +265,17 @@ CFMutableBitVectorRef CFBitVectorCreateMutable(CFAllocatorRef allocator, CFIndex } CFBitVectorRef CFBitVectorCreateCopy(CFAllocatorRef allocator, CFBitVectorRef bv) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); return __CFBitVectorInit(allocator, kCFBitVectorImmutable, __CFBitVectorCount(bv), (const uint8_t *)bv->_buckets, __CFBitVectorCount(bv)); } CFMutableBitVectorRef CFBitVectorCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFBitVectorRef bv) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); return __CFBitVectorInit(allocator, kCFBitVectorMutable, capacity, (const uint8_t *)bv->_buckets, __CFBitVectorCount(bv)); } CFIndex CFBitVectorGetCount(CFBitVectorRef bv) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); return __CFBitVectorCount(bv); } @@ -340,7 +334,7 @@ static __CFBitVectorBucket __CFBitVectorCountBits(__CFBitVectorBucket bucketValu CFIndex CFBitVectorGetCountOfBit(CFBitVectorRef bv, CFRange range, CFBit value) { struct _occursContext context; - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); if (0 == range.length) return 0; context.value = value; @@ -350,13 +344,13 @@ CFIndex CFBitVectorGetCountOfBit(CFBitVectorRef bv, CFRange range, CFBit value) } Boolean CFBitVectorContainsBit(CFBitVectorRef bv, CFRange range, CFBit value) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); return (CFBitVectorGetCountOfBit(bv, range, value) != 0) ? true : false; } CFBit CFBitVectorGetBitAtIndex(CFBitVectorRef bv, CFIndex idx) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); return __CFBitVectorBit(bv->_buckets, idx); } @@ -406,7 +400,7 @@ static __CFBitVectorBucket __CFBitVectorGetBits(__CFBitVectorBucket bucketValue, void CFBitVectorGetBits(CFBitVectorRef bv, CFRange range, uint8_t *bytes) { struct _getBitsContext context; - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); if (0 == range.length) return; context.curByte = bytes; @@ -418,7 +412,7 @@ void CFBitVectorGetBits(CFBitVectorRef bv, CFRange range, uint8_t *bytes) { CFIndex CFBitVectorGetFirstIndexOfBit(CFBitVectorRef bv, CFRange range, CFBit value) { CFIndex idx; - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); for (idx = 0; idx < range.length; idx++) { if (value == CFBitVectorGetBitAtIndex(bv, range.location + idx)) { @@ -430,7 +424,7 @@ CFIndex CFBitVectorGetFirstIndexOfBit(CFBitVectorRef bv, CFRange range, CFBit va CFIndex CFBitVectorGetLastIndexOfBit(CFBitVectorRef bv, CFRange range, CFBit value) { CFIndex idx; - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); for (idx = range.length; idx--;) { if (value == CFBitVectorGetBitAtIndex(bv, range.location + idx)) { @@ -479,7 +473,7 @@ void CFBitVectorSetCount(CFMutableBitVectorRef bv, CFIndex count) { } void CFBitVectorFlipBitAtIndex(CFMutableBitVectorRef bv, CFIndex idx) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__); __CFFlipBitVectorBit(bv->_buckets, idx); @@ -490,7 +484,7 @@ static __CFBitVectorBucket __CFBitVectorFlipBits(__CFBitVectorBucket bucketValue } void CFBitVectorFlipBits(CFMutableBitVectorRef bv, CFRange range) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__); if (0 == range.length) return; @@ -498,14 +492,14 @@ void CFBitVectorFlipBits(CFMutableBitVectorRef bv, CFRange range) { } void CFBitVectorSetBitAtIndex(CFMutableBitVectorRef bv, CFIndex idx, CFBit value) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx); CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__); __CFSetBitVectorBit(bv->_buckets, idx, value); } void CFBitVectorSetBits(CFMutableBitVectorRef bv, CFRange range, CFBit value) { - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__); CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable , __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__); if (0 == range.length) return; @@ -518,7 +512,7 @@ void CFBitVectorSetBits(CFMutableBitVectorRef bv, CFRange range, CFBit value) { void CFBitVectorSetAllBits(CFMutableBitVectorRef bv, CFBit value) { CFIndex nBuckets, leftover; - __CFGenericValidateType(bv, __kCFBitVectorTypeID); + __CFGenericValidateType(bv, CFBitVectorGetTypeID()); CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable , __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__); nBuckets = __CFBitVectorCount(bv) / __CF_BITS_PER_BUCKET; leftover = __CFBitVectorCount(bv) - nBuckets * __CF_BITS_PER_BUCKET; diff --git a/CFBitVector.h b/CFBitVector.h index 73a965c..4b1d03a 100644 --- a/CFBitVector.h +++ b/CFBitVector.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBitVector.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBITVECTOR__) diff --git a/CFBuiltinConverters.c b/CFBuiltinConverters.c index b75dbbe..3750050 100644 --- a/CFBuiltinConverters.c +++ b/CFBuiltinConverters.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBuiltinConverters.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ diff --git a/CFBundle.c b/CFBundle.c index a7266ac..550c499 100644 --- a/CFBundle.c +++ b/CFBundle.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBundle.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -55,19 +55,10 @@ #endif /* !AVOID_WEAK_COLLECTIONS */ #if defined(BINARY_SUPPORT_DYLD) -// Import the mach-o headers that define the macho magic numbers -#include -#include -#include -#include -#include #include #include #include #include -#if defined(USE_DYLD_PRIV) -#include -#endif /* USE_DYLD_PRIV */ #endif /* BINARY_SUPPORT_DYLD */ #if defined(BINARY_SUPPORT_DLFCN) @@ -79,25 +70,9 @@ #elif DEPLOYMENT_TARGET_WINDOWS #include #include - -#define open _NS_open -#define stat(x,y) _NS_stat(x,y) #endif -#if DEPLOYMENT_TARGET_WINDOWS -#define statinfo _stat - -// Windows isspace implementation limits the input chars to < 256 in the ASCII range. It will -// assert in debug builds. This is annoying. We merrily grok chars > 256. -static inline BOOL isspace(char c) { - return (c == ' ' || c == '\t' || c == '\n' || c == '\r'|| c == '\v' || c == '\f'); -} - -#else -#define statinfo stat -#endif - static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean alreadyLocked); #define LOG_BUNDLE_LOAD 0 @@ -197,20 +172,10 @@ static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void); static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath); static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths); -#if defined(BINARY_SUPPORT_DYLD) -static CFMutableDictionaryRef _CFBundleCreateInfoDictFromMainExecutable(void); -static Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags); -static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p); -#if !defined(BINARY_SUPPORT_DLFCN) -static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch); -#endif /* !BINARY_SUPPORT_DLFCN */ -#endif /* BINARY_SUPPORT_DYLD */ -#if defined(BINARY_SUPPORT_DLFCN) -static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch); -#if !defined(BINARY_SUPPORT_DYLD) -static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p); -#endif /* !BINARY_SUPPORT_DYLD */ -#endif /* BINARY_SUPPORT_DLFCN */ + +#pragma mark - + + #if AVOID_WEAK_COLLECTIONS @@ -666,6 +631,16 @@ CFBundleRef _CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef return bundle; } +CF_EXPORT Boolean _CFBundleURLLooksLikeBundle(CFURLRef url) { + Boolean result = false; + CFBundleRef bundle = _CFBundleCreateIfLooksLikeBundle(kCFAllocatorSystemDefault, url); + if (bundle) { + result = true; + CFRelease(bundle); + } + return result; +} + CFBundleRef _CFBundleGetMainBundleIfLooksLikeBundle(void) { CFBundleRef mainBundle = CFBundleGetMainBundle(); if (mainBundle && (3 == mainBundle->_version || 4 == mainBundle->_version)) mainBundle = NULL; @@ -681,7 +656,8 @@ CFBundleRef _CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef all CFBundleRef bundle = NULL; CFURLRef bundleURL = _CFBundleCopyBundleURLForExecutableURL(url), resolvedURL = _CFBundleCopyResolvedURLForExecutableURL(url); if (bundleURL && resolvedURL) { - bundle = _CFBundleCreateIfLooksLikeBundle(allocator, bundleURL); + // We used to call _CFBundleCreateIfLooksLikeBundle here, but switched to the regular CFBundleCreate because we want this to return a result for certain flat bundles as well. + bundle = CFBundleCreate(allocator, bundleURL); if (bundle) { CFURLRef executableURL = _CFBundleCopyExecutableURLIgnoringCache(bundle); char buff1[CFMaxPathSize], buff2[CFMaxPathSize]; @@ -698,61 +674,32 @@ CFBundleRef _CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef all } CFBundleRef _CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) { + // This function is obsolete CFBundleRef bundle = CFBundleCreate(allocator, url); - if (bundle) { - Boolean mightBeBundle = true, isDir = false; - uint8_t localVersion = _CFBundleEffectiveLayoutVersion(bundle); - if (3 == localVersion) { - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - CFURLRef executableURL, supportFilesURL, resourceSpecificationFileURL; - CFArrayRef supportedPlatforms; - CFStringRef resourceSpecificationFile; - - mightBeBundle = false; - if (infoDict && CFDictionaryGetValue(infoDict, kCFBundleExecutableKey) && (executableURL = _CFBundleCopyExecutableURLIgnoringCache(bundle))) { - supportedPlatforms = _CFBundleGetSupportedPlatforms(bundle); - resourceSpecificationFile = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleResourceSpecificationKey); - if (supportedPlatforms && CFArrayGetCount(supportedPlatforms) > 0 && CFArrayGetFirstIndexOfValue(supportedPlatforms, CFRangeMake(0, CFArrayGetCount(supportedPlatforms)), CFSTR("iPhoneOS")) >= 0) { - mightBeBundle = true; - } else if (resourceSpecificationFile && CFGetTypeID(resourceSpecificationFile) == CFStringGetTypeID() && (supportFilesURL = CFBundleCopySupportFilesDirectoryURL(bundle))) { - resourceSpecificationFileURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, resourceSpecificationFile, kCFURLPOSIXPathStyle, false, supportFilesURL); - if (resourceSpecificationFileURL) { - if (_CFIsResourceAtURL(resourceSpecificationFileURL, &isDir) && !isDir) mightBeBundle = true; - CFRelease(resourceSpecificationFileURL); - } - CFRelease(supportFilesURL); - } - CFRelease(executableURL); - } - } else if (4 == localVersion) { - mightBeBundle = false; - } - if (!mightBeBundle) { - CFRelease(bundle); - bundle = NULL; - } - } return bundle; } CFBundleRef _CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) { - CFBundleRef bundle = NULL; - CFURLRef bundleURL = _CFBundleCopyBundleURLForExecutableURL(url), resolvedURL = _CFBundleCopyResolvedURLForExecutableURL(url); - if (bundleURL && resolvedURL) { - bundle = _CFBundleCreateIfMightBeBundle(allocator, bundleURL); - if (bundle) { - CFURLRef executableURL = _CFBundleCopyExecutableURLIgnoringCache(bundle); - char buff1[CFMaxPathSize], buff2[CFMaxPathSize]; - if (!executableURL || !CFURLGetFileSystemRepresentation(resolvedURL, true, (uint8_t *)buff1, CFMaxPathSize) || !CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff2, CFMaxPathSize) || 0 != strcmp(buff1, buff2)) { - CFRelease(bundle); - bundle = NULL; + CFBundleRef result = _CFBundleCreateWithExecutableURLIfLooksLikeBundle(allocator, url); + + // This function applies additional requirements on a bundle to return a result + // The above makes sure that: + // 0. CFBundleCreate must succeed using a URL derived from the executable URL + // 1. The bundle must have an executableURL, and it must match the passed in executable URL + + // This function additionally requires that + // 2. If flat, the bundle must have a non-empty Info.plist. (15663535) + if (result) { + uint8_t localVersion = _CFBundleEffectiveLayoutVersion(result); + if (3 == localVersion || 4 == localVersion) { + CFDictionaryRef infoPlist = CFBundleGetInfoDictionary(result); + if (!infoPlist || (infoPlist && CFDictionaryGetCount(infoPlist) == 0)) { + CFRelease(result); + result = NULL; } - if (executableURL) CFRelease(executableURL); } } - if (bundleURL) CFRelease(bundleURL); - if (resolvedURL) CFRelease(resolvedURL); - return bundle; + return result; } CFURLRef _CFBundleCopyMainBundleExecutableURL(Boolean *looksLikeBundle) { @@ -842,9 +789,9 @@ static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean CFRelease(bundle->_searchLanguages); bundle->_searchLanguages = NULL; } - if (bundle->_resourceData._stringTableCache) { - CFRelease(bundle->_resourceData._stringTableCache); - bundle->_resourceData._stringTableCache = NULL; + if (bundle->_stringTable) { + CFRelease(bundle->_stringTable); + bundle->_stringTable = NULL; } if (bundle == _mainBundle) { CFStringRef executablePath = bundle->_executablePath; @@ -860,11 +807,8 @@ static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean if (val) CFDictionarySetValue((CFMutableDictionaryRef)bundle->_infoDict, _kCFBundlePrincipalClassKey, val); CFRelease(oldInfoDict); } - __CFSpinLock(&bundle->_queryLock); - if (bundle->_queryTable) { - CFDictionaryRemoveAllValues(bundle->_queryTable); - } - __CFSpinUnlock(&bundle->_queryLock); + + _CFBundleFlushQueryTableCache(bundle); } CF_EXPORT void _CFBundleFlushBundleCaches(CFBundleRef bundle) { @@ -953,12 +897,7 @@ CFBundleRef CFBundleGetBundleWithIdentifier(CFStringRef bundleID) { // Try to create the bundle for the caller and try again void *p = __builtin_return_address(0); if (p) { - CFStringRef imagePath = NULL; -#if defined(BINARY_SUPPORT_DYLD) - if (!imagePath) imagePath = _CFBundleDYLDCopyLoadedImagePathForPointer(p); -#elif defined(BINARY_SUPPORT_DLFCN) - if (!imagePath) imagePath = _CFBundleDlfcnCopyLoadedImagePathForPointer(p); -#endif /* BINARY_SUPPORT_DYLD */ + CFStringRef imagePath = _CFBundleCopyLoadedImagePathForPointer(p); if (imagePath) { _CFBundleEnsureBundleExistsForImagePath(imagePath); CFRelease(imagePath); @@ -1028,7 +967,7 @@ static void __CFBundleDeallocate(CFTypeRef cf) { CFURLRef bundleURL; CFStringRef bundleID = NULL; - __CFGenericValidateType(cf, __kCFBundleTypeID); + __CFGenericValidateType(cf, CFBundleGetTypeID()); bundleURL = bundle->_url; bundle->_url = NULL; if (bundle->_infoDict) bundleID = (CFStringRef)CFDictionaryGetValue(bundle->_infoDict, kCFBundleIdentifierKey); @@ -1048,7 +987,7 @@ static void __CFBundleDeallocate(CFTypeRef cf) { CFDictionaryApplyFunction(bundle->_glueDict, _CFBundleDeallocateGlue, (void *)CFGetAllocator(bundle)); CFRelease(bundle->_glueDict); } - if (bundle->_resourceData._stringTableCache) CFRelease(bundle->_resourceData._stringTableCache); + if (bundle->_stringTable) CFRelease(bundle->_stringTable); if (bundle->_bundleBasePath) CFRelease(bundle->_bundleBasePath); if (bundle->_queryTable) CFRelease(bundle->_queryTable); @@ -1074,12 +1013,9 @@ static const CFRuntimeClass __CFBundleClass = { // From CFBundle_Resources.c CF_PRIVATE void _CFBundleResourcesInitialize(); -CF_PRIVATE void __CFBundleInitialize(void) { - __kCFBundleTypeID = _CFRuntimeRegisterClass(&__CFBundleClass); - _CFBundleResourcesInitialize(); -} - CFTypeID CFBundleGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFBundleTypeID = _CFRuntimeRegisterClass(&__CFBundleClass); _CFBundleResourcesInitialize(); }); return __kCFBundleTypeID; } @@ -1145,7 +1081,7 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, } } - bundle = (CFBundleRef)_CFRuntimeCreateInstance(allocator, __kCFBundleTypeID, sizeof(struct __CFBundle) - sizeof(CFRuntimeBase), NULL); + bundle = (CFBundleRef)_CFRuntimeCreateInstance(allocator, CFBundleGetTypeID(), sizeof(struct __CFBundle) - sizeof(CFRuntimeBase), NULL); if (!bundle) { CFRelease(newURL); return NULL; @@ -1160,7 +1096,7 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, bundle->_searchLanguages = NULL; bundle->_executablePath = NULL; bundle->_developmentRegion = NULL; - bundle->_developmentRegionCalculated = false; + bundle->_developmentRegionCalculated = 0; #if defined(BINARY_SUPPORT_DYLD) /* We'll have to figure it out later */ bundle->_binaryType = __CFBundleUnknownBinary; @@ -1191,7 +1127,8 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, bundle->_resourceData._executableLacksResourceFork = false; bundle->_resourceData._infoDictionaryFromResourceFork = false; - bundle->_resourceData._stringTableCache = NULL; + + bundle->_stringTable = NULL; bundle->_plugInData._isPlugIn = false; bundle->_plugInData._loadOnDemand = false; @@ -1208,13 +1145,13 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, CFLog(4, CFSTR("%s: failed to initialize bundle loading lock for bundle %@."), __PRETTY_FUNCTION__, bundle); } - bundle->_lock = CFSpinLockInit; + bundle->_lock = CFLockInit; bundle->_resourceDirectoryContents = NULL; bundle->_localizations = NULL; bundle->_lookedForLocalizations = false; - bundle->_queryLock = CFSpinLockInit; + bundle->_queryLock = CFLockInit; bundle->_queryTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFURLRef absoURL = CFURLCopyAbsoluteURL(bundle->_url); bundle->_bundleBasePath = CFURLCopyFileSystemPath(absoURL, PLATFORM_PATH_STYLE); @@ -1222,6 +1159,9 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, CFBundleGetInfoDictionary(bundle); + // Do this so that we can use the dispatch_once on the ivar of this bundle safely + OSMemoryBarrier(); + _CFBundleAddToTables(bundle, alreadyLocked); if (doFinalProcessing) { @@ -1467,10 +1407,8 @@ UInt32 CFBundleGetVersionNumber(CFBundleRef bundle) { } CFStringRef CFBundleGetDevelopmentRegion(CFBundleRef bundle) { - CFStringRef devRegion = NULL; - devRegion = bundle->_developmentRegion; - - if (!devRegion && !bundle->_developmentRegionCalculated) { + dispatch_once(&bundle->_developmentRegionCalculated, ^{ + CFStringRef devRegion = NULL; CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); if (infoDict) { devRegion = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); @@ -1478,12 +1416,10 @@ CFStringRef CFBundleGetDevelopmentRegion(CFBundleRef bundle) { devRegion = NULL; } } - + if (devRegion) bundle->_developmentRegion = (CFStringRef)CFRetain(devRegion); - bundle->_developmentRegionCalculated = true; - } - - return devRegion; + }); + return bundle->_developmentRegion; } Boolean _CFBundleGetHasChanged(CFBundleRef bundle) { @@ -1572,7 +1508,7 @@ CF_PRIVATE CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundl return result; } -CFURLRef CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) { +CF_EXPORT CFURLRef CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) { return _CFBundleCopyResourcesDirectoryURLInDirectory(bundle->_url, bundle->_version); } @@ -1725,10 +1661,10 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL // If we have a bundle instance and an info dict, see if we have already cached the path if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && bundle->_executablePath) { - __CFSpinLock(&bundle->_lock); + __CFLock(&bundle->_lock); executablePath = bundle->_executablePath; if (executablePath) CFRetain(executablePath); - __CFSpinUnlock(&bundle->_lock); + __CFUnlock(&bundle->_lock); if (executablePath) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, executablePath, kCFURLPOSIXPathStyle, false); @@ -1820,9 +1756,9 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL executablePath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle); #endif CFRelease(absURL); - __CFSpinLock(&bundle->_lock); + __CFLock(&bundle->_lock); bundle->_executablePath = (CFStringRef)CFRetain(executablePath); - __CFSpinUnlock(&bundle->_lock); + __CFUnlock(&bundle->_lock); CFRelease(executablePath); } if (lookupMainExe && !useOtherPlatform && bundle && !executableURL) bundle->_binaryType = __CFBundleNoBinary; @@ -1883,1071 +1819,123 @@ CFBundleExecutableType CFBundleGetExecutableType(CFBundleRef bundle) { return result; } -static SInt32 _CFBundleCurrentArchitecture(void) { - SInt32 arch = 0; -#if defined(__ppc__) - arch = kCFBundleExecutableArchitecturePPC; -#elif defined(__ppc64__) - arch = kCFBundleExecutableArchitecturePPC64; -#elif defined(__i386__) - arch = kCFBundleExecutableArchitectureI386; -#elif defined(__x86_64__) - arch = kCFBundleExecutableArchitectureX86_64; -#elif defined(BINARY_SUPPORT_DYLD) - const NXArchInfo *archInfo = NXGetLocalArchInfo(); - if (archInfo) arch = archInfo->cputype; -#endif - return arch; -} - -#define UNKNOWN_FILETYPE 0x0 -#define PEF_FILETYPE 0x1000 -#define PEF_MAGIC 0x4a6f7921 -#define PEF_CIGAM 0x21796f4a -#define TEXT_SEGMENT "__TEXT" -#define PLIST_SECTION "__info_plist" -#define OBJC_SEGMENT "__OBJC" -#define IMAGE_INFO_SECTION "__image_info" -#define OBJC_SEGMENT_64 "__DATA" -#define IMAGE_INFO_SECTION_64 "__objc_imageinfo" -#define LIB_X11 "/usr/X11R6/lib/libX" - -#define XLS_NAME "Book" -#define XLS_NAME2 "Workbook" -#define DOC_NAME "WordDocument" -#define PPT_NAME "PowerPoint Document" - -#define ustrncmp(x, y, z) strncmp((char *)(x), (char *)(y), (z)) -#define ustrncasecmp(x, y, z) strncasecmp_l((char *)(x), (char *)(y), (z), NULL) - -static const uint32_t __CFBundleMagicNumbersArray[] = { - 0xcafebabe, 0xbebafeca, 0xfeedface, 0xcefaedfe, 0xfeedfacf, 0xcffaedfe, 0x4a6f7921, 0x21796f4a, - 0x7f454c46, 0xffd8ffe0, 0x4d4d002a, 0x49492a00, 0x47494638, 0x89504e47, 0x69636e73, 0x00000100, - 0x7b5c7274, 0x25504446, 0x2e7261fd, 0x2e524d46, 0x2e736e64, 0x2e736400, 0x464f524d, 0x52494646, - 0x38425053, 0x000001b3, 0x000001ba, 0x4d546864, 0x504b0304, 0x53495421, 0x53495432, 0x53495435, - 0x53495444, 0x53747566, 0x30373037, 0x3c212d2d, 0x25215053, 0xd0cf11e0, 0x62656769, 0x3d796265, - 0x6b6f6c79, 0x3026b275, 0x0000000c, 0xfe370023, 0x09020600, 0x09040600, 0x4f676753, 0x664c6143, - 0x00010000, 0x74727565, 0x4f54544f, 0x41433130, 0xc809fe02, 0x0809fe02, 0x2356524d, 0x67696d70, - 0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664, 0x63616666, 0x802a5fd7, 0x762f3101 -}; - -// string, with groups of 5 characters being 1 element in the array -static const char * __CFBundleExtensionsArray = - "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "pef\0\0" "pef\0\0" - "elf\0\0" "jpeg\0" "tiff\0" "tiff\0" "gif\0\0" "png\0\0" "icns\0" "ico\0\0" - "rtf\0\0" "pdf\0\0" "ra\0\0\0""rm\0\0\0""au\0\0\0""au\0\0\0""iff\0\0" "riff\0" - "psd\0\0" "mpeg\0" "mpeg\0" "mid\0\0" "zip\0\0" "sit\0\0" "sit\0\0" "sit\0\0" - "sit\0\0" "sit\0\0" "cpio\0" "html\0" "ps\0\0\0""ole\0\0" "uu\0\0\0""ync\0\0" - "dmg\0\0" "wmv\0\0" "jp2\0\0" "doc\0\0" "xls\0\0" "xls\0\0" "ogg\0\0" "flac\0" - "ttf\0\0" "ttf\0\0" "otf\0\0" "dwg\0\0" "dgn\0\0" "dgn\0\0" "wrl\0\0" "xcf\0\0" - "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0" "caf\0\0" "cin\0\0" "exr\0\0"; - -static const char * __CFBundleOOExtensionsArray = "sxc\0\0" "sxd\0\0" "sxg\0\0" "sxi\0\0" "sxm\0\0" "sxw\0\0"; -static const char * __CFBundleODExtensionsArray = "odc\0\0" "odf\0\0" "odg\0\0" "oth\0\0" "odi\0\0" "odm\0\0" "odp\0\0" "ods\0\0" "odt\0\0"; - -#define EXTENSION_LENGTH 5 -#define NUM_EXTENSIONS 64 -#define MAGIC_BYTES_TO_READ 512 -#define DMG_BYTES_TO_READ 512 -#define ZIP_BYTES_TO_READ 1024 -#define OLE_BYTES_TO_READ 512 -#define X11_BYTES_TO_READ 4096 -#define IMAGE_INFO_BYTES_TO_READ 4096 - -#if defined(BINARY_SUPPORT_DYLD) - -CF_INLINE uint32_t _CFBundleSwapInt32Conditional(uint32_t arg, Boolean swap) {return swap ? CFSwapInt32(arg) : arg;} -CF_INLINE uint32_t _CFBundleSwapInt64Conditional(uint64_t arg, Boolean swap) {return swap ? CFSwapInt64(arg) : arg;} - -static CFMutableDictionaryRef _CFBundleCreateInfoDictFromData(const char *bytes, uint32_t length) { - CFMutableDictionaryRef result = NULL; - CFDataRef infoData = NULL; - if (bytes && 0 < length) { - infoData = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (uint8_t *)bytes, length, kCFAllocatorNull); - if (infoData) { - result = (CFMutableDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, infoData, kCFPropertyListMutableContainers, NULL); - if (result && CFDictionaryGetTypeID() != CFGetTypeID(result)) { - CFRelease(result); - result = NULL; - } - CFRelease(infoData); - } - if (!result) result = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } - if (result) _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); - return result; +void _CFBundleSetCFMConnectionID(CFBundleRef bundle, void *connectionID) { + bundle->_connectionCookie = connectionID; + bundle->_isLoaded = true; } -static char *_CFBundleGetSectData(const char *segname, const char *sectname, unsigned long *size) { - char *retval = NULL; - unsigned long localSize = 0; - uint32_t i, numImages = _dyld_image_count(); - const void *mhp = (const void *)_NSGetMachExecuteHeader(); - - for (i = 0; i < numImages; i++) { - if (mhp == (void *)_dyld_get_image_header(i)) { -#if __LP64__ - const struct section_64 *sp = getsectbynamefromheader_64((const struct mach_header_64 *)mhp, segname, sectname); - if (sp) { - retval = (char *)(sp->addr + _dyld_get_image_vmaddr_slide(i)); - localSize = (unsigned long)sp->size; - } -#else /* __LP64__ */ - const struct section *sp = getsectbynamefromheader((const struct mach_header *)mhp, segname, sectname); - if (sp) { - retval = (char *)(sp->addr + _dyld_get_image_vmaddr_slide(i)); - localSize = (unsigned long)sp->size; - } -#endif /* __LP64__ */ - break; - } +static CFStringRef _CFBundleCopyLastPathComponent(CFBundleRef bundle) { + CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); + if (!bundleURL) { + return CFSTR(""); } - if (size) *size = localSize; - return retval; -} + CFStringRef str = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); + UniChar buff[CFMaxPathSize]; + CFIndex buffLen = CFStringGetLength(str), startOfLastDir = 0; -static CFMutableDictionaryRef _CFBundleCreateInfoDictFromMainExecutable() { - char *bytes = NULL; - unsigned long length = 0; - if (getsegbyname(TEXT_SEGMENT)) bytes = _CFBundleGetSectData(TEXT_SEGMENT, PLIST_SECTION, &length); - return _CFBundleCreateInfoDictFromData(bytes, length); + CFRelease(bundleURL); + if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize; + CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff); + CFRelease(str); + if (buffLen > 0) startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen); + return CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfLastDir]), buffLen - startOfLastDir); } -static Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags) { - Boolean retval = false; - uint32_t localVersion = 0, localFlags = 0; - char *bytes = NULL; - unsigned long length = 0; -#if __LP64__ - if (getsegbyname(OBJC_SEGMENT_64)) bytes = _CFBundleGetSectData(OBJC_SEGMENT_64, IMAGE_INFO_SECTION_64, &length); -#else /* __LP64__ */ - if (getsegbyname(OBJC_SEGMENT)) bytes = _CFBundleGetSectData(OBJC_SEGMENT, IMAGE_INFO_SECTION, &length); -#endif /* __LP64__ */ - if (bytes && length >= 8) { - localVersion = *(uint32_t *)bytes; - localFlags = *(uint32_t *)(bytes + 4); - retval = true; - } - if (objcVersion) *objcVersion = localVersion; - if (objcFlags) *objcFlags = localFlags; - return retval; -} +#pragma mark - -static Boolean _CFBundleGrokX11FromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour) { - static const char libX11name[] = LIB_X11; - char *buffer = NULL; - const char *loc = NULL; - unsigned i; - Boolean result = false; - - if (fd >= 0 && lseek(fd, offset, SEEK_SET) == (off_t)offset) { - buffer = malloc(X11_BYTES_TO_READ); - if (buffer && read(fd, buffer, X11_BYTES_TO_READ) >= X11_BYTES_TO_READ) loc = buffer; - } else if (bytes && length >= offset + X11_BYTES_TO_READ) { - loc = bytes + offset; - } - if (loc) { - if (sixtyFour) { - uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->ncmds, swapped); - uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->sizeofcmds, swapped); - const char *startofcmds = loc + sizeof(struct mach_header_64); - const char *endofcmds = startofcmds + sizeofcmds; - struct dylib_command *dlp = (struct dylib_command *)startofcmds; - if (endofcmds > loc + X11_BYTES_TO_READ) endofcmds = loc + X11_BYTES_TO_READ; - for (i = 0; !result && i < ncmds && startofcmds <= (char *)dlp && (char *)dlp < endofcmds; i++) { - if (LC_LOAD_DYLIB == _CFBundleSwapInt32Conditional(dlp->cmd, swapped)) { - uint32_t nameoffset = _CFBundleSwapInt32Conditional(dlp->dylib.name.offset, swapped); - const char *name = (const char *)dlp + nameoffset; - if (startofcmds <= name && name + sizeof(libX11name) <= endofcmds && 0 == strncmp(name, libX11name, sizeof(libX11name) - 1)) result = true; - } - dlp = (struct dylib_command *)((char *)dlp + _CFBundleSwapInt32Conditional(dlp->cmdsize, swapped)); - } - } else { - uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->ncmds, swapped); - uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->sizeofcmds, swapped); - const char *startofcmds = loc + sizeof(struct mach_header); - const char *endofcmds = startofcmds + sizeofcmds; - struct dylib_command *dlp = (struct dylib_command *)startofcmds; - if (endofcmds > loc + X11_BYTES_TO_READ) endofcmds = loc + X11_BYTES_TO_READ; - for (i = 0; !result && i < ncmds && startofcmds <= (char *)dlp && (char *)dlp < endofcmds; i++) { - if (LC_LOAD_DYLIB == _CFBundleSwapInt32Conditional(dlp->cmd, swapped)) { - uint32_t nameoffset = _CFBundleSwapInt32Conditional(dlp->dylib.name.offset, swapped); - const char *name = (const char *)dlp + nameoffset; - if (startofcmds <= name && name + sizeof(libX11name) <= endofcmds && 0 == strncmp(name, libX11name, sizeof(libX11name) - 1)) result = true; - } - dlp = (struct dylib_command *)((char *)dlp + _CFBundleSwapInt32Conditional(dlp->cmdsize, swapped)); - } +CF_PRIVATE CFErrorRef _CFBundleCreateErrorDebug(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code, CFStringRef debugString) { + const void *userInfoKeys[6], *userInfoValues[6]; + CFIndex numKeys = 0; + CFURLRef bundleURL = CFBundleCopyBundleURL(bundle), absoluteURL = CFURLCopyAbsoluteURL(bundleURL), executableURL = CFBundleCopyExecutableURL(bundle); + CFBundleRef bdl = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation")); + CFStringRef bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE), executablePath = executableURL ? CFURLCopyFileSystemPath(executableURL, PLATFORM_PATH_STYLE) : NULL, descFormat = NULL, desc = NULL, reason = NULL, suggestion = NULL; + CFErrorRef error; + if (bdl) { + CFStringRef name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleNameKey); + name = name ? (CFStringRef)CFRetain(name) : _CFBundleCopyLastPathComponent(bundle); + if (CFBundleExecutableNotFoundError == code) { + descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable couldn\\U2019t be located."), "NSFileNoSuchFileError"); + reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable couldn\\U2019t be located."), "NSFileNoSuchFileError"); + suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError"); + } else if (CFBundleExecutableNotLoadableError == code) { + descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable isn\\U2019t loadable."), "NSExecutableNotLoadableError"); + reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable isn\\U2019t loadable."), "NSExecutableNotLoadableError"); + suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError"); + } else if (CFBundleExecutableArchitectureMismatchError == code) { + descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError"); + reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl, CFSTR("The bundle doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError"); + suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError"); + } else if (CFBundleExecutableRuntimeMismatchError == code) { + descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it isn\\U2019t compatible with the current application."), "NSExecutableRuntimeMismatchError"); + reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl, CFSTR("The bundle isn\\U2019t compatible with this application."), "NSExecutableRuntimeMismatchError"); + suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError"); + } else if (CFBundleExecutableLoadError == code) { + descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it is damaged or missing necessary resources."), "NSExecutableLoadError"); + reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError"); + suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError"); + } else if (CFBundleExecutableLinkError == code) { + descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded."), "NSExecutableLinkError"); + reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl, CFSTR("The bundle couldn\\U2019t be loaded."), "NSExecutableLinkError"); + suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError"); } + if (descFormat) { + desc = CFStringCreateWithFormat(allocator, NULL, descFormat, name); + CFRelease(descFormat); + } + CFRelease(name); } - if (buffer) free(buffer); - return result; -} - -static CFDictionaryRef _CFBundleCreateInfoDictFromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour) { - struct statinfo statBuf; - off_t fileLength = 0; - char *maploc = NULL; - const char *loc; - unsigned i, j; - CFDictionaryRef result = NULL; - Boolean foundit = false; - if (fd >= 0 && fstat(fd, &statBuf) == 0 && (maploc = mmap(0, statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) != (void *)-1) { - loc = maploc; - fileLength = statBuf.st_size; - } else { - loc = bytes; - fileLength = length; + if (bundlePath) { + userInfoKeys[numKeys] = CFSTR("NSBundlePath"); + userInfoValues[numKeys] = bundlePath; + numKeys++; } - if (fileLength > offset + sizeof(struct mach_header_64)) { - if (sixtyFour) { - uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)(loc + offset))->ncmds, swapped); - uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)(loc + offset))->sizeofcmds, swapped); - const char *startofcmds = loc + offset + sizeof(struct mach_header_64); - const char *endofcmds = startofcmds + sizeofcmds; - struct segment_command_64 *sgp = (struct segment_command_64 *)startofcmds; - if (endofcmds > loc + fileLength) endofcmds = loc + fileLength; - for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { - if (LC_SEGMENT_64 == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { - struct section_64 *sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64)); - uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); - for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { - if (0 == strncmp(sp->sectname, PLIST_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, TEXT_SEGMENT, sizeof(sp->segname))) { - uint64_t sectlength64 = _CFBundleSwapInt64Conditional(sp->size, swapped); - uint32_t sectlength = (uint32_t)(sectlength64 & 0xffffffff); - uint32_t sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); - const char *sectbytes = loc + offset + sectoffset; - // we don't support huge-sized plists - if (sectlength64 <= 0xffffffff && loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleCreateInfoDictFromData(sectbytes, sectlength); - foundit = true; - } - sp = (struct section_64 *)((char *)sp + sizeof(struct section_64)); - } - } - sgp = (struct segment_command_64 *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); - } - } else { - uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header *)(loc + offset))->ncmds, swapped); - uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header *)(loc + offset))->sizeofcmds, swapped); - const char *startofcmds = loc + offset + sizeof(struct mach_header); - const char *endofcmds = startofcmds + sizeofcmds; - struct segment_command *sgp = (struct segment_command *)startofcmds; - if (endofcmds > loc + fileLength) endofcmds = loc + fileLength; - for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { - if (LC_SEGMENT == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { - struct section *sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); - uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); - for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { - if (0 == strncmp(sp->sectname, PLIST_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, TEXT_SEGMENT, sizeof(sp->segname))) { - uint32_t sectlength = _CFBundleSwapInt32Conditional(sp->size, swapped); - uint32_t sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); - const char *sectbytes = loc + offset + sectoffset; - if (loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleCreateInfoDictFromData(sectbytes, sectlength); - foundit = true; - } - sp = (struct section *)((char *)sp + sizeof(struct section)); - } - } - sgp = (struct segment_command *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); - } - } + if (executablePath) { + userInfoKeys[numKeys] = CFSTR("NSFilePath"); + userInfoValues[numKeys] = executablePath; + numKeys++; } - if (maploc) munmap(maploc, statBuf.st_size); - return result; -} - -static void _CFBundleGrokObjcImageInfoFromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { - uint32_t sectlength = 0, sectoffset = 0, localVersion = 0, localFlags = 0; - char *buffer = NULL; - char sectbuffer[8]; - const char *loc = NULL; - unsigned i, j; - Boolean foundit = false, localHasObjc = false; - - if (fd >= 0 && lseek(fd, offset, SEEK_SET) == (off_t)offset) { - buffer = malloc(IMAGE_INFO_BYTES_TO_READ); - if (buffer && read(fd, buffer, IMAGE_INFO_BYTES_TO_READ) >= IMAGE_INFO_BYTES_TO_READ) loc = buffer; - } else if (bytes && length >= offset + IMAGE_INFO_BYTES_TO_READ) { - loc = bytes + offset; + if (desc) { + userInfoKeys[numKeys] = kCFErrorLocalizedDescriptionKey; + userInfoValues[numKeys] = desc; + numKeys++; } - if (loc) { - if (sixtyFour) { - uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->ncmds, swapped); - uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->sizeofcmds, swapped); - const char *startofcmds = loc + sizeof(struct mach_header_64); - const char *endofcmds = startofcmds + sizeofcmds; - struct segment_command_64 *sgp = (struct segment_command_64 *)startofcmds; - if (endofcmds > loc + IMAGE_INFO_BYTES_TO_READ) endofcmds = loc + IMAGE_INFO_BYTES_TO_READ; - for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { - if (LC_SEGMENT_64 == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { - struct section_64 *sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64)); - uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); - for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { - if (0 == strncmp(sp->segname, OBJC_SEGMENT_64, sizeof(sp->segname))) localHasObjc = true; - if (0 == strncmp(sp->sectname, IMAGE_INFO_SECTION_64, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, OBJC_SEGMENT_64, sizeof(sp->segname))) { - uint64_t sectlength64 = _CFBundleSwapInt64Conditional(sp->size, swapped); - sectlength = (uint32_t)(sectlength64 & 0xffffffff); - sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); - foundit = true; - } - sp = (struct section_64 *)((char *)sp + sizeof(struct section_64)); - } - } - sgp = (struct segment_command_64 *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); - } - } else { - uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->ncmds, swapped); - uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->sizeofcmds, swapped); - const char *startofcmds = loc + sizeof(struct mach_header); - const char *endofcmds = startofcmds + sizeofcmds; - struct segment_command *sgp = (struct segment_command *)startofcmds; - if (endofcmds > loc + IMAGE_INFO_BYTES_TO_READ) endofcmds = loc + IMAGE_INFO_BYTES_TO_READ; - for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { - if (LC_SEGMENT == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { - struct section *sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); - uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); - for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { - if (0 == strncmp(sp->segname, OBJC_SEGMENT, sizeof(sp->segname))) localHasObjc = true; - if (0 == strncmp(sp->sectname, IMAGE_INFO_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, OBJC_SEGMENT, sizeof(sp->segname))) { - sectlength = _CFBundleSwapInt32Conditional(sp->size, swapped); - sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); - foundit = true; - } - sp = (struct section *)((char *)sp + sizeof(struct section)); - } - } - sgp = (struct segment_command *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); - } - } - if (sectlength >= 8) { - if (fd >= 0 && lseek(fd, offset + sectoffset, SEEK_SET) == (off_t)(offset + sectoffset) && read(fd, sectbuffer, 8) >= 8) { - localVersion = _CFBundleSwapInt32Conditional(*(uint32_t *)sectbuffer, swapped); - localFlags = _CFBundleSwapInt32Conditional(*(uint32_t *)(sectbuffer + 4), swapped); - } else if (bytes && length >= offset + sectoffset + 8) { - localVersion = _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes + offset + sectoffset), swapped); - localFlags = _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes + offset + sectoffset + 4), swapped); - } - } + if (reason) { + userInfoKeys[numKeys] = kCFErrorLocalizedFailureReasonKey; + userInfoValues[numKeys] = reason; + numKeys++; } - if (buffer) free(buffer); - if (hasObjc) *hasObjc = localHasObjc; - if (objcVersion) *objcVersion = localVersion; - if (objcFlags) *objcFlags = localFlags; -} - -static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex length, Boolean swap, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { - CFIndex headerLength = length; - unsigned char headerBuffer[MAGIC_BYTES_TO_READ]; - UInt32 machtype = UNKNOWN_FILETYPE, magic, numFatHeaders, maxFatHeaders, i; - unsigned char buffer[sizeof(struct mach_header_64)]; - const unsigned char *moreBytes = NULL; - const NXArchInfo *archInfo = NXGetLocalArchInfo(); - SInt32 curArch = _CFBundleCurrentArchitecture(); - - struct fat_arch *fat = NULL; - - if (isX11) *isX11 = false; - if (architectures) *architectures = NULL; - if (infodict) *infodict = NULL; - if (hasObjc) *hasObjc = false; - if (objcVersion) *objcVersion = 0; - if (objcFlags) *objcFlags = 0; - - if (headerLength > MAGIC_BYTES_TO_READ) headerLength = MAGIC_BYTES_TO_READ; - (void)memmove(headerBuffer, bytes, headerLength); - if (swap) { - for (i = 0; i < headerLength; i += 4) *(UInt32 *)(headerBuffer + i) = CFSwapInt32(*(UInt32 *)(headerBuffer + i)); + if (suggestion) { + userInfoKeys[numKeys] = kCFErrorLocalizedRecoverySuggestionKey; + userInfoValues[numKeys] = suggestion; + numKeys++; } - numFatHeaders = ((struct fat_header *)headerBuffer)->nfat_arch; - maxFatHeaders = (headerLength - sizeof(struct fat_header)) / sizeof(struct fat_arch); - if (numFatHeaders > maxFatHeaders) numFatHeaders = maxFatHeaders; - if (numFatHeaders > 0) { - if (archInfo) fat = NXFindBestFatArch(archInfo->cputype, archInfo->cpusubtype, (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)), numFatHeaders); - if (!fat && curArch != 0) fat = NXFindBestFatArch((cpu_type_t)curArch, (cpu_subtype_t)0, (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)), numFatHeaders); - if (!fat) fat = (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)); - if (architectures) { - CFMutableArrayRef mutableArchitectures = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - for (i = 0; i < numFatHeaders; i++) { - CFNumberRef architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, headerBuffer + sizeof(struct fat_header) + i * sizeof(struct fat_arch)); - if (CFArrayGetFirstIndexOfValue(mutableArchitectures, CFRangeMake(0, CFArrayGetCount(mutableArchitectures)), architecture) < 0) CFArrayAppendValue(mutableArchitectures, architecture); - CFRelease(architecture); - } - *architectures = (CFArrayRef)mutableArchitectures; - } - } - if (fat) { - if (fd >= 0 && lseek(fd, fat->offset, SEEK_SET) == (off_t)fat->offset && read(fd, buffer, sizeof(struct mach_header_64)) >= (int)sizeof(struct mach_header_64)) { - moreBytes = buffer; - } else if (bytes && (uint32_t)length >= fat->offset + sizeof(struct mach_header_64)) { - moreBytes = bytes + fat->offset; - } - if (moreBytes) { - magic = *((UInt32 *)moreBytes); - if (MH_MAGIC == magic) { - machtype = ((struct mach_header *)moreBytes)->filetype; - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, false, false); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, false, false); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, false, false, hasObjc, objcVersion, objcFlags); - } else if (MH_CIGAM == magic) { - machtype = CFSwapInt32(((struct mach_header *)moreBytes)->filetype); - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, true, false); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, true, false); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, true, false, hasObjc, objcVersion, objcFlags); - } else if (MH_MAGIC_64 == magic) { - machtype = ((struct mach_header_64 *)moreBytes)->filetype; - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, false, true); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, false, true); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, false, true, hasObjc, objcVersion, objcFlags); - } else if (MH_CIGAM_64 == magic) { - machtype = CFSwapInt32(((struct mach_header_64 *)moreBytes)->filetype); - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, true, true); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, true, true); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, true, true, hasObjc, objcVersion, objcFlags); - } - } + if (debugString) { + userInfoKeys[numKeys] = CFSTR("NSDebugDescription"); + userInfoValues[numKeys] = debugString; + numKeys++; } - return machtype; + error = CFErrorCreateWithUserInfoKeysAndValues(allocator, kCFErrorDomainCocoa, code, userInfoKeys, userInfoValues, numKeys); + if (bundleURL) CFRelease(bundleURL); + if (absoluteURL) CFRelease(absoluteURL); + if (executableURL) CFRelease(executableURL); + if (bundlePath) CFRelease(bundlePath); + if (executablePath) CFRelease(executablePath); + if (desc) CFRelease(desc); + if (reason) CFRelease(reason); + if (suggestion) CFRelease(suggestion); + return error; } -static UInt32 _CFBundleGrokMachType(int fd, const void *bytes, CFIndex length, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { - unsigned int magic = *((UInt32 *)bytes), machtype = UNKNOWN_FILETYPE, cputype; - CFNumberRef architecture = NULL; - - if (isX11) *isX11 = false; - if (architectures) *architectures = NULL; - if (infodict) *infodict = NULL; - if (hasObjc) *hasObjc = false; - if (objcVersion) *objcVersion = 0; - if (objcFlags) *objcFlags = 0; - if (MH_MAGIC == magic) { - machtype = ((struct mach_header *)bytes)->filetype; - cputype = ((struct mach_header *)bytes)->cputype; - if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, false, false); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, false, false); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, false, false, hasObjc, objcVersion, objcFlags); - } else if (MH_CIGAM == magic) { - machtype = CFSwapInt32(((struct mach_header *)bytes)->filetype); - cputype = CFSwapInt32(((struct mach_header *)bytes)->cputype); - if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, true, false); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, true, false); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, true, false, hasObjc, objcVersion, objcFlags); - } else if (MH_MAGIC_64 == magic) { - machtype = ((struct mach_header_64 *)bytes)->filetype; - cputype = ((struct mach_header_64 *)bytes)->cputype; - if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, false, true); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, false, true); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, false, true, hasObjc, objcVersion, objcFlags); - } else if (MH_CIGAM_64 == magic) { - machtype = CFSwapInt32(((struct mach_header_64 *)bytes)->filetype); - cputype = CFSwapInt32(((struct mach_header_64 *)bytes)->cputype); - if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); - if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, true, true); - if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, true, true); - if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, true, true, hasObjc, objcVersion, objcFlags); - } else if (FAT_MAGIC == magic) { - machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, false, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags); - } else if (FAT_CIGAM == magic) { - machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, true, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags); - } else if (PEF_MAGIC == magic || PEF_CIGAM == magic) { - machtype = PEF_FILETYPE; - } - if (architectures && architecture) *architectures = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&architecture, 1, &kCFTypeArrayCallBacks); - if (architecture) CFRelease(architecture); - return machtype; +CFErrorRef _CFBundleCreateError(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code) { + return _CFBundleCreateErrorDebug(allocator, bundle, code, NULL); } -#endif /* BINARY_SUPPORT_DYLD */ +#pragma mark - -static Boolean _CFBundleGrokFileTypeForZipMimeType(const unsigned char *bytes, CFIndex length, const char **ext) { - unsigned namelength = CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 26))), extralength = CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 28))); - const unsigned char *data = bytes + 30 + namelength + extralength; - int i = -1; - if (bytes < data && data + 56 <= bytes + length && 0 == CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 8))) && (0 == ustrncasecmp(data, "application/vnd.", 16) || 0 == ustrncasecmp(data, "application/x-vnd.", 18))) { - data += ('.' == *(data + 15)) ? 16 : 18; - if (0 == ustrncasecmp(data, "sun.xml.", 8)) { - data += 8; - if (0 == ustrncasecmp(data, "calc", 4)) i = 0; - else if (0 == ustrncasecmp(data, "draw", 4)) i = 1; - else if (0 == ustrncasecmp(data, "writer.global", 13)) i = 2; - else if (0 == ustrncasecmp(data, "impress", 7)) i = 3; - else if (0 == ustrncasecmp(data, "math", 4)) i = 4; - else if (0 == ustrncasecmp(data, "writer", 6)) i = 5; - if (i >= 0 && ext) *ext = __CFBundleOOExtensionsArray + i * EXTENSION_LENGTH; - } else if (0 == ustrncasecmp(data, "oasis.opendocument.", 19)) { - data += 19; - if (0 == ustrncasecmp(data, "chart", 5)) i = 0; - else if (0 == ustrncasecmp(data, "formula", 7)) i = 1; - else if (0 == ustrncasecmp(data, "graphics", 8)) i = 2; - else if (0 == ustrncasecmp(data, "text-web", 8)) i = 3; - else if (0 == ustrncasecmp(data, "image", 5)) i = 4; - else if (0 == ustrncasecmp(data, "text-master", 11)) i = 5; - else if (0 == ustrncasecmp(data, "presentation", 12)) i = 6; - else if (0 == ustrncasecmp(data, "spreadsheet", 11)) i = 7; - else if (0 == ustrncasecmp(data, "text", 4)) i = 8; - if (i >= 0 && ext) *ext = __CFBundleODExtensionsArray + i * EXTENSION_LENGTH; - } - } else if (bytes < data && data + 41 <= bytes + length && 8 == CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 8))) && 0x4b2c28c8 == CFSwapInt32HostToBig(*((UInt32 *)data)) && 0xc94c4e2c == CFSwapInt32HostToBig(*((UInt32 *)(data + 4)))) { - // AbiWord compressed mimetype odt - if (ext) *ext = "odt"; - // almost certainly this should set i to 0 but I don't want to upset the apple cart now - } else if (bytes < data && data + 29 <= bytes + length && (0 == ustrncasecmp(data, "application/oebps-package+xml", 29))) { - // epub, official epub 3 mime type - if (ext) *ext = "epub"; - i = 0; - } else if (bytes < data && data + 20 <= bytes + length && (0 == ustrncasecmp(data, "application/epub+zip", 20))) { - // epub, unofficial epub 2 mime type - if (ext) *ext = "epub"; - i = 0; - } - return (i >= 0); -} - -static const char *_CFBundleGrokFileTypeForZipFile(int fd, const unsigned char *bytes, CFIndex length, off_t fileLength) { - const char *ext = "zip"; - const unsigned char *moreBytes = NULL; - unsigned char *buffer = NULL; - CFIndex i; - Boolean foundMimetype = false, hasMetaInf = false, hasContentXML = false, hasManifestMF = false, hasManifestXML = false, hasRels = false, hasContentTypes = false, hasWordDocument = false, hasExcelDocument = false, hasPowerPointDocument = false, hasOPF = false, hasSMIL = false; - - if (bytes) { - for (i = 0; !foundMimetype && i + 30 < length; i++) { - if (0x50 == bytes[i] && 0x4b == bytes[i + 1]) { - unsigned namelength = 0, offset = 0; - if (0x01 == bytes[i + 2] && 0x02 == bytes[i + 3]) { - namelength = (unsigned)CFSwapInt16HostToLittle(*((UInt16 *)(bytes + i + 28))); - offset = 46; - } else if (0x03 == bytes[i + 2] && 0x04 == bytes[i + 3]) { - namelength = (unsigned)CFSwapInt16HostToLittle(*((UInt16 *)(bytes + i + 26))); - offset = 30; - } - if (offset > 0 && (CFIndex)(i + offset + namelength) <= length) { - //printf("%.*s\n", namelength, bytes + i + offset); - if (8 == namelength && 30 == offset && 0 == ustrncasecmp(bytes + i + offset, "mimetype", 8)) foundMimetype = _CFBundleGrokFileTypeForZipMimeType(bytes + i, length - i, &ext); - else if (9 == namelength && 0 == ustrncasecmp(bytes + i + offset, "META-INF/", 9)) hasMetaInf = true; - else if (11 == namelength && 0 == ustrncasecmp(bytes + i + offset, "content.xml", 11)) hasContentXML = true; - else if (11 == namelength && 0 == ustrncasecmp(bytes + i + offset, "_rels/.rels", 11)) hasRels = true; - else if (19 == namelength && 0 == ustrncasecmp(bytes + i + offset, "[Content_Types].xml", 19)) hasContentTypes = true; - else if (20 == namelength && 0 == ustrncasecmp(bytes + i + offset, "META-INF/MANIFEST.MF", 20)) hasManifestMF = true; - else if (21 == namelength && 0 == ustrncasecmp(bytes + i + offset, "META-INF/manifest.xml", 21)) hasManifestXML = true; - else if (4 < namelength && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".opf", 4)) hasOPF = true; - else if (4 < namelength && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".sml", 4)) hasSMIL = true; - else if (5 < namelength && 0 == ustrncasecmp(bytes + i + offset + namelength - 5, ".smil", 5)) hasSMIL = true; - else if (7 < namelength && 0 == ustrncasecmp(bytes + i + offset, "xl/", 3) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; - else if (8 < namelength && 0 == ustrncasecmp(bytes + i + offset, "ppt/", 4) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; - else if (9 < namelength && 0 == ustrncasecmp(bytes + i + offset, "word/", 5) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasWordDocument = true; - else if (10 < namelength && 0 == ustrncasecmp(bytes + i + offset, "excel/", 6) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; - else if (15 < namelength && 0 == ustrncasecmp(bytes + i + offset, "powerpoint/", 11) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; - i += offset + namelength - 1; - } - } - } - } - if (!foundMimetype) { - if (fileLength >= ZIP_BYTES_TO_READ) { - if (fd >= 0 && lseek(fd, fileLength - ZIP_BYTES_TO_READ, SEEK_SET) == fileLength - ZIP_BYTES_TO_READ) { - buffer = (unsigned char *)malloc(ZIP_BYTES_TO_READ); - if (buffer && read(fd, buffer, ZIP_BYTES_TO_READ) >= ZIP_BYTES_TO_READ) moreBytes = buffer; - } else if (bytes && length >= ZIP_BYTES_TO_READ) { - moreBytes = bytes + length - ZIP_BYTES_TO_READ; - } - } - if (moreBytes) { - for (i = 0; i + 30 < ZIP_BYTES_TO_READ; i++) { - if (0x50 == moreBytes[i] && 0x4b == moreBytes[i + 1]) { - unsigned namelength = 0, offset = 0; - if (0x01 == moreBytes[i + 2] && 0x02 == moreBytes[i + 3]) { - namelength = CFSwapInt16HostToLittle(*((UInt16 *)(moreBytes + i + 28))); - offset = 46; - } else if (0x03 == moreBytes[i + 2] && 0x04 == moreBytes[i + 3]) { - namelength = CFSwapInt16HostToLittle(*((UInt16 *)(moreBytes + i + 26))); - offset = 30; - } - if (offset > 0 && i + offset + namelength <= ZIP_BYTES_TO_READ) { - //printf("%.*s\n", namelength, moreBytes + i + offset); - if (9 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "META-INF/", 9)) hasMetaInf = true; - else if (11 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "content.xml", 11)) hasContentXML = true; - else if (11 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "_rels/.rels", 11)) hasRels = true; - else if (19 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "[Content_Types].xml", 19)) hasContentTypes = true; - else if (20 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "META-INF/MANIFEST.MF", 20)) hasManifestMF = true; - else if (21 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "META-INF/manifest.xml", 21)) hasManifestXML = true; - else if (4 < namelength && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".opf", 4)) hasOPF = true; - else if (4 < namelength && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".sml", 4)) hasSMIL = true; - else if (5 < namelength && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 5, ".smil", 5)) hasSMIL = true; - else if (7 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "xl/", 3) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; - else if (8 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "ppt/", 4) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; - else if (9 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "word/", 5) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasWordDocument = true; - else if (10 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "excel/", 6) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; - else if (15 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "powerpoint/", 11) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; - i += offset + namelength - 1; - } - } - } - } - //printf("hasManifestMF %d hasManifestXML %d hasContentXML %d hasRels %d hasContentTypes %d hasWordDocument %d hasExcelDocument %d hasPowerPointDocument %d hasMetaInf %d hasOPF %d hasSMIL %d\n", hasManifestMF, hasManifestXML, hasContentXML, hasRels, hasContentTypes, hasWordDocument, hasExcelDocument, hasPowerPointDocument, hasMetaInf, hasOPF, hasSMIL); - if (hasManifestMF) ext = "jar"; - else if ((hasRels || hasContentTypes) && hasWordDocument) ext = "docx"; - else if ((hasRels || hasContentTypes) && hasExcelDocument) ext = "xlsx"; - else if ((hasRels || hasContentTypes) && hasPowerPointDocument) ext = "pptx"; - else if (hasManifestXML || hasContentXML) ext = "odt"; - else if (hasMetaInf) ext = "jar"; - else if (hasOPF && hasSMIL) ext = "dtb"; - else if (hasOPF) ext = "oeb"; - - if (buffer) free(buffer); - } - return ext; -} - -static Boolean _CFBundleCheckOLEName(const char *name, const char *bytes, unsigned length) { - Boolean retval = true; - unsigned j; - for (j = 0; retval && j < length; j++) if (bytes[2 * j] != name[j]) retval = false; - return retval; -} - -static const char *_CFBundleGrokFileTypeForOLEFile(int fd, const void *bytes, CFIndex length, off_t offset) { - const char *ext = "ole", *moreBytes = NULL; - char *buffer = NULL; - - if (fd >= 0 && lseek(fd, offset, SEEK_SET) == (off_t)offset) { - buffer = (char *)malloc(OLE_BYTES_TO_READ); - if (buffer && read(fd, buffer, OLE_BYTES_TO_READ) >= OLE_BYTES_TO_READ) moreBytes = buffer; - } else if (bytes && length >= offset + OLE_BYTES_TO_READ) { - moreBytes = (char *)bytes + offset; - } - if (moreBytes) { - Boolean foundit = false; - unsigned i; - for (i = 0; !foundit && i < 4; i++) { - char namelength = moreBytes[128 * i + 64] / 2; - foundit = true; - if (sizeof(XLS_NAME) == namelength && _CFBundleCheckOLEName(XLS_NAME, moreBytes + 128 * i, namelength - 1)) ext = "xls"; - else if (sizeof(XLS_NAME2) == namelength && _CFBundleCheckOLEName(XLS_NAME2, moreBytes + 128 * i, namelength - 1)) ext = "xls"; - else if (sizeof(DOC_NAME) == namelength && _CFBundleCheckOLEName(DOC_NAME, moreBytes + 128 * i, namelength - 1)) ext = "doc"; - else if (sizeof(PPT_NAME) == namelength && _CFBundleCheckOLEName(PPT_NAME, moreBytes + 128 * i, namelength - 1)) ext = "ppt"; - else foundit = false; - } - } - if (buffer) free(buffer); - return ext; -} - -static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *extension, UInt32 *machtype, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { - int fd = -1; - const unsigned char *bytes = NULL; - unsigned char buffer[MAGIC_BYTES_TO_READ]; - CFIndex i, length = 0; - off_t fileLength = 0; - const char *ext = NULL; - UInt32 mt = UNKNOWN_FILETYPE; -#if defined(BINARY_SUPPORT_DYLD) - Boolean isX11 = false; -#endif /* BINARY_SUPPORT_DYLD */ - Boolean isFile = false, isPlain = true, isZero = true, isSpace = true, hasBOM = false; - // extensions returned: o, tool, x11app, pef, core, dylib, bundle, elf, jpeg, jp2, tiff, gif, png, pict, icns, ico, rtf, rtfd, pdf, ra, rm, au, aiff, aifc, caf, wav, avi, wmv, ogg, flac, psd, mpeg, mid, zip, jar, sit, cpio, html, ps, mov, qtif, ttf, otf, sfont, bmp, hqx, bin, class, tar, txt, gz, Z, uu, ync, bz, bz2, sh, pl, py, rb, dvi, sgi, tga, mp3, xml, plist, xls, doc, ppt, mp4, m4a, m4b, m4p, m4v, 3gp, 3g2, dmg, cwk, webarchive, dwg, dgn, pfa, pfb, afm, tfm, xcf, cpx, dwf, swf, swc, abw, bom, lit, svg, rdf, x3d, oeb, dtb, docx, xlsx, pptx, sxc, sxd, sxg, sxi, sxm, sxw, odc, odf, odg, oth, odi, odm, odp, ods, cin, exr - // ??? we do not distinguish between different wm types, returning wmv for any of wmv, wma, or asf - // ??? we do not distinguish between ordinary documents and template versions (often there is no difference in file contents) - // ??? the distinctions between docx, xlsx, and pptx may not be entirely reliable - if (architectures) *architectures = NULL; - if (infodict) *infodict = NULL; - if (hasObjc) *hasObjc = false; - if (objcVersion) *objcVersion = 0; - if (objcFlags) *objcFlags = 0; - if (url) { - Boolean gotPath = FALSE; - char path[CFMaxPathSize]; - gotPath = CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize); - struct statinfo statBuf; - if (gotPath && stat(path, &statBuf) == 0 && (statBuf.st_mode & S_IFMT) == S_IFREG && (fd = open(path, O_RDONLY | CF_OPENFLGS, 0777)) >= 0) { - length = read(fd, buffer, MAGIC_BYTES_TO_READ); - fileLength = statBuf.st_size; - bytes = buffer; - isFile = true; - } - } - if (!isFile && data) { - length = CFDataGetLength(data); - fileLength = (off_t)length; - bytes = CFDataGetBytePtr(data); - if (length == 0) ext = "txt"; - } - if (bytes) { - if (length >= 4) { - UInt32 magic = CFSwapInt32HostToBig(*((UInt32 *)bytes)); - for (i = 0; !ext && i < NUM_EXTENSIONS; i++) { - if (__CFBundleMagicNumbersArray[i] == magic) ext = __CFBundleExtensionsArray + i * EXTENSION_LENGTH; - } - if (ext) { - if (0xcafebabe == magic && 8 <= length && 0 != *((UInt16 *)(bytes + 4))) ext = "class"; -#if defined(BINARY_SUPPORT_DYLD) - else if ((int)sizeof(struct mach_header_64) <= length) mt = _CFBundleGrokMachType(fd, bytes, length, extension ? &isX11 : NULL, architectures, infodict, hasObjc, objcVersion, objcFlags); - - if (MH_OBJECT == mt) ext = "o"; - else if (MH_EXECUTE == mt) ext = isX11 ? "x11app" : "tool"; - else if (PEF_FILETYPE == mt) ext = "pef"; - else if (MH_CORE == mt) ext = "core"; - else if (MH_DYLIB == mt) ext = "dylib"; - else if (MH_BUNDLE == mt) ext = "bundle"; -#endif /* BINARY_SUPPORT_DYLD */ - else if (0x7b5c7274 == magic && (6 > length || 'f' != bytes[4])) ext = NULL; - else if (0x25504446 == magic && (6 > length || '-' != bytes[4])) ext = NULL; - else if (0x00010000 == magic && (6 > length || 0 != bytes[4])) ext = NULL; - else if (0x47494638 == magic && (6 > length || (0x3761 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))) && 0x3961 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4)))))) ext = NULL; - else if (0x0000000c == magic && (6 > length || 0x6a50 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL; - else if (0x2356524d == magic && (6 > length || 0x4c20 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL; - else if (0x28445746 == magic && (6 > length || 0x2056 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL; - else if (0x30373037 == magic && (6 > length || 0x30 != bytes[4] || !isdigit(bytes[5]))) ext = NULL; - else if (0x41433130 == magic && (6 > length || 0x31 != bytes[4] || !isdigit(bytes[5]))) ext = NULL; - else if (0x89504e47 == magic && (8 > length || 0x0d0a1a0a != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x53747566 == magic && (8 > length || 0x66497420 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x3026b275 == magic && (8 > length || 0x8e66cf11 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x67696d70 == magic && (8 > length || 0x20786366 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x424f4d53 == magic && (8 > length || 0x746f7265 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x49544f4c == magic && (8 > length || 0x49544c53 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x72746664 == magic && (8 > length || 0x00000000 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; - else if (0x3d796265 == magic && (12 > length || 0x67696e20 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || (0x6c696e65 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))) && 0x70617274 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))))) ext = NULL; - else if (0x63616666 == magic && (12 > length || 0 != bytes[4] || 0x64657363 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))))) ext = NULL; - else if (0x504b0304 == magic) ext = _CFBundleGrokFileTypeForZipFile(fd, bytes, length, fileLength); - else if (0x25215053 == magic) { - if (11 <= length && 0 == ustrncmp(bytes + 4, "-Adobe-", 7)) ext = "ps"; - else if (14 <= length && 0 == ustrncmp(bytes + 4, "-AdobeFont", 10)) ext = "pfa"; - else ext = NULL; - } else if (0x464f524d == magic) { - // IFF - ext = NULL; - if (12 <= length) { - UInt32 iffMagic = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))); - if (0x41494646 == iffMagic) ext = "aiff"; - else if (0x414946 == iffMagic) ext = "aifc"; - } - } else if (0x52494646 == magic) { - // RIFF - ext = NULL; - if (12 <= length) { - UInt32 riffMagic = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))); - if (0x57415645 == riffMagic) ext = "wav"; - else if (0x41564920 == riffMagic) ext = "avi"; - } - } else if (0xd0cf11e0 == magic) { - // OLE - if (52 <= length) ext = _CFBundleGrokFileTypeForOLEFile(fd, bytes, length, 512 * (1 + CFSwapInt32HostToLittle(*((UInt32 *)(bytes + 48))))); - } else if (0x62656769 == magic) { - // uu - ext = NULL; - if (76 <= length && 'n' == bytes[4] && ' ' == bytes[5] && isdigit(bytes[6]) && isdigit(bytes[7]) && isdigit(bytes[8]) && ' ' == bytes[9]) { - CFIndex endOfLine = 0; - for (i = 10; 0 == endOfLine && i < length; i++) if ('\n' == bytes[i]) endOfLine = i; - if (10 <= endOfLine && endOfLine + 62 < length && 'M' == bytes[endOfLine + 1] && '\n' == bytes[endOfLine + 62]) { - ext = "uu"; - for (i = endOfLine + 1; ext && i < endOfLine + 62; i++) if (!isprint(bytes[i])) ext = NULL; - } - } - } - } - if (extension && !ext) { - UInt16 shortMagic = CFSwapInt16HostToBig(*((UInt16 *)bytes)); - if (5 <= length && 0 == bytes[3] && 0 == bytes[4] && ((1 == bytes[1] && 1 == (0xf7 & bytes[2])) || (0 == bytes[1] && (2 == (0xf7 & bytes[2]) || (3 == (0xf7 & bytes[2])))))) ext = "tga"; - else if (8 <= length && (0x6d6f6f76 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x6d646174 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x77696465 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "mov"; - else if (8 <= length && (0x69647363 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x69646174 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "qtif"; - else if (8 <= length && 0x424f424f == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4)))) ext = "cwk"; - else if (8 <= length && 0x62706c69 == magic && 0x7374 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))) && isdigit(bytes[6]) && isdigit(bytes[7])) { - for (i = 8; !ext && i < 128 && i + 16 <= length; i++) { - if (0 == ustrncmp(bytes + i, "WebMainResource", 15)) ext = "webarchive"; - } - if (!ext) ext = "plist"; - } else if (0 == shortMagic && 12 <= length && 0x66747970 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4)))) { - // ??? may want more ftyp values - UInt32 ftyp = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))); - if (0x6d703431 == ftyp || 0x6d703432 == ftyp || 0x69736f6d == ftyp || 0x69736f32 == ftyp) ext = "mp4"; - else if (0x4d344120 == ftyp) ext = "m4a"; - else if (0x4d344220 == ftyp) ext = "m4b"; - else if (0x4d345020 == ftyp) ext = "m4p"; - else if (0x4d345620 == ftyp || 0x4d345648 == ftyp || 0x4d345650 == ftyp) ext = "m4v"; - else if (0x3367 == (ftyp >> 16)) { - UInt16 remainder = (ftyp & 0xffff); - if (0x6536 == remainder || 0x6537 == remainder || 0x6736 == remainder || 0x7034 == remainder || 0x7035 == remainder || 0x7036 == remainder || 0x7236 == remainder || 0x7336 == remainder || 0x7337 == remainder) ext = "3gp"; - else if (0x3261 == remainder) ext = "3g2"; - } - } else if (0x424d == shortMagic && 18 <= length) { - UInt32 btyp = CFSwapInt32HostToLittle(*((UInt32 *)(bytes + 14))); - if (40 == btyp || btyp == 12 || btyp == 64 || btyp == 108 || btyp == 124) ext = "bmp"; - } else if (20 <= length && 0 == ustrncmp(bytes + 6, "%!PS-AdobeFont", 14)) ext = "pfb"; - else if (40 <= length && 0x42696e48 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 34))) && 0x6578 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 38)))) ext = "hqx"; - else if (128 <= length && 0x6d42494e == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 102)))) ext = "bin"; - else if (128 <= length && 0 == bytes[0] && 0 < bytes[1] && bytes[1] < 64 && 0 == bytes[74] && 0 == bytes[82] && 0 == (fileLength % 128)) { - UInt32 df = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 83))), rf = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 87))), blocks = 1 + (df + 127) / 128 + (rf + 127) / 128; - if (df < 0x00800000 && rf < 0x00800000 && 1 < blocks && (off_t)(128 * blocks) == fileLength) ext = "bin"; - } else if (265 <= length && 0x75737461 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 257))) && (0x72202000 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 261))) || 0x7200 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 261))))) ext = "tar"; - else if (0xfeff == shortMagic || 0xfffe == shortMagic) { - ext = "txt"; - if (12 <= length && ((0x3cfeff == *((UInt32 *)bytes) && 0x740068 == *((UInt32 *)(bytes + 4)) && 0x6c006d == *((UInt32 *)(bytes + 8))) || (0xfffe3c00 == *((UInt32 *)bytes) && 0x68007400 == *((UInt32 *)(bytes + 4)) && 0x6d006c00 == *((UInt32 *)(bytes + 8))))) ext = "html"; - } else if (0x1f9d == shortMagic) ext = "Z"; - else if (0x1f8b == shortMagic) ext = "gz"; - else if (0x71c7 == shortMagic || 0xc771 == shortMagic) ext = "cpio"; - else if (0xf702 == shortMagic) ext = "dvi"; - else if (0x01da == shortMagic && (0 == bytes[2] || 1 == bytes[2]) && (0 < bytes[3] && 16 > bytes[3])) ext = "sgi"; - else if (0x2321 == shortMagic) { - CFIndex endOfLine = 0, lastSlash = 0; - for (i = 2; 0 == endOfLine && i < length; i++) if ('\n' == bytes[i]) endOfLine = i; - if (endOfLine > 3) { - for (i = endOfLine - 1; 0 == lastSlash && i > 1; i--) if ('/' == bytes[i]) lastSlash = i; - if (lastSlash > 0) { - if (0 == ustrncmp(bytes + lastSlash + 1, "perl", 4)) ext = "pl"; - else if (0 == ustrncmp(bytes + lastSlash + 1, "python", 6)) ext = "py"; - else if (0 == ustrncmp(bytes + lastSlash + 1, "ruby", 4)) ext = "rb"; - else ext = "sh"; - } - } - } else if (0xffd8 == shortMagic && 0xff == bytes[2]) ext = "jpeg"; - else if (0x4657 == shortMagic && 0x53 == bytes[2]) ext = "swf"; - else if (0x4357 == shortMagic && 0x53 == bytes[2]) ext = "swc"; - else if (0x4944 == shortMagic && '3' == bytes[2] && 0x20 > bytes[3]) ext = "mp3"; - else if (0x425a == shortMagic && isdigit(bytes[2]) && isdigit(bytes[3])) ext = "bz"; - else if (0x425a == shortMagic && 'h' == bytes[2] && isdigit(bytes[3]) && 8 <= length && (0x31415926 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x17724538 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "bz2"; - else if (0x0011 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 2))) || 0x0012 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 2)))) ext = "tfm"; - } - } - if (extension && !ext) { - //??? what about MacOSRoman? - if (0xef == bytes[0] && 0xbb == bytes[1] && 0xbf == bytes[2]) { // UTF-8 BOM - hasBOM = true; - isZero = false; - } - for (i = (hasBOM ? 3 : 0); (isPlain || isZero) && !ext && i < length && i < 512; i++) { - char c = bytes[i]; - if (isPlain && '<' == c && i + 14 <= length && 0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) ext = "html"; - if (isSpace && '<' == c && i + 14 <= length) { - if (0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13) || 0 == ustrncasecmp(bytes + i + 1, "head", 4) || 0 == ustrncasecmp(bytes + i + 1, "title", 5) || 0 == ustrncasecmp(bytes + i + 1, "script", 6) || 0 == ustrncasecmp(bytes + i + 1, "html", 4)) { - ext = "html"; - } else if (0 == ustrncasecmp(bytes + i + 1, "?xml", 4)) { - for (i += 4; !ext && i < 128 && i + 20 <= length; i++) { - if ('<' == bytes[i]) { - if (0 == ustrncasecmp(bytes + i + 1, "abiword", 7)) ext = "abw"; - else if (0 == ustrncasecmp(bytes + i + 1, "!doctype svg", 12)) ext = "svg"; - else if (0 == ustrncasecmp(bytes + i + 1, "!doctype rdf", 12)) ext = "rdf"; - else if (0 == ustrncasecmp(bytes + i + 1, "!doctype x3d", 12)) ext = "x3d"; - else if (0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) ext = "html"; - else if (0 == ustrncasecmp(bytes + i + 1, "!doctype posingfont", 19)) ext = "sfont"; - else if (0 == ustrncasecmp(bytes + i + 1, "!doctype plist", 14)) { - for (i += 14; !ext && i < 256 && i + 16 <= length; i++) { - if (0 == ustrncmp(bytes + i, "WebMainResource", 15)) ext = "webarchive"; - } - if (!ext) ext = "plist"; - } - } - } - if (!ext) ext = "xml"; - } - } - if (0 != c) isZero = false; - if (isZero || 0x7f <= c || (0x20 > c && !isspace(c))) isPlain = false; - if (isZero || !isspace(c)) isSpace = false; - } - if (!ext) { - if (isPlain) { - if (16 <= length && 0 == ustrncmp(bytes, "StartFontMetrics", 16)) ext = "afm"; - else ext = "txt"; - } else if (isZero && length >= MAGIC_BYTES_TO_READ && fileLength >= 526) { - if (isFile) { - if (lseek(fd, 512, SEEK_SET) == 512 && read(fd, buffer, MAGIC_BYTES_TO_READ) >= 14) { - if (0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(buffer + 10)))) ext = "pict"; - } - } else { - if (526 <= length && 0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 522)))) ext = "pict"; - } - } - } - } - if (extension && (!ext || 0 == strcmp(ext, "bz2")) && length >= MAGIC_BYTES_TO_READ && fileLength >= DMG_BYTES_TO_READ) { - if (isFile) { - if (lseek(fd, fileLength - DMG_BYTES_TO_READ, SEEK_SET) == fileLength - DMG_BYTES_TO_READ && read(fd, buffer, DMG_BYTES_TO_READ) >= DMG_BYTES_TO_READ) { - if (0x6b6f6c79 == CFSwapInt32HostToBig(*((UInt32 *)buffer)) || (0x63647361 == CFSwapInt32HostToBig(*((UInt32 *)(buffer + DMG_BYTES_TO_READ - 8))) && 0x656e6372 == CFSwapInt32HostToBig(*((UInt32 *)(buffer + DMG_BYTES_TO_READ - 4))))) ext = "dmg"; - } - } else { - if (DMG_BYTES_TO_READ <= length && (0x6b6f6c79 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + length - DMG_BYTES_TO_READ))) || (0x63647361 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + length - 8))) && 0x656e6372 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + length - 4)))))) ext = "dmg"; - } - } - } - if (extension) *extension = ext ? CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, ext, kCFStringEncodingUTF8, kCFAllocatorNull) : NULL; - if (machtype) *machtype = mt; - if (fd >= 0) close(fd); - return (ext ? true : false); -} - -CFStringRef _CFBundleCopyFileTypeForFileURL(CFURLRef url) { - CFStringRef extension = NULL; - (void)_CFBundleGrokFileType(url, NULL, &extension, NULL, NULL, NULL, NULL, NULL, NULL); - return extension; -} - -CFStringRef _CFBundleCopyFileTypeForFileData(CFDataRef data) { - CFStringRef extension = NULL; - (void)_CFBundleGrokFileType(NULL, data, &extension, NULL, NULL, NULL, NULL, NULL, NULL); - return extension; -} - -CF_PRIVATE CFDictionaryRef _CFBundleCopyInfoDictionaryInExecutable(CFURLRef url) { - CFDictionaryRef result = NULL; - (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, NULL, &result, NULL, NULL, NULL); - return result; -} - -CF_PRIVATE CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef url) { - CFArrayRef result = NULL; - (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, &result, NULL, NULL, NULL, NULL); - return result; -} - -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -static Boolean _CFBundleGetObjCImageInfoForExecutable(CFURLRef url, uint32_t *objcVersion, uint32_t *objcFlags) { - Boolean retval = false; - (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, NULL, NULL, &retval, objcVersion, objcFlags); - return retval; -} -#endif - -#if defined(BINARY_SUPPORT_DYLD) - -CF_PRIVATE __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableURL) { - // Attempt to grok the type of the binary by looking for DYLD magic numbers. If one of the DYLD magic numbers is found, find out what type of Mach-o file it is. Otherwise, look for the PEF magic numbers to see if it is CFM. - __CFPBinaryType result = executableURL ? __CFBundleUnreadableBinary : __CFBundleNoBinary; - UInt32 machtype = UNKNOWN_FILETYPE; - if (_CFBundleGrokFileType(executableURL, NULL, NULL, &machtype, NULL, NULL, NULL, NULL, NULL)) { - switch (machtype) { - case MH_EXECUTE: - result = __CFBundleDYLDExecutableBinary; - break; - case MH_BUNDLE: - result = __CFBundleDYLDBundleBinary; - break; - case MH_DYLIB: - result = __CFBundleDYLDFrameworkBinary; - break; - case PEF_FILETYPE: - result = __CFBundleCFMBinary; - break; - } - } - return result; -} - -#endif /* BINARY_SUPPORT_DYLD */ - -void _CFBundleSetCFMConnectionID(CFBundleRef bundle, void *connectionID) { - bundle->_connectionCookie = connectionID; - bundle->_isLoaded = true; -} - -static CFStringRef _CFBundleCopyLastPathComponent(CFBundleRef bundle) { - CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); - if (!bundleURL) { - return CFSTR(""); - } - CFStringRef str = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); - UniChar buff[CFMaxPathSize]; - CFIndex buffLen = CFStringGetLength(str), startOfLastDir = 0; - - CFRelease(bundleURL); - if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize; - CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff); - CFRelease(str); - if (buffLen > 0) startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen); - return CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfLastDir]), buffLen - startOfLastDir); -} - -static CFErrorRef _CFBundleCreateErrorDebug(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code, CFStringRef debugString) { - const void *userInfoKeys[6], *userInfoValues[6]; - CFIndex numKeys = 0; - CFURLRef bundleURL = CFBundleCopyBundleURL(bundle), absoluteURL = CFURLCopyAbsoluteURL(bundleURL), executableURL = CFBundleCopyExecutableURL(bundle); - CFBundleRef bdl = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation")); - CFStringRef bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE), executablePath = executableURL ? CFURLCopyFileSystemPath(executableURL, PLATFORM_PATH_STYLE) : NULL, descFormat = NULL, desc = NULL, reason = NULL, suggestion = NULL; - CFErrorRef error; - if (bdl) { - CFStringRef name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleNameKey); - name = name ? (CFStringRef)CFRetain(name) : _CFBundleCopyLastPathComponent(bundle); - if (CFBundleExecutableNotFoundError == code) { - descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable couldn\\U2019t be located."), "NSFileNoSuchFileError"); - reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable couldn\\U2019t be located."), "NSFileNoSuchFileError"); - suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError"); - } else if (CFBundleExecutableNotLoadableError == code) { - descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable isn\\U2019t loadable."), "NSExecutableNotLoadableError"); - reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable isn\\U2019t loadable."), "NSExecutableNotLoadableError"); - suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError"); - } else if (CFBundleExecutableArchitectureMismatchError == code) { - descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError"); - reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl, CFSTR("The bundle doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError"); - suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError"); - } else if (CFBundleExecutableRuntimeMismatchError == code) { - descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it isn\\U2019t compatible with the current application."), "NSExecutableRuntimeMismatchError"); - reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl, CFSTR("The bundle isn\\U2019t compatible with this application."), "NSExecutableRuntimeMismatchError"); - suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError"); - } else if (CFBundleExecutableLoadError == code) { - descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it is damaged or missing necessary resources."), "NSExecutableLoadError"); - reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError"); - suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError"); - } else if (CFBundleExecutableLinkError == code) { - descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded."), "NSExecutableLinkError"); - reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl, CFSTR("The bundle couldn\\U2019t be loaded."), "NSExecutableLinkError"); - suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError"); - } - if (descFormat) { - desc = CFStringCreateWithFormat(allocator, NULL, descFormat, name); - CFRelease(descFormat); - } - CFRelease(name); - } - if (bundlePath) { - userInfoKeys[numKeys] = CFSTR("NSBundlePath"); - userInfoValues[numKeys] = bundlePath; - numKeys++; - } - if (executablePath) { - userInfoKeys[numKeys] = CFSTR("NSFilePath"); - userInfoValues[numKeys] = executablePath; - numKeys++; - } - if (desc) { - userInfoKeys[numKeys] = kCFErrorLocalizedDescriptionKey; - userInfoValues[numKeys] = desc; - numKeys++; - } - if (reason) { - userInfoKeys[numKeys] = kCFErrorLocalizedFailureReasonKey; - userInfoValues[numKeys] = reason; - numKeys++; - } - if (suggestion) { - userInfoKeys[numKeys] = kCFErrorLocalizedRecoverySuggestionKey; - userInfoValues[numKeys] = suggestion; - numKeys++; - } - if (debugString) { - userInfoKeys[numKeys] = CFSTR("NSDebugDescription"); - userInfoValues[numKeys] = debugString; - numKeys++; - } - error = CFErrorCreateWithUserInfoKeysAndValues(allocator, kCFErrorDomainCocoa, code, userInfoKeys, userInfoValues, numKeys); - if (bundleURL) CFRelease(bundleURL); - if (absoluteURL) CFRelease(absoluteURL); - if (executableURL) CFRelease(executableURL); - if (bundlePath) CFRelease(bundlePath); - if (executablePath) CFRelease(executablePath); - if (desc) CFRelease(desc); - if (reason) CFRelease(reason); - if (suggestion) CFRelease(suggestion); - return error; -} - -CFErrorRef _CFBundleCreateError(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code) { - return _CFBundleCreateErrorDebug(allocator, bundle, code, NULL); -} - -Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { - Boolean result = false; - CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); +Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { + Boolean result = false; + CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); pthread_mutex_lock(&(bundle->_bundleLoadingLock)); @@ -3155,21 +2143,6 @@ CFArrayRef CFBundleCopyExecutableArchitectures(CFBundleRef bundle) { return result; } -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -static Boolean _CFBundleGetObjCImageInfo(CFBundleRef bundle, uint32_t *objcVersion, uint32_t *objcFlags) { - Boolean retval = false; - uint32_t localVersion = 0, localFlags = 0; - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - if (executableURL) { - retval = _CFBundleGetObjCImageInfoForExecutable(executableURL, &localVersion, &localFlags); - CFRelease(executableURL); - } - if (objcVersion) *objcVersion = localVersion; - if (objcFlags) *objcFlags = localFlags; - return retval; -} -#endif - void CFBundleUnloadExecutable(CFBundleRef bundle) { // First unload bundles scheduled for unloading (if that's not what we are already doing.) if (!_scheduledBundlesAreUnloading) _CFBundleUnloadScheduledBundles(); @@ -3304,144 +2277,26 @@ CF_PRIVATE void _CFBundleUnloadScheduledBundles(void) { #endif /* AVOID_WEAK_COLLECTIONS */ -void *CFBundleGetFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) { - void *tvp = NULL; - // Load if necessary - if (!bundle->_isLoaded) { - if (!CFBundleLoadExecutable(bundle)) return NULL; - } - - switch (bundle->_binaryType) { -#if defined(BINARY_SUPPORT_DYLD) - case __CFBundleDYLDBundleBinary: - case __CFBundleDYLDFrameworkBinary: - case __CFBundleDYLDExecutableBinary: -#if defined(BINARY_SUPPORT_DLFCN) - if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName); -#else /* BINARY_SUPPORT_DLFCN */ - return _CFBundleDYLDGetSymbolByName(bundle, funcName); -#endif /* BINARY_SUPPORT_DLFCN */ - break; -#endif /* BINARY_SUPPORT_DYLD */ -#if defined(BINARY_SUPPORT_DLL) - case __CFBundleDLLBinary: - tvp = _CFBundleDLLGetSymbolByName(bundle, funcName); - break; -#endif /* BINARY_SUPPORT_DLL */ - default: -#if defined(BINARY_SUPPORT_DLFCN) - if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName); -#endif /* BINARY_SUPPORT_DLFCN */ - break; - } - return tvp; -} +#pragma mark - -void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) { - void *fp = NULL; - // Load if necessary - if (!bundle->_isLoaded) { - if (!CFBundleLoadExecutable(bundle)) return NULL; - } -#if defined (BINARY_SUPPORT_DYLD) || defined (BINARY_SUPPORT_DLFCN) - switch (bundle->_binaryType) { -#if defined(BINARY_SUPPORT_DYLD) - case __CFBundleDYLDBundleBinary: - case __CFBundleDYLDFrameworkBinary: - case __CFBundleDYLDExecutableBinary: -#if defined(BINARY_SUPPORT_DLFCN) - if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true); -#else /* BINARY_SUPPORT_DLFCN */ - fp = _CFBundleDYLDGetSymbolByNameWithSearch(bundle, funcName, true); -#endif /* BINARY_SUPPORT_DLFCN */ - break; -#endif /* BINARY_SUPPORT_DYLD */ - default: -#if defined(BINARY_SUPPORT_DLFCN) - if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true); -#endif /* BINARY_SUPPORT_DLFCN */ - break; - } -#endif /* BINARY_SUPPORT_DYLD || BINARY_SUPPORT_DLFCN */ - return fp; +CF_PRIVATE _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle) { + return &(bundle->_resourceData); } -void CFBundleGetFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) { - SInt32 i, c; - - if (!ftbl) return; - - c = CFArrayGetCount(functionNames); - for (i = 0; i < c; i++) ftbl[i] = CFBundleGetFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i)); +CFPlugInRef CFBundleGetPlugIn(CFBundleRef bundle) { + return (bundle->_plugInData._isPlugIn) ? (CFPlugInRef)bundle : NULL; } -void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) { - SInt32 i, c; - - if (!ftbl) return; +CF_PRIVATE _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle) { + return &(bundle->_plugInData); +} - c = CFArrayGetCount(functionNames); - for (i = 0; i < c; i++) ftbl[i] = _CFBundleGetCFMFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i)); -} - -void *CFBundleGetDataPointerForName(CFBundleRef bundle, CFStringRef symbolName) { - void *dp = NULL; - // Load if necessary - if (!bundle->_isLoaded && !CFBundleLoadExecutable(bundle)) return NULL; - - switch (bundle->_binaryType) { -#if defined(BINARY_SUPPORT_DYLD) - case __CFBundleDYLDBundleBinary: - case __CFBundleDYLDFrameworkBinary: - case __CFBundleDYLDExecutableBinary: -#if defined(BINARY_SUPPORT_DLFCN) - if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName); -#else /* BINARY_SUPPORT_DLFCN */ - dp = _CFBundleDYLDGetSymbolByName(bundle, symbolName); -#endif /* BINARY_SUPPORT_DLFCN */ - break; -#endif /* BINARY_SUPPORT_DYLD */ -#if defined(BINARY_SUPPORT_DLL) - case __CFBundleDLLBinary: - /* MF:!!! Handle this someday */ - break; -#endif /* BINARY_SUPPORT_DLL */ - default: -#if defined(BINARY_SUPPORT_DLFCN) - if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName); -#endif /* BINARY_SUPPORT_DLFCN */ - break; - } - return dp; -} - -void CFBundleGetDataPointersForNames(CFBundleRef bundle, CFArrayRef symbolNames, void *stbl[]) { - SInt32 i, c; - - if (!stbl) return; - - c = CFArrayGetCount(symbolNames); - for (i = 0; i < c; i++) stbl[i] = CFBundleGetDataPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(symbolNames, i)); -} - -CF_PRIVATE _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle) { - return &(bundle->_resourceData); -} - -CFPlugInRef CFBundleGetPlugIn(CFBundleRef bundle) { - return (bundle->_plugInData._isPlugIn) ? (CFPlugInRef)bundle : NULL; -} - -CF_PRIVATE _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle) { - return &(bundle->_plugInData); -} - -CF_PRIVATE Boolean _CFBundleCouldBeBundle(CFURLRef url) { - Boolean result = false; - Boolean exists; - SInt32 mode; - if (_CFGetFileProperties(kCFAllocatorSystemDefault, url, &exists, &mode, NULL, NULL, NULL, NULL) == 0) result = (exists && (mode & S_IFMT) == S_IFDIR && (mode & 0444) != 0); - return result; +CF_PRIVATE Boolean _CFBundleCouldBeBundle(CFURLRef url) { + Boolean result = false; + Boolean exists; + SInt32 mode; + if (_CFGetFileProperties(kCFAllocatorSystemDefault, url, &exists, &mode, NULL, NULL, NULL, NULL) == 0) result = (exists && (mode & S_IFMT) == S_IFDIR && (mode & 0444) != 0); + return result; } #define LENGTH_OF(A) (sizeof(A) / sizeof(A[0])) @@ -3681,114 +2536,7 @@ CF_EXPORT CFArrayRef _CFBundleCopyAllBundles(void) { CF_PRIVATE uint8_t _CFBundleLayoutVersion(CFBundleRef bundle) { return bundle->_version; } - -static void __addPlatformAndProductNamesToKeys(const void *value, void *context) { - CFMutableSetRef newKeys = (CFMutableSetRef)context; - CFStringRef key = (CFStringRef)value; - CFStringRef firstPartOfKey = NULL; - CFStringRef restOfKey = NULL; - - // Find the first ':' - CFRange range; - Boolean success = CFStringFindWithOptions(key, CFSTR(":"), CFRangeMake(0, CFStringGetLength(key)), 0, &range); - if (success) { - firstPartOfKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, key, CFRangeMake(0, range.location)); - restOfKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, key, CFRangeMake(range.location + 1, CFStringGetLength(key) - range.location - 1)); - } else { - firstPartOfKey = (CFStringRef)CFRetain(key); - } - - // only apply product and platform to top-level key - CFStringRef newKeyWithPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@%@%@"), firstPartOfKey, _CFGetPlatformName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR("")); - CFStringRef newKeyWithProduct = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@~%@%@%@"), firstPartOfKey, _CFGetProductName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR("")); - CFStringRef newKeyWithProductAndPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@~%@%@%@"), firstPartOfKey, _CFGetPlatformName(), _CFGetProductName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR("")); - - CFSetAddValue(newKeys, key); - CFSetAddValue(newKeys, newKeyWithPlatform); - CFSetAddValue(newKeys, newKeyWithProduct); - CFSetAddValue(newKeys, newKeyWithProductAndPlatform); - - if (firstPartOfKey) CFRelease(firstPartOfKey); - if (restOfKey) CFRelease(restOfKey); - CFRelease(newKeyWithPlatform); - CFRelease(newKeyWithProduct); - CFRelease(newKeyWithProductAndPlatform); -} - -// from CFUtilities.c -CF_PRIVATE Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, Boolean uncached, void **outBytes, CFIndex *outLength, CFErrorRef *errorPtr); - -// implementation of below functions - takes URL as parameter -static CFPropertyListRef _CFBundleCreateFilteredInfoPlistWithURL(CFURLRef infoPlistURL, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) { - CFPropertyListRef result = NULL; - - if (!infoPlistURL) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFURLRef absoluteURL = CFURLCopyAbsoluteURL(infoPlistURL); - CFStringRef filePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - CFRelease(absoluteURL); - - if (!filePath) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - void *bytes = NULL; - CFIndex length = 0; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - Boolean mapped = options & _CFBundleFilteredPlistMemoryMapped ? true : false; -#else - Boolean mapped = false; -#endif - Boolean success = _CFReadMappedFromFile(filePath, mapped, false, &bytes, &length, NULL); - CFRelease(filePath); - if (!success) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFDataRef infoPlistData = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)bytes, length, kCFAllocatorNull); - // We need to include all possible variants of the platform/product combo as possible keys. - CFMutableSetRef newKeyPaths = CFSetCreateMutable(kCFAllocatorSystemDefault, CFSetGetCount(keyPaths), &kCFTypeSetCallBacks); - CFSetApplyFunction(keyPaths, __addPlatformAndProductNamesToKeys, newKeyPaths); - - success = _CFPropertyListCreateFiltered(kCFAllocatorSystemDefault, infoPlistData, kCFPropertyListMutableContainers, newKeyPaths, &result, NULL); - - if (!success) { - result = CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } else { - _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); - } - - CFRelease(newKeyPaths); - CFRelease(infoPlistData); - if (mapped) { -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - munmap(bytes, length); -#endif - } else { - free(bytes); - } - - return result; -} - -// Returns a subset of the bundle's property list, only including the keyPaths in the CFSet. If the top level object is not a dictionary, you will get back an empty dictionary as the result. If the Info.plist does not exist or could not be parsed, you will get back an empty dictionary. -CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) { - CFURLRef infoPlistURL = _CFBundleCopyInfoPlistURL(bundle); - CFPropertyListRef result = _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL, keyPaths, options); - if (infoPlistURL) CFRelease(infoPlistURL); - return result; -} - -CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredLocalizedInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, CFStringRef localizationName, _CFBundleFilteredPlistOptions options) { - CFURLRef infoPlistURL = CFBundleCopyResourceURLForLocalization(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL, localizationName); - CFPropertyListRef result = _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL, keyPaths, options); - if (infoPlistURL) CFRelease(infoPlistURL); - return result; -} - -CF_EXPORT CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle) { - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - CFURLRef url = (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleInfoPlistURLKey); - if (!url) url = (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleRawInfoPlistURLKey); - return (url ? (CFURLRef)CFRetain(url) : NULL); -} - + CF_EXPORT CFURLRef _CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) { return CFBundleCopyPrivateFrameworksURL(bundle); } @@ -3873,701 +2621,3 @@ CF_EXPORT CFURLRef CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) { return result; } -#if defined(BINARY_SUPPORT_DYLD) - -CF_PRIVATE CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint) { - uint32_t i, numImages = _dyld_image_count(); - CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFRange range = CFRangeMake(0, CFStringGetLength(hint)), altRange = CFRangeMake(0, 0), testRange = CFRangeMake(0, 0); - const char *processPath = _CFProcessPath(); - const void *mhp = (const void *)_NSGetMachExecuteHeader(); - - if (range.length > 14) { - // handle some common variations on framework bundle identifiers - if (CFStringFindWithOptions(hint, CFSTR(".framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) { - // identifier has .framework appended - altRange.length = testRange.location; - } else if (CFStringFindWithOptions(hint, CFSTR("framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) { - // identifier has Framework appended - altRange.length = testRange.location; - } else if (CFStringFindWithOptions(hint, CFSTR("fw"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) { - // identifier has FW appended - altRange.length = testRange.location; - } - } - for (i = 0; i < numImages; i++) { - const char *curName = _dyld_get_image_name(i), *lastComponent = NULL; - if (curName && (!processPath || 0 != strcmp(curName, processPath)) && mhp != (void *)_dyld_get_image_header(i)) lastComponent = strrchr(curName, '/'); - if (lastComponent) { - CFStringRef str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, lastComponent + 1); - if (str) { - if (CFStringFindWithOptions(hint, str, range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL) || (altRange.length > 0 && CFStringFindWithOptions(hint, str, altRange, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL))) { - CFStringRef curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName); - if (curStr) { - CFArrayAppendValue(result, curStr); - CFRelease(curStr); - } - } - CFRelease(str); - } - } - } - return result; -} - -static char *_cleanedPathForPath(const char *curName) { - char *thePath = strdup(curName); - if (thePath) { - // We are going to process the buffer replacing all "/./" and "//" with "/" - CFIndex srcIndex = 0, dstIndex = 0; - CFIndex len = strlen(thePath); - for (srcIndex=0; srcIndexncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { - if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) { - foundit = true; - name = _dyld_get_image_name(i); - if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name); - } - } - } - } -#undef MACH_HEADER_TYPE -#undef MACH_SEGMENT_CMD_TYPE -#undef MACH_SEGMENT_FLAVOR - } -#endif /* USE_DYLD_PRIV */ -#if LOG_BUNDLE_LOAD - printf("dyld image path for pointer %p is %p\n", p, result); -#endif /* LOG_BUNDLE_LOAD */ - return result; -} - -#if !defined(BINARY_SUPPORT_DLFCN) - -static const void *__CFBundleDYLDFindImage(char *buff) { - const void *header = NULL; - uint32_t i, numImages = _dyld_image_count(), numMatches = 0; - const char *curName, *p, *q; - - for (i = 0; !header && i < numImages; i++) { - curName = _dyld_get_image_name(i); - if (curName && 0 == strncmp(curName, buff, CFMaxPathSize)) { - header = _dyld_get_image_header(i); - numMatches = 1; - } - } - if (!header) { - for (i = 0; i < numImages; i++) { - curName = _dyld_get_image_name(i); - if (curName) { - for (p = buff, q = curName; *p && *q && (q - curName < CFMaxPathSize); p++, q++) { - if (*p != *q && (q - curName > 11) && 0 == strncmp(q - 11, ".framework/Versions/", 20) && *(q + 9) && '/' == *(q + 10)) q += 11; - else if (*p != *q && (q - curName > 12) && 0 == strncmp(q - 12, ".framework/Versions/", 20) && *(q + 8) && '/' == *(q + 9)) q += 10; - if (*p != *q) break; - } - if (*p == *q) { - header = _dyld_get_image_header(i); - numMatches++; - } - } - } - } - return (numMatches == 1) ? header : NULL; -} - -CF_PRIVATE Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle) { - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - const void *header = __CFBundleDYLDFindImage(buff); - if (header) { - if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = __CFBundleDYLDFrameworkBinary; - if (!bundle->_imageCookie) { - bundle->_imageCookie = header; -#if LOG_BUNDLE_LOAD - printf("dyld check load bundle %p, find %s getting image %p\n", bundle, buff, bundle->_imageCookie); -#endif /* LOG_BUNDLE_LOAD */ - } - bundle->_isLoaded = true; - } else { -#if LOG_BUNDLE_LOAD - printf("dyld check load bundle %p, find %s no image\n", bundle, buff); -#endif /* LOG_BUNDLE_LOAD */ - } - } - if (executableURL) CFRelease(executableURL); - } - return bundle->_isLoaded; -} - -CF_PRIVATE Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { - CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); - NSLinkEditErrors c = NSLinkEditUndefinedError; - int errorNumber = 0; - const char *fileName = NULL; - const char *errorString = NULL; - - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - NSObjectFileImage image; - NSObjectFileImageReturnCode retCode = NSCreateObjectFileImageFromFile(buff, &image); -#if LOG_BUNDLE_LOAD - printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle, buff, image, retCode); -#endif /* LOG_BUNDLE_LOAD */ - if (retCode == NSObjectFileImageSuccess) { - uint32_t options = forceGlobal ? NSLINKMODULE_OPTION_RETURN_ON_ERROR : (NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR); - NSModule module = NSLinkModule(image, buff, options); -#if LOG_BUNDLE_LOAD - printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle, buff, options, module, image); -#endif /* LOG_BUNDLE_LOAD */ - if (module) { - bundle->_imageCookie = image; - bundle->_moduleCookie = module; - bundle->_isLoaded = true; - } else { - NSLinkEditError(&c, &errorNumber, &fileName, &errorString); - if (error) { -#if defined(BINARY_SUPPORT_DLFCN) - _CFBundleDlfcnPreflight(bundle, subError); -#endif /* BINARY_SUPPORT_DLFCN */ - if (!localError) { - CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString); - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); - if (tempString) CFRelease(tempString); - if (debugString) CFRelease(debugString); - } - } else { - CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName); - CFLog(__kCFLogBundle, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString); - if (tempString) CFRelease(tempString); - if (executableString) CFRelease(executableString); - } - (void)NSDestroyObjectFileImage(image); - } - } else { - if (error) { - if (retCode == NSObjectFileImageArch) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError); - } else if (retCode == NSObjectFileImageInappropriateFile) { - Boolean hasRuntimeMismatch = false; - uint32_t mainFlags = 0, bundleFlags = 0; - if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) { - if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true; - } - if (hasRuntimeMismatch) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError); - } else { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError); - } - } else { -#if defined(BINARY_SUPPORT_DLFCN) - _CFBundleDlfcnPreflight(bundle, subError); -#endif /* BINARY_SUPPORT_DLFCN */ - if (!localError) { - CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("dyld returns %d"), retCode); - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); - CFRelease(debugString); - } - } - } else { - CFLog(__kCFLogBundle, CFSTR("dyld returns %d when trying to load %@"), retCode, executableURL); - } - } - } else { - if (error) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); - } else { - CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); - } - } - if (executableURL) CFRelease(executableURL); - } - if (!bundle->_isLoaded && error) *error = localError; - return bundle->_isLoaded; -} - -CF_PRIVATE Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErrorRef *error) { - // !!! Framework loading should be better. Can't unload frameworks. - CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); - NSLinkEditErrors c = NSLinkEditUndefinedError; - int errorNumber = 0; - const char *fileName = NULL; - const char *errorString = NULL; - - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - void *image = (void *)NSAddImage(buff, NSADDIMAGE_OPTION_RETURN_ON_ERROR); -#if LOG_BUNDLE_LOAD - printf("dyld load framework %p, add image of %s returns image %p\n", bundle, buff, image); -#endif /* LOG_BUNDLE_LOAD */ - if (image) { - bundle->_imageCookie = image; - bundle->_isLoaded = true; - } else { - NSLinkEditError(&c, &errorNumber, &fileName, &errorString); - if (error) { -#if defined(BINARY_SUPPORT_DLFCN) - _CFBundleDlfcnPreflight(bundle, subError); -#endif /* BINARY_SUPPORT_DLFCN */ - if (!localError) { - CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString); - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); - if (tempString) CFRelease(tempString); - if (debugString) CFRelease(debugString); - } - } else { - CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName); - CFLog(__kCFLogBundle, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString); - if (tempString) CFRelease(tempString); - if (executableString) CFRelease(executableString); - } - } - } else { - if (error) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); - } else { - CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); - } - } - if (executableURL) CFRelease(executableURL); - } - if (!bundle->_isLoaded && error) *error = localError; - return bundle->_isLoaded; -} - -CF_PRIVATE void _CFBundleDYLDUnloadBundle(CFBundleRef bundle) { - if (bundle->_isLoaded) { -#if LOG_BUNDLE_LOAD - printf("dyld unload bundle %p, handle %p module %p image %p\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie); -#endif /* LOG_BUNDLE_LOAD */ - if (bundle->_moduleCookie && !NSUnLinkModule((NSModule)(bundle->_moduleCookie), NSUNLINKMODULE_OPTION_NONE)) { - CFLog(__kCFLogBundle, CFSTR("Internal error unloading bundle %@"), bundle); - } else { - if (bundle->_moduleCookie && bundle->_imageCookie) (void)NSDestroyObjectFileImage((NSObjectFileImage)(bundle->_imageCookie)); - bundle->_connectionCookie = bundle->_handleCookie = NULL; - bundle->_imageCookie = bundle->_moduleCookie = NULL; - bundle->_isLoaded = false; - } - } -} - -CF_PRIVATE void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { - return _CFBundleDYLDGetSymbolByNameWithSearch(bundle, symbolName, false); -} - -static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) { - void *result = NULL; - char buff[1026]; - NSSymbol symbol = NULL; - - buff[0] = '_'; - if (CFStringGetCString(symbolName, &(buff[1]), 1024, kCFStringEncodingUTF8)) { - if (bundle->_moduleCookie) { - symbol = NSLookupSymbolInModule((NSModule)(bundle->_moduleCookie), buff); - } else if (bundle->_imageCookie) { - symbol = NSLookupSymbolInImage(bundle->_imageCookie, buff, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); - } - if (!symbol && !bundle->_moduleCookie && (!bundle->_imageCookie || globalSearch)) { - char hintBuff[1026]; - CFStringRef executableName = _CFBundleCopyExecutableName(bundle, NULL, NULL); - hintBuff[0] = '\0'; - if (executableName) { - if (!CFStringGetCString(executableName, hintBuff, 1024, kCFStringEncodingUTF8)) hintBuff[0] = '\0'; - CFRelease(executableName); - } - // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint() - // are identical, except the first just returns a bool, so checking with the - // Is function first just causes a redundant lookup. - // This returns NULL on failure. - symbol = NSLookupAndBindSymbolWithHint(buff, hintBuff); - } - if (symbol) result = NSAddressOfSymbol(symbol); -#if defined(DEBUG) - if (!result) CFLog(__kCFLogBundle, CFSTR("dyld cannot find symbol %@ in %@"), symbolName, bundle); -#endif /* DEBUG */ -#if LOG_BUNDLE_LOAD - printf("bundle %p handle %p module %p image %p dyld returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff + 1); -#endif /* LOG_BUNDLE_LOAD */ - } - return result; -} - -#endif /* !BINARY_SUPPORT_DLFCN */ -#endif /* BINARY_SUPPORT_DYLD */ - -#if defined(BINARY_SUPPORT_DLFCN) - -CF_PRIVATE Boolean _CFBundleDlfcnCheckLoaded(CFBundleRef bundle) { - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - int mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD | RTLD_FIRST; - void *handle = dlopen(buff, mode); - if (handle) { - if (!bundle->_handleCookie) { - bundle->_handleCookie = handle; -#if LOG_BUNDLE_LOAD - printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x getting handle %p\n", bundle, buff, mode, bundle->_handleCookie); -#endif /* LOG_BUNDLE_LOAD */ - } - bundle->_isLoaded = true; - } else { -#if LOG_BUNDLE_LOAD - printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x no handle\n", bundle, buff, mode); -#endif /* LOG_BUNDLE_LOAD */ - } - } - if (executableURL) CFRelease(executableURL); - } - return bundle->_isLoaded; -} - -CF_EXPORT Boolean _CFBundleDlfcnPreflight(CFBundleRef bundle, CFErrorRef *error) { - Boolean retval = true; - CFErrorRef localError = NULL; - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - - retval = false; - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - retval = dlopen_preflight(buff); - if (!retval && error) { - CFArrayRef archs = CFBundleCopyExecutableArchitectures(bundle); - CFStringRef debugString = NULL; - const char *errorString = dlerror(); - if (errorString && strlen(errorString) > 0) debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString); - if (archs) { - Boolean hasSuitableArch = false, hasRuntimeMismatch = false; - CFIndex i, count = CFArrayGetCount(archs); - SInt32 arch, curArch = _CFBundleCurrentArchitecture(); - for (i = 0; !hasSuitableArch && i < count; i++) { - if (CFNumberGetValue((CFNumberRef)CFArrayGetValueAtIndex(archs, i), kCFNumberSInt32Type, (void *)&arch) && arch == curArch) hasSuitableArch = true; - } -#if defined(BINARY_SUPPORT_DYLD) - if (hasSuitableArch) { - uint32_t mainFlags = 0; - if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) { -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - uint32_t bundleFlags = 0; - if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true; -#endif - } - } -#endif /* BINARY_SUPPORT_DYLD */ - if (hasRuntimeMismatch) { - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError, debugString); - } else if (!hasSuitableArch) { - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError, debugString); - } else { - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLoadError, debugString); - } - CFRelease(archs); - } else { - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLoadError, debugString); - } - if (debugString) CFRelease(debugString); - } - } else { - if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); - } - if (executableURL) CFRelease(executableURL); - } - if (!retval && error) *error = localError; - return retval; -} - -CF_PRIVATE Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { - CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - int mode = forceGlobal ? (RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST) : (RTLD_NOW | RTLD_LOCAL | RTLD_FIRST); - void *cookie = dlopen(buff, mode); -#if LOG_BUNDLE_LOAD - printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie); -#endif /* LOG_BUNDLE_LOAD */ - if (cookie && cookie == bundle->_handleCookie) { - // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose -#if LOG_BUNDLE_LOAD - printf("dlfcn load bundle %p closing existing reference to handle %p\n", bundle, cookie); -#endif /* LOG_BUNDLE_LOAD */ - dlclose(bundle->_handleCookie); - } - bundle->_handleCookie = cookie; - if (bundle->_handleCookie) { - bundle->_isLoaded = true; - } else { - const char *errorString = dlerror(); - if (error) { - _CFBundleDlfcnPreflight(bundle, subError); - if (!localError) { - CFStringRef debugString = errorString ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString) : NULL; - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); - if (debugString) CFRelease(debugString); - } - } else { - CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); - if (errorString) { - CFStringRef debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString); - CFLog(__kCFLogBundle, CFSTR("Error loading %@: %@"), executableString, debugString); - if (debugString) CFRelease(debugString); - } else { - CFLog(__kCFLogBundle, CFSTR("Error loading %@"), executableString); - } - if (executableString) CFRelease(executableString); - } - } - } else { - if (error) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); - } else { - CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); - } - } - if (executableURL) CFRelease(executableURL); - } - if (!bundle->_isLoaded && error) *error = localError; - return bundle->_isLoaded; -} - -CF_PRIVATE Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErrorRef *error) { - CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - char buff[CFMaxPathSize]; - if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { - int mode = RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST; - void *cookie = dlopen(buff, mode); -#if LOG_BUNDLE_LOAD - printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie); -#endif /* LOG_BUNDLE_LOAD */ - if (cookie && cookie == bundle->_handleCookie) { - // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose -#if LOG_BUNDLE_LOAD - printf("dlfcn load framework %p closing existing reference to handle %p\n", bundle, cookie); -#endif /* LOG_BUNDLE_LOAD */ - dlclose(bundle->_handleCookie); - } - bundle->_handleCookie = cookie; - if (bundle->_handleCookie) { - bundle->_isLoaded = true; - } else { - const char *errorString = dlerror(); - if (error) { - _CFBundleDlfcnPreflight(bundle, subError); - if (!localError) { - CFStringRef debugString = errorString ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString) : NULL; - localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); - if (debugString) CFRelease(debugString); - } - } else { - CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); - if (errorString) { - CFStringRef debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString); - CFLog(__kCFLogBundle, CFSTR("Error loading %@: %@"), executableString, debugString); - if (debugString) CFRelease(debugString); - } else { - CFLog(__kCFLogBundle, CFSTR("Error loading %@"), executableString); - } - if (executableString) CFRelease(executableString); - } - } - } else { - if (error) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); - } else { - CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); - } - } - if (executableURL) CFRelease(executableURL); - } - if (!bundle->_isLoaded && error) *error = localError; - return bundle->_isLoaded; -} - -CF_PRIVATE void _CFBundleDlfcnUnload(CFBundleRef bundle) { - if (bundle->_isLoaded) { -#if LOG_BUNDLE_LOAD - printf("dlfcn unload bundle %p, handle %p module %p image %p\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie); -#endif /* LOG_BUNDLE_LOAD */ - if (0 != dlclose(bundle->_handleCookie)) { - CFLog(__kCFLogBundle, CFSTR("Internal error unloading bundle %@"), bundle); - } else { - bundle->_connectionCookie = bundle->_handleCookie = NULL; - bundle->_imageCookie = bundle->_moduleCookie = NULL; - bundle->_isLoaded = false; - } - } -} - -CF_PRIVATE void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { - return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, symbolName, false); -} - -static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) { - void *result = NULL; - char buff[1026]; - - if (CFStringGetCString(symbolName, buff, 1024, kCFStringEncodingUTF8)) { - result = dlsym(bundle->_handleCookie, buff); - if (!result && globalSearch) result = dlsym(RTLD_DEFAULT, buff); -#if defined(DEBUG) - if (!result) CFLog(__kCFLogBundle, CFSTR("dlsym cannot find symbol %@ in %@"), symbolName, bundle); -#endif /* DEBUG */ -#if LOG_BUNDLE_LOAD - printf("bundle %p handle %p module %p image %p dlsym returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff); -#endif /* LOG_BUNDLE_LOAD */ - } - return result; -} - -#if !defined(BINARY_SUPPORT_DYLD) - -static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p) { - CFStringRef result = NULL; - Dl_info info; - if (0 != dladdr(p, &info) && info.dli_fname) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, info.dli_fname); -#if LOG_BUNDLE_LOAD - printf("dlfcn image path for pointer %p is %p\n", p, result); -#endif /* LOG_BUNDLE_LOAD */ - return result; -} - -#endif /* !BINARY_SUPPORT_DYLD */ -#endif /* BINARY_SUPPORT_DLFCN */ - -#if defined(BINARY_SUPPORT_DLL) - -CF_PRIVATE Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *error) { - CFErrorRef localError = NULL; - if (!bundle->_isLoaded) { - CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); - wchar_t buff[CFMaxPathSize]; - - if (executableURL && _CFURLGetWideFileSystemRepresentation(executableURL, true, (wchar_t *)buff, CFMaxPathSize)) { - bundle->_hModule = LoadLibraryW(buff); - if (bundle->_hModule) { - bundle->_isLoaded = true; - } else { - if (error) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError); - } else { - CFLog(__kCFLogBundle, CFSTR("Failed to load bundle %@"), bundle); - } - } - } else { - if (error) { - localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); - } else { - CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); - } - } - if (executableURL) CFRelease(executableURL); - } - if (!bundle->_isLoaded && error) *error = localError; - return bundle->_isLoaded; -} - -CF_PRIVATE void _CFBundleDLLUnload(CFBundleRef bundle) { - if (bundle->_isLoaded) { - FreeLibrary(bundle->_hModule); - bundle->_hModule = NULL; - bundle->_isLoaded = false; - } -} - -CF_PRIVATE void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { - void *result = NULL; - char buff[1024]; - if (CFStringGetCString(symbolName, buff, 1024, kCFStringEncodingWindowsLatin1)) result = GetProcAddress(bundle->_hModule, buff); - return result; -} - -#endif /* BINARY_SUPPORT_DLL */ - -/* Workarounds to be applied in the presence of certain bundles can go here. This is called on every bundle creation. -*/ - - - - diff --git a/CFBundle.h b/CFBundle.h index 36b727e..68f8522 100644 --- a/CFBundle.h +++ b/CFBundle.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBundle.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLE__) @@ -35,6 +35,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFBundle *CFBundleRef; @@ -351,6 +352,7 @@ CF_EXPORT void CFBundleCloseBundleResourceMap(CFBundleRef bundle, CFBundleRefNum refNum); CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFBUNDLE__ */ diff --git a/CFBundlePriv.h b/CFBundlePriv.h index b8547fe..970e254 100644 --- a/CFBundlePriv.h +++ b/CFBundlePriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBundlePriv.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLEPRIV__) @@ -144,6 +144,7 @@ CFURLRef _CFBundleCopyMainBundleExecutableURL(Boolean *looksLikeBundle); CF_EXPORT CFBundleRef _CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL); +// This function is obsolete. CF_EXPORT CFArrayRef _CFBundleGetSupportedPlatforms(CFBundleRef bundle); @@ -153,9 +154,11 @@ CFStringRef _CFBundleGetCurrentPlatform(void); /* For Code Signing */ +// This function is obsolete. Use CFBundleCreate instead. CF_EXPORT -CFBundleRef _CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url); +CFBundleRef _CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) CF_DEPRECATED(10_6, 10_10, 2_0, 8_0); +// This function is for code signing only. Do not use this function. CF_EXPORT CFBundleRef _CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url); @@ -200,6 +203,9 @@ CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SIn /* specified. Pass in -1 for language, region code, or script code, or */ /* 0xFFFF for stringEncoding, if you do not wish to specify one of these. */ +// Get a localized string for a specific localization (including processing as strings dict file). This skips the usual cache for localized strings. +CF_EXPORT CFStringRef CFBundleCopyLocalizedStringForLocalization(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName, CFStringRef localizationName) CF_AVAILABLE(10_10, 8_0); + CF_EXPORT void _CFBundleSetDefaultLocalization(CFStringRef localizationName); @@ -248,6 +254,11 @@ Boolean _CFBundleGetStringsFilesShared(CFBundleRef bundle); CF_EXPORT CFURLRef _CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath); +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) +#include +CF_EXPORT +void _CFBundleSetupXPCBootstrap(xpc_object_t bootstrap) CF_AVAILABLE(10_10, 8_0); +#endif /* Functions deprecated as SPI */ diff --git a/CFBundle_Binary.c b/CFBundle_Binary.c new file mode 100644 index 0000000..a84d68e --- /dev/null +++ b/CFBundle_Binary.c @@ -0,0 +1,886 @@ +/* + * Copyright (c) 2014 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* CFBundle_Binary.c + Copyright (c) 1999-2014, Apple Inc. All rights reserved. + Responsibility: Tony Parker +*/ + +#include "CFBundle_Internal.h" + +#if defined(BINARY_SUPPORT_DYLD) +// Import the mach-o headers that define the macho magic numbers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(USE_DYLD_PRIV) +#include +#endif /* USE_DYLD_PRIV */ +#endif /* BINARY_SUPPORT_DYLD */ + +#if defined(BINARY_SUPPORT_DLFCN) +#include +#endif /* BINARY_SUPPORT_DLFCN */ + +#if defined(BINARY_SUPPORT_DYLD) +static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p); +#if !defined(BINARY_SUPPORT_DLFCN) +static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch); +#endif /* !BINARY_SUPPORT_DLFCN */ +#endif /* BINARY_SUPPORT_DYLD */ +#if defined(BINARY_SUPPORT_DLFCN) +static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch); +#if !defined(BINARY_SUPPORT_DYLD) +static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p); +#endif /* !BINARY_SUPPORT_DYLD */ +#endif /* BINARY_SUPPORT_DLFCN */ + + +CF_PRIVATE SInt32 _CFBundleCurrentArchitecture(void) { + SInt32 arch = 0; +#if defined(__ppc__) + arch = kCFBundleExecutableArchitecturePPC; +#elif defined(__ppc64__) + arch = kCFBundleExecutableArchitecturePPC64; +#elif defined(__i386__) + arch = kCFBundleExecutableArchitectureI386; +#elif defined(__x86_64__) + arch = kCFBundleExecutableArchitectureX86_64; +#elif defined(BINARY_SUPPORT_DYLD) + const NXArchInfo *archInfo = NXGetLocalArchInfo(); + if (archInfo) arch = archInfo->cputype; +#endif + return arch; +} + +#if defined(BINARY_SUPPORT_DYLD) + +CF_PRIVATE CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint) { + uint32_t i, numImages = _dyld_image_count(); + CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + CFRange range = CFRangeMake(0, CFStringGetLength(hint)), altRange = CFRangeMake(0, 0), testRange = CFRangeMake(0, 0); + const char *processPath = _CFProcessPath(); + const void *mhp = (const void *)_NSGetMachExecuteHeader(); + + if (range.length > 14) { + // handle some common variations on framework bundle identifiers + if (CFStringFindWithOptions(hint, CFSTR(".framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) { + // identifier has .framework appended + altRange.length = testRange.location; + } else if (CFStringFindWithOptions(hint, CFSTR("framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) { + // identifier has Framework appended + altRange.length = testRange.location; + } else if (CFStringFindWithOptions(hint, CFSTR("fw"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) { + // identifier has FW appended + altRange.length = testRange.location; + } + } + for (i = 0; i < numImages; i++) { + const char *curName = _dyld_get_image_name(i), *lastComponent = NULL; + if (curName && (!processPath || 0 != strcmp(curName, processPath)) && mhp != (void *)_dyld_get_image_header(i)) lastComponent = strrchr(curName, '/'); + if (lastComponent) { + CFStringRef str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, lastComponent + 1); + if (str) { + if (CFStringFindWithOptions(hint, str, range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL) || (altRange.length > 0 && CFStringFindWithOptions(hint, str, altRange, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL))) { + CFStringRef curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName); + if (curStr) { + CFArrayAppendValue(result, curStr); + CFRelease(curStr); + } + } + CFRelease(str); + } + } + } + return result; +} + +static char *_cleanedPathForPath(const char *curName) { + char *thePath = strdup(curName); + if (thePath) { + // We are going to process the buffer replacing all "/./" and "//" with "/" + CFIndex srcIndex = 0, dstIndex = 0; + CFIndex len = strlen(thePath); + for (srcIndex=0; srcIndexncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { + if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) { + foundit = true; + name = _dyld_get_image_name(i); + if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name); + } + } + } + } +#undef MACH_HEADER_TYPE +#undef MACH_SEGMENT_CMD_TYPE +#undef MACH_SEGMENT_FLAVOR + } +#endif /* USE_DYLD_PRIV */ +#if LOG_BUNDLE_LOAD + printf("dyld image path for pointer %p is %p\n", p, result); +#endif /* LOG_BUNDLE_LOAD */ + return result; +} + +#if !defined(BINARY_SUPPORT_DLFCN) + +static const void *__CFBundleDYLDFindImage(char *buff) { + const void *header = NULL; + uint32_t i, numImages = _dyld_image_count(), numMatches = 0; + const char *curName, *p, *q; + + for (i = 0; !header && i < numImages; i++) { + curName = _dyld_get_image_name(i); + if (curName && 0 == strncmp(curName, buff, CFMaxPathSize)) { + header = _dyld_get_image_header(i); + numMatches = 1; + } + } + if (!header) { + for (i = 0; i < numImages; i++) { + curName = _dyld_get_image_name(i); + if (curName) { + for (p = buff, q = curName; *p && *q && (q - curName < CFMaxPathSize); p++, q++) { + if (*p != *q && (q - curName > 11) && 0 == strncmp(q - 11, ".framework/Versions/", 20) && *(q + 9) && '/' == *(q + 10)) q += 11; + else if (*p != *q && (q - curName > 12) && 0 == strncmp(q - 12, ".framework/Versions/", 20) && *(q + 8) && '/' == *(q + 9)) q += 10; + if (*p != *q) break; + } + if (*p == *q) { + header = _dyld_get_image_header(i); + numMatches++; + } + } + } + } + return (numMatches == 1) ? header : NULL; +} + +CF_PRIVATE Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle) { + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + const void *header = __CFBundleDYLDFindImage(buff); + if (header) { + if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = __CFBundleDYLDFrameworkBinary; + if (!bundle->_imageCookie) { + bundle->_imageCookie = header; +#if LOG_BUNDLE_LOAD + printf("dyld check load bundle %p, find %s getting image %p\n", bundle, buff, bundle->_imageCookie); +#endif /* LOG_BUNDLE_LOAD */ + } + bundle->_isLoaded = true; + } else { +#if LOG_BUNDLE_LOAD + printf("dyld check load bundle %p, find %s no image\n", bundle, buff); +#endif /* LOG_BUNDLE_LOAD */ + } + } + if (executableURL) CFRelease(executableURL); + } + return bundle->_isLoaded; +} + +CF_PRIVATE Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { + CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); + NSLinkEditErrors c = NSLinkEditUndefinedError; + int errorNumber = 0; + const char *fileName = NULL; + const char *errorString = NULL; + + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + NSObjectFileImage image; + NSObjectFileImageReturnCode retCode = NSCreateObjectFileImageFromFile(buff, &image); +#if LOG_BUNDLE_LOAD + printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle, buff, image, retCode); +#endif /* LOG_BUNDLE_LOAD */ + if (retCode == NSObjectFileImageSuccess) { + uint32_t options = forceGlobal ? NSLINKMODULE_OPTION_RETURN_ON_ERROR : (NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR); + NSModule module = NSLinkModule(image, buff, options); +#if LOG_BUNDLE_LOAD + printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle, buff, options, module, image); +#endif /* LOG_BUNDLE_LOAD */ + if (module) { + bundle->_imageCookie = image; + bundle->_moduleCookie = module; + bundle->_isLoaded = true; + } else { + NSLinkEditError(&c, &errorNumber, &fileName, &errorString); + if (error) { +#if defined(BINARY_SUPPORT_DLFCN) + _CFBundleDlfcnPreflight(bundle, subError); +#endif /* BINARY_SUPPORT_DLFCN */ + if (!localError) { + CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString); + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); + if (tempString) CFRelease(tempString); + if (debugString) CFRelease(debugString); + } + } else { + CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName); + CFLog(__kCFLogBundle, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString); + if (tempString) CFRelease(tempString); + if (executableString) CFRelease(executableString); + } + (void)NSDestroyObjectFileImage(image); + } + } else { + if (error) { + if (retCode == NSObjectFileImageArch) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError); + } else if (retCode == NSObjectFileImageInappropriateFile) { + Boolean hasRuntimeMismatch = false; + uint32_t mainFlags = 0, bundleFlags = 0; + if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) { + if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true; + } + if (hasRuntimeMismatch) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError); + } else { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError); + } + } else { +#if defined(BINARY_SUPPORT_DLFCN) + _CFBundleDlfcnPreflight(bundle, subError); +#endif /* BINARY_SUPPORT_DLFCN */ + if (!localError) { + CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("dyld returns %d"), retCode); + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); + CFRelease(debugString); + } + } + } else { + CFLog(__kCFLogBundle, CFSTR("dyld returns %d when trying to load %@"), retCode, executableURL); + } + } + } else { + if (error) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); + } else { + CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); + } + } + if (executableURL) CFRelease(executableURL); + } + if (!bundle->_isLoaded && error) *error = localError; + return bundle->_isLoaded; +} + +CF_PRIVATE Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErrorRef *error) { + // !!! Framework loading should be better. Can't unload frameworks. + CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); + NSLinkEditErrors c = NSLinkEditUndefinedError; + int errorNumber = 0; + const char *fileName = NULL; + const char *errorString = NULL; + + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + void *image = (void *)NSAddImage(buff, NSADDIMAGE_OPTION_RETURN_ON_ERROR); +#if LOG_BUNDLE_LOAD + printf("dyld load framework %p, add image of %s returns image %p\n", bundle, buff, image); +#endif /* LOG_BUNDLE_LOAD */ + if (image) { + bundle->_imageCookie = image; + bundle->_isLoaded = true; + } else { + NSLinkEditError(&c, &errorNumber, &fileName, &errorString); + if (error) { +#if defined(BINARY_SUPPORT_DLFCN) + _CFBundleDlfcnPreflight(bundle, subError); +#endif /* BINARY_SUPPORT_DLFCN */ + if (!localError) { + CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString); + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); + if (tempString) CFRelease(tempString); + if (debugString) CFRelease(debugString); + } + } else { + CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName); + CFLog(__kCFLogBundle, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString); + if (tempString) CFRelease(tempString); + if (executableString) CFRelease(executableString); + } + } + } else { + if (error) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); + } else { + CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); + } + } + if (executableURL) CFRelease(executableURL); + } + if (!bundle->_isLoaded && error) *error = localError; + return bundle->_isLoaded; +} + +CF_PRIVATE void _CFBundleDYLDUnloadBundle(CFBundleRef bundle) { + if (bundle->_isLoaded) { +#if LOG_BUNDLE_LOAD + printf("dyld unload bundle %p, handle %p module %p image %p\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie); +#endif /* LOG_BUNDLE_LOAD */ + if (bundle->_moduleCookie && !NSUnLinkModule((NSModule)(bundle->_moduleCookie), NSUNLINKMODULE_OPTION_NONE)) { + CFLog(__kCFLogBundle, CFSTR("Internal error unloading bundle %@"), bundle); + } else { + if (bundle->_moduleCookie && bundle->_imageCookie) (void)NSDestroyObjectFileImage((NSObjectFileImage)(bundle->_imageCookie)); + bundle->_connectionCookie = bundle->_handleCookie = NULL; + bundle->_imageCookie = bundle->_moduleCookie = NULL; + bundle->_isLoaded = false; + } + } +} + +CF_PRIVATE void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { + return _CFBundleDYLDGetSymbolByNameWithSearch(bundle, symbolName, false); +} + +static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) { + void *result = NULL; + char buff[1026]; + NSSymbol symbol = NULL; + + buff[0] = '_'; + if (CFStringGetCString(symbolName, &(buff[1]), 1024, kCFStringEncodingUTF8)) { + if (bundle->_moduleCookie) { + symbol = NSLookupSymbolInModule((NSModule)(bundle->_moduleCookie), buff); + } else if (bundle->_imageCookie) { + symbol = NSLookupSymbolInImage(bundle->_imageCookie, buff, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + if (!symbol && !bundle->_moduleCookie && (!bundle->_imageCookie || globalSearch)) { + char hintBuff[1026]; + CFStringRef executableName = _CFBundleCopyExecutableName(bundle, NULL, NULL); + hintBuff[0] = '\0'; + if (executableName) { + if (!CFStringGetCString(executableName, hintBuff, 1024, kCFStringEncodingUTF8)) hintBuff[0] = '\0'; + CFRelease(executableName); + } + // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint() + // are identical, except the first just returns a bool, so checking with the + // Is function first just causes a redundant lookup. + // This returns NULL on failure. + symbol = NSLookupAndBindSymbolWithHint(buff, hintBuff); + } + if (symbol) result = NSAddressOfSymbol(symbol); +#if defined(DEBUG) + if (!result) CFLog(__kCFLogBundle, CFSTR("dyld cannot find symbol %@ in %@"), symbolName, bundle); +#endif /* DEBUG */ +#if LOG_BUNDLE_LOAD + printf("bundle %p handle %p module %p image %p dyld returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff + 1); +#endif /* LOG_BUNDLE_LOAD */ + } + return result; +} + +#endif /* !BINARY_SUPPORT_DLFCN */ +#endif /* BINARY_SUPPORT_DYLD */ + +#if defined(BINARY_SUPPORT_DLFCN) + +CF_PRIVATE Boolean _CFBundleDlfcnCheckLoaded(CFBundleRef bundle) { + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + int mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD | RTLD_FIRST; + void *handle = dlopen(buff, mode); + if (handle) { + if (!bundle->_handleCookie) { + bundle->_handleCookie = handle; +#if LOG_BUNDLE_LOAD + printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x getting handle %p\n", bundle, buff, mode, bundle->_handleCookie); +#endif /* LOG_BUNDLE_LOAD */ + } + bundle->_isLoaded = true; + } else { +#if LOG_BUNDLE_LOAD + printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x no handle\n", bundle, buff, mode); +#endif /* LOG_BUNDLE_LOAD */ + } + } + if (executableURL) CFRelease(executableURL); + } + return bundle->_isLoaded; +} + +CF_EXPORT Boolean _CFBundleDlfcnPreflight(CFBundleRef bundle, CFErrorRef *error) { + Boolean retval = true; + CFErrorRef localError = NULL; + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + + retval = false; + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + retval = dlopen_preflight(buff); + if (!retval && error) { + CFArrayRef archs = CFBundleCopyExecutableArchitectures(bundle); + CFStringRef debugString = NULL; + const char *errorString = dlerror(); + if (errorString && strlen(errorString) > 0) debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString); + if (archs) { + Boolean hasSuitableArch = false, hasRuntimeMismatch = false; + CFIndex i, count = CFArrayGetCount(archs); + SInt32 arch, curArch = _CFBundleCurrentArchitecture(); + for (i = 0; !hasSuitableArch && i < count; i++) { + if (CFNumberGetValue((CFNumberRef)CFArrayGetValueAtIndex(archs, i), kCFNumberSInt32Type, (void *)&arch) && arch == curArch) hasSuitableArch = true; + } +#if defined(BINARY_SUPPORT_DYLD) + if (hasSuitableArch) { + uint32_t mainFlags = 0; + if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) { +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED + uint32_t bundleFlags = 0; + if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true; +#endif + } + } +#endif /* BINARY_SUPPORT_DYLD */ + if (hasRuntimeMismatch) { + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError, debugString); + } else if (!hasSuitableArch) { + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError, debugString); + } else { + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLoadError, debugString); + } + CFRelease(archs); + } else { + localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLoadError, debugString); + } + if (debugString) CFRelease(debugString); + } + } else { + if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); + } + if (executableURL) CFRelease(executableURL); + } + if (!retval && error) *error = localError; + return retval; +} + +CF_PRIVATE Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { + CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + int mode = forceGlobal ? (RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST) : (RTLD_NOW | RTLD_LOCAL | RTLD_FIRST); + void *cookie = dlopen(buff, mode); +#if LOG_BUNDLE_LOAD + printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie); +#endif /* LOG_BUNDLE_LOAD */ + if (cookie && cookie == bundle->_handleCookie) { + // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose +#if LOG_BUNDLE_LOAD + printf("dlfcn load bundle %p closing existing reference to handle %p\n", bundle, cookie); +#endif /* LOG_BUNDLE_LOAD */ + dlclose(bundle->_handleCookie); + } + bundle->_handleCookie = cookie; + if (bundle->_handleCookie) { + bundle->_isLoaded = true; + } else { + const char *dyldError = dlerror(); + CFStringRef errorString = dyldError ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dyldError) : NULL; + if (error) { + _CFBundleDlfcnPreflight(bundle, subError); + if (!localError) localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, errorString); + } else { + CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); + CFLog(__kCFLogBundle, CFSTR("Error loading %@: %@"), executableString, errorString ? errorString : CFSTR("(no additional info)")); + if (executableString) CFRelease(executableString); + } + if (errorString) CFRelease(errorString); + } + } else { + if (error) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); + } else { + CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); + } + } + if (executableURL) CFRelease(executableURL); + } + if (!bundle->_isLoaded && error) *error = localError; + return bundle->_isLoaded; +} + +CF_PRIVATE Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErrorRef *error) { + CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + char buff[CFMaxPathSize]; + if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { + int mode = RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST; + void *cookie = dlopen(buff, mode); +#if LOG_BUNDLE_LOAD + printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie); +#endif /* LOG_BUNDLE_LOAD */ + if (cookie && cookie == bundle->_handleCookie) { + // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose +#if LOG_BUNDLE_LOAD + printf("dlfcn load framework %p closing existing reference to handle %p\n", bundle, cookie); +#endif /* LOG_BUNDLE_LOAD */ + dlclose(bundle->_handleCookie); + } + bundle->_handleCookie = cookie; + if (bundle->_handleCookie) { + bundle->_isLoaded = true; + } else { + const char *dyldError = dlerror(); + CFStringRef errorString = dyldError ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dyldError) : NULL; + if (error) { + _CFBundleDlfcnPreflight(bundle, subError); + if (!localError) localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, errorString); + } else { + CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); + CFLog(__kCFLogBundle, CFSTR("Error loading %@: %@"), executableString, errorString ? errorString : CFSTR("(no additional info)")); + } + if (errorString) CFRelease(errorString); + } + } else { + if (error) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); + } else { + CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); + } + } + if (executableURL) CFRelease(executableURL); + } + if (!bundle->_isLoaded && error) *error = localError; + return bundle->_isLoaded; +} + +CF_PRIVATE void _CFBundleDlfcnUnload(CFBundleRef bundle) { + if (bundle->_isLoaded) { +#if LOG_BUNDLE_LOAD + printf("dlfcn unload bundle %p, handle %p module %p image %p\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie); +#endif /* LOG_BUNDLE_LOAD */ + if (0 != dlclose(bundle->_handleCookie)) { + CFLog(__kCFLogBundle, CFSTR("Internal error unloading bundle %@"), bundle); + } else { + bundle->_connectionCookie = bundle->_handleCookie = NULL; + bundle->_imageCookie = bundle->_moduleCookie = NULL; + bundle->_isLoaded = false; + } + } +} + +CF_PRIVATE void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { + return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, symbolName, false); +} + +static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) { + void *result = NULL; + char buff[1026]; + + if (CFStringGetCString(symbolName, buff, 1024, kCFStringEncodingUTF8)) { + result = dlsym(bundle->_handleCookie, buff); + if (!result && globalSearch) result = dlsym(RTLD_DEFAULT, buff); +#if defined(DEBUG) + if (!result) CFLog(__kCFLogBundle, CFSTR("dlsym cannot find symbol %@ in %@"), symbolName, bundle); +#endif /* DEBUG */ +#if LOG_BUNDLE_LOAD + printf("bundle %p handle %p module %p image %p dlsym returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff); +#endif /* LOG_BUNDLE_LOAD */ + } + return result; +} + +#if !defined(BINARY_SUPPORT_DYLD) + +static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p) { + CFStringRef result = NULL; + Dl_info info; + if (0 != dladdr(p, &info) && info.dli_fname) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, info.dli_fname); +#if LOG_BUNDLE_LOAD + printf("dlfcn image path for pointer %p is %p\n", p, result); +#endif /* LOG_BUNDLE_LOAD */ + return result; +} + +#endif /* !BINARY_SUPPORT_DYLD */ +#endif /* BINARY_SUPPORT_DLFCN */ + +#if defined(BINARY_SUPPORT_DLL) + +CF_PRIVATE Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *error) { + CFErrorRef localError = NULL; + if (!bundle->_isLoaded) { + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + wchar_t buff[CFMaxPathSize]; + + if (executableURL && _CFURLGetWideFileSystemRepresentation(executableURL, true, (wchar_t *)buff, CFMaxPathSize)) { + bundle->_hModule = LoadLibraryW(buff); + if (bundle->_hModule) { + bundle->_isLoaded = true; + } else { + if (error) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError); + } else { + CFLog(__kCFLogBundle, CFSTR("Failed to load bundle %@"), bundle); + } + } + } else { + if (error) { + localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); + } else { + CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); + } + } + if (executableURL) CFRelease(executableURL); + } + if (!bundle->_isLoaded && error) *error = localError; + return bundle->_isLoaded; +} + +CF_PRIVATE void _CFBundleDLLUnload(CFBundleRef bundle) { + if (bundle->_isLoaded) { + FreeLibrary(bundle->_hModule); + bundle->_hModule = NULL; + bundle->_isLoaded = false; + } +} + +CF_PRIVATE void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { + void *result = NULL; + char buff[1024]; + if (CFStringGetCString(symbolName, buff, 1024, kCFStringEncodingWindowsLatin1)) result = GetProcAddress(bundle->_hModule, buff); + return result; +} + +#endif /* BINARY_SUPPORT_DLL */ + +CF_PRIVATE CFStringRef _CFBundleCopyLoadedImagePathForPointer(void *p) { + CFStringRef imagePath = NULL; +#if defined(BINARY_SUPPORT_DYLD) + if (!imagePath) imagePath = _CFBundleDYLDCopyLoadedImagePathForPointer(p); +#elif defined(BINARY_SUPPORT_DLFCN) + if (!imagePath) imagePath = _CFBundleDlfcnCopyLoadedImagePathForPointer(p); +#endif /* BINARY_SUPPORT_DYLD */ + return imagePath; +} + +void *CFBundleGetFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) { + void *tvp = NULL; + // Load if necessary + if (!bundle->_isLoaded) { + if (!CFBundleLoadExecutable(bundle)) return NULL; + } + + switch (bundle->_binaryType) { +#if defined(BINARY_SUPPORT_DYLD) + case __CFBundleDYLDBundleBinary: + case __CFBundleDYLDFrameworkBinary: + case __CFBundleDYLDExecutableBinary: +#if defined(BINARY_SUPPORT_DLFCN) + if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName); +#else /* BINARY_SUPPORT_DLFCN */ + return _CFBundleDYLDGetSymbolByName(bundle, funcName); +#endif /* BINARY_SUPPORT_DLFCN */ + break; +#endif /* BINARY_SUPPORT_DYLD */ +#if defined(BINARY_SUPPORT_DLL) + case __CFBundleDLLBinary: + tvp = _CFBundleDLLGetSymbolByName(bundle, funcName); + break; +#endif /* BINARY_SUPPORT_DLL */ + default: +#if defined(BINARY_SUPPORT_DLFCN) + if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName); +#endif /* BINARY_SUPPORT_DLFCN */ + break; + } + return tvp; +} + +void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) { + void *fp = NULL; + // Load if necessary + if (!bundle->_isLoaded) { + if (!CFBundleLoadExecutable(bundle)) return NULL; + } +#if defined (BINARY_SUPPORT_DYLD) || defined (BINARY_SUPPORT_DLFCN) + switch (bundle->_binaryType) { +#if defined(BINARY_SUPPORT_DYLD) + case __CFBundleDYLDBundleBinary: + case __CFBundleDYLDFrameworkBinary: + case __CFBundleDYLDExecutableBinary: +#if defined(BINARY_SUPPORT_DLFCN) + if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true); +#else /* BINARY_SUPPORT_DLFCN */ + fp = _CFBundleDYLDGetSymbolByNameWithSearch(bundle, funcName, true); +#endif /* BINARY_SUPPORT_DLFCN */ + break; +#endif /* BINARY_SUPPORT_DYLD */ + default: +#if defined(BINARY_SUPPORT_DLFCN) + if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true); +#endif /* BINARY_SUPPORT_DLFCN */ + break; + } +#endif /* BINARY_SUPPORT_DYLD || BINARY_SUPPORT_DLFCN */ + return fp; +} + +void CFBundleGetFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) { + SInt32 i, c; + + if (!ftbl) return; + + c = CFArrayGetCount(functionNames); + for (i = 0; i < c; i++) ftbl[i] = CFBundleGetFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i)); +} + +void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) { + SInt32 i, c; + + if (!ftbl) return; + + c = CFArrayGetCount(functionNames); + for (i = 0; i < c; i++) ftbl[i] = _CFBundleGetCFMFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i)); +} + +void *CFBundleGetDataPointerForName(CFBundleRef bundle, CFStringRef symbolName) { + void *dp = NULL; + // Load if necessary + if (!bundle->_isLoaded && !CFBundleLoadExecutable(bundle)) return NULL; + + switch (bundle->_binaryType) { +#if defined(BINARY_SUPPORT_DYLD) + case __CFBundleDYLDBundleBinary: + case __CFBundleDYLDFrameworkBinary: + case __CFBundleDYLDExecutableBinary: +#if defined(BINARY_SUPPORT_DLFCN) + if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName); +#else /* BINARY_SUPPORT_DLFCN */ + dp = _CFBundleDYLDGetSymbolByName(bundle, symbolName); +#endif /* BINARY_SUPPORT_DLFCN */ + break; +#endif /* BINARY_SUPPORT_DYLD */ +#if defined(BINARY_SUPPORT_DLL) + case __CFBundleDLLBinary: + /* MF:!!! Handle this someday */ + break; +#endif /* BINARY_SUPPORT_DLL */ + default: +#if defined(BINARY_SUPPORT_DLFCN) + if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName); +#endif /* BINARY_SUPPORT_DLFCN */ + break; + } + return dp; +} + +void CFBundleGetDataPointersForNames(CFBundleRef bundle, CFArrayRef symbolNames, void *stbl[]) { + SInt32 i, c; + + if (!stbl) return; + + c = CFArrayGetCount(symbolNames); + for (i = 0; i < c; i++) stbl[i] = CFBundleGetDataPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(symbolNames, i)); +} + diff --git a/CFBundle_BinaryTypes.h b/CFBundle_BinaryTypes.h index 8629306..1fea55c 100644 --- a/CFBundle_BinaryTypes.h +++ b/CFBundle_BinaryTypes.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBundle_BinaryTypes.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLE_BINARYTYPES__) diff --git a/CFBundle_Grok.c b/CFBundle_Grok.c new file mode 100644 index 0000000..9d63c78 --- /dev/null +++ b/CFBundle_Grok.c @@ -0,0 +1,1014 @@ +/* + * Copyright (c) 2014 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* CFBundle_Grok.c + Copyright (c) 1999-2014, Apple Inc. All rights reserved. + Responsibility: Tony Parker +*/ + +#include "CFBundle_Internal.h" + +#if defined(BINARY_SUPPORT_DYLD) +// Import the mach-o headers that define the macho magic numbers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(USE_DYLD_PRIV) +#include +#endif /* USE_DYLD_PRIV */ +#endif /* BINARY_SUPPORT_DYLD */ + +#if defined(BINARY_SUPPORT_DLFCN) +#include +#endif /* BINARY_SUPPORT_DLFCN */ + +#include +#include + +#if DEPLOYMENT_TARGET_WINDOWS +#define statinfo _stat +#define stat(x,y) _NS_stat(x,y) +#define open _NS_open +#define MAP_FAILED 0 + +// Windows isspace implementation limits the input chars to < 256 in the ASCII range. It will +// assert in debug builds. This is annoying. We merrily grok chars > 256. +static inline BOOL isspace(char c) { + return (c == ' ' || c == '\t' || c == '\n' || c == '\r'|| c == '\v' || c == '\f'); +} + +#else +#define statinfo stat +#endif + +#define UNKNOWN_FILETYPE 0x0 +#define PEF_FILETYPE 0x1000 +#define PEF_MAGIC 0x4a6f7921 +#define PEF_CIGAM 0x21796f4a +#define TEXT_SEGMENT "__TEXT" +#define PLIST_SECTION "__info_plist" +#define OBJC_SEGMENT "__OBJC" +#define IMAGE_INFO_SECTION "__image_info" +#define OBJC_SEGMENT_64 "__DATA" +#define IMAGE_INFO_SECTION_64 "__objc_imageinfo" +#define LIB_X11 "/usr/X11R6/lib/libX" + +#define XLS_NAME "Book" +#define XLS_NAME2 "Workbook" +#define DOC_NAME "WordDocument" +#define PPT_NAME "PowerPoint Document" + +#define ustrncmp(x, y, z) strncmp((char *)(x), (char *)(y), (z)) +#define ustrncasecmp(x, y, z) strncasecmp_l((char *)(x), (char *)(y), (z), NULL) + +static const uint32_t __CFBundleMagicNumbersArray[] = { + 0xcafebabe, 0xbebafeca, 0xfeedface, 0xcefaedfe, 0xfeedfacf, 0xcffaedfe, 0x4a6f7921, 0x21796f4a, + 0x7f454c46, 0xffd8ffe0, 0x4d4d002a, 0x49492a00, 0x47494638, 0x89504e47, 0x69636e73, 0x00000100, + 0x7b5c7274, 0x25504446, 0x2e7261fd, 0x2e524d46, 0x2e736e64, 0x2e736400, 0x464f524d, 0x52494646, + 0x38425053, 0x000001b3, 0x000001ba, 0x4d546864, 0x504b0304, 0x53495421, 0x53495432, 0x53495435, + 0x53495444, 0x53747566, 0x30373037, 0x3c212d2d, 0x25215053, 0xd0cf11e0, 0x62656769, 0x3d796265, + 0x6b6f6c79, 0x3026b275, 0x0000000c, 0xfe370023, 0x09020600, 0x09040600, 0x4f676753, 0x664c6143, + 0x00010000, 0x74727565, 0x4f54544f, 0x41433130, 0xc809fe02, 0x0809fe02, 0x2356524d, 0x67696d70, + 0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664, 0x63616666, 0x802a5fd7, 0x762f3101 +}; + +// string, with groups of 5 characters being 1 element in the array +static const char * __CFBundleExtensionsArray = + "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "pef\0\0" "pef\0\0" + "elf\0\0" "jpeg\0" "tiff\0" "tiff\0" "gif\0\0" "png\0\0" "icns\0" "ico\0\0" + "rtf\0\0" "pdf\0\0" "ra\0\0\0""rm\0\0\0""au\0\0\0""au\0\0\0""iff\0\0" "riff\0" + "psd\0\0" "mpeg\0" "mpeg\0" "mid\0\0" "zip\0\0" "sit\0\0" "sit\0\0" "sit\0\0" + "sit\0\0" "sit\0\0" "cpio\0" "html\0" "ps\0\0\0""ole\0\0" "uu\0\0\0""ync\0\0" + "dmg\0\0" "wmv\0\0" "jp2\0\0" "doc\0\0" "xls\0\0" "xls\0\0" "ogg\0\0" "flac\0" + "ttf\0\0" "ttf\0\0" "otf\0\0" "dwg\0\0" "dgn\0\0" "dgn\0\0" "wrl\0\0" "xcf\0\0" + "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0" "caf\0\0" "cin\0\0" "exr\0\0"; + +static const char * __CFBundleOOExtensionsArray = "sxc\0\0" "sxd\0\0" "sxg\0\0" "sxi\0\0" "sxm\0\0" "sxw\0\0"; +static const char * __CFBundleODExtensionsArray = "odc\0\0" "odf\0\0" "odg\0\0" "oth\0\0" "odi\0\0" "odm\0\0" "odp\0\0" "ods\0\0" "odt\0\0"; + +#define EXTENSION_LENGTH 5 +#define NUM_EXTENSIONS 64 +#define MAGIC_BYTES_TO_READ 512 +#define DMG_BYTES_TO_READ 512 +#define ZIP_BYTES_TO_READ 1024 +#define OLE_BYTES_TO_READ 512 +#define X11_BYTES_TO_READ 4096 +#define IMAGE_INFO_BYTES_TO_READ 4096 + +#if defined(BINARY_SUPPORT_DYLD) + +static CFMutableDictionaryRef _CFBundleCreateInfoDictFromData(const char *bytes, uint32_t length) { + CFMutableDictionaryRef result = NULL; + CFDataRef infoData = NULL; + if (bytes && 0 < length) { + infoData = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (uint8_t *)bytes, length, kCFAllocatorNull); + if (infoData) { + result = (CFMutableDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorSystemDefault, infoData, kCFPropertyListMutableContainers, NULL, NULL); + if (result && CFDictionaryGetTypeID() != CFGetTypeID(result)) { + CFRelease(result); + result = NULL; + } + CFRelease(infoData); + } + if (!result) result = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + if (result) _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); + return result; +} + +static char *_CFBundleGetSectData(const char *segname, const char *sectname, unsigned long *size) { + char *retval = NULL; + unsigned long localSize = 0; + uint32_t i, numImages = _dyld_image_count(); + const void *mhp = (const void *)_NSGetMachExecuteHeader(); + + for (i = 0; i < numImages; i++) { + if (mhp == (void *)_dyld_get_image_header(i)) { +#if __LP64__ + const struct section_64 *sp = getsectbynamefromheader_64((const struct mach_header_64 *)mhp, segname, sectname); + if (sp) { + retval = (char *)(sp->addr + _dyld_get_image_vmaddr_slide(i)); + localSize = (unsigned long)sp->size; + } +#else /* __LP64__ */ + const struct section *sp = getsectbynamefromheader((const struct mach_header *)mhp, segname, sectname); + if (sp) { + retval = (char *)(sp->addr + _dyld_get_image_vmaddr_slide(i)); + localSize = (unsigned long)sp->size; + } +#endif /* __LP64__ */ + break; + } + } + if (size) *size = localSize; + return retval; +} + +CF_PRIVATE CFMutableDictionaryRef _CFBundleCreateInfoDictFromMainExecutable() { + char *bytes = NULL; + unsigned long length = 0; + if (getsegbyname(TEXT_SEGMENT)) bytes = _CFBundleGetSectData(TEXT_SEGMENT, PLIST_SECTION, &length); + return _CFBundleCreateInfoDictFromData(bytes, length); +} + +CF_PRIVATE Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags) { + Boolean retval = false; + uint32_t localVersion = 0, localFlags = 0; + char *bytes = NULL; + unsigned long length = 0; +#if __LP64__ + if (getsegbyname(OBJC_SEGMENT_64)) bytes = _CFBundleGetSectData(OBJC_SEGMENT_64, IMAGE_INFO_SECTION_64, &length); +#else /* __LP64__ */ + if (getsegbyname(OBJC_SEGMENT)) bytes = _CFBundleGetSectData(OBJC_SEGMENT, IMAGE_INFO_SECTION, &length); +#endif /* __LP64__ */ + if (bytes && length >= 8) { + localVersion = *(uint32_t *)bytes; + localFlags = *(uint32_t *)(bytes + 4); + retval = true; + } + if (objcVersion) *objcVersion = localVersion; + if (objcFlags) *objcFlags = localFlags; + return retval; +} + +static Boolean _CFBundleGrokX11FromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour) { + static const char libX11name[] = LIB_X11; + char *buffer = NULL; + const char *loc = NULL; + unsigned i; + Boolean result = false; + + if (fd >= 0 && lseek(fd, offset, SEEK_SET) == (off_t)offset) { + buffer = malloc(X11_BYTES_TO_READ); + if (buffer && read(fd, buffer, X11_BYTES_TO_READ) >= X11_BYTES_TO_READ) loc = buffer; + } else if (bytes && length >= offset + X11_BYTES_TO_READ) { + loc = bytes + offset; + } + if (loc) { + if (sixtyFour) { + uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->ncmds, swapped); + uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->sizeofcmds, swapped); + const char *startofcmds = loc + sizeof(struct mach_header_64); + const char *endofcmds = startofcmds + sizeofcmds; + struct dylib_command *dlp = (struct dylib_command *)startofcmds; + if (endofcmds > loc + X11_BYTES_TO_READ) endofcmds = loc + X11_BYTES_TO_READ; + for (i = 0; !result && i < ncmds && startofcmds <= (char *)dlp && (char *)dlp < endofcmds; i++) { + if (LC_LOAD_DYLIB == _CFBundleSwapInt32Conditional(dlp->cmd, swapped)) { + uint32_t nameoffset = _CFBundleSwapInt32Conditional(dlp->dylib.name.offset, swapped); + const char *name = (const char *)dlp + nameoffset; + if (startofcmds <= name && name + sizeof(libX11name) <= endofcmds && 0 == strncmp(name, libX11name, sizeof(libX11name) - 1)) result = true; + } + dlp = (struct dylib_command *)((char *)dlp + _CFBundleSwapInt32Conditional(dlp->cmdsize, swapped)); + } + } else { + uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->ncmds, swapped); + uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->sizeofcmds, swapped); + const char *startofcmds = loc + sizeof(struct mach_header); + const char *endofcmds = startofcmds + sizeofcmds; + struct dylib_command *dlp = (struct dylib_command *)startofcmds; + if (endofcmds > loc + X11_BYTES_TO_READ) endofcmds = loc + X11_BYTES_TO_READ; + for (i = 0; !result && i < ncmds && startofcmds <= (char *)dlp && (char *)dlp < endofcmds; i++) { + if (LC_LOAD_DYLIB == _CFBundleSwapInt32Conditional(dlp->cmd, swapped)) { + uint32_t nameoffset = _CFBundleSwapInt32Conditional(dlp->dylib.name.offset, swapped); + const char *name = (const char *)dlp + nameoffset; + if (startofcmds <= name && name + sizeof(libX11name) <= endofcmds && 0 == strncmp(name, libX11name, sizeof(libX11name) - 1)) result = true; + } + dlp = (struct dylib_command *)((char *)dlp + _CFBundleSwapInt32Conditional(dlp->cmdsize, swapped)); + } + } + } + if (buffer) free(buffer); + return result; +} + +static CFDictionaryRef _CFBundleCreateInfoDictFromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour) { + struct statinfo statBuf; + off_t fileLength = 0; + char *maploc = NULL; + const char *loc; + unsigned i, j; + CFDictionaryRef result = NULL; + Boolean foundit = false; + if (fd >= 0 && fstat(fd, &statBuf) == 0 && (maploc = mmap(0, statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) != (void *)-1) { + loc = maploc; + fileLength = statBuf.st_size; + } else { + loc = bytes; + fileLength = length; + } + if (fileLength > offset + sizeof(struct mach_header_64)) { + if (sixtyFour) { + uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)(loc + offset))->ncmds, swapped); + uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)(loc + offset))->sizeofcmds, swapped); + const char *startofcmds = loc + offset + sizeof(struct mach_header_64); + const char *endofcmds = startofcmds + sizeofcmds; + struct segment_command_64 *sgp = (struct segment_command_64 *)startofcmds; + if (endofcmds > loc + fileLength) endofcmds = loc + fileLength; + for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { + if (LC_SEGMENT_64 == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { + struct section_64 *sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64)); + uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); + for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { + if (0 == strncmp(sp->sectname, PLIST_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, TEXT_SEGMENT, sizeof(sp->segname))) { + uint64_t sectlength64 = _CFBundleSwapInt64Conditional(sp->size, swapped); + uint32_t sectlength = (uint32_t)(sectlength64 & 0xffffffff); + uint32_t sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); + const char *sectbytes = loc + offset + sectoffset; + // we don't support huge-sized plists + if (sectlength64 <= 0xffffffff && loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleCreateInfoDictFromData(sectbytes, sectlength); + foundit = true; + } + sp = (struct section_64 *)((char *)sp + sizeof(struct section_64)); + } + } + sgp = (struct segment_command_64 *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); + } + } else { + uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header *)(loc + offset))->ncmds, swapped); + uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header *)(loc + offset))->sizeofcmds, swapped); + const char *startofcmds = loc + offset + sizeof(struct mach_header); + const char *endofcmds = startofcmds + sizeofcmds; + struct segment_command *sgp = (struct segment_command *)startofcmds; + if (endofcmds > loc + fileLength) endofcmds = loc + fileLength; + for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { + if (LC_SEGMENT == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { + struct section *sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); + uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); + for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { + if (0 == strncmp(sp->sectname, PLIST_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, TEXT_SEGMENT, sizeof(sp->segname))) { + uint32_t sectlength = _CFBundleSwapInt32Conditional(sp->size, swapped); + uint32_t sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); + const char *sectbytes = loc + offset + sectoffset; + if (loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleCreateInfoDictFromData(sectbytes, sectlength); + foundit = true; + } + sp = (struct section *)((char *)sp + sizeof(struct section)); + } + } + sgp = (struct segment_command *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); + } + } + } + if (maploc) munmap(maploc, statBuf.st_size); + return result; +} + +static void _CFBundleGrokObjcImageInfoFromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { + uint32_t sectlength = 0, sectoffset = 0, localVersion = 0, localFlags = 0; + char *buffer = NULL; + char sectbuffer[8]; + const char *loc = NULL; + unsigned i, j; + Boolean foundit = false, localHasObjc = false; + + if (fd >= 0 && lseek(fd, offset, SEEK_SET) == (off_t)offset) { + buffer = malloc(IMAGE_INFO_BYTES_TO_READ); + if (buffer && read(fd, buffer, IMAGE_INFO_BYTES_TO_READ) >= IMAGE_INFO_BYTES_TO_READ) loc = buffer; + } else if (bytes && length >= offset + IMAGE_INFO_BYTES_TO_READ) { + loc = bytes + offset; + } + if (loc) { + if (sixtyFour) { + uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->ncmds, swapped); + uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header_64 *)loc)->sizeofcmds, swapped); + const char *startofcmds = loc + sizeof(struct mach_header_64); + const char *endofcmds = startofcmds + sizeofcmds; + struct segment_command_64 *sgp = (struct segment_command_64 *)startofcmds; + if (endofcmds > loc + IMAGE_INFO_BYTES_TO_READ) endofcmds = loc + IMAGE_INFO_BYTES_TO_READ; + for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { + if (LC_SEGMENT_64 == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { + struct section_64 *sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64)); + uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); + for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { + if (0 == strncmp(sp->segname, OBJC_SEGMENT_64, sizeof(sp->segname))) localHasObjc = true; + if (0 == strncmp(sp->sectname, IMAGE_INFO_SECTION_64, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, OBJC_SEGMENT_64, sizeof(sp->segname))) { + uint64_t sectlength64 = _CFBundleSwapInt64Conditional(sp->size, swapped); + sectlength = (uint32_t)(sectlength64 & 0xffffffff); + sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); + foundit = true; + } + sp = (struct section_64 *)((char *)sp + sizeof(struct section_64)); + } + } + sgp = (struct segment_command_64 *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); + } + } else { + uint32_t ncmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->ncmds, swapped); + uint32_t sizeofcmds = _CFBundleSwapInt32Conditional(((struct mach_header *)loc)->sizeofcmds, swapped); + const char *startofcmds = loc + sizeof(struct mach_header); + const char *endofcmds = startofcmds + sizeofcmds; + struct segment_command *sgp = (struct segment_command *)startofcmds; + if (endofcmds > loc + IMAGE_INFO_BYTES_TO_READ) endofcmds = loc + IMAGE_INFO_BYTES_TO_READ; + for (i = 0; !foundit && i < ncmds && startofcmds <= (char *)sgp && (char *)sgp < endofcmds; i++) { + if (LC_SEGMENT == _CFBundleSwapInt32Conditional(sgp->cmd, swapped)) { + struct section *sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); + uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped); + for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) { + if (0 == strncmp(sp->segname, OBJC_SEGMENT, sizeof(sp->segname))) localHasObjc = true; + if (0 == strncmp(sp->sectname, IMAGE_INFO_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, OBJC_SEGMENT, sizeof(sp->segname))) { + sectlength = _CFBundleSwapInt32Conditional(sp->size, swapped); + sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped); + foundit = true; + } + sp = (struct section *)((char *)sp + sizeof(struct section)); + } + } + sgp = (struct segment_command *)((char *)sgp + _CFBundleSwapInt32Conditional(sgp->cmdsize, swapped)); + } + } + if (sectlength >= 8) { + if (fd >= 0 && lseek(fd, offset + sectoffset, SEEK_SET) == (off_t)(offset + sectoffset) && read(fd, sectbuffer, 8) >= 8) { + localVersion = _CFBundleSwapInt32Conditional(*(uint32_t *)sectbuffer, swapped); + localFlags = _CFBundleSwapInt32Conditional(*(uint32_t *)(sectbuffer + 4), swapped); + } else if (bytes && length >= offset + sectoffset + 8) { + localVersion = _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes + offset + sectoffset), swapped); + localFlags = _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes + offset + sectoffset + 4), swapped); + } + } + } + if (buffer) free(buffer); + if (hasObjc) *hasObjc = localHasObjc; + if (objcVersion) *objcVersion = localVersion; + if (objcFlags) *objcFlags = localFlags; +} + +static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex length, Boolean swap, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { + CFIndex headerLength = length; + unsigned char headerBuffer[MAGIC_BYTES_TO_READ]; + UInt32 machtype = UNKNOWN_FILETYPE, magic, numFatHeaders, maxFatHeaders, i; + unsigned char buffer[sizeof(struct mach_header_64)]; + const unsigned char *moreBytes = NULL; + const NXArchInfo *archInfo = NXGetLocalArchInfo(); + SInt32 curArch = _CFBundleCurrentArchitecture(); + + struct fat_arch *fat = NULL; + + if (isX11) *isX11 = false; + if (architectures) *architectures = NULL; + if (infodict) *infodict = NULL; + if (hasObjc) *hasObjc = false; + if (objcVersion) *objcVersion = 0; + if (objcFlags) *objcFlags = 0; + + if (headerLength > MAGIC_BYTES_TO_READ) headerLength = MAGIC_BYTES_TO_READ; + (void)memmove(headerBuffer, bytes, headerLength); + if (swap) { + for (i = 0; i < headerLength; i += 4) *(UInt32 *)(headerBuffer + i) = CFSwapInt32(*(UInt32 *)(headerBuffer + i)); + } + numFatHeaders = ((struct fat_header *)headerBuffer)->nfat_arch; + maxFatHeaders = (headerLength - sizeof(struct fat_header)) / sizeof(struct fat_arch); + if (numFatHeaders > maxFatHeaders) numFatHeaders = maxFatHeaders; + if (numFatHeaders > 0) { + if (archInfo) fat = NXFindBestFatArch(archInfo->cputype, archInfo->cpusubtype, (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)), numFatHeaders); + if (!fat && curArch != 0) fat = NXFindBestFatArch((cpu_type_t)curArch, (cpu_subtype_t)0, (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)), numFatHeaders); + if (!fat) fat = (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)); + if (architectures) { + CFMutableArrayRef mutableArchitectures = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + for (i = 0; i < numFatHeaders; i++) { + CFNumberRef architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, headerBuffer + sizeof(struct fat_header) + i * sizeof(struct fat_arch)); + if (CFArrayGetFirstIndexOfValue(mutableArchitectures, CFRangeMake(0, CFArrayGetCount(mutableArchitectures)), architecture) < 0) CFArrayAppendValue(mutableArchitectures, architecture); + CFRelease(architecture); + } + *architectures = (CFArrayRef)mutableArchitectures; + } + } + if (fat) { + if (fd >= 0 && lseek(fd, fat->offset, SEEK_SET) == (off_t)fat->offset && read(fd, buffer, sizeof(struct mach_header_64)) >= (int)sizeof(struct mach_header_64)) { + moreBytes = buffer; + } else if (bytes && (uint32_t)length >= fat->offset + sizeof(struct mach_header_64)) { + moreBytes = bytes + fat->offset; + } + if (moreBytes) { + magic = *((UInt32 *)moreBytes); + if (MH_MAGIC == magic) { + machtype = ((struct mach_header *)moreBytes)->filetype; + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, false, false); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, false, false); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, false, false, hasObjc, objcVersion, objcFlags); + } else if (MH_CIGAM == magic) { + machtype = CFSwapInt32(((struct mach_header *)moreBytes)->filetype); + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, true, false); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, true, false); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, true, false, hasObjc, objcVersion, objcFlags); + } else if (MH_MAGIC_64 == magic) { + machtype = ((struct mach_header_64 *)moreBytes)->filetype; + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, false, true); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, false, true); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, false, true, hasObjc, objcVersion, objcFlags); + } else if (MH_CIGAM_64 == magic) { + machtype = CFSwapInt32(((struct mach_header_64 *)moreBytes)->filetype); + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, fat->offset, true, true); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, fat->offset, true, true); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, fat->offset, true, true, hasObjc, objcVersion, objcFlags); + } + } + } + return machtype; +} + +static UInt32 _CFBundleGrokMachType(int fd, const void *bytes, CFIndex length, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { + unsigned int magic = *((UInt32 *)bytes), machtype = UNKNOWN_FILETYPE, cputype; + CFNumberRef architecture = NULL; + + if (isX11) *isX11 = false; + if (architectures) *architectures = NULL; + if (infodict) *infodict = NULL; + if (hasObjc) *hasObjc = false; + if (objcVersion) *objcVersion = 0; + if (objcFlags) *objcFlags = 0; + if (MH_MAGIC == magic) { + machtype = ((struct mach_header *)bytes)->filetype; + cputype = ((struct mach_header *)bytes)->cputype; + if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, false, false); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, false, false); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, false, false, hasObjc, objcVersion, objcFlags); + } else if (MH_CIGAM == magic) { + machtype = CFSwapInt32(((struct mach_header *)bytes)->filetype); + cputype = CFSwapInt32(((struct mach_header *)bytes)->cputype); + if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, true, false); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, true, false); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, true, false, hasObjc, objcVersion, objcFlags); + } else if (MH_MAGIC_64 == magic) { + machtype = ((struct mach_header_64 *)bytes)->filetype; + cputype = ((struct mach_header_64 *)bytes)->cputype; + if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, false, true); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, false, true); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, false, true, hasObjc, objcVersion, objcFlags); + } else if (MH_CIGAM_64 == magic) { + machtype = CFSwapInt32(((struct mach_header_64 *)bytes)->filetype); + cputype = CFSwapInt32(((struct mach_header_64 *)bytes)->cputype); + if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype); + if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, true, true); + if (infodict) *infodict = _CFBundleCreateInfoDictFromFile(fd, bytes, length, 0, true, true); + if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, true, true, hasObjc, objcVersion, objcFlags); + } else if (FAT_MAGIC == magic) { + machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, false, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags); + } else if (FAT_CIGAM == magic) { + machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, true, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags); + } else if (PEF_MAGIC == magic || PEF_CIGAM == magic) { + machtype = PEF_FILETYPE; + } + if (architectures && architecture) *architectures = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&architecture, 1, &kCFTypeArrayCallBacks); + if (architecture) CFRelease(architecture); + return machtype; +} + +#endif /* BINARY_SUPPORT_DYLD */ + +static Boolean _CFBundleGrokFileTypeForZipMimeType(const unsigned char *bytes, CFIndex length, const char **ext) { + unsigned namelength = CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 26))), extralength = CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 28))); + const unsigned char *data = bytes + 30 + namelength + extralength; + int i = -1; + if (bytes < data && data + 56 <= bytes + length && 0 == CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 8))) && (0 == ustrncasecmp(data, "application/vnd.", 16) || 0 == ustrncasecmp(data, "application/x-vnd.", 18))) { + data += ('.' == *(data + 15)) ? 16 : 18; + if (0 == ustrncasecmp(data, "sun.xml.", 8)) { + data += 8; + if (0 == ustrncasecmp(data, "calc", 4)) i = 0; + else if (0 == ustrncasecmp(data, "draw", 4)) i = 1; + else if (0 == ustrncasecmp(data, "writer.global", 13)) i = 2; + else if (0 == ustrncasecmp(data, "impress", 7)) i = 3; + else if (0 == ustrncasecmp(data, "math", 4)) i = 4; + else if (0 == ustrncasecmp(data, "writer", 6)) i = 5; + if (i >= 0 && ext) *ext = __CFBundleOOExtensionsArray + i * EXTENSION_LENGTH; + } else if (0 == ustrncasecmp(data, "oasis.opendocument.", 19)) { + data += 19; + if (0 == ustrncasecmp(data, "chart", 5)) i = 0; + else if (0 == ustrncasecmp(data, "formula", 7)) i = 1; + else if (0 == ustrncasecmp(data, "graphics", 8)) i = 2; + else if (0 == ustrncasecmp(data, "text-web", 8)) i = 3; + else if (0 == ustrncasecmp(data, "image", 5)) i = 4; + else if (0 == ustrncasecmp(data, "text-master", 11)) i = 5; + else if (0 == ustrncasecmp(data, "presentation", 12)) i = 6; + else if (0 == ustrncasecmp(data, "spreadsheet", 11)) i = 7; + else if (0 == ustrncasecmp(data, "text", 4)) i = 8; + if (i >= 0 && ext) *ext = __CFBundleODExtensionsArray + i * EXTENSION_LENGTH; + } + } else if (bytes < data && data + 41 <= bytes + length && 8 == CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 8))) && 0x4b2c28c8 == CFSwapInt32HostToBig(*((UInt32 *)data)) && 0xc94c4e2c == CFSwapInt32HostToBig(*((UInt32 *)(data + 4)))) { + // AbiWord compressed mimetype odt + if (ext) *ext = "odt"; + // almost certainly this should set i to 0 but I don't want to upset the apple cart now + } else if (bytes < data && data + 29 <= bytes + length && (0 == ustrncasecmp(data, "application/oebps-package+xml", 29))) { + // epub, official epub 3 mime type + if (ext) *ext = "epub"; + i = 0; + } else if (bytes < data && data + 20 <= bytes + length && (0 == ustrncasecmp(data, "application/epub+zip", 20))) { + // epub, unofficial epub 2 mime type + if (ext) *ext = "epub"; + i = 0; + } + return (i >= 0); +} + +static const char *_CFBundleGrokFileTypeForZipFile(int fd, const unsigned char *bytes, CFIndex length, off_t fileLength) { + const char *ext = "zip"; + const unsigned char *moreBytes = NULL; + unsigned char *buffer = NULL; + CFIndex i; + Boolean foundMimetype = false, hasMetaInf = false, hasContentXML = false, hasManifestMF = false, hasManifestXML = false, hasRels = false, hasContentTypes = false, hasWordDocument = false, hasExcelDocument = false, hasPowerPointDocument = false, hasOPF = false, hasSMIL = false; + + if (bytes) { + for (i = 0; !foundMimetype && i + 30 < length; i++) { + if (0x50 == bytes[i] && 0x4b == bytes[i + 1]) { + unsigned namelength = 0, offset = 0; + if (0x01 == bytes[i + 2] && 0x02 == bytes[i + 3]) { + namelength = (unsigned)CFSwapInt16HostToLittle(*((UInt16 *)(bytes + i + 28))); + offset = 46; + } else if (0x03 == bytes[i + 2] && 0x04 == bytes[i + 3]) { + namelength = (unsigned)CFSwapInt16HostToLittle(*((UInt16 *)(bytes + i + 26))); + offset = 30; + } + if (offset > 0 && (CFIndex)(i + offset + namelength) <= length) { + //printf("%.*s\n", namelength, bytes + i + offset); + if (8 == namelength && 30 == offset && 0 == ustrncasecmp(bytes + i + offset, "mimetype", 8)) foundMimetype = _CFBundleGrokFileTypeForZipMimeType(bytes + i, length - i, &ext); + else if (9 == namelength && 0 == ustrncasecmp(bytes + i + offset, "META-INF/", 9)) hasMetaInf = true; + else if (11 == namelength && 0 == ustrncasecmp(bytes + i + offset, "content.xml", 11)) hasContentXML = true; + else if (11 == namelength && 0 == ustrncasecmp(bytes + i + offset, "_rels/.rels", 11)) hasRels = true; + else if (19 == namelength && 0 == ustrncasecmp(bytes + i + offset, "[Content_Types].xml", 19)) hasContentTypes = true; + else if (20 == namelength && 0 == ustrncasecmp(bytes + i + offset, "META-INF/MANIFEST.MF", 20)) hasManifestMF = true; + else if (21 == namelength && 0 == ustrncasecmp(bytes + i + offset, "META-INF/manifest.xml", 21)) hasManifestXML = true; + else if (4 < namelength && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".opf", 4)) hasOPF = true; + else if (4 < namelength && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".sml", 4)) hasSMIL = true; + else if (5 < namelength && 0 == ustrncasecmp(bytes + i + offset + namelength - 5, ".smil", 5)) hasSMIL = true; + else if (7 < namelength && 0 == ustrncasecmp(bytes + i + offset, "xl/", 3) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; + else if (8 < namelength && 0 == ustrncasecmp(bytes + i + offset, "ppt/", 4) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; + else if (9 < namelength && 0 == ustrncasecmp(bytes + i + offset, "word/", 5) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasWordDocument = true; + else if (10 < namelength && 0 == ustrncasecmp(bytes + i + offset, "excel/", 6) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; + else if (15 < namelength && 0 == ustrncasecmp(bytes + i + offset, "powerpoint/", 11) && 0 == ustrncasecmp(bytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; + i += offset + namelength - 1; + } + } + } + } + if (!foundMimetype) { + if (fileLength >= ZIP_BYTES_TO_READ) { + if (fd >= 0 && lseek(fd, fileLength - ZIP_BYTES_TO_READ, SEEK_SET) == fileLength - ZIP_BYTES_TO_READ) { + buffer = (unsigned char *)malloc(ZIP_BYTES_TO_READ); + if (buffer && read(fd, buffer, ZIP_BYTES_TO_READ) >= ZIP_BYTES_TO_READ) moreBytes = buffer; + } else if (bytes && length >= ZIP_BYTES_TO_READ) { + moreBytes = bytes + length - ZIP_BYTES_TO_READ; + } + } + if (moreBytes) { + for (i = 0; i + 30 < ZIP_BYTES_TO_READ; i++) { + if (0x50 == moreBytes[i] && 0x4b == moreBytes[i + 1]) { + unsigned namelength = 0, offset = 0; + if (0x01 == moreBytes[i + 2] && 0x02 == moreBytes[i + 3]) { + namelength = CFSwapInt16HostToLittle(*((UInt16 *)(moreBytes + i + 28))); + offset = 46; + } else if (0x03 == moreBytes[i + 2] && 0x04 == moreBytes[i + 3]) { + namelength = CFSwapInt16HostToLittle(*((UInt16 *)(moreBytes + i + 26))); + offset = 30; + } + if (offset > 0 && i + offset + namelength <= ZIP_BYTES_TO_READ) { + //printf("%.*s\n", namelength, moreBytes + i + offset); + if (9 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "META-INF/", 9)) hasMetaInf = true; + else if (11 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "content.xml", 11)) hasContentXML = true; + else if (11 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "_rels/.rels", 11)) hasRels = true; + else if (19 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "[Content_Types].xml", 19)) hasContentTypes = true; + else if (20 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "META-INF/MANIFEST.MF", 20)) hasManifestMF = true; + else if (21 == namelength && 0 == ustrncasecmp(moreBytes + i + offset, "META-INF/manifest.xml", 21)) hasManifestXML = true; + else if (4 < namelength && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".opf", 4)) hasOPF = true; + else if (4 < namelength && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".sml", 4)) hasSMIL = true; + else if (5 < namelength && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 5, ".smil", 5)) hasSMIL = true; + else if (7 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "xl/", 3) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; + else if (8 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "ppt/", 4) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; + else if (9 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "word/", 5) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasWordDocument = true; + else if (10 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "excel/", 6) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasExcelDocument = true; + else if (15 < namelength && 0 == ustrncasecmp(moreBytes + i + offset, "powerpoint/", 11) && 0 == ustrncasecmp(moreBytes + i + offset + namelength - 4, ".xml", 4)) hasPowerPointDocument = true; + i += offset + namelength - 1; + } + } + } + } + //printf("hasManifestMF %d hasManifestXML %d hasContentXML %d hasRels %d hasContentTypes %d hasWordDocument %d hasExcelDocument %d hasPowerPointDocument %d hasMetaInf %d hasOPF %d hasSMIL %d\n", hasManifestMF, hasManifestXML, hasContentXML, hasRels, hasContentTypes, hasWordDocument, hasExcelDocument, hasPowerPointDocument, hasMetaInf, hasOPF, hasSMIL); + if (hasManifestMF) ext = "jar"; + else if ((hasRels || hasContentTypes) && hasWordDocument) ext = "docx"; + else if ((hasRels || hasContentTypes) && hasExcelDocument) ext = "xlsx"; + else if ((hasRels || hasContentTypes) && hasPowerPointDocument) ext = "pptx"; + else if (hasManifestXML || hasContentXML) ext = "odt"; + else if (hasMetaInf) ext = "jar"; + else if (hasOPF && hasSMIL) ext = "dtb"; + else if (hasOPF) ext = "oeb"; + + if (buffer) free(buffer); + } + return ext; +} + +static Boolean _CFBundleCheckOLEName(const char *name, const char *bytes, unsigned length) { + Boolean retval = true; + unsigned j; + for (j = 0; retval && j < length; j++) if (bytes[2 * j] != name[j]) retval = false; + return retval; +} + +static const char *_CFBundleGrokFileTypeForOLEFile(int fd, const void *bytes, CFIndex length, off_t offset) { + const char *ext = "ole", *moreBytes = NULL; + char *buffer = NULL; + + if (fd >= 0 && lseek(fd, offset, SEEK_SET) == (off_t)offset) { + buffer = (char *)malloc(OLE_BYTES_TO_READ); + if (buffer && read(fd, buffer, OLE_BYTES_TO_READ) >= OLE_BYTES_TO_READ) moreBytes = buffer; + } else if (bytes && length >= offset + OLE_BYTES_TO_READ) { + moreBytes = (char *)bytes + offset; + } + if (moreBytes) { + Boolean foundit = false; + unsigned i; + for (i = 0; !foundit && i < 4; i++) { + char namelength = moreBytes[128 * i + 64] / 2; + foundit = true; + if (sizeof(XLS_NAME) == namelength && _CFBundleCheckOLEName(XLS_NAME, moreBytes + 128 * i, namelength - 1)) ext = "xls"; + else if (sizeof(XLS_NAME2) == namelength && _CFBundleCheckOLEName(XLS_NAME2, moreBytes + 128 * i, namelength - 1)) ext = "xls"; + else if (sizeof(DOC_NAME) == namelength && _CFBundleCheckOLEName(DOC_NAME, moreBytes + 128 * i, namelength - 1)) ext = "doc"; + else if (sizeof(PPT_NAME) == namelength && _CFBundleCheckOLEName(PPT_NAME, moreBytes + 128 * i, namelength - 1)) ext = "ppt"; + else foundit = false; + } + } + if (buffer) free(buffer); + return ext; +} + +static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *extension, UInt32 *machtype, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) { + int fd = -1; + const unsigned char *bytes = NULL; + unsigned char buffer[MAGIC_BYTES_TO_READ]; + CFIndex i, length = 0; + off_t fileLength = 0; + const char *ext = NULL; + UInt32 mt = UNKNOWN_FILETYPE; +#if defined(BINARY_SUPPORT_DYLD) + Boolean isX11 = false; +#endif /* BINARY_SUPPORT_DYLD */ + Boolean isFile = false, isPlain = true, isZero = true, isSpace = true, hasBOM = false; + // extensions returned: o, tool, x11app, pef, core, dylib, bundle, elf, jpeg, jp2, tiff, gif, png, pict, icns, ico, rtf, rtfd, pdf, ra, rm, au, aiff, aifc, caf, wav, avi, wmv, ogg, flac, psd, mpeg, mid, zip, jar, sit, cpio, html, ps, mov, qtif, ttf, otf, sfont, bmp, hqx, bin, class, tar, txt, gz, Z, uu, ync, bz, bz2, sh, pl, py, rb, dvi, sgi, tga, mp3, xml, plist, xls, doc, ppt, mp4, m4a, m4b, m4p, m4v, 3gp, 3g2, dmg, cwk, webarchive, dwg, dgn, pfa, pfb, afm, tfm, xcf, cpx, dwf, swf, swc, abw, bom, lit, svg, rdf, x3d, oeb, dtb, docx, xlsx, pptx, sxc, sxd, sxg, sxi, sxm, sxw, odc, odf, odg, oth, odi, odm, odp, ods, cin, exr + // ??? we do not distinguish between different wm types, returning wmv for any of wmv, wma, or asf + // ??? we do not distinguish between ordinary documents and template versions (often there is no difference in file contents) + // ??? the distinctions between docx, xlsx, and pptx may not be entirely reliable + if (architectures) *architectures = NULL; + if (infodict) *infodict = NULL; + if (hasObjc) *hasObjc = false; + if (objcVersion) *objcVersion = 0; + if (objcFlags) *objcFlags = 0; + if (url) { + Boolean gotPath = FALSE; + char path[CFMaxPathSize]; + gotPath = CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize); + struct statinfo statBuf; + if (gotPath && stat(path, &statBuf) == 0 && (statBuf.st_mode & S_IFMT) == S_IFREG && (fd = open(path, O_RDONLY | CF_OPENFLGS, 0777)) >= 0) { + length = read(fd, buffer, MAGIC_BYTES_TO_READ); + fileLength = statBuf.st_size; + bytes = buffer; + isFile = true; + } + } + if (!isFile && data) { + length = CFDataGetLength(data); + fileLength = (off_t)length; + bytes = CFDataGetBytePtr(data); + if (length == 0) ext = "txt"; + } + if (bytes) { + if (length >= 4) { + UInt32 magic = CFSwapInt32HostToBig(*((UInt32 *)bytes)); + for (i = 0; !ext && i < NUM_EXTENSIONS; i++) { + if (__CFBundleMagicNumbersArray[i] == magic) ext = __CFBundleExtensionsArray + i * EXTENSION_LENGTH; + } + if (ext) { + if (0xcafebabe == magic && 8 <= length && 0 != *((UInt16 *)(bytes + 4))) ext = "class"; +#if defined(BINARY_SUPPORT_DYLD) + else if ((int)sizeof(struct mach_header_64) <= length) mt = _CFBundleGrokMachType(fd, bytes, length, extension ? &isX11 : NULL, architectures, infodict, hasObjc, objcVersion, objcFlags); + + if (MH_OBJECT == mt) ext = "o"; + else if (MH_EXECUTE == mt) ext = isX11 ? "x11app" : "tool"; + else if (PEF_FILETYPE == mt) ext = "pef"; + else if (MH_CORE == mt) ext = "core"; + else if (MH_DYLIB == mt) ext = "dylib"; + else if (MH_BUNDLE == mt) ext = "bundle"; +#endif /* BINARY_SUPPORT_DYLD */ + else if (0x7b5c7274 == magic && (6 > length || 'f' != bytes[4])) ext = NULL; + else if (0x25504446 == magic && (6 > length || '-' != bytes[4])) ext = NULL; + else if (0x00010000 == magic && (6 > length || 0 != bytes[4])) ext = NULL; + else if (0x47494638 == magic && (6 > length || (0x3761 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))) && 0x3961 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4)))))) ext = NULL; + else if (0x0000000c == magic && (6 > length || 0x6a50 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL; + else if (0x2356524d == magic && (6 > length || 0x4c20 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL; + else if (0x28445746 == magic && (6 > length || 0x2056 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL; + else if (0x30373037 == magic && (6 > length || 0x30 != bytes[4] || !isdigit(bytes[5]))) ext = NULL; + else if (0x41433130 == magic && (6 > length || 0x31 != bytes[4] || !isdigit(bytes[5]))) ext = NULL; + else if (0x89504e47 == magic && (8 > length || 0x0d0a1a0a != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x53747566 == magic && (8 > length || 0x66497420 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x3026b275 == magic && (8 > length || 0x8e66cf11 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x67696d70 == magic && (8 > length || 0x20786366 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x424f4d53 == magic && (8 > length || 0x746f7265 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x49544f4c == magic && (8 > length || 0x49544c53 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x72746664 == magic && (8 > length || 0x00000000 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL; + else if (0x3d796265 == magic && (12 > length || 0x67696e20 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || (0x6c696e65 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))) && 0x70617274 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))))) ext = NULL; + else if (0x63616666 == magic && (12 > length || 0 != bytes[4] || 0x64657363 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))))) ext = NULL; + else if (0x504b0304 == magic) ext = _CFBundleGrokFileTypeForZipFile(fd, bytes, length, fileLength); + else if (0x25215053 == magic) { + if (11 <= length && 0 == ustrncmp(bytes + 4, "-Adobe-", 7)) ext = "ps"; + else if (14 <= length && 0 == ustrncmp(bytes + 4, "-AdobeFont", 10)) ext = "pfa"; + else ext = NULL; + } else if (0x464f524d == magic) { + // IFF + ext = NULL; + if (12 <= length) { + UInt32 iffMagic = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))); + if (0x41494646 == iffMagic) ext = "aiff"; + else if (0x414946 == iffMagic) ext = "aifc"; + } + } else if (0x52494646 == magic) { + // RIFF + ext = NULL; + if (12 <= length) { + UInt32 riffMagic = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))); + if (0x57415645 == riffMagic) ext = "wav"; + else if (0x41564920 == riffMagic) ext = "avi"; + } + } else if (0xd0cf11e0 == magic) { + // OLE + if (52 <= length) ext = _CFBundleGrokFileTypeForOLEFile(fd, bytes, length, 512 * (1 + CFSwapInt32HostToLittle(*((UInt32 *)(bytes + 48))))); + } else if (0x62656769 == magic) { + // uu + ext = NULL; + if (76 <= length && 'n' == bytes[4] && ' ' == bytes[5] && isdigit(bytes[6]) && isdigit(bytes[7]) && isdigit(bytes[8]) && ' ' == bytes[9]) { + CFIndex endOfLine = 0; + for (i = 10; 0 == endOfLine && i < length; i++) if ('\n' == bytes[i]) endOfLine = i; + if (10 <= endOfLine && endOfLine + 62 < length && 'M' == bytes[endOfLine + 1] && '\n' == bytes[endOfLine + 62]) { + ext = "uu"; + for (i = endOfLine + 1; ext && i < endOfLine + 62; i++) if (!isprint(bytes[i])) ext = NULL; + } + } + } + } + if (extension && !ext) { + UInt16 shortMagic = CFSwapInt16HostToBig(*((UInt16 *)bytes)); + if (5 <= length && 0 == bytes[3] && 0 == bytes[4] && ((1 == bytes[1] && 1 == (0xf7 & bytes[2])) || (0 == bytes[1] && (2 == (0xf7 & bytes[2]) || (3 == (0xf7 & bytes[2])))))) ext = "tga"; + else if (8 <= length && (0x6d6f6f76 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x6d646174 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x77696465 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "mov"; + else if (8 <= length && (0x69647363 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x69646174 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "qtif"; + else if (8 <= length && 0x424f424f == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4)))) ext = "cwk"; + else if (8 <= length && 0x62706c69 == magic && 0x7374 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))) && isdigit(bytes[6]) && isdigit(bytes[7])) { + for (i = 8; !ext && i < 128 && i + 16 <= length; i++) { + if (0 == ustrncmp(bytes + i, "WebMainResource", 15)) ext = "webarchive"; + } + if (!ext) ext = "plist"; + } else if (0 == shortMagic && 12 <= length && 0x66747970 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4)))) { + // ??? may want more ftyp values + UInt32 ftyp = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))); + if (0x6d703431 == ftyp || 0x6d703432 == ftyp || 0x69736f6d == ftyp || 0x69736f32 == ftyp) ext = "mp4"; + else if (0x4d344120 == ftyp) ext = "m4a"; + else if (0x4d344220 == ftyp) ext = "m4b"; + else if (0x4d345020 == ftyp) ext = "m4p"; + else if (0x4d345620 == ftyp || 0x4d345648 == ftyp || 0x4d345650 == ftyp) ext = "m4v"; + else if (0x3367 == (ftyp >> 16)) { + UInt16 remainder = (ftyp & 0xffff); + if (0x6536 == remainder || 0x6537 == remainder || 0x6736 == remainder || 0x7034 == remainder || 0x7035 == remainder || 0x7036 == remainder || 0x7236 == remainder || 0x7336 == remainder || 0x7337 == remainder) ext = "3gp"; + else if (0x3261 == remainder) ext = "3g2"; + } + } else if (0x424d == shortMagic && 18 <= length) { + UInt32 btyp = CFSwapInt32HostToLittle(*((UInt32 *)(bytes + 14))); + if (40 == btyp || btyp == 12 || btyp == 64 || btyp == 108 || btyp == 124) ext = "bmp"; + } else if (20 <= length && 0 == ustrncmp(bytes + 6, "%!PS-AdobeFont", 14)) ext = "pfb"; + else if (40 <= length && 0x42696e48 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 34))) && 0x6578 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 38)))) ext = "hqx"; + else if (128 <= length && 0x6d42494e == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 102)))) ext = "bin"; + else if (128 <= length && 0 == bytes[0] && 0 < bytes[1] && bytes[1] < 64 && 0 == bytes[74] && 0 == bytes[82] && 0 == (fileLength % 128)) { + UInt32 df = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 83))), rf = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 87))), blocks = 1 + (df + 127) / 128 + (rf + 127) / 128; + if (df < 0x00800000 && rf < 0x00800000 && 1 < blocks && (off_t)(128 * blocks) == fileLength) ext = "bin"; + } else if (265 <= length && 0x75737461 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 257))) && (0x72202000 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 261))) || 0x7200 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 261))))) ext = "tar"; + else if (0xfeff == shortMagic || 0xfffe == shortMagic) { + ext = "txt"; + if (12 <= length && ((0x3cfeff == *((UInt32 *)bytes) && 0x740068 == *((UInt32 *)(bytes + 4)) && 0x6c006d == *((UInt32 *)(bytes + 8))) || (0xfffe3c00 == *((UInt32 *)bytes) && 0x68007400 == *((UInt32 *)(bytes + 4)) && 0x6d006c00 == *((UInt32 *)(bytes + 8))))) ext = "html"; + } else if (0x1f9d == shortMagic) ext = "Z"; + else if (0x1f8b == shortMagic) ext = "gz"; + else if (0x71c7 == shortMagic || 0xc771 == shortMagic) ext = "cpio"; + else if (0xf702 == shortMagic) ext = "dvi"; + else if (0x01da == shortMagic && (0 == bytes[2] || 1 == bytes[2]) && (0 < bytes[3] && 16 > bytes[3])) ext = "sgi"; + else if (0x2321 == shortMagic) { + CFIndex endOfLine = 0, lastSlash = 0; + for (i = 2; 0 == endOfLine && i < length; i++) if ('\n' == bytes[i]) endOfLine = i; + if (endOfLine > 3) { + for (i = endOfLine - 1; 0 == lastSlash && i > 1; i--) if ('/' == bytes[i]) lastSlash = i; + if (lastSlash > 0) { + if (0 == ustrncmp(bytes + lastSlash + 1, "perl", 4)) ext = "pl"; + else if (0 == ustrncmp(bytes + lastSlash + 1, "python", 6)) ext = "py"; + else if (0 == ustrncmp(bytes + lastSlash + 1, "ruby", 4)) ext = "rb"; + else ext = "sh"; + } + } + } else if (0xffd8 == shortMagic && 0xff == bytes[2]) ext = "jpeg"; + else if (0x4657 == shortMagic && 0x53 == bytes[2]) ext = "swf"; + else if (0x4357 == shortMagic && 0x53 == bytes[2]) ext = "swc"; + else if (0x4944 == shortMagic && '3' == bytes[2] && 0x20 > bytes[3]) ext = "mp3"; + else if (0x425a == shortMagic && isdigit(bytes[2]) && isdigit(bytes[3])) ext = "bz"; + else if (0x425a == shortMagic && 'h' == bytes[2] && isdigit(bytes[3]) && 8 <= length && (0x31415926 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x17724538 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "bz2"; + else if (0x0011 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 2))) || 0x0012 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 2)))) ext = "tfm"; + } + } + if (extension && !ext) { + //??? what about MacOSRoman? + if (0xef == bytes[0] && 0xbb == bytes[1] && 0xbf == bytes[2]) { // UTF-8 BOM + hasBOM = true; + isZero = false; + } + for (i = (hasBOM ? 3 : 0); (isPlain || isZero) && !ext && i < length && i < 512; i++) { + char c = bytes[i]; + if (isPlain && '<' == c && i + 14 <= length && 0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) ext = "html"; + if (isSpace && '<' == c && i + 14 <= length) { + if (0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13) || 0 == ustrncasecmp(bytes + i + 1, "head", 4) || 0 == ustrncasecmp(bytes + i + 1, "title", 5) || 0 == ustrncasecmp(bytes + i + 1, "script", 6) || 0 == ustrncasecmp(bytes + i + 1, "html", 4)) { + ext = "html"; + } else if (0 == ustrncasecmp(bytes + i + 1, "?xml", 4)) { + for (i += 4; !ext && i < 128 && i + 20 <= length; i++) { + if ('<' == bytes[i]) { + if (0 == ustrncasecmp(bytes + i + 1, "abiword", 7)) ext = "abw"; + else if (0 == ustrncasecmp(bytes + i + 1, "!doctype svg", 12)) ext = "svg"; + else if (0 == ustrncasecmp(bytes + i + 1, "!doctype rdf", 12)) ext = "rdf"; + else if (0 == ustrncasecmp(bytes + i + 1, "!doctype x3d", 12)) ext = "x3d"; + else if (0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) ext = "html"; + else if (0 == ustrncasecmp(bytes + i + 1, "!doctype posingfont", 19)) ext = "sfont"; + else if (0 == ustrncasecmp(bytes + i + 1, "!doctype plist", 14)) { + for (i += 14; !ext && i < 256 && i + 16 <= length; i++) { + if (0 == ustrncmp(bytes + i, "WebMainResource", 15)) ext = "webarchive"; + } + if (!ext) ext = "plist"; + } + } + } + if (!ext) ext = "xml"; + } + } + if (0 != c) isZero = false; + if (isZero || 0x7f <= c || (0x20 > c && !isspace(c))) isPlain = false; + if (isZero || !isspace(c)) isSpace = false; + } + if (!ext) { + if (isPlain) { + if (16 <= length && 0 == ustrncmp(bytes, "StartFontMetrics", 16)) ext = "afm"; + else ext = "txt"; + } else if (isZero && length >= MAGIC_BYTES_TO_READ && fileLength >= 526) { + if (isFile) { + if (lseek(fd, 512, SEEK_SET) == 512 && read(fd, buffer, MAGIC_BYTES_TO_READ) >= 14) { + if (0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(buffer + 10)))) ext = "pict"; + } + } else { + if (526 <= length && 0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 522)))) ext = "pict"; + } + } + } + } + if (extension && (!ext || 0 == strcmp(ext, "bz2")) && length >= MAGIC_BYTES_TO_READ && fileLength >= DMG_BYTES_TO_READ) { + if (isFile) { + if (lseek(fd, fileLength - DMG_BYTES_TO_READ, SEEK_SET) == fileLength - DMG_BYTES_TO_READ && read(fd, buffer, DMG_BYTES_TO_READ) >= DMG_BYTES_TO_READ) { + if (0x6b6f6c79 == CFSwapInt32HostToBig(*((UInt32 *)buffer)) || (0x63647361 == CFSwapInt32HostToBig(*((UInt32 *)(buffer + DMG_BYTES_TO_READ - 8))) && 0x656e6372 == CFSwapInt32HostToBig(*((UInt32 *)(buffer + DMG_BYTES_TO_READ - 4))))) ext = "dmg"; + } + } else { + if (DMG_BYTES_TO_READ <= length && (0x6b6f6c79 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + length - DMG_BYTES_TO_READ))) || (0x63647361 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + length - 8))) && 0x656e6372 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + length - 4)))))) ext = "dmg"; + } + } + } + if (extension) *extension = ext ? CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, ext, kCFStringEncodingUTF8, kCFAllocatorNull) : NULL; + if (machtype) *machtype = mt; + if (fd >= 0) close(fd); + return (ext ? true : false); +} + +CFStringRef _CFBundleCopyFileTypeForFileURL(CFURLRef url) { + CFStringRef extension = NULL; + (void)_CFBundleGrokFileType(url, NULL, &extension, NULL, NULL, NULL, NULL, NULL, NULL); + return extension; +} + +CFStringRef _CFBundleCopyFileTypeForFileData(CFDataRef data) { + CFStringRef extension = NULL; + (void)_CFBundleGrokFileType(NULL, data, &extension, NULL, NULL, NULL, NULL, NULL, NULL); + return extension; +} + +CF_PRIVATE CFDictionaryRef _CFBundleCopyInfoDictionaryInExecutable(CFURLRef url) { + CFDictionaryRef result = NULL; + (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, NULL, &result, NULL, NULL, NULL); + return result; +} + +CF_PRIVATE CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef url) { + CFArrayRef result = NULL; + (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, &result, NULL, NULL, NULL, NULL); + return result; +} + +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED +static Boolean _CFBundleGetObjCImageInfoForExecutable(CFURLRef url, uint32_t *objcVersion, uint32_t *objcFlags) { + Boolean retval = false; + (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, NULL, NULL, &retval, objcVersion, objcFlags); + return retval; +} + +CF_PRIVATE Boolean _CFBundleGetObjCImageInfo(CFBundleRef bundle, uint32_t *objcVersion, uint32_t *objcFlags) { + Boolean retval = false; + uint32_t localVersion = 0, localFlags = 0; + CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + if (executableURL) { + retval = _CFBundleGetObjCImageInfoForExecutable(executableURL, &localVersion, &localFlags); + CFRelease(executableURL); + } + if (objcVersion) *objcVersion = localVersion; + if (objcFlags) *objcFlags = localFlags; + return retval; +} +#endif + +#if defined(BINARY_SUPPORT_DYLD) + +CF_PRIVATE __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableURL) { + // Attempt to grok the type of the binary by looking for DYLD magic numbers. If one of the DYLD magic numbers is found, find out what type of Mach-o file it is. Otherwise, look for the PEF magic numbers to see if it is CFM. + __CFPBinaryType result = executableURL ? __CFBundleUnreadableBinary : __CFBundleNoBinary; + UInt32 machtype = UNKNOWN_FILETYPE; + if (_CFBundleGrokFileType(executableURL, NULL, NULL, &machtype, NULL, NULL, NULL, NULL, NULL)) { + switch (machtype) { + case MH_EXECUTE: + result = __CFBundleDYLDExecutableBinary; + break; + case MH_BUNDLE: + result = __CFBundleDYLDBundleBinary; + break; + case MH_DYLIB: + result = __CFBundleDYLDFrameworkBinary; + break; + case PEF_FILETYPE: + result = __CFBundleCFMBinary; + break; + } + } + return result; +} + +#endif /* BINARY_SUPPORT_DYLD */ + diff --git a/CFBundle_InfoPlist.c b/CFBundle_InfoPlist.c index 6e48d72..510a73f 100644 --- a/CFBundle_InfoPlist.c +++ b/CFBundle_InfoPlist.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -38,6 +38,7 @@ #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_EMBEDDED_MINI #include #include +#include #endif // The following strings are initialized 'later' (i.e., not at static initialization time) because static init time is too early for CFSTR to work, on platforms without constant CF strings @@ -364,7 +365,10 @@ static CFArrayRef _CopySortedOverridesForBaseKey(CFStringRef keyName, CFDictiona return overrides; } -CF_PRIVATE void _CFBundleInfoPlistProcessInfoDictionary(CFMutableDictionaryRef dict) { +CF_PRIVATE void _CFBundleInfoPlistProcessInfoDictionary(CFMutableDictionaryRef dict) { + // Defensive programming + if (!dict) return; + CFIndex count = CFDictionaryGetCount(dict); if (count > 0) { @@ -736,14 +740,14 @@ static void _CFBundleInfoPlistFixupInfoDictionary(CFBundleRef bundle, CFMutableD } CFDictionaryRef CFBundleGetInfoDictionary(CFBundleRef bundle) { - __CFSpinLock(&bundle->_lock); + __CFLock(&bundle->_lock); if (!bundle->_infoDict) { bundle->_infoDict = _CFBundleCopyInfoDictionaryInDirectoryWithVersion(kCFAllocatorSystemDefault, bundle->_url, bundle->_version); // Add or fixup any keys that will be expected later if (bundle->_infoDict) _CFBundleInfoPlistFixupInfoDictionary(bundle, (CFMutableDictionaryRef)bundle->_infoDict); } - __CFSpinUnlock(&bundle->_lock); + __CFUnlock(&bundle->_lock); return bundle->_infoDict; } @@ -754,11 +758,11 @@ CFDictionaryRef _CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { CFDictionaryRef localInfoDict = NULL; - __CFSpinLock(&bundle->_lock); + __CFLock(&bundle->_lock); localInfoDict = bundle->_localInfoDict; if (!localInfoDict) { // To avoid keeping the spin lock for too long, let go of it here while we create a new dictionary. We'll relock later to set the value. If it turns out that we have already created another local info dictionary in the meantime, then we'll take care of it then. - __CFSpinUnlock(&bundle->_lock); + __CFUnlock(&bundle->_lock); CFURLRef url = CFBundleCopyResourceURL(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL); if (url) { CFDataRef data; @@ -781,7 +785,7 @@ CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { } if (localInfoDict) _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)localInfoDict); // remain locked here until we exit the if statement. - __CFSpinLock(&bundle->_lock); + __CFLock(&bundle->_lock); if (!bundle->_localInfoDict) { // Still have no info dictionary, so set it bundle->_localInfoDict = localInfoDict; @@ -791,7 +795,7 @@ CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { localInfoDict = bundle->_localInfoDict; } } - __CFSpinUnlock(&bundle->_lock); + __CFUnlock(&bundle->_lock); return localInfoDict; } @@ -820,3 +824,111 @@ CFStringRef CFBundleGetIdentifier(CFBundleRef bundle) { if (infoDict) bundleID = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleIdentifierKey); return bundleID; } + + +static void __addPlatformAndProductNamesToKeys(const void *value, void *context) { + CFMutableSetRef newKeys = (CFMutableSetRef)context; + CFStringRef key = (CFStringRef)value; + CFStringRef firstPartOfKey = NULL; + CFStringRef restOfKey = NULL; + + // Find the first ':' + CFRange range; + Boolean success = CFStringFindWithOptions(key, CFSTR(":"), CFRangeMake(0, CFStringGetLength(key)), 0, &range); + if (success) { + firstPartOfKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, key, CFRangeMake(0, range.location)); + restOfKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, key, CFRangeMake(range.location + 1, CFStringGetLength(key) - range.location - 1)); + } else { + firstPartOfKey = (CFStringRef)CFRetain(key); + } + + // only apply product and platform to top-level key + CFStringRef newKeyWithPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@%@%@"), firstPartOfKey, _CFGetPlatformName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR("")); + CFStringRef newKeyWithProduct = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@~%@%@%@"), firstPartOfKey, _CFGetProductName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR("")); + CFStringRef newKeyWithProductAndPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@~%@%@%@"), firstPartOfKey, _CFGetPlatformName(), _CFGetProductName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR("")); + + CFSetAddValue(newKeys, key); + CFSetAddValue(newKeys, newKeyWithPlatform); + CFSetAddValue(newKeys, newKeyWithProduct); + CFSetAddValue(newKeys, newKeyWithProductAndPlatform); + + if (firstPartOfKey) CFRelease(firstPartOfKey); + if (restOfKey) CFRelease(restOfKey); + CFRelease(newKeyWithPlatform); + CFRelease(newKeyWithProduct); + CFRelease(newKeyWithProductAndPlatform); +} + +// from CFUtilities.c +CF_PRIVATE Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, Boolean uncached, void **outBytes, CFIndex *outLength, CFErrorRef *errorPtr); + +// implementation of below functions - takes URL as parameter +static CFPropertyListRef _CFBundleCreateFilteredInfoPlistWithURL(CFURLRef infoPlistURL, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) { + CFPropertyListRef result = NULL; + + if (!infoPlistURL) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFURLRef absoluteURL = CFURLCopyAbsoluteURL(infoPlistURL); + CFStringRef filePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); + CFRelease(absoluteURL); + + if (!filePath) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + void *bytes = NULL; + CFIndex length = 0; +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + Boolean mapped = options & _CFBundleFilteredPlistMemoryMapped ? true : false; +#else + Boolean mapped = false; +#endif + Boolean success = _CFReadMappedFromFile(filePath, mapped, false, &bytes, &length, NULL); + CFRelease(filePath); + if (!success) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFDataRef infoPlistData = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)bytes, length, kCFAllocatorNull); + // We need to include all possible variants of the platform/product combo as possible keys. + CFMutableSetRef newKeyPaths = CFSetCreateMutable(kCFAllocatorSystemDefault, CFSetGetCount(keyPaths), &kCFTypeSetCallBacks); + CFSetApplyFunction(keyPaths, __addPlatformAndProductNamesToKeys, newKeyPaths); + + success = _CFPropertyListCreateFiltered(kCFAllocatorSystemDefault, infoPlistData, kCFPropertyListMutableContainers, newKeyPaths, &result, NULL); + + if (!success || !result) { + result = CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } else { + _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); + } + + CFRelease(newKeyPaths); + CFRelease(infoPlistData); + if (mapped) { +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + munmap(bytes, length); +#endif + } else { + free(bytes); + } + + return result; +} + +// Returns a subset of the bundle's property list, only including the keyPaths in the CFSet. If the top level object is not a dictionary, you will get back an empty dictionary as the result. If the Info.plist does not exist or could not be parsed, you will get back an empty dictionary. +CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) { + CFURLRef infoPlistURL = _CFBundleCopyInfoPlistURL(bundle); + CFPropertyListRef result = _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL, keyPaths, options); + if (infoPlistURL) CFRelease(infoPlistURL); + return result; +} + +CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredLocalizedInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, CFStringRef localizationName, _CFBundleFilteredPlistOptions options) { + CFURLRef infoPlistURL = CFBundleCopyResourceURLForLocalization(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL, localizationName); + CFPropertyListRef result = _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL, keyPaths, options); + if (infoPlistURL) CFRelease(infoPlistURL); + return result; +} + +CF_EXPORT CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle) { + CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); + CFURLRef url = (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleInfoPlistURLKey); + if (!url) url = (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleRawInfoPlistURLKey); + return (url ? (CFURLRef)CFRetain(url) : NULL); +} diff --git a/CFBundle_Internal.h b/CFBundle_Internal.h index 9f2f7a8..d9d66b8 100644 --- a/CFBundle_Internal.h +++ b/CFBundle_Internal.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBundle_Internal.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLE_INTERNAL__) @@ -35,6 +35,7 @@ #include "CFInternal.h" #include "CFPlugIn_Factory.h" #include "CFBundle_BinaryTypes.h" +#include "CFByteOrder.h" CF_EXTERN_C_BEGIN @@ -54,17 +55,19 @@ CF_EXTERN_C_BEGIN #define CFBundleExecutableLoadError 3587 #define CFBundleExecutableLinkError 3588 +CF_INLINE uint32_t _CFBundleSwapInt32Conditional(uint32_t arg, Boolean swap) {return swap ? CFSwapInt32(arg) : arg;} +CF_INLINE uint32_t _CFBundleSwapInt64Conditional(uint64_t arg, Boolean swap) {return swap ? CFSwapInt64(arg) : arg;} + // uncomment this to enable the checking for 8302591 //#define CFBUNDLE_NO_TRAVERSE_OUTSIDE typedef struct __CFResourceData { - CFMutableDictionaryRef _stringTableCache; Boolean _executableLacksResourceFork; Boolean _infoDictionaryFromResourceFork; char _padding[2]; } _CFResourceData; -extern _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle); +CF_PRIVATE _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle); typedef struct __CFPlugInData { Boolean _isPlugIn; @@ -113,16 +116,18 @@ struct __CFBundle { CFStringRef _executablePath; // Calculated and cached here CFStringRef _developmentRegion; // Calculated and cached here - Boolean _developmentRegionCalculated; + dispatch_once_t _developmentRegionCalculated; - CFSpinLock_t _lock; + CFLock_t _lock; CFArrayRef _localizations; // List of localizations, including the development language fallback if required Boolean _lookedForLocalizations; CFMutableDictionaryRef _resourceDirectoryContents; - CFSpinLock_t _queryLock; + CFMutableDictionaryRef _stringTable; + + CFLock_t _queryLock; CFMutableDictionaryRef _queryTable; CFStringRef _bundleBasePath; @@ -136,6 +141,8 @@ extern _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle); /* Private CFBundle API */ +CF_PRIVATE CFErrorRef _CFBundleCreateErrorDebug(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code, CFStringRef debugString); + CF_PRIVATE void _CFBundleInfoPlistProcessInfoDictionary(CFMutableDictionaryRef dict); CF_PRIVATE Boolean _CFBundleSupportedProductName(CFStringRef fileName, CFRange searchRange); CF_PRIVATE Boolean _CFBundleSupportedPlatformName(CFStringRef fileName, CFRange searchRange); @@ -144,6 +151,27 @@ CF_EXPORT CFStringRef _CFGetProductName(void); CF_EXPORT CFStringRef _CFGetPlatformName(void); CF_EXPORT CFStringRef _CFGetAlternatePlatformName(void); +CF_PRIVATE void _CFBundleFlushQueryTableCache(CFBundleRef bundle); + +CF_PRIVATE SInt32 _CFBundleCurrentArchitecture(void); +CF_PRIVATE Boolean _CFBundleGetObjCImageInfo(CFBundleRef bundle, uint32_t *objcVersion, uint32_t *objcFlags); + +#if defined(BINARY_SUPPORT_DYLD) +CF_PRIVATE CFMutableDictionaryRef _CFBundleCreateInfoDictFromMainExecutable(); +CF_PRIVATE Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags); +#endif + +CF_PRIVATE CFStringRef _CFBundleCopyLoadedImagePathForPointer(void *p); + +// Languages and locales + +CF_PRIVATE CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFURLRef url, uint8_t *version); +CF_PRIVATE CFArrayRef _CFBundleCopyLanguageSearchListInBundle(CFBundleRef bundle); + +CF_PRIVATE Boolean CFBundleAllowMixedLocalizations(void); + +// Misc + extern Boolean _CFIsResourceAtURL(CFURLRef url, Boolean *isDir); extern Boolean _CFIsResourceAtPath(CFStringRef path, Boolean *isDir); diff --git a/CFBundle_Locale.c b/CFBundle_Locale.c new file mode 100644 index 0000000..54fe30e --- /dev/null +++ b/CFBundle_Locale.c @@ -0,0 +1,979 @@ +/* + * Copyright (c) 2014 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* CFBundle_Locale.c + Copyright (c) 1999-2014, Apple Inc. All rights reserved. + Responsibility: Tony Parker +*/ + +#include "CFBundle_Internal.h" + +#include + +#include +#include + +static CFStringRef _CFBundleCopyLanguageFoundInLocalizations(CFArrayRef localizations, CFStringRef language); + +#pragma mark - +#pragma mark Mixed Localizations + +// This helper function checks for various permutations of the ways people put boolean values in Info.plist dictionaries +static Boolean _CFBundleGetInfoDictionaryBoolean(CFStringRef key) { + Boolean result = false; + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFDictionaryRef infoDict = mainBundle ? CFBundleGetInfoDictionary(mainBundle) : NULL; + CFTypeRef infoDictValue = infoDict ? CFDictionaryGetValue(infoDict, key) : NULL; + if (infoDictValue) { + CFTypeID typeID = CFGetTypeID(infoDictValue); + if (typeID == CFBooleanGetTypeID()) { + result = CFBooleanGetValue((CFBooleanRef)infoDictValue); + } else if (typeID == CFStringGetTypeID()) { + result = (CFStringCompare((CFStringRef)infoDictValue, CFSTR("true"), kCFCompareCaseInsensitive) == kCFCompareEqualTo || CFStringCompare((CFStringRef)infoDictValue, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo); + } else if (typeID == CFNumberGetTypeID()) { + SInt32 val = 0; + if (CFNumberGetValue((CFNumberRef)infoDictValue, kCFNumberSInt32Type, &val)) result = (val != 0); + } + } + return result; +} + +CF_PRIVATE Boolean CFBundleAllowMixedLocalizations(void) { + static Boolean allowMixed = false; + static dispatch_once_t once = 0; + dispatch_once(&once, ^{ + allowMixed = _CFBundleGetInfoDictionaryBoolean(_kCFBundleAllowMixedLocalizationsKey); + }); + return allowMixed; +} + +static Boolean CFBundleFollowParentLocalization(void) { + static Boolean followParent = false; + static dispatch_once_t once = 0; + dispatch_once(&once, ^{ + followParent = _CFBundleGetInfoDictionaryBoolean(CFSTR("CFBundleFollowParentLocalization")); + }); + return followParent; + +} + +#pragma mark - +#pragma mark Language and Locale Codes + +// string, with groups of 6 characters being 1 element in the array of locale abbreviations +const char * __CFBundleLocaleAbbreviationsArray = + "en_US\0" "fr_FR\0" "en_GB\0" "de_DE\0" "it_IT\0" "nl_NL\0" "nl_BE\0" "sv_SE\0" + "es_ES\0" "da_DK\0" "pt_PT\0" "fr_CA\0" "nb_NO\0" "he_IL\0" "ja_JP\0" "en_AU\0" + "ar\0\0\0\0" "fi_FI\0" "fr_CH\0" "de_CH\0" "el_GR\0" "is_IS\0" "mt_MT\0" "el_CY\0" + "tr_TR\0" "hr_HR\0" "nl_NL\0" "nl_BE\0" "en_CA\0" "en_CA\0" "pt_PT\0" "nb_NO\0" + "da_DK\0" "hi_IN\0" "ur_PK\0" "tr_TR\0" "it_CH\0" "en\0\0\0\0" "\0\0\0\0\0\0" "ro_RO\0" + "grc\0\0\0" "lt_LT\0" "pl_PL\0" "hu_HU\0" "et_EE\0" "lv_LV\0" "se\0\0\0\0" "fo_FO\0" + "fa_IR\0" "ru_RU\0" "ga_IE\0" "ko_KR\0" "zh_CN\0" "zh_TW\0" "th_TH\0" "\0\0\0\0\0\0" + "cs_CZ\0" "sk_SK\0" "\0\0\0\0\0\0" "hu_HU\0" "bn\0\0\0\0" "be_BY\0" "uk_UA\0" "\0\0\0\0\0\0" + "el_GR\0" "sr_CS\0" "sl_SI\0" "mk_MK\0" "hr_HR\0" "\0\0\0\0\0\0" "de_DE\0" "pt_BR\0" + "bg_BG\0" "ca_ES\0" "\0\0\0\0\0\0" "gd\0\0\0\0" "gv\0\0\0\0" "br\0\0\0\0" "iu_CA\0" "cy\0\0\0\0" + "en_CA\0" "ga_IE\0" "en_CA\0" "dz_BT\0" "hy_AM\0" "ka_GE\0" "es_XL\0" "es_ES\0" + "to_TO\0" "pl_PL\0" "ca_ES\0" "fr\0\0\0\0" "de_AT\0" "es_XL\0" "gu_IN\0" "pa\0\0\0\0" + "ur_IN\0" "vi_VN\0" "fr_BE\0" "uz_UZ\0" "en_SG\0" "nn_NO\0" "af_ZA\0" "eo\0\0\0\0" + "mr_IN\0" "bo\0\0\0\0" "ne_NP\0" "kl\0\0\0\0" "en_IE\0"; + +#define NUM_LOCALE_ABBREVIATIONS 109 +#define LOCALE_ABBREVIATION_LENGTH 6 + +static const char * const __CFBundleLanguageNamesArray[] = { + "English", "French", "German", "Italian", "Dutch", "Swedish", "Spanish", "Danish", + "Portuguese", "Norwegian", "Hebrew", "Japanese", "Arabic", "Finnish", "Greek", "Icelandic", + "Maltese", "Turkish", "Croatian", "Chinese", "Urdu", "Hindi", "Thai", "Korean", + "Lithuanian", "Polish", "Hungarian", "Estonian", "Latvian", "Sami", "Faroese", "Farsi", + "Russian", "Chinese", "Dutch", "Irish", "Albanian", "Romanian", "Czech", "Slovak", + "Slovenian", "Yiddish", "Serbian", "Macedonian", "Bulgarian", "Ukrainian", "Byelorussian", "Uzbek", + "Kazakh", "Azerbaijani", "Azerbaijani", "Armenian", "Georgian", "Moldavian", "Kirghiz", "Tajiki", + "Turkmen", "Mongolian", "Mongolian", "Pashto", "Kurdish", "Kashmiri", "Sindhi", "Tibetan", + "Nepali", "Sanskrit", "Marathi", "Bengali", "Assamese", "Gujarati", "Punjabi", "Oriya", + "Malayalam", "Kannada", "Tamil", "Telugu", "Sinhalese", "Burmese", "Khmer", "Lao", + "Vietnamese", "Indonesian", "Tagalog", "Malay", "Malay", "Amharic", "Tigrinya", "Oromo", + "Somali", "Swahili", "Kinyarwanda", "Rundi", "Nyanja", "Malagasy", "Esperanto", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", + "Welsh", "Basque", "Catalan", "Latin", "Quechua", "Guarani", "Aymara", "Tatar", + "Uighur", "Dzongkha", "Javanese", "Sundanese", "Galician", "Afrikaans", "Breton", "Inuktitut", + "Scottish", "Manx", "Irish", "Tongan", "Greek", "Greenlandic", "Azerbaijani", "Nynorsk" +}; + +#define NUM_LANGUAGE_NAMES 152 +#define LANGUAGE_NAME_LENGTH 13 + +// string, with groups of 3 characters being 1 element in the array of abbreviations +const char * __CFBundleLanguageAbbreviationsArray = + "en\0" "fr\0" "de\0" "it\0" "nl\0" "sv\0" "es\0" "da\0" + "pt\0" "nb\0" "he\0" "ja\0" "ar\0" "fi\0" "el\0" "is\0" + "mt\0" "tr\0" "hr\0" "zh\0" "ur\0" "hi\0" "th\0" "ko\0" + "lt\0" "pl\0" "hu\0" "et\0" "lv\0" "se\0" "fo\0" "fa\0" + "ru\0" "zh\0" "nl\0" "ga\0" "sq\0" "ro\0" "cs\0" "sk\0" + "sl\0" "yi\0" "sr\0" "mk\0" "bg\0" "uk\0" "be\0" "uz\0" + "kk\0" "az\0" "az\0" "hy\0" "ka\0" "mo\0" "ky\0" "tg\0" + "tk\0" "mn\0" "mn\0" "ps\0" "ku\0" "ks\0" "sd\0" "bo\0" + "ne\0" "sa\0" "mr\0" "bn\0" "as\0" "gu\0" "pa\0" "or\0" + "ml\0" "kn\0" "ta\0" "te\0" "si\0" "my\0" "km\0" "lo\0" + "vi\0" "id\0" "tl\0" "ms\0" "ms\0" "am\0" "ti\0" "om\0" + "so\0" "sw\0" "rw\0" "rn\0" "\0\0\0" "mg\0" "eo\0" "\0\0\0" + "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" + "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" + "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" + "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" + "cy\0" "eu\0" "ca\0" "la\0" "qu\0" "gn\0" "ay\0" "tt\0" + "ug\0" "dz\0" "jv\0" "su\0" "gl\0" "af\0" "br\0" "iu\0" + "gd\0" "gv\0" "ga\0" "to\0" "el\0" "kl\0" "az\0" "nn\0"; + +#define NUM_LANGUAGE_ABBREVIATIONS 152 +#define LANGUAGE_ABBREVIATION_LENGTH 3 + +static CFStringRef _CFBundleGetAlternateNameForLanguage(CFStringRef language) { + // These are not necessarily common localizations per se, but localizations for which the full language name is still in common use. + // These are used to provide a fast path for it (other localizations usually use the abbreviation, which is even faster). + static CFStringRef const __CFBundleCommonLanguageNamesArray[] = {CFSTR("English"), CFSTR("French"), CFSTR("German"), CFSTR("Italian"), CFSTR("Dutch"), CFSTR("Spanish"), CFSTR("Japanese")}; + static CFStringRef const __CFBundleCommonLanguageAbbreviationsArray[] = {CFSTR("en"), CFSTR("fr"), CFSTR("de"), CFSTR("it"), CFSTR("nl"), CFSTR("es"), CFSTR("ja")}; + + for (CFIndex idx = 0; idx < sizeof(__CFBundleCommonLanguageNamesArray) / sizeof(CFStringRef); idx++) { + if (CFEqual(language, __CFBundleCommonLanguageAbbreviationsArray[idx])) { + return __CFBundleCommonLanguageNamesArray[idx]; + } else if (CFEqual(language, __CFBundleCommonLanguageNamesArray[idx])) { + return __CFBundleCommonLanguageAbbreviationsArray[idx]; + } + } + + return NULL; +} + +static const SInt32 __CFBundleScriptCodesArray[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 4, 0, 6, 0, + 0, 0, 0, 2, 4, 9, 21, 3, 29, 29, 29, 29, 29, 0, 0, 4, + 7, 25, 0, 0, 0, 0, 29, 29, 0, 5, 7, 7, 7, 7, 7, 7, + 7, 7, 4, 24, 23, 7, 7, 7, 7, 27, 7, 4, 4, 4, 4, 26, + 9, 9, 9, 13, 13, 11, 10, 12, 17, 16, 14, 15, 18, 19, 20, 22, + 30, 0, 0, 0, 4, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 4, 26, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 6, 0, 0, 0 +}; + +static const CFStringEncoding __CFBundleStringEncodingsArray[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 4, 0, 6, 37, + 0, 35, 36, 2, 4, 9, 21, 3, 29, 29, 29, 29, 29, 0, 37, 0x8C, + 7, 25, 0, 39, 0, 38, 29, 29, 36, 5, 7, 7, 7, 0x98, 7, 7, + 7, 7, 4, 24, 23, 7, 7, 7, 7, 27, 7, 4, 4, 4, 4, 26, + 9, 9, 9, 13, 13, 11, 10, 12, 17, 16, 14, 15, 18, 19, 20, 22, + 30, 0, 0, 0, 4, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 39, 0, 0, 0, 0, 0, 0, 7, 4, 26, 0, 0, 0, 0, 39, 0xEC, + 39, 39, 40, 0, 6, 0, 0, 0 +}; + +static SInt32 _CFBundleGetLanguageCodeForLocalization(CFStringRef localizationName) { + SInt32 result = -1, i; + char buff[256]; + CFIndex length = CFStringGetLength(localizationName); + if (length >= LANGUAGE_ABBREVIATION_LENGTH - 1 && length <= 255 && CFStringGetCString(localizationName, buff, 255, kCFStringEncodingASCII)) { + buff[255] = '\0'; + for (i = 0; -1 == result && i < NUM_LANGUAGE_NAMES; i++) { + if (0 == strcmp(buff, __CFBundleLanguageNamesArray[i])) result = i; + } + if (0 == strcmp(buff, "zh_TW") || 0 == strcmp(buff, "zh-Hant")) result = 19; else if (0 == strcmp(buff, "zh_CN") || 0 == strcmp(buff, "zh-Hans")) result = 33; // hack for mixed-up Chinese language codes + if (-1 == result && (length == LANGUAGE_ABBREVIATION_LENGTH - 1 || !isalpha(buff[LANGUAGE_ABBREVIATION_LENGTH - 1]))) { + buff[LANGUAGE_ABBREVIATION_LENGTH - 1] = '\0'; + if ('n' == buff[0] && 'o' == buff[1]) result = 9; // hack for Norwegian + for (i = 0; -1 == result && i < NUM_LANGUAGE_ABBREVIATIONS * LANGUAGE_ABBREVIATION_LENGTH; i += LANGUAGE_ABBREVIATION_LENGTH) { + if (buff[0] == *(__CFBundleLanguageAbbreviationsArray + i + 0) && buff[1] == *(__CFBundleLanguageAbbreviationsArray + i + 1)) result = i / LANGUAGE_ABBREVIATION_LENGTH; + } + } + } + return result; +} + +static CFStringRef _CFBundleCopyLanguageAbbreviationForLanguageCode(SInt32 languageCode) { + CFStringRef result = NULL; + if (0 <= languageCode && languageCode < NUM_LANGUAGE_ABBREVIATIONS) { + const char *languageAbbreviation = __CFBundleLanguageAbbreviationsArray + languageCode * LANGUAGE_ABBREVIATION_LENGTH; + if (languageAbbreviation && *languageAbbreviation != '\0') result = CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, languageAbbreviation, kCFStringEncodingASCII, kCFAllocatorNull); + } + return result; +} + +// Swaps - for _ and _ for - in a localization name +static CFStringRef _CFBundleCopyModifiedLocalization(CFStringRef localizationName) { + CFMutableStringRef result = NULL; + CFIndex length = CFStringGetLength(localizationName); + if (length >= 4) { + UniChar c = CFStringGetCharacterAtIndex(localizationName, 2); + if ('-' == c || '_' == c) { + result = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, length, localizationName); + CFStringReplace(result, CFRangeMake(2, 1), ('-' == c) ? CFSTR("_") : CFSTR("-")); + } + } + return result; +} + +static SInt32 _CFBundleGetLanguageCodeForRegionCode(SInt32 regionCode) { + SInt32 result = -1, i; + if (52 == regionCode) { // hack for mixed-up Chinese language codes + result = 33; + } else if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) { + const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH; + if (localeAbbreviation && *localeAbbreviation != '\0') { + for (i = 0; -1 == result && i < NUM_LANGUAGE_ABBREVIATIONS * LANGUAGE_ABBREVIATION_LENGTH; i += LANGUAGE_ABBREVIATION_LENGTH) { + if (localeAbbreviation[0] == *(__CFBundleLanguageAbbreviationsArray + i + 0) && localeAbbreviation[1] == *(__CFBundleLanguageAbbreviationsArray + i + 1)) result = i / LANGUAGE_ABBREVIATION_LENGTH; + } + } + } + return result; +} + +static SInt32 _CFBundleGetRegionCodeForLanguageCode(SInt32 languageCode) { + SInt32 result = -1, i; + if (19 == languageCode) { // hack for mixed-up Chinese language codes + result = 53; + } else if (0 <= languageCode && languageCode < NUM_LANGUAGE_ABBREVIATIONS) { + const char *languageAbbreviation = __CFBundleLanguageAbbreviationsArray + languageCode * LANGUAGE_ABBREVIATION_LENGTH; + if (languageAbbreviation && *languageAbbreviation != '\0') { + for (i = 0; -1 == result && i < NUM_LOCALE_ABBREVIATIONS * LOCALE_ABBREVIATION_LENGTH; i += LOCALE_ABBREVIATION_LENGTH) { + if (*(__CFBundleLocaleAbbreviationsArray + i + 0) == languageAbbreviation[0] && *(__CFBundleLocaleAbbreviationsArray + i + 1) == languageAbbreviation[1]) result = i / LOCALE_ABBREVIATION_LENGTH; + } + } + } + if (25 == result) result = 68; + if (28 == result) result = 82; + return result; +} + +static SInt32 _CFBundleGetRegionCodeForLocalization(CFStringRef localizationName) { + SInt32 result = -1, i; + char buff[LOCALE_ABBREVIATION_LENGTH]; + CFIndex length = CFStringGetLength(localizationName); + if (length >= LANGUAGE_ABBREVIATION_LENGTH - 1 && length <= LOCALE_ABBREVIATION_LENGTH - 1 && CFStringGetCString(localizationName, buff, LOCALE_ABBREVIATION_LENGTH, kCFStringEncodingASCII)) { + buff[LOCALE_ABBREVIATION_LENGTH - 1] = '\0'; + for (i = 0; -1 == result && i < NUM_LOCALE_ABBREVIATIONS * LOCALE_ABBREVIATION_LENGTH; i += LOCALE_ABBREVIATION_LENGTH) { + if (0 == strcmp(buff, __CFBundleLocaleAbbreviationsArray + i)) result = i / LOCALE_ABBREVIATION_LENGTH; + } + } + if (25 == result) result = 68; + if (28 == result) result = 82; + if (37 == result) result = 0; + if (-1 == result) { + SInt32 languageCode = _CFBundleGetLanguageCodeForLocalization(localizationName); + result = _CFBundleGetRegionCodeForLanguageCode(languageCode); + } + return result; +} + +CF_PRIVATE CFStringRef _CFBundleCopyLocaleAbbreviationForRegionCode(SInt32 regionCode) { + CFStringRef result = NULL; + if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) { + const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH; + if (localeAbbreviation && *localeAbbreviation != '\0') { + result = CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, localeAbbreviation, kCFStringEncodingASCII, kCFAllocatorNull); + } + } + return result; +} + +CF_EXPORT Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName, SInt32 *languageCode, SInt32 *regionCode, SInt32 *scriptCode, CFStringEncoding *stringEncoding) { + Boolean retval = false; + SInt32 language = -1, region = -1, script = 0; + CFStringEncoding encoding = kCFStringEncodingMacRoman; + if (!localizationName) { + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFArrayRef languages = NULL; + if (mainBundle) { + languages = _CFBundleCopyLanguageSearchListInBundle(mainBundle); + } + if (!languages) languages = _CFBundleCopyUserLanguages(); + if (languages && CFArrayGetCount(languages) > 0) localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); + } + if (localizationName) { + LangCode langCode = -1; + RegionCode regCode = -1; + ScriptCode scrCode = 0; + CFStringEncoding enc = kCFStringEncodingMacRoman; + retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, ®Code, &scrCode, &enc); + if (retval) { + language = langCode; + region = regCode; + script = scrCode; + encoding = enc; + } + } + if (!retval) { + if (localizationName) { + language = _CFBundleGetLanguageCodeForLocalization(localizationName); + region = _CFBundleGetRegionCodeForLocalization(localizationName); + } else { + _CFBundleGetLanguageAndRegionCodes(&language, ®ion); + } + if ((language < 0 || language > (int)(sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32))) && region != -1) language = _CFBundleGetLanguageCodeForRegionCode(region); + if (region == -1 && language != -1) region = _CFBundleGetRegionCodeForLanguageCode(language); + if (language >= 0 && language < (int)(sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32))) { + script = __CFBundleScriptCodesArray[language]; + } + if (language >= 0 && language < (int)(sizeof(__CFBundleStringEncodingsArray)/sizeof(CFStringEncoding))) { + encoding = __CFBundleStringEncodingsArray[language]; + } + retval = (language != -1 || region != -1); + } + if (languageCode) *languageCode = language; + if (regionCode) *regionCode = region; + if (scriptCode) *scriptCode = script; + if (stringEncoding) *stringEncoding = encoding; + return retval; +} + +CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SInt32 regionCode, SInt32 scriptCode, CFStringEncoding stringEncoding) { + CFStringRef localizationName = NULL; + if (!localizationName) localizationName = _CFBundleCopyLocaleAbbreviationForRegionCode(regionCode); +#if DEPLOYMENT_TARGET_MACOSX + if (!localizationName && 0 <= languageCode && languageCode < SHRT_MAX) localizationName = CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(kCFAllocatorSystemDefault, (LangCode)languageCode, (RegionCode)-1); +#endif + if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode); + if (!localizationName) { + SInt32 language = -1, scriptLanguage = -1, encodingLanguage = -1; + unsigned int i; + for (i = 0; language == -1 && i < (sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32)); i++) { + if (__CFBundleScriptCodesArray[i] == scriptCode && __CFBundleStringEncodingsArray[i] == stringEncoding) language = i; + } + for (i = 0; scriptLanguage == -1 && i < (sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32)); i++) { + if (__CFBundleScriptCodesArray[i] == scriptCode) scriptLanguage = i; + } + for (i = 0; encodingLanguage == -1 && i < (sizeof(__CFBundleStringEncodingsArray)/sizeof(CFStringEncoding)); i++) { + if (__CFBundleStringEncodingsArray[i] == stringEncoding) encodingLanguage = i; + } + localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(language); + if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(encodingLanguage); + if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(scriptLanguage); + } + return localizationName; +} + +#pragma mark - + +// Get a list of lproj directories for a particular resource directory URL. Uncached. Does not include any predefined localizations from an Info.plist. This function does make any attempt to localize or canonicalize the results. +static CFArrayRef _CFBundleCopyLProjDirectoriesForURL(CFAllocatorRef allocator, CFURLRef url) { + __block CFMutableArrayRef result = NULL; + CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url); + CFStringRef directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); + CFRelease(absoluteURL); + + CFStringRef lproj = _CFBundleLprojExtensionWithDot; + CFIndex lprojLen = CFStringGetLength(lproj); + + _CFIterateDirectory(directoryPath, ^Boolean(CFStringRef fileName, uint8_t fileType) { + // See if the fileName ends in .lproj + // The comparison starts at the end of the fileName, backed up by the length of .lproj + CFIndex fileNameLen = CFStringGetLength(fileName); + if (fileNameLen > lprojLen && CFStringCompareWithOptions(fileName, lproj, CFRangeMake(fileNameLen - lprojLen, lprojLen), 0) == kCFCompareEqualTo) { + // Chop off the .lproj part before creating a string + CFStringRef lprojDirectoryName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fileName, CFRangeMake(0, fileNameLen - lprojLen)); + if (!result) result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(result, lprojDirectoryName); + CFRelease(lprojDirectoryName); + } + return true; + }); + + CFRelease(directoryPath); + return (CFArrayRef)result; +} + +/* This function returns: + 1. The predefined localizations in the Info.plist (CFBundleLocalizations) + 2. Additionally, the .lproj directories inside the bundle + 3. Additionally, the development region of the bundle (CFBundleDevelopmentRegion) -- although if it's already in #1, or #2, we don't append it again + 4. As an ultimate fallback, an empty array + + This doesn't attempt to include a list of localizations supported by a bundle by way of a fallback path; e.g., if the bundle has en_GB then we do not include en_IN (which falls back to en_GB if not present). + + Since the result of this is "typically passed as a parameter to either the CFBundleCopyPreferredLocalizationsFromArray or CFBundleCopyLocalizationsForPreferences function", those other functions will take into account the user prefs and pick the right lproj. +*/ +CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) { + CFArrayRef result = NULL; + + __CFLock(&bundle->_lock); + if (bundle->_lookedForLocalizations) { + result = (CFArrayRef)CFRetain(bundle->_localizations); + __CFUnlock(&bundle->_lock); + return result; + } + __CFUnlock(&bundle->_lock); + + CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); + if (infoDict) { + CFArrayRef predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); + if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) == CFArrayGetTypeID()) { + // Some people put bad things inside this array =( + CFMutableArrayRef realPredefinedLocalizations = CFArrayCreateMutable(CFGetAllocator(bundle), CFArrayGetCount(predefinedLocalizations), &kCFTypeArrayCallBacks); + for (CFIndex i = 0; i < CFArrayGetCount(predefinedLocalizations); i++) { + CFStringRef oneEntry = CFArrayGetValueAtIndex(predefinedLocalizations, i); + if (CFGetTypeID(oneEntry) == CFStringGetTypeID() && CFStringGetLength(oneEntry) > 0) { + CFArrayAppendValue(realPredefinedLocalizations, oneEntry); + } + } + result = CFArrayCreateCopy(CFGetAllocator(bundle), realPredefinedLocalizations); + CFRelease(realPredefinedLocalizations); + } + } + + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); + if (resourcesURL) { + CFArrayRef lprojDirectoriesInResources = _CFBundleCopyLProjDirectoriesForURL(CFGetAllocator(bundle), resourcesURL); + if (lprojDirectoriesInResources) { + if (result) { + // Append the lproj result to the predefined localization array + CFMutableArrayRef newResult = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, result); + CFRelease(result); + CFArrayAppendArray(newResult, lprojDirectoriesInResources, CFRangeMake(0, CFArrayGetCount(lprojDirectoriesInResources))); + CFRelease(lprojDirectoriesInResources); + result = newResult; + } else { + result = lprojDirectoriesInResources; + } + } + CFRelease(resourcesURL); + } + + CFStringRef developmentLocalization = CFBundleGetDevelopmentRegion(bundle); + if (result) { + if (developmentLocalization) { + CFRange entireRange = CFRangeMake(0, CFArrayGetCount(result)); + if (CFArrayContainsValue(result, entireRange, _CFBundleBaseDirectory)) { + // Base.lproj contains localizations for the development region. Insert the development region into the existing array if there isn't already a match so that resource lookup doesn't default to another language. + // We need to make sure that we don't add "en" if "English" exists. (14006652) + CFStringRef foundInLocalizations = _CFBundleCopyLanguageFoundInLocalizations(result, developmentLocalization); + if (!foundInLocalizations) { + CFMutableArrayRef newResult = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, result); + CFRelease(result); + CFArrayAppendValue(newResult, developmentLocalization); + result = newResult; + } else { + // The development localization was in the result, but in some other form. We don't need to add it again. + CFRelease(foundInLocalizations); + } + } + } + } else { + if (developmentLocalization) { + result = CFArrayCreate(CFGetAllocator(bundle), (const void **)&developmentLocalization, 1, &kCFTypeArrayCallBacks); + } else { + result = CFArrayCreate(CFGetAllocator(bundle), NULL, 0, &kCFTypeArrayCallBacks); + } + } + + // Cache the result. + __CFLock(&bundle->_lock); + if (bundle->_lookedForLocalizations && result) { + // Another thread beat us to it. Release our result and return the existing answer. + CFRelease(result); + result = (CFArrayRef)CFRetain(bundle->_localizations); + } else { + bundle->_localizations = (CFArrayRef)CFRetain(result); + bundle->_lookedForLocalizations = true; + } + __CFUnlock(&bundle->_lock); + + return result; +} + +CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForURL(CFURLRef url) { + CFArrayRef result = NULL; + CFBundleRef bundle = CFBundleCreate(kCFAllocatorSystemDefault, url); + CFStringRef devLang = NULL; + if (bundle) { + result = CFBundleCopyBundleLocalizations(bundle); + CFRelease(bundle); + } else { + CFDictionaryRef infoDict = _CFBundleCopyInfoDictionaryInExecutable(url); + if (infoDict) { + CFArrayRef predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); + if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) == CFArrayGetTypeID()) { + result = (CFArrayRef)CFRetain(predefinedLocalizations); + } + if (!result) { + devLang = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); + if (devLang && (CFGetTypeID(devLang) == CFStringGetTypeID() && CFStringGetLength(devLang) > 0)) { + result = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&devLang, 1, &kCFTypeArrayCallBacks); + } + } + CFRelease(infoDict); + } + } + return result; +} + +extern void *__CFAppleLanguages; + + + + +CF_PRIVATE CFArrayRef _CFBundleCopyUserLanguages() { + static CFArrayRef _CFBundleUserLanguages = NULL; + static dispatch_once_t once = 0; + dispatch_once(&once, ^{ + CFArrayRef preferencesArray = NULL; + if (__CFAppleLanguages) { + CFDataRef data; + CFIndex length = strlen((const char *)__CFAppleLanguages); + if (length > 0) { + data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)__CFAppleLanguages, length, kCFAllocatorNull); + if (data) { + _CFBundleUserLanguages = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL, NULL); + CFRelease(data); + } + } + } + if (!_CFBundleUserLanguages && preferencesArray) _CFBundleUserLanguages = (CFArrayRef)CFRetain(preferencesArray); + Boolean useEnglishAsBackstop = true; + // could perhaps read out of LANG environment variable + if (useEnglishAsBackstop && !_CFBundleUserLanguages) { + CFStringRef english = CFSTR("en"); + _CFBundleUserLanguages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&english, 1, &kCFTypeArrayCallBacks); + } + if (_CFBundleUserLanguages && CFGetTypeID(_CFBundleUserLanguages) != CFArrayGetTypeID()) { + CFRelease(_CFBundleUserLanguages); + _CFBundleUserLanguages = NULL; + } + if (preferencesArray) CFRelease(preferencesArray); + }); + + if (_CFBundleUserLanguages) { + CFRetain(_CFBundleUserLanguages); + return _CFBundleUserLanguages; + } else { + return NULL; + } +} + +CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 *regionCode) { + // an attempt to answer the question, "what language are we running in?" + // note that the question cannot be answered fully since it may depend on the bundle + SInt32 language = -1, region = -1; + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFArrayRef languages = NULL; + if (mainBundle) { + languages = _CFBundleCopyLanguageSearchListInBundle(mainBundle); + } + if (!languages) languages = _CFBundleCopyUserLanguages(); + if (languages && CFArrayGetCount(languages) > 0) { + CFStringRef localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); + Boolean retval = false; + LangCode langCode = -1; + RegionCode regCode = -1; + retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, ®Code, NULL, NULL); + if (retval) { + language = langCode; + region = regCode; + } + if (!retval) { + language = _CFBundleGetLanguageCodeForLocalization(localizationName); + region = _CFBundleGetRegionCodeForLocalization(localizationName); + } + } else { + language = 0; + region = 0; + } + if (language == -1 && region != -1) language = _CFBundleGetLanguageCodeForRegionCode(region); + if (region == -1 && language != -1) region = _CFBundleGetRegionCodeForLanguageCode(language); + if (languages) CFRelease(languages); + if (languageCode) *languageCode = language; + if (regionCode) *regionCode = region; +} + +// Return a CFStringRef as it appears in the localizations, if it matches the input language in any form. +// For example, if the input language is 'en', and the array contains 'English', return 'English'. +// If the input language is 'en-US', and the array contains 'en_US', return 'en_US'. +// If the input language is 'froobleblax' and the array does not contain it, return NULL. +static CFStringRef _CFBundleCopyLanguageFoundInLocalizations(CFArrayRef localizations, CFStringRef language) { + // Bail early on empty input + if (!localizations || !language) { + return NULL; + } + + CFRange localizationsRange = CFRangeMake(0, CFArrayGetCount(localizations)); + + // Does the array straight-up contain this language? + if (CFArrayContainsValue(localizations, localizationsRange, language)) { + return CFRetain(language); + } + + // Does the array contain the alternate form of this language? (en -> English, or vice versa) + CFStringRef altLangStr = _CFBundleGetAlternateNameForLanguage(language); + if (altLangStr && CFArrayContainsValue(localizations, localizationsRange, altLangStr)) { + return CFRetain(altLangStr); + } + + // Does the array contain a modified form of this language? (en-US -> en_US, or vice versa) + CFStringRef modifiedLangStr = _CFBundleCopyModifiedLocalization(language); + if (modifiedLangStr) { + if (CFArrayContainsValue(localizations, localizationsRange, modifiedLangStr)) { + return modifiedLangStr; + } + CFRelease(modifiedLangStr); + } + + // Does the array contain a canonical form of this language? + CFStringRef canonicalLanguage = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault, language); + if (canonicalLanguage) { + if (CFArrayContainsValue(localizations, localizationsRange, canonicalLanguage)) { + return canonicalLanguage; + } + + // Does the array converted to canonical forms match the canonical form of this language? + for (CFIndex i = 0; i < localizationsRange.length; i++) { + CFStringRef oneLanguage = (CFStringRef)CFArrayGetValueAtIndex(localizations, i); + CFStringRef canonicalOneLanguage = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault, oneLanguage); + + if (canonicalOneLanguage) { + if (CFEqual(canonicalOneLanguage, canonicalLanguage)) { + // oneLocalization is the same as the input language, even though they are in different forms + CFRelease(canonicalOneLanguage); + CFRelease(canonicalLanguage); + + return CFRetain(oneLanguage); + } + CFRelease(canonicalOneLanguage); + } + } + + CFRelease(canonicalLanguage); + } + + // The language was not found in the array in any form + return NULL; +} + +// Given a list of localizations (e.g., provided as argument to API, or present as .lproj directories), return a mutable array of localizations in preferred order. Returns NULL if nothing is found. +static CFMutableArrayRef _CFBundleCreateMutableArrayOfFallbackLanguages(CFArrayRef localizations, CFStringRef language) { + CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + + // Check for the language itself (in whatever form) + CFStringRef languageInLocalizations = _CFBundleCopyLanguageFoundInLocalizations(localizations, language); + if (languageInLocalizations) { + CFArrayAppendValue(result, languageInLocalizations); + CFRelease(languageInLocalizations); + } + + // Languages form a tree in ICU data. For example: + + // en_IN -> en_GB -> en_001 -> en -> root + // or + // zh_Hant_MO -> zh_Hant_HK -> zh_Hant -> zh_TW -> root + // or + // zh_Hans -> zh -> zh_CN -> root + + // We will iterate through each element until we get to root, adding the entries to our resulting list of preferred languages as we go if they exist in the localizations list. + + char locale[128]; + if (CFStringGetCString(language, locale, 128, kCFStringEncodingUTF8)) { + UErrorCode error = U_ZERO_ERROR; + char parent[128]; + + int counter = 0; + while (1) { + ualoc_getAppleParent(locale, parent, 128, &error); + if (error != U_ZERO_ERROR) break; + if (strncmp(parent, "root", 4) == 0) break; + + CFStringRef parentString = CFStringCreateWithCString(kCFAllocatorSystemDefault, parent, kCFStringEncodingUTF8); + if (parentString) { + CFStringRef parentInLocalizations = _CFBundleCopyLanguageFoundInLocalizations(localizations, parentString); + if (parentInLocalizations) { + // Be sure not to add the same language to the result array twice. This can happen when the above function canonicalizes names (e.g., zh_TW -> zh_Hans). + if (!CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), parentInLocalizations)) { + CFArrayAppendValue(result, parentInLocalizations); + } + CFRelease(parentInLocalizations); + } + CFRelease(parentString); + } + + // The parent now becomes the locale we enter in the next loop + if (strlcpy(locale, parent, 128) >= 128) break; + + // Just in case the call into ICU to get the parent locale results in a cycle, we need a fallback mechanism to break out of this while loop. Therefore we'll only fallback a max of 16 times. + counter++; + if (counter >= 16) break; + } + } + + if (CFArrayGetCount(result) == 0) { + CFRelease(result); + result = NULL; + } + + return result; +} + +/* + Funnel point for figuring out the language search order for resource lookup and other functions. + + The input to the search is the list of searchLanguages, a development language, and the list of user-preferred languages. + + The output is a mutable array. The result will add elements in order of the preferred languages specified. Returns an empty array if nothing is found. + + The users list can contain region names (like "en_US" for US English). In this case, if the region lproj exists, it will be added, and, if the region's associated language lproj exists that will be added. +*/ +static CFMutableArrayRef _CFBundleCopyPreferredLanguagesInList(CFArrayRef searchLanguages, CFStringRef devLang, CFArrayRef userLanguages, Boolean considerMain, CFURLRef bundleURL, CFBundleRef bundle) { + CFMutableArrayRef result = NULL; + CFArrayRef mainBundleLangs = NULL; + + // If CFBundleAllowMixedLocalizations is set, then we do not check the main bundle. If considerMain is not set (we've entered through the API that specifically ignores the main bundle), then do not check the main bundle. + if (considerMain && !CFBundleAllowMixedLocalizations()) { + if (CFBundleFollowParentLocalization()) { + } else { + CFBundleRef mainBundle = CFBundleGetMainBundle(); + if (mainBundle) { + CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle); + if (mainBundleURL) { + if (!bundleURL || !CFEqual(bundleURL, mainBundleURL)) { + // If there is a main bundle, and it isn't this one, try to use the language it prefers. + mainBundleLangs = _CFBundleCopyLanguageSearchListInBundle(mainBundle); + } + CFRelease(mainBundleURL); + } + } + } + + if (mainBundleLangs) { + if (CFArrayGetCount(mainBundleLangs) > 0) { + result = _CFBundleCreateMutableArrayOfFallbackLanguages(searchLanguages, (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0)); + } + } + } + + if (!result) { + // If we didn't find the main bundle's preferred language, look at the users' prefs again and find the best one. + if (userLanguages) { + CFIndex count = CFArrayGetCount(userLanguages); + for (CFIndex i = 0; i < count; i++) { + CFStringRef curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, i); + result = _CFBundleCreateMutableArrayOfFallbackLanguages(searchLanguages, curLangStr); + + if (result) break; + } + } + + // use development region and U.S. English as backstops + if (!result && devLang) { + result = _CFBundleCreateMutableArrayOfFallbackLanguages(searchLanguages, devLang); + } + + if (!result) { + result = _CFBundleCreateMutableArrayOfFallbackLanguages(searchLanguages, CFSTR("en_US")); + } + } + + if (!result) { + result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + } + + + if (mainBundleLangs) CFRelease(mainBundleLangs); + + return result; +} + +// userLanguages must be non-NULL +static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef localizations, CFArrayRef userLanguages, Boolean considerMain) { + CFMutableArrayRef result = NULL; + + if (localizations && CFArrayGetCount(localizations) > 0) { + result = _CFBundleCopyPreferredLanguagesInList(localizations, NULL, userLanguages, considerMain, NULL, NULL); + + // Additional backstop behavior: use first entry as backstop + if (CFArrayGetCount(result) == 0 && CFArrayGetCount(localizations) > 0) { + CFArrayAppendValue(result, CFArrayGetValueAtIndex(localizations, 0)); + } else if (CFArrayGetCount(result) == 0) { + // Total backstop behavior to avoid having an empty array. + CFArrayAppendValue(result, CFSTR("en")); + } + } + + if (!result) { + // Total backstop behavior to avoid having an empty array. + result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(result, CFSTR("en")); + } + + return result; +} + +CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForPreferences(CFArrayRef localizations, CFArrayRef preferredLocalizations) { + // NOTE: This function has an interesting side effect; passing NULL for preferredLocalizations will still use the user's current set of preferences, but it will ignore the main bundle for the purposes of matching languages. This is something that people rely upon. + // Given an array of possible localizations, returns the one or more of them that CFBundle would use, without reference to the current application context, if the user's preferred localizations were given by prefArray. If prefArray is NULL, the current user's actual preferred localizations will be used. This is not the same as CFBundleCopyPreferredLocalizationsFromArray(), because that function takes the current application context into account. To determine the localizations that another application would use, apply this function to the result of CFBundleCopyBundleLocalizations(). + + if (preferredLocalizations) { + return _CFBundleCopyLocalizationsForPreferences(localizations, preferredLocalizations, false); + } else { + CFArrayRef defaultPreferredLocalizations = _CFBundleCopyUserLanguages(); + if (!defaultPreferredLocalizations) defaultPreferredLocalizations = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks); + CFArrayRef result = _CFBundleCopyLocalizationsForPreferences(localizations, defaultPreferredLocalizations, false); + CFRelease(defaultPreferredLocalizations); + return result; + } +} + +CF_EXPORT CFArrayRef CFBundleCopyPreferredLocalizationsFromArray(CFArrayRef localizations) { + // Given an array of possible localizations, returns the one or more of them that CFBundle would use in the current application context. To determine the localizations that would be used for a particular bundle in the current application context, apply this function to the result of CFBundleCopyBundleLocalizations(). + // NOTE: Current application context refers to both using the main bundle and also using the preferred languages for the user + CFArrayRef preferredLocalizations = _CFBundleCopyUserLanguages(); + if (!preferredLocalizations) preferredLocalizations = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks); + + CFArrayRef result = _CFBundleCopyLocalizationsForPreferences(localizations, preferredLocalizations, true); + + CFRelease(preferredLocalizations); + return result; +} + +static CFStringRef _defaultLocalization = NULL; + +CF_EXPORT void _CFBundleSetDefaultLocalization(CFStringRef localizationName) { + CFStringRef newLocalization = localizationName ? (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, localizationName) : NULL; + if (_defaultLocalization) CFRelease(_defaultLocalization); + _defaultLocalization = newLocalization; +} + +#pragma mark - + + + +// This is the funnel point for looking up languages for a particular bundle. +CF_PRIVATE CFArrayRef _CFBundleCopyLanguageSearchListInBundle(CFBundleRef bundle) { + if (!bundle->_searchLanguages) { +#if DEPLOYMENT_TARGET_WINDOWS + if (_defaultLocalization) CFArrayAppendValue(langs, _defaultLocalization); +#endif + // includes predefined localizations + CFArrayRef localizationsForBundle = CFBundleCopyBundleLocalizations(bundle); + CFArrayRef userLanguages = _CFBundleCopyUserLanguages(); + CFStringRef devLang = CFBundleGetDevelopmentRegion(bundle); + + CFMutableArrayRef result = _CFBundleCopyPreferredLanguagesInList(localizationsForBundle, devLang, userLanguages, true, bundle->_url, bundle); + + if (CFArrayGetCount(result) == 0) { + // If the user does not prefer any of our languages, and devLang is not present, try English + CFRelease(result); + result = _CFBundleCopyPreferredLanguagesInList(localizationsForBundle, CFSTR("en_US"), userLanguages, true, bundle->_url, bundle); + } + + // if none of the preferred localizations are present, fall back on a random localization that is present + if (CFArrayGetCount(result) == 0 && localizationsForBundle && CFArrayGetCount(localizationsForBundle) > 0) { + CFStringRef firstLocalization = (CFStringRef)CFArrayGetValueAtIndex(localizationsForBundle, 0); + CFRelease(result); + result = _CFBundleCopyPreferredLanguagesInList(localizationsForBundle, firstLocalization, userLanguages, true, bundle->_url, bundle); + } + + if (userLanguages) CFRelease(userLanguages); + + if (devLang && !CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), devLang)) { + // Make sure that devLang is on the list as a fallback for individual resources that are not present + CFArrayAppendValue(result, devLang); + } else if (!devLang) { + if (localizationsForBundle) { + CFStringRef en_US = CFSTR("en_US"), en = CFSTR("en"), English = CFSTR("English"); + CFRange range = CFRangeMake(0, CFArrayGetCount(localizationsForBundle)); + if (CFArrayContainsValue(localizationsForBundle, range, en)) { + if (!CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), en)) CFArrayAppendValue(result, en); + } else if (CFArrayContainsValue(localizationsForBundle, range, English)) { + if (!CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), English)) CFArrayAppendValue(result, English); + } else if (CFArrayContainsValue(localizationsForBundle, range, en_US)) { + if (!CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), en_US)) CFArrayAppendValue(result, en_US); + } + } + } + + if (localizationsForBundle) CFRelease(localizationsForBundle); + + if (CFArrayGetCount(result) == 0) { + // Total backstop behavior to avoid having an empty array. + if (_defaultLocalization) { + CFArrayAppendValue(result, _defaultLocalization); + } else { + CFArrayAppendValue(result, CFSTR("en")); + } + } + + if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)result, (void * volatile *)&(bundle->_searchLanguages))) { + CFRelease(result); + } + } + return (CFArrayRef)CFRetain(bundle->_searchLanguages); +} + +// This is the funnel point for looking up languages for a particular directory. +CF_PRIVATE CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFURLRef url, uint8_t *version) { + uint8_t localVersion = 0; + CFDictionaryRef infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, &localVersion); + + CFArrayRef predefinedLocalizations = NULL; + CFStringRef devLang = NULL; + if (infoDict) { + devLang = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); + if (devLang && (CFGetTypeID(devLang) != CFStringGetTypeID() || CFStringGetLength(devLang) == 0)) devLang = NULL; + + predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); + if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) != CFArrayGetTypeID()) { + predefinedLocalizations = NULL; + } + } + + CFURLRef resourcesURL = _CFBundleCopyResourcesDirectoryURLInDirectory(url, localVersion); + CFArrayRef localizationsInDirectory = _CFBundleCopyLProjDirectoriesForURL(kCFAllocatorSystemDefault, resourcesURL); + CFRelease(resourcesURL); + + if (predefinedLocalizations && localizationsInDirectory) { + CFMutableArrayRef newLocalizations = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, predefinedLocalizations); + CFArrayAppendArray(newLocalizations, localizationsInDirectory, CFRangeMake(0, CFArrayGetCount(localizationsInDirectory))); + CFRelease(localizationsInDirectory); + localizationsInDirectory = (CFArrayRef)newLocalizations; + } else if (predefinedLocalizations) { + localizationsInDirectory = (CFArrayRef)CFRetain(predefinedLocalizations); + } else if (!localizationsInDirectory) { + localizationsInDirectory = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks); + } + + CFArrayRef userLanguages = _CFBundleCopyUserLanguages(); + CFMutableArrayRef result = _CFBundleCopyPreferredLanguagesInList(localizationsInDirectory, devLang, userLanguages, true, url, NULL); + + if (userLanguages) CFRelease(userLanguages); + CFRelease(localizationsInDirectory); + + if (devLang && CFArrayGetFirstIndexOfValue(result, CFRangeMake(0, CFArrayGetCount(result)), devLang) < 0) CFArrayAppendValue(result, devLang); + + // Total backstop behavior to avoid having an empty array. + if (CFArrayGetCount(result) == 0) CFArrayAppendValue(result, CFSTR("en")); + + if (infoDict) CFRelease(infoDict); + if (version) *version = localVersion; + return result; +} + diff --git a/CFBundle_Resources.c b/CFBundle_Resources.c index e7e4172..b532e86 100644 --- a/CFBundle_Resources.c +++ b/CFBundle_Resources.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBundle_Resources.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -43,6 +43,7 @@ #include #include + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #include #include @@ -50,10 +51,6 @@ #include #endif -#if DEPLOYMENT_TARGET_MACOSX - -#endif - #if DEPLOYMENT_TARGET_WINDOWS #include #include @@ -79,10 +76,18 @@ CF_EXPORT void _CFBundleFlushCachesForURL(CFURLRef url) { } CF_EXPORT void _CFBundleFlushCaches(void) { } +CF_PRIVATE void _CFBundleFlushQueryTableCache(CFBundleRef bundle) { + __CFLock(&bundle->_queryLock); + if (bundle->_queryTable) { + CFDictionaryRemoveAllValues(bundle->_queryTable); + } + __CFUnlock(&bundle->_queryLock); +} + #pragma mark - #pragma mark Resource URL Lookup -static inline Boolean _CFIsResourceCommon(char *path, Boolean *isDir) { +static Boolean _CFIsResourceCommon(char *path, Boolean *isDir) { Boolean exists; SInt32 mode; if (_CFGetPathProperties(kCFAllocatorSystemDefault, path, &exists, &mode, NULL, NULL, NULL, NULL) == 0) { @@ -136,13 +141,13 @@ CF_PRIVATE void _CFBundleAppendResourceDir(CFMutableStringRef path, uint8_t vers CF_EXPORT CFURLRef CFBundleCopyResourceURL(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) { if (!bundle) return NULL; - CFURLRef result = (CFURLRef) _CFBundleCopyFindResources(bundle, NULL, NULL, resourceName, resourceType, subDirName, NULL, NO, NO, NULL); + CFURLRef result = (CFURLRef) _CFBundleCopyFindResources(bundle, NULL, NULL, resourceName, resourceType, subDirName, NULL, false, false, NULL); return result; } CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfType(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName) { if (!bundle) return CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFArrayRef result = (CFArrayRef) _CFBundleCopyFindResources(bundle, NULL, NULL, NULL, resourceType, subDirName, NULL, YES, NO, NULL); + CFArrayRef result = (CFArrayRef) _CFBundleCopyFindResources(bundle, NULL, NULL, NULL, resourceType, subDirName, NULL, true, false, NULL); return result; } @@ -152,7 +157,7 @@ CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStr CF_EXPORT CFURLRef CFBundleCopyResourceURLForLocalization(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) { if (!bundle) return NULL; - CFURLRef result = (CFURLRef) _CFBundleCopyFindResources(bundle, NULL, NULL, resourceName, resourceType, subDirName, localizationName, NO, YES, NULL); + CFURLRef result = (CFURLRef) _CFBundleCopyFindResources(bundle, NULL, NULL, resourceName, resourceType, subDirName, localizationName, false, true, NULL); return result; } @@ -162,7 +167,7 @@ CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bund CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeForLocalization(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) { if (!bundle) return CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFArrayRef result = (CFArrayRef) _CFBundleCopyFindResources(bundle, NULL, NULL, NULL, resourceType, subDirName, localizationName, YES, YES, NULL); + CFArrayRef result = (CFArrayRef) _CFBundleCopyFindResources(bundle, NULL, NULL, NULL, resourceType, subDirName, localizationName, true, true, NULL); return result; } @@ -176,7 +181,7 @@ CF_EXPORT CFURLRef CFBundleCopyResourceURLInDirectory(CFURLRef bundleURL, CFStri newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, buff, strlen((char *)buff), true); if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL); if (_CFBundleCouldBeBundle(newURL)) { - result = (CFURLRef) _CFBundleCopyFindResources(NULL, bundleURL, NULL, resourceName, resourceType, subDirName, NULL, NO, NO, NULL); + result = (CFURLRef) _CFBundleCopyFindResources(NULL, bundleURL, NULL, resourceName, resourceType, subDirName, NULL, false, false, NULL); } if (newURL) CFRelease(newURL); return result; @@ -192,965 +197,13 @@ CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeInDirectory(CFURLRef bundleUR newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, buff, strlen((char *)buff), true); if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL); if (_CFBundleCouldBeBundle(newURL)) { - array = (CFArrayRef) _CFBundleCopyFindResources(NULL, bundleURL, NULL, NULL, resourceType, subDirName, NULL, YES, NO, NULL); + array = (CFArrayRef) _CFBundleCopyFindResources(NULL, bundleURL, NULL, NULL, resourceType, subDirName, NULL, true, false, NULL); } if (newURL) CFRelease(newURL); return array; } #pragma mark - -#pragma mark Lanaguages and Locales - -// string, with groups of 6 characters being 1 element in the array of locale abbreviations -const char * __CFBundleLocaleAbbreviationsArray = - "en_US\0" "fr_FR\0" "en_GB\0" "de_DE\0" "it_IT\0" "nl_NL\0" "nl_BE\0" "sv_SE\0" - "es_ES\0" "da_DK\0" "pt_PT\0" "fr_CA\0" "nb_NO\0" "he_IL\0" "ja_JP\0" "en_AU\0" - "ar\0\0\0\0" "fi_FI\0" "fr_CH\0" "de_CH\0" "el_GR\0" "is_IS\0" "mt_MT\0" "el_CY\0" - "tr_TR\0" "hr_HR\0" "nl_NL\0" "nl_BE\0" "en_CA\0" "en_CA\0" "pt_PT\0" "nb_NO\0" - "da_DK\0" "hi_IN\0" "ur_PK\0" "tr_TR\0" "it_CH\0" "en\0\0\0\0" "\0\0\0\0\0\0" "ro_RO\0" - "grc\0\0\0" "lt_LT\0" "pl_PL\0" "hu_HU\0" "et_EE\0" "lv_LV\0" "se\0\0\0\0" "fo_FO\0" - "fa_IR\0" "ru_RU\0" "ga_IE\0" "ko_KR\0" "zh_CN\0" "zh_TW\0" "th_TH\0" "\0\0\0\0\0\0" - "cs_CZ\0" "sk_SK\0" "\0\0\0\0\0\0" "hu_HU\0" "bn\0\0\0\0" "be_BY\0" "uk_UA\0" "\0\0\0\0\0\0" - "el_GR\0" "sr_CS\0" "sl_SI\0" "mk_MK\0" "hr_HR\0" "\0\0\0\0\0\0" "de_DE\0" "pt_BR\0" - "bg_BG\0" "ca_ES\0" "\0\0\0\0\0\0" "gd\0\0\0\0" "gv\0\0\0\0" "br\0\0\0\0" "iu_CA\0" "cy\0\0\0\0" - "en_CA\0" "ga_IE\0" "en_CA\0" "dz_BT\0" "hy_AM\0" "ka_GE\0" "es_XL\0" "es_ES\0" - "to_TO\0" "pl_PL\0" "ca_ES\0" "fr\0\0\0\0" "de_AT\0" "es_XL\0" "gu_IN\0" "pa\0\0\0\0" - "ur_IN\0" "vi_VN\0" "fr_BE\0" "uz_UZ\0" "en_SG\0" "nn_NO\0" "af_ZA\0" "eo\0\0\0\0" - "mr_IN\0" "bo\0\0\0\0" "ne_NP\0" "kl\0\0\0\0" "en_IE\0"; - -#define NUM_LOCALE_ABBREVIATIONS 109 -#define LOCALE_ABBREVIATION_LENGTH 6 - -static const char * const __CFBundleLanguageNamesArray[] = { - "English", "French", "German", "Italian", "Dutch", "Swedish", "Spanish", "Danish", - "Portuguese", "Norwegian", "Hebrew", "Japanese", "Arabic", "Finnish", "Greek", "Icelandic", - "Maltese", "Turkish", "Croatian", "Chinese", "Urdu", "Hindi", "Thai", "Korean", - "Lithuanian", "Polish", "Hungarian", "Estonian", "Latvian", "Sami", "Faroese", "Farsi", - "Russian", "Chinese", "Dutch", "Irish", "Albanian", "Romanian", "Czech", "Slovak", - "Slovenian", "Yiddish", "Serbian", "Macedonian", "Bulgarian", "Ukrainian", "Byelorussian", "Uzbek", - "Kazakh", "Azerbaijani", "Azerbaijani", "Armenian", "Georgian", "Moldavian", "Kirghiz", "Tajiki", - "Turkmen", "Mongolian", "Mongolian", "Pashto", "Kurdish", "Kashmiri", "Sindhi", "Tibetan", - "Nepali", "Sanskrit", "Marathi", "Bengali", "Assamese", "Gujarati", "Punjabi", "Oriya", - "Malayalam", "Kannada", "Tamil", "Telugu", "Sinhalese", "Burmese", "Khmer", "Lao", - "Vietnamese", "Indonesian", "Tagalog", "Malay", "Malay", "Amharic", "Tigrinya", "Oromo", - "Somali", "Swahili", "Kinyarwanda", "Rundi", "Nyanja", "Malagasy", "Esperanto", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", - "Welsh", "Basque", "Catalan", "Latin", "Quechua", "Guarani", "Aymara", "Tatar", - "Uighur", "Dzongkha", "Javanese", "Sundanese", "Galician", "Afrikaans", "Breton", "Inuktitut", - "Scottish", "Manx", "Irish", "Tongan", "Greek", "Greenlandic", "Azerbaijani", "Nynorsk" -}; - -#define NUM_LANGUAGE_NAMES 152 -#define LANGUAGE_NAME_LENGTH 13 - -// string, with groups of 3 characters being 1 element in the array of abbreviations -const char * __CFBundleLanguageAbbreviationsArray = - "en\0" "fr\0" "de\0" "it\0" "nl\0" "sv\0" "es\0" "da\0" - "pt\0" "nb\0" "he\0" "ja\0" "ar\0" "fi\0" "el\0" "is\0" - "mt\0" "tr\0" "hr\0" "zh\0" "ur\0" "hi\0" "th\0" "ko\0" - "lt\0" "pl\0" "hu\0" "et\0" "lv\0" "se\0" "fo\0" "fa\0" - "ru\0" "zh\0" "nl\0" "ga\0" "sq\0" "ro\0" "cs\0" "sk\0" - "sl\0" "yi\0" "sr\0" "mk\0" "bg\0" "uk\0" "be\0" "uz\0" - "kk\0" "az\0" "az\0" "hy\0" "ka\0" "mo\0" "ky\0" "tg\0" - "tk\0" "mn\0" "mn\0" "ps\0" "ku\0" "ks\0" "sd\0" "bo\0" - "ne\0" "sa\0" "mr\0" "bn\0" "as\0" "gu\0" "pa\0" "or\0" - "ml\0" "kn\0" "ta\0" "te\0" "si\0" "my\0" "km\0" "lo\0" - "vi\0" "id\0" "tl\0" "ms\0" "ms\0" "am\0" "ti\0" "om\0" - "so\0" "sw\0" "rw\0" "rn\0" "\0\0\0" "mg\0" "eo\0" "\0\0\0" - "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" - "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" - "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" - "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" "\0\0\0" - "cy\0" "eu\0" "ca\0" "la\0" "qu\0" "gn\0" "ay\0" "tt\0" - "ug\0" "dz\0" "jv\0" "su\0" "gl\0" "af\0" "br\0" "iu\0" - "gd\0" "gv\0" "ga\0" "to\0" "el\0" "kl\0" "az\0" "nn\0"; - -#define NUM_LANGUAGE_ABBREVIATIONS 152 -#define LANGUAGE_ABBREVIATION_LENGTH 3 - -#if defined(__CONSTANT_CFSTRINGS__) - -// These are not necessarily common localizations per se, but localizations for which the full language name is still in common use. -// These are used to provide a fast path for it (other localizations usually use the abbreviation, which is even faster). -static CFStringRef const __CFBundleCommonLanguageNamesArray[] = {CFSTR("English"), CFSTR("French"), CFSTR("German"), CFSTR("Italian"), CFSTR("Dutch"), CFSTR("Spanish"), CFSTR("Japanese")}; -static CFStringRef const __CFBundleCommonLanguageAbbreviationsArray[] = {CFSTR("en"), CFSTR("fr"), CFSTR("de"), CFSTR("it"), CFSTR("nl"), CFSTR("es"), CFSTR("ja")}; - -#define NUM_COMMON_LANGUAGE_NAMES 7 - -#endif /* __CONSTANT_CFSTRINGS__ */ - -static const SInt32 __CFBundleScriptCodesArray[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 4, 0, 6, 0, - 0, 0, 0, 2, 4, 9, 21, 3, 29, 29, 29, 29, 29, 0, 0, 4, - 7, 25, 0, 0, 0, 0, 29, 29, 0, 5, 7, 7, 7, 7, 7, 7, - 7, 7, 4, 24, 23, 7, 7, 7, 7, 27, 7, 4, 4, 4, 4, 26, - 9, 9, 9, 13, 13, 11, 10, 12, 17, 16, 14, 15, 18, 19, 20, 22, - 30, 0, 0, 0, 4, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 7, 4, 26, 0, 0, 0, 0, 0, 28, - 0, 0, 0, 0, 6, 0, 0, 0 -}; - -static const CFStringEncoding __CFBundleStringEncodingsArray[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 4, 0, 6, 37, - 0, 35, 36, 2, 4, 9, 21, 3, 29, 29, 29, 29, 29, 0, 37, 0x8C, - 7, 25, 0, 39, 0, 38, 29, 29, 36, 5, 7, 7, 7, 0x98, 7, 7, - 7, 7, 4, 24, 23, 7, 7, 7, 7, 27, 7, 4, 4, 4, 4, 26, - 9, 9, 9, 13, 13, 11, 10, 12, 17, 16, 14, 15, 18, 19, 20, 22, - 30, 0, 0, 0, 4, 28, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 39, 0, 0, 0, 0, 0, 0, 7, 4, 26, 0, 0, 0, 0, 39, 0xEC, - 39, 39, 40, 0, 6, 0, 0, 0 -}; - -static SInt32 _CFBundleGetLanguageCodeForLocalization(CFStringRef localizationName) { - SInt32 result = -1, i; - char buff[256]; - CFIndex length = CFStringGetLength(localizationName); - if (length >= LANGUAGE_ABBREVIATION_LENGTH - 1 && length <= 255 && CFStringGetCString(localizationName, buff, 255, kCFStringEncodingASCII)) { - buff[255] = '\0'; - for (i = 0; -1 == result && i < NUM_LANGUAGE_NAMES; i++) { - if (0 == strcmp(buff, __CFBundleLanguageNamesArray[i])) result = i; - } - if (0 == strcmp(buff, "zh_TW") || 0 == strcmp(buff, "zh-Hant")) result = 19; else if (0 == strcmp(buff, "zh_CN") || 0 == strcmp(buff, "zh-Hans")) result = 33; // hack for mixed-up Chinese language codes - if (-1 == result && (length == LANGUAGE_ABBREVIATION_LENGTH - 1 || !isalpha(buff[LANGUAGE_ABBREVIATION_LENGTH - 1]))) { - buff[LANGUAGE_ABBREVIATION_LENGTH - 1] = '\0'; - if ('n' == buff[0] && 'o' == buff[1]) result = 9; // hack for Norwegian - for (i = 0; -1 == result && i < NUM_LANGUAGE_ABBREVIATIONS * LANGUAGE_ABBREVIATION_LENGTH; i += LANGUAGE_ABBREVIATION_LENGTH) { - if (buff[0] == *(__CFBundleLanguageAbbreviationsArray + i + 0) && buff[1] == *(__CFBundleLanguageAbbreviationsArray + i + 1)) result = i / LANGUAGE_ABBREVIATION_LENGTH; - } - } - } - return result; -} - -static CFStringRef _CFBundleCopyLanguageAbbreviationForLanguageCode(SInt32 languageCode) { - CFStringRef result = NULL; - if (0 <= languageCode && languageCode < NUM_LANGUAGE_ABBREVIATIONS) { - const char *languageAbbreviation = __CFBundleLanguageAbbreviationsArray + languageCode * LANGUAGE_ABBREVIATION_LENGTH; - if (languageAbbreviation && *languageAbbreviation != '\0') result = CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, languageAbbreviation, kCFStringEncodingASCII, kCFAllocatorNull); - } - return result; -} - -CF_INLINE CFStringRef _CFBundleCopyLanguageNameForLanguageCode(SInt32 languageCode) { - CFStringRef result = NULL; - if (0 <= languageCode && languageCode < NUM_LANGUAGE_NAMES) { - const char *languageName = __CFBundleLanguageNamesArray[languageCode]; - if (languageName && *languageName != '\0') result = CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, languageName, kCFStringEncodingASCII, kCFAllocatorNull); - } - return result; -} - -CF_INLINE CFStringRef _CFBundleCopyLanguageAbbreviationForLocalization(CFStringRef localizationName) { - CFStringRef result = NULL; - SInt32 languageCode = _CFBundleGetLanguageCodeForLocalization(localizationName); - if (languageCode >= 0) { - result = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode); - } else { - CFIndex length = CFStringGetLength(localizationName); - if (length == LANGUAGE_ABBREVIATION_LENGTH - 1 || (length > LANGUAGE_ABBREVIATION_LENGTH - 1 && CFStringGetCharacterAtIndex(localizationName, LANGUAGE_ABBREVIATION_LENGTH - 1) == '_')) { - result = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, localizationName, CFRangeMake(0, LANGUAGE_ABBREVIATION_LENGTH - 1)); - } - } - return result; -} - -CF_INLINE CFStringRef _CFBundleCopyModifiedLocalization(CFStringRef localizationName) { - CFMutableStringRef result = NULL; - CFIndex length = CFStringGetLength(localizationName); - if (length >= 4) { - UniChar c = CFStringGetCharacterAtIndex(localizationName, 2); - if ('-' == c || '_' == c) { - result = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, length, localizationName); - CFStringReplace(result, CFRangeMake(2, 1), ('-' == c) ? CFSTR("_") : CFSTR("-")); - } - } - return result; -} - -CF_INLINE CFStringRef _CFBundleCopyLanguageNameForLocalization(CFStringRef localizationName) { - CFStringRef result = NULL; - SInt32 languageCode = _CFBundleGetLanguageCodeForLocalization(localizationName); - if (languageCode >= 0) { - result = _CFBundleCopyLanguageNameForLanguageCode(languageCode); - } else { - result = (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, localizationName); - } - return result; -} - -static SInt32 _CFBundleGetLanguageCodeForRegionCode(SInt32 regionCode) { - SInt32 result = -1, i; - if (52 == regionCode) { // hack for mixed-up Chinese language codes - result = 33; - } else if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) { - const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH; - if (localeAbbreviation && *localeAbbreviation != '\0') { - for (i = 0; -1 == result && i < NUM_LANGUAGE_ABBREVIATIONS * LANGUAGE_ABBREVIATION_LENGTH; i += LANGUAGE_ABBREVIATION_LENGTH) { - if (localeAbbreviation[0] == *(__CFBundleLanguageAbbreviationsArray + i + 0) && localeAbbreviation[1] == *(__CFBundleLanguageAbbreviationsArray + i + 1)) result = i / LANGUAGE_ABBREVIATION_LENGTH; - } - } - } - return result; -} - -static SInt32 _CFBundleGetRegionCodeForLanguageCode(SInt32 languageCode) { - SInt32 result = -1, i; - if (19 == languageCode) { // hack for mixed-up Chinese language codes - result = 53; - } else if (0 <= languageCode && languageCode < NUM_LANGUAGE_ABBREVIATIONS) { - const char *languageAbbreviation = __CFBundleLanguageAbbreviationsArray + languageCode * LANGUAGE_ABBREVIATION_LENGTH; - if (languageAbbreviation && *languageAbbreviation != '\0') { - for (i = 0; -1 == result && i < NUM_LOCALE_ABBREVIATIONS * LOCALE_ABBREVIATION_LENGTH; i += LOCALE_ABBREVIATION_LENGTH) { - if (*(__CFBundleLocaleAbbreviationsArray + i + 0) == languageAbbreviation[0] && *(__CFBundleLocaleAbbreviationsArray + i + 1) == languageAbbreviation[1]) result = i / LOCALE_ABBREVIATION_LENGTH; - } - } - } - if (25 == result) result = 68; - if (28 == result) result = 82; - return result; -} - -static SInt32 _CFBundleGetRegionCodeForLocalization(CFStringRef localizationName) { - SInt32 result = -1, i; - char buff[LOCALE_ABBREVIATION_LENGTH]; - CFIndex length = CFStringGetLength(localizationName); - if (length >= LANGUAGE_ABBREVIATION_LENGTH - 1 && length <= LOCALE_ABBREVIATION_LENGTH - 1 && CFStringGetCString(localizationName, buff, LOCALE_ABBREVIATION_LENGTH, kCFStringEncodingASCII)) { - buff[LOCALE_ABBREVIATION_LENGTH - 1] = '\0'; - for (i = 0; -1 == result && i < NUM_LOCALE_ABBREVIATIONS * LOCALE_ABBREVIATION_LENGTH; i += LOCALE_ABBREVIATION_LENGTH) { - if (0 == strcmp(buff, __CFBundleLocaleAbbreviationsArray + i)) result = i / LOCALE_ABBREVIATION_LENGTH; - } - } - if (25 == result) result = 68; - if (28 == result) result = 82; - if (37 == result) result = 0; - if (-1 == result) { - SInt32 languageCode = _CFBundleGetLanguageCodeForLocalization(localizationName); - result = _CFBundleGetRegionCodeForLanguageCode(languageCode); - } - return result; -} - -CF_PRIVATE CFStringRef _CFBundleCopyLocaleAbbreviationForRegionCode(SInt32 regionCode) { - CFStringRef result = NULL; - if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) { - const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH; - if (localeAbbreviation && *localeAbbreviation != '\0') { - result = CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, localeAbbreviation, kCFStringEncodingASCII, kCFAllocatorNull); - } - } - return result; -} - -CF_EXPORT Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName, SInt32 *languageCode, SInt32 *regionCode, SInt32 *scriptCode, CFStringEncoding *stringEncoding) { - Boolean retval = false; - SInt32 language = -1, region = -1, script = 0; - CFStringEncoding encoding = kCFStringEncodingMacRoman; - if (!localizationName) { - CFBundleRef mainBundle = CFBundleGetMainBundle(); - CFArrayRef languages = NULL; - if (mainBundle) { - languages = _CFBundleGetLanguageSearchList(mainBundle); - if (languages) CFRetain(languages); - } - if (!languages) languages = _CFBundleCopyUserLanguages(); - if (languages && CFArrayGetCount(languages) > 0) localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); - } - if (localizationName) { - LangCode langCode = -1; - RegionCode regCode = -1; - ScriptCode scrCode = 0; - CFStringEncoding enc = kCFStringEncodingMacRoman; - retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, ®Code, &scrCode, &enc); - if (retval) { - language = langCode; - region = regCode; - script = scrCode; - encoding = enc; - } - } - if (!retval) { - if (localizationName) { - language = _CFBundleGetLanguageCodeForLocalization(localizationName); - region = _CFBundleGetRegionCodeForLocalization(localizationName); - } else { - _CFBundleGetLanguageAndRegionCodes(&language, ®ion); - } - if ((language < 0 || language > (int)(sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32))) && region != -1) language = _CFBundleGetLanguageCodeForRegionCode(region); - if (region == -1 && language != -1) region = _CFBundleGetRegionCodeForLanguageCode(language); - if (language >= 0 && language < (int)(sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32))) { - script = __CFBundleScriptCodesArray[language]; - } - if (language >= 0 && language < (int)(sizeof(__CFBundleStringEncodingsArray)/sizeof(CFStringEncoding))) { - encoding = __CFBundleStringEncodingsArray[language]; - } - retval = (language != -1 || region != -1); - } - if (languageCode) *languageCode = language; - if (regionCode) *regionCode = region; - if (scriptCode) *scriptCode = script; - if (stringEncoding) *stringEncoding = encoding; - return retval; -} - -CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SInt32 regionCode, SInt32 scriptCode, CFStringEncoding stringEncoding) { - CFStringRef localizationName = NULL; - if (!localizationName) localizationName = _CFBundleCopyLocaleAbbreviationForRegionCode(regionCode); -#if DEPLOYMENT_TARGET_MACOSX - if (!localizationName && 0 <= languageCode && languageCode < SHRT_MAX) localizationName = CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(kCFAllocatorSystemDefault, (LangCode)languageCode, (RegionCode)-1); -#endif - if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode); - if (!localizationName) { - SInt32 language = -1, scriptLanguage = -1, encodingLanguage = -1; - unsigned int i; - for (i = 0; language == -1 && i < (sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32)); i++) { - if (__CFBundleScriptCodesArray[i] == scriptCode && __CFBundleStringEncodingsArray[i] == stringEncoding) language = i; - } - for (i = 0; scriptLanguage == -1 && i < (sizeof(__CFBundleScriptCodesArray)/sizeof(SInt32)); i++) { - if (__CFBundleScriptCodesArray[i] == scriptCode) scriptLanguage = i; - } - for (i = 0; encodingLanguage == -1 && i < (sizeof(__CFBundleStringEncodingsArray)/sizeof(CFStringEncoding)); i++) { - if (__CFBundleStringEncodingsArray[i] == stringEncoding) encodingLanguage = i; - } - localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(language); - if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(encodingLanguage); - if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(scriptLanguage); - } - return localizationName; -} - - -static Boolean CFBundleAllowMixedLocalizations(void) { - static Boolean allowMixed = false; - static dispatch_once_t once = 0; - dispatch_once(&once, ^{ - CFBundleRef mainBundle = CFBundleGetMainBundle(); - CFDictionaryRef infoDict = mainBundle ? CFBundleGetInfoDictionary(mainBundle) : NULL; - CFTypeRef allowMixedValue = infoDict ? CFDictionaryGetValue(infoDict, _kCFBundleAllowMixedLocalizationsKey) : NULL; - if (allowMixedValue) { - CFTypeID typeID = CFGetTypeID(allowMixedValue); - if (typeID == CFBooleanGetTypeID()) { - allowMixed = CFBooleanGetValue((CFBooleanRef)allowMixedValue); - } else if (typeID == CFStringGetTypeID()) { - allowMixed = (CFStringCompare((CFStringRef)allowMixedValue, CFSTR("true"), kCFCompareCaseInsensitive) == kCFCompareEqualTo || CFStringCompare((CFStringRef)allowMixedValue, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo); - } else if (typeID == CFNumberGetTypeID()) { - SInt32 val = 0; - if (CFNumberGetValue((CFNumberRef)allowMixedValue, kCFNumberSInt32Type, &val)) allowMixed = (val != 0); - } - } - }); - return allowMixed; -} - -// Get a list of localizations for a particular resource directory URL. Uncached. Does not include any predefined localizations from an Info.plist. -static CFArrayRef _CFBundleCopyURLLocalizations(CFAllocatorRef allocator, CFURLRef url) { - __block CFMutableArrayRef result = NULL; - CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url); - CFStringRef directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - CFRelease(absoluteURL); - - CFStringRef lproj = _CFBundleLprojExtensionWithDot; - CFIndex lprojLen = CFStringGetLength(lproj); - - _CFIterateDirectory(directoryPath, ^Boolean(CFStringRef fileName, uint8_t fileType) { - // See if the fileName ends in .lproj - // The comparison starts at the end of the fileName, backed up by the length of .lproj - CFIndex fileNameLen = CFStringGetLength(fileName); - if (fileNameLen > lprojLen && CFStringCompareWithOptions(fileName, lproj, CFRangeMake(fileNameLen - lprojLen, lprojLen), 0) == kCFCompareEqualTo) { - // Chop off the .lproj part before creating a string - CFStringRef lprojDirectoryName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fileName, CFRangeMake(0, fileNameLen - lprojLen)); - if (!result) result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(result, lprojDirectoryName); - CFRelease(lprojDirectoryName); - } - return true; - }); - - CFRelease(directoryPath); - return (CFArrayRef)result; -} - -static Boolean _CFBundleTryOnePreferredLprojNameInURL(CFAllocatorRef alloc, CFArrayRef localizations, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage); - -CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) { - CFArrayRef result = NULL; - - __CFSpinLock(&bundle->_lock); - if (bundle->_lookedForLocalizations) { - result = (CFArrayRef)CFRetain(bundle->_localizations); - __CFSpinUnlock(&bundle->_lock); - return result; - } - __CFSpinUnlock(&bundle->_lock); - - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - if (infoDict) { - CFArrayRef predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); - if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) != CFArrayGetTypeID()) { - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, kCFBundleLocalizationsKey); - } else if (predefinedLocalizations) { - // Some people put bad things inside this array =( - CFMutableArrayRef realPredefinedLocalizations = CFArrayCreateMutable(CFGetAllocator(bundle), CFArrayGetCount(predefinedLocalizations), &kCFTypeArrayCallBacks); - for (CFIndex i = 0; i < CFArrayGetCount(predefinedLocalizations); i++) { - CFStringRef oneEntry = CFArrayGetValueAtIndex(predefinedLocalizations, i); - if (CFGetTypeID(oneEntry) == CFStringGetTypeID() && CFStringGetLength(oneEntry) > 0) { - CFArrayAppendValue(realPredefinedLocalizations, oneEntry); - } - } - result = CFArrayCreateCopy(CFGetAllocator(bundle), realPredefinedLocalizations); - CFRelease(realPredefinedLocalizations); - } - } - - CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); - if (resourcesURL) { - CFArrayRef lprojDirectoriesInResources = _CFBundleCopyURLLocalizations(CFGetAllocator(bundle), resourcesURL); - if (lprojDirectoriesInResources) { - if (result) { - // Append the lproj result to the predefined localization array - CFMutableArrayRef newResult = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, result); - CFRelease(result); - CFArrayAppendArray(newResult, lprojDirectoriesInResources, CFRangeMake(0, CFArrayGetCount(lprojDirectoriesInResources))); - CFRelease(lprojDirectoriesInResources); - result = newResult; - } else { - result = lprojDirectoriesInResources; - } - } - CFRelease(resourcesURL); - } - - CFStringRef developmentLocalization = CFBundleGetDevelopmentRegion(bundle); - if (result) { - if (developmentLocalization) { - CFRange entireRange = CFRangeMake(0, CFArrayGetCount(result)); - if (CFArrayContainsValue(result, entireRange, _CFBundleBaseDirectory)) { - // Base.lproj contains localizations for the development region. Insert the devleopment region into the existing array if there isn't already a match so that resource lookup doesn't default to another language. - CFMutableArrayRef tempArray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - if (tempArray) { - if (!_CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, result, developmentLocalization, tempArray, false) && CFArrayGetCount(tempArray) == 0) { - CFMutableArrayRef newResult = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, result); - CFRelease(result); - CFArrayAppendValue(newResult, developmentLocalization); - result = newResult; - } - CFRelease(tempArray); - } - } - } - } else { - if (developmentLocalization) { - result = CFArrayCreate(CFGetAllocator(bundle), (const void **)&developmentLocalization, 1, &kCFTypeArrayCallBacks); - } else { - result = CFArrayCreate(CFGetAllocator(bundle), NULL, 0, &kCFTypeArrayCallBacks); - } - } - - // Cache the result. - __CFSpinLock(&bundle->_lock); - if (bundle->_localizations) CFRelease(bundle->_localizations); - bundle->_localizations = (CFArrayRef)CFRetain(result); - bundle->_lookedForLocalizations = true; - __CFSpinUnlock(&bundle->_lock); - - return result; -} - -CFArrayRef CFBundleCopyLocalizationsForURL(CFURLRef url) { - CFArrayRef result = NULL; - CFBundleRef bundle = CFBundleCreate(kCFAllocatorSystemDefault, url); - CFStringRef devLang = NULL; - if (bundle) { - result = CFBundleCopyBundleLocalizations(bundle); - CFRelease(bundle); - } else { - CFDictionaryRef infoDict = _CFBundleCopyInfoDictionaryInExecutable(url); - if (infoDict) { - CFArrayRef predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); - if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) == CFArrayGetTypeID()) result = (CFArrayRef)CFRetain(predefinedLocalizations); - if (!result) { - devLang = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); - if (devLang && (CFGetTypeID(devLang) == CFStringGetTypeID() && CFStringGetLength(devLang) > 0)) result = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&devLang, 1, &kCFTypeArrayCallBacks); - } - CFRelease(infoDict); - } - } - return result; -} - -extern void *__CFAppleLanguages; - - -CF_PRIVATE CFArrayRef _CFBundleCopyUserLanguages() { - static CFArrayRef _CFBundleUserLanguages = NULL; - static dispatch_once_t once = 0; - dispatch_once(&once, ^{ - CFArrayRef preferencesArray = NULL; - if (__CFAppleLanguages) { - CFDataRef data; - CFIndex length = strlen((const char *)__CFAppleLanguages); - if (length > 0) { - data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)__CFAppleLanguages, length, kCFAllocatorNull); - if (data) { - _CFBundleUserLanguages = (CFArrayRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL); - CFRelease(data); - } - } - } - if (!_CFBundleUserLanguages && preferencesArray) _CFBundleUserLanguages = (CFArrayRef)CFRetain(preferencesArray); - Boolean useEnglishAsBackstop = true; - // could perhaps read out of LANG environment variable - if (useEnglishAsBackstop && !_CFBundleUserLanguages) { - CFStringRef english = CFSTR("en"); - _CFBundleUserLanguages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&english, 1, &kCFTypeArrayCallBacks); - } - if (_CFBundleUserLanguages && CFGetTypeID(_CFBundleUserLanguages) != CFArrayGetTypeID()) { - CFRelease(_CFBundleUserLanguages); - _CFBundleUserLanguages = NULL; - } - if (preferencesArray) CFRelease(preferencesArray); - }); - - if (_CFBundleUserLanguages) { - CFRetain(_CFBundleUserLanguages); - return _CFBundleUserLanguages; - } else { - return NULL; - } -} - -CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 *regionCode) { - // an attempt to answer the question, "what language are we running in?" - // note that the question cannot be answered fully since it may depend on the bundle - SInt32 language = -1, region = -1; - CFBundleRef mainBundle = CFBundleGetMainBundle(); - CFArrayRef languages = NULL; - if (mainBundle) { - languages = _CFBundleGetLanguageSearchList(mainBundle); - if (languages) CFRetain(languages); - } - if (!languages) languages = _CFBundleCopyUserLanguages(); - if (languages && CFArrayGetCount(languages) > 0) { - CFStringRef localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); - Boolean retval = false; - LangCode langCode = -1; - RegionCode regCode = -1; - retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, ®Code, NULL, NULL); - if (retval) { - language = langCode; - region = regCode; - } - if (!retval) { - language = _CFBundleGetLanguageCodeForLocalization(localizationName); - region = _CFBundleGetRegionCodeForLocalization(localizationName); - } - } else { - language = 0; - region = 0; - } - if (language == -1 && region != -1) language = _CFBundleGetLanguageCodeForRegionCode(region); - if (region == -1 && language != -1) region = _CFBundleGetRegionCodeForLanguageCode(language); - if (languages) CFRelease(languages); - if (languageCode) *languageCode = language; - if (regionCode) *regionCode = region; -} - - - -static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) { - CFRange range = CFRangeMake(0, CFArrayGetCount(array)); - if (range.length == 0) return false; - - Boolean foundOne = false, specifiesScript = false; - CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL; - CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL; - - if (CFArrayContainsValue(array, range, curLangStr)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), curLangStr)) CFArrayAppendValue(lprojNames, curLangStr); - foundOne = true; - if (range.length == 1 || CFStringGetLength(curLangStr) <= 2) return foundOne; - } - if (range.length == 1 && CFArrayContainsValue(array, range, CFSTR("default"))) return foundOne; - -#if defined(__CONSTANT_CFSTRINGS__) - if (!altLangStr) { - CFIndex idx; - for (idx = 0; !altLangStr && idx < NUM_COMMON_LANGUAGE_NAMES; idx++) { - if (CFEqual(curLangStr, __CFBundleCommonLanguageAbbreviationsArray[idx])) altLangStr = __CFBundleCommonLanguageNamesArray[idx]; - else if (CFEqual(curLangStr, __CFBundleCommonLanguageNamesArray[idx])) altLangStr = __CFBundleCommonLanguageAbbreviationsArray[idx]; - } - } - if (foundOne && altLangStr) return foundOne; -#endif /* __CONSTANT_CFSTRINGS__ */ - - if (altLangStr && CFArrayContainsValue(array, range, altLangStr)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), altLangStr)) CFArrayAppendValue(lprojNames, altLangStr); - foundOne = true; - return foundOne; - } - - if (!altLangStr && (modifiedLangStr = _CFBundleCopyModifiedLocalization(curLangStr))) { - if (CFArrayContainsValue(array, range, modifiedLangStr)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), modifiedLangStr)) CFArrayAppendValue(lprojNames, modifiedLangStr); - foundOne = true; - } - } - - if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) { - if (CFArrayContainsValue(array, range, languageAbbreviation)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageAbbreviation)) CFArrayAppendValue(lprojNames, languageAbbreviation); - foundOne = true; - } - } - if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) { - if (CFArrayContainsValue(array, range, languageName)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName); - foundOne = true; - } - } - if (modifiedLangStr) CFRelease(modifiedLangStr); - if (languageAbbreviation) CFRelease(languageAbbreviation); - if (languageName) CFRelease(languageName); - if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier); - if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers); - if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation); - return foundOne; -} - -// localizations array must include both predefined and actual lproj localizations -static Boolean _CFBundleTryOnePreferredLprojNameInURL(CFAllocatorRef alloc, CFArrayRef localizations, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) { - CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL; - CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL; - Boolean foundOne = false, specifiesScript = false; - - if (!localizations) return false; - - CFRange localizationsRange = CFRangeMake(0, CFArrayGetCount(localizations)); - - // this use of contents is only checking for language strings - it could get the list of existing localizations and use that instead - if (CFArrayContainsValue(localizations, localizationsRange, curLangStr)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), curLangStr)) CFArrayAppendValue(lprojNames, curLangStr); - foundOne = true; - if (CFStringGetLength(curLangStr) <= 2) { - return foundOne; - } - } - -#if defined(__CONSTANT_CFSTRINGS__) - if (!altLangStr) { - CFIndex idx; - for (idx = 0; !altLangStr && idx < NUM_COMMON_LANGUAGE_NAMES; idx++) { - if (CFEqual(curLangStr, __CFBundleCommonLanguageAbbreviationsArray[idx])) altLangStr = __CFBundleCommonLanguageNamesArray[idx]; - else if (CFEqual(curLangStr, __CFBundleCommonLanguageNamesArray[idx])) altLangStr = __CFBundleCommonLanguageAbbreviationsArray[idx]; - } - } -#endif /* __CONSTANT_CFSTRINGS__ */ - if (foundOne && altLangStr) { - return foundOne; - } - if (altLangStr) { - if (CFArrayContainsValue(localizations, localizationsRange, altLangStr)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), altLangStr)) CFArrayAppendValue(lprojNames, altLangStr); - foundOne = true; - return foundOne; - } - } - - if (!altLangStr && (modifiedLangStr = _CFBundleCopyModifiedLocalization(curLangStr))) { - if (CFArrayContainsValue(localizations, localizationsRange, modifiedLangStr)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), modifiedLangStr)) CFArrayAppendValue(lprojNames, modifiedLangStr); - foundOne = true; - } - } - - - if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) { - if (CFArrayContainsValue(localizations, localizationsRange, languageAbbreviation)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageAbbreviation)) CFArrayAppendValue(lprojNames, languageAbbreviation); - foundOne = true; - } - } - if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) { - if (CFArrayContainsValue(localizations, localizationsRange, languageName)) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName); - foundOne = true; - } - } - if (modifiedLangStr) CFRelease(modifiedLangStr); - if (languageAbbreviation) CFRelease(languageAbbreviation); - if (languageName) CFRelease(languageName); - if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier); - if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers); - if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation); - return foundOne; -} - -static Boolean _CFBundleLocalizationsHaveCommonPrefix(CFStringRef loc1, CFStringRef loc2) { - Boolean result = false; - CFIndex length1 = CFStringGetLength(loc1), length2 = CFStringGetLength(loc2), idx; - if (length1 > 3 && length2 > 3) { - for (idx = 0; idx < length1 && idx < length2; idx++) { - UniChar c1 = CFStringGetCharacterAtIndex(loc1, idx), c2 = CFStringGetCharacterAtIndex(loc2, idx); - if (idx >= 2 && (c1 == '-' || c1 == '_') && (c2 == '-' || c2 == '_')) { - result = true; - break; - } else if (c1 != c2) { - break; - } - } - } - return result; -} - -static void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, CFArrayRef localizations, CFMutableArrayRef lprojNames, CFStringRef devLang) { - // This function will add zero, one or two elements to the lprojNames array. - // It examines the users preferred language list and the lproj directories inside the bundle directory. It picks the lproj directory that is highest on the users list. - // The users list can contain region names (like "en_US" for US English). In this case, if the region lproj exists, it will be added, and, if the region's associated language lproj exists that will be added. - - Boolean foundOne = false; - - // First check the main bundle. - if (!CFBundleAllowMixedLocalizations()) { - CFBundleRef mainBundle = CFBundleGetMainBundle(); - if (mainBundle) { - CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle); - if (mainBundleURL) { - if (!CFEqual(bundleURL, mainBundleURL)) { - // If there is a main bundle, and it isn't this one, try to use the language it prefers. - CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle); - if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) { - CFStringRef curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0); - foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, curLangStr, lprojNames, true); - } - } - CFRelease(mainBundleURL); - } - } - } - - if (!foundOne) { - // If we didn't find the main bundle's preferred language, look at the users' prefs again and find the best one. - CFArrayRef userLanguages = _CFBundleCopyUserLanguages(); - if (userLanguages) { - CFIndex count = CFArrayGetCount(userLanguages); - CFIndex idx, startIdx; - for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) { - CFStringRef curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx); - CFStringRef nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx + 1) : NULL; - if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) { - foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, curLangStr, lprojNames, false); - if (startIdx < 0) startIdx = idx; - } else if (startIdx >= 0 && startIdx <= idx) { - foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, curLangStr, lprojNames, false); - for (; !foundOne && startIdx <= idx; startIdx++) { - curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, startIdx); - foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, curLangStr, lprojNames, true); - } - startIdx = -1; - } else { - foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, curLangStr, lprojNames, true); - startIdx = -1; - } - } - } - // use development region and U.S. English as backstops - if (!foundOne && devLang) foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, devLang, lprojNames, true); - if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, CFSTR("en_US"), lprojNames, true); - if (userLanguages) CFRelease(userLanguages); - } -} - -static CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) { - uint8_t localVersion = 0; - CFDictionaryRef infoDict = _CFBundleCopyInfoDictionaryInDirectory(alloc, url, &localVersion); - - CFArrayRef predefinedLocalizations = NULL; - CFStringRef devLang = NULL; - if (infoDict) { - devLang = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); - if (devLang && (CFGetTypeID(devLang) != CFStringGetTypeID() || CFStringGetLength(devLang) == 0)) devLang = NULL; - - predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); - if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) != CFArrayGetTypeID()) { - predefinedLocalizations = NULL; - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, kCFBundleLocalizationsKey); - } - } - - CFURLRef resourcesURL = _CFBundleCopyResourcesDirectoryURLInDirectory(url, localVersion); - CFArrayRef localizations = _CFBundleCopyURLLocalizations(alloc, resourcesURL); - CFRelease(resourcesURL); - - if (predefinedLocalizations && localizations) { - CFMutableArrayRef newLocalizations = CFArrayCreateMutableCopy(alloc, 0, predefinedLocalizations); - CFArrayAppendArray(newLocalizations, localizations, CFRangeMake(0, CFArrayGetCount(localizations))); - CFRelease(localizations); - localizations = (CFArrayRef)newLocalizations; - } else if (predefinedLocalizations) { - localizations = (CFArrayRef)CFRetain(predefinedLocalizations); - } else if (!localizations) { - localizations = CFArrayCreate(alloc, NULL, 0, &kCFTypeArrayCallBacks); - } - - CFMutableArrayRef langs = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks); - _CFBundleAddPreferredLprojNamesInDirectory(alloc, url, localizations, langs, devLang); - CFRelease(localizations); - - if (devLang && CFArrayGetFirstIndexOfValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), devLang) < 0) CFArrayAppendValue(langs, devLang); - - // Total backstop behavior to avoid having an empty array. - if (CFArrayGetCount(langs) == 0) CFArrayAppendValue(langs, CFSTR("en")); - - if (infoDict) CFRelease(infoDict); - if (version) *version = localVersion; - return langs; -} - -static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray, Boolean considerMain) { - CFMutableArrayRef lprojNames = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - Boolean foundOne = false, releasePrefArray = false; - CFIndex idx, count, startIdx; - - if (considerMain && !CFBundleAllowMixedLocalizations()) { - CFBundleRef mainBundle = CFBundleGetMainBundle(); - if (mainBundle) { - // If there is a main bundle, try to use the language it prefers. - CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle); - if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0), lprojNames, true); - } - } - - if (!foundOne) { - CFStringRef curLangStr, nextLangStr; - if (!prefArray) { - prefArray = _CFBundleCopyUserLanguages(); - if (prefArray) releasePrefArray = true; - } - count = (prefArray ? CFArrayGetCount(prefArray) : 0); - for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) { - curLangStr = (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx); - nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx + 1) : NULL; - if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) { - foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, false); - if (startIdx < 0) startIdx = idx; - } else if (startIdx >= 0 && startIdx <= idx) { - foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, false); - for (; !foundOne && startIdx <= idx; startIdx++) { - curLangStr = (CFStringRef)CFArrayGetValueAtIndex(prefArray, startIdx); - foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, true); - } - startIdx = -1; - } else { - foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, true); - startIdx = -1; - } - } - // use U.S. English as backstop - if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, CFSTR("en_US"), lprojNames, true); - // use random entry as backstop - if (!foundOne && CFArrayGetCount(locArray) > 0) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(locArray, 0), lprojNames, true); - } - if (CFArrayGetCount(lprojNames) == 0) { - // Total backstop behavior to avoid having an empty array. - CFArrayAppendValue(lprojNames, CFSTR("en")); - } - if (releasePrefArray) { - CFRelease(prefArray); - } - return lprojNames; -} - -CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray) { - return _CFBundleCopyLocalizationsForPreferences(locArray, prefArray, false); -} - -CF_EXPORT CFArrayRef CFBundleCopyPreferredLocalizationsFromArray(CFArrayRef locArray) { - return _CFBundleCopyLocalizationsForPreferences(locArray, NULL, true); -} - -static CFStringRef _defaultLocalization = NULL; - -CF_EXPORT void _CFBundleSetDefaultLocalization(CFStringRef localizationName) { - CFStringRef newLocalization = localizationName ? (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, localizationName) : NULL; - if (_defaultLocalization) CFRelease(_defaultLocalization); - _defaultLocalization = newLocalization; -} - -CF_EXPORT CFArrayRef _CFBundleGetLanguageSearchList(CFBundleRef bundle) { - if (!bundle->_searchLanguages) { - CFMutableArrayRef langs = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFStringRef devLang = CFBundleGetDevelopmentRegion(bundle); - -#if DEPLOYMENT_TARGET_WINDOWS - if (_defaultLocalization) CFArrayAppendValue(langs, _defaultLocalization); -#endif - // includes predefined localizations - CFArrayRef localizationsForBundle = CFBundleCopyBundleLocalizations(bundle); - - _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, localizationsForBundle, langs, devLang); - - if (CFArrayGetCount(langs) == 0) { - // If the user does not prefer any of our languages, and devLang is not present, try English - _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, localizationsForBundle, langs, CFSTR("en_US")); - } - - if (CFArrayGetCount(langs) == 0) { - // if none of the preferred localizations are present, fall back on a random localization that is present - if (localizationsForBundle && CFArrayGetCount(localizationsForBundle) > 0) { - CFStringRef firstLocalization = (CFStringRef)CFArrayGetValueAtIndex(localizationsForBundle, 0); - _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, localizationsForBundle, langs, firstLocalization); - } - } - - if (devLang && !CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), devLang)) { - // Make sure that devLang is on the list as a fallback for individual resources that are not present - CFArrayAppendValue(langs, devLang); - } else if (!devLang) { - if (localizationsForBundle) { - CFStringRef en_US = CFSTR("en_US"), en = CFSTR("en"), English = CFSTR("English"); - CFRange range = CFRangeMake(0, CFArrayGetCount(localizationsForBundle)); - if (CFArrayContainsValue(localizationsForBundle, range, en)) { - if (!CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), en)) CFArrayAppendValue(langs, en); - } else if (CFArrayContainsValue(localizationsForBundle, range, English)) { - if (!CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), English)) CFArrayAppendValue(langs, English); - } else if (CFArrayContainsValue(localizationsForBundle, range, en_US)) { - if (!CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), en_US)) CFArrayAppendValue(langs, en_US); - } - } - } - - if (localizationsForBundle) CFRelease(localizationsForBundle); - - if (CFArrayGetCount(langs) == 0) { - // Total backstop behavior to avoid having an empty array. - if (_defaultLocalization) { - CFArrayAppendValue(langs, _defaultLocalization); - } else { - CFArrayAppendValue(langs, CFSTR("en")); - } - } - if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)langs, (void * volatile *)&(bundle->_searchLanguages))) CFRelease(langs); - } - return bundle->_searchLanguages; -} - -#pragma mark - - -CF_EXPORT Boolean _CFBundleURLLooksLikeBundle(CFURLRef url) { - Boolean result = false; - CFBundleRef bundle = _CFBundleCreateIfLooksLikeBundle(kCFAllocatorSystemDefault, url); - if (bundle) { - result = true; - CFRelease(bundle); - } - return result; -} #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS // Note that subDirName is expected to be the string for a URL @@ -1256,65 +309,9 @@ CF_PRIVATE uint8_t _CFBundleGetBundleVersionForURL(CFURLRef url) { #pragma mark - #pragma mark Platforms -static void _CFBundleCheckSupportedPlatform(CFMutableArrayRef mutableArray, UniChar *buff, CFIndex startLen, CFStringRef platformName, CFStringRef platformIdentifier) { - CFIndex buffLen = startLen, platformLen = CFStringGetLength(platformName), extLen = CFStringGetLength(_CFBundleInfoExtension); - CFMutableStringRef str; - Boolean isDir; - if (buffLen + platformLen + extLen < CFMaxPathSize) { - CFStringGetCharacters(platformName, CFRangeMake(0, platformLen), buff + buffLen); - buffLen += platformLen; - buff[buffLen++] = (UniChar)'.'; - CFStringGetCharacters(_CFBundleInfoExtension, CFRangeMake(0, extLen), buff + buffLen); - buffLen += extLen; - str = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - CFStringAppendCharacters(str, buff, buffLen); - if (_CFIsResourceAtPath(str, &isDir) && !isDir && CFArrayGetFirstIndexOfValue(mutableArray, CFRangeMake(0, CFArrayGetCount(mutableArray)), platformIdentifier) < 0) CFArrayAppendValue(mutableArray, platformIdentifier); - CFRelease(str); - } -} - CF_EXPORT CFArrayRef _CFBundleGetSupportedPlatforms(CFBundleRef bundle) { - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - CFArrayRef platformArray = infoDict ? (CFArrayRef)CFDictionaryGetValue(infoDict, _kCFBundleSupportedPlatformsKey) : NULL; - if (platformArray && CFGetTypeID(platformArray) != CFArrayGetTypeID()) { - platformArray = NULL; - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleSupportedPlatformsKey); - } - if (!platformArray) { - CFURLRef infoPlistURL = infoDict ? (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleInfoPlistURLKey) : NULL, absoluteURL; - CFStringRef infoPlistPath; - UniChar buff[CFMaxPathSize]; - CFIndex buffLen, infoLen = CFStringGetLength(_CFBundleInfoURLFromBaseNoExtension3), startLen, extLen = CFStringGetLength(_CFBundleInfoExtension); - if (infoPlistURL) { - CFMutableArrayRef mutableArray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - absoluteURL = CFURLCopyAbsoluteURL(infoPlistURL); - infoPlistPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - CFRelease(absoluteURL); - buffLen = CFStringGetLength(infoPlistPath); - if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize; - CFStringGetCharacters(infoPlistPath, CFRangeMake(0, buffLen), buff); - CFRelease(infoPlistPath); - if (buffLen > 0) { - buffLen = _CFStartOfLastPathComponent(buff, buffLen); - if (buffLen > 0 && buffLen + infoLen + extLen < CFMaxPathSize) { - CFStringGetCharacters(_CFBundleInfoURLFromBaseNoExtension3, CFRangeMake(0, infoLen), buff + buffLen); - buffLen += infoLen; - buff[buffLen++] = (UniChar)'-'; - startLen = buffLen; - _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("macos"), CFSTR("MacOS")); - _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("macosx"), CFSTR("MacOS")); - _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("iphoneos"), CFSTR("iPhoneOS")); - _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("windows"), CFSTR("Windows")); - } - } - if (CFArrayGetCount(mutableArray) > 0) { - platformArray = (CFArrayRef)mutableArray; - CFDictionarySetValue((CFMutableDictionaryRef)infoDict, _kCFBundleSupportedPlatformsKey, platformArray); - } - CFRelease(mutableArray); - } - } - return platformArray; + // This function is obsolete + return NULL; } CF_EXPORT CFStringRef _CFBundleGetCurrentPlatform(void) { @@ -1444,29 +441,6 @@ static void _CFBundleAddValueForType(CFStringRef type, CFMutableDictionaryRef qu } } -CF_INLINE Boolean _CFBundleFindCharacterInStr(const UniChar *str, UniChar c, Boolean backward, CFIndex start, CFIndex length, CFRange *result){ - *result = CFRangeMake(kCFNotFound, 0); - Boolean found = false; - if (backward) { - for (CFIndex i = start; i > start-length; i--) { - if (c == str[i]) { - result->location = i; - found = true; - break; - } - } - } else { - for (CFIndex i = start; i < start+length; i++) { - if (c == str[i]) { - result->location = i; - found = true; - break; - } - } - } - return found; -} - typedef enum { _CFBundleFileVersionNoProductNoPlatform = 1, _CFBundleFileVersionWithProductNoPlatform, @@ -1631,7 +605,7 @@ static void _CFBundleSplitFileName(CFStringRef fileName, CFStringRef *noProductO } } -static Boolean _CFBundleReadDirectory(CFStringRef pathOfDir, CFBundleRef bundle, CFStringRef subdirectory, CFMutableArrayRef allFiles, Boolean hasFileAdded, CFMutableStringRef type, CFMutableDictionaryRef queryTable, CFMutableDictionaryRef typeDir, CFMutableDictionaryRef addedTypes, Boolean firstLproj, CFStringRef product, CFStringRef platform, CFStringRef lprojName, Boolean appendLprojCharacters) { +static Boolean _CFBundleReadDirectory(CFStringRef pathOfDir, CFStringRef subdirectory, CFMutableArrayRef allFiles, Boolean hasFileAdded, CFMutableDictionaryRef queryTable, CFMutableDictionaryRef typeDir, CFMutableDictionaryRef addedTypes, Boolean firstLproj, CFStringRef product, CFStringRef platform, CFStringRef lprojName, Boolean appendLprojCharacters) { Boolean result = true; CFMutableStringRef pathPrefix = NULL; @@ -1774,13 +748,12 @@ static Boolean _CFBundleReadDirectory(CFStringRef pathOfDir, CFBundleRef bundle, } -static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourcesDirectory, CFStringRef subdirectory) +static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFStringRef inPath, CFArrayRef languages, CFStringRef resourcesDirectory, CFStringRef subdirectory) { CFMutableDictionaryRef queryTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFMutableArrayRef allFiles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); CFMutableDictionaryRef typeDir = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFMutableStringRef type = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull); CFStringRef productName = _CFGetProductName();//CFSTR("iphone"); CFStringRef platformName = _CFGetPlatformName();//CFSTR("iphoneos"); @@ -1790,16 +763,7 @@ static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURL CFStringRef product = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("~%@"), productName); CFStringRef platform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("-%@"), platformName); - CFMutableStringRef path = NULL; - if (bundle) { - path = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, bundle->_bundleBasePath); - } else { - CFURLRef url = CFURLCopyAbsoluteURL(bundleURL); - CFStringRef bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE); - CFRelease(url); - path = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, bundlePath); - CFRelease(bundlePath); - } + CFMutableStringRef path = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, inPath); if (resourcesDirectory) { _CFAppendPathComponent2(path, resourcesDirectory); @@ -1812,14 +776,11 @@ static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURL _CFAppendPathComponent2(path, subdirectory); } // read the content in sub dir and put them into query table - _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, false, type, queryTable, typeDir, NULL, false, product, platform, NULL, false); + _CFBundleReadDirectory(path, subdirectory, allFiles, false, queryTable, typeDir, NULL, false, product, platform, NULL, false); CFStringDelete(path, CFRangeMake(basePathLen, CFStringGetLength(path) - basePathLen)); // Strip the string back to the base path CFIndex numOfAllFiles = CFArrayGetCount(allFiles); - if (bundle && !languages) { - languages = _CFBundleGetLanguageSearchList(bundle); - } CFIndex numLprojs = languages ? CFArrayGetCount(languages) : 0; CFMutableDictionaryRef addedTypes = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -1834,7 +795,7 @@ static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURL if (subdirectory) { _CFAppendPathComponent2(path, subdirectory); } - _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, hasFileAdded, type, queryTable, typeDir, addedTypes, firstLproj, product, platform, lprojTarget, true); + _CFBundleReadDirectory(path, subdirectory, allFiles, hasFileAdded, queryTable, typeDir, addedTypes, firstLproj, product, platform, lprojTarget, true); CFStringDelete(path, CFRangeMake(basePathLen, CFStringGetLength(path) - basePathLen)); // Strip the string back to the base path if (!hasFileAdded && numOfAllFiles < CFArrayGetCount(allFiles)) { @@ -1849,7 +810,7 @@ static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURL if (subdirectory) { _CFAppendPathComponent2(path, subdirectory); } - _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, hasFileAdded, type, queryTable, typeDir, addedTypes, YES, product, platform, _CFBundleBaseDirectory, true); + _CFBundleReadDirectory(path, subdirectory, allFiles, hasFileAdded, queryTable, typeDir, addedTypes, YES, product, platform, _CFBundleBaseDirectory, true); CFStringDelete(path, CFRangeMake(basePathLen, CFStringGetLength(path) - basePathLen)); // Strip the string back to the base path if (!hasFileAdded && numOfAllFiles < CFArrayGetCount(allFiles)) { @@ -1866,7 +827,7 @@ static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURL if (subdirectory) { _CFAppendPathComponent2(path, subdirectory); } - _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, hasFileAdded, type, queryTable, typeDir, addedTypes, false, product, platform, lprojTarget, true); + _CFBundleReadDirectory(path, subdirectory, allFiles, hasFileAdded, queryTable, typeDir, addedTypes, false, product, platform, lprojTarget, true); CFStringDelete(path, CFRangeMake(basePathLen, CFStringGetLength(path) - basePathLen)); // Strip the string back to the base path if (!hasFileAdded && numOfAllFiles < CFArrayGetCount(allFiles)) { @@ -1887,8 +848,6 @@ static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURL CFRelease(product); CFRelease(allFiles); CFRelease(typeDir); - CFRelease(type); - return queryTable; } @@ -1898,7 +857,12 @@ static CFDictionaryRef _CFBundleCopyQueryTable(CFBundleRef bundle, CFURLRef bund { CFDictionaryRef subTable = NULL; - // take the lock + if (bundle && !languages) { + languages = _CFBundleCopyLanguageSearchListInBundle(bundle); + } else if (languages) { + CFRetain(languages); + } + if (bundle) { CFMutableStringRef argDirStr = NULL; if (subdirectory) { @@ -1908,25 +872,30 @@ static CFDictionaryRef _CFBundleCopyQueryTable(CFBundleRef bundle, CFURLRef bund argDirStr = (CFMutableStringRef)CFRetain(resourcesDirectory); } - __CFSpinLock(&bundle->_queryLock); + __CFLock(&bundle->_queryLock); // check if the query table for the given sub dir has been created subTable = (CFDictionaryRef) CFDictionaryGetValue(bundle->_queryTable, argDirStr); if (!subTable) { // create the query table for the given sub dir - subTable = _CFBundleCreateQueryTableAtPath(bundle, bundleURL, languages, resourcesDirectory, subdirectory); + subTable = _CFBundleCreateQueryTableAtPath(bundle->_bundleBasePath, languages, resourcesDirectory, subdirectory); CFDictionarySetValue(bundle->_queryTable, argDirStr, subTable); } else { CFRetain(subTable); } - __CFSpinUnlock(&bundle->_queryLock); + __CFUnlock(&bundle->_queryLock); CFRelease(argDirStr); } else { - subTable = _CFBundleCreateQueryTableAtPath(NULL, bundleURL, languages, resourcesDirectory, subdirectory); + CFURLRef url = CFURLCopyAbsoluteURL(bundleURL); + CFStringRef bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE); + CFRelease(url); + subTable = _CFBundleCreateQueryTableAtPath(bundlePath, languages, resourcesDirectory, subdirectory); + CFRelease(bundlePath); } + if (languages) CFRelease(languages); return subTable; } @@ -1960,8 +929,10 @@ static void _CFBundleFindResourcesWithPredicate(CFMutableArrayRef interResult, C if (dictSize == 0) { return; } - STACK_BUFFER_DECL(CFTypeRef, keys, dictSize); - STACK_BUFFER_DECL(CFTypeRef, values, dictSize); + CFTypeRef *keys = (CFTypeRef *)malloc(sizeof(CFTypeRef) * dictSize); + CFTypeRef *values = (CFTypeRef *)malloc(sizeof(CFTypeRef) * dictSize); + if (!keys || !values) return; + CFDictionaryGetKeysAndValues(queryTable, keys, values); for (CFIndex i = 0; i < dictSize; i++) { if (predicate((CFStringRef)keys[i], stop)) { @@ -1974,9 +945,12 @@ static void _CFBundleFindResourcesWithPredicate(CFMutableArrayRef interResult, C if (*stop) break; } + + free(keys); + free(values); } -static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourcesDirectory, CFStringRef subDir, CFStringRef key, CFStringRef lproj, Boolean returnArray, Boolean localized, uint8_t bundleVersion, Boolean (^predicate)(CFStringRef filename, Boolean *stop)) +static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef bundleURLLanguages, CFStringRef resourcesDirectory, CFStringRef subDir, CFStringRef key, CFStringRef lproj, Boolean returnArray, Boolean localized, uint8_t bundleVersion, Boolean (^predicate)(CFStringRef filename, Boolean *stop)) { CFTypeRef value = NULL; Boolean stop = false; // for predicate @@ -1988,7 +962,7 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFIndex savedPathLength = CFStringGetLength(path); // add the non-localized resource dir _CFAppendPathComponent2(path, _CFBundleNonLocalizedResourcesDirectoryName); - subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, path, subDir); + subTable = _CFBundleCopyQueryTable(bundle, bundleURL, bundleURLLanguages, path, subDir); if (predicate) { _CFBundleFindResourcesWithPredicate(interResult, subTable, predicate, &stop); } else { @@ -1999,7 +973,7 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, if (!value && !stop) { if (subTable) CFRelease(subTable); - subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, path, subDir); + subTable = _CFBundleCopyQueryTable(bundle, bundleURL, bundleURLLanguages, path, subDir); if (predicate) { _CFBundleFindResourcesWithPredicate(interResult, subTable, predicate, &stop); } else { @@ -2072,9 +1046,9 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFMutableStringRef lprojSubdirName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, lproj); _CFAppendPathExtension2(lprojSubdirName, _CFBundleLprojExtension); if (subDir && CFStringGetLength(subDir) > 0) { - _CFAppendTrailingPathSlash2(lprojSubdirName); + _CFAppendPathComponent2(lprojSubdirName, subDir); } - subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, path, lprojSubdirName); + subTable = _CFBundleCopyQueryTable(bundle, bundleURL, bundleURLLanguages, path, lprojSubdirName); CFRelease(lprojSubdirName); value = CFDictionaryGetValue(subTable, key); @@ -2154,11 +1128,12 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, #pragma mark - + // This is the main entry point for all resource lookup. // Research shows that by far the most common scenario is to pass in a bundle object, a resource name, and a resource type, using the default localization. // It is probably the case that more than a few resources will be looked up, making the cost of a readdir less than repeated stats. But it is a relative waste of memory to create strings for every file name in the bundle, especially since those are not what are returned to the caller (URLs are). So, an idea: cache the existence of the most common file names (Info.plist, en.lproj, etc) instead of creating entries for them. If other resources are requested, then go ahead and do the readdir and cache the rest of the file names. // Another idea: if you want caching, you should create a bundle object. Otherwise we'll happily readdir each time. -CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subPath, CFStringRef lproj, Boolean returnArray, Boolean localized, Boolean (^predicate)(CFStringRef filename, Boolean *stop)) +CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef _unused_pass_null_, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subPath, CFStringRef lproj, Boolean returnArray, Boolean localized, Boolean (^predicate)(CFStringRef filename, Boolean *stop)) { // Don't use any path info passed into the resource name @@ -2173,6 +1148,13 @@ CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bund subPathFromResourceName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, resourceName, CFRangeMake(0, slashLocation)); } + if (slashLocation > 0 && CFStringGetLength(realResourceName) == 0 && slashLocation == CFStringGetLength(resourceName) - 1) { + // Did we have a name with just a single / at the end? Taking the lastPathComponent will end up with an empty resource name, which is probably not what was expected. + // Reset the name to be just the directory name. + CFRelease(realResourceName); + realResourceName = CFStringCreateCopy(kCFAllocatorSystemDefault, subPathFromResourceName); + } + // Normalize the resource name by converting it to file system representation. Otherwise when we look for the key in our tables, it will not match. // TODO: remove this in some way to avoid the malloc? char buff[CFMaxPathSize]; @@ -2204,22 +1186,28 @@ CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bund CFStringRef realSubdirectory = NULL; - if (subPath && CFStringGetLength(subPath) && !subPathFromResourceName) { + bool hasSubPath = subPath && CFStringGetLength(subPath); + bool hasSubPathFromResourceName = subPathFromResourceName && CFStringGetLength(subPathFromResourceName); + + if (hasSubPath && !hasSubPathFromResourceName) { realSubdirectory = (CFStringRef)CFRetain(subPath); - } else if (subPathFromResourceName && CFStringGetLength(subPathFromResourceName)) { + } else if (!hasSubPath && hasSubPathFromResourceName) { realSubdirectory = (CFStringRef)CFRetain(subPathFromResourceName); + } else if (hasSubPath && hasSubPathFromResourceName) { + // Multiple sub paths - we'll have to concatenate + realSubdirectory = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, subPath); + _CFAppendPathComponent2((CFMutableStringRef)realSubdirectory, subPathFromResourceName); } uint8_t bundleVersion = bundle ? _CFBundleLayoutVersion(bundle) : 0; - if (bundleURL && !languages) { - languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, bundleURL, &bundleVersion); - } else if (languages) { - CFRetain(languages); + CFArrayRef bundleURLLanguages = NULL; + if (bundleURL) { + bundleURLLanguages = _CFBundleCopyLanguageSearchListInDirectory(bundleURL, &bundleVersion); } CFStringRef resDir = _CFBundleGetResourceDirForVersion(bundleVersion); - CFTypeRef returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, languages, resDir, realSubdirectory, key, lproj, returnArray, localized, bundleVersion, predicate); + CFTypeRef returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, bundleURLLanguages, resDir, realSubdirectory, key, lproj, returnArray, localized, bundleVersion, predicate); if ((!returnValue || (CFGetTypeID(returnValue) == CFArrayGetTypeID() && CFArrayGetCount((CFArrayRef)returnValue) == 0)) && (0 == bundleVersion || 2 == bundleVersion)) { CFStringRef bundlePath = NULL; @@ -2250,7 +1238,7 @@ CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bund // Assume no resources directory resDir = CFSTR(""); } - returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, languages, resDir, realSubdirectory, key, lproj, returnArray, localized, bundleVersion, predicate); + returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, bundleURLLanguages, resDir, realSubdirectory, key, lproj, returnArray, localized, bundleVersion, predicate); } CFRelease(bundlePath); } @@ -2258,94 +1246,9 @@ CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bund if (realResourceName) CFRelease(realResourceName); if (realSubdirectory) CFRelease(realSubdirectory); if (subPathFromResourceName) CFRelease(subPathFromResourceName); - if (languages) CFRelease(languages); + if (bundleURLLanguages) CFRelease(bundleURLLanguages); CFRelease(key); - return returnValue; -} - -#pragma mark - -#pragma mark Localized Strings - - -CF_EXPORT CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName) { - CFStringRef result = NULL; - CFDictionaryRef stringTable = NULL; - static CFSpinLock_t CFBundleLocalizedStringLock = CFSpinLockInit; - - if (!key) return (value ? (CFStringRef)CFRetain(value) : (CFStringRef)CFRetain(CFSTR(""))); - // Make sure to check the mixed localizations key early -- if the main bundle has not yet been cached, then we need to create the cache of the Info.plist before we start asking for resources (11172381) - (void)CFBundleAllowMixedLocalizations(); - - if (!tableName || CFEqual(tableName, CFSTR(""))) tableName = _CFBundleDefaultStringTableName; - - __CFSpinLock(&CFBundleLocalizedStringLock); - if (__CFBundleGetResourceData(bundle)->_stringTableCache) { - stringTable = (CFDictionaryRef)CFDictionaryGetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName); - if (stringTable) CFRetain(stringTable); - } - __CFSpinUnlock(&CFBundleLocalizedStringLock); - if (!stringTable) { - // Go load the table. - CFURLRef tableURL = CFBundleCopyResourceURL(bundle, tableName, _CFBundleStringTableType, NULL); - if (tableURL) { - CFStringRef nameForSharing = NULL; - if (!stringTable) { - CFDataRef tableData = NULL; - SInt32 errCode; - CFStringRef errStr; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated" - if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tableURL, &tableData, NULL, NULL, &errCode)) { -#pragma GCC diagnostic pop - stringTable = (CFDictionaryRef)CFPropertyListCreateFromXMLData(CFGetAllocator(bundle), tableData, kCFPropertyListImmutable, &errStr); - if (errStr) { - CFRelease(errStr); - errStr = NULL; - } - if (stringTable && CFDictionaryGetTypeID() != CFGetTypeID(stringTable)) { - CFRelease(stringTable); - stringTable = NULL; - } - CFRelease(tableData); - - } - } - if (nameForSharing) CFRelease(nameForSharing); - if (tableURL) CFRelease(tableURL); - } - if (!stringTable) stringTable = CFDictionaryCreate(CFGetAllocator(bundle), NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - if (!CFStringHasSuffix(tableName, CFSTR(".nocache")) || !_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) { - __CFSpinLock(&CFBundleLocalizedStringLock); - if (!__CFBundleGetResourceData(bundle)->_stringTableCache) __CFBundleGetResourceData(bundle)->_stringTableCache = CFDictionaryCreateMutable(CFGetAllocator(bundle), 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName, stringTable); - __CFSpinUnlock(&CFBundleLocalizedStringLock); - } - } - - result = (CFStringRef)CFDictionaryGetValue(stringTable, key); - if (!result) { - if (!value) { - result = (CFStringRef)CFRetain(key); - } else if (CFEqual(value, CFSTR(""))) { - result = (CFStringRef)CFRetain(key); - } else { - result = (CFStringRef)CFRetain(value); - } - __block Boolean capitalize = false; - if (capitalize) { - CFMutableStringRef capitalizedResult = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, result); - CFLog(__kCFLogBundle, CFSTR("Localizable string \"%@\" not found in strings table \"%@\" of bundle %@."), key, tableName, bundle); - CFStringUppercase(capitalizedResult, NULL); - CFRelease(result); - result = capitalizedResult; - } - } else { - CFRetain(result); - } - CFRelease(stringTable); - return result; + return returnValue; } - diff --git a/CFBundle_Strings.c b/CFBundle_Strings.c new file mode 100644 index 0000000..d2737e1 --- /dev/null +++ b/CFBundle_Strings.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* CFBundle_Strings.c + Copyright (c) 1999-2014, Apple Inc. All rights reserved. + Responsibility: Tony Parker +*/ + +#include "CFBundle_Internal.h" +#if DEPLOYMENT_TARGET_MACOSX + +#endif + +#include +#include + +#pragma mark - +#pragma mark Localized Strings + + +CF_EXPORT CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName) { + return CFBundleCopyLocalizedStringForLocalization(bundle, key, value, tableName, NULL); +} + +CF_EXPORT CFStringRef CFBundleCopyLocalizedStringForLocalization(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName, CFStringRef localizationName) { + CFStringRef result = NULL; + CFDictionaryRef stringTable = NULL; + + if (!key) return (value ? (CFStringRef)CFRetain(value) : (CFStringRef)CFRetain(CFSTR(""))); + + // Make sure to check the mixed localizations key early -- if the main bundle has not yet been cached, then we need to create the cache of the Info.plist before we start asking for resources (11172381) + (void)CFBundleAllowMixedLocalizations(); + + if (!tableName || CFEqual(tableName, CFSTR(""))) tableName = _CFBundleDefaultStringTableName; + + __CFLock(&bundle->_lock); + // Only consult the cache when a specific localization has not been requested. We only cache results for the preferred language as determined by normal bundle lookup rules. + if (!localizationName && bundle->_stringTable) { + stringTable = (CFDictionaryRef)CFDictionaryGetValue(bundle->_stringTable, tableName); + if (stringTable) CFRetain(stringTable); + } + + if (!stringTable) { + // Go load the table. First, unlock so we don't hold the lock across file system access. + __CFUnlock(&bundle->_lock); + + CFURLRef tableURL = NULL; + if (localizationName) { + tableURL = CFBundleCopyResourceURLForLocalization(bundle, tableName, _CFBundleStringTableType, NULL, localizationName); + } else { + tableURL = CFBundleCopyResourceURL(bundle, tableName, _CFBundleStringTableType, NULL); + } + + if (tableURL) { + CFStringRef nameForSharing = NULL; + if (!stringTable) { + CFDataRef tableData = NULL; + SInt32 errCode; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tableURL, &tableData, NULL, NULL, &errCode)) { +#pragma GCC diagnostic pop + CFErrorRef error = NULL; + stringTable = (CFDictionaryRef)CFPropertyListCreateWithData(CFGetAllocator(bundle), tableData, kCFPropertyListImmutable, NULL, &error); + if (stringTable && CFDictionaryGetTypeID() != CFGetTypeID(stringTable)) { + CFRelease(stringTable); + stringTable = NULL; + } + if (!stringTable && error) { + CFLog(kCFLogLevelError, CFSTR("Unable to load string table file: %@ / %@: %@"), bundle, tableName, error); + CFRelease(error); + error = NULL; + } + CFRelease(tableData); + + } + } + if (nameForSharing) CFRelease(nameForSharing); + if (tableURL) CFRelease(tableURL); + } + if (!stringTable) stringTable = CFDictionaryCreate(CFGetAllocator(bundle), NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + if ((!CFStringHasSuffix(tableName, CFSTR(".nocache")) || !_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) && localizationName == NULL) { + // Take lock again, because this we will unlock after getting the value out of the table. + __CFLock(&bundle->_lock); + if (!bundle->_stringTable) bundle->_stringTable = CFDictionaryCreateMutable(CFGetAllocator(bundle), 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // If another thread beat us to setting this tableName, then we'll just replace it here. + CFDictionarySetValue(bundle->_stringTable, tableName, stringTable); + } else { + // Take lock again, because this we will unlock after getting the value out of the table. + __CFLock(&bundle->_lock); + } + } + + result = (CFStringRef)CFDictionaryGetValue(stringTable, key); + if (result) { + CFRetain(result); + } + + __CFUnlock(&bundle->_lock); + CFRelease(stringTable); + + if (!result) { + if (!value) { + result = (CFStringRef)CFRetain(key); + } else if (CFEqual(value, CFSTR(""))) { + result = (CFStringRef)CFRetain(key); + } else { + result = (CFStringRef)CFRetain(value); + } + static Boolean capitalize = false; + if (capitalize) { + CFMutableStringRef capitalizedResult = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, result); + CFLog(__kCFLogBundle, CFSTR("Localizable string \"%@\" not found in strings table \"%@\" of bundle %@."), key, tableName, bundle); + CFStringUppercase(capitalizedResult, NULL); + CFRelease(result); + result = capitalizedResult; + } + } + + return result; +} + diff --git a/CFBurstTrie.c b/CFBurstTrie.c index 498e16d..2c9aeb4 100644 --- a/CFBurstTrie.c +++ b/CFBurstTrie.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBurstTrie.c - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. Responsibility: Jennifer Moore */ @@ -416,6 +416,8 @@ CFBurstTrieRef CFBurstTrieCreateFromFile(CFStringRef path) { // On Windows, the file being mapped must stay open as long as the map exists. Don't close it early. Other platforms close it here. close(fd); #endif + } else { + close(fd); } return trie; } @@ -1181,7 +1183,7 @@ static void traverseCFBurstTrieWithCursor(CFBurstTrieRef trie, const uint8_t *pr } } else { TrieCursor csr; - csr.next = ((unsigned long)&trie->root)|TrieKind; + csr.next = ((uintptr_t)&trie->root)|TrieKind; csr.prefix = prefix; csr.prefixlen = prefixLen; csr.key[0] = 0; diff --git a/CFBurstTrie.h b/CFBurstTrie.h index 12d5e3d..c594470 100644 --- a/CFBurstTrie.h +++ b/CFBurstTrie.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFBurstTrie.h - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBURSTTRIE__) diff --git a/CFByteOrder.h b/CFByteOrder.h index b9e6014..a37b01b 100644 --- a/CFByteOrder.h +++ b/CFByteOrder.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFByteOrder.h - Copyright (c) 1995-2013, Apple Inc. All rights reserved. + Copyright (c) 1995-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBYTEORDER__) diff --git a/CFCalendar.c b/CFCalendar.c index a4c2c90..979b1b5 100644 --- a/CFCalendar.c +++ b/CFCalendar.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFCalendar.c - Copyright (c) 2004-2013, Apple Inc. All rights reserved. + Copyright (c) 2004-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -83,12 +83,9 @@ static const CFRuntimeClass __CFCalendarClass = { __CFCalendarCopyDescription }; -CF_PRIVATE void __CFCalendarInitialize(void) { - __kCFCalendarTypeID = _CFRuntimeRegisterClass(&__CFCalendarClass); -} - CFTypeID CFCalendarGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFCalendarTypeID) __CFCalendarInitialize(); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFCalendarTypeID = _CFRuntimeRegisterClass(&__CFCalendarClass); }); return __kCFCalendarTypeID; } @@ -502,106 +499,6 @@ static Boolean __validUnits(CFCalendarUnit smaller, CFCalendarUnit bigger) { return false; }; -static CFRange __CFCalendarGetRangeOfUnit1(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) { - CFRange range = {kCFNotFound, kCFNotFound}; - if (!__validUnits(smallerUnit, biggerUnit)) return range; - CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFRange, calendar, _rangeOfUnit:smallerUnit inUnit:biggerUnit forAT:at); - __CFGenericValidateType(calendar, CFCalendarGetTypeID()); - if (!calendar->_cal) __CFCalendarSetupCal(calendar); - if (calendar->_cal) { - int32_t dow = -1; - ucal_clear(calendar->_cal); - UCalendarDateFields smallField = __CFCalendarGetICUFieldCode(smallerUnit); - UCalendarDateFields bigField = __CFCalendarGetICUFieldCode(biggerUnit); - if (kCFCalendarUnitWeekdayOrdinal == smallerUnit) { - UErrorCode status = U_ZERO_ERROR; - UDate udate = floor((at + kCFAbsoluteTimeIntervalSince1970) * 1000.0); - ucal_setMillis(calendar->_cal, udate, &status); - dow = ucal_get(calendar->_cal, UCAL_DAY_OF_WEEK, &status); - } - // Set calendar to first instant of big unit - __CFCalendarSetToFirstInstant(calendar, biggerUnit, at); - UErrorCode status = U_ZERO_ERROR; - UDate start = ucal_getMillis(calendar->_cal, &status); - if (kCFCalendarUnitWeek == biggerUnit) { - range.location = ucal_get(calendar->_cal, smallField, &status); - if (kCFCalendarUnitMonth == smallerUnit) range.location++; - } else { - range.location = (kCFCalendarUnitHour == smallerUnit || kCFCalendarUnitMinute == smallerUnit || kCFCalendarUnitSecond == smallerUnit) ? 0 : 1; - } - // Set calendar to first instant of next value of big unit - if (UCAL_ERA == bigField) { - // ICU refuses to do the addition, probably because we are - // at the limit of UCAL_ERA. Use alternate strategy. - CFIndex limit = ucal_getLimit(calendar->_cal, UCAL_YEAR, UCAL_MAXIMUM, &status); - if (100000 < limit) limit = 100000; - ucal_add(calendar->_cal, UCAL_YEAR, limit, &status); - } else { - ucal_add(calendar->_cal, bigField, 1, &status); - } - if (kCFCalendarUnitWeek == smallerUnit && kCFCalendarUnitYear == biggerUnit) { - ucal_add(calendar->_cal, UCAL_SECOND, -1, &status); - range.length = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status); - while (1 == range.length) { - ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, -1, &status); - range.length = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status); - } - range.location = 1; - return range; - } else if (kCFCalendarUnitWeek == smallerUnit && kCFCalendarUnitMonth == biggerUnit) { - ucal_add(calendar->_cal, UCAL_SECOND, -1, &status); - range.length = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status); - range.location = 1; - return range; - } - UDate goal = ucal_getMillis(calendar->_cal, &status); - // Set calendar back to first instant of big unit - ucal_setMillis(calendar->_cal, start, &status); - if (kCFCalendarUnitWeekdayOrdinal == smallerUnit) { - // roll day forward to first 'dow' - while (ucal_get(calendar->_cal, (kCFCalendarUnitMonth == biggerUnit) ? UCAL_WEEK_OF_MONTH : UCAL_WEEK_OF_YEAR, &status) != 1) { - ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, 1, &status); - } - while (ucal_get(calendar->_cal, UCAL_DAY_OF_WEEK, &status) != dow) { - ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, 1, &status); - } - start = ucal_getMillis(calendar->_cal, &status); - goal -= 1000; - range.location = 1; // constant here works around ICU -- see 3948293 - } - UDate curr = start; - range.length = (kCFCalendarUnitWeekdayOrdinal == smallerUnit) ? 1 : 0; - const int multiple_table[] = {0, 0, 16, 19, 24, 26, 24, 28, 14, 14, 14}; - int multiple = (1 << multiple_table[flsl(smallerUnit) - 1]); - Boolean divide = false, alwaysDivide = false; - while (curr < goal) { - ucal_add(calendar->_cal, smallField, multiple, &status); - UDate newcurr = ucal_getMillis(calendar->_cal, &status); - if (curr < newcurr && newcurr <= goal) { - range.length += multiple; - curr = newcurr; - } else { - // Either newcurr is going backwards, or not making - // progress, or has overshot the goal; reset date - // and try smaller multiples. - ucal_setMillis(calendar->_cal, curr, &status); - divide = true; - // once we start overshooting the goal, the add at - // smaller multiples will succeed at most once for - // each multiple, so we reduce it every time through - // the loop. - if (goal < newcurr) alwaysDivide = true; - } - if (divide) { - multiple = multiple / 2; - if (0 == multiple) break; - divide = alwaysDivide; - } - } - } - return range; -} - static CFRange __CFCalendarGetRangeOfUnit2(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) __attribute__((noinline)); static CFRange __CFCalendarGetRangeOfUnit2(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) { CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFRange, calendar, _rangeOfUnit:smallerUnit inUnit:biggerUnit forAT:at); diff --git a/CFCalendar.h b/CFCalendar.h index 433c415..c88435e 100644 --- a/CFCalendar.h +++ b/CFCalendar.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFCalendar.h - Copyright (c) 2004-2013, Apple Inc. All rights reserved. + Copyright (c) 2004-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFCALENDAR__) @@ -36,7 +36,7 @@ CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -typedef struct __CFCalendar * CFCalendarRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSCalendar) __CFCalendar * CFCalendarRef; CF_EXPORT CFTypeID CFCalendarGetTypeID(void); @@ -86,7 +86,7 @@ typedef CF_OPTIONS(CFOptionFlags, CFCalendarUnit) { kCFCalendarUnitHour = (1UL << 5), kCFCalendarUnitMinute = (1UL << 6), kCFCalendarUnitSecond = (1UL << 7), - kCFCalendarUnitWeek = (1UL << 8) /* CF_DEPRECATED(10_4, 10_7, 2_0, 5_0) */, + kCFCalendarUnitWeek CF_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0) = (1UL << 8), kCFCalendarUnitWeekday = (1UL << 9), kCFCalendarUnitWeekdayOrdinal = (1UL << 10), kCFCalendarUnitQuarter CF_ENUM_AVAILABLE(10_6, 4_0) = (1UL << 11), diff --git a/CFCharacterSet.c b/CFCharacterSet.c index 9b4ab0b..bd5c853 100644 --- a/CFCharacterSet.c +++ b/CFCharacterSet.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFCharacterSet.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -467,17 +467,6 @@ CF_INLINE uint32_t __CFCSetGetCompactBitmapSize(const uint8_t *compactBitmap) { return size; } -/* Take a private "set" structure and make a bitmap from it. Return the bitmap. THE CALLER MUST RELEASE THE RETURNED MEMORY as necessary. -*/ - -CF_INLINE void __CFCSetBitmapProcessManyCharacters(unsigned char *map, unsigned n, unsigned m, Boolean isInverted) { - if (isInverted) { - __CFCSetBitmapRemoveCharactersInRange(map, n, m); - } else { - __CFCSetBitmapAddCharactersInRange(map, n, m); - } -} - CF_INLINE void __CFExpandCompactBitmap(const uint8_t *src, uint8_t *dst) { const uint8_t *srcBody = src + __kCFCompactBitmapNumPages; int i; @@ -894,7 +883,7 @@ static CFCharacterSetRef *__CFBuiltinSets = NULL; /* Global lock for character set */ -static CFSpinLock_t __CFCharacterSetLock = CFSpinLockInit; +static OSSpinLock __CFCharacterSetLock = OS_SPINLOCK_INIT; /* CFBase API functions */ @@ -1298,11 +1287,14 @@ static const CFRuntimeClass __CFCharacterSetClass = { static bool __CFCheckForExapendedSet = false; CF_PRIVATE void __CFCharacterSetInitialize(void) { - const char *checkForExpandedSet = __CFgetenv("__CF_DEBUG_EXPANDED_SET"); - - __kCFCharacterSetTypeID = _CFRuntimeRegisterClass(&__CFCharacterSetClass); - - if (checkForExpandedSet && (*checkForExpandedSet == 'Y')) __CFCheckForExapendedSet = true; + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFCharacterSetTypeID = _CFRuntimeRegisterClass(&__CFCharacterSetClass); // initOnce covered + const char *checkForExpandedSet = __CFgetenv("__CF_DEBUG_EXPANDED_SET"); + if (checkForExpandedSet && (*checkForExpandedSet == 'Y')) __CFCheckForExapendedSet = true; + __CFBuiltinSets = (CFCharacterSetRef *)CFAllocatorAllocate((CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()), sizeof(CFCharacterSetRef) * __kCFLastBuiltinSetID, 0); + memset(__CFBuiltinSets, 0, sizeof(CFCharacterSetRef) * __kCFLastBuiltinSetID); + }); } /* Public functions @@ -1320,23 +1312,18 @@ CFCharacterSetRef CFCharacterSetGetPredefined(CFCharacterSetPredefinedSet theSet __CFCSetValidateBuiltinType(theSetIdentifier, __PRETTY_FUNCTION__); - __CFSpinLock(&__CFCharacterSetLock); + OSSpinLockLock(&__CFCharacterSetLock); cset = ((NULL != __CFBuiltinSets) ? __CFBuiltinSets[theSetIdentifier - 1] : NULL); - __CFSpinUnlock(&__CFCharacterSetLock); + OSSpinLockUnlock(&__CFCharacterSetLock); if (NULL != cset) return cset; if (!(cset = __CFCSetGenericCreate(kCFAllocatorSystemDefault, __kCFCharSetClassBuiltin))) return NULL; __CFCSetPutBuiltinType((CFMutableCharacterSetRef)cset, theSetIdentifier); - __CFSpinLock(&__CFCharacterSetLock); - if (!__CFBuiltinSets) { - __CFBuiltinSets = (CFCharacterSetRef *)CFAllocatorAllocate((CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()), sizeof(CFCharacterSetRef) * __kCFLastBuiltinSetID, 0); - memset(__CFBuiltinSets, 0, sizeof(CFCharacterSetRef) * __kCFLastBuiltinSetID); - } - + OSSpinLockLock(&__CFCharacterSetLock); __CFBuiltinSets[theSetIdentifier - 1] = cset; - __CFSpinUnlock(&__CFCharacterSetLock); + OSSpinLockUnlock(&__CFCharacterSetLock); return cset; } @@ -2622,18 +2609,34 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef if (__CFCSetHasNonBMPPlane(theOtherSet)) { CFMutableCharacterSetRef annexPlane; CFMutableCharacterSetRef otherSetPlane; + CFMutableCharacterSetRef emptySet = CFCharacterSetCreateMutable(NULL); int idx; for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theOtherSet, idx))) { + if (__CFCSetAnnexIsInverted(theOtherSet)) CFCharacterSetInvert(otherSetPlane); annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); CFCharacterSetIntersect(annexPlane, otherSetPlane); if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); + if (__CFCSetAnnexIsInverted(theOtherSet)) CFCharacterSetInvert(otherSetPlane); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); - } else if (__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { - __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); + } else if ((annexPlane = (CFMutableCharacterSetRef) __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx))) { + if (__CFCSetAnnexIsInverted(theSet)) { // if the annexPlane is inverted, we need to set the plane to empty + CFCharacterSetInvert(annexPlane); + CFCharacterSetIntersect(annexPlane, emptySet); + CFCharacterSetInvert(annexPlane); + } else { // the annexPlane is not inverted, we can clear the plane + __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); + } + } else if ((__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx) == NULL) && __CFCSetAnnexIsInverted(theSet)) { + // the set has no such annex plane and the annex plane is inverted, it means the set contains everything in the annex plane + annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); + CFCharacterSetIntersect(annexPlane, emptySet); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); } } + CFRelease(emptySet); if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet); } else if (__CFCSetIsBuiltin(theOtherSet) && !__CFCSetAnnexIsInverted(theOtherSet)) { CFMutableCharacterSetRef annexPlane; @@ -2670,6 +2673,7 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef CFMutableCharacterSetRef tempOtherSet = CFCharacterSetCreateMutable(CFGetAllocator(theSet)); CFMutableCharacterSetRef annexPlane; CFMutableCharacterSetRef otherSetPlane; + CFMutableCharacterSetRef emptySet = CFCharacterSetCreateMutable(NULL); int idx; __CFCSetAddNonBMPPlanesInRange(tempOtherSet, CFRangeMake(__CFCSetRangeFirstChar(theOtherSet), __CFCSetRangeLength(theOtherSet))); @@ -2677,16 +2681,31 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(tempOtherSet, idx))) { annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); + if (__CFCSetAnnexIsInverted(tempOtherSet)) CFCharacterSetInvert(otherSetPlane); if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); CFCharacterSetIntersect(annexPlane, otherSetPlane); if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); + if (__CFCSetAnnexIsInverted(tempOtherSet)) CFCharacterSetInvert(otherSetPlane); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); - } else if (__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { - __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); + } else if ((annexPlane = (CFMutableCharacterSetRef) __CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx))) { + if (__CFCSetAnnexIsInverted(theSet)) { + CFCharacterSetInvert(annexPlane); + CFCharacterSetIntersect(annexPlane, emptySet); + CFCharacterSetInvert(annexPlane); + } else { + __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); + } + } else if ((__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx) == NULL) && __CFCSetAnnexIsInverted(theSet)) { + // the set has no such annex plane and the annex plane is inverted, it means the set contains everything in the annex plane + annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); + CFCharacterSetIntersect(annexPlane, emptySet); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); } } if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet); CFRelease(tempOtherSet); + CFRelease(emptySet); } else if ((__CFCSetHasNonBMPPlane(theSet) || __CFCSetAnnexIsInverted(theSet)) && !__CFCSetAnnexIsInverted(theOtherSet)) { __CFCSetDeallocateAnnexPlane(theSet); } diff --git a/CFCharacterSet.h b/CFCharacterSet.h index 97c9f0e..cf62591 100644 --- a/CFCharacterSet.h +++ b/CFCharacterSet.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFCharacterSet.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ /*! @@ -64,13 +64,13 @@ CF_EXTERN_C_BEGIN @typedef CFCharacterSetRef This is the type of a reference to immutable CFCharacterSets. */ -typedef const struct __CFCharacterSet * CFCharacterSetRef; +typedef const struct CF_BRIDGED_TYPE(NSCharacterSet) __CFCharacterSet * CFCharacterSetRef; /*! @typedef CFMutableCharacterSetRef This is the type of a reference to mutable CFMutableCharacterSets. */ -typedef struct __CFCharacterSet * CFMutableCharacterSetRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMutableCharacterSet) __CFCharacterSet * CFMutableCharacterSetRef; /*! @typedef CFCharacterSetPredefinedSet diff --git a/CFCharacterSetBitmaps.bitmap b/CFCharacterSetBitmaps.bitmap index 50b16f1e755efa3692d63f9a692e4160d666f913..81fa63db5ca3004f01d8481036243b1b497a01d8 100644 GIT binary patch delta 198 zcmcb9Q0n?YDJC=HMy6IK#;r_DDy@wC)6cmvc2D2y%F4ZcZ!6OoYsUMNA3DfxUw)8D zo0;eS|Ih#b*Z-IQ|Np=J_IpQ|m=-YFPk)%g?8*88DD)GkQli~Gl^KXxw!5dY`pQiI z^oUhr`o9E5w(Xl5SrwS3TO_c>PQ0*~=LZ7=Lk$oE!TsrptW5r!1r|0-Z{M(h^_c^s v`1a`!S#6m(Dj*6trr&dBvts0&F8+k|1k?Th+aEq*HIHZH+%DKuB_bK_qH;fv1U9!`JsdC z_T>kew3&J2|9t-czy81c|NsBlx8FO$#I%5sefq-`X3xnV99S5C0#!=1yQeY(G0S%M zR90V^iH9Yo|4U$G+rFuhRe@>o1#3p$9}El(H9!mm@_#lnF1#qceZvCQXAX?)+owNd qwPoV4fJkyozvs+m#mG2a{0Zv`Ciy?xA3k9_length; -} - CF_INLINE void __CFDataSetNumBytesUsed(CFMutableDataRef data, CFIndex v) { data->_length = v; } @@ -334,11 +330,9 @@ static const CFRuntimeClass __CFDataClass = { __CFDataCopyDescription }; -CF_PRIVATE void __CFDataInitialize(void) { - __kCFDataTypeID = _CFRuntimeRegisterClass(&__CFDataClass); -} - CFTypeID CFDataGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFDataTypeID = _CFRuntimeRegisterClass(&__CFDataClass); }); return __kCFDataTypeID; } @@ -364,7 +358,7 @@ static CFMutableDataRef __CFDataInit(CFAllocatorRef allocator, CFOptionFlags fla if (allocateInline) { size += sizeof(uint8_t) * __CFDataNumBytesForCapacity(capacity) + sizeof(uint8_t) * 15; // for 16-byte alignment fixup } - memory = (CFMutableDataRef)_CFRuntimeCreateInstance(allocator, __kCFDataTypeID, size, NULL); + memory = (CFMutableDataRef)_CFRuntimeCreateInstance(allocator, CFDataGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -487,27 +481,27 @@ CFMutableDataRef CFDataCreateMutableCopy(CFAllocatorRef allocator, CFIndex capac } CFIndex CFDataGetLength(CFDataRef data) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, CFIndex, (NSData *)data, length); - __CFGenericValidateType(data, __kCFDataTypeID); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), CFIndex, (NSData *)data, length); + __CFGenericValidateType(data, CFDataGetTypeID()); return __CFDataLength(data); } const uint8_t *CFDataGetBytePtr(CFDataRef data) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, const uint8_t *, (NSData *)data, bytes); - __CFGenericValidateType(data, __kCFDataTypeID); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), const uint8_t *, (NSData *)data, bytes); + __CFGenericValidateType(data, CFDataGetTypeID()); // compaction: if inline, always do the computation. return __CFDataBytesInline(data) ? (uint8_t *)__CFDataInlineBytesPtr(data) : data->_bytes; } uint8_t *CFDataGetMutableBytePtr(CFMutableDataRef data) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, uint8_t *, (NSMutableData *)data, mutableBytes); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), uint8_t *, (NSMutableData *)data, mutableBytes); CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); // compaction: if inline, always do the computation. return __CFDataBytesInline(data) ? (uint8_t *)__CFDataInlineBytesPtr(data) : data->_bytes; } void CFDataGetBytes(CFDataRef data, CFRange range, uint8_t *buffer) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSData *)data, getBytes:(void *)buffer range:NSMakeRange(range.location, range.length)); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSData *)data, getBytes:(void *)buffer range:NSMakeRange(range.location, range.length)); __CFDataValidateRange(data, range, __PRETTY_FUNCTION__); memmove(buffer, CFDataGetBytePtr(data) + range.location, range.length); } @@ -552,7 +546,7 @@ static void __CFDataGrow(CFMutableDataRef data, CFIndex numNewValues, Boolean cl void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) { CFIndex oldLength, capacity; Boolean isGrowable; - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, setLength:(NSUInteger)newLength); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, setLength:(NSUInteger)newLength); CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); oldLength = __CFDataLength(data); capacity = __CFDataCapacity(data); @@ -581,27 +575,27 @@ void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) { } void CFDataIncreaseLength(CFMutableDataRef data, CFIndex extraLength) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, increaseLengthBy:(NSUInteger)extraLength); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, increaseLengthBy:(NSUInteger)extraLength); CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); if (extraLength < 0) HALT; // Avoid integer overflow. CFDataSetLength(data, __CFDataLength(data) + extraLength); } void CFDataAppendBytes(CFMutableDataRef data, const uint8_t *bytes, CFIndex length) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, appendBytes:(const void *)bytes length:(NSUInteger)length); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, appendBytes:(const void *)bytes length:(NSUInteger)length); CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); CFDataReplaceBytes(data, CFRangeMake(__CFDataLength(data), 0), bytes, length); } void CFDataDeleteBytes(CFMutableDataRef data, CFRange range) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:NULL length:0); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:NULL length:0); CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); CFDataReplaceBytes(data, range, NULL, 0); } void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *newBytes, CFIndex newLength) { - CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:(const void *)newBytes length:(NSUInteger)newLength); - __CFGenericValidateType(data, __kCFDataTypeID); + CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:(const void *)newBytes length:(NSUInteger)newLength); + __CFGenericValidateType(data, CFDataGetTypeID()); __CFDataValidateRange(data, range, __PRETTY_FUNCTION__); CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__); CFAssert2(0 <= newLength, __kCFLogAssertion, "%s(): newLength (%d) cannot be less than zero", __PRETTY_FUNCTION__, newLength); @@ -798,8 +792,8 @@ CFRange _CFDataFindBytes(CFDataRef data, CFDataRef dataToFind, CFRange searchRan CFRange CFDataFind(CFDataRef data, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions) { // No objc dispatch - __CFGenericValidateType(data, __kCFDataTypeID); - __CFGenericValidateType(dataToFind, __kCFDataTypeID); + __CFGenericValidateType(data, CFDataGetTypeID()); + __CFGenericValidateType(dataToFind, CFDataGetTypeID()); __CFDataValidateRange(data, searchRange, __PRETTY_FUNCTION__); return _CFDataFindBytes(data, dataToFind, searchRange, compareOptions); diff --git a/CFData.h b/CFData.h index d81a3b5..97e951a 100644 --- a/CFData.h +++ b/CFData.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFData.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFDATA__) @@ -33,8 +33,8 @@ CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -typedef const struct __CFData * CFDataRef; -typedef struct __CFData * CFMutableDataRef; +typedef const struct CF_BRIDGED_TYPE(NSData) __CFData * CFDataRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMutableData) __CFData * CFMutableDataRef; CF_EXPORT CFTypeID CFDataGetTypeID(void); diff --git a/CFDate.c b/CFDate.c index 79c439b..e96fb9c 100644 --- a/CFDate.c +++ b/CFDate.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFDate.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -98,32 +98,6 @@ CFAbsoluteTime CFAbsoluteTimeGetCurrent(void) { return ret; } -CF_PRIVATE void __CFDateInitialize(void) { -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - struct mach_timebase_info info; - mach_timebase_info(&info); - __CFTSRRate = (1.0E9 / (double)info.numer) * (double)info.denom; - __CF1_TSRRate = 1.0 / __CFTSRRate; -#elif DEPLOYMENT_TARGET_WINDOWS - LARGE_INTEGER freq; - if (!QueryPerformanceFrequency(&freq)) { - HALT; - } - __CFTSRRate = (double)freq.QuadPart; - __CF1_TSRRate = 1.0 / __CFTSRRate; -#elif DEPLOYMENT_TARGET_LINUX - struct timespec res; - if (clock_getres(CLOCK_MONOTONIC, &res) != 0) { - HALT; - } - __CFTSRRate = res.tv_sec + (1000000000 * res.tv_nsec); - __CF1_TSRRate = 1.0 / __CFTSRRate; -#else -#error Unable to initialize date -#endif - CFDateGetTypeID(); // cause side-effects -} - struct __CFDate { CFRuntimeBase _base; CFAbsoluteTime _time; /* immutable */ @@ -161,7 +135,33 @@ static const CFRuntimeClass __CFDateClass = { }; CFTypeID CFDateGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFDateTypeID) __kCFDateTypeID = _CFRuntimeRegisterClass(&__CFDateClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFDateTypeID = _CFRuntimeRegisterClass(&__CFDateClass); + +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + struct mach_timebase_info info; + mach_timebase_info(&info); + __CFTSRRate = (1.0E9 / (double)info.numer) * (double)info.denom; + __CF1_TSRRate = 1.0 / __CFTSRRate; +#elif DEPLOYMENT_TARGET_WINDOWS + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq)) { + HALT; + } + __CFTSRRate = (double)freq.QuadPart; + __CF1_TSRRate = 1.0 / __CFTSRRate; +#elif DEPLOYMENT_TARGET_LINUX + struct timespec res; + if (clock_getres(CLOCK_MONOTONIC, &res) != 0) { + HALT; + } + __CFTSRRate = res.tv_sec + (1000000000 * res.tv_nsec); + __CF1_TSRRate = 1.0 / __CFTSRRate; +#else +#error Unable to initialize date +#endif + }); return __kCFDateTypeID; } diff --git a/CFDate.h b/CFDate.h index 5b5369a..01444fa 100644 --- a/CFDate.h +++ b/CFDate.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFDate.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFDATE__) @@ -46,7 +46,7 @@ const CFTimeInterval kCFAbsoluteTimeIntervalSince1970; CF_EXPORT const CFTimeInterval kCFAbsoluteTimeIntervalSince1904; -typedef const struct __CFDate * CFDateRef; +typedef const struct CF_BRIDGED_TYPE(NSDate) __CFDate * CFDateRef; CF_EXPORT CFTypeID CFDateGetTypeID(void); @@ -65,17 +65,12 @@ CFComparisonResult CFDateCompare(CFDateRef theDate, CFDateRef otherDate, void *c CF_IMPLICIT_BRIDGING_DISABLED -typedef const struct __CFTimeZone * CFTimeZoneRef; +typedef const struct CF_BRIDGED_TYPE(NSTimeZone) __CFTimeZone * CFTimeZoneRef; #if !defined(CF_CALENDAR_ENUM_DEPRECATED) -#if NS_ENABLE_CALENDAR_DEPRECATIONS #define CF_CALENDAR_ENUM_DEPRECATED(A, B, C, D, ...) CF_ENUM_DEPRECATED(A, B, C, D, __VA_ARGS__) #define CF_CALENDAR_DEPRECATED(A, B, C, D, ...) CF_DEPRECATED(A, B, C, D, __VA_ARGS__) -#else -#define CF_CALENDAR_ENUM_DEPRECATED(A, B, C, D, ...) CF_ENUM_AVAILABLE(A, C) -#define CF_CALENDAR_DEPRECATED(A, B, C, D, ...) CF_AVAILABLE(A, C) -#endif #endif typedef struct { @@ -85,7 +80,7 @@ typedef struct { SInt8 hour; SInt8 minute; double second; -} CFGregorianDate CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +} CFGregorianDate CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); typedef struct { SInt32 years; @@ -94,41 +89,41 @@ typedef struct { SInt32 hours; SInt32 minutes; double seconds; -} CFGregorianUnits CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +} CFGregorianUnits CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); typedef CF_OPTIONS(CFOptionFlags, CFGregorianUnitFlags) { - kCFGregorianUnitsYears CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 0), - kCFGregorianUnitsMonths CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 1), - kCFGregorianUnitsDays CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 2), - kCFGregorianUnitsHours CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 3), - kCFGregorianUnitsMinutes CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 4), - kCFGregorianUnitsSeconds CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 5), - kCFGregorianAllUnits CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead") = 0x00FFFFFF + kCFGregorianUnitsYears CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 0), + kCFGregorianUnitsMonths CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 1), + kCFGregorianUnitsDays CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 2), + kCFGregorianUnitsHours CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 3), + kCFGregorianUnitsMinutes CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 4), + kCFGregorianUnitsSeconds CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = (1UL << 5), + kCFGregorianAllUnits CF_CALENDAR_ENUM_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead") = 0x00FFFFFF }; CF_EXPORT -Boolean CFGregorianDateIsValid(CFGregorianDate gdate, CFOptionFlags unitFlags) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +Boolean CFGregorianDateIsValid(CFGregorianDate gdate, CFOptionFlags unitFlags) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFAbsoluteTime CFGregorianDateGetAbsoluteTime(CFGregorianDate gdate, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +CFAbsoluteTime CFGregorianDateGetAbsoluteTime(CFGregorianDate gdate, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFGregorianDate CFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +CFGregorianDate CFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFAbsoluteTime CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTime at, CFTimeZoneRef tz, CFGregorianUnits units) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +CFAbsoluteTime CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTime at, CFTimeZoneRef tz, CFGregorianUnits units) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFGregorianUnits CFAbsoluteTimeGetDifferenceAsGregorianUnits(CFAbsoluteTime at1, CFAbsoluteTime at2, CFTimeZoneRef tz, CFOptionFlags unitFlags) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +CFGregorianUnits CFAbsoluteTimeGetDifferenceAsGregorianUnits(CFAbsoluteTime at1, CFAbsoluteTime at2, CFTimeZoneRef tz, CFOptionFlags unitFlags) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -SInt32 CFAbsoluteTimeGetDayOfWeek(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +SInt32 CFAbsoluteTimeGetDayOfWeek(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -SInt32 CFAbsoluteTimeGetDayOfYear(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +SInt32 CFAbsoluteTimeGetDayOfYear(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -SInt32 CFAbsoluteTimeGetWeekOfYear(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); +SInt32 CFAbsoluteTimeGetWeekOfYear(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_10, 2_0, 8_0, "Use CFCalendar or NSCalendar API instead"); CF_EXTERN_C_END diff --git a/CFDateFormatter.c b/CFDateFormatter.c index e539e91..c3d4337 100644 --- a/CFDateFormatter.c +++ b/CFDateFormatter.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFDateFormatter.c - Copyright (c) 2002-2013, Apple Inc. All rights reserved. + Copyright (c) 2002-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -54,6 +54,8 @@ typedef CF_ENUM(CFIndex, CFDateFormatterAmbiguousYearHandling) { extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz); +static CONST_STRING_DECL(kCFDateFormatterFormattingContextKey, "kCFDateFormatterFormattingContextKey"); + CF_EXPORT const CFStringRef kCFDateFormatterCalendarIdentifierKey; #undef CFReleaseIfNotNull @@ -61,7 +63,7 @@ CF_EXPORT const CFStringRef kCFDateFormatterCalendarIdentifierKey; #define BUFFER_SIZE 768 -static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFStringRef inString); +static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFStringRef inString, Boolean stripAMPM); // If you pass in a string in tmplate, you get back NULL (failure) or a CFStringRef. // If you pass in an array in tmplate, you get back NULL (global failure) or a CFArrayRef with CFStringRefs or kCFNulls (per-template failure) at each corresponding index. @@ -70,11 +72,17 @@ CFArrayRef CFDateFormatterCreateDateFormatsFromTemplates(CFAllocatorRef allocato return (CFArrayRef)CFDateFormatterCreateDateFormatFromTemplate(allocator, (CFStringRef)tmplates, options, locale); } -static Boolean useTemplatePatternGenerator(const char *localeName, void(^work)(UDateTimePatternGenerator *ptg)) { +static Boolean useTemplatePatternGenerator(CFLocaleRef locale, void(^work)(UDateTimePatternGenerator *ptg)) { static UDateTimePatternGenerator *ptg; static pthread_mutex_t ptgLock = PTHREAD_MUTEX_INITIALIZER; static const char *ptgLocaleName; - + CFStringRef ln = locale ? CFLocaleGetIdentifier(locale) : CFSTR(""); + char buffer[BUFFER_SIZE]; + const char *localeName = CFStringGetCStringPtr(ln, kCFStringEncodingASCII); + if (NULL == localeName) { + if (CFStringGetCString(ln, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) localeName = buffer; + } + static void (^flushCache)() = ^{ __cficu_udatpg_close(ptg); ptg = NULL; @@ -99,7 +107,35 @@ static Boolean useTemplatePatternGenerator(const char *localeName, void(^work)(U pthread_mutex_unlock(&ptgLock); return result; } - + +/* + 1) Scan the string for an AM/PM indicator + 2) Back up past any spaces in front of the AM/PM indicator + 3) As long as the current character is whitespace, or an 'a', remove it and shift everything past it down + */ +static void _CFDateFormatterStripAMPMIndicators(UniChar **bpat, int32_t *bpatlen, CFIndex bufferSize) { + + //scan + for (CFIndex idx = 0; idx < *bpatlen; idx++) { + if ((*bpat)[idx] == 'a') { + + //back up + while ((*bpat)[idx - 1] == ' ') { + idx--; + } + + //shift + for (; (*bpat)[idx] == ' ' || (*bpat)[idx] == 'a'; idx++) { + for (CFIndex shiftIdx = idx; shiftIdx < *bpatlen && shiftIdx + 1 < bufferSize; shiftIdx++) { + (*bpat)[shiftIdx] = (*bpat)[shiftIdx + 1]; + } + //compensate for the character we just removed + (*bpatlen)--; + idx--; + } + } + } +} CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator, CFStringRef tmplate, CFOptionFlags options, CFLocaleRef locale) { if (allocator) __CFGenericValidateType(allocator, CFAllocatorGetTypeID()); @@ -108,38 +144,32 @@ CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator if (!tmplateIsString) { __CFGenericValidateType(tmplate, CFArrayGetTypeID()); } - - CFStringRef localeName = locale ? CFLocaleGetIdentifier(locale) : CFSTR(""); - char buffer[BUFFER_SIZE]; - const char *cstr = CFStringGetCStringPtr(localeName, kCFStringEncodingASCII); - if (NULL == cstr) { - if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer; - } - if (NULL == cstr) { - return NULL; - } __block CFTypeRef result = tmplateIsString ? NULL : (CFTypeRef)CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); - Boolean success = useTemplatePatternGenerator(cstr, ^(UDateTimePatternGenerator *ptg) { + Boolean success = useTemplatePatternGenerator(locale, ^(UDateTimePatternGenerator *ptg) { for (CFIndex idx = 0, cnt = tmplateIsString ? 1 : CFArrayGetCount((CFArrayRef)tmplate); idx < cnt; idx++) { CFStringRef tmplateString = tmplateIsString ? (CFStringRef)tmplate : (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)tmplate, idx); CFStringRef resultString = NULL; - tmplateString = __CFDateFormatterCreateForcedTemplate(locale ? locale : CFLocaleGetSystem(), tmplateString); + Boolean stripAMPM = CFStringFind(tmplateString, CFSTR("J"), 0).location != kCFNotFound; + tmplateString = __CFDateFormatterCreateForcedTemplate(locale ? locale : CFLocaleGetSystem(), tmplateString, stripAMPM); CFIndex jCount = 0; // the only interesting cases are 0, 1, and 2 (adjacent) - CFRange r = CFStringFind(tmplateString, CFSTR("j"), 0); + UniChar adjacentJs[2] = {-1, -1}; + CFRange r = CFStringFind(tmplateString, CFSTR("j"), kCFCompareCaseInsensitive); if (kCFNotFound != r.location) { + adjacentJs[0] = CFStringGetCharacterAtIndex(tmplateString, r.location); jCount++; - if ((r.location + 1 < CFStringGetLength(tmplateString)) && ('j' == CFStringGetCharacterAtIndex(tmplateString, r.location + 1))) { + if ((r.location + 1 < CFStringGetLength(tmplateString)) && ('j' == CFStringGetCharacterAtIndex(tmplateString, r.location + 1) || 'J' == CFStringGetCharacterAtIndex(tmplateString, r.location + 1))) { jCount++; + adjacentJs[1] = CFStringGetCharacterAtIndex(tmplateString, r.location + 1); } } - UChar pattern[BUFFER_SIZE], skel[BUFFER_SIZE], bpat[BUFFER_SIZE]; + UChar pattern[BUFFER_SIZE] = {0}, skel[BUFFER_SIZE] = {0}, bpat[BUFFER_SIZE] = {0}; CFIndex tmpltLen = CFStringGetLength(tmplateString); if (BUFFER_SIZE < tmpltLen) tmpltLen = BUFFER_SIZE; CFStringGetCharacters(tmplateString, CFRangeMake(0, tmpltLen), (UniChar *)pattern); @@ -150,13 +180,19 @@ CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator int32_t skellen = __cficu_udatpg_getSkeleton(ptg, pattern, patlen, skel, sizeof(skel) / sizeof(skel[0]), &status); if (!U_FAILURE(status)) { if ((0 < jCount) && (skellen + jCount < (sizeof(skel) / sizeof(skel[0])))) { - skel[skellen++] = 'j'; - if (1 < jCount) skel[skellen++] = 'j'; + + skel[skellen++] = 'j'; //adjacentJs[0]; + if (1 < jCount) skel[skellen++] = 'j'; //adjacentJs[1]; + //stripAMPM = false; //'J' will take care of it. We only need to do it manually if we stripped the Js out ourselves while forcing 12/24 hour time } status = U_ZERO_ERROR; int32_t bpatlen = __cficu_udatpg_getBestPattern(ptg, skel, skellen, bpat, sizeof(bpat) / sizeof(bpat[0]), &status); if (!U_FAILURE(status)) { + if (stripAMPM) { + UniChar *bpatptr = (UniChar *)bpat; + _CFDateFormatterStripAMPMIndicators(&bpatptr, &bpatlen, BUFFER_SIZE); + } resultString = CFStringCreateWithCharacters(allocator, (const UniChar *)bpat, bpatlen); } } @@ -171,7 +207,7 @@ CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator }); if (!success) { - CFRelease(result); + if (result) CFRelease(result); result = NULL; } @@ -218,6 +254,7 @@ struct __CFDateFormatter { CFStringRef _PMSymbol; CFNumberRef _AmbiguousYearStrategy; CFBooleanRef _UsesCharacterDirection; + CFNumberRef _FormattingContext; // the following are from preferences CFArrayRef _CustomEraSymbols; @@ -291,6 +328,7 @@ static void __CFDateFormatterDeallocate(CFTypeRef cf) { CFReleaseIfNotNull(formatter->_property._PMSymbol); CFReleaseIfNotNull(formatter->_property._AmbiguousYearStrategy); CFReleaseIfNotNull(formatter->_property._UsesCharacterDirection); + CFReleaseIfNotNull(formatter->_property._FormattingContext); CFReleaseIfNotNull(formatter->_property._CustomEraSymbols); CFReleaseIfNotNull(formatter->_property._CustomMonthSymbols); CFReleaseIfNotNull(formatter->_property._CustomShortMonthSymbols); @@ -595,9 +633,17 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF UErrorCode status = U_ZERO_ERROR; UDateFormat *icudf = __cficu_udat_open((UDateFormatStyle)utstyle, (UDateFormatStyle)udstyle, loc_buffer, tz_buffer, CFStringGetLength(tmpTZName), NULL, 0, &status); + if (NULL == icudf || U_FAILURE(status)) { return; } + + // "Yesterday" and "Today" now appear in lower case + // ICU uses middle of sentence context for relative days by default. We need to have relative dates to be captalized by default for backward compatibility + if (wantRelative) { + __cficu_udat_setContext(icudf, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, &status); + } + if (df->_property._IsLenient != NULL) { __cficu_udat_setLenient(icudf, (kCFBooleanTrue == df->_property._IsLenient)); } else { @@ -714,6 +760,7 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF RESET_PROPERTY(_GregorianStartDate, kCFDateFormatterGregorianStartDateKey); RESET_PROPERTY(_AmbiguousYearStrategy, kCFDateFormatterAmbiguousYearStrategyKey); RESET_PROPERTY(_UsesCharacterDirection, kCFDateFormatterUsesCharacterDirectionKey); + RESET_PROPERTY(_FormattingContext, kCFDateFormatterFormattingContextKey); } static CFTypeID __kCFDateFormatterTypeID = _kCFRuntimeNotATypeID; @@ -730,12 +777,9 @@ static const CFRuntimeClass __CFDateFormatterClass = { __CFDateFormatterCopyDescription }; -static void __CFDateFormatterInitialize(void) { - __kCFDateFormatterTypeID = _CFRuntimeRegisterClass(&__CFDateFormatterClass); -} - CFTypeID CFDateFormatterGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFDateFormatterTypeID) __CFDateFormatterInitialize(); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFDateFormatterTypeID = _CFRuntimeRegisterClass(&__CFDateFormatterClass); }); return __kCFDateFormatterTypeID; } @@ -786,6 +830,7 @@ CFDateFormatterRef CFDateFormatterCreate(CFAllocatorRef allocator, CFLocaleRef l memory->_property._PMSymbol = NULL; memory->_property._AmbiguousYearStrategy = NULL; memory->_property._UsesCharacterDirection = NULL; + memory->_property._FormattingContext = NULL; memory->_property._CustomEraSymbols = NULL; memory->_property._CustomMonthSymbols = NULL; memory->_property._CustomShortMonthSymbols = NULL; @@ -1026,9 +1071,8 @@ static void __CFDateFormatterStoreSymbolPrefs(const void *key, const void *value } } -static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFStringRef inString) { +static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFStringRef inString, Boolean stripAMPM) { if (!inString) return NULL; - Boolean doForce24 = false, doForce12 = false; CFDictionaryRef prefs = __CFLocaleGetPrefs(locale); CFPropertyListRef pref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce24HourTime")) : NULL; @@ -1051,6 +1095,7 @@ static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFS UniChar ch = CFStringGetCharacterAtIndex(inString, idx); switch (ch) { case '\'': isInQuote = !isInQuote; break; + case 'J': //fall through case 'j': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); if (doForce24) ch = 'H'; else ch = 'h';} break; case 'h': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had12Hour = true; if (doForce24) ch = 'H';} break; // switch 12-hour to 24-hour case 'K': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had12Hour = true; if (doForce24) ch = 'k';} break; // switch 12-hour to 24-hour @@ -1058,7 +1103,7 @@ static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFS case 'k': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'K';} break; // switch 24-hour to 12-hour case 'm': if (!isInQuote) lastMinute = CFStringGetLength(outString); break; case 's': if (!isInQuote) lastSecond = CFStringGetLength(outString); break; - case 'a': if (!isInQuote) {hasA = true; if (doForce24) emit = false;} break; + case 'a': if (!isInQuote) {hasA = true; if (doForce24 || stripAMPM) emit = false;} break; break; } if (emit) CFStringAppendCharacters(outString, &ch, 1); @@ -1067,80 +1112,18 @@ static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFS return outString; } -/* - Mapping H<->h and K<->k is not correct in all locales; Japanese 12 hour, for example, uses H<->k - This gets an approximately correct replacement character for the locale and forcing direction in question - [iCal] Incorrect time format is used for current time indicator line - */ -static UChar __CFDateFormatterForcedHourCharacterForLocale(CFLocaleRef locale, Boolean doForce24, Boolean doForce12, Boolean *succeeded) { - if (doForce24) doForce12 = false; // if both are set, Force24 wins, period - if (!locale || (!doForce24 && !doForce12)) { - *succeeded = false; - return '\0'; - } - CFStringRef localeName = locale ? CFLocaleGetIdentifier(locale) : CFSTR(""); - char buffer[BUFFER_SIZE] = {0}; - const char *cstr = CFStringGetCStringPtr(localeName, kCFStringEncodingASCII); - if (NULL == cstr) { - if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer; - } - - __block UChar hourPatternChar = '\0'; - - useTemplatePatternGenerator(cstr, ^(UDateTimePatternGenerator *ptg) { - UChar hourPattern[256] = {0}; - int32_t patternLen = -1; - if (ptg) { - UErrorCode errorCode = U_ZERO_ERROR; - patternLen = __cficu_udatpg_getBestPattern(ptg, (const UChar *)(doForce12 ? "h" : "H"), 1, hourPattern, sizeof(hourPattern) / sizeof(UChar), &errorCode); - if (errorCode != U_ZERO_ERROR) { - memset(hourPattern, 0, sizeof(hourPattern)); //make sure there's nothing there if we failed - patternLen = -1; - } - } - - /* - Blindly replacing HHHH with four copies of the entire udatpg_getBestPattern result is not going to work. Search for the first [hHkK] in the result and use just that - */ - if (patternLen > 0) { - for (CFIndex idx = 0; hourPattern[idx] != '\0' && idx < patternLen && idx < sizeof(hourPattern) / sizeof(UChar); idx++) { - if (hourPattern[idx] == 'k' || hourPattern[idx] == 'K' || hourPattern[idx] == 'h' || hourPattern[idx] == 'H') { - hourPatternChar = hourPattern[idx]; - break; - } - } - } - }); - - *succeeded = hourPatternChar != '\0'; - return hourPatternChar; -} - -#define FORCE_CHAR(replacement, oldType, newType) do { \ - if (!isInQuote) {\ - if (-1 == firstHour) {\ - firstHour = CFStringGetLength(outString);\ - }\ - had##oldType##Hour = true;\ - if (doForce##newType) {\ - ch = useSpecialHourChar ? hourPatternChar : replacement;\ - }\ - }\ -}while(0) -#define FORCE_CHAR_12(replacement) FORCE_CHAR(replacement, 12, 24) -#define FORCE_CHAR_24(replacement) FORCE_CHAR(replacement, 24, 12) - static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef formatter, CFStringRef inString) { if (!inString) return NULL; - - Boolean doForce24 = false, doForce12 = false; - if (formatter->_property._Custom24Hour != NULL) { - doForce24 = CFBooleanGetValue((CFBooleanRef)formatter->_property._Custom24Hour); + + UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS; + + if (formatter->_property._Custom12Hour != NULL && CFBooleanGetValue((CFBooleanRef)formatter->_property._Custom12Hour)) { + options = UADATPG_FORCE_12_HOUR_CYCLE; } - if (formatter->_property._Custom12Hour != NULL) { - doForce12 = CFBooleanGetValue((CFBooleanRef)formatter->_property._Custom12Hour); + if (formatter->_property._Custom24Hour != NULL && CFBooleanGetValue((CFBooleanRef)formatter->_property._Custom24Hour)) { + options = UADATPG_FORCE_24_HOUR_CYCLE; //force 24 hour always wins if both are specified } - if (doForce24) doForce12 = false; // if both are set, Force24 wins, period + if (options == UDATPG_MATCH_NO_OPTIONS) return (CFStringRef)CFRetain(inString); static CFCharacterSetRef hourCharacters; static dispatch_once_t onceToken; @@ -1150,79 +1133,35 @@ static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef format CFRange hourRange = CFRangeMake(kCFNotFound, 0); if (!CFStringFindCharacterFromSet(inString, hourCharacters, CFRangeMake(0, CFStringGetLength(inString)), 0, &hourRange) || hourRange.location == kCFNotFound) { - doForce12 = false; - doForce24 = false; + return (CFStringRef)CFRetain(inString); } - - if (!doForce24 && !doForce12) return (CFStringRef)CFRetain(inString); - - Boolean useSpecialHourChar = false; - UChar hourPatternChar = __CFDateFormatterForcedHourCharacterForLocale(formatter->_locale, doForce24, doForce12, &useSpecialHourChar); - - CFMutableStringRef outString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - CFIndex cnt = CFStringGetLength(inString); - CFIndex lastSecond = -1, lastMinute = -1, firstHour = -1; - Boolean isInQuote = false, hasA = false, had12Hour = false, had24Hour = false; - for (CFIndex idx = 0; idx < cnt; idx++) { - Boolean emit = true; - UniChar ch = CFStringGetCharacterAtIndex(inString, idx); - switch (ch) { - case '\'': isInQuote = !isInQuote; break; - case 'h': FORCE_CHAR_12('H'); break; // switch 12-hour to 24-hour - case 'k': FORCE_CHAR_24('K'); break; // switch 24-hour to 12-hour - case 'H': FORCE_CHAR_24('h'); break; // switch 24-hour to 12-hour - case 'K': FORCE_CHAR_12('k'); break; // switch 12-hour to 24-hour - case 'm': if (!isInQuote) lastMinute = CFStringGetLength(outString); break; - case 's': if (!isInQuote) lastSecond = CFStringGetLength(outString); break; - case 'a': if (!isInQuote) hasA = true; - if (!isInQuote && doForce24) { - // skip 'a' and one optional trailing space - emit = false; - if (idx + 1 < cnt && ' ' == CFStringGetCharacterAtIndex(inString, idx + 1)) idx++; - } - break; - case ' ': - if (!isInQuote && doForce24) { - // if next character is 'a' AND we have seen the hour designator, skip space and 'a' - if (idx + 1 < cnt && 'a' == CFStringGetCharacterAtIndex(inString, idx + 1) && -1 != firstHour) { - emit = false; - idx++; - } - } - break; + __block CFStringRef result = NULL; + __block int32_t newPatternLen = 0; + Boolean success = useTemplatePatternGenerator(formatter->_locale, ^(UDateTimePatternGenerator *ptg) { + CFIndex cnt = CFStringGetLength(inString); + STACK_BUFFER_DECL(UChar, ubuffer, cnt); + const UChar *ustr = (UChar *)CFStringGetCharactersPtr(inString); + if (NULL == ustr) { + CFStringGetCharacters(inString, CFRangeMake(0, cnt), (UniChar *)ubuffer); + ustr = ubuffer; } - if (emit) CFStringAppendCharacters(outString, &ch, 1); - } - if (doForce12 && !hasA && had24Hour) { - CFStringRef locName = CFLocaleGetIdentifier(formatter->_locale); - if (-1 != firstHour && (CFStringHasPrefix(locName, CFSTR("ko")) || CFEqual(locName, CFSTR("zh_SG")))) { - CFStringInsert(outString, firstHour, CFSTR("a ")); - } else if (-1 != firstHour && (CFStringHasPrefix(locName, CFSTR("zh")) || CFStringHasPrefix(locName, CFSTR("ja")))) { - CFStringInsert(outString, firstHour, CFSTR("a")); - } else { - CFIndex lastPos = (-1 != lastSecond) ? lastSecond : ((-1 != lastMinute) ? lastMinute : -1); - if (-1 != lastPos) { - cnt = CFStringGetLength(outString); - lastPos++; - UniChar ch = (lastPos < cnt) ? CFStringGetCharacterAtIndex(outString, lastPos) : 0; - switch (ch) { - case '\"': lastPos++; break; - case '\'':; - again:; - do { - lastPos++; - ch = (lastPos < cnt) ? CFStringGetCharacterAtIndex(outString, lastPos) : 0; - } while ('\'' != ch && '\0' != ch); - if ('\'' == ch) lastPos++; - ch = (lastPos < cnt) ? CFStringGetCharacterAtIndex(outString, lastPos) : 0; - if ('\'' == ch) goto again; - break; - } - CFStringInsert(outString, lastPos, CFSTR(" a")); + STACK_BUFFER_DECL(UChar, outBuffer, 256); + + UErrorCode err = U_ZERO_ERROR; + newPatternLen = uadatpg_remapPatternWithOptions(ptg, ustr, cnt, options, outBuffer, 256, &err); + if (U_SUCCESS(err)) { + result = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, outBuffer, newPatternLen); + } else if (err == U_BUFFER_OVERFLOW_ERROR) { + err = U_ZERO_ERROR; + UChar *largerBuffer = calloc(newPatternLen + 1, sizeof(UChar)); + newPatternLen = uadatpg_remapPatternWithOptions(ptg, ustr, cnt, options, outBuffer, newPatternLen + 1, &err); + if (U_SUCCESS(err)) { + result = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, largerBuffer, newPatternLen); } + free(largerBuffer); } - } - return outString; + }); + return success && result && newPatternLen > 0 ? result : CFRetain(inString); } CFLocaleRef CFDateFormatterGetLocale(CFDateFormatterRef formatter) { @@ -1915,6 +1854,18 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR __CFGenericValidateType(value, CFBooleanGetTypeID()); oldProperty = formatter->_property._UsesCharacterDirection; formatter->_property._UsesCharacterDirection = (CFBooleanRef)CFRetain(value); + } else if (CFEqual(key, kCFDateFormatterFormattingContextKey)) { + if (!directToICU) { + oldProperty = formatter->_property. _FormattingContext; + formatter->_property._FormattingContext = NULL; + } + __CFGenericValidateType(value, CFNumberGetTypeID()); + int context = 0; + CFNumberGetValue(value, kCFNumberIntType, &context); + __cficu_udat_setContext(formatter->_df, context, &status); + if (!directToICU) { + formatter->_property._FormattingContext = (CFNumberRef)CFRetain(value); + } } else { CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key); } @@ -2037,6 +1988,10 @@ CFTypeRef CFDateFormatterCopyProperty(CFDateFormatterRef formatter, CFStringRef if (formatter->_property._AmbiguousYearStrategy) return CFRetain(formatter->_property._AmbiguousYearStrategy); } else if (kCFDateFormatterUsesCharacterDirectionKey == key) { return formatter->_property._UsesCharacterDirection ? CFRetain(formatter->_property._UsesCharacterDirection) : CFRetain(kCFBooleanFalse); + } else if (CFEqual(key, kCFDateFormatterFormattingContextKey)) { + if (formatter->_property._FormattingContext) return CFRetain(formatter->_property._FormattingContext); + int value = __cficu_udat_getContext(formatter->_df, UDISPCTX_TYPE_CAPITALIZATION, &status); + return CFNumberCreate(CFGetAllocator(formatter), kCFNumberIntType, (const void *)&value); } else { CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key); } diff --git a/CFDateFormatter.h b/CFDateFormatter.h index 81b4259..10f4f2d 100644 --- a/CFDateFormatter.h +++ b/CFDateFormatter.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFDateFormatter.h - Copyright (c) 2003-2013, Apple Inc. All rights reserved. + Copyright (c) 2003-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFDATEFORMATTER__) @@ -32,6 +32,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFDateFormatter *CFDateFormatterRef; @@ -167,6 +168,7 @@ CF_EXPORT const CFStringRef kCFDateFormatterDoesRelativeDateFormattingKey CF_AVA // const CFStringRef kCFISO8601Calendar; CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFDATEFORMATTER__ */ diff --git a/CFDictionary.c b/CFDictionary.c index e5fa4a7..c5cd29b 100644 --- a/CFDictionary.c +++ b/CFDictionary.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFDictionary.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane Machine generated from Notes/HashingCode.template */ @@ -47,8 +47,6 @@ const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; -static const CFDictionaryKeyCallBacks __kCFNullDictionaryKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; -static const CFDictionaryValueCallBacks __kCFNullDictionaryValueCallBacks = {0, NULL, NULL, NULL, NULL}; #define CFHashRef CFDictionaryRef #define CFMutableHashRef CFMutableDictionaryRef @@ -59,14 +57,11 @@ static const CFDictionaryValueCallBacks __kCFNullDictionaryValueCallBacks = {0, #if CFSet const CFDictionaryCallBacks kCFTypeDictionaryCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFDictionaryCallBacks kCFCopyStringDictionaryCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; -static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; #define CFDictionaryKeyCallBacks CFDictionaryCallBacks #define CFDictionaryValueCallBacks CFDictionaryCallBacks #define kCFTypeDictionaryKeyCallBacks kCFTypeDictionaryCallBacks #define kCFTypeDictionaryValueCallBacks kCFTypeDictionaryCallBacks -#define __kCFNullDictionaryKeyCallBacks __kCFNullDictionaryCallBacks -#define __kCFNullDictionaryValueCallBacks __kCFNullDictionaryCallBacks #define CFHashRef CFSetRef #define CFMutableHashRef CFMutableSetRef @@ -77,14 +72,11 @@ static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL #if CFBag const CFDictionaryCallBacks kCFTypeDictionaryCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFDictionaryCallBacks kCFCopyStringDictionaryCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; -static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; #define CFDictionaryKeyCallBacks CFDictionaryCallBacks #define CFDictionaryValueCallBacks CFDictionaryCallBacks #define kCFTypeDictionaryKeyCallBacks kCFTypeDictionaryCallBacks #define kCFTypeDictionaryValueCallBacks kCFTypeDictionaryCallBacks -#define __kCFNullDictionaryKeyCallBacks __kCFNullDictionaryCallBacks -#define __kCFNullDictionaryValueCallBacks __kCFNullDictionaryCallBacks #define CFHashRef CFBagRef #define CFMutableHashRef CFMutableBagRef @@ -128,7 +120,8 @@ static const CFRuntimeClass __CFDictionaryClass = { }; CFTypeID CFDictionaryGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFDictionaryTypeID) __kCFDictionaryTypeID = _CFRuntimeRegisterClass(&__CFDictionaryClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFDictionaryTypeID = _CFRuntimeRegisterClass(&__CFDictionaryClass); }); return __kCFDictionaryTypeID; } @@ -368,9 +361,13 @@ CFMutableHashRef CFDictionaryCreateMutableCopy(CFAllocatorRef allocator, CFIndex } CFIndex CFDictionaryGetCount(CFHashRef hc) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, count); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSSet *)hc, count); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), CFIndex, (NSDictionary *)hc, count); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), CFIndex, (NSSet *)hc, count); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return CFBasicHashGetCount((CFBasicHashRef)hc); } @@ -380,9 +377,13 @@ CFIndex CFDictionaryGetCountOfKey(CFHashRef hc, const_any_pointer_t key) { #if CFSet || CFBag CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t key) { #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), CFIndex, (NSDictionary *)hc, countForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), CFIndex, (NSSet *)hc, countForObject:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key); } @@ -392,24 +393,36 @@ Boolean CFDictionaryContainsKey(CFHashRef hc, const_any_pointer_t key) { #if CFSet || CFBag Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t key) { #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSDictionary *)hc, containsKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSSet *)hc, containsObject:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), char, (NSDictionary *)hc, containsKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), char, (NSSet *)hc, containsObject:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key)); } const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), const_any_pointer_t, (NSSet *)hc, member:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0); } Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); if (0 < bkt.count) { if (value) { @@ -426,19 +439,19 @@ Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, con #if CFDictionary CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) { - CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); + CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), CFIndex, (NSDictionary *)hc, countForObject:(id)value); + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value); } Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) { - CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSDictionary *)hc, containsObject:(id)value); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); + CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), char, (NSDictionary *)hc, containsObject:(id)value); + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value)); } CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) { - __CFGenericValidateType(hc, __kCFDictionaryTypeID); + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); if (0 < bkt.count) { if (actualkey) { @@ -461,9 +474,13 @@ void CFDictionaryGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, con void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { const_any_pointer_t *valuebuf = 0; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSSet *)hc, getObjects:(id *)keybuf); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); if (kCFUseCollectableAllocator) { CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc); __block const_any_pointer_t *keys = keybuf; @@ -484,9 +501,13 @@ void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier, any_pointer_t context) { FAULT_CALLBACK((void **)&(applier)); - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) { #if CFDictionary INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context); @@ -505,22 +526,22 @@ void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier // This function is for Foundation's benefit; no one else should use it. CF_EXPORT unsigned long _CFDictionaryFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) { - if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return 0; - __CFGenericValidateType(hc, __kCFDictionaryTypeID); + if (CF_IS_OBJC(CFDictionaryGetTypeID(), hc)) return 0; + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count); } // This function is for Foundation's benefit; no one else should use it. CF_EXPORT Boolean _CFDictionaryIsMutable(CFHashRef hc) { - if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return false; - __CFGenericValidateType(hc, __kCFDictionaryTypeID); + if (CF_IS_OBJC(CFDictionaryGetTypeID(), hc)) return false; + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); return CFBasicHashIsMutable((CFBasicHashRef)hc); } // This function is for Foundation's benefit; no one else should use it. CF_EXPORT void _CFDictionarySetCapacity(CFMutableHashRef hc, CFIndex cap) { - if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return; - __CFGenericValidateType(hc, __kCFDictionaryTypeID); + if (CF_IS_OBJC(CFDictionaryGetTypeID(), hc)) return; + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); CFAssert3(CFDictionaryGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFDictionaryGetCount(hc)); CFBasicHashSetCapacity((CFBasicHashRef)hc, cap); @@ -559,9 +580,13 @@ void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_an void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, addObject:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableSet *)hc, addObject:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -578,9 +603,13 @@ void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, cons void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableSet *)hc, replaceObject:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -597,9 +626,13 @@ void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key, const_an void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, setObject:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableSet *)hc, setObject:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -611,9 +644,13 @@ void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) { } void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, removeObject:(id)key); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableSet *)hc, removeObject:(id)key); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -624,9 +661,13 @@ void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { } void CFDictionaryRemoveAllValues(CFMutableHashRef hc) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, removeAllObjects); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, removeAllObjects); - __CFGenericValidateType(hc, __kCFDictionaryTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableDictionary *)hc, removeAllObjects); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFDictionaryGetTypeID(), void, (NSMutableSet *)hc, removeAllObjects); +#endif + __CFGenericValidateType(hc, CFDictionaryGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); diff --git a/CFDictionary.h b/CFDictionary.h index 17bd863..5e7508e 100644 --- a/CFDictionary.h +++ b/CFDictionary.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFDictionary.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /*! @@ -201,13 +201,13 @@ typedef void (*CFDictionaryApplierFunction)(const void *key, const void *value, @typedef CFDictionaryRef This is the type of a reference to immutable CFDictionarys. */ -typedef const struct __CFDictionary * CFDictionaryRef; +typedef const struct CF_BRIDGED_TYPE(NSDictionary) __CFDictionary * CFDictionaryRef; /*! @typedef CFMutableDictionaryRef This is the type of a reference to mutable CFDictionarys. */ -typedef struct __CFDictionary * CFMutableDictionaryRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMutableDictionary) __CFDictionary * CFMutableDictionaryRef; /*! @function CFDictionaryGetTypeID diff --git a/CFError.c b/CFError.c index c9c6541..2cb71b9 100644 --- a/CFError.c +++ b/CFError.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFError.c - Copyright (c) 2006-2013, Apple Inc. All rights reserved. + Copyright (c) 2006-2014, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -72,11 +72,11 @@ static CFDictionaryRef _CFErrorCreateEmptyDictionary(CFAllocatorRef allocator); /* Assertions and other macros/inlines */ -#define __CFAssertIsError(cf) __CFGenericValidateType(cf, __kCFErrorTypeID) +#define __CFAssertIsError(cf) __CFGenericValidateType(cf, CFErrorGetTypeID()) /* This lock is used in the few places in CFError where we create and access shared static objects. Should only be around tiny snippets of code; no recursion */ -static CFSpinLock_t _CFErrorSpinlock = CFSpinLockInit; +static CFLock_t _CFErrorSpinlock = CFLockInit; @@ -160,11 +160,9 @@ static const CFRuntimeClass __CFErrorClass = { __CFErrorCopyDescription }; -CF_PRIVATE void __CFErrorInitialize(void) { - __kCFErrorTypeID = _CFRuntimeRegisterClass(&__CFErrorClass); -} - CFTypeID CFErrorGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFErrorTypeID = _CFRuntimeRegisterClass(&__CFErrorClass); }); return __kCFErrorTypeID; } @@ -181,12 +179,12 @@ static CFDictionaryRef _CFErrorCreateEmptyDictionary(CFAllocatorRef allocator) { static CFDictionaryRef emptyErrorDictionary = NULL; if (emptyErrorDictionary == NULL) { CFDictionaryRef tmp = CFDictionaryCreate(allocator, NULL, NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - __CFSpinLock(&_CFErrorSpinlock); + __CFLock(&_CFErrorSpinlock); if (emptyErrorDictionary == NULL) { emptyErrorDictionary = tmp; - __CFSpinUnlock(&_CFErrorSpinlock); + __CFUnlock(&_CFErrorSpinlock); } else { - __CFSpinUnlock(&_CFErrorSpinlock); + __CFUnlock(&_CFErrorSpinlock); CFRelease(tmp); } } @@ -199,7 +197,7 @@ static CFDictionaryRef _CFErrorCreateEmptyDictionary(CFAllocatorRef allocator) { /* A non-retained accessor for the userInfo. Might return NULL in some cases, if the subclass of NSError returned nil for some reason. It works with a CF or NSError. */ static CFDictionaryRef _CFErrorGetUserInfo(CFErrorRef err) { - CF_OBJC_FUNCDISPATCHV(__kCFErrorTypeID, CFDictionaryRef, (NSError *)err, userInfo); + CF_OBJC_FUNCDISPATCHV(CFErrorGetTypeID(), CFDictionaryRef, (NSError *)err, userInfo); __CFAssertIsError(err); return err->userInfo; } @@ -337,12 +335,12 @@ CFErrorRef CFErrorCreate(CFAllocatorRef allocator, CFStringRef domain, CFIndex c __CFGenericValidateType(domain, CFStringGetTypeID()); if (userInfo) __CFGenericValidateType(userInfo, CFDictionaryGetTypeID()); - CFErrorRef err = (CFErrorRef)_CFRuntimeCreateInstance(allocator, __kCFErrorTypeID, sizeof(struct __CFError) - sizeof(CFRuntimeBase), NULL); + CFErrorRef err = (CFErrorRef)_CFRuntimeCreateInstance(allocator, CFErrorGetTypeID(), sizeof(struct __CFError) - sizeof(CFRuntimeBase), NULL); if (NULL == err) return NULL; - err->domain = CFStringCreateCopy(allocator, domain); - err->code = code; - err->userInfo = userInfo ? CFDictionaryCreateCopy(allocator, userInfo) : _CFErrorCreateEmptyDictionary(allocator); + ((struct __CFError *)err)->domain = CFStringCreateCopy(allocator, domain); + ((struct __CFError *)err)->code = code; + ((struct __CFError *)err)->userInfo = userInfo ? CFDictionaryCreateCopy(allocator, userInfo) : _CFErrorCreateEmptyDictionary(allocator); return err; } @@ -352,24 +350,24 @@ CFErrorRef CFErrorCreate(CFAllocatorRef allocator, CFStringRef domain, CFIndex c CFErrorRef CFErrorCreateWithUserInfoKeysAndValues(CFAllocatorRef allocator, CFStringRef domain, CFIndex code, const void *const *userInfoKeys, const void *const *userInfoValues, CFIndex numUserInfoValues) { __CFGenericValidateType(domain, CFStringGetTypeID()); - CFErrorRef err = (CFErrorRef)_CFRuntimeCreateInstance(allocator, __kCFErrorTypeID, sizeof(struct __CFError) - sizeof(CFRuntimeBase), NULL); + CFErrorRef err = (CFErrorRef)_CFRuntimeCreateInstance(allocator, CFErrorGetTypeID(), sizeof(struct __CFError) - sizeof(CFRuntimeBase), NULL); if (NULL == err) return NULL; - err->domain = CFStringCreateCopy(allocator, domain); - err->code = code; - err->userInfo = CFDictionaryCreate(allocator, (const void **)userInfoKeys, (const void **)userInfoValues, numUserInfoValues, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + ((struct __CFError *)err)->domain = CFStringCreateCopy(allocator, domain); + ((struct __CFError *)err)->code = code; + ((struct __CFError *)err)->userInfo = CFDictionaryCreate(allocator, (const void **)userInfoKeys, (const void **)userInfoValues, numUserInfoValues, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); return err; } CFStringRef CFErrorGetDomain(CFErrorRef err) { - CF_OBJC_FUNCDISPATCHV(__kCFErrorTypeID, CFStringRef, (NSError *)err, domain); + CF_OBJC_FUNCDISPATCHV(CFErrorGetTypeID(), CFStringRef, (NSError *)err, domain); __CFAssertIsError(err); return err->domain; } CFIndex CFErrorGetCode(CFErrorRef err) { - CF_OBJC_FUNCDISPATCHV(__kCFErrorTypeID, CFIndex, (NSError *)err, code); + CF_OBJC_FUNCDISPATCHV(CFErrorGetTypeID(), CFIndex, (NSError *)err, code); __CFAssertIsError(err); return err->code; } @@ -382,7 +380,7 @@ CFDictionaryRef CFErrorCopyUserInfo(CFErrorRef err) { } CFStringRef CFErrorCopyDescription(CFErrorRef err) { - if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially + if (CF_IS_OBJC(CFErrorGetTypeID(), err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially CFStringRef desc = (CFStringRef) CF_OBJC_CALLV((NSError *)err, localizedDescription); return desc ? (CFStringRef)CFRetain(desc) : NULL; // !!! It really should never return nil. } @@ -391,7 +389,7 @@ CFStringRef CFErrorCopyDescription(CFErrorRef err) { } CFStringRef CFErrorCopyFailureReason(CFErrorRef err) { - if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially + if (CF_IS_OBJC(CFErrorGetTypeID(), err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially CFStringRef str = (CFStringRef) CF_OBJC_CALLV((NSError *)err, localizedFailureReason); return str ? (CFStringRef)CFRetain(str) : NULL; // It's possible for localizedFailureReason to return nil } @@ -400,7 +398,7 @@ CFStringRef CFErrorCopyFailureReason(CFErrorRef err) { } CFStringRef CFErrorCopyRecoverySuggestion(CFErrorRef err) { - if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially + if (CF_IS_OBJC(CFErrorGetTypeID(), err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially CFStringRef str = (CFStringRef) CF_OBJC_CALLV((NSError *)err, localizedRecoverySuggestion); return str ? (CFStringRef)CFRetain(str) : NULL; // It's possible for localizedRecoverySuggestion to return nil } @@ -483,12 +481,12 @@ static CFTypeRef _CFErrorMachCallBack(CFErrorRef err, CFStringRef key) { static void _CFErrorInitializeCallBackTable(void) { // Create the table outside the lock CFMutableDictionaryRef table = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL); - __CFSpinLock(&_CFErrorSpinlock); + __CFLock(&_CFErrorSpinlock); if (!_CFErrorCallBackTable) { _CFErrorCallBackTable = table; - __CFSpinUnlock(&_CFErrorSpinlock); + __CFUnlock(&_CFErrorSpinlock); } else { - __CFSpinUnlock(&_CFErrorSpinlock); + __CFUnlock(&_CFErrorSpinlock); CFRelease(table); // Note, even though the table looks like it was initialized, we go on to register the items on this thread as well, since otherwise we might consult the table before the items are actually registered. } @@ -500,20 +498,20 @@ static void _CFErrorInitializeCallBackTable(void) { void CFErrorSetCallBackForDomain(CFStringRef domainName, CFErrorUserInfoKeyCallBack callBack) { if (!_CFErrorCallBackTable) _CFErrorInitializeCallBackTable(); - __CFSpinLock(&_CFErrorSpinlock); + __CFLock(&_CFErrorSpinlock); if (callBack) { CFDictionarySetValue(_CFErrorCallBackTable, domainName, (void *)callBack); } else { CFDictionaryRemoveValue(_CFErrorCallBackTable, domainName); } - __CFSpinUnlock(&_CFErrorSpinlock); + __CFUnlock(&_CFErrorSpinlock); } CFErrorUserInfoKeyCallBack CFErrorGetCallBackForDomain(CFStringRef domainName) { if (!_CFErrorCallBackTable) _CFErrorInitializeCallBackTable(); - __CFSpinLock(&_CFErrorSpinlock); + __CFLock(&_CFErrorSpinlock); CFErrorUserInfoKeyCallBack callBack = (CFErrorUserInfoKeyCallBack)CFDictionaryGetValue(_CFErrorCallBackTable, domainName); - __CFSpinUnlock(&_CFErrorSpinlock); + __CFUnlock(&_CFErrorSpinlock); return callBack; } diff --git a/CFError.h b/CFError.h index 7eba225..714e8ee 100644 --- a/CFError.h +++ b/CFError.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFError.h - Copyright (c) 2006-2013, Apple Inc. All rights reserved. + Copyright (c) 2006-2014, Apple Inc. All rights reserved. */ /*! @@ -63,7 +63,7 @@ CF_EXTERN_C_BEGIN @typedef CFErrorRef This is the type of a reference to CFErrors. CFErrorRef is toll-free bridged with NSError. */ -typedef struct __CFError * CFErrorRef; +typedef struct CF_BRIDGED_TYPE(NSError) __CFError * CFErrorRef; /*! @function CFErrorGetTypeID diff --git a/CFError_Private.h b/CFError_Private.h index ed7c8c8..0ac7d59 100644 --- a/CFError_Private.h +++ b/CFError_Private.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFError_Private.h - Copyright (c) 2006-2013, Apple Inc. All rights reserved. + Copyright (c) 2006-2014, Apple Inc. All rights reserved. This is Apple-internal SPI for CFError. */ diff --git a/CFFileUtilities.c b/CFFileUtilities.c index 58a9dbf..87fb8da 100644 --- a/CFFileUtilities.c +++ b/CFFileUtilities.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFFileUtilities.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -100,7 +100,7 @@ CF_PRIVATE Boolean _CFDeleteFile(const char *path) { return ret; } -CF_PRIVATE Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags, int *fd) { // maxLength is the number of bytes desired, or 0 if the whole file is desired regardless of length. +static Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags, int *fd) { // maxLength is the number of bytes desired, or 0 if the whole file is desired regardless of length. struct statinfo statBuf; *bytes = NULL; @@ -140,6 +140,12 @@ CF_PRIVATE Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, const char desiredLength = maxLength; } *bytes = CFAllocatorAllocate(alloc, desiredLength, 0); + if (!bytes) { + close(*fd); + *fd = -1; + closeAutoFSNoWait(no_hang_fd); + return false; + } if (__CFOASafe) __CFSetLastAllocationEventName(*bytes, "CFUtilities (file-bytes)"); // fcntl(fd, F_NOCACHE, 1); if (read(*fd, *bytes, desiredLength) < 0) { @@ -155,7 +161,7 @@ CF_PRIVATE Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, const char return true; } -CF_PRIVATE Boolean _CFReadBytesFromPath(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags) { +static Boolean _CFReadBytesFromPath(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags) { int fd = -1; Boolean result = _CFReadBytesFromPathAndGetFD(alloc, path, bytes, length, maxLength, extraOpenFlags, &fd); if (fd >= 0) { diff --git a/CFICUConverters.c b/CFICUConverters.c index 52af14e..1588ef8 100644 --- a/CFICUConverters.c +++ b/CFICUConverters.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFICUConverters.c - Copyright (c) 2004-2013, Apple Inc. All rights reserved. + Copyright (c) 2004-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ diff --git a/CFICUConverters.h b/CFICUConverters.h index 19556a7..0c24775 100644 --- a/CFICUConverters.h +++ b/CFICUConverters.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -26,7 +26,7 @@ * CoreFoundation * * Created by Aki Inoue on 07/12/04. - * Copyright (c) 2007-2013, Apple Inc. All rights reserved. + * Copyright (c) 2007-2014, Apple Inc. All rights reserved. * */ diff --git a/CFICULogging.h b/CFICULogging.h index 7b69f51..e8484ef 100644 --- a/CFICULogging.h +++ b/CFICULogging.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFICULogging.h - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. */ /* @@ -43,6 +43,7 @@ // ucal +// ucal #define __cficu_ucal_open ucal_open #define __cficu_ucal_close ucal_close #define __cficu_ucal_clone ucal_clone @@ -105,11 +106,13 @@ #define __cficu_unum_setSymbol unum_setSymbol #define __cficu_unum_setTextAttribute unum_setTextAttribute #define __cficu_unum_toPattern unum_toPattern - +#define __cficu_udat_setContext udat_setContext +#define __cficu_udat_getContext udat_getContext // ucurr - #define __cficu_ucurr_getDefaultFractionDigits ucurr_getDefaultFractionDigits #define __cficu_ucurr_getRoundingIncrement ucurr_getRoundingIncrement - +// unum +#define __cficu_unum_setContext unum_setContext +#define __cficu_unum_getContext unum_getContext #endif diff --git a/CFInternal.h b/CFInternal.h index 66dc507..eddd467 100644 --- a/CFInternal.h +++ b/CFInternal.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFInternal.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /* @@ -216,6 +216,7 @@ enum { __CFTSDKeyRunLoop = 10, __CFTSDKeyRunLoopCntr = 11, __CFTSDKeyMachMessageBoost = 12, // valid only in the context of a CFMachPort callout + __CFTSDKeyMachMessageHasVoucher = 13, // autorelease pool stuff must be higher than run loop constants __CFTSDKeyAutoreleaseData2 = 61, __CFTSDKeyAutoreleaseData1 = 62, @@ -387,104 +388,83 @@ CF_PRIVATE Boolean __CFProphylacticAutofsAccess; #if DEPLOYMENT_TARGET_MACOSX -typedef OSSpinLock CFSpinLock_t; - -#define CFSpinLockInit OS_SPINLOCK_INIT -#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit) - -#define __CFSpinLock(LP) ({ \ - OSSpinLock *__lockp__ = (LP); \ - OSSpinLock __lockv__ = *__lockp__; \ - if (0 != __lockv__ && ~0 != __lockv__ && (uintptr_t)__lockp__ != (uintptr_t)__lockv__) { \ - CFLog(3, CFSTR("In '%s', file %s, line %d, during lock, spin lock %p has value 0x%x, which is neither locked nor unlocked. The memory has been smashed."), __PRETTY_FUNCTION__, __FILE__, __LINE__, __lockp__, __lockv__); \ - /* HALT; */ \ - } \ - OSSpinLockLock(__lockp__); }) - -#define __CFSpinUnlock(LP) ({ \ - OSSpinLock *__lockp__ = (LP); \ - OSSpinLock __lockv__ = *__lockp__; \ - if (~0 != __lockv__ && (uintptr_t)__lockp__ != (uintptr_t)__lockv__) { \ - CFLog(3, CFSTR("In '%s', file %s, line %d, during unlock, spin lock %p has value 0x%x, which is not locked. The memory has been smashed or the lock is being unlocked when not locked."), __PRETTY_FUNCTION__, __FILE__, __LINE__, __lockp__, __lockv__); \ - /* HALT; */ \ - } \ - OSSpinLockUnlock(__lockp__); }) - -#define __CFSpinLockTry(LP) ({ \ - OSSpinLock *__lockp__ = (LP); \ - OSSpinLock __lockv__ = *__lockp__; \ - if (0 != __lockv__ && ~0 != __lockv__ && (uintptr_t)__lockp__ != (uintptr_t)__lockv__) { \ - CFLog(3, CFSTR("In '%s', file %s, line %d, during lock, spin lock %p has value 0x%x, which is neither locked nor unlocked. The memory has been smashed."), __PRETTY_FUNCTION__, __FILE__, __LINE__, __lockp__, __lockv__); \ - /* HALT; */ \ - } \ - OSSpinLockTry(__lockp__); }) +typedef pthread_mutex_t CFLock_t; + +#define CFLockInit ((pthread_mutex_t)PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) +#define CF_LOCK_INIT_FOR_STRUCTS(X) (X = CFLockInit) + +#define __CFLock(LP) ({ \ + (void)pthread_mutex_lock(LP); }) + +#define __CFUnlock(LP) ({ \ + (void)pthread_mutex_unlock(LP); }) + +#define __CFLockTry(LP) ({ \ + pthread_mutex_trylock(LP) == 0; }) #elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -typedef OSSpinLock CFSpinLock_t; +typedef pthread_mutex_t CFLock_t; -#define CFSpinLockInit OS_SPINLOCK_INIT -#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit) +#define CFLockInit ((pthread_mutex_t)PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) +#define CF_LOCK_INIT_FOR_STRUCTS(X) (X = CFLockInit) -#define __CFSpinLock(LP) ({ \ - OSSpinLock *__lockp__ = (LP); \ - OSSpinLockLock(__lockp__); }) +#define __CFLock(LP) ({ \ + (void)pthread_mutex_lock(LP); }) -#define __CFSpinUnlock(LP) ({ \ - OSSpinLock *__lockp__ = (LP); \ - OSSpinLockUnlock(__lockp__); }) +#define __CFUnlock(LP) ({ \ + (void)pthread_mutex_unlock(LP); }) -#define __CFSpinLockTry(LP) ({ \ - OSSpinLock *__lockp__ = (LP); \ - OSSpinLockTry(__lockp__); }) +#define __CFLockTry(LP) ({ \ + pthread_mutex_trylock(LP) == 0; }) #elif DEPLOYMENT_TARGET_WINDOWS -typedef int32_t CFSpinLock_t; -#define CFSpinLockInit 0 -#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit) +typedef int32_t CFLock_t; +#define CFLockInit 0 +#define CF_LOCK_INIT_FOR_STRUCTS(X) (X = CFLockInit) -CF_INLINE void __CFSpinLock(volatile CFSpinLock_t *lock) { +CF_INLINE void __CFLock(volatile CFLock_t *lock) { while (InterlockedCompareExchange((LONG volatile *)lock, ~0, 0) != 0) { Sleep(0); } } -CF_INLINE void __CFSpinUnlock(volatile CFSpinLock_t *lock) { +CF_INLINE void __CFUnlock(volatile CFLock_t *lock) { MemoryBarrier(); *lock = 0; } -CF_INLINE Boolean __CFSpinLockTry(volatile CFSpinLock_t *lock) { +CF_INLINE Boolean __CFLockTry(volatile CFLock_t *lock) { return (InterlockedCompareExchange((LONG volatile *)lock, ~0, 0) == 0); } #elif DEPLOYMENT_TARGET_LINUX -typedef int32_t CFSpinLock_t; -#define CFSpinLockInit 0 -#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit) +typedef int32_t CFLock_t; +#define CFLockInit 0 +#define CF_LOCK_INIT_FOR_STRUCTS(X) (X = CFLockInit) -CF_INLINE void __CFSpinLock(volatile CFSpinLock_t *lock) { +CF_INLINE void __CFLock(volatile CFLock_t *lock) { while (__sync_val_compare_and_swap(lock, 0, ~0) != 0) { sleep(0); } } -CF_INLINE void __CFSpinUnlock(volatile CFSpinLock_t *lock) { +CF_INLINE void __CFUnlock(volatile CFLock_t *lock) { __sync_synchronize(); *lock = 0; } -CF_INLINE Boolean __CFSpinLockTry(volatile CFSpinLock_t *lock) { +CF_INLINE Boolean __CFLockTry(volatile CFLock_t *lock) { return (__sync_val_compare_and_swap(lock, 0, ~0) == 0); } #else -#warning CF spin locks not defined for this platform -- CF is not thread-safe -#define __CFSpinLock(A) do {} while (0) -#define __CFSpinUnlock(A) do {} while (0) +#warning CF locks not defined for this platform -- CF is not thread-safe +#define __CFLock(A) do {} while (0) +#define __CFUnlock(A) do {} while (0) #endif @@ -525,13 +505,11 @@ CF_EXPORT CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstractType); /* ==================== Simple file access ==================== */ /* These functions all act on a c-strings which must be in the file system encoding. */ -CF_EXPORT Boolean _CFCreateDirectory(const char *path); -CF_EXPORT Boolean _CFRemoveDirectory(const char *path); -CF_EXPORT Boolean _CFDeleteFile(const char *path); +CF_PRIVATE Boolean _CFCreateDirectory(const char *path); +CF_PRIVATE Boolean _CFRemoveDirectory(const char *path); +CF_PRIVATE Boolean _CFDeleteFile(const char *path); -CF_EXPORT Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags, int *fd); -CF_EXPORT Boolean _CFReadBytesFromPath(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags); -CF_EXPORT Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags); +CF_PRIVATE Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags); /* resulting bytes are allocated from alloc which MUST be non-NULL. */ /* maxLength of zero means the whole file. Otherwise it sets a limit on the number of bytes read. */ @@ -777,6 +755,50 @@ CF_INLINE const char *CFPathRelativeToAppleFrameworksRoot(const char *path, Bool return path; } +#include +#include + +#if (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED) + +// Returns a generic dispatch queue for when you want to just throw some work +// into the concurrent pile to execute, and don't care about specifics except +// to match the QOS of the main thread. +CF_INLINE dispatch_queue_t __CFDispatchQueueGetGenericMatchingMain(void) { + return dispatch_get_global_queue(qos_class_main(), DISPATCH_QUEUE_OVERCOMMIT); +} + +// Returns a generic dispatch queue for when you want to just throw some work +// into the concurrent pile to execute, and don't care about specifics except +// to match the QOS of the current thread. +CF_INLINE dispatch_queue_t __CFDispatchQueueGetGenericMatchingCurrent(void) { + return dispatch_get_global_queue(qos_class_self(), 0); // DISPATCH_QUEUE_OVERCOMMIT left out intentionally at this point +} + +// Returns a generic dispatch queue for when you want to just throw some work +// into the concurrent pile to execute, and don't care about specifics except +// that it should be in background QOS. +CF_INLINE dispatch_queue_t __CFDispatchQueueGetGenericBackground(void) { + // Don't ACTUALLY use BACKGROUND, because of unknowable and unfavorable interactions like () + return dispatch_get_global_queue(QOS_CLASS_UTILITY, DISPATCH_QUEUE_OVERCOMMIT); +} + +#else + +CF_INLINE dispatch_queue_t __CFDispatchQueueGetGenericMatchingMain(void) { + return dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, DISPATCH_QUEUE_OVERCOMMIT); +} + +CF_INLINE dispatch_queue_t __CFDispatchQueueGetGenericMatchingCurrent(void) { + return dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0); // DISPATCH_QUEUE_OVERCOMMIT left out intentionally at this point +} + +CF_INLINE dispatch_queue_t __CFDispatchQueueGetGenericBackground(void) { + return dispatch_get_global_queue(QOS_CLASS_UTILITY, DISPATCH_QUEUE_OVERCOMMIT); +} + +#endif + + CF_EXTERN_C_END #endif /* ! __COREFOUNDATION_CFINTERNAL__ */ diff --git a/CFLocale.c b/CFLocale.c index e8cc764..c0fc91e 100644 --- a/CFLocale.c +++ b/CFLocale.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFLocale.c - Copyright (c) 2002-2013, Apple Inc. All rights reserved. + Copyright (c) 2002-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -142,7 +142,7 @@ static struct key_table __CFLocaleKeyTable[__kCFLocaleKeyTableCount] = { static CFLocaleRef __CFLocaleSystem = NULL; static CFMutableDictionaryRef __CFLocaleCache = NULL; -static CFSpinLock_t __CFLocaleGlobalLock = CFSpinLockInit; +static CFLock_t __CFLocaleGlobalLock = CFLockInit; struct __CFLocale { CFRuntimeBase _base; @@ -150,15 +150,17 @@ struct __CFLocale { CFMutableDictionaryRef _cache; CFMutableDictionaryRef _overrides; CFDictionaryRef _prefs; - CFSpinLock_t _lock; + CFLock_t _lock; Boolean _nullLocale; }; CF_PRIVATE Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale) { + CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), Boolean, (NSLocale *)locale, _nullLocale); return locale->_nullLocale; } CF_PRIVATE void __CFLocaleSetNullLocale(struct __CFLocale *locale) { + CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), void, (NSLocale *)locale, _setNullLocale); locale->_nullLocale = true; } @@ -179,19 +181,19 @@ CF_INLINE void __CFLocaleSetType(CFLocaleRef locale, CFIndex type) { } CF_INLINE void __CFLocaleLockGlobal(void) { - __CFSpinLock(&__CFLocaleGlobalLock); + __CFLock(&__CFLocaleGlobalLock); } CF_INLINE void __CFLocaleUnlockGlobal(void) { - __CFSpinUnlock(&__CFLocaleGlobalLock); + __CFUnlock(&__CFLocaleGlobalLock); } CF_INLINE void __CFLocaleLock(CFLocaleRef locale) { - __CFSpinLock(&((struct __CFLocale *)locale)->_lock); + __CFLock(&((struct __CFLocale *)locale)->_lock); } CF_INLINE void __CFLocaleUnlock(CFLocaleRef locale) { - __CFSpinUnlock(&((struct __CFLocale *)locale)->_lock); + __CFUnlock(&((struct __CFLocale *)locale)->_lock); } @@ -249,20 +251,18 @@ static const CFRuntimeClass __CFLocaleClass = { __CFLocaleCopyDescription }; -static void __CFLocaleInitialize(void) { - CFIndex idx; - __kCFLocaleTypeID = _CFRuntimeRegisterClass(&__CFLocaleClass); - for (idx = 0; idx < __kCFLocaleKeyTableCount; idx++) { - // table fixup to workaround compiler/language limitations - __CFLocaleKeyTable[idx].key = *((CFStringRef *)__CFLocaleKeyTable[idx].key); - if (NULL != __CFLocaleKeyTable[idx].context) { - __CFLocaleKeyTable[idx].context = *((CFStringRef *)__CFLocaleKeyTable[idx].context); - } - } -} - CFTypeID CFLocaleGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFLocaleTypeID) __CFLocaleInitialize(); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFLocaleTypeID = _CFRuntimeRegisterClass(&__CFLocaleClass); // initOnce covered + for (CFIndex idx = 0; idx < __kCFLocaleKeyTableCount; idx++) { + // table fixup to workaround compiler/language limitations + __CFLocaleKeyTable[idx].key = *((CFStringRef *)__CFLocaleKeyTable[idx].key); + if (NULL != __CFLocaleKeyTable[idx].context) { + __CFLocaleKeyTable[idx].context = *((CFStringRef *)__CFLocaleKeyTable[idx].context); + } + } + }); return __kCFLocaleTypeID; } @@ -353,7 +353,7 @@ static CFLocaleRef _CFLocaleCopyCurrentGuts(CFStringRef name, Boolean useCache, locale->_cache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); locale->_overrides = NULL; locale->_prefs = prefs; - locale->_lock = CFSpinLockInit; + locale->_lock = CFLockInit; locale->_nullLocale = false; if (useCache) { @@ -432,7 +432,7 @@ CFLocaleRef CFLocaleCreate(CFAllocatorRef allocator, CFStringRef identifier) { locale->_cache = CFDictionaryCreateMutable(allocator, 0, NULL, &kCFTypeDictionaryValueCallBacks); locale->_overrides = NULL; locale->_prefs = NULL; - locale->_lock = CFSpinLockInit; + locale->_lock = CFLockInit; if (canCache) { if (NULL == __CFLocaleCache) { __CFLocaleCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -444,6 +444,7 @@ CFLocaleRef CFLocaleCreate(CFAllocatorRef allocator, CFStringRef identifier) { } CFLocaleRef CFLocaleCreateCopy(CFAllocatorRef allocator, CFLocaleRef locale) { + CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFLocaleRef, (NSLocale *)locale, copy); return (CFLocaleRef)CFRetain(locale); } @@ -948,7 +949,13 @@ static bool __CFLocaleCopyCalendarID(CFLocaleRef locale, bool user, CFTypeRef *c } else if (CFEqual(*cf, kCFCalendarIdentifierEthiopicAmeteAlem)) { CFRelease(*cf); *cf = CFRetain(kCFCalendarIdentifierEthiopicAmeteAlem); - } else { + } else if (CFEqual(*cf, kCFCalendarIdentifierIslamicTabular)) { + CFRelease(*cf); + *cf = CFRetain(kCFCalendarIdentifierIslamicTabular); + } else if (CFEqual(*cf, kCFCalendarIdentifierIslamicUmmAlQura)) { + CFRelease(*cf); + *cf = CFRetain(kCFCalendarIdentifierIslamicUmmAlQura); + } else { CFRelease(*cf); *cf = NULL; return false; diff --git a/CFLocale.h b/CFLocale.h index 3ea3b99..21edcc2 100644 --- a/CFLocale.h +++ b/CFLocale.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFLocale.h - Copyright (c) 2002-2013, Apple Inc. All rights reserved. + Copyright (c) 2002-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFLOCALE__) @@ -35,7 +35,7 @@ CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -typedef const struct __CFLocale *CFLocaleRef; +typedef const struct CF_BRIDGED_TYPE(NSLocale) __CFLocale *CFLocaleRef; CF_EXPORT CFTypeID CFLocaleGetTypeID(void); @@ -206,6 +206,8 @@ CF_EXPORT const CFStringRef kCFRepublicOfChinaCalendar CF_AVAILABLE(10_6, 4_0); CF_EXPORT const CFStringRef kCFPersianCalendar CF_AVAILABLE(10_6, 4_0); CF_EXPORT const CFStringRef kCFIndianCalendar CF_AVAILABLE(10_6, 4_0); CF_EXPORT const CFStringRef kCFISO8601Calendar CF_AVAILABLE(10_6, 4_0); +CF_EXPORT const CFStringRef kCFIslamicTabularCalendar CF_AVAILABLE(10_10, 8_0); +CF_EXPORT const CFStringRef kCFIslamicUmmAlQuraCalendar CF_AVAILABLE(10_10, 8_0); CF_EXTERN_C_END CF_IMPLICIT_BRIDGING_DISABLED diff --git a/CFLocaleIdentifier.c b/CFLocaleIdentifier.c index 593b649..9b6b2fe 100644 --- a/CFLocaleIdentifier.c +++ b/CFLocaleIdentifier.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFLocaleIdentifier.c - Copyright (c) 2002-2013, Apple Inc. All rights reserved. + Copyright (c) 2002-2014, Apple Inc. All rights reserved. Responsibility: David Smith CFLocaleIdentifier.c defines @@ -822,7 +822,7 @@ static const KeyStringToResultString localeStringPrefixToCanonical[] = { { "tat", "tt" }, // Tatar { "tel", "te" }, // Telugu { "tgk", "tg" }, // Tajik - { "tgl", "tl" }, // Tagalog + { "tgl", "fil" }, // Tagalog { "tha", "th" }, // Thai { "tib", "bo" }, // Tibetan { "tir", "ti" }, // Tigrinya @@ -1128,15 +1128,16 @@ static const KeyStringToResultString appleLocaleToLanguageString[] = { // ------- ------- { "en_US_POSIX", "en-US-POSIX" }, // POSIX locale, need as language string // <1.17> [3840752] { "zh_CN", "zh-Hans" }, // mainland China => simplified - { "zh_HK", "zh-Hant" }, // Hong Kong => traditional, not currently used - { "zh_MO", "zh-Hant" }, // Macao => traditional, not currently used - { "zh_SG", "zh-Hans" }, // Singapore => simplified, not currently used + { "zh_HK", "zh-HK" }, // Hong Kong => traditional, not currently used + { "zh_MO", "zh-MO" }, // Macao => traditional, not currently used + { "zh_SG", "zh-SG" }, // Singapore => simplified, not currently used { "zh_TW", "zh-Hant" }, // Taiwan => traditional }; enum { kNumAppleLocaleToLanguageString = sizeof(appleLocaleToLanguageString)/sizeof(KeyStringToResultString) }; +/* static const KeyStringToResultString appleLocaleToLanguageStringForCFBundle[] = { // Map locale strings that Apple uses as language IDs to real language strings. // Must be sorted according to how strcmp compares the strings in the first column. @@ -1170,7 +1171,9 @@ static const KeyStringToResultString appleLocaleToLanguageStringForCFBundle[] = enum { kNumAppleLocaleToLanguageStringForCFBundle = sizeof(appleLocaleToLanguageStringForCFBundle)/sizeof(KeyStringToResultString) }; + */ +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX struct LocaleToLegacyCodes { const char * locale; // reduced to language plus one other component (script, region, variant), separators normalized to'_' @@ -1350,6 +1353,8 @@ enum { kNumLocaleToLegacyCodes = sizeof(localeToLegacyCodes)/sizeof(localeToLegacyCodes[0]) }; +#endif + /* For reference here is a list of ICU locales with variants and how some of them are canonicalized with the ICU function uloc_canonicalize: diff --git a/CFLocaleInternal.h b/CFLocaleInternal.h index 48fcf38..8c601f4 100644 --- a/CFLocaleInternal.h +++ b/CFLocaleInternal.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFLocaleInternal.h - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. */ /* @@ -130,6 +130,8 @@ CF_EXPORT CFStringRef const kCFCalendarIdentifierBuddhist; CF_EXPORT CFStringRef const kCFCalendarIdentifierJapanese; CF_EXPORT CFStringRef const kCFCalendarIdentifierIslamic; CF_EXPORT CFStringRef const kCFCalendarIdentifierIslamicCivil; +CF_EXPORT CFStringRef const kCFCalendarIdentifierIslamicTabular; +CF_EXPORT CFStringRef const kCFCalendarIdentifierIslamicUmmAlQura; CF_EXPORT CFStringRef const kCFCalendarIdentifierHebrew; CF_EXPORT CFStringRef const kCFCalendarIdentifierChinese; CF_EXPORT CFStringRef const kCFCalendarIdentifierRepublicOfChina; diff --git a/CFLocaleKeys.c b/CFLocaleKeys.c index 000051b..7604aea 100644 --- a/CFLocaleKeys.c +++ b/CFLocaleKeys.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFLocaleKeys.c - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -127,6 +127,8 @@ CONST_STRING_DECL(kCFCalendarIdentifierBuddhist, "buddhist"); CONST_STRING_DECL(kCFCalendarIdentifierJapanese, "japanese"); CONST_STRING_DECL(kCFCalendarIdentifierIslamic, "islamic"); CONST_STRING_DECL(kCFCalendarIdentifierIslamicCivil, "islamic-civil"); +CONST_STRING_DECL(kCFCalendarIdentifierIslamicUmmAlQura, "islamic-umalqura"); +CONST_STRING_DECL(kCFCalendarIdentifierIslamicTabular, "islamic-tbla"); CONST_STRING_DECL(kCFCalendarIdentifierHebrew, "hebrew"); CONST_STRING_DECL(kCFCalendarIdentifierChinese, "chinese"); CONST_STRING_DECL(kCFCalendarIdentifierRepublicOfChina, "roc"); @@ -147,6 +149,8 @@ CF_EXPORT CFStringRef const kCFHebrewCalendar __attribute__((alias ("kCFCalendar CF_EXPORT CFStringRef const kCFISO8601Calendar __attribute__((alias ("kCFCalendarIdentifierISO8601"))); CF_EXPORT CFStringRef const kCFIndianCalendar __attribute__((alias ("kCFCalendarIdentifierIndian"))); CF_EXPORT CFStringRef const kCFIslamicCalendar __attribute__((alias ("kCFCalendarIdentifierIslamic"))); +CF_EXPORT CFStringRef const kCFIslamicTabularCalendar __attribute__((alias ("kCFCalendarIdentifierIslamicTabular"))); +CF_EXPORT CFStringRef const kCFIslamicUmmAlQuraCalendar __attribute__((alias ("kCFCalendarIdentifierIslamicUmmAlQura"))); CF_EXPORT CFStringRef const kCFIslamicCivilCalendar __attribute__((alias ("kCFCalendarIdentifierIslamicCivil"))); CF_EXPORT CFStringRef const kCFJapaneseCalendar __attribute__((alias ("kCFCalendarIdentifierJapanese"))); CF_EXPORT CFStringRef const kCFPersianCalendar __attribute__((alias ("kCFCalendarIdentifierPersian"))); diff --git a/CFLogUtilities.h b/CFLogUtilities.h index f1da61e..115b679 100644 --- a/CFLogUtilities.h +++ b/CFLogUtilities.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFLogUtilities.h - Copyright (c) 2004-2013, Apple Inc. All rights reserved. + Copyright (c) 2004-2014, Apple Inc. All rights reserved. */ /* diff --git a/CFMachPort.c b/CFMachPort.c index 24c2aa4..2f3411e 100644 --- a/CFMachPort.c +++ b/CFMachPort.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFMachPort.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -46,7 +46,10 @@ static dispatch_queue_t _CFMachPortQueue() { static volatile dispatch_queue_t __CFMachPortQueue = NULL; static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ __CFMachPortQueue = dispatch_queue_create("CFMachPort Queue", NULL); }); + dispatch_once(&onceToken, ^{ + dispatch_queue_attr_t dqattr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_BACKGROUND, 0); + __CFMachPortQueue = dispatch_queue_create("com.apple.CFMachPort", dqattr); + }); return __CFMachPortQueue; } @@ -68,7 +71,7 @@ struct __CFMachPort { CFRunLoopSourceRef _source; /* immutable, once created */ CFMachPortCallBack _callout; /* immutable */ CFMachPortContext _context; /* immutable */ - CFSpinLock_t _lock; + CFLock_t _lock; const void *(*retain)(const void *info); // use these to store the real callbacks void (*release)(const void *info); }; @@ -96,11 +99,12 @@ CF_INLINE void __CFMachPortSetHasSend(CFMachPortRef mp) { CF_INLINE Boolean __CFMachPortHasSend2(CFMachPortRef mp) { return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 3, 3); } - +/* + //TODO we should either use this or delete the entire Send2 flag concept CF_INLINE void __CFMachPortSetHasSend2(CFMachPortRef mp) { __CFBitfieldSetValue(((CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 3, 3, 1); } - +*/ CF_INLINE Boolean __CFMachPortIsValid(CFMachPortRef mp) { return kCFMachPortStateReady == mp->_state; } @@ -143,23 +147,23 @@ static CFStringRef __CFMachPortCopyDescription(CFTypeRef cf) { CF_INLINE void __CFMachPortInvalidateLocked(CFRunLoopSourceRef source, CFMachPortRef mp) { CFMachPortInvalidationCallBack cb = mp->_icallout; if (cb) { - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); cb(mp, mp->_context.info); - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); } if (NULL != source) { - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); CFRunLoopSourceInvalidate(source); CFRelease(source); - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); } void *info = mp->_context.info; void (*release)(const void *info) = mp->release; mp->_context.info = NULL; if (release) { - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); release(info); - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); } mp->_state = kCFMachPortStateInvalid; OSMemoryBarrier(); @@ -170,7 +174,7 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { CFMachPortRef mp = (CFMachPortRef)cf; // CFMachPortRef is invalid before we get here, except under GC - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); CFRunLoopSourceRef source = NULL; Boolean wasReady = (mp->_state == kCFMachPortStateReady); if (wasReady) { @@ -193,9 +197,9 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { dispatch_semaphore_t sem1 = mp->_dsrc_sem; Boolean doSend2 = __CFMachPortHasSend2(mp), doSend = __CFMachPortHasSend(mp), doReceive = __CFMachPortHasReceive(mp); - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + dispatch_async(__CFDispatchQueueGetGenericBackground(), ^{ if (sem1) { dispatch_semaphore_wait(sem1, DISPATCH_TIME_FOREVER); // immediate release is only safe if dispatch_semaphore_signal() does not touch the semaphore after doing the signal bit @@ -218,7 +222,7 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { } // This lock protects __CFAllMachPorts. Take before any instance-specific lock. -static CFSpinLock_t __CFAllMachPortsLock = CFSpinLockInit; +static CFLock_t __CFAllMachPortsLock = CFLockInit; #if AVOID_WEAK_COLLECTIONS static CFMutableArrayRef __CFAllMachPorts = NULL; @@ -234,7 +238,7 @@ static Boolean __CFMachPortCheck(mach_port_t port) { } static void __CFMachPortChecker(Boolean fromTimer) { - __CFSpinLock(&__CFAllMachPortsLock); // take this lock first before any instance-specific lock + __CFLock(&__CFAllMachPortsLock); // take this lock first before any instance-specific lock #if AVOID_WEAK_COLLECTIONS for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) { CFMachPortRef mp = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx); @@ -248,7 +252,7 @@ static void __CFMachPortChecker(Boolean fromTimer) { CFRunLoopSourceRef source = NULL; Boolean wasReady = (mp->_state == kCFMachPortStateReady); if (wasReady) { - __CFSpinLock(&mp->_lock); // take this lock second + __CFLock(&mp->_lock); // take this lock second mp->_state = kCFMachPortStateInvalidating; OSMemoryBarrier(); if (mp->_dsrc) { @@ -258,13 +262,13 @@ static void __CFMachPortChecker(Boolean fromTimer) { source = mp->_source; mp->_source = NULL; CFRetain(mp); - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); dispatch_async(dispatch_get_main_queue(), ^{ // We can grab the mach port-specific spin lock here since we're no longer on the same thread as the one taking the all mach ports spin lock. // But be sure to release it during callouts - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); __CFMachPortInvalidateLocked(source, mp); - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); CFRelease(mp); }); } @@ -280,7 +284,7 @@ static void __CFMachPortChecker(Boolean fromTimer) { #if !AVOID_WEAK_COLLECTIONS [__CFAllMachPorts compact]; #endif - __CFSpinUnlock(&__CFAllMachPortsLock); + __CFUnlock(&__CFAllMachPortsLock); }; @@ -298,11 +302,9 @@ static const CFRuntimeClass __CFMachPortClass = { __CFMachPortCopyDescription }; -CF_PRIVATE void __CFMachPortInitialize(void) { - __kCFMachPortTypeID = _CFRuntimeRegisterClass(&__CFMachPortClass); -} - CFTypeID CFMachPortGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFMachPortTypeID = _CFRuntimeRegisterClass(&__CFMachPortClass); }); return __kCFMachPortTypeID; } @@ -323,6 +325,7 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p return NULL; } +#if 0 static dispatch_source_t timerSource = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -332,9 +335,10 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p }); dispatch_resume(timerSource); }); +#endif CFMachPortRef mp = NULL; - __CFSpinLock(&__CFAllMachPortsLock); + __CFLock(&__CFAllMachPortsLock); #if AVOID_WEAK_COLLECTIONS for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) { CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx); @@ -354,7 +358,7 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p } } #endif - __CFSpinUnlock(&__CFAllMachPortsLock); + __CFUnlock(&__CFAllMachPortsLock); if (!mp) { CFIndex size = sizeof(struct __CFMachPort) - sizeof(CFRuntimeBase); @@ -374,7 +378,7 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p memory->retain = NULL; memory->release = NULL; memory->_callout = callout; - memory->_lock = CFSpinLockInit; + memory->_lock = CFLockInit; if (NULL != context) { objc_memmove_collectable(&memory->_context, context, sizeof(CFMachPortContext)); memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info; @@ -384,7 +388,7 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p memory->_context.release = (void *)0xAAAAAAAAAABBBAAA; } memory->_state = kCFMachPortStateReady; - __CFSpinLock(&__CFAllMachPortsLock); + __CFLock(&__CFAllMachPortsLock); #if AVOID_WEAK_COLLECTIONS if (!__CFAllMachPorts) __CFAllMachPorts = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue(__CFAllMachPorts, memory); @@ -392,7 +396,7 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p if (!__CFAllMachPorts) __CFAllMachPorts = [[__CFPointerArray alloc] initWithOptions:(kCFUseCollectableAllocator ? CFPointerFunctionsZeroingWeakMemory : CFPointerFunctionsStrongMemory)]; [__CFAllMachPorts addPointer:memory]; #endif - __CFSpinUnlock(&__CFAllMachPortsLock); + __CFUnlock(&__CFAllMachPortsLock); mp = memory; if (shouldFreeInfo) *shouldFreeInfo = false; @@ -449,8 +453,8 @@ void CFMachPortInvalidate(CFMachPortRef mp) { CFRetain(mp); CFRunLoopSourceRef source = NULL; Boolean wasReady = false; - __CFSpinLock(&__CFAllMachPortsLock); // take this lock first - __CFSpinLock(&mp->_lock); + __CFLock(&__CFAllMachPortsLock); // take this lock first + __CFLock(&mp->_lock); wasReady = (mp->_state == kCFMachPortStateReady); if (wasReady) { mp->_state = kCFMachPortStateInvalidating; @@ -479,12 +483,12 @@ void CFMachPortInvalidate(CFMachPortRef mp) { source = mp->_source; mp->_source = NULL; } - __CFSpinUnlock(&mp->_lock); - __CFSpinUnlock(&__CFAllMachPortsLock); // release this lock last + __CFUnlock(&mp->_lock); + __CFUnlock(&__CFAllMachPortsLock); // release this lock last if (wasReady) { - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); __CFMachPortInvalidateLocked(source, mp); - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); } CFRelease(mp); } @@ -516,9 +520,9 @@ Boolean CFMachPortIsValid(CFMachPortRef mp) { CFMachPortInvalidationCallBack CFMachPortGetInvalidationCallBack(CFMachPortRef mp) { __CFGenericValidateType(mp, CFMachPortGetTypeID()); - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); CFMachPortInvalidationCallBack cb = mp->_icallout; - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); return cb; } @@ -534,17 +538,17 @@ void CFMachPortSetInvalidationCallBack(CFMachPortRef mp, CFMachPortInvalidationC CFLog(kCFLogLevelError, CFSTR("*** WARNING: CFMachPortSetInvalidationCallBack() called on a CFMachPort with a Mach port (0x%x) which does not have any send rights. This is not going to work. Callback function: %p"), mp->_port, callout); } } - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); if (__CFMachPortIsValid(mp) || !callout) { mp->_icallout = callout; } else if (!mp->_icallout && callout) { - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); callout(mp, mp->_context.info); - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); } else { CFLog(kCFLogLevelWarning, CFSTR("CFMachPortSetInvalidationCallBack(): attempt to set invalidation callback (%p) on invalid CFMachPort (%p) thwarted"), callout, mp); } - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); } /* Returns the number of messages queued for a receive port. */ @@ -565,7 +569,7 @@ static mach_port_t __CFMachPortGetPort(void *info) { CF_PRIVATE void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef allocator, void *info) { CHECK_FOR_FORK_RET(NULL); CFMachPortRef mp = (CFMachPortRef)info; - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); Boolean isValid = __CFMachPortIsValid(mp); void *context_info = NULL; void (*context_release)(const void *) = NULL; @@ -577,7 +581,7 @@ CF_PRIVATE void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef all context_info = mp->_context.info; } } - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); if (isValid) { mp->_callout(mp, msg, size, context_info); @@ -590,13 +594,14 @@ CF_PRIVATE void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef all } - + + CFRunLoopSourceRef CFMachPortCreateRunLoopSource(CFAllocatorRef allocator, CFMachPortRef mp, CFIndex order) { CHECK_FOR_FORK_RET(NULL); __CFGenericValidateType(mp, CFMachPortGetTypeID()); if (!CFMachPortIsValid(mp)) return NULL; CFRunLoopSourceRef result = NULL; - __CFSpinLock(&mp->_lock); + __CFLock(&mp->_lock); if (__CFMachPortIsValid(mp)) { if (NULL != mp->_source && !CFRunLoopSourceIsValid(mp->_source)) { CFRelease(mp->_source); @@ -617,7 +622,7 @@ CFRunLoopSourceRef CFMachPortCreateRunLoopSource(CFAllocatorRef allocator, CFMac } result = mp->_source ? (CFRunLoopSourceRef)CFRetain(mp->_source) : NULL; } - __CFSpinUnlock(&mp->_lock); + __CFUnlock(&mp->_lock); return result; } diff --git a/CFMachPort.h b/CFMachPort.h index 86c88f4..a31b032 100644 --- a/CFMachPort.h +++ b/CFMachPort.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFMachPort.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFMACHPORT__) @@ -31,9 +31,10 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -typedef struct __CFMachPort * CFMachPortRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMachPort) __CFMachPort * CFMachPortRef; typedef struct { CFIndex version; @@ -61,6 +62,7 @@ CF_EXPORT void CFMachPortSetInvalidationCallBack(CFMachPortRef port, CFMachPort CF_EXPORT CFRunLoopSourceRef CFMachPortCreateRunLoopSource(CFAllocatorRef allocator, CFMachPortRef port, CFIndex order); CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFMACHPORT__ */ diff --git a/CFMessagePort.c b/CFMessagePort.c index e8447df..0e73995 100644 --- a/CFMessagePort.c +++ b/CFMessagePort.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFMessagePort.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -60,13 +60,13 @@ extern pid_t getpid(void); #define __CFMessagePortMaxDataSize 0x60000000L -static CFSpinLock_t __CFAllMessagePortsLock = CFSpinLockInit; +static CFLock_t __CFAllMessagePortsLock = CFLockInit; static CFMutableDictionaryRef __CFAllLocalMessagePorts = NULL; static CFMutableDictionaryRef __CFAllRemoteMessagePorts = NULL; struct __CFMessagePort { CFRuntimeBase _base; - CFSpinLock_t _lock; + CFLock_t _lock; CFStringRef _name; CFMachPortRef _port; /* immutable; invalidated */ CFMutableDictionaryRef _replies; @@ -132,84 +132,77 @@ CF_INLINE void __CFMessagePortSetIsDeallocing(CFMessagePortRef ms) { } CF_INLINE void __CFMessagePortLock(CFMessagePortRef ms) { - __CFSpinLock(&(ms->_lock)); + __CFLock(&(ms->_lock)); } CF_INLINE void __CFMessagePortUnlock(CFMessagePortRef ms) { - __CFSpinUnlock(&(ms->_lock)); + __CFUnlock(&(ms->_lock)); } -// Just a heuristic -#define __CFMessagePortMaxInlineBytes 4096*10 +#if !defined(__LP64__) +#define __LP64__ 0 +#endif -struct __CFMessagePortMachMessage0 { - mach_msg_base_t base; - int32_t magic; - int32_t msgid; - int32_t byteslen; - uint8_t bytes[0]; -}; +// Just a heuristic +#define __CFMessagePortMaxInlineBytes ((int32_t)4000) -struct __CFMessagePortMachMessage1 { +struct __CFMessagePortMachMessage { mach_msg_base_t base; mach_msg_ool_descriptor_t ool; - int32_t magic; - int32_t msgid; - int32_t byteslen; + struct innards { + int32_t magic; + int32_t msgid; + int32_t convid; + int32_t byteslen; + uint8_t bytes[0]; + } innards; }; +#define __INNARD_OFFSET (((!(msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && ((mach_msg_header_t *)msgp)->msgh_id == 0) || ( (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && !__LP64__)) ? 40 : 44) + +#define MAGIC 0xF0F2F4F8 -#define MAGIC 0xF1F2F3F4 +// These 3 macros should ONLY be used on RECEIVED messages, not ones being constructed on the sending side +#define MSGP_GET(msgp, ident) (((struct __CFMessagePortMachMessage *)msgp)->ident) +#define MSGP_INFO(msgp, ident) ((struct innards *)((void *)msgp + __INNARD_OFFSET))->ident +#define MSGP_SIZE(msgp) (__INNARD_OFFSET + sizeof(struct innards)) -#define MSGP0_FIELD(msgp, ident) ((struct __CFMessagePortMachMessage0 *)msgp)->ident -#define MSGP1_FIELD(msgp, ident) ((struct __CFMessagePortMachMessage1 *)msgp)->ident -#define MSGP_GET(msgp, ident) \ - ((((mach_msg_base_t *)msgp)->body.msgh_descriptor_count) ? MSGP1_FIELD(msgp, ident) : MSGP0_FIELD(msgp, ident)) static mach_msg_base_t *__CFMessagePortCreateMessage(bool reply, mach_port_t port, mach_port_t replyPort, int32_t convid, int32_t msgid, const uint8_t *bytes, int32_t byteslen) { if (__CFMessagePortMaxDataSize < byteslen) return NULL; - int32_t rounded_byteslen = ((byteslen + 3) & ~0x3); + if (byteslen < -1) return NULL; + int32_t rounded_byteslen = (byteslen < 0) ? 0 : ((byteslen + 7) & ~0x7); + int32_t size = (int32_t)sizeof(struct __CFMessagePortMachMessage) + ((rounded_byteslen <= __CFMessagePortMaxInlineBytes) ? rounded_byteslen : 0); + struct __CFMessagePortMachMessage *msg = CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0); + if (!msg) return NULL; + memset(msg, 0, size); +#if __LP64__ + msg->base.header.msgh_id = 1; +#else + msg->base.header.msgh_id = 0; +#endif + msg->base.header.msgh_size = size; + msg->base.header.msgh_remote_port = port; + msg->base.header.msgh_local_port = replyPort; + msg->base.header.msgh_bits = MACH_MSGH_BITS((reply ? MACH_MSG_TYPE_MOVE_SEND_ONCE : MACH_MSG_TYPE_COPY_SEND), (MACH_PORT_NULL != replyPort ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0)); + msg->base.body.msgh_descriptor_count = 0; + msg->innards.magic = MAGIC; + msg->innards.msgid = CFSwapInt32HostToLittle(msgid); + msg->innards.convid = CFSwapInt32HostToLittle(convid); + msg->innards.byteslen = CFSwapInt32HostToLittle(byteslen); if (rounded_byteslen <= __CFMessagePortMaxInlineBytes) { - int32_t size = sizeof(struct __CFMessagePortMachMessage0) + rounded_byteslen; - struct __CFMessagePortMachMessage0 *msg = CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0); - if (!msg) return NULL; - memset(msg, 0, size); - msg->base.header.msgh_id = convid; - msg->base.header.msgh_size = size; - msg->base.header.msgh_remote_port = port; - msg->base.header.msgh_local_port = replyPort; - msg->base.header.msgh_reserved = 0; - msg->base.header.msgh_bits = MACH_MSGH_BITS((reply ? MACH_MSG_TYPE_MOVE_SEND_ONCE : MACH_MSG_TYPE_COPY_SEND), (MACH_PORT_NULL != replyPort ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0)); - msg->base.body.msgh_descriptor_count = 0; - msg->magic = MAGIC; - msg->msgid = CFSwapInt32HostToLittle(msgid); - msg->byteslen = CFSwapInt32HostToLittle(byteslen); if (NULL != bytes && 0 < byteslen) { - memmove(msg->bytes, bytes, byteslen); + memmove(msg->innards.bytes, bytes, byteslen); } - return (mach_msg_base_t *)msg; } else { - int32_t size = sizeof(struct __CFMessagePortMachMessage1); - struct __CFMessagePortMachMessage1 *msg = CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0); - if (!msg) return NULL; - memset(msg, 0, size); - msg->base.header.msgh_id = convid; - msg->base.header.msgh_size = size; - msg->base.header.msgh_remote_port = port; - msg->base.header.msgh_local_port = replyPort; - msg->base.header.msgh_reserved = 0; - msg->base.header.msgh_bits = MACH_MSGH_BITS((reply ? MACH_MSG_TYPE_MOVE_SEND_ONCE : MACH_MSG_TYPE_COPY_SEND), (MACH_PORT_NULL != replyPort ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0)); msg->base.header.msgh_bits |= MACH_MSGH_BITS_COMPLEX; msg->base.body.msgh_descriptor_count = 1; - msg->magic = MAGIC; - msg->msgid = CFSwapInt32HostToLittle(msgid); - msg->byteslen = CFSwapInt32HostToLittle(byteslen); msg->ool.deallocate = false; msg->ool.copy = MACH_MSG_VIRTUAL_COPY; msg->ool.address = (void *)bytes; msg->ool.size = byteslen; msg->ool.type = MACH_MSG_OOL_DESCRIPTOR; - return (mach_msg_base_t *)msg; } + return (mach_msg_base_t *)msg; } static CFStringRef __CFMessagePortCopyDescription(CFTypeRef cf) { @@ -217,7 +210,7 @@ static CFStringRef __CFMessagePortCopyDescription(CFTypeRef cf) { CFStringRef result; const char *locked; CFStringRef contextDesc = NULL; - locked = ms->_lock ? "Yes" : "No"; + locked = "Maybe"; if (__CFMessagePortIsRemote(ms)) { result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{locked = %s, valid = %s, remote = %s, name = %@}"), cf, CFGetAllocator(ms), locked, (__CFMessagePortIsValid(ms) ? "Yes" : "No"), (__CFMessagePortIsRemote(ms) ? "Yes" : "No"), ms->_name); } else { @@ -265,7 +258,7 @@ static void __CFMessagePortDeallocate(CFTypeRef cf) { // auto-invalidating; so we manually implement the 'auto-invalidation' here by // tickling each remote port to check its state after any message port is destroyed, // but most importantly after local message ports are destroyed. - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); CFMessagePortRef *remotePorts = NULL; CFIndex cnt = 0; if (NULL != __CFAllRemoteMessagePorts) { @@ -276,7 +269,7 @@ static void __CFMessagePortDeallocate(CFTypeRef cf) { CFRetain(remotePorts[idx]); } } - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); if (remotePorts) { for (CFIndex idx = 0; idx < cnt; idx++) { // as a side-effect, this will auto-invalidate the CFMessagePort if the CFMachPort is invalid @@ -301,11 +294,9 @@ static const CFRuntimeClass __CFMessagePortClass = { __CFMessagePortCopyDescription }; -CF_PRIVATE void __CFMessagePortInitialize(void) { - __kCFMessagePortTypeID = _CFRuntimeRegisterClass(&__CFMessagePortClass); -} - CFTypeID CFMessagePortGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFMessagePortTypeID = _CFRuntimeRegisterClass(&__CFMessagePortClass); }); return __kCFMessagePortTypeID; } @@ -356,12 +347,12 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS if (NULL != name) { name = __CFMessagePortSanitizeStringName(name, &utfname, NULL); } - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); if (!perPID && NULL != name) { CFMessagePortRef existing; if (NULL != __CFAllLocalMessagePorts && CFDictionaryGetValueIfPresent(__CFAllLocalMessagePorts, name, (const void **)&existing)) { CFRetain(existing); - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFRelease(name); CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); if (!CFMessagePortIsValid(existing)) { // must do this outside lock to avoid deadlock @@ -371,9 +362,9 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS return (CFMessagePortRef)(existing); } } - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFIndex size = sizeof(struct __CFMessagePort) - sizeof(CFRuntimeBase); - memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, __kCFMessagePortTypeID, size, NULL); + memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, CFMessagePortGetTypeID(), size, NULL); if (NULL == memory) { if (NULL != name) { CFRelease(name); @@ -384,7 +375,7 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS __CFMessagePortUnsetValid(memory); __CFMessagePortUnsetExtraMachRef(memory); __CFMessagePortUnsetRemote(memory); - memory->_lock = CFSpinLockInit; + memory->_lock = CFLockInit; memory->_name = name; memory->_port = NULL; memory->_replies = NULL; @@ -410,13 +401,25 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS if (!perPID) { ret = bootstrap_check_in(bs, (char *)utfname, &mp); /* If we're started by launchd or the old mach_init */ if (ret == KERN_SUCCESS) { - ret = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND); + mach_port_type_t type = 0; + ret = mach_port_type(mach_task_self(), mp, &type); + if (KERN_SUCCESS != ret || (0 == (type & MACH_PORT_TYPE_PORT_RIGHTS))) { + CFLog(kCFLogLevelError, CFSTR("*** CFMessagePort: bootstrap_check_in() succeeded, but mach port type is unknown (err %d) or returned invalid type (0x%x); name = '%s'"), ret, type, utfname); + ret = KERN_INVALID_RIGHT; + } + ret = (KERN_SUCCESS == ret) ? mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND) : ret; if (KERN_SUCCESS == ret) { CFMachPortContext ctx = {0, memory, NULL, NULL, NULL}; native = CFMachPortCreateWithPort(allocator, mp, __CFMessagePortDummyCallback, &ctx, NULL); + if (!native) { + mach_port_destroy(mach_task_self(), mp); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); + // name is released by deallocation + CFRelease(memory); + return NULL; + } __CFMessagePortSetExtraMachRef(memory); } else { - CFLog(kCFLogLevelDebug, CFSTR("*** CFMessagePort: mach_port_insert_member() after bootstrap_check_in(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'"), ret, ret, bootstrap_strerror(ret), mp, utfname); mach_port_destroy(mach_task_self(), mp); CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); // name is released by deallocation @@ -435,7 +438,10 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS return NULL; } mp = CFMachPortGetPort(native); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" ret = bootstrap_register2(bs, (char *)utfname, mp, perPID ? BOOTSTRAP_PER_PID_SERVICE : 0); +#pragma GCC diagnostic pop if (ret != KERN_SUCCESS) { CFLog(kCFLogLevelDebug, CFSTR("*** CFMessagePort: bootstrap_register(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'\nSee /usr/include/servers/bootstrap_defs.h for the error codes."), ret, ret, bootstrap_strerror(ret), mp, utfname); CFMachPortInvalidate(native); @@ -456,12 +462,12 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS memmove(&memory->_context, context, sizeof(CFMessagePortContext)); memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info; } - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); if (!perPID && NULL != name) { CFMessagePortRef existing; if (NULL != __CFAllLocalMessagePorts && CFDictionaryGetValueIfPresent(__CFAllLocalMessagePorts, name, (const void **)&existing)) { CFRetain(existing); - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFRelease(memory); return (CFMessagePortRef)(existing); } @@ -470,7 +476,7 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS } CFDictionaryAddValue(__CFAllLocalMessagePorts, name, memory); } - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); if (shouldFreeInfo) *shouldFreeInfo = false; return memory; } @@ -500,12 +506,12 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF if (NULL == name) { return NULL; } - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); if (!perPID && NULL != name) { CFMessagePortRef existing; if (NULL != __CFAllRemoteMessagePorts && CFDictionaryGetValueIfPresent(__CFAllRemoteMessagePorts, name, (const void **)&existing)) { CFRetain(existing); - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFRelease(name); CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); if (!CFMessagePortIsValid(existing)) { // must do this outside lock to avoid deadlock @@ -515,9 +521,9 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF return (CFMessagePortRef)(existing); } } - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); size = sizeof(struct __CFMessagePort) - sizeof(CFMessagePortContext) - sizeof(CFRuntimeBase); - memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, __kCFMessagePortTypeID, size, NULL); + memory = (CFMessagePortRef)_CFRuntimeCreateInstance(allocator, CFMessagePortGetTypeID(), size, NULL); if (NULL == memory) { if (NULL != name) { CFRelease(name); @@ -528,7 +534,7 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF __CFMessagePortUnsetValid(memory); __CFMessagePortUnsetExtraMachRef(memory); __CFMessagePortSetRemote(memory); - memory->_lock = CFSpinLockInit; + memory->_lock = CFLockInit; memory->_name = name; memory->_port = NULL; memory->_replies = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL); @@ -557,12 +563,12 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF } memory->_port = native; __CFMessagePortSetValid(memory); - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); if (!perPID && NULL != name) { CFMessagePortRef existing; if (NULL != __CFAllRemoteMessagePorts && CFDictionaryGetValueIfPresent(__CFAllRemoteMessagePorts, name, (const void **)&existing)) { CFRetain(existing); - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFRelease(memory); return (CFMessagePortRef)(existing); } @@ -572,7 +578,7 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF CFDictionaryAddValue(__CFAllRemoteMessagePorts, name, memory); } CFRetain(native); - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack); // that set-invalidation-callback might have called back into us // if the CFMachPort is already bad, but that was a no-op since @@ -596,12 +602,12 @@ CFMessagePortRef CFMessagePortCreatePerProcessRemote(CFAllocatorRef allocator, C } Boolean CFMessagePortIsRemote(CFMessagePortRef ms) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); return __CFMessagePortIsRemote(ms); } CFStringRef CFMessagePortGetName(CFMessagePortRef ms) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); return ms->_name; } @@ -609,23 +615,23 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) { CFAllocatorRef allocator = CFGetAllocator(ms); uint8_t *utfname = NULL; - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); if (ms->_perPID || __CFMessagePortIsRemote(ms)) return false; name = __CFMessagePortSanitizeStringName(name, &utfname, NULL); if (NULL == name) { return false; } - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); if (NULL != name) { CFMessagePortRef existing; if (NULL != __CFAllLocalMessagePorts && CFDictionaryGetValueIfPresent(__CFAllLocalMessagePorts, name, (const void **)&existing)) { - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); CFRelease(name); CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); return false; } } - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); if (NULL != name && (NULL == ms->_name || !CFEqual(ms->_name, name))) { CFMachPortRef oldPort = ms->_port; @@ -656,7 +662,10 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) { return false; } mp = CFMachPortGetPort(native); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" ret = bootstrap_register2(bs, (char *)utfname, mp, 0); +#pragma GCC diagnostic pop if (ret != KERN_SUCCESS) { CFLog(kCFLogLevelDebug, CFSTR("*** CFMessagePort: bootstrap_register(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'\nSee /usr/include/servers/bootstrap_defs.h for the error codes."), ret, ret, bootstrap_strerror(ret), mp, utfname); CFMachPortInvalidate(native); @@ -676,7 +685,7 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) { CFMachPortInvalidate(oldPort); CFRelease(oldPort); } - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); // This relocking without checking to see if something else has grabbed // that name in the cache is rather suspect, but what would that even // mean has happened? We'd expect the bootstrap_* calls above to have @@ -693,7 +702,7 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) { } ms->_name = name; CFDictionaryAddValue(__CFAllLocalMessagePorts, name, ms); - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); } CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname); @@ -701,14 +710,14 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) { } void CFMessagePortGetContext(CFMessagePortRef ms, CFMessagePortContext *context) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); //#warning CF: assert that this is a local port CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__); memmove(context, &ms->_context, sizeof(CFMessagePortContext)); } void CFMessagePortInvalidate(CFMessagePortRef ms) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); if (!__CFMessagePortIsDeallocing(ms)) { CFRetain(ms); } @@ -737,11 +746,11 @@ void CFMessagePortInvalidate(CFMessagePortRef ms) { ms->_port = NULL; __CFMessagePortUnlock(ms); - __CFSpinLock(&__CFAllMessagePortsLock); + __CFLock(&__CFAllMessagePortsLock); if (0 == ms->_perPID && NULL != name && NULL != (__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts)) { CFDictionaryRemoveValue(__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts, name); } - __CFSpinUnlock(&__CFAllMessagePortsLock); + __CFUnlock(&__CFAllMessagePortsLock); if (NULL != callout) { callout(ms, info); } @@ -783,7 +792,7 @@ void CFMessagePortInvalidate(CFMessagePortRef ms) { } Boolean CFMessagePortIsValid(CFMessagePortRef ms) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); if (!__CFMessagePortIsValid(ms)) return false; CFRetain(ms); if (NULL != ms->_port && !CFMachPortIsValid(ms->_port)) { @@ -801,12 +810,12 @@ Boolean CFMessagePortIsValid(CFMessagePortRef ms) { } CFMessagePortInvalidationCallBack CFMessagePortGetInvalidationCallBack(CFMessagePortRef ms) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); return ms->_icallout; } void CFMessagePortSetInvalidationCallBack(CFMessagePortRef ms, CFMessagePortInvalidationCallBack callout) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); if (!__CFMessagePortIsValid(ms) && NULL != callout) { callout(ms, ms->_context.info); } else { @@ -826,22 +835,26 @@ static void __CFMessagePortReplyCallBack(CFMachPortRef port, void *msg, CFIndex int32_t byteslen = 0; - Boolean invalidMagic = (MSGP_GET(msgp, magic) != MAGIC) && (CFSwapInt32(MSGP_GET(msgp, magic)) != MAGIC); - Boolean invalidComplex = (0 != msgp->body.msgh_descriptor_count) && !(msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX); - invalidComplex = invalidComplex || ((msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (0 == msgp->body.msgh_descriptor_count)); - Boolean wayTooBig = ((msgp->body.msgh_descriptor_count) ? sizeof(struct __CFMessagePortMachMessage1) : sizeof(struct __CFMessagePortMachMessage0) + __CFMessagePortMaxInlineBytes) < msgp->header.msgh_size; - Boolean wayTooSmall = msgp->header.msgh_size < sizeof(struct __CFMessagePortMachMessage0); + Boolean wayTooSmall = size < sizeof(mach_msg_header_t) || size < MSGP_SIZE(msgp) || msgp->header.msgh_size < MSGP_SIZE(msgp); + Boolean invalidMagic = false; + Boolean invalidComplex = false; + Boolean wayTooBig = false; + if (!wayTooSmall) { + invalidMagic = ((MSGP_INFO(msgp, magic) != MAGIC) && (CFSwapInt32(MSGP_INFO(msgp, magic)) != MAGIC)); + invalidComplex = (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (1 != msgp->body.msgh_descriptor_count); + wayTooBig = ((int32_t)MSGP_SIZE(msgp) + __CFMessagePortMaxInlineBytes) < msgp->header.msgh_size; // also less than a 32-bit signed int can hold + } Boolean wrongSize = false; if (!(invalidComplex || wayTooBig || wayTooSmall)) { - byteslen = CFSwapInt32LittleToHost(MSGP_GET(msgp, byteslen)); - wrongSize = (byteslen < 0) || (__CFMessagePortMaxDataSize < byteslen); - if (0 != msgp->body.msgh_descriptor_count) { - wrongSize = wrongSize || (MSGP1_FIELD(msgp, ool).size != byteslen); + byteslen = CFSwapInt32LittleToHost(MSGP_INFO(msgp, byteslen)); + wrongSize = (byteslen < -1) || (__CFMessagePortMaxDataSize < byteslen); + if (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) { + wrongSize = wrongSize || (MSGP_GET(msgp, ool).size != byteslen); } else { - wrongSize = wrongSize || (msgp->header.msgh_size - sizeof(struct __CFMessagePortMachMessage0) < byteslen); + wrongSize = wrongSize || ((int32_t)msgp->header.msgh_size - (int32_t)MSGP_SIZE(msgp) < byteslen); } } - Boolean invalidMsgID = (0 <= msgp->header.msgh_id) && (msgp->header.msgh_id <= INT32_MAX); // conversation id + Boolean invalidMsgID = wayTooSmall ? false : ((0 <= MSGP_INFO(msgp, convid)) && (MSGP_INFO(msgp, convid) <= INT32_MAX)); // conversation id if (invalidMagic || invalidComplex || wayTooBig || wayTooSmall || wrongSize || invalidMsgID) { CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: dropping corrupt reply Mach message (0b%d%d%d%d%d%d)"), invalidMagic, invalidComplex, wayTooBig, wayTooSmall, wrongSize, invalidMsgID); mach_msg_destroy((mach_msg_header_t *)msgp); @@ -849,26 +862,27 @@ static void __CFMessagePortReplyCallBack(CFMachPortRef port, void *msg, CFIndex return; } - if (CFDictionaryContainsKey(ms->_replies, (void *)(uintptr_t)msgp->header.msgh_id)) { + if (CFDictionaryContainsKey(ms->_replies, (void *)(uintptr_t)MSGP_INFO(msgp, convid))) { CFDataRef reply = NULL; replymsg = (mach_msg_base_t *)msg; - if (0 == replymsg->body.msgh_descriptor_count) { + if (!(replymsg->header.msgh_bits & MACH_MSGH_BITS_COMPLEX)) { uintptr_t msgp_extent = (uintptr_t)((uint8_t *)msgp + msgp->header.msgh_size); - uintptr_t data_extent = (uintptr_t)((uint8_t *)&(MSGP0_FIELD(replymsg, bytes)) + byteslen); + uintptr_t data_extent = (uintptr_t)((uint8_t *)&(MSGP_INFO(replymsg, bytes)) + byteslen); + if (byteslen < 0) byteslen = 0; // from here on, treat negative same as zero -- this is historical behavior: a NULL return from the callback on the other side results in empty data to the original requestor if (0 <= byteslen && data_extent <= msgp_extent) { - reply = CFDataCreate(kCFAllocatorSystemDefault, MSGP0_FIELD(replymsg, bytes), byteslen); + reply = CFDataCreate(kCFAllocatorSystemDefault, MSGP_INFO(replymsg, bytes), byteslen); } else { reply = (void *)~0; // means NULL data } } else { //#warning CF: should create a no-copy data here that has a custom VM-freeing allocator, and not vm_dealloc here - reply = CFDataCreate(kCFAllocatorSystemDefault, MSGP1_FIELD(replymsg, ool).address, MSGP1_FIELD(replymsg, ool).size); - vm_deallocate(mach_task_self(), (vm_address_t)MSGP1_FIELD(replymsg, ool).address, MSGP1_FIELD(replymsg, ool).size); + reply = CFDataCreate(kCFAllocatorSystemDefault, MSGP_GET(replymsg, ool).address, MSGP_GET(replymsg, ool).size); + vm_deallocate(mach_task_self(), (vm_address_t)MSGP_GET(replymsg, ool).address, MSGP_GET(replymsg, ool).size); } - CFDictionarySetValue(ms->_replies, (void *)(uintptr_t)msgp->header.msgh_id, (void *)reply); + CFDictionarySetValue(ms->_replies, (void *)(uintptr_t)MSGP_INFO(msgp, convid), (void *)reply); } else { /* discard message */ - if (1 == msgp->body.msgh_descriptor_count) { - vm_deallocate(mach_task_self(), (vm_address_t)MSGP1_FIELD(msgp, ool).address, MSGP1_FIELD(msgp, ool).size); + if (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) { + vm_deallocate(mach_task_self(), (vm_address_t)MSGP_GET(msgp, ool).address, MSGP_GET(msgp, ool).size); } } __CFMessagePortUnlock(ms); @@ -908,7 +922,7 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef } remote->_convCounter++; desiredReply = -remote->_convCounter; - sendmsg = __CFMessagePortCreateMessage(false, CFMachPortGetPort(remote->_port), (replyMode != NULL ? CFMachPortGetPort(remote->_replyPort) : MACH_PORT_NULL), -desiredReply, msgid, (data ? CFDataGetBytePtr(data) : NULL), (data ? CFDataGetLength(data) : 0)); + sendmsg = __CFMessagePortCreateMessage(false, CFMachPortGetPort(remote->_port), (replyMode != NULL ? CFMachPortGetPort(remote->_replyPort) : MACH_PORT_NULL), -desiredReply, msgid, (data ? CFDataGetBytePtr(data) : NULL), (data ? CFDataGetLength(data) : -1)); if (!sendmsg) { __CFMessagePortUnlock(remote); CFRelease(remote); @@ -999,7 +1013,7 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo void (*context_release)(const void *); CFDataRef returnData, data = NULL; void *return_bytes = NULL; - CFIndex return_len = 0; + CFIndex return_len = -1; int32_t msgid; __CFMessagePortLock(ms); @@ -1019,39 +1033,45 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo int32_t byteslen = 0; - Boolean invalidMagic = (MSGP_GET(msgp, magic) != MAGIC) && (CFSwapInt32(MSGP_GET(msgp, magic)) != MAGIC); - Boolean invalidComplex = (0 != msgp->body.msgh_descriptor_count) && !(msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX); - invalidComplex = invalidComplex || ((msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (0 == msgp->body.msgh_descriptor_count)); - Boolean wayTooBig = ((msgp->body.msgh_descriptor_count) ? sizeof(struct __CFMessagePortMachMessage1) : sizeof(struct __CFMessagePortMachMessage0) + __CFMessagePortMaxInlineBytes) < msgp->header.msgh_size; - Boolean wayTooSmall = msgp->header.msgh_size < sizeof(struct __CFMessagePortMachMessage0); + Boolean wayTooSmall = size < sizeof(mach_msg_header_t) || size < MSGP_SIZE(msgp) || msgp->header.msgh_size < MSGP_SIZE(msgp); + Boolean invalidMagic = false; + Boolean invalidComplex = false; + Boolean wayTooBig = false; + if (!wayTooSmall) { + invalidMagic = ((MSGP_INFO(msgp, magic) != MAGIC) && (CFSwapInt32(MSGP_INFO(msgp, magic)) != MAGIC)); + invalidComplex = (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (1 != msgp->body.msgh_descriptor_count); + wayTooBig = ((int32_t)MSGP_SIZE(msgp) + __CFMessagePortMaxInlineBytes) < msgp->header.msgh_size; // also less than a 32-bit signed int can hold + } Boolean wrongSize = false; if (!(invalidComplex || wayTooBig || wayTooSmall)) { - byteslen = CFSwapInt32LittleToHost(MSGP_GET(msgp, byteslen)); - wrongSize = (byteslen < 0) || (__CFMessagePortMaxDataSize < byteslen); - if (0 != msgp->body.msgh_descriptor_count) { - wrongSize = wrongSize || (MSGP1_FIELD(msgp, ool).size != byteslen); + byteslen = CFSwapInt32LittleToHost(MSGP_INFO(msgp, byteslen)); + wrongSize = (byteslen < -1) || (__CFMessagePortMaxDataSize < byteslen); + if (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) { + wrongSize = wrongSize || (MSGP_GET(msgp, ool).size != byteslen); } else { - wrongSize = wrongSize || (msgp->header.msgh_size - sizeof(struct __CFMessagePortMachMessage0) < byteslen); + wrongSize = wrongSize || ((int32_t)msgp->header.msgh_size - (int32_t)MSGP_SIZE(msgp) < byteslen); } } - Boolean invalidMsgID = (msgp->header.msgh_id <= 0) || (INT32_MAX < msgp->header.msgh_id); // conversation id + Boolean invalidMsgID = wayTooSmall ? false : ((MSGP_INFO(msgp, convid) <= 0) || (INT32_MAX < MSGP_INFO(msgp, convid))); // conversation id if (invalidMagic || invalidComplex || wayTooBig || wayTooSmall || wrongSize || invalidMsgID) { CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: dropping corrupt request Mach message (0b%d%d%d%d%d%d)"), invalidMagic, invalidComplex, wayTooBig, wayTooSmall, wrongSize, invalidMsgID); mach_msg_destroy((mach_msg_header_t *)msgp); return NULL; } + if (byteslen < 0) byteslen = 0; // from here on, treat negative same as zero + /* Create no-copy, no-free-bytes wrapper CFData */ - if (0 == msgp->body.msgh_descriptor_count) { + if (!(msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX)) { uintptr_t msgp_extent = (uintptr_t)((uint8_t *)msgp + msgp->header.msgh_size); - uintptr_t data_extent = (uintptr_t)((uint8_t *)&(MSGP0_FIELD(msgp, bytes)) + byteslen); - msgid = CFSwapInt32LittleToHost(MSGP_GET(msgp, msgid)); + uintptr_t data_extent = (uintptr_t)((uint8_t *)&(MSGP_INFO(msgp, bytes)) + byteslen); + msgid = CFSwapInt32LittleToHost(MSGP_INFO(msgp, msgid)); if (0 <= byteslen && data_extent <= msgp_extent) { - data = CFDataCreateWithBytesNoCopy(allocator, MSGP0_FIELD(msgp, bytes), byteslen, kCFAllocatorNull); - } + data = CFDataCreateWithBytesNoCopy(allocator, MSGP_INFO(msgp, bytes), byteslen, kCFAllocatorNull); + } } else { - msgid = CFSwapInt32LittleToHost(MSGP_GET(msgp, msgid)); - data = CFDataCreateWithBytesNoCopy(allocator, MSGP1_FIELD(msgp, ool).address, MSGP1_FIELD(msgp, ool).size, kCFAllocatorNull); + msgid = CFSwapInt32LittleToHost(MSGP_INFO(msgp, msgid)); + data = CFDataCreateWithBytesNoCopy(allocator, MSGP_GET(msgp, ool).address, MSGP_GET(msgp, ool).size, kCFAllocatorNull); } if (ms->_callout) { returnData = ms->_callout(ms, msgid, data, context_info); @@ -1074,6 +1094,7 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo if (__CFMessagePortMaxDataSize < return_len) { CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort reply: CFMessagePort cannot send more than %lu bytes of data"), __CFMessagePortMaxDataSize); return_len = 0; + CFRelease(returnData); returnData = NULL; } if (returnData && return_len < __CFMessagePortMaxInlineBytes) { @@ -1088,13 +1109,13 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo memmove(return_bytes, CFDataGetBytePtr(returnData), return_len); } } - replymsg = __CFMessagePortCreateMessage(true, msgp->header.msgh_remote_port, MACH_PORT_NULL, -1 * (int32_t)msgp->header.msgh_id, msgid, return_bytes, return_len); - if (1 == replymsg->body.msgh_descriptor_count) { - MSGP1_FIELD(replymsg, ool).deallocate = true; + replymsg = __CFMessagePortCreateMessage(true, msgp->header.msgh_remote_port, MACH_PORT_NULL, -1 * (int32_t)MSGP_INFO(msgp, convid), msgid, return_bytes, return_len); + if (replymsg->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) { + MSGP_GET(replymsg, ool).deallocate = true; } if (data) CFRelease(data); - if (1 == msgp->body.msgh_descriptor_count) { - vm_deallocate(mach_task_self(), (vm_address_t)MSGP1_FIELD(msgp, ool).address, MSGP1_FIELD(msgp, ool).size); + if (msgp->header.msgh_bits & MACH_MSGH_BITS_COMPLEX) { + vm_deallocate(mach_task_self(), (vm_address_t)MSGP_GET(msgp, ool).address, MSGP_GET(msgp, ool).size); } if (returnData) CFRelease(returnData); if (context_release) { @@ -1105,7 +1126,7 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef ms, CFIndex order) { CFRunLoopSourceRef result = NULL; - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); if (!CFMessagePortIsValid(ms)) return NULL; if (__CFMessagePortIsRemote(ms)) return NULL; __CFMessagePortLock(ms); @@ -1134,7 +1155,7 @@ CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CF } void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) { - __CFGenericValidateType(ms, __kCFMessagePortTypeID); + __CFGenericValidateType(ms, CFMessagePortGetTypeID()); __CFMessagePortLock(ms); if (!__CFMessagePortIsValid(ms)) { __CFMessagePortUnlock(ms); @@ -1164,7 +1185,8 @@ void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) static dispatch_queue_t mportQueue = NULL; static dispatch_once_t once; dispatch_once(&once, ^{ - mportQueue = dispatch_queue_create("CFMessagePort Queue", NULL); + dispatch_queue_attr_t dqattr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qos_class_main(), 0); + mportQueue = dispatch_queue_create("com.apple.CFMessagePort", dqattr); }); dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, port, 0, mportQueue); dispatch_source_set_cancel_handler(theSource, ^{ diff --git a/CFMessagePort.h b/CFMessagePort.h index c00c60a..b13a4dd 100644 --- a/CFMessagePort.h +++ b/CFMessagePort.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFMessagePort.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFMESSAGEPORT__) @@ -33,9 +33,10 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -typedef struct __CFMessagePort * CFMessagePortRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMessagePort) __CFMessagePort * CFMessagePortRef; enum { kCFMessagePortSuccess = 0, @@ -80,6 +81,7 @@ CF_EXPORT CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef all CF_EXPORT void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) CF_AVAILABLE(10_6, 4_0); CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFMESSAGEPORT__ */ diff --git a/CFNumber.c b/CFNumber.c index ae4147c..5413794 100644 --- a/CFNumber.c +++ b/CFNumber.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFNumber.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -39,7 +39,7 @@ #define copysign(A, B) _copysign(A, B) #endif -#define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID) +#define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, CFBooleanGetTypeID()) struct __CFBoolean { CFRuntimeBase _base; @@ -88,18 +88,18 @@ static const CFRuntimeClass __CFBooleanClass = { __CFBooleanCopyDescription }; -CF_PRIVATE void __CFBooleanInitialize(void) { - __kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass); - _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanTrue, __kCFBooleanTypeID); - _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanFalse, __kCFBooleanTypeID); -} - CFTypeID CFBooleanGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass); // initOnce covered + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanTrue, __kCFBooleanTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanFalse, __kCFBooleanTypeID); + }); return __kCFBooleanTypeID; } Boolean CFBooleanGetValue(CFBooleanRef boolean) { - CF_OBJC_FUNCDISPATCHV(__kCFBooleanTypeID, Boolean, (NSNumber *)boolean, boolValue); + CF_OBJC_FUNCDISPATCHV(CFBooleanGetTypeID(), Boolean, (NSNumber *)boolean, boolValue); return (boolean == kCFBooleanTrue) ? true : false; } @@ -139,7 +139,7 @@ static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, s #endif -#define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID) +#define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, CFNumberGetTypeID()) #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type); /* The IEEE bit patterns... Also have: @@ -1007,27 +1007,27 @@ static const CFRuntimeClass __CFNumberClass = { }; -CF_PRIVATE void __CFNumberInitialize(void) { - __kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass); - - _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN, __kCFNumberTypeID); - __CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); - __kCFNumberNaN._pad = BITSFORDOUBLENAN; +CFTypeID CFNumberGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass); // initOnce covered - _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity, __kCFNumberTypeID); - __CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); - __kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF; + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN, __kCFNumberTypeID); + __CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); + __kCFNumberNaN._pad = BITSFORDOUBLENAN; - _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity, __kCFNumberTypeID); - __CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); - __kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF; + _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity, __kCFNumberTypeID); + __CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); + __kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF; + _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity, __kCFNumberTypeID); + __CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); + __kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF; - const char *caching = __CFgetenv("CFNumberDisableCache"); // "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled - if (caching) __CFNumberCaching = (!strcmp(caching, "all")) ? kCFNumberCachingFullyDisabled : kCFNumberCachingDisabled; // initial state above is kCFNumberCachingEnabled -} -CFTypeID CFNumberGetTypeID(void) { + const char *caching = __CFgetenv("CFNumberDisableCache"); // "all" to disable caching and tagging; anything else to disable caching; nothing to leave both enabled + if (caching) __CFNumberCaching = (!strcmp(caching, "all")) ? kCFNumberCachingFullyDisabled : kCFNumberCachingDisabled; // initial state above is kCFNumberCachingEnabled + }); return __kCFNumberTypeID; } @@ -1080,7 +1080,7 @@ CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType type, const vo #if OLD_CRAP_TOO size += 2 * sizeof(void *); #endif - CFNumberRef result = (CFNumberRef)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, size, NULL); + CFNumberRef result = (CFNumberRef)_CFRuntimeCreateInstance(allocator, CFNumberGetTypeID(), size, NULL); if (NULL == result) { return NULL; } @@ -1130,7 +1130,7 @@ CFLog(kCFLogLevelWarning, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDes CFNumberType CFNumberGetType(CFNumberRef number) { //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number); - CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType); + CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), CFNumberType, (NSNumber *)number, _cfNumberType); __CFAssertIsNumber(number); CFNumberType type = __CFNumberGetType(number); if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; // must hide this type, since it is not public @@ -1149,7 +1149,7 @@ CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), } CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number) { - CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType); + CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), CFNumberType, (NSNumber *)number, _cfNumberType); __CFAssertIsNumber(number); return __CFNumberGetType(number); } @@ -1193,7 +1193,7 @@ CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d' Boolean CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr) { //printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr); - CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, Boolean, (NSNumber *)number, _getValue:(void *)valuePtr forType:(CFNumberType)__CFNumberTypeTable[type].canonicalType); + CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), Boolean, (NSNumber *)number, _getValue:(void *)valuePtr forType:(CFNumberType)__CFNumberTypeTable[type].canonicalType); __CFAssertIsNumber(number); __CFAssertIsValidNumberType(type); uint8_t localMemory[128]; @@ -1217,8 +1217,8 @@ CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT } static CFComparisonResult CFNumberCompare_new(CFNumberRef number1, CFNumberRef number2, void *context) { - CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFComparisonResult, (NSNumber *)number1, compare:(NSNumber *)number2); - CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFComparisonResult, (NSNumber *)number2, _reverseCompare:(NSNumber *)number1); + CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), CFComparisonResult, (NSNumber *)number1, compare:(NSNumber *)number2); + CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), CFComparisonResult, (NSNumber *)number2, _reverseCompare:(NSNumber *)number1); __CFAssertIsNumber(number1); __CFAssertIsNumber(number2); @@ -1585,7 +1585,7 @@ type = kCFNumberSInt64Type; storageType = __CFNumberGetStorageTypeForType_old(type); - num = (struct __CFNumber_old *)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, __CFNumberSizeOfType_old(storageType), NULL); + num = (struct __CFNumber_old *)_CFRuntimeCreateInstance(allocator, CFNumberGetTypeID(), __CFNumberSizeOfType_old(storageType), NULL); if (NULL == num) { return NULL; } diff --git a/CFNumber.h b/CFNumber.h index 2249d9c..7ac3760 100644 --- a/CFNumber.h +++ b/CFNumber.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFNumber.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFNUMBER__) @@ -33,7 +33,7 @@ CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN -typedef const struct __CFBoolean * CFBooleanRef; +typedef const struct CF_BRIDGED_TYPE(NSNumber) __CFBoolean * CFBooleanRef; CF_EXPORT const CFBooleanRef kCFBooleanTrue; @@ -69,7 +69,7 @@ typedef CF_ENUM(CFIndex, CFNumberType) { kCFNumberMaxType = 16 }; -typedef const struct __CFNumber * CFNumberRef; +typedef const struct CF_BRIDGED_TYPE(NSNumber) __CFNumber * CFNumberRef; CF_EXPORT const CFNumberRef kCFNumberPositiveInfinity; diff --git a/CFNumberFormatter.c b/CFNumberFormatter.c index 6dbe697..906ae39 100644 --- a/CFNumberFormatter.c +++ b/CFNumberFormatter.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFNumberFormatter.c - Copyright (c) 2002-2013, Apple Inc. All rights reserved. + Copyright (c) 2002-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -39,6 +39,7 @@ static void __CFNumberFormatterCustomize(CFNumberFormatterRef formatter); static CFStringRef __CFNumberFormatterCreateCompressedString(CFStringRef inString, Boolean isFormat, CFRange *rangep); static UErrorCode __CFNumberFormatterApplyPattern(CFNumberFormatterRef formatter, CFStringRef pattern); +static CONST_STRING_DECL(kCFNumberFormatterFormattingContextKey, "kCFNumberFormatterFormattingContextKey"); #define BUFFER_SIZE 768 @@ -87,12 +88,9 @@ static const CFRuntimeClass __CFNumberFormatterClass = { __CFNumberFormatterCopyDescription }; -static void __CFNumberFormatterInitialize(void) { - __kCFNumberFormatterTypeID = _CFRuntimeRegisterClass(&__CFNumberFormatterClass); -} - CFTypeID CFNumberFormatterGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFNumberFormatterTypeID) __CFNumberFormatterInitialize(); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFNumberFormatterTypeID = _CFRuntimeRegisterClass(&__CFNumberFormatterClass); }); return __kCFNumberFormatterTypeID; } @@ -179,6 +177,7 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR } } __cficu_unum_setAttribute(memory->_nf, UNUM_LENIENT_PARSE, 0); + __cficu_unum_setContext(memory->_nf, UDISPCTX_CAPITALIZATION_NONE, &status); return (CFNumberFormatterRef)memory; } @@ -769,6 +768,11 @@ void CFNumberFormatterSetProperty(CFNumberFormatterRef formatter, CFStringRef ke __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID()); __CFGenericValidateType(key, CFStringGetTypeID()); // rule-based formatters don't do attributes and symbols, except for one + if (CFEqual(kCFNumberFormatterFormattingContextKey, key)) { + __CFGenericValidateType(value, CFNumberGetTypeID()); + CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); + __cficu_unum_setContext(formatter->_nf, n, &status); + } if (kCFNumberFormatterSpellOutStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return; if (kCFNumberFormatterOrdinalStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return; if (kCFNumberFormatterDurationStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return; @@ -983,6 +987,12 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID()); __CFGenericValidateType(key, CFStringGetTypeID()); // rule-based formatters don't do attributes and symbols, except for one + if (CFEqual(kCFNumberFormatterFormattingContextKey, key)) { + n = __cficu_unum_getContext(formatter->_nf, UDISPCTX_TYPE_CAPITALIZATION, &status); + if (1) { + return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); + } + } if (kCFNumberFormatterSpellOutStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return NULL; if (kCFNumberFormatterOrdinalStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return NULL; if (kCFNumberFormatterDurationStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return NULL; @@ -1203,5 +1213,10 @@ Boolean CFNumberFormatterGetDecimalInfoForCurrencyCode(CFStringRef currencyCode, return (!defaultFractionDigits || 0 <= *defaultFractionDigits) && (!roundingIncrement || 0.0 <= *roundingIncrement); } +// This is for NSNumberFormatter use only! +void *_CFNumberFormatterGetFormatter(CFNumberFormatterRef formatter) { + return (void *)formatter->_nf; +} + #undef BUFFER_SIZE diff --git a/CFNumberFormatter.h b/CFNumberFormatter.h index ce38a6b..35beb70 100644 --- a/CFNumberFormatter.h +++ b/CFNumberFormatter.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFNumberFormatter.h - Copyright (c) 2003-2013, Apple Inc. All rights reserved. + Copyright (c) 2003-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFNUMBERFORMATTER__) @@ -32,6 +32,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFNumberFormatter *CFNumberFormatterRef; @@ -179,6 +180,7 @@ Boolean CFNumberFormatterGetDecimalInfoForCurrencyCode(CFStringRef currencyCode, // Not localized because these are properties of the currency. CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFNUMBERFORMATTER__ */ diff --git a/CFOldStylePList.c b/CFOldStylePList.c index 3398658..e66c15b 100644 --- a/CFOldStylePList.c +++ b/CFOldStylePList.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFOldStylePList.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ diff --git a/CFPlatform.c b/CFPlatform.c index 348024a..9124aa0 100644 --- a/CFPlatform.c +++ b/CFPlatform.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlatform.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ diff --git a/CFPlatformConverters.c b/CFPlatformConverters.c index 071b97f..4bc3217 100644 --- a/CFPlatformConverters.c +++ b/CFPlatformConverters.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlatformConverters.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -45,6 +45,8 @@ CF_INLINE bool __CFIsPlatformConverterAvailable(int encoding) { #endif } +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX + static const CFStringEncodingConverter __CFICUBootstrap = { NULL /* toBytes */, NULL /* toUnicode */, 6 /* maxBytesPerChar */, 4 /* maxDecomposedCharLen */, kCFStringEncodingConverterICU /* encodingClass */, @@ -52,6 +54,8 @@ static const CFStringEncodingConverter __CFICUBootstrap = { NULL /* toUnicodeFallback */, NULL /* toBytesPrecompose */, NULL, /* isValidCombiningChar */ }; +#endif + static const CFStringEncodingConverter __CFPlatformBootstrap = { NULL /* toBytes */, NULL /* toUnicode */, 6 /* maxBytesPerChar */, 4 /* maxDecomposedCharLen */, kCFStringEncodingConverterPlatformSpecific /* encodingClass */, diff --git a/CFPlugIn.c b/CFPlugIn.c index 0f0ef1a..0a13b2f 100644 --- a/CFPlugIn.c +++ b/CFPlugIn.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugIn.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ diff --git a/CFPlugIn.h b/CFPlugIn.h index 72fe4f5..54b7276 100644 --- a/CFPlugIn.h +++ b/CFPlugIn.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugIn.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPLUGIN__) @@ -39,6 +39,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN /* ================ Standard Info.plist keys for plugIns ================ */ @@ -131,6 +132,7 @@ CF_EXPORT CFTypeID CFPlugInInstanceGetTypeID(void); CF_EXPORT CFPlugInInstanceRef CFPlugInInstanceCreateWithInstanceDataSize(CFAllocatorRef allocator, CFIndex instanceDataSize, CFPlugInInstanceDeallocateInstanceDataFunction deallocateInstanceFunction, CFStringRef factoryName, CFPlugInInstanceGetInterfaceFunction getInterfaceFunction); CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #if !COREFOUNDATION_CFPLUGINCOM_SEPARATE #include diff --git a/CFPlugInCOM.h b/CFPlugInCOM.h index 62a88f1..e9b9b66 100644 --- a/CFPlugInCOM.h +++ b/CFPlugInCOM.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugInCOM.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPLUGINCOM__) diff --git a/CFPlugIn_Factory.c b/CFPlugIn_Factory.c index e65cf92..20be4b4 100644 --- a/CFPlugIn_Factory.c +++ b/CFPlugIn_Factory.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugIn_Factory.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -44,7 +44,7 @@ struct __CFPFactory { CFStringRef _funcName; CFMutableArrayRef _types; - CFSpinLock_t _lock; + CFLock_t _lock; }; static void _CFPFactoryDeallocate(CFTypeRef factory); @@ -62,44 +62,45 @@ static const CFRuntimeClass __CFPFactoryClass = { }; CF_PRIVATE void __CFPFactoryInitialize(void) { - __kCFPFactoryTypeID = _CFRuntimeRegisterClass(&__CFPFactoryClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFPFactoryTypeID = _CFRuntimeRegisterClass(&__CFPFactoryClass); }); } static CFTypeID _CFPFactoryGetTypeID(void) { return __kCFPFactoryTypeID; } -static CFSpinLock_t CFPlugInGlobalDataLock = CFSpinLockInit; +static CFLock_t CFPlugInGlobalDataLock = CFLockInit; static CFMutableDictionaryRef _factoriesByFactoryID = NULL; /* Value is _CFPFactoryRef */ static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _CFPFactoryRef */ static void _CFPFactoryAddToTable(_CFPFactoryRef factory) { - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); CFUUIDRef uuid = (CFUUIDRef)CFRetain(factory->_uuid); CFRetain(factory); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); - __CFSpinLock(&CFPlugInGlobalDataLock); + __CFLock(&CFPlugInGlobalDataLock); if (!_factoriesByFactoryID) { CFDictionaryValueCallBacks _factoryDictValueCallbacks = {0, NULL, NULL, NULL, NULL}; _factoriesByFactoryID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &_factoryDictValueCallbacks); } CFDictionarySetValue(_factoriesByFactoryID, uuid, factory); - __CFSpinUnlock(&CFPlugInGlobalDataLock); + __CFUnlock(&CFPlugInGlobalDataLock); if (uuid) CFRelease(uuid); CFRelease(factory); } static void _CFPFactoryRemoveFromTable(_CFPFactoryRef factory) { - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); CFUUIDRef uuid = factory->_uuid; if (uuid) CFRetain(uuid); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); - __CFSpinLock(&CFPlugInGlobalDataLock); + __CFLock(&CFPlugInGlobalDataLock); if (uuid && _factoriesByTypeID) CFDictionaryRemoveValue(_factoriesByFactoryID, uuid); - __CFSpinUnlock(&CFPlugInGlobalDataLock); + __CFUnlock(&CFPlugInGlobalDataLock); if (uuid) CFRelease(uuid); } @@ -107,12 +108,12 @@ static void _CFPFactoryRemoveFromTable(_CFPFactoryRef factory) { CF_PRIVATE _CFPFactoryRef _CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) { _CFPFactoryRef result = NULL; - __CFSpinLock(&CFPlugInGlobalDataLock); + __CFLock(&CFPlugInGlobalDataLock); if (_factoriesByFactoryID) { result = (_CFPFactoryRef )CFDictionaryGetValue(_factoriesByFactoryID, factoryID); if (result && result->_enabled != enabled) result = NULL; } - __CFSpinUnlock(&CFPlugInGlobalDataLock); + __CFUnlock(&CFPlugInGlobalDataLock); return result; } @@ -146,7 +147,7 @@ static _CFPFactoryRef _CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRe factory->_uuid = (CFUUIDRef)CFRetain(factoryID); factory->_enabled = true; factory->_types = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); - factory->_lock = CFSpinLockInit; // WARNING: grab global lock before this lock + factory->_lock = CFLockInit; // WARNING: grab global lock before this lock _CFPFactoryAddToTable(factory); @@ -156,11 +157,11 @@ static _CFPFactoryRef _CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRe CF_PRIVATE _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) { _CFPFactoryRef factory = _CFPFactoryCommonCreate(allocator, factoryID); - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); factory->_func = func; factory->_plugIn = NULL; factory->_funcName = NULL; - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); return factory; } @@ -168,36 +169,36 @@ CF_PRIVATE _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef CF_PRIVATE _CFPFactoryRef _CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) { _CFPFactoryRef factory = _CFPFactoryCommonCreate(allocator, factoryID); - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); factory->_func = NULL; factory->_plugIn = (CFPlugInRef)CFRetain(plugIn); if (plugIn) _CFPlugInAddFactory(plugIn, factory); factory->_funcName = (funcName ? (CFStringRef)CFStringCreateCopy(allocator, funcName) : NULL); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); return factory; } CF_PRIVATE CFUUIDRef _CFPFactoryCopyFactoryID(_CFPFactoryRef factory) { - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); CFUUIDRef uuid = factory->_uuid; if (uuid) CFRetain(uuid); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); return uuid; } CF_PRIVATE CFPlugInRef _CFPFactoryCopyPlugIn(_CFPFactoryRef factory) { - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); CFPlugInRef result = factory->_plugIn; if (result) CFRetain(result); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); return result; } CF_PRIVATE void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactoryRef factory, CFUUIDRef typeID) { void *result = NULL; - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); if (factory->_enabled) { if (!factory->_func) { factory->_func = (CFPlugInFactoryFunction)CFBundleGetFunctionPointerForName(factory->_plugIn, factory->_funcName); @@ -206,42 +207,42 @@ CF_PRIVATE void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactory if (factory->_func) { // UPPGOOP CFPlugInFactoryFunction f = factory->_func; - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); FAULT_CALLBACK((void **)&(f)); result = (void *)INVOKE_CALLBACK2(f, allocator, typeID); - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); } } else { CFLog(__kCFLogPlugIn, CFSTR("Factory %@ is disabled"), factory->_uuid); } - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); return result; } CF_PRIVATE void _CFPFactoryDisable(_CFPFactoryRef factory) { - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); factory->_enabled = false; - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); CFRelease(factory); } CF_PRIVATE void _CFPFactoryFlushFunctionCache(_CFPFactoryRef factory) { /* MF:!!! Assert that this factory belongs to a plugIn. */ /* This is called by the factory's plugIn when the plugIn unloads its code. */ - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); factory->_func = NULL; - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); } CF_PRIVATE void _CFPFactoryAddType(_CFPFactoryRef factory, CFUUIDRef typeID) { /* Add the factory to the type's array of factories */ - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); /* Add the type to the factory's type list */ CFArrayAppendValue(factory->_types, typeID); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); - __CFSpinLock(&CFPlugInGlobalDataLock); + __CFLock(&CFPlugInGlobalDataLock); if (!_factoriesByTypeID) _factoriesByTypeID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID); if (!array) { @@ -252,20 +253,20 @@ CF_PRIVATE void _CFPFactoryAddType(_CFPFactoryRef factory, CFUUIDRef typeID) { CFRelease(array); } CFArrayAppendValue(array, factory); - __CFSpinUnlock(&CFPlugInGlobalDataLock); + __CFUnlock(&CFPlugInGlobalDataLock); } CF_PRIVATE void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef typeID) { /* Remove it from the factory's type list */ SInt32 idx; - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID); if (idx >= 0) CFArrayRemoveValueAtIndex(factory->_types, idx); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); /* Remove the factory from the type's list of factories */ - __CFSpinLock(&CFPlugInGlobalDataLock); + __CFLock(&CFPlugInGlobalDataLock); if (_factoriesByTypeID) { CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID); if (array) { @@ -276,27 +277,27 @@ CF_PRIVATE void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef typeID) } } } - __CFSpinUnlock(&CFPlugInGlobalDataLock); + __CFUnlock(&CFPlugInGlobalDataLock); } CF_PRIVATE Boolean _CFPFactorySupportsType(_CFPFactoryRef factory, CFUUIDRef typeID) { SInt32 idx; - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); return (idx >= 0 ? true : false); } CF_PRIVATE CFArrayRef _CFPFactoryFindCopyForType(CFUUIDRef typeID) { CFArrayRef result = NULL; - __CFSpinLock(&CFPlugInGlobalDataLock); + __CFLock(&CFPlugInGlobalDataLock); if (_factoriesByTypeID) { result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID); if (result) CFRetain(result); } - __CFSpinUnlock(&CFPlugInGlobalDataLock); + __CFUnlock(&CFPlugInGlobalDataLock); return result; } @@ -305,10 +306,10 @@ CF_PRIVATE CFArrayRef _CFPFactoryFindCopyForType(CFUUIDRef typeID) { CF_PRIVATE void _CFPFactoryAddInstance(_CFPFactoryRef factory) { /* MF:!!! Assert that factory is enabled. */ CFRetain(factory); - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); CFPlugInRef plugin = factory->_plugIn; if (plugin) CFRetain(plugin); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); if (plugin) { _CFPlugInAddPlugInInstance(plugin); CFRelease(plugin); @@ -316,10 +317,10 @@ CF_PRIVATE void _CFPFactoryAddInstance(_CFPFactoryRef factory) { } CF_PRIVATE void _CFPFactoryRemoveInstance(_CFPFactoryRef factory) { - __CFSpinLock(&factory->_lock); + __CFLock(&factory->_lock); CFPlugInRef plugin = factory->_plugIn; if (plugin) CFRetain(plugin); - __CFSpinUnlock(&factory->_lock); + __CFUnlock(&factory->_lock); if (plugin) { _CFPlugInRemovePlugInInstance(factory->_plugIn); CFRelease(plugin); diff --git a/CFPlugIn_Factory.h b/CFPlugIn_Factory.h index 15ff7af..3b01923 100644 --- a/CFPlugIn_Factory.h +++ b/CFPlugIn_Factory.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugIn_Factory.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPLUGIN_FACTORY__) diff --git a/CFPlugIn_Instance.c b/CFPlugIn_Instance.c index 3eebd0c..e99211f 100644 --- a/CFPlugIn_Instance.c +++ b/CFPlugIn_Instance.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugIn_Instance.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -57,7 +57,7 @@ static CFStringRef __CFPlugInInstanceCopyDescription(CFTypeRef cf) { static void __CFPlugInInstanceDeallocate(CFTypeRef cf) { CFPlugInInstanceRef instance = (CFPlugInInstanceRef)cf; - __CFGenericValidateType(cf, __kCFPlugInInstanceTypeID); + __CFGenericValidateType(cf, CFPlugInInstanceGetTypeID()); if (instance->deallocateInstanceDataFunction) { FAULT_CALLBACK((void **)&(instance->deallocateInstanceDataFunction)); @@ -79,11 +79,9 @@ static const CFRuntimeClass __CFPlugInInstanceClass = { __CFPlugInInstanceCopyDescription }; -CF_PRIVATE void __CFPlugInInstanceInitialize(void) { - __kCFPlugInInstanceTypeID = _CFRuntimeRegisterClass(&__CFPlugInInstanceClass); -} - CFTypeID CFPlugInInstanceGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFPlugInInstanceTypeID = _CFRuntimeRegisterClass(&__CFPlugInInstanceClass); }); return __kCFPlugInInstanceTypeID; } @@ -91,7 +89,7 @@ CF_EXPORT CFPlugInInstanceRef CFPlugInInstanceCreateWithInstanceDataSize(CFAlloc CFPlugInInstanceRef instance; UInt32 size; size = sizeof(struct __CFPlugInInstance) + instanceDataSize - sizeof(CFRuntimeBase); - instance = (CFPlugInInstanceRef)_CFRuntimeCreateInstance(allocator, __kCFPlugInInstanceTypeID, size, NULL); + instance = (CFPlugInInstanceRef)_CFRuntimeCreateInstance(allocator, CFPlugInInstanceGetTypeID(), size, NULL); if (!instance) return NULL; instance->factory = _CFPFactoryFind((CFUUIDRef)factoryName, true); diff --git a/CFPlugIn_PlugIn.c b/CFPlugIn_PlugIn.c index fdcf7c5..fef9aab 100644 --- a/CFPlugIn_PlugIn.c +++ b/CFPlugIn_PlugIn.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPlugIn_PlugIn.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ diff --git a/CFPreferences.c b/CFPreferences.c index c8cc416..09e8070 100644 --- a/CFPreferences.c +++ b/CFPreferences.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPreferences.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -244,7 +244,7 @@ Boolean __CFPreferencesShouldWriteXML(void) { return __CFPreferencesWritesXML; } -static CFSpinLock_t domainCacheLock = CFSpinLockInit; +static CFLock_t domainCacheLock = CFLockInit; static CFMutableDictionaryRef domainCache = NULL; // mutable // Public API @@ -424,11 +424,6 @@ static const CFRuntimeClass __CFPreferencesDomainClass = { __CFPreferencesDomainCopyDescription }; -/* This is called once at CFInitialize() time. */ -CF_PRIVATE void __CFPreferencesDomainInitialize(void) { - __kCFPreferencesDomainTypeID = _CFRuntimeRegisterClass(&__CFPreferencesDomainClass); -} - /* We spend a lot of time constructing these prefixes; we should cache. REW, 7/19/99 */ static CFStringRef _CFPreferencesCachePrefixForUserHost(CFStringRef userName, CFStringRef hostName) { if (userName == kCFPreferencesAnyUser && hostName == kCFPreferencesAnyHost) { @@ -525,13 +520,13 @@ CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef domainName, CFS CFStringRef domainKey; Boolean shouldReleaseDomain = true; domainKey = _CFPreferencesStandardDomainCacheKey(domainName, userName, hostName); - __CFSpinLock(&domainCacheLock); + __CFLock(&domainCacheLock); if (!domainCache) { CFAllocatorRef alloc = __CFPreferencesAllocator(); domainCache = CFDictionaryCreateMutable(alloc, 0, & kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } domain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey); - __CFSpinUnlock(&domainCacheLock); + __CFUnlock(&domainCacheLock); if (!domain) { // Domain's not in the cache; load from permanent storage CFURLRef theURL = _CFPreferencesURLForStandardDomain(domainName, userName, hostName); @@ -543,7 +538,7 @@ CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef domainName, CFS } CFRelease(theURL); } - __CFSpinLock(&domainCacheLock); + __CFLock(&domainCacheLock); if (domain && domainCache) { // We've just synthesized a domain & we're about to throw it in the domain cache. The problem is that someone else might have gotten in here behind our backs, so we can't just blindly set the domain (3021920). We'll need to check to see if this happened, and compensate. CFPreferencesDomainRef checkDomain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey); @@ -559,7 +554,7 @@ CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef domainName, CFS } if(shouldReleaseDomain) CFRelease(domain); } - __CFSpinUnlock(&domainCacheLock); + __CFUnlock(&domainCacheLock); } CFRelease(domainKey); return domain; @@ -573,22 +568,22 @@ static void __CFPreferencesPerformSynchronize(const void *key, const void *value CF_PRIVATE Boolean _CFSynchronizeDomainCache(void) { Boolean result = true; - __CFSpinLock(&domainCacheLock); + __CFLock(&domainCacheLock); if (domainCache) { CFDictionaryApplyFunction(domainCache, __CFPreferencesPerformSynchronize, &result); } - __CFSpinUnlock(&domainCacheLock); + __CFUnlock(&domainCacheLock); return result; } CF_PRIVATE void _CFPreferencesPurgeDomainCache(void) { _CFSynchronizeDomainCache(); - __CFSpinLock(&domainCacheLock); + __CFLock(&domainCacheLock); if (domainCache) { CFRelease(domainCache); domainCache = NULL; } - __CFSpinUnlock(&domainCacheLock); + __CFUnlock(&domainCacheLock); } CF_PRIVATE CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { @@ -642,16 +637,16 @@ CF_PRIVATE CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFS CFRelease(suffix); // Now add any domains added in the cache; delete any that have been deleted in the cache - __CFSpinLock(&domainCacheLock); + __CFLock(&domainCacheLock); if (!domainCache) { - __CFSpinUnlock(&domainCacheLock); + __CFUnlock(&domainCacheLock); return marray; } cnt = CFDictionaryGetCount(domainCache); cachedDomainKeys = (CFStringRef *)CFAllocatorAllocate(prefAlloc, 2 * cnt * sizeof(CFStringRef), 0); cachedDomains = (CFPreferencesDomainRef *)(cachedDomainKeys + cnt); CFDictionaryGetKeysAndValues(domainCache, (const void **)cachedDomainKeys, (const void **)cachedDomains); - __CFSpinUnlock(&domainCacheLock); + __CFUnlock(&domainCacheLock); suffix = _CFPreferencesCachePrefixForUserHost(userName, hostName); suffixLen = CFStringGetLength(suffix); @@ -694,6 +689,8 @@ CF_PRIVATE CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFS // CFPreferencesDomainRef _CFPreferencesDomainCreate(CFTypeRef context, const _CFPreferencesDomainCallBacks *callBacks) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFPreferencesDomainTypeID = _CFRuntimeRegisterClass(&__CFPreferencesDomainClass); }); CFAllocatorRef alloc = __CFPreferencesAllocator(); CFPreferencesDomainRef newDomain; CFAssert(callBacks != NULL && callBacks->createDomain != NULL && callBacks->freeDomain != NULL && callBacks->fetchValue != NULL && callBacks->writeValue != NULL, __kCFLogAssertion, "Cannot create a domain with NULL callbacks"); diff --git a/CFPreferences.h b/CFPreferences.h index c572ec6..033f9e7 100644 --- a/CFPreferences.h +++ b/CFPreferences.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPreferences.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPREFERENCES__) @@ -32,6 +32,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN CF_EXPORT @@ -139,6 +140,7 @@ CFArrayRef CFPreferencesCopyKeyList(CFStringRef applicationID, CFStringRef userN CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFPREFERENCES__ */ diff --git a/CFPriv.h b/CFPriv.h index 9753c9d..9140ac8 100644 --- a/CFPriv.h +++ b/CFPriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPriv.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /* diff --git a/CFPropertyList.c b/CFPropertyList.c index d93b7e2..a4c0e85 100644 --- a/CFPropertyList.c +++ b/CFPropertyList.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPropertyList.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -598,22 +599,38 @@ static void _CFAppendXML0(CFTypeRef object, UInt32 indentation, CFMutableDataRef } else if (typeID == datetype) { // YYYY '-' MM '-' DD 'T' hh ':' mm ':' ss 'Z' int32_t y = 0, M = 0, d = 0, H = 0, m = 0, s = 0; -#if 1 - CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime((CFDateRef)object), NULL); - y = date.year; - M = date.month; - d = date.day; - H = date.hour; - m = date.minute; - s = (int32_t)date.second; -#else - CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian); - CFTimeZoneRef tz = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, CFSTR("GMT"), true); - CFCalendarSetTimeZone(calendar, tz); - CFCalendarDecomposeAbsoluteTime(calendar, CFDateGetAbsoluteTime((CFDateRef)object), (const uint8_t *)"yMdHms", &y, &M, &d, &H, &m, &s); - CFRelease(calendar); - CFRelease(tz); + CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)object); +#if 0 + // Alternative to the CFAbsoluteTimeGetGregorianDate() code which works well + struct timeval tv; + struct tm mine; + tv.tv_sec = floor(at + kCFAbsoluteTimeIntervalSince1970); + gmtime_r(&tv.tv_sec, &mine); + y = mine.tm_year + 1900; + M = mine.tm_mon + 1; + d = mine.tm_mday; + H = mine.tm_hour; + m = mine.tm_min; + s = mine.tm_sec; #endif + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(at, NULL); +#pragma GCC diagnostic pop + +#if 0 +if (date.year != y || date.month != M || date.day != d || date.hour != H || date.minute != m || (int32_t)date.second != s) { + CFLog(4, CFSTR("DATE ERROR {%d, %d, %d, %d, %d, %d} != {%d, %d, %d, %d, %d, %d}\n"), (int)date.year, (int)date.month, (int)date.day, (int)date.hour, (int)date.minute, (int32_t)date.second, y, M, d, H, m, s); +} +#endif + y = date.year; + M = date.month; + d = date.day; + H = date.hour; + m = date.minute; + s = (int32_t)date.second; + _plistAppendUTF8CString(xmlString, "<"); _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DATE_IX], DATE_TAG_LENGTH); _plistAppendUTF8CString(xmlString, ">"); @@ -1708,18 +1725,39 @@ static Boolean parseDateTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) { } CFAbsoluteTime at = 0.0; -#if 1 + +#if 0 + { // alternative to CFGregorianDateGetAbsoluteTime() below; also, cheaper than CFCalendar would be; + // clearly not thread-safe with that environment variable having to be set; + // timegm() could be used instead of mktime(), on platforms which have it + struct tm mine; + mine.tm_year = (yearIsNegative ? -year : year) - 1900; + mine.tm_mon = month - 1; + mine.tm_mday = day; + mine.tm_hour = hour; + mine.tm_min = minute; + mine.tm_sec = second; + char *tz = getenv("TZ"); + setenv("TZ", "", 1); + tzset(); + at = mktime(tm) - kCFAbsoluteTimeIntervalSince1970; + if (tz) { + setenv("TZ", tz, 1); + } else { + unsetenv("TZ"); + } + tzset(); + } +#endif + + // See Revisit the CFGregorianDate -> CFCalendar change in CFPropertyList.c + // for why we can't use CFCalendar +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" CFGregorianDate date = {yearIsNegative ? -year : year, month, day, hour, minute, second}; at = CFGregorianDateGetAbsoluteTime(date, NULL); -#else - // this doesn't work - CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian); - CFTimeZoneRef tz = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, CFSTR("GMT"), true); - CFCalendarSetTimeZone(calendar, tz); - CFCalendarComposeAbsoluteTime(calendar, &at, (const uint8_t *)"yMdHms", year, month, day, hour, minute, second); - CFRelease(calendar); - CFRelease(tz); -#endif +#pragma GCC diagnostic pop + if (pInfo->skip) { *out = NULL; } else { diff --git a/CFPropertyList.h b/CFPropertyList.h index 9b3af33..038e417 100644 --- a/CFPropertyList.h +++ b/CFPropertyList.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFPropertyList.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPROPERTYLIST__) @@ -55,10 +55,10 @@ CF_IMPLICIT_BRIDGING_DISABLED is returned in errorString. It is the caller's responsibility to release either the returned object or the error string, whichever is applicable. - This function is obsolete and will be deprecated soon. See CFPropertyListCreateWithData() for a replacement. + This function is deprecated. See CFPropertyListCreateWithData() for a replacement. */ CF_EXPORT -CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags mutabilityOption, CFStringRef *errorString); +CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags mutabilityOption, CFStringRef *errorString) CF_DEPRECATED(10_0, 10_10, 2_0, 8_0, "Use CFPropertyListCreateWithData instead."); /* Returns the XML description of the given object; propertyList must @@ -70,10 +70,10 @@ CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDa string, is returned because the bytes contain in them a description of the string encoding used. - This function is obsolete and will be deprecated soon. See CFPropertyListCreateData() for a replacement. + This function is deprecated. See CFPropertyListCreateData() for a replacement. */ CF_EXPORT -CFDataRef CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList); +CFDataRef CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList) CF_DEPRECATED(10_0, 10_10, 2_0, 8_0, "Use CFPropertyListCreateData instead."); CF_IMPLICIT_BRIDGING_ENABLED @@ -112,9 +112,9 @@ CF_IMPLICIT_BRIDGING_DISABLED * written, or 0 on error. Error messages are not currently localized, but * may be in the future, so they are not suitable for comparison. * - * This function is obsolete and will be deprecated soon. See CFPropertyListWrite() for a replacement. */ + * This function is deprecated. See CFPropertyListWrite() for a replacement. */ CF_EXPORT -CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFStringRef *errorString); +CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFStringRef *errorString) CF_DEPRECATED(10_2, 10_10, 2_0, 8_0, "Use CFPropertyListWrite instead."); /* Same as current function CFPropertyListCreateFromXMLData() @@ -127,9 +127,9 @@ CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStrea * are not currently localized, but may be in the future, so they are not * suitable for comparison. * - * This function is obsolete and will be deprecated soon. See CFPropertyListCreateWithStream() for a replacement. */ + * This function is deprecated. See CFPropertyListCreateWithStream() for a replacement. */ CF_EXPORT -CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString); +CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString) CF_DEPRECATED(10_2, 10_10, 2_0, 8_0, "Use CFPropertyListCreateWithStream instead."); CF_IMPLICIT_BRIDGING_ENABLED #endif @@ -150,7 +150,7 @@ CFPropertyListRef CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataR #if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_EMBEDDED -/* Create and return a property list with a CFReadStream input. TIf the format parameter is non-NULL, it will be set to the format of the data after parsing is complete. The options parameter is used to specify CFPropertyListMutabilityOptions. The streamLength parameter specifies the number of bytes to read from the stream. Set streamLength to 0 to read until the end of the stream is detected. If an error occurs while parsing the data, the return value will be NULL. Additionally, if an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release. If the parse succeeds, the returned value is a reference to the new property list. It is the responsibility of the caller to release this value. +/* Create and return a property list with a CFReadStream input. If the format parameter is non-NULL, it will be set to the format of the data after parsing is complete. The options parameter is used to specify CFPropertyListMutabilityOptions. The streamLength parameter specifies the number of bytes to read from the stream. Set streamLength to 0 to read until the end of the stream is detected. If an error occurs while parsing the data, the return value will be NULL. Additionally, if an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release. If the parse succeeds, the returned value is a reference to the new property list. It is the responsibility of the caller to release this value. */ CF_EXPORT CFPropertyListRef CFPropertyListCreateWithStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0); diff --git a/CFRunLoop.c b/CFRunLoop.c index e83ddbf..e87d5db 100644 --- a/CFRunLoop.c +++ b/CFRunLoop.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFRunLoop.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -54,6 +54,7 @@ #include #include #include +#include extern mach_port_t _dispatch_get_main_queue_port_4CF(void); extern void _dispatch_main_queue_callback_4CF(mach_msg_header_t *msg); #elif DEPLOYMENT_TARGET_WINDOWS @@ -324,7 +325,7 @@ typedef struct ___CFPortSet { uint16_t used; uint16_t size; HANDLE *handles; - CFSpinLock_t lock; // insert and remove must be thread safe, like the Mach calls + CFLock_t lock; // insert and remove must be thread safe, like the Mach calls } *__CFPortSet; CF_INLINE __CFPort __CFPortAllocate(void) { @@ -351,7 +352,7 @@ static void __CFPortSetFree(__CFPortSet portSet) { // Returns portBuf if ports fit in that space, else returns another ptr that must be freed static __CFPort *__CFPortSetGetPorts(__CFPortSet portSet, __CFPort *portBuf, uint32_t bufSize, uint32_t *portsUsed) { - __CFSpinLock(&(portSet->lock)); + __CFLock(&(portSet->lock)); __CFPort *result = portBuf; if (bufSize < portSet->used) result = (__CFPort *)CFAllocatorAllocate(kCFAllocatorSystemDefault, portSet->used * sizeof(HANDLE), 0); @@ -364,7 +365,7 @@ static __CFPort *__CFPortSetGetPorts(__CFPortSet portSet, __CFPort *portBuf, uin } memmove(result, portSet->handles, portSet->used * sizeof(HANDLE)); *portsUsed = portSet->used; - __CFSpinUnlock(&(portSet->lock)); + __CFUnlock(&(portSet->lock)); return result; } @@ -372,7 +373,7 @@ static kern_return_t __CFPortSetInsert(__CFPort port, __CFPortSet portSet) { if (NULL == port) { return -1; } - __CFSpinLock(&(portSet->lock)); + __CFLock(&(portSet->lock)); if (portSet->used >= portSet->size) { portSet->size += 4; portSet->handles = (HANDLE *)CFAllocatorReallocate(kCFAllocatorSystemDefault, portSet->handles, portSet->size * sizeof(HANDLE), 0); @@ -381,7 +382,7 @@ static kern_return_t __CFPortSetInsert(__CFPort port, __CFPortSet portSet) { CFLog(kCFLogLevelWarning, CFSTR("*** More than MAXIMUM_WAIT_OBJECTS (%d) ports add to a port set. The last ones will be ignored."), MAXIMUM_WAIT_OBJECTS); } portSet->handles[portSet->used++] = port; - __CFSpinUnlock(&(portSet->lock)); + __CFUnlock(&(portSet->lock)); return KERN_SUCCESS; } @@ -390,18 +391,18 @@ static kern_return_t __CFPortSetRemove(__CFPort port, __CFPortSet portSet) { if (NULL == port) { return -1; } - __CFSpinLock(&(portSet->lock)); + __CFLock(&(portSet->lock)); for (i = 0; i < portSet->used; i++) { if (portSet->handles[i] == port) { for (j = i+1; j < portSet->used; j++) { portSet->handles[j-1] = portSet->handles[j]; } portSet->used--; - __CFSpinUnlock(&(portSet->lock)); + __CFUnlock(&(portSet->lock)); return true; } } - __CFSpinUnlock(&(portSet->lock)); + __CFUnlock(&(portSet->lock)); return KERN_SUCCESS; } @@ -647,6 +648,8 @@ struct __CFRunLoop { CFMutableSetRef _modes; struct _block_item *_blocks_head; struct _block_item *_blocks_tail; + CFAbsoluteTime _runTime; + CFAbsoluteTime _sleepTime; CFTypeRef _counterpart; }; @@ -1095,14 +1098,14 @@ CF_INLINE void __CFRunLoopTimerUnlock(CFRunLoopTimerRef rlt) { pthread_mutex_unlock(&(rlt->_lock)); } -static CFSpinLock_t __CFRLTFireTSRLock = CFSpinLockInit; +static CFLock_t __CFRLTFireTSRLock = CFLockInit; CF_INLINE void __CFRunLoopTimerFireTSRLock(void) { - __CFSpinLock(&__CFRLTFireTSRLock); + __CFLock(&__CFRLTFireTSRLock); } CF_INLINE void __CFRunLoopTimerFireTSRUnlock(void) { - __CFSpinUnlock(&__CFRLTFireTSRLock); + __CFUnlock(&__CFRLTFireTSRLock); } #pragma mark - @@ -1309,12 +1312,9 @@ static const CFRuntimeClass __CFRunLoopClass = { CF_PRIVATE void __CFFinalizeRunLoop(uintptr_t data); -CF_PRIVATE void __CFRunLoopInitialize(void) { - __kCFRunLoopTypeID = _CFRuntimeRegisterClass(&__CFRunLoopClass); - __kCFRunLoopModeTypeID = _CFRuntimeRegisterClass(&__CFRunLoopModeClass); -} - CFTypeID CFRunLoopGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFRunLoopTypeID = _CFRuntimeRegisterClass(&__CFRunLoopClass); __kCFRunLoopModeTypeID = _CFRuntimeRegisterClass(&__CFRunLoopModeClass); }); return __kCFRunLoopTypeID; } @@ -1322,7 +1322,7 @@ static CFRunLoopRef __CFRunLoopCreate(pthread_t t) { CFRunLoopRef loop = NULL; CFRunLoopModeRef rlm; uint32_t size = sizeof(struct __CFRunLoop) - sizeof(CFRuntimeBase); - loop = (CFRunLoopRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, __kCFRunLoopTypeID, size, NULL); + loop = (CFRunLoopRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, CFRunLoopGetTypeID(), size, NULL); if (NULL == loop) { return NULL; } @@ -1351,7 +1351,7 @@ static CFRunLoopRef __CFRunLoopCreate(pthread_t t) { } static CFMutableDictionaryRef __CFRunLoops = NULL; -static CFSpinLock_t loopsLock = CFSpinLockInit; +static CFLock_t loopsLock = CFLockInit; // should only be called by Foundation // t==0 is a synonym for "main thread" that always works @@ -1359,9 +1359,9 @@ CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) { if (pthread_equal(t, kNilPthreadT)) { t = pthread_main_thread_np(); } - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); if (!__CFRunLoops) { - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np()); CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop); @@ -1369,20 +1369,20 @@ CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) { CFRelease(dict); } CFRelease(mainLoop); - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); } CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); if (!loop) { CFRunLoopRef newLoop = __CFRunLoopCreate(t); - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); if (!loop) { CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop); loop = newLoop; } // don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); CFRelease(newLoop); } if (pthread_equal(t, pthread_self())) { @@ -1399,12 +1399,12 @@ CFRunLoopRef _CFRunLoopGet0b(pthread_t t) { if (pthread_equal(t, kNilPthreadT)) { t = pthread_main_thread_np(); } - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); CFRunLoopRef loop = NULL; if (__CFRunLoops) { loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); } - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); return loop; } @@ -1414,13 +1414,13 @@ static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName); CF_PRIVATE void __CFFinalizeRunLoop(uintptr_t data) { CFRunLoopRef rl = NULL; if (data <= 1) { - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); if (__CFRunLoops) { rl = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(pthread_self())); if (rl) CFRetain(rl); CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self())); } - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); } else { _CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(data - 1), (void (*)(void *))__CFFinalizeRunLoop); } @@ -1448,9 +1448,9 @@ pthread_t _CFRunLoopGet1(CFRunLoopRef rl) { // should only be called by Foundation CF_EXPORT CFTypeRef _CFRunLoopGet2(CFRunLoopRef rl) { CFTypeRef ret = NULL; - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); ret = rl->_counterpart; - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); return ret; } @@ -1465,13 +1465,13 @@ void _CFRunLoopSetCurrent(CFRunLoopRef rl) { CFRunLoopRef currentLoop = CFRunLoopGetCurrent(); if (rl != currentLoop) { CFRetain(currentLoop); // avoid a deallocation of the currentLoop inside the lock - __CFSpinLock(&loopsLock); + __CFLock(&loopsLock); if (rl) { CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), rl); } else { CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self())); } - __CFSpinUnlock(&loopsLock); + __CFUnlock(&loopsLock); CFRelease(currentLoop); _CFSetTSD(__CFTSDKeyRunLoop, NULL, NULL); _CFSetTSD(__CFTSDKeyRunLoopCntr, 0, (void (*)(void *))__CFFinalizeRunLoop); @@ -1524,11 +1524,11 @@ static void __CFRunLoopAddItemsToCommonMode(const void *value, void *ctx) { CFTypeRef item = (CFTypeRef)value; CFRunLoopRef rl = (CFRunLoopRef)(((CFTypeRef *)ctx)[0]); CFStringRef modeName = (CFStringRef)(((CFTypeRef *)ctx)[1]); - if (CFGetTypeID(item) == __kCFRunLoopSourceTypeID) { + if (CFGetTypeID(item) == CFRunLoopSourceGetTypeID()) { CFRunLoopAddSource(rl, (CFRunLoopSourceRef)item, modeName); - } else if (CFGetTypeID(item) == __kCFRunLoopObserverTypeID) { + } else if (CFGetTypeID(item) == CFRunLoopObserverGetTypeID()) { CFRunLoopAddObserver(rl, (CFRunLoopObserverRef)item, modeName); - } else if (CFGetTypeID(item) == __kCFRunLoopTimerTypeID) { + } else if (CFGetTypeID(item) == CFRunLoopTimerGetTypeID()) { CFRunLoopAddTimer(rl, (CFRunLoopTimerRef)item, modeName); } } @@ -1537,11 +1537,11 @@ static void __CFRunLoopAddItemToCommonModes(const void *value, void *ctx) { CFStringRef modeName = (CFStringRef)value; CFRunLoopRef rl = (CFRunLoopRef)(((CFTypeRef *)ctx)[0]); CFTypeRef item = (CFTypeRef)(((CFTypeRef *)ctx)[1]); - if (CFGetTypeID(item) == __kCFRunLoopSourceTypeID) { + if (CFGetTypeID(item) == CFRunLoopSourceGetTypeID()) { CFRunLoopAddSource(rl, (CFRunLoopSourceRef)item, modeName); - } else if (CFGetTypeID(item) == __kCFRunLoopObserverTypeID) { + } else if (CFGetTypeID(item) == CFRunLoopObserverGetTypeID()) { CFRunLoopAddObserver(rl, (CFRunLoopObserverRef)item, modeName); - } else if (CFGetTypeID(item) == __kCFRunLoopTimerTypeID) { + } else if (CFGetTypeID(item) == CFRunLoopTimerGetTypeID()) { CFRunLoopAddTimer(rl, (CFRunLoopTimerRef)item, modeName); } } @@ -1550,11 +1550,11 @@ static void __CFRunLoopRemoveItemFromCommonModes(const void *value, void *ctx) { CFStringRef modeName = (CFStringRef)value; CFRunLoopRef rl = (CFRunLoopRef)(((CFTypeRef *)ctx)[0]); CFTypeRef item = (CFTypeRef)(((CFTypeRef *)ctx)[1]); - if (CFGetTypeID(item) == __kCFRunLoopSourceTypeID) { + if (CFGetTypeID(item) == CFRunLoopSourceGetTypeID()) { CFRunLoopRemoveSource(rl, (CFRunLoopSourceRef)item, modeName); - } else if (CFGetTypeID(item) == __kCFRunLoopObserverTypeID) { + } else if (CFGetTypeID(item) == CFRunLoopObserverGetTypeID()) { CFRunLoopRemoveObserver(rl, (CFRunLoopObserverRef)item, modeName); - } else if (CFGetTypeID(item) == __kCFRunLoopTimerTypeID) { + } else if (CFGetTypeID(item) == CFRunLoopTimerGetTypeID()) { CFRunLoopRemoveTimer(rl, (CFRunLoopTimerRef)item, modeName); } } @@ -1588,7 +1588,7 @@ void CFRunLoopAddCommonMode(CFRunLoopRef rl, CFStringRef modeName) { static void __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__() __attribute__((noinline)); static void __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(void *msg) { _dispatch_main_queue_callback_4CF(msg); - getpid(); // thwart tail-call optimization + asm __volatile__(""); // thwart tail-call optimization } static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() __attribute__((noinline)); @@ -1596,7 +1596,7 @@ static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(CFRunL if (func) { func(observer, activity, info); } - getpid(); // thwart tail-call optimization + asm __volatile__(""); // thwart tail-call optimization } static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__() __attribute__((noinline)); @@ -1604,7 +1604,7 @@ static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__(CFRunLoopT if (func) { func(timer, info); } - getpid(); // thwart tail-call optimization + asm __volatile__(""); // thwart tail-call optimization } static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__() __attribute__((noinline)); @@ -1612,7 +1612,7 @@ static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__(void (^block)(void)) { if (block) { block(); } - getpid(); // thwart tail-call optimization + asm __volatile__(""); // thwart tail-call optimization } static Boolean __CFRunLoopDoBlocks(CFRunLoopRef rl, CFRunLoopModeRef rlm) { // Call with rl and rlm locked @@ -1720,7 +1720,7 @@ static void __CFRunLoopCollectSources0(const void *value, void *context) { if (0 == rls->_context.version0.version && __CFIsValid(rls) && __CFRunLoopSourceIsSignaled(rls)) { if (NULL == *sources) { *sources = CFRetain(rls); - } else if (CFGetTypeID(*sources) == __kCFRunLoopSourceTypeID) { + } else if (CFGetTypeID(*sources) == CFRunLoopSourceGetTypeID()) { CFTypeRef oldrls = *sources; *sources = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); CFArrayAppendValue((CFMutableArrayRef)*sources, oldrls); @@ -1737,7 +1737,7 @@ static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__(void (*pe if (perform) { perform(info); } - getpid(); // thwart tail-call optimization + asm __volatile__(""); // thwart tail-call optimization } static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__() __attribute__((noinline)); @@ -1756,7 +1756,7 @@ static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__( perform(info); #endif } - getpid(); // thwart tail-call optimization + asm __volatile__(""); // thwart tail-call optimization } /* rl is locked, rlm is locked on entrance and exit */ @@ -1774,7 +1774,7 @@ static Boolean __CFRunLoopDoSources0(CFRunLoopRef rl, CFRunLoopModeRef rlm, Bool __CFRunLoopModeUnlock(rlm); __CFRunLoopUnlock(rl); // sources is either a single (retained) CFRunLoopSourceRef or an array of (retained) CFRunLoopSourceRef - if (CFGetTypeID(sources) == __kCFRunLoopSourceTypeID) { + if (CFGetTypeID(sources) == CFRunLoopSourceGetTypeID()) { CFRunLoopSourceRef rls = (CFRunLoopSourceRef)sources; __CFRunLoopSourceLock(rls); if (__CFRunLoopSourceIsSignaled(rls)) { @@ -2093,6 +2093,11 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo if (LLONG_MAX - intervalTSR <= oldFireTSR) { nextFireTSR = LLONG_MAX; } else { + if (intervalTSR == 0) { + // 15304159: Make sure we don't accidentally loop forever here + CRSetCrashLogMessage("A CFRunLoopTimer with an interval of 0 is set to repeat"); + HALT; + } uint64_t currentTSR = mach_absolute_time(); nextFireTSR = oldFireTSR; while (nextFireTSR <= currentTSR) { @@ -2193,7 +2198,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter #define TIMEOUT_INFINITY (~(mach_msg_timeout_t)0) -static Boolean __CFRunLoopServiceMachPort(mach_port_name_t port, mach_msg_header_t **buffer, size_t buffer_size, mach_port_t *livePort, mach_msg_timeout_t timeout) { +static Boolean __CFRunLoopServiceMachPort(mach_port_name_t port, mach_msg_header_t **buffer, size_t buffer_size, mach_port_t *livePort, mach_msg_timeout_t timeout, voucher_mach_msg_state_t *voucherState, voucher_t *voucherCopy) { Boolean originalBuffer = true; kern_return_t ret = KERN_SUCCESS; for (;;) { /* In that sleep of death what nightmares may come ... */ @@ -2204,7 +2209,25 @@ static Boolean __CFRunLoopServiceMachPort(mach_port_name_t port, mach_msg_header msg->msgh_size = buffer_size; msg->msgh_id = 0; if (TIMEOUT_INFINITY == timeout) { CFRUNLOOP_SLEEP(); } else { CFRUNLOOP_POLL(); } - ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|((TIMEOUT_INFINITY != timeout) ? MACH_RCV_TIMEOUT : 0)|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, timeout, MACH_PORT_NULL); + ret = mach_msg(msg, MACH_RCV_MSG|(voucherState ? MACH_RCV_VOUCHER : 0)|MACH_RCV_LARGE|((TIMEOUT_INFINITY != timeout) ? MACH_RCV_TIMEOUT : 0)|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, timeout, MACH_PORT_NULL); + + // Take care of all voucher-related work right after mach_msg. + // If we don't release the previous voucher we're going to leak it. + voucher_mach_msg_revert(*voucherState); + + // Someone will be responsible for calling voucher_mach_msg_revert. This call makes the received voucher the current one. + *voucherState = voucher_mach_msg_adopt(msg); + + if (voucherCopy) { + if (*voucherState != VOUCHER_MACH_MSG_STATE_UNCHANGED) { + // Caller requested a copy of the voucher at this point. By doing this right next to mach_msg we make sure that no voucher has been set in between the return of mach_msg and the use of the voucher copy. + // CFMachPortBoost uses the voucher to drop importance explicitly. However, we want to make sure we only drop importance for a new voucher (not unchanged), so we only set the TSD when the voucher is not state_unchanged. + *voucherCopy = voucher_copy(); + } else { + *voucherCopy = NULL; + } + } + CFRUNLOOP_WAKEUP(ret); if (MACH_MSG_SUCCESS == ret) { *livePort = msg ? msg->msgh_local_port : MACH_PORT_NULL; @@ -2336,7 +2359,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter seconds = 0.0; timeout_context->termTSR = 0ULL; } else if (seconds <= TIMER_INTERVAL_LIMIT) { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_OVERCOMMIT); + dispatch_queue_t queue = pthread_main_np() ? __CFDispatchQueueGetGenericMatchingMain() : __CFDispatchQueueGetGenericBackground(); timeout_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_retain(timeout_timer); timeout_context->ds = timeout_timer; @@ -2356,6 +2379,10 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter Boolean didDispatchPortLastTime = true; int32_t retVal = 0; do { +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + voucher_mach_msg_state_t voucherState = VOUCHER_MACH_MSG_STATE_UNCHANGED; + voucher_t voucherCopy = NULL; +#endif uint8_t msg_buffer[3 * 1024]; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI mach_msg_header_t *msg = NULL; @@ -2383,7 +2410,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI msg = (mach_msg_header_t *)msg_buffer; - if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0)) { + if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) { goto handle_msg; } #elif DEPLOYMENT_TARGET_WINDOWS @@ -2408,15 +2435,19 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter __CFRunLoopModeUnlock(rlm); __CFRunLoopUnlock(rl); + CFAbsoluteTime sleepStart = poll ? 0.0 : CFAbsoluteTimeGetCurrent(); + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI #if USE_DISPATCH_SOURCE_FOR_TIMERS do { if (kCFUseCollectableAllocator) { - objc_clear_stack(0); + // objc_clear_stack(0); + // memset(msg_buffer, 0, sizeof(msg_buffer)); } msg = (mach_msg_header_t *)msg_buffer; - __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY); + + __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy); if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) { // Drain the internal queue. If one of the callout blocks sets the timerFired flag, break out and service the timer. @@ -2435,11 +2466,12 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter } while (1); #else if (kCFUseCollectableAllocator) { - objc_clear_stack(0); + // objc_clear_stack(0); + // memset(msg_buffer, 0, sizeof(msg_buffer)); } msg = (mach_msg_header_t *)msg_buffer; - __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY); + __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy); #endif @@ -2451,6 +2483,8 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter __CFRunLoopLock(rl); __CFRunLoopModeLock(rlm); + rl->_sleepTime += (poll ? 0.0 : (CFAbsoluteTimeGetCurrent() - sleepStart)); + // Must remove the local-to-this-activation ports in on every loop // iteration, as this mode could be run re-entrantly and we don't // want these ports to get serviced. Also, we don't want them left @@ -2545,12 +2579,16 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter #endif __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg); _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL); - __CFRunLoopLock(rl); - __CFRunLoopModeLock(rlm); - sourceHandledThisLoop = true; + __CFRunLoopLock(rl); + __CFRunLoopModeLock(rlm); + sourceHandledThisLoop = true; didDispatchPortLastTime = true; } else { CFRUNLOOP_WAKEUP_FOR_SOURCE(); + + // If we received a voucher from this mach_msg, then put a copy of the new voucher into TSD. CFMachPortBoost will look in the TSD for the voucher. By using the value in the TSD we tie the CFMachPortBoost to this received mach_msg explicitly without a chance for anything in between the two pieces of code to set the voucher again. + voucher_t previousVoucher = _CFSetTSD(__CFTSDKeyMachMessageHasVoucher, (void *)voucherCopy, os_release); + // Despite the name, this works for windows handles as well CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, livePort); if (rls) { @@ -2565,6 +2603,10 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls) || sourceHandledThisLoop; #endif } + + // Restore the previous voucher + _CFSetTSD(__CFTSDKeyMachMessageHasVoucher, previousVoucher, os_release); + } #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg); @@ -2586,6 +2628,12 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter } else if (__CFRunLoopModeIsEmpty(rl, rlm, previousMode)) { retVal = kCFRunLoopRunFinished; } + +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + voucher_mach_msg_revert(voucherState); + os_release(voucherCopy); +#endif + } while (0 == retVal); if (timeout_timer) { @@ -3247,11 +3295,9 @@ static const CFRuntimeClass __CFRunLoopSourceClass = { __CFRunLoopSourceCopyDescription }; -CF_PRIVATE void __CFRunLoopSourceInitialize(void) { - __kCFRunLoopSourceTypeID = _CFRuntimeRegisterClass(&__CFRunLoopSourceClass); -} - CFTypeID CFRunLoopSourceGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFRunLoopSourceTypeID = _CFRuntimeRegisterClass(&__CFRunLoopSourceClass); }); return __kCFRunLoopSourceTypeID; } @@ -3262,7 +3308,7 @@ CFRunLoopSourceRef CFRunLoopSourceCreate(CFAllocatorRef allocator, CFIndex order if (NULL == context) CRASH("*** NULL context value passed to CFRunLoopSourceCreate(). (%d) ***", -1); size = sizeof(struct __CFRunLoopSource) - sizeof(CFRuntimeBase); - memory = (CFRunLoopSourceRef)_CFRuntimeCreateInstance(allocator, __kCFRunLoopSourceTypeID, size, NULL); + memory = (CFRunLoopSourceRef)_CFRuntimeCreateInstance(allocator, CFRunLoopSourceGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -3290,7 +3336,7 @@ CFRunLoopSourceRef CFRunLoopSourceCreate(CFAllocatorRef allocator, CFIndex order CFIndex CFRunLoopSourceGetOrder(CFRunLoopSourceRef rls) { CHECK_FOR_FORK(); - __CFGenericValidateType(rls, __kCFRunLoopSourceTypeID); + __CFGenericValidateType(rls, CFRunLoopSourceGetTypeID()); return rls->_order; } @@ -3322,7 +3368,7 @@ static void __CFRunLoopSourceRemoveFromRunLoop(const void *value, void *context) void CFRunLoopSourceInvalidate(CFRunLoopSourceRef rls) { CHECK_FOR_FORK(); - __CFGenericValidateType(rls, __kCFRunLoopSourceTypeID); + __CFGenericValidateType(rls, CFRunLoopSourceGetTypeID()); __CFRunLoopSourceLock(rls); CFRetain(rls); if (__CFIsValid(rls)) { @@ -3349,13 +3395,13 @@ void CFRunLoopSourceInvalidate(CFRunLoopSourceRef rls) { Boolean CFRunLoopSourceIsValid(CFRunLoopSourceRef rls) { CHECK_FOR_FORK(); - __CFGenericValidateType(rls, __kCFRunLoopSourceTypeID); + __CFGenericValidateType(rls, CFRunLoopSourceGetTypeID()); return __CFIsValid(rls); } void CFRunLoopSourceGetContext(CFRunLoopSourceRef rls, CFRunLoopSourceContext *context) { CHECK_FOR_FORK(); - __CFGenericValidateType(rls, __kCFRunLoopSourceTypeID); + __CFGenericValidateType(rls, CFRunLoopSourceGetTypeID()); CFAssert1(0 == context->version || 1 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0 or 1", __PRETTY_FUNCTION__); CFIndex size = 0; switch (context->version) { @@ -3441,11 +3487,9 @@ static const CFRuntimeClass __CFRunLoopObserverClass = { __CFRunLoopObserverCopyDescription }; -CF_PRIVATE void __CFRunLoopObserverInitialize(void) { - __kCFRunLoopObserverTypeID = _CFRuntimeRegisterClass(&__CFRunLoopObserverClass); -} - CFTypeID CFRunLoopObserverGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFRunLoopObserverTypeID = _CFRuntimeRegisterClass(&__CFRunLoopObserverClass); }); return __kCFRunLoopObserverTypeID; } @@ -3454,7 +3498,7 @@ CFRunLoopObserverRef CFRunLoopObserverCreate(CFAllocatorRef allocator, CFOptionF CFRunLoopObserverRef memory; UInt32 size; size = sizeof(struct __CFRunLoopObserver) - sizeof(CFRuntimeBase); - memory = (CFRunLoopObserverRef)_CFRuntimeCreateInstance(allocator, __kCFRunLoopObserverTypeID, size, NULL); + memory = (CFRunLoopObserverRef)_CFRuntimeCreateInstance(allocator, CFRunLoopObserverGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -3508,25 +3552,25 @@ CFRunLoopObserverRef CFRunLoopObserverCreateWithHandler(CFAllocatorRef allocator CFOptionFlags CFRunLoopObserverGetActivities(CFRunLoopObserverRef rlo) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlo, __kCFRunLoopObserverTypeID); + __CFGenericValidateType(rlo, CFRunLoopObserverGetTypeID()); return rlo->_activities; } CFIndex CFRunLoopObserverGetOrder(CFRunLoopObserverRef rlo) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlo, __kCFRunLoopObserverTypeID); + __CFGenericValidateType(rlo, CFRunLoopObserverGetTypeID()); return rlo->_order; } Boolean CFRunLoopObserverDoesRepeat(CFRunLoopObserverRef rlo) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlo, __kCFRunLoopObserverTypeID); + __CFGenericValidateType(rlo, CFRunLoopObserverGetTypeID()); return __CFRunLoopObserverRepeats(rlo); } void CFRunLoopObserverInvalidate(CFRunLoopObserverRef rlo) { /* DOES CALLOUT */ CHECK_FOR_FORK(); - __CFGenericValidateType(rlo, __kCFRunLoopObserverTypeID); + __CFGenericValidateType(rlo, CFRunLoopObserverGetTypeID()); __CFRunLoopObserverLock(rlo); CFRetain(rlo); if (__CFIsValid(rlo)) { @@ -3571,7 +3615,7 @@ Boolean CFRunLoopObserverIsValid(CFRunLoopObserverRef rlo) { void CFRunLoopObserverGetContext(CFRunLoopObserverRef rlo, CFRunLoopObserverContext *context) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlo, __kCFRunLoopObserverTypeID); + __CFGenericValidateType(rlo, CFRunLoopObserverGetTypeID()); CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__); *context = rlo->_context; } @@ -3636,20 +3680,22 @@ static const CFRuntimeClass __CFRunLoopTimerClass = { __CFRunLoopTimerCopyDescription }; -CF_PRIVATE void __CFRunLoopTimerInitialize(void) { - __kCFRunLoopTimerTypeID = _CFRuntimeRegisterClass(&__CFRunLoopTimerClass); -} - CFTypeID CFRunLoopTimerGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFRunLoopTimerTypeID = _CFRuntimeRegisterClass(&__CFRunLoopTimerClass); }); return __kCFRunLoopTimerTypeID; } CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime fireDate, CFTimeInterval interval, CFOptionFlags flags, CFIndex order, CFRunLoopTimerCallBack callout, CFRunLoopTimerContext *context) { - CHECK_FOR_FORK(); + CHECK_FOR_FORK(); + if (isnan(interval)) { + CRSetCrashLogMessage("NaN was used as an interval for a CFRunLoopTimer"); + HALT; + } CFRunLoopTimerRef memory; UInt32 size; size = sizeof(struct __CFRunLoopTimer) - sizeof(CFRuntimeBase); - memory = (CFRunLoopTimerRef)_CFRuntimeCreateInstance(allocator, __kCFRunLoopTimerTypeID, size, NULL); + memory = (CFRunLoopTimerRef)_CFRuntimeCreateInstance(allocator, CFRunLoopTimerGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -3713,8 +3759,8 @@ CFRunLoopTimerRef CFRunLoopTimerCreateWithHandler(CFAllocatorRef allocator, CFAb CFAbsoluteTime CFRunLoopTimerGetNextFireDate(CFRunLoopTimerRef rlt) { CHECK_FOR_FORK(); - CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, CFAbsoluteTime, (NSTimer *)rlt, _cffireTime); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + CF_OBJC_FUNCDISPATCHV(CFRunLoopTimerGetTypeID(), CFAbsoluteTime, (NSTimer *)rlt, _cffireTime); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); CFAbsoluteTime at = 0.0; __CFRunLoopTimerLock(rlt); __CFRunLoopTimerFireTSRLock(); @@ -3792,27 +3838,27 @@ void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDat CFTimeInterval CFRunLoopTimerGetInterval(CFRunLoopTimerRef rlt) { CHECK_FOR_FORK(); - CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, CFTimeInterval, (NSTimer *)rlt, timeInterval); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + CF_OBJC_FUNCDISPATCHV(CFRunLoopTimerGetTypeID(), CFTimeInterval, (NSTimer *)rlt, timeInterval); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); return rlt->_interval; } Boolean CFRunLoopTimerDoesRepeat(CFRunLoopTimerRef rlt) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); return (0.0 < rlt->_interval); } CFIndex CFRunLoopTimerGetOrder(CFRunLoopTimerRef rlt) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); return rlt->_order; } void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt) { /* DOES CALLOUT */ CHECK_FOR_FORK(); - CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, void, (NSTimer *)rlt, invalidate); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + CF_OBJC_FUNCDISPATCHV(CFRunLoopTimerGetTypeID(), void, (NSTimer *)rlt, invalidate); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); __CFRunLoopTimerLock(rlt); if (!__CFRunLoopTimerIsDeallocating(rlt)) { CFRetain(rlt); @@ -3862,14 +3908,14 @@ void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt) { /* DOES CALLOUT */ Boolean CFRunLoopTimerIsValid(CFRunLoopTimerRef rlt) { CHECK_FOR_FORK(); - CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, Boolean, (NSTimer *)rlt, isValid); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + CF_OBJC_FUNCDISPATCHV(CFRunLoopTimerGetTypeID(), Boolean, (NSTimer *)rlt, isValid); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); return __CFIsValid(rlt); } void CFRunLoopTimerGetContext(CFRunLoopTimerRef rlt, CFRunLoopTimerContext *context) { CHECK_FOR_FORK(); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__); *context = rlt->_context; } @@ -3877,8 +3923,8 @@ void CFRunLoopTimerGetContext(CFRunLoopTimerRef rlt, CFRunLoopTimerContext *cont CFTimeInterval CFRunLoopTimerGetTolerance(CFRunLoopTimerRef rlt) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI CHECK_FOR_FORK(); - CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, CFTimeInterval, (NSTimer *)rlt, tolerance); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + CF_OBJC_FUNCDISPATCHV(CFRunLoopTimerGetTypeID(), CFTimeInterval, (NSTimer *)rlt, tolerance); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); return rlt->_tolerance; #else return 0.0; @@ -3888,8 +3934,8 @@ CFTimeInterval CFRunLoopTimerGetTolerance(CFRunLoopTimerRef rlt) { void CFRunLoopTimerSetTolerance(CFRunLoopTimerRef rlt, CFTimeInterval tolerance) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI CHECK_FOR_FORK(); - CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, void, (NSTimer *)rlt, setTolerance:tolerance); - __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID); + CF_OBJC_FUNCDISPATCHV(CFRunLoopTimerGetTypeID(), void, (NSTimer *)rlt, setTolerance:tolerance); + __CFGenericValidateType(rlt, CFRunLoopTimerGetTypeID()); /* * dispatch rules: * diff --git a/CFRunLoop.h b/CFRunLoop.h index 855e82a..d2999b9 100644 --- a/CFRunLoop.h +++ b/CFRunLoop.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFRunLoop.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFRUNLOOP__) @@ -36,6 +36,7 @@ #include #endif +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFRunLoop * CFRunLoopRef; @@ -44,7 +45,7 @@ typedef struct __CFRunLoopSource * CFRunLoopSourceRef; typedef struct __CFRunLoopObserver * CFRunLoopObserverRef; -typedef struct __CFRunLoopTimer * CFRunLoopTimerRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSTimer) __CFRunLoopTimer * CFRunLoopTimerRef; /* Reasons for CFRunLoopRunInMode() to Return */ enum { @@ -199,6 +200,7 @@ CF_EXPORT CFTimeInterval CFRunLoopTimerGetTolerance(CFRunLoopTimerRef timer) CF_ CF_EXPORT void CFRunLoopTimerSetTolerance(CFRunLoopTimerRef timer, CFTimeInterval tolerance) CF_AVAILABLE(10_9, 7_0); CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFRUNLOOP__ */ diff --git a/CFRuntime.c b/CFRuntime.c index fe3ca57..663a9f9 100644 --- a/CFRuntime.c +++ b/CFRuntime.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFRuntime.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -34,6 +34,8 @@ #include #include #include +#include +#include #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI #include #include @@ -49,7 +51,6 @@ OBJC_EXPORT void *objc_destructInstance(id obj); #endif - #if DEPLOYMENT_TARGET_WINDOWS #include #endif @@ -198,7 +199,7 @@ static const CFRuntimeClass __CFTypeClass = { #endif //__cplusplus // the lock does not protect most reading of these; we just leak the old table to allow read-only accesses to continue to work -static CFSpinLock_t __CFBigRuntimeFunnel = CFSpinLockInit; +static CFLock_t __CFBigRuntimeFunnel = CFLockInit; CF_PRIVATE CFRuntimeClass * __CFRuntimeClassTable[__CFRuntimeClassTableSize] = {0}; CF_PRIVATE int32_t __CFRuntimeClassTableCount = 0; @@ -235,20 +236,20 @@ CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls) { CFLog(kCFLogLevelWarning, CFSTR("*** _CFRuntimeRegisterClass() given inconsistent class '%s'. Program will crash soon."), cls->className); return _kCFRuntimeNotATypeID; } - __CFSpinLock(&__CFBigRuntimeFunnel); + __CFLock(&__CFBigRuntimeFunnel); if (__CFMaxRuntimeTypes <= __CFRuntimeClassTableCount) { CFLog(kCFLogLevelWarning, CFSTR("*** CoreFoundation class table full; registration failing for class '%s'. Program will crash soon."), cls->className); - __CFSpinUnlock(&__CFBigRuntimeFunnel); + __CFUnlock(&__CFBigRuntimeFunnel); return _kCFRuntimeNotATypeID; } if (__CFRuntimeClassTableSize <= __CFRuntimeClassTableCount) { CFLog(kCFLogLevelWarning, CFSTR("*** CoreFoundation class table full; registration failing for class '%s'. Program will crash soon."), cls->className); - __CFSpinUnlock(&__CFBigRuntimeFunnel); + __CFUnlock(&__CFBigRuntimeFunnel); return _kCFRuntimeNotATypeID; } __CFRuntimeClassTable[__CFRuntimeClassTableCount++] = (CFRuntimeClass *)cls; CFTypeID typeID = __CFRuntimeClassTableCount - 1; - __CFSpinUnlock(&__CFBigRuntimeFunnel); + __CFUnlock(&__CFBigRuntimeFunnel); return typeID; } @@ -258,9 +259,9 @@ const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID) { } void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID) { - __CFSpinLock(&__CFBigRuntimeFunnel); + __CFLock(&__CFBigRuntimeFunnel); __CFRuntimeClassTable[typeID] = NULL; - __CFSpinUnlock(&__CFBigRuntimeFunnel); + __CFUnlock(&__CFBigRuntimeFunnel); } @@ -294,25 +295,30 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF if (NULL == cls) { return NULL; } + if (cls->version & _kCFRuntimeRequiresAlignment) { + allocator = kCFAllocatorSystemDefault; + } Boolean customRC = !!(cls->version & _kCFRuntimeCustomRefCount); if (customRC && !cls->refcount) { CFLog(kCFLogLevelWarning, CFSTR("*** _CFRuntimeCreateInstance() found inconsistent class '%s'."), cls->className); return NULL; } - if (customRC && kCFUseCollectableAllocator && (0 || 0)) { - CFLog(kCFLogLevelWarning, CFSTR("*** _CFRuntimeCreateInstance(): special zero-ref allocators cannot be used with class '%s' with custom ref counting."), cls->className); - return NULL; - } CFAllocatorRef realAllocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator; if (kCFAllocatorNull == realAllocator) { return NULL; } Boolean usesSystemDefaultAllocator = _CFAllocatorIsSystemDefault(realAllocator); + size_t align = (cls->version & _kCFRuntimeRequiresAlignment) ? cls->requiredAlignment : 16; CFIndex size = sizeof(CFRuntimeBase) + extraBytes + (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef)); size = (size + 0xF) & ~0xF; // CF objects are multiples of 16 in size // CFType version 0 objects are unscanned by default since they don't have write-barriers and hard retain their innards // CFType version 1 objects are scanned and use hand coded write-barriers to store collectable storage within - CFRuntimeBase *memory = (CFRuntimeBase *)CFAllocatorAllocate(allocator, size, CF_GET_COLLECTABLE_MEMORY_TYPE(cls)); + CFRuntimeBase *memory = NULL; + if (cls->version & _kCFRuntimeRequiresAlignment) { + memory = malloc_zone_memalign(malloc_default_zone(), align, size); + } else { + memory = (CFRuntimeBase *)CFAllocatorAllocate(allocator, size, CF_GET_COLLECTABLE_MEMORY_TYPE(cls)); + } if (NULL == memory) { return NULL; } @@ -421,37 +427,37 @@ enum { #define DISGUISE(O) (~(uintptr_t)(O)) static struct { - CFSpinLock_t lock; + CFLock_t lock; CFBasicHashRef table; - uint8_t padding[64 - sizeof(CFBasicHashRef) - sizeof(CFSpinLock_t)]; +// uint8_t padding[64 - sizeof(CFBasicHashRef) - sizeof(CFLock_t)]; } __NSRetainCounters[NUM_EXTERN_TABLES]; CF_EXPORT uintptr_t __CFDoExternRefOperation(uintptr_t op, id obj) { if (nil == obj) HALT; uintptr_t idx = EXTERN_TABLE_IDX(obj); uintptr_t disguised = DISGUISE(obj); - CFSpinLock_t *lock = &__NSRetainCounters[idx].lock; + CFLock_t *lock = &__NSRetainCounters[idx].lock; CFBasicHashRef table = __NSRetainCounters[idx].table; uintptr_t count; switch (op) { case 300: // increment case 350: // increment, no event - __CFSpinLock(lock); + __CFLock(lock); CFBasicHashAddValue(table, disguised, disguised); - __CFSpinUnlock(lock); + __CFUnlock(lock); if (__CFOASafe && op != 350) __CFRecordAllocationEvent(__kCFObjectRetainedEvent, obj, 0, 0, NULL); return (uintptr_t)obj; case 400: // decrement if (__CFOASafe) __CFRecordAllocationEvent(__kCFObjectReleasedEvent, obj, 0, 0, NULL); case 450: // decrement, no event - __CFSpinLock(lock); + __CFLock(lock); count = (uintptr_t)CFBasicHashRemoveValue(table, disguised); - __CFSpinUnlock(lock); + __CFUnlock(lock); return 0 == count; case 500: - __CFSpinLock(lock); + __CFLock(lock); count = (uintptr_t)CFBasicHashGetCountOfKey(table, disguised); - __CFSpinUnlock(lock); + __CFUnlock(lock); return count; } return 0; @@ -621,7 +627,7 @@ CF_PRIVATE void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void * } #if !__LP64__ -static CFSpinLock_t __CFRuntimeExternRefCountTableLock = CFSpinLockInit; +static CFLock_t __CFRuntimeExternRefCountTableLock = CFLockInit; #endif static uint64_t __CFGetFullRetainCount(CFTypeRef cf) { @@ -744,34 +750,18 @@ CFAllocatorRef CFGetAllocator(CFTypeRef cf) { return __CFGetAllocator(cf); } -extern void __CFNullInitialize(void); + +extern CFTypeID CFBinaryHeapGetTypeID(); +extern CFTypeID CFBitVectorGetTypeID(); +extern CFTypeID CFTreeGetTypeID(); +extern CFTypeID CFPlugInInstanceGetTypeID(); +extern CFTypeID CFStringTokenizerGetTypeID(); +extern CFTypeID CFStorageGetTypeID(void); extern void __CFAllocatorInitialize(void); extern void __CFStringInitialize(void); -extern void __CFArrayInitialize(void); -extern void __CFBooleanInitialize(void); extern void __CFCharacterSetInitialize(void); -extern void __CFDataInitialize(void); -extern void __CFNumberInitialize(void); -extern void __CFStorageInitialize(void); -extern void __CFErrorInitialize(void); -extern void __CFTreeInitialize(void); -extern void __CFURLInitialize(void); -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -extern void __CFMachPortInitialize(void); -#endif -extern void __CFMessagePortInitialize(void); -extern void __CFRunLoopInitialize(void); -extern void __CFRunLoopObserverInitialize(void); -extern void __CFRunLoopSourceInitialize(void); -extern void __CFRunLoopTimerInitialize(void); extern void __CFPFactoryInitialize(void); -extern void __CFBundleInitialize(void); extern void __CFPlugInInitialize(void); -extern void __CFPlugInInstanceInitialize(void); -extern void __CFUUIDInitialize(void); -extern void __CFBinaryHeapInitialize(void); -extern void __CFBitVectorInitialize(void); -CF_PRIVATE void __CFDateInitialize(void); #if DEPLOYMENT_TARGET_LINUX CF_PRIVATE void __CFTSDLinuxInitialize(); #endif @@ -782,12 +772,6 @@ CF_PRIVATE void __CFTSDWindowsCleanup(void); CF_PRIVATE void __CFFinalizeWindowsThreadData(); #endif extern void __CFStreamInitialize(void); -extern void __CFCalendarInitialize(); -extern void __CFTimeZoneInitialize(); -#if DEPLOYMENT_TARGET_LINUX -extern void __CFCalendarInitialize(); -extern void __CFTimeZoneInitialize(); -#endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS extern void __CFXPreferencesInitialize(void); #endif @@ -862,8 +846,6 @@ static struct { {"CFStringDisableROM", NULL}, {"CF_CHARSET_PATH", NULL}, {"__CF_USER_TEXT_ENCODING", NULL}, - {"__CFPREFERENCES_AUTOSYNC_INTERVAL", NULL}, - {"__CFPREFERENCES_LOG_FAILURES", NULL}, {"CFNumberDisableCache", NULL}, {"__CFPREFERENCES_AVOID_DAEMON", NULL}, {"APPLE_FRAMEWORKS_ROOT", NULL}, @@ -991,7 +973,7 @@ void __CFInitialize(void) { CFBasicHashCallbacks callbacks = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; __NSRetainCounters[idx].table = CFBasicHashCreate(kCFAllocatorSystemDefault, kCFBasicHashHasCounts | kCFBasicHashLinearHashing | kCFBasicHashAggressiveGrowth, &callbacks); CFBasicHashSetCapacity(__NSRetainCounters[idx].table, 40); - __NSRetainCounters[idx].lock = CFSpinLockInit; + __NSRetainCounters[idx].lock = CFLockInit; } /*** _CFRuntimeCreateInstance() can finally be called generally after this line. ***/ @@ -1000,58 +982,58 @@ void __CFInitialize(void) { __CFStringInitialize(); // CFString's TypeID must be 0x7, now and forever __CFRuntimeClassTableCount = 16; - __CFNullInitialize(); // See above for hard-coding of this position + CFNullGetTypeID(); // See above for hard-coding of this position CFSetGetTypeID(); // See above for hard-coding of this position CFDictionaryGetTypeID(); // See above for hard-coding of this position - __CFArrayInitialize(); // See above for hard-coding of this position - __CFDataInitialize(); // See above for hard-coding of this position - __CFBooleanInitialize(); // See above for hard-coding of this position - __CFNumberInitialize(); // See above for hard-coding of this position + CFArrayGetTypeID(); // See above for hard-coding of this position + CFDataGetTypeID(); // See above for hard-coding of this position + CFBooleanGetTypeID(); // See above for hard-coding of this position + CFNumberGetTypeID(); // See above for hard-coding of this position - __CFBinaryHeapInitialize(); - __CFBitVectorInitialize(); + CFBinaryHeapGetTypeID(); + CFBitVectorGetTypeID(); __CFCharacterSetInitialize(); - __CFStorageInitialize(); - __CFErrorInitialize(); - __CFTreeInitialize(); - __CFURLInitialize(); + CFStorageGetTypeID(); + CFErrorGetTypeID(); + CFTreeGetTypeID(); + CFURLGetTypeID(); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS - __CFBundleInitialize(); + CFBundleGetTypeID(); __CFPFactoryInitialize(); #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED __CFPlugInInitialize(); - __CFPlugInInstanceInitialize(); + CFPlugInInstanceGetTypeID(); #endif - __CFUUIDInitialize(); + CFUUIDGetTypeID(); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS - __CFMessagePortInitialize(); + CFMessagePortGetTypeID(); #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - __CFMachPortInitialize(); + CFMachPortGetTypeID(); #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS __CFStreamInitialize(); #endif #if DEPLOYMENT_TARGET_WINDOWS - __CFWindowsNamedPipeInitialize(); + CFWindowsNamedPipeGetTypeID(); #endif - __CFDateInitialize(); + CFDateGetTypeID(); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS - __CFRunLoopInitialize(); - __CFRunLoopObserverInitialize(); - __CFRunLoopSourceInitialize(); - __CFRunLoopTimerInitialize(); + CFRunLoopGetTypeID(); + CFRunLoopObserverGetTypeID(); + CFRunLoopSourceGetTypeID(); + CFRunLoopTimerGetTypeID(); #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX - __CFTimeZoneInitialize(); - __CFCalendarInitialize(); + CFTimeZoneGetTypeID(); + CFCalendarGetTypeID(); #if DEPLOYMENT_TARGET_LINUX - __CFTimeZoneInitialize(); - __CFCalendarInitialize(); + CFTimeZoneGetTypeID(); + CFCalendarGetTypeID(); #endif #endif @@ -1205,11 +1187,13 @@ int DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) { #define RC_MASK (0xFFFFFFFFULL) #define RC_GET(V) ((V) & RC_MASK) #define RC_DEALLOCATING_BIT (0x400000ULL << 32) +#define RC_DEALLOCATED_BIT (0x200000ULL << 32) #else #define RC_INCREMENT (1ULL << 32) #define RC_MASK (0xFFFFFFFFULL << 32) #define RC_GET(V) (((V) & RC_MASK) >> 32) #define RC_DEALLOCATING_BIT (0x400000ULL) +#define RC_DEALLOCATED_BIT (0x200000ULL) #endif #if !DEPLOYMENT_TARGET_WINDOWS && __LP64__ @@ -1239,6 +1223,7 @@ static CFTypeRef _CFRetain(CFTypeRef cf, Boolean tryR) { } Boolean didAuto = false; + if (tryR && (cfinfo & (0x400000 | 0x200000))) return NULL; // deallocating or deallocated #if __LP64__ if (0 == ((CFRuntimeBase *)cf)->_rc && !CF_IS_COLLECTABLE(cf)) return cf; // Constant CFTypeRef #if !DEPLOYMENT_TARGET_WINDOWS @@ -1266,9 +1251,9 @@ static CFTypeRef _CFRetain(CFTypeRef cf, Boolean tryR) { #else #define RC_START 24 #define RC_END 31 - volatile uint32_t *infoLocation = (uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo); CFIndex rcLowBits = __CFBitfieldGetValue(cfinfo, RC_END, RC_START); if (__builtin_expect(0 == rcLowBits, 0) && !CF_IS_COLLECTABLE(cf)) return cf; // Constant CFTypeRef + volatile uint32_t *infoLocation = (uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo); bool success = 0; do { cfinfo = *infoLocation; @@ -1290,12 +1275,12 @@ static CFTypeRef _CFRetain(CFTypeRef cf, Boolean tryR) { */ prospectiveNewInfo = cfinfo; __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, ((1 << 7) | (1 << 6))); - __CFSpinLock(&__CFRuntimeExternRefCountTableLock); + __CFLock(&__CFRuntimeExternRefCountTableLock); success = CAS32(*(int32_t *)& cfinfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation); if (__builtin_expect(success, 1)) { __CFDoExternRefOperation(350, (id)cf); } - __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock); + __CFUnlock(&__CFRuntimeExternRefCountTableLock); } else { success = CAS32(*(int32_t *)& cfinfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation); // XXX_PCB: 0 --> 1 transition? then add a GC retain count, to root the object. we'll remove it on the 1 --> 0 transition. @@ -1336,6 +1321,7 @@ Boolean _CFIsDeallocating(CFTypeRef cf) { static void _CFRelease(CFTypeRef cf) { uint32_t cfinfo = *(uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo); + if (cfinfo & 0x200000) return; // deallocated, or not a cf object CFTypeID typeID = (cfinfo >> 8) & 0x03FF; // mask up to 0x0FFF if (cfinfo & 0x800000) { // custom ref counting for object CFRuntimeClass *cfClass = __CFRuntimeClassTable[typeID]; @@ -1377,14 +1363,17 @@ static void _CFRelease(CFTypeRef cf) { if (!CAS64(allBits, newAllBits, (int64_t *)&((CFRuntimeBase *)cf)->_cfinfo)) { goto again; } - allBits = newAllBits; void (*func)(CFTypeRef) = __CFRuntimeClassTable[typeID]->finalize; if (NULL != func) { func(cf); } + // Any further ref-count changes after this point are operating on a finalized object allBits = *(uint64_t *)&(((CFRuntimeBase *)cf)->_cfinfo); lowBits = RC_GET(allBits); - if (isAllocator || ((1 == lowBits) && CAS64(allBits, allBits - RC_INCREMENT, (int64_t *)&((CFRuntimeBase *)cf)->_cfinfo))) { + if (isAllocator || (1 == lowBits)) { + do { // hammer until it takes; trying to retain the object on another thread at this point? too late! + allBits = *(uint64_t *)&(((CFRuntimeBase *)cf)->_cfinfo); + } while (!CAS64(allBits, (allBits | RC_DEALLOCATED_BIT) - RC_INCREMENT, (int64_t *)&((CFRuntimeBase *)cf)->_cfinfo)); goto really_free; } Boolean success = false; @@ -1438,7 +1427,7 @@ static void _CFRelease(CFTypeRef cf) { again:; volatile uint32_t *infoLocation = (uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo); CFIndex rcLowBits = __CFBitfieldGetValue(cfinfo, RC_END, RC_START); - if (__builtin_expect(0 == rcLowBits, 0)) { + if (0 == rcLowBits) { if (CF_IS_COLLECTABLE(cf)) auto_zone_release(objc_collectableZone(), (void*)cf); return; // Constant CFTypeRef } @@ -1447,7 +1436,7 @@ static void _CFRelease(CFTypeRef cf) { do { cfinfo = *infoLocation; rcLowBits = __CFBitfieldGetValue(cfinfo, RC_END, RC_START); - if (__builtin_expect(1 == rcLowBits, 0)) { + if (1 == rcLowBits) { // we think cf should be deallocated uint32_t prospectiveNewInfo = cfinfo | (0x400000); if (CF_IS_COLLECTABLE(cf)) { @@ -1458,9 +1447,9 @@ static void _CFRelease(CFTypeRef cf) { } else { // not yet junk uint32_t prospectiveNewInfo = cfinfo; // don't want compiler to generate prospectiveNewInfo = *infoLocation. This is why infoLocation is declared as a pointer to volatile memory. - if (__builtin_expect((1 << 7) == rcLowBits, 0)) { + if ((1 << 7) == rcLowBits) { // Time to remove a bit from the external ref count - __CFSpinLock(&__CFRuntimeExternRefCountTableLock); + __CFLock(&__CFRuntimeExternRefCountTableLock); CFIndex rcHighBitsCnt = __CFDoExternRefOperation(500, (id)cf); if (1 == rcHighBitsCnt) { __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, (1 << 6) - 1); @@ -1468,16 +1457,16 @@ static void _CFRelease(CFTypeRef cf) { __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, ((1 << 6) | (1 << 7)) - 1); } success = CAS32(*(int32_t *)& cfinfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation); - if (__builtin_expect(success, 1)) { + if (success) { __CFDoExternRefOperation(450, (id)cf); } - __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock); + __CFUnlock(&__CFRuntimeExternRefCountTableLock); } else { prospectiveNewInfo -= (1 << RC_START); success = CAS32(*(int32_t *)& cfinfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation); } } - } while (__builtin_expect(!success, 0)); + } while (!success); if (whack) { CFRuntimeClass *cfClass = __CFRuntimeClassTable[typeID]; @@ -1496,8 +1485,12 @@ static void _CFRelease(CFTypeRef cf) { if (NULL != func) { func(cf); } + // Any further ref-count changes after this point are operating on a finalized object rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START); if (1 == rcLowBits) { + do { // hammer until it takes; trying to retain the object on another thread at this point? too late! + cfinfo = *infoLocation; + } while (!CAS32(cfinfo, cfinfo | 0x200000, (int32_t *)infoLocation)); goto really_free; } do { // drop the deallocating bit; racey, but this resurrection stuff isn't thread-safe anyway @@ -1512,7 +1505,7 @@ static void _CFRelease(CFTypeRef cf) { #else volatile uint32_t *infoLocation = (uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo); CFIndex rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START); - if (__builtin_expect(0 == rcLowBits, 0)) { + if (0 == rcLowBits) { if (CF_IS_COLLECTABLE(cf)) auto_zone_release(objc_collectableZone(), (void*)cf); return; // Constant CFTypeRef } @@ -1520,7 +1513,7 @@ static void _CFRelease(CFTypeRef cf) { do { uint32_t initialCheckInfo = *infoLocation; rcLowBits = __CFBitfieldGetValue(initialCheckInfo, RC_END, RC_START); - if (__builtin_expect(1 == rcLowBits, 0)) { + if (1 == rcLowBits) { // we think cf should be deallocated // CANNOT WRITE ANY NEW VALUE INTO [CF_RC_BITS] UNTIL AFTER FINALIZATION CFRuntimeClass *cfClass = __CFRuntimeClassTable[typeID]; @@ -1551,7 +1544,7 @@ static void _CFRelease(CFTypeRef cf) { // which (that thread) would be the thing doing the extra retain in that case. rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START); success = (1 == rcLowBits); - if (__builtin_expect(success, 1)) { + if (success) { goto really_free; } } @@ -1559,9 +1552,9 @@ static void _CFRelease(CFTypeRef cf) { } else { // not yet junk uint32_t prospectiveNewInfo = initialCheckInfo; // don't want compiler to generate prospectiveNewInfo = *infoLocation. This is why infoLocation is declared as a pointer to volatile memory. - if (__builtin_expect((1 << 7) == rcLowBits, 0)) { + if ((1 << 7) == rcLowBits) { // Time to remove a bit from the external ref count - __CFSpinLock(&__CFRuntimeExternRefCountTableLock); + __CFLock(&__CFRuntimeExternRefCountTableLock); CFIndex rcHighBitsCnt = __CFDoExternRefOperation(500, (id)cf); if (1 == rcHighBitsCnt) { __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, (1 << 6) - 1); @@ -1569,16 +1562,16 @@ static void _CFRelease(CFTypeRef cf) { __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, ((1 << 6) | (1 << 7)) - 1); } success = CAS32(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation); - if (__builtin_expect(success, 1)) { + if (success) { __CFDoExternRefOperation(450, (id)cf); } - __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock); + __CFUnlock(&__CFRuntimeExternRefCountTableLock); } else { prospectiveNewInfo -= (1 << RC_START); success = CAS32(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation); } } - } while (__builtin_expect(!success, 0)); + } while (!success); #endif #endif if (!didAuto && __builtin_expect(__CFOASafe, 0)) { diff --git a/CFRuntime.h b/CFRuntime.h index ae0a800..b67e44e 100644 --- a/CFRuntime.h +++ b/CFRuntime.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFRuntime.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFRUNTIME__) @@ -81,6 +81,7 @@ enum { // Version field constants _kCFRuntimeScannedObject = (1UL << 0), _kCFRuntimeResourcefulObject = (1UL << 2), // tells CFRuntime to make use of the reclaim field _kCFRuntimeCustomRefCount = (1UL << 3), // tells CFRuntime to make use of the refcount field + _kCFRuntimeRequiresAlignment = (1UL << 4), // tells CFRuntime to make use of the requiredAlignment field }; typedef struct __CFRuntimeClass { @@ -95,10 +96,10 @@ typedef struct __CFRuntimeClass { CFStringRef (*copyDebugDesc)(CFTypeRef cf); // return str with retain #define CF_RECLAIM_AVAILABLE 1 - void (*reclaim)(CFTypeRef cf); // Set _kCFRuntimeResourcefulObject in the .version to indicate this field should be used + void (*reclaim)(CFTypeRef cf); // Or in _kCFRuntimeResourcefulObject in the .version to indicate this field should be used #define CF_REFCOUNT_AVAILABLE 1 - uint32_t (*refcount)(intptr_t op, CFTypeRef cf); // Set _kCFRuntimeCustomRefCount in the .version to indicate this field should be used + uint32_t (*refcount)(intptr_t op, CFTypeRef cf); // Or in _kCFRuntimeCustomRefCount in the .version to indicate this field should be used // this field must be non-NULL when _kCFRuntimeCustomRefCount is in the .version field // - if the callback is passed 1 in 'op' it should increment the 'cf's reference count and return 0 // - if the callback is passed 0 in 'op' it should return the 'cf's reference count, up to 32 bits @@ -108,6 +109,11 @@ typedef struct __CFRuntimeClass { // objects should be created/initialized with a custom ref-count of 1 by the class creation functions // do not attempt to use any bits within the CFRuntimeBase for your reference count; store that in some additional field in your CF object +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#define CF_REQUIRED_ALIGNMENT_AVAILABLE 1 + uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .version field to indicate this field should be used; the allocator to _CFRuntimeCreateInstance() will be ignored in this case; if this is less than the minimum alignment the system supports, you'll get higher alignment; if this is not an alignment the system supports (e.g., most systems will only support powers of two, or if it is too high), the result (consequences) will be up to CF or the system to decide + } CFRuntimeClass; #define RADAR_5115468_FIXED 1 @@ -136,6 +142,8 @@ CF_EXPORT CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls); * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(), * and CFGetAllocator() are valid on it when the init * function if any is called. + * - copy field should always be NULL. Generic copying of CF + * objects has never been defined (and is unlikely). * - finalize field points to a function which destroys an * instance when the retain count has fallen to zero; if * this is NULL, finalization does nothing. Note that if @@ -267,117 +275,7 @@ CF_EXPORT void _CFRuntimeInitStaticInstance(void *memory, CFTypeID typeID); */ #define CF_HAS_INIT_STATIC_INSTANCE 1 -#if 0 -// ========================= EXAMPLE ========================= - -// Example: EXRange -- a "range" object, which keeps the starting -// location and length of the range. ("EX" as in "EXample"). - -// ---- API ---- - -typedef const struct __EXRange * EXRangeRef; - -CFTypeID EXRangeGetTypeID(void); - -EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length); - -uint32_t EXRangeGetLocation(EXRangeRef rangeref); -uint32_t EXRangeGetLength(EXRangeRef rangeref); - - -// ---- implementation ---- - -#include -#include - -struct __EXRange { - CFRuntimeBase _base; - uint32_t _location; - uint32_t _length; -}; - -static Boolean __EXRangeEqual(CFTypeRef cf1, CFTypeRef cf2) { - EXRangeRef rangeref1 = (EXRangeRef)cf1; - EXRangeRef rangeref2 = (EXRangeRef)cf2; - if (rangeref1->_location != rangeref2->_location) return false; - if (rangeref1->_length != rangeref2->_length) return false; - return true; -} - -static CFHashCode __EXRangeHash(CFTypeRef cf) { - EXRangeRef rangeref = (EXRangeRef)cf; - return (CFHashCode)(rangeref->_location + rangeref->_length); -} - -static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) { - EXRangeRef rangeref = (EXRangeRef)cf; - return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts, - CFSTR("[%u, %u)"), - rangeref->_location, - rangeref->_location + rangeref->_length); -} - -static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) { - EXRangeRef rangeref = (EXRangeRef)cf; - return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL, - CFSTR("{loc = %u, len = %u}"), - rangeref, - CFGetAllocator(rangeref), - rangeref->_location, - rangeref->_length); -} - -static void __EXRangeEXRangeFinalize(CFTypeRef cf) { - EXRangeRef rangeref = (EXRangeRef)cf; - // nothing to finalize -} - -static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID; - -static CFRuntimeClass _kEXRangeClass = {0}; - -/* Something external to this file is assumed to call this - * before the EXRange class is used. - */ -void __EXRangeClassInitialize(void) { - _kEXRangeClass.version = 0; - _kEXRangeClass.className = "EXRange"; - _kEXRangeClass.init = NULL; - _kEXRangeClass.copy = NULL; - _kEXRangeClass.finalize = __EXRangeEXRangeFinalize; - _kEXRangeClass.equal = __EXRangeEqual; - _kEXRangeClass.hash = __EXRangeHash; - _kEXRangeClass.copyFormattingDesc = __EXRangeCopyFormattingDesc; - _kEXRangeClass.copyDebugDesc = __EXRangeCopyDebugDesc; - _kEXRangeID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&_kEXRangeClass); -} - -CFTypeID EXRangeGetTypeID(void) { - return _kEXRangeID; -} - -EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) { - struct __EXRange *newrange; - uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase); - newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra, NULL); - if (NULL == newrange) { - return NULL; - } - newrange->_location = location; - newrange->_length = length; - return (EXRangeRef)newrange; -} - -uint32_t EXRangeGetLocation(EXRangeRef rangeref) { - return rangeref->_location; -} - -uint32_t EXRangeGetLength(EXRangeRef rangeref) { - return rangeref->_length; -} - -#endif - CF_EXTERN_C_END #endif /* ! __COREFOUNDATION_CFRUNTIME__ */ + diff --git a/CFSet.c b/CFSet.c index a5099d0..10fc87c 100644 --- a/CFSet.c +++ b/CFSet.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSet.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane Machine generated from Notes/HashingCode.template */ @@ -47,8 +47,6 @@ const CFSetKeyCallBacks kCFTypeSetKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFSetKeyCallBacks kCFCopyStringSetKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFSetValueCallBacks kCFTypeSetValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; -static const CFSetKeyCallBacks __kCFNullSetKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; -static const CFSetValueCallBacks __kCFNullSetValueCallBacks = {0, NULL, NULL, NULL, NULL}; #define CFHashRef CFDictionaryRef #define CFMutableHashRef CFMutableDictionaryRef @@ -59,14 +57,11 @@ static const CFSetValueCallBacks __kCFNullSetValueCallBacks = {0, NULL, NULL, NU #if CFSet const CFSetCallBacks kCFTypeSetCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFSetCallBacks kCFCopyStringSetCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; -static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; #define CFSetKeyCallBacks CFSetCallBacks #define CFSetValueCallBacks CFSetCallBacks #define kCFTypeSetKeyCallBacks kCFTypeSetCallBacks #define kCFTypeSetValueCallBacks kCFTypeSetCallBacks -#define __kCFNullSetKeyCallBacks __kCFNullSetCallBacks -#define __kCFNullSetValueCallBacks __kCFNullSetCallBacks #define CFHashRef CFSetRef #define CFMutableHashRef CFMutableSetRef @@ -77,14 +72,11 @@ static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL, #if CFBag const CFSetCallBacks kCFTypeSetCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; const CFSetCallBacks kCFCopyStringSetCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash}; -static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; #define CFSetKeyCallBacks CFSetCallBacks #define CFSetValueCallBacks CFSetCallBacks #define kCFTypeSetKeyCallBacks kCFTypeSetCallBacks #define kCFTypeSetValueCallBacks kCFTypeSetCallBacks -#define __kCFNullSetKeyCallBacks __kCFNullSetCallBacks -#define __kCFNullSetValueCallBacks __kCFNullSetCallBacks #define CFHashRef CFBagRef #define CFMutableHashRef CFMutableBagRef @@ -128,7 +120,8 @@ static const CFRuntimeClass __CFSetClass = { }; CFTypeID CFSetGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFSetTypeID) __kCFSetTypeID = _CFRuntimeRegisterClass(&__CFSetClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFSetTypeID = _CFRuntimeRegisterClass(&__CFSetClass); }); return __kCFSetTypeID; } @@ -368,9 +361,13 @@ CFMutableHashRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capaci } CFIndex CFSetGetCount(CFHashRef hc) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, count); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSSet *)hc, count); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSDictionary *)hc, count); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSSet *)hc, count); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); return CFBasicHashGetCount((CFBasicHashRef)hc); } @@ -380,9 +377,13 @@ CFIndex CFSetGetCountOfKey(CFHashRef hc, const_any_pointer_t key) { #if CFSet || CFBag CFIndex CFSetGetCountOfValue(CFHashRef hc, const_any_pointer_t key) { #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSDictionary *)hc, countForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSSet *)hc, countForObject:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key); } @@ -392,24 +393,36 @@ Boolean CFSetContainsKey(CFHashRef hc, const_any_pointer_t key) { #if CFSet || CFBag Boolean CFSetContainsValue(CFHashRef hc, const_any_pointer_t key) { #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSDictionary *)hc, containsKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSSet *)hc, containsObject:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), char, (NSDictionary *)hc, containsKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), char, (NSSet *)hc, containsObject:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key)); } const_any_pointer_t CFSetGetValue(CFHashRef hc, const_any_pointer_t key) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), const_any_pointer_t, (NSSet *)hc, member:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0); } Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); if (0 < bkt.count) { if (value) { @@ -426,19 +439,19 @@ Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_ #if CFDictionary CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) { - CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value); - __CFGenericValidateType(hc, __kCFSetTypeID); + CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), CFIndex, (NSDictionary *)hc, countForObject:(id)value); + __CFGenericValidateType(hc, CFSetGetTypeID()); return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value); } Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) { - CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSDictionary *)hc, containsObject:(id)value); - __CFGenericValidateType(hc, __kCFSetTypeID); + CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), char, (NSDictionary *)hc, containsObject:(id)value); + __CFGenericValidateType(hc, CFSetGetTypeID()); return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value)); } CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) { - __CFGenericValidateType(hc, __kCFSetTypeID); + __CFGenericValidateType(hc, CFSetGetTypeID()); CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key); if (0 < bkt.count) { if (actualkey) { @@ -461,9 +474,13 @@ void CFSetGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_ void CFSetGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { const_any_pointer_t *valuebuf = 0; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSSet *)hc, getObjects:(id *)keybuf); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); if (kCFUseCollectableAllocator) { CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc); __block const_any_pointer_t *keys = keybuf; @@ -484,9 +501,13 @@ void CFSetGetValues(CFHashRef hc, const_any_pointer_t *keybuf) { void CFSetApplyFunction(CFHashRef hc, CFSetApplierFunction applier, any_pointer_t context) { FAULT_CALLBACK((void **)&(applier)); - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) { #if CFDictionary INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context); @@ -505,22 +526,22 @@ void CFSetApplyFunction(CFHashRef hc, CFSetApplierFunction applier, any_pointer_ // This function is for Foundation's benefit; no one else should use it. CF_EXPORT unsigned long _CFSetFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) { - if (CF_IS_OBJC(__kCFSetTypeID, hc)) return 0; - __CFGenericValidateType(hc, __kCFSetTypeID); + if (CF_IS_OBJC(CFSetGetTypeID(), hc)) return 0; + __CFGenericValidateType(hc, CFSetGetTypeID()); return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count); } // This function is for Foundation's benefit; no one else should use it. CF_EXPORT Boolean _CFSetIsMutable(CFHashRef hc) { - if (CF_IS_OBJC(__kCFSetTypeID, hc)) return false; - __CFGenericValidateType(hc, __kCFSetTypeID); + if (CF_IS_OBJC(CFSetGetTypeID(), hc)) return false; + __CFGenericValidateType(hc, CFSetGetTypeID()); return CFBasicHashIsMutable((CFBasicHashRef)hc); } // This function is for Foundation's benefit; no one else should use it. CF_EXPORT void _CFSetSetCapacity(CFMutableHashRef hc, CFIndex cap) { - if (CF_IS_OBJC(__kCFSetTypeID, hc)) return; - __CFGenericValidateType(hc, __kCFSetTypeID); + if (CF_IS_OBJC(CFSetGetTypeID(), hc)) return; + __CFGenericValidateType(hc, CFSetGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); CFAssert3(CFSetGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFSetGetCount(hc)); CFBasicHashSetCapacity((CFBasicHashRef)hc, cap); @@ -559,9 +580,13 @@ void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_point void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, addObject:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, addObject:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -578,9 +603,13 @@ void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_p void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, replaceObject:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -597,9 +626,13 @@ void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_point void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key) { const_any_pointer_t value = key; #endif - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, setObject:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, setObject:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -611,9 +644,13 @@ void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key) { } void CFSetRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, removeObject:(id)key); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, removeObject:(id)key); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); @@ -624,9 +661,13 @@ void CFSetRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) { } void CFSetRemoveAllValues(CFMutableHashRef hc) { - if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, removeAllObjects); - if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, removeAllObjects); - __CFGenericValidateType(hc, __kCFSetTypeID); +#if CFDictionary + if (CFDictionary) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableDictionary *)hc, removeAllObjects); +#endif +#if CFSet + if (CFSet) CF_OBJC_FUNCDISPATCHV(CFSetGetTypeID(), void, (NSMutableSet *)hc, removeAllObjects); +#endif + __CFGenericValidateType(hc, CFSetGetTypeID()); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc); diff --git a/CFSet.h b/CFSet.h index 6fede10..d4090eb 100644 --- a/CFSet.h +++ b/CFSet.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSet.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /*! @header CFSet @@ -145,13 +145,13 @@ typedef void (*CFSetApplierFunction)(const void *value, void *context); @typedef CFSetRef This is the type of a reference to immutable CFSets. */ -typedef const struct __CFSet * CFSetRef; +typedef const struct CF_BRIDGED_TYPE(NSSet) __CFSet * CFSetRef; /*! @typedef CFMutableSetRef This is the type of a reference to mutable CFSets. */ -typedef struct __CFSet * CFMutableSetRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSMutableSet) __CFSet * CFMutableSetRef; /*! @function CFSetGetTypeID diff --git a/CFSocket.c b/CFSocket.c index 44cd67c..cf64cca 100644 --- a/CFSocket.c +++ b/CFSocket.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSocket.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -210,8 +210,9 @@ static const CFRuntimeClass __CFSocketClass = { static CFMutableArrayRef __CFAllSockets = NULL; CFTypeID CFSocketGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) { - __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass); // initOnce covered __CFAllSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); struct rlimit lim1; int ret1 = getrlimit(RLIMIT_NOFILE, &lim1); @@ -227,7 +228,7 @@ CFTypeID CFSocketGetTypeID(void) { setrlimit(RLIMIT_NOFILE, &lim2); // we try, but do not go to extraordinary measures } - } + }); return __kCFSocketTypeID; } @@ -1055,9 +1056,9 @@ CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fd (2) an individual CFSocket's lock (3) __CFActiveSocketsLock */ -static CFSpinLock_t __CFAllSocketsLock = CFSpinLockInit; /* controls __CFAllSockets */ +static CFLock_t __CFAllSocketsLock = CFLockInit; /* controls __CFAllSockets */ static CFMutableDictionaryRef __CFAllSockets = NULL; -static CFSpinLock_t __CFActiveSocketsLock = CFSpinLockInit; /* controls __CFRead/WriteSockets, __CFRead/WriteSocketsFds, __CFSocketManagerThread, and __CFSocketManagerIteration */ +static CFLock_t __CFActiveSocketsLock = CFLockInit; /* controls __CFRead/WriteSockets, __CFRead/WriteSocketsFds, __CFSocketManagerThread, and __CFSocketManagerIteration */ static volatile UInt32 __CFSocketManagerIteration = 0; static CFMutableArrayRef __CFWriteSockets = NULL; static CFMutableArrayRef __CFReadSockets = NULL; @@ -1081,8 +1082,8 @@ struct __CFSocket { unsigned closeSignaled:1; // Have we seen FD_CLOSE? (only used on Win32) unsigned unused:13; } _f; - CFSpinLock_t _lock; - CFSpinLock_t _writeLock; + CFLock_t _lock; + CFLock_t _writeLock; CFSocketNativeHandle _socket; /* immutable */ SInt32 _socketType; SInt32 _errorCode; @@ -1105,6 +1106,13 @@ struct __CFSocket { int _bufferedReadError; CFMutableDataRef _leftoverBytes; + + // + // If the timeout is set on the CFSocketRef but we never get select() timeout + // because we always have some network events so select never times out (e.g. while having a large download). + // We need to notify any waiting buffered read clients if there is data available without relying on select timing out. + struct timeval _readBufferTimeoutNotificationTime; + Boolean _hitTheTimeout; }; /* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */ @@ -1162,11 +1170,11 @@ CF_INLINE void __CFSocketSetCallBackTypes(CFSocketRef s, uint8_t types) { } CF_INLINE void __CFSocketLock(CFSocketRef s) { - __CFSpinLock(&(s->_lock)); + __CFLock(&(s->_lock)); } CF_INLINE void __CFSocketUnlock(CFSocketRef s) { - __CFSpinUnlock(&(s->_lock)); + __CFUnlock(&(s->_lock)); } CF_INLINE Boolean __CFSocketIsConnectionOriented(CFSocketRef s) { @@ -1325,9 +1333,9 @@ static void __CFSocketInitializeWinSock_Guts(void) { } CF_EXPORT void __CFSocketInitializeWinSock(void) { - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); __CFSocketInitializeWinSock_Guts(); - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); } CF_PRIVATE void __CFSocketCleanup(void) { @@ -1470,6 +1478,62 @@ static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) { } } + +#if defined(LOG_CFSOCKET) + +static CFStringRef someAddrToString(CFAllocatorRef alloc, int (*fun) (int, struct sockaddr*, socklen_t*), const char* name, CFSocketNativeHandle s) +{ + CFStringRef resultString = NULL; + union { + struct sockaddr sa; + struct sockaddr_in sa4b; + struct sockaddr_in6 sa6b; + UInt8 static_buffer[SOCK_MAXADDRLEN]; + } u; + socklen_t addrlen = sizeof(u.static_buffer); + + uint16_t* pPort = NULL; + char buffer[1024]; + + if ((*fun) (s, &u.sa, &addrlen) != 0) + snprintf(buffer, sizeof(buffer), "error %d resolving %s address for socket %d", errno, name, s); + else { + void* pAddr = NULL; + + switch (u.sa.sa_family) { + case AF_INET: + pAddr = &u.sa4b.sin_addr; + pPort = &u.sa4b.sin_port; + break; + case AF_INET6: + pAddr = &u.sa6b.sin6_addr; + pPort = &u.sa6b.sin6_port; + break; + } + + if (pAddr == NULL || inet_ntop(u.sa.sa_family, pAddr, buffer, sizeof(buffer)) == NULL) + snprintf(buffer, sizeof(buffer), "[error %d converting %s address for socket %d]", pAddr != NULL? errno : EBADF, name, s); + } + if (pPort) { + resultString = CFStringCreateWithFormat(alloc, NULL, CFSTR("%s:%d"), buffer, htons(*pPort)); + } else { + resultString = CFStringCreateWithFormat(alloc, NULL, CFSTR("%s"), buffer); + } + return resultString; +} + +CFStringRef copyPeerAddress(CFAllocatorRef alloc, CFSocketNativeHandle s) +{ + return someAddrToString(alloc, getpeername, "peer", s); +} + +CFStringRef copyLocalAddress(CFAllocatorRef alloc, CFSocketNativeHandle s) +{ + return someAddrToString(alloc, getsockname, "local", s); +} + +#endif + static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) { CFDataRef data = NULL, address = NULL; @@ -1529,10 +1593,10 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) && (s->_f.client & kCFSocketDataCallBack) != 0 && (s->_f.disabled & kCFSocketDataCallBack) == 0 && __CFSocketIsScheduled(s) ) { - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); /* restore socket to fds */ __CFSocketSetFDForRead(s); - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); } } else if (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) { uint8_t name[MAX_SOCKADDR_LEN]; @@ -1567,10 +1631,10 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) if ((s->_f.client & kCFSocketAcceptCallBack) != 0 && (s->_f.disabled & kCFSocketAcceptCallBack) == 0 && __CFSocketIsScheduled(s) ) { - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); /* restore socket to fds */ __CFSocketSetFDForRead(s); - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); } } else { __CFSocketLock(s); @@ -1589,11 +1653,13 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) fprintf(stdout, "TIMEOUT - but no bytes, restoring to active set\n"); fflush(stdout); #endif + // Clear the timeout notification time if there is no prefetched data left + timerclear(&s->_readBufferTimeoutNotificationTime); - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); /* restore socket to fds */ __CFSocketSetFDForRead(s); - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); __CFSocketUnlock(s); return; } @@ -1605,10 +1671,42 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) /* if our buffer has room, we go ahead and buffer */ if (ctRemaining > 0) { base = CFDataGetMutableBytePtr(s->_readBuffer); - - do { - ctRead = read(CFSocketGetNative(s), &base[s->_bytesToBufferPos], ctRemaining); - } while (ctRead == -1 && errno == EAGAIN); + + struct timeval timeBeforeRead = { 0 }; + gettimeofday(&timeBeforeRead, NULL); + + struct timeval deadlineTime = { 0 }; + timeradd(&timeBeforeRead, &s->_readBufferTimeout, &deadlineTime); + + struct timeval timeAfterRead = { 0 }; + + while (1) { + ctRead = read(CFSocketGetNative(s), &base[s->_bytesToBufferPos], ctRemaining); + + if (ctRead >= 0) { + break; + } + + if (errno != EAGAIN) { + break; + } + + gettimeofday(&timeAfterRead, NULL); + + if (timercmp(&timeAfterRead, &deadlineTime, >)) { +#if defined(LOG_CFSOCKET) + CFSocketNativeHandle fd = CFSocketGetNative(s); + CFStringRef peerName = copyPeerAddress(kCFAllocatorDefault, fd); + CFStringRef localName = copyLocalAddress(kCFAllocatorDefault, fd); + CFLog(kCFLogLevelCritical, CFSTR("ERROR: Buffered read of %llu bytes failed for fd %d (socket valid? %d fd valid? %d %@ => %@)"), ctRemaining, fd, __CFSocketIsValid(s), __CFNativeSocketIsValid(fd), localName, peerName); + if (peerName) + CFRelease(peerName); + if (localName) + CFRelease(localName); +#endif + break; + } + } switch (ctRead) { case -1: @@ -1629,16 +1727,23 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) default: s->_bytesToBufferPos += ctRead; if (s->_bytesToBuffer != s->_bytesToBufferPos) { + + // Update the timeout notification time + struct timeval timeNow = { 0 }; + gettimeofday(&timeNow, NULL); + timeradd(&timeNow, &s->_readBufferTimeout, &s->_readBufferTimeoutNotificationTime); #if defined(LOG_CFSOCKET) fprintf(stdout, "READ %ld - need %ld MORE - GOING BACK FOR MORE\n", ctRead, s->_bytesToBuffer - s->_bytesToBufferPos); #endif - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); /* restore socket to fds */ __CFSocketSetFDForRead(s); - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); __CFSocketUnlock(s); return; } else { + // Clear the timeout notification time if the buffer is full + timerclear(&s->_readBufferTimeoutNotificationTime); #if defined(LOG_CFSOCKET) fprintf(stdout, "DONE READING (read %ld bytes) - GOING TO SIGNAL\n", ctRead); #endif @@ -1713,7 +1818,7 @@ void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, C /* lock ordering is socket lock, activesocketslock */ /* activesocketslock protects our timeout calculation */ __CFSocketLock(s); - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); if (s->_bytesToBuffer != length) { CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos; @@ -1776,7 +1881,7 @@ void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, C __CFReadSocketsTimeoutInvalid = true; } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); __CFSocketUnlock(s); } @@ -1938,7 +2043,7 @@ manageSelectError() if (EBADF == selectError) { CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); CFIndex cnt = CFArrayGetCount(__CFWriteSockets); CFIndex idx; for (idx = 0; idx < cnt; idx++) { @@ -1979,7 +2084,7 @@ manageSelectError() clearInvalidFileDescriptors(__CFWriteSocketsFds); } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); for (idx = 0; idx < cnt; idx++) { CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx))); @@ -1988,10 +2093,7 @@ manageSelectError() } } -#ifdef __GNUC__ -__attribute__ ((noreturn)) // mostly interesting for shutting up a warning -#endif /* __GNUC__ */ -static void __CFSocketManager(void * arg) +static void *__CFSocketManager(void * arg) { pthread_setname_np("com.apple.CFSocket.private"); if (objc_collectingEnabled()) objc_registerThreadWithCollector(); @@ -2011,8 +2113,8 @@ static void __CFSocketManager(void * arg) struct timeval* pTimeout = NULL; struct timeval timeBeforeSelect; - for (;;) { - __CFSpinLock(&__CFActiveSocketsLock); + for (;;) { + __CFLock(&__CFActiveSocketsLock); __CFSocketManagerIteration++; #if defined(LOG_CFSOCKET) fprintf(stdout, "socket manager iteration %lu looking at read sockets ", (unsigned long)__CFSocketManagerIteration); @@ -2065,7 +2167,7 @@ static void __CFSocketManager(void * arg) gettimeofday(&timeBeforeSelect, NULL); } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); #if DEPLOYMENT_TARGET_WINDOWS // On Windows, select checks connection failed sockets via the exceptfds parameter. connection succeeded is checked via writefds. We need both. @@ -2091,7 +2193,7 @@ static void __CFSocketManager(void * arg) fprintf(stdout, "Socket manager received timeout - kicking off expired reads (expired delta %ld, %d)\n", deltaTime.tv_sec, deltaTime.tv_usec); #endif - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); tempfds = NULL; cnt = CFArrayGetCount(__CFReadSockets); @@ -2117,7 +2219,7 @@ static void __CFSocketManager(void * arg) } } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); /* and below, we dispatch through the normal read dispatch mechanism */ } @@ -2132,7 +2234,7 @@ static void __CFSocketManager(void * arg) fprintf(stdout, "socket manager received %c on wakeup socket\n", buffer[0]); #endif } - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); tempfds = NULL; cnt = CFArrayGetCount(__CFWriteSockets); for (idx = 0; idx < cnt; idx++) { @@ -2155,6 +2257,12 @@ static void __CFSocketManager(void * arg) } tempfds = NULL; cnt = CFArrayGetCount(__CFReadSockets); + + struct timeval timeNow = { 0 }; + if (pTimeout) { + gettimeofday(&timeNow, NULL); + } + for (idx = 0; idx < cnt; idx++) { CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx); CFSocketNativeHandle sock = s->_socket; @@ -2162,7 +2270,17 @@ static void __CFSocketManager(void * arg) // in which case we must be sure not to test a bit in the fdset that is // outside our mask size. Boolean sockInBounds = (0 <= sock && sock < maxnrfds); - if (INVALID_SOCKET != sock && sockInBounds && FD_ISSET(sock, readfds)) { + + // Check if we hit the timeout + s->_hitTheTimeout = false; + if (pTimeout && sockInBounds && 0 != nrfds && !FD_ISSET(sock, readfds) && + timerisset(&s->_readBufferTimeoutNotificationTime) && + timercmp(&timeNow, &s->_readBufferTimeoutNotificationTime, >)) + { + s->_hitTheTimeout = true; + } + + if (INVALID_SOCKET != sock && sockInBounds && (FD_ISSET(sock, readfds) || s->_hitTheTimeout)) { CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s); selectedReadSocketsIndex++; /* socket is removed from fds here, will be restored in read handling or in perform function */ @@ -2170,7 +2288,7 @@ static void __CFSocketManager(void * arg) FD_CLR(sock, tempfds); } } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); for (idx = 0; idx < selectedWriteSocketsIndex; idx++) { CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedWriteSockets, idx); @@ -2189,11 +2307,12 @@ static void __CFSocketManager(void * arg) #if defined(LOG_CFSOCKET) fprintf(stdout, "socket manager signaling socket %d for read\n", s->_socket); #endif - __CFSocketHandleRead(s, nrfds == 0); + __CFSocketHandleRead(s, nrfds == 0 || s->_hitTheTimeout); CFArraySetValueAtIndex(selectedReadSockets, idx, kCFNull); } selectedReadSocketsIndex = 0; } + return NULL; } static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) { @@ -2266,8 +2385,9 @@ static const CFRuntimeClass __CFSocketClass = { }; CFTypeID CFSocketGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) { - __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ + __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass); // initOnce covered #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI struct rlimit lim1; int ret1 = getrlimit(RLIMIT_NOFILE, &lim1); @@ -2284,38 +2404,54 @@ CFTypeID CFSocketGetTypeID(void) { // we try, but do not go to extraordinary measures } #endif - } + }); return __kCFSocketTypeID; } +#if DEPLOYMENT_TARGET_WINDOWS +struct _args { + void *func; + void *arg; + HANDLE handle; +}; +static unsigned __stdcall __CFWinThreadFunc(void *arg) { + struct _args *args = (struct _args*)arg; + ((void (*)(void *))args->func)(args->arg); + CloseHandle(args->handle); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, arg); + _endthreadex(0); + return 0; +} +#endif + static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, Boolean useExistingInstance) { CHECK_FOR_FORK(); CFSocketRef memory; int typeSize = sizeof(memory->_socketType); - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); if (NULL == __CFReadSockets) __CFSocketInitializeSockets(); - __CFSpinUnlock(&__CFActiveSocketsLock); - __CFSpinLock(&__CFAllSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); + __CFLock(&__CFAllSocketsLock); if (NULL == __CFAllSockets) { __CFAllSockets = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); } if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)(uintptr_t)sock, (const void **)&memory)) { if (useExistingInstance) { - __CFSpinUnlock(&__CFAllSocketsLock); + __CFUnlock(&__CFAllSocketsLock); CFRetain(memory); return memory; } else { #if defined(LOG_CFSOCKET) fprintf(stdout, "useExistingInstance is FALSE, removing existing instance %p from __CFAllSockets\n", memory); #endif - __CFSpinUnlock(&__CFAllSocketsLock); + __CFUnlock(&__CFAllSocketsLock); CFSocketInvalidate(memory); - __CFSpinLock(&__CFAllSocketsLock); + __CFLock(&__CFAllSocketsLock); } } memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL); if (NULL == memory) { - __CFSpinUnlock(&__CFAllSocketsLock); + __CFUnlock(&__CFAllSocketsLock); return NULL; } __CFSocketSetCallBackTypes(memory, callBackTypes); @@ -2327,8 +2463,8 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN memory->_f.connected = FALSE; memory->_f.writableHint = FALSE; memory->_f.closeSignaled = FALSE; - memory->_lock = CFSpinLockInit; - memory->_writeLock = CFSpinLockInit; + memory->_lock = CFLockInit; + memory->_writeLock = CFLockInit; memory->_socket = sock; if (INVALID_SOCKET == sock || 0 != getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *)&(memory->_socketType), (socklen_t *)&typeSize)) memory->_socketType = 0; // cast for WinSock bad API memory->_errorCode = 0; @@ -2349,6 +2485,8 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN memory->_context.release = 0; memory->_context.copyDescription = 0; timerclear(&memory->_readBufferTimeout); + timerclear(&memory->_readBufferTimeoutNotificationTime); + memory->_hitTheTimeout = false; memory->_readBuffer = NULL; memory->_bytesToBuffer = 0; memory->_bytesToBufferPos = 0; @@ -2358,8 +2496,33 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN memory->_leftoverBytes = NULL; if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)(uintptr_t)sock, memory); - if (NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0); - __CFSpinUnlock(&__CFAllSocketsLock); + if (NULL == __CFSocketManagerThread) { +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD + pthread_t tid = 0; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_set_qos_class_np(&attr, qos_class_main(), 0); + pthread_create(&tid, &attr, __CFSocketManager, 0); + pthread_attr_destroy(&attr); +//warning CF: we dont actually know that a pthread_t is the same size as void * + __CFSocketManagerThread = (void *)tid; +#elif DEPLOYMENT_TARGET_WINDOWS + unsigned tid; + struct _args *args = (struct _args*)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(struct _args), 0); + if (__CFOASafe) __CFSetLastAllocationEventName(args, "CFUtilities (thread-args)"); + HANDLE handle; + args->func = __CFSocketManager; + args->arg = 0; + /* The thread is created suspended, because otherwise there would be a race between the assignment below of the handle field, and it's possible use in the thread func above. */ + args->handle = (HANDLE)_beginthreadex(NULL, 0, __CFWinThreadFunc, args, CREATE_SUSPENDED, &tid); + handle = args->handle; + ResumeThread(handle); + __CFSocketManagerThread = handle; +#endif + } + __CFUnlock(&__CFAllSocketsLock); if (NULL != context) { void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info; __CFSocketLock(memory); @@ -2388,7 +2551,7 @@ void CFSocketInvalidate(CFSocketRef s) { fprintf(stdout, "invalidating socket %d with flags 0x%x disabled 0x%x connected 0x%x\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected); #endif CFRetain(s); - __CFSpinLock(&__CFAllSocketsLock); + __CFLock(&__CFAllSocketsLock); __CFSocketLock(s); if (__CFSocketIsValid(s)) { SInt32 idx; @@ -2398,7 +2561,7 @@ void CFSocketInvalidate(CFSocketRef s) { __CFSocketUnsetValid(s); __CFSocketUnsetWriteSignalled(s); __CFSocketUnsetReadSignalled(s); - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s); if (0 <= idx) { CFArrayRemoveValueAtIndex(__CFWriteSockets, idx); @@ -2411,7 +2574,7 @@ void CFSocketInvalidate(CFSocketRef s) { __CFSocketClearFDForRead(s); } previousSocketManagerIteration = __CFSocketManagerIteration; - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); CFDictionaryRemoveValue(__CFAllSockets, (void *)(uintptr_t)(s->_socket)); if ((s->_f.client & kCFSocketCloseOnInvalidate) != 0) closesocket(s->_socket); s->_socket = INVALID_SOCKET; @@ -2460,7 +2623,7 @@ void CFSocketInvalidate(CFSocketRef s) { } else { __CFSocketUnlock(s); } - __CFSpinUnlock(&__CFAllSocketsLock); + __CFUnlock(&__CFAllSocketsLock); CFRelease(s); #if defined(LOG_CFSOCKET) CFLog(5, CFSTR("CFSocketInvalidate(%p) done"), s); @@ -2549,7 +2712,7 @@ void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) { #if defined(LOG_CFSOCKET) fprintf(stdout, "unscheduling socket %d with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected, callBackTypes); #endif - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE; if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && !s->_f.connected)) { if (__CFSocketClearFDForWrite(s)) { @@ -2565,7 +2728,7 @@ void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) { if (readCallBackType != kCFSocketReadCallBack) wakeup = true; } } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); } __CFSocketUnlock(s); } @@ -2607,7 +2770,7 @@ void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boole // Now turn on the callbacks we've determined that we want on if (turnOnRead || turnOnWrite || turnOnConnect) { - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); if (turnOnWrite || turnOnConnect) { if (force) { SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s); @@ -2623,7 +2786,7 @@ void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boole } if (__CFSocketSetFDForRead(s)) wakeup = true; } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); } } __CFSocketUnlock(s); @@ -2669,7 +2832,7 @@ static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) { __CFSocketLock(s); s->_socketSetCount--; if (0 == s->_socketSetCount) { - __CFSpinLock(&__CFActiveSocketsLock); + __CFLock(&__CFActiveSocketsLock); idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s); if (0 <= idx) { // CFLog(5, CFSTR("__CFSocketCancel: removing %p from __CFWriteSockets list"), s); @@ -2681,7 +2844,7 @@ static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) { CFArrayRemoveValueAtIndex(__CFReadSockets, idx); __CFSocketClearFDForRead(s); } - __CFSpinUnlock(&__CFActiveSocketsLock); + __CFUnlock(&__CFActiveSocketsLock); } if (NULL != s->_runLoops) { CFMutableArrayRef runLoopsOrig = s->_runLoops; @@ -2905,15 +3068,15 @@ CONST_STRING_DECL(kCFSocketRegisterCommand, "Register") CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve") CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest") -static CFSpinLock_t __CFSocketWriteLock_ = CFSpinLockInit; +static CFLock_t __CFSocketWriteLock_ = CFLockInit; //#warning can only send on one socket at a time now CF_INLINE void __CFSocketWriteLock(CFSocketRef s) { - __CFSpinLock(& __CFSocketWriteLock_); + __CFLock(& __CFSocketWriteLock_); } CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) { - __CFSpinUnlock(& __CFSocketWriteLock_); + __CFUnlock(& __CFSocketWriteLock_); } #if NEW_SOCKET @@ -3154,7 +3317,7 @@ static void __CFSocketHandleNameRegistryReply(CFSocketRef s, CFSocketCallBackTyp __CFSocketNameRegistryResponse *response = (__CFSocketNameRegistryResponse *)info; CFDictionaryRef replyDictionary = NULL; CFPropertyListRef value; - replyDictionary = (CFDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, replyData, kCFPropertyListImmutable, NULL); + replyDictionary = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorSystemDefault, replyData, kCFPropertyListImmutable, NULL, NULL); if (NULL != response->error) *(response->error) = kCFSocketError; if (NULL != replyDictionary) { if (CFGetTypeID((CFTypeRef)replyDictionary) == CFDictionaryGetTypeID() && NULL != (value = CFDictionaryGetValue(replyDictionary, kCFSocketResultKey))) { @@ -3173,7 +3336,7 @@ static void __CFSocketSendNameRegistryRequest(CFSocketSignature *signature, CFDi CFSocketRef s = NULL; CFRunLoopSourceRef source = NULL; if (NULL != response->error) *(response->error) = kCFSocketError; - requestData = CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, requestDictionary); + requestData = CFPropertyListCreateData(kCFAllocatorSystemDefault, requestDictionary, kCFPropertyListXMLFormat_v1_0, 0, NULL); if (NULL != requestData) { if (NULL != response->error) *(response->error) = kCFSocketTimeout; s = CFSocketCreateConnectedToSocketSignature(kCFAllocatorSystemDefault, signature, kCFSocketDataCallBack, __CFSocketHandleNameRegistryReply, &context, timeout); diff --git a/CFSocket.h b/CFSocket.h index c4b9346..b591711 100644 --- a/CFSocket.h +++ b/CFSocket.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSocket.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSOCKET__) @@ -31,6 +31,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFSocket * CFSocketRef; @@ -231,6 +232,7 @@ CF_EXPORT const CFStringRef kCFSocketRegisterCommand; CF_EXPORT const CFStringRef kCFSocketRetrieveCommand; CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFSOCKET__ */ diff --git a/CFSocketStream.c b/CFSocketStream.c index c9b3768..9beed39 100644 --- a/CFSocketStream.c +++ b/CFSocketStream.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSocketStream.c - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. Responsibility: Jeremy Wyld */ // Original Author: Becky Willrich @@ -101,7 +101,7 @@ enum { }; static struct { - CFSpinLock_t lock; + CFLock_t lock; UInt32 flags; #if DEPLOYMENT_TARGET_WINDOWS HMODULE image; @@ -110,7 +110,7 @@ static struct { CFErrorRef (*_CFErrorCreateWithStreamError)(CFAllocatorRef, CFStreamError*); CFStreamError (*_CFStreamErrorFromCFError)(CFErrorRef); } CFNetworkSupport = { - CFSpinLockInit, + CFLockInit, 0x0, #if DEPLOYMENT_TARGET_WINDOWS NULL, @@ -183,9 +183,9 @@ createPair(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFSocketNativeHa if (writeStream) *writeStream = NULL; - __CFSpinLock(&(CFNetworkSupport.lock)); + __CFLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); - __CFSpinUnlock(&(CFNetworkSupport.lock)); + __CFUnlock(&(CFNetworkSupport.lock)); CFNETWORK_CALL(_CFSocketStreamCreatePair, (alloc, host, port, sock, sig, readStream, writeStream)); } @@ -207,10 +207,10 @@ CF_PRIVATE CFStreamError _CFStreamErrorFromError(CFErrorRef error) { CFStreamError result; Boolean canUpCall; - __CFSpinLock(&(CFNetworkSupport.lock)); + __CFLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); canUpCall = (CFNetworkSupport._CFStreamErrorFromCFError != NULL); - __CFSpinUnlock(&(CFNetworkSupport.lock)); + __CFUnlock(&(CFNetworkSupport.lock)); if (canUpCall) { result = CFNETWORK_CALL(_CFStreamErrorFromCFError, (error)); @@ -234,10 +234,10 @@ CF_PRIVATE CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamErro CFErrorRef result; Boolean canUpCall; - __CFSpinLock(&(CFNetworkSupport.lock)); + __CFLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); canUpCall = (CFNetworkSupport._CFErrorCreateWithStreamError != NULL); - __CFSpinUnlock(&(CFNetworkSupport.lock)); + __CFUnlock(&(CFNetworkSupport.lock)); if (canUpCall) { result = CFNETWORK_CALL(_CFErrorCreateWithStreamError, (alloc, streamError)); diff --git a/CFSortFunctions.c b/CFSortFunctions.c index ed64d3c..b702a5b 100644 --- a/CFSortFunctions.c +++ b/CFSortFunctions.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSortFunctions.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -213,7 +213,7 @@ static void __CFSortIndexesN(VALUE_TYPE listp[], INDEX_TYPE count, int32_t ncore } VALUE_TYPE **tmps = stack_tmps; - dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_OVERCOMMIT); + dispatch_queue_t q = __CFDispatchQueueGetGenericMatchingCurrent(); dispatch_apply(num_sect, q, ^(size_t sect) { INDEX_TYPE sect_len = (sect < num_sect - 1) ? sz : last_sect_len; __CFSimpleMergeSort(listp + sect * sz, sect_len, tmps[sect], cmp); // naturally stable @@ -277,7 +277,7 @@ void CFSortIndexes(CFIndex *indexBuffer, CFIndex count, CFOptionFlags opts, CFCo } else { /* Specifically hard-coded to 8; the count has to be very large before more chunks and/or cores is worthwhile. */ CFIndex sz = ((((size_t)count + 15) / 16) * 16) / 8; - dispatch_apply(8, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_OVERCOMMIT), ^(size_t n) { + dispatch_apply(8, __CFDispatchQueueGetGenericMatchingCurrent(), ^(size_t n) { CFIndex idx = n * sz, lim = __CFMin(idx + sz, count); for (; idx < lim; idx++) indexBuffer[idx] = idx; }); diff --git a/CFStorage.c b/CFStorage.c index fa30231..810942f 100644 --- a/CFStorage.c +++ b/CFStorage.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStorage.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -119,7 +119,7 @@ struct __CFStorage { CFRuntimeBase base; CFIndex valueSize; uint32_t byteToValueShifter; - CFSpinLock_t cacheReaderMemoryAllocationLock; + CFLock_t cacheReaderMemoryAllocationLock; bool alwaysFrozen; CFStorageNode * volatile cacheNode; CFIndex maxLeafCapacity; // In terms of bytes @@ -150,14 +150,14 @@ CF_INLINE void __CFStorageAllocLeafNodeMemory(CFAllocatorRef allocator, CFStorag } /* We must be careful here, because another thread may be trying to allocate this memory at the same time (8203146). This may happen if two threads both attempt to read from a lazily-allocated node. */ if ((compact ? (cap != node->info.leaf.capacityInBytes) : (cap > node->info.leaf.capacityInBytes))) { - __CFSpinLock(&(storage->cacheReaderMemoryAllocationLock)); + __CFLock(&(storage->cacheReaderMemoryAllocationLock)); /* Check again now that we've acquired the lock. We know that we can do this because two simulaneous readers will always pass the same capacity. This is the fix for 8203146. This probably needs a memory barrier. */ if ((compact ? (cap != node->info.leaf.capacityInBytes) : (cap > node->info.leaf.capacityInBytes))) { __CFAssignWithWriteBarrier((void **)&node->info.leaf.memory, _CFAllocatorReallocateGC(allocator, node->info.leaf.memory, cap, storage->nodeHint)); // This will free... if (__CFOASafe) __CFSetLastAllocationEventName(node->info.leaf.memory, "CFStorage (node bytes)"); node->info.leaf.capacityInBytes = cap; } - __CFSpinUnlock(&(storage->cacheReaderMemoryAllocationLock)); + __CFUnlock(&(storage->cacheReaderMemoryAllocationLock)); } } @@ -1007,7 +1007,7 @@ static bool __CFStorageEnumerateNodesInByteRangeWithBlock(CFStorageRef storage, CFStorageNode ** childrenPtr = children; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS __block bool blockStop = false; - dispatch_apply(numChildren, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t ind) { + dispatch_apply(numChildren, __CFDispatchQueueGetGenericMatchingCurrent(), ^(size_t ind) { if (! blockStop && overlapsPtr[ind].length > 0) { if (__CFStorageEnumerateNodesInByteRangeWithBlock(storage, childrenPtr[ind], globalOffsetOfNode + offsetsPtr[ind], CFRangeMake(overlapsPtr[ind].location - offsetsPtr[ind], overlapsPtr[ind].length), concurrencyToken, applier)) { blockStop = true; @@ -1105,16 +1105,12 @@ static const CFRuntimeClass __CFStorageClass = { __CFStorageCopyDescription }; -CF_PRIVATE void __CFStorageInitialize(void) { - __kCFStorageTypeID = _CFRuntimeRegisterClass(&__CFStorageClass); -} - /*** Public API ***/ CFStorageRef CFStorageCreate(CFAllocatorRef allocator, CFIndex valueSize) { CFStorageRef storage; CFIndex size = sizeof(struct __CFStorage) - sizeof(CFRuntimeBase); - storage = (CFStorageRef)_CFRuntimeCreateInstance(allocator, __kCFStorageTypeID, size, NULL); + storage = (CFStorageRef)_CFRuntimeCreateInstance(allocator, CFStorageGetTypeID(), size, NULL); if (NULL == storage) { return NULL; } @@ -1136,7 +1132,7 @@ CFStorageRef CFStorageCreate(CFAllocatorRef allocator, CFIndex valueSize) { storage->byteToValueShifter = NO_SHIFTER; } - CF_SPINLOCK_INIT_FOR_STRUCTS(storage->cacheReaderMemoryAllocationLock); + CF_LOCK_INIT_FOR_STRUCTS(storage->cacheReaderMemoryAllocationLock); storage->maxLeafCapacity = __CFStorageMaxLeafCapacity; if (valueSize && ((storage->maxLeafCapacity % valueSize) != 0)) { storage->maxLeafCapacity = (storage->maxLeafCapacity / valueSize) * valueSize; // Make it fit perfectly (3406853) @@ -1205,6 +1201,8 @@ CFStorageRef CFStorageCreateWithSubrange(CFStorageRef mutStorage, CFRange range) } CFTypeID CFStorageGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFStorageTypeID = _CFRuntimeRegisterClass(&__CFStorageClass); }); return __kCFStorageTypeID; } diff --git a/CFStorage.h b/CFStorage.h index fb59f1d..d462ccd 100644 --- a/CFStorage.h +++ b/CFStorage.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStorage.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ /*! @header CFStorage diff --git a/CFStream.c b/CFStream.c index 960b0a3..1bc2e55 100644 --- a/CFStream.c +++ b/CFStream.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStream.c - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. Responsibility: John Iarocci */ @@ -48,7 +48,7 @@ struct _CFStream { void *info; const struct _CFStreamCallBacks *callBacks; // This will not exist (will not be allocated) if the callbacks are from our known, "blessed" set. - CFSpinLock_t streamLock; + CFLock_t streamLock; CFArrayRef previousRunloopsAndModes; dispatch_queue_t queue; }; @@ -80,7 +80,7 @@ enum { RunLoop+RunLoopMode pair that it's scheduled in. If the stream is scheduled in more than one loop or mode, it can't share RunLoopSources with others, and is not in this dict. */ -static CFSpinLock_t sSourceLock = CFSpinLockInit; +static CFLock_t sSourceLock = CFLockInit; static CFMutableDictionaryRef sSharedSources = NULL; static CFTypeID __kCFReadStreamTypeID = _kCFRuntimeNotATypeID; @@ -101,11 +101,11 @@ CF_INLINE void checkRLMArray(CFArrayRef arr) } CF_INLINE void _CFStreamLock(struct _CFStream* stream) { - __CFSpinLock(&stream->streamLock); + __CFLock(&stream->streamLock); } CF_INLINE void _CFStreamUnlock(struct _CFStream* stream) { - __CFSpinUnlock(&stream->streamLock); + __CFUnlock(&stream->streamLock); } CF_INLINE CFRunLoopSourceRef _CFStreamCopySource(struct _CFStream* stream) { @@ -185,7 +185,7 @@ CF_INLINE void _CFStreamSetStreamError(struct _CFStream *stream, CFStreamError * if (!stream->error) { stream->error = (CFErrorRef)CFAllocatorAllocate(CFGetAllocator(stream), sizeof(CFStreamError), 0); } - memmove(stream->error, err, sizeof(CFStreamError)); + memmove((void *)stream->error, err, sizeof(CFStreamError)); } static CFStringRef __CFStreamCopyDescription(CFTypeRef cf) { @@ -223,7 +223,7 @@ static void _CFStreamDetachSource(struct _CFStream* stream) { CFIndex count; CFIndex i; - __CFSpinLock(&sSourceLock); + __CFLock(&sSourceLock); runLoopAndSourceKey = (CFArrayRef)CFDictionaryGetValue(sSharedSources, stream); list = (CFMutableArrayRef)CFDictionaryGetValue(sSharedSources, runLoopAndSourceKey); @@ -252,7 +252,7 @@ static void _CFStreamDetachSource(struct _CFStream* stream) { __CFBitClear(stream->flags, SHARED_SOURCE); - __CFSpinUnlock(&sSourceLock); + __CFUnlock(&sSourceLock); } } } @@ -312,7 +312,7 @@ static void __CFStreamDeallocate(CFTypeRef cf) { } if (stream->error) { if (cb->version < 2) { - CFAllocatorDeallocate(alloc, stream->error); + CFAllocatorDeallocate(alloc, (void *)stream->error); } else { CFRelease(stream->error); } @@ -361,8 +361,8 @@ CONST_STRING_DECL(kCFStreamPropertyDataWritten, "kCFStreamPropertyDataWritten") CONST_STRING_DECL(kCFStreamPropertyAppendToFile, "kCFStreamPropertyAppendToFile") CF_PRIVATE void __CFStreamInitialize(void) { - __kCFReadStreamTypeID = _CFRuntimeRegisterClass(&__CFReadStreamClass); - __kCFWriteStreamTypeID = _CFRuntimeRegisterClass(&__CFWriteStreamClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFReadStreamTypeID = _CFRuntimeRegisterClass(&__CFReadStreamClass); __kCFWriteStreamTypeID = _CFRuntimeRegisterClass(&__CFWriteStreamClass); }); } @@ -385,7 +385,7 @@ static struct _CFStream *_CFStreamCreate(CFAllocatorRef allocator, Boolean isRea newStream->info = NULL; newStream->callBacks = NULL; - newStream->streamLock = CFSpinLockInit; + newStream->streamLock = CFLockInit; newStream->previousRunloopsAndModes = NULL; newStream->queue = NULL; } @@ -676,7 +676,7 @@ static void _cfstream_shared_signalEventSync(void* info) dispatch_queue_t queue = 0; struct _CFStream* stream = NULL; - __CFSpinLock(&sSourceLock); + __CFLock(&sSourceLock); /* Looks like, we grab the first stream that wants an event... */ /* Note that I grab an extra retain when I pull out the stream here... */ @@ -708,7 +708,7 @@ static void _cfstream_shared_signalEventSync(void* info) } } - __CFSpinUnlock(&sSourceLock); + __CFUnlock(&sSourceLock); /* We're sitting here now, possibly with a stream that needs to be processed by the common routine */ if (stream) { @@ -1359,7 +1359,7 @@ CF_EXPORT Boolean CFReadStreamSetClient(CFReadStreamRef readStream, CFOptionFlag CF_EXPORT Boolean CFWriteStreamSetClient(CFWriteStreamRef writeStream, CFOptionFlags streamEvents, CFWriteStreamClientCallBack clientCB, CFStreamClientContext *clientContext) { #if defined(CFSTREAM_SUPPORTS_BRIDGING) - if (CF_IS_OBJC(__kCFWriteStreamTypeID, (const void *)(NSInputStream *)writeStream)) { + if (CF_IS_OBJC(__kCFWriteStreamTypeID, (const void *)(NSOutputStream *)writeStream)) { NSOutputStream* os = (NSOutputStream*) writeStream; if ([os respondsToSelector:@selector(_setCFClientFlags:callback:context:)]) @@ -1408,7 +1408,7 @@ CF_PRIVATE void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, CFRunLoop CFArrayRef runLoopAndSourceKey = CFArrayCreate(kCFAllocatorSystemDefault, a, sizeof(a) / sizeof(a[0]), &kCFTypeArrayCallBacks); - __CFSpinLock(&sSourceLock); + __CFLock(&sSourceLock); if (!sSharedSources) sSharedSources = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -1456,7 +1456,7 @@ CF_PRIVATE void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, CFRunLoop __CFBitSet(stream->flags, SHARED_SOURCE); - __CFSpinUnlock(&sSourceLock); + __CFUnlock(&sSourceLock); } else if (__CFBitIsSet(stream->flags, SHARED_SOURCE)) { /* We were sharing, but now we'll get our own source */ @@ -1479,7 +1479,7 @@ CF_PRIVATE void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, CFRunLoop (void(*)(void *))_cfstream_solo_signalEventSync }; - __CFSpinLock(&sSourceLock); + __CFLock(&sSourceLock); runLoopAndSourceKey = (CFArrayRef)CFRetain((CFTypeRef)CFDictionaryGetValue(sSharedSources, stream)); listOfStreamsSharingASource = (CFMutableArrayRef)CFDictionaryGetValue(sSharedSources, runLoopAndSourceKey); @@ -1506,7 +1506,7 @@ CF_PRIVATE void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, CFRunLoop __CFBitClear(stream->flags, SHARED_SOURCE); - __CFSpinUnlock(&sSourceLock); + __CFUnlock(&sSourceLock); CFRunLoopSourceRef source = CFRunLoopSourceCreate(alloc, 0, &ctxt); _CFStreamSetSource(stream, source, FALSE); @@ -1600,7 +1600,7 @@ CF_PRIVATE void _CFStreamUnscheduleFromRunLoop(struct _CFStream *stream, CFRunLo CFMutableArrayRef list; CFIndex count, i; - __CFSpinLock(&sSourceLock); + __CFLock(&sSourceLock); runLoopAndSourceKey = (CFArrayRef)CFDictionaryGetValue(sSharedSources, stream); list = (CFMutableArrayRef)CFDictionaryGetValue(sSharedSources, runLoopAndSourceKey); @@ -1627,7 +1627,7 @@ CF_PRIVATE void _CFStreamUnscheduleFromRunLoop(struct _CFStream *stream, CFRunLo __CFBitClear(stream->flags, SHARED_SOURCE); - __CFSpinUnlock(&sSourceLock); + __CFUnlock(&sSourceLock); } _CFStreamLock(stream); @@ -1678,6 +1678,7 @@ static void _perform(void* info) static void* _legacyStreamRunLoop_workThread(void* arg) { + pthread_setname_np("com.apple.CFStream.LegacyThread"); sLegacyRL = CFRunLoopGetCurrent(); #if defined(LOG_STREAM) @@ -1744,6 +1745,7 @@ static CFRunLoopRef _legacyStreamRunLoop() pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_set_qos_class_np(&attr, qos_class_main(), 0); pthread_t workThread; (void) pthread_create(&workThread, &attr, _legacyStreamRunLoop_workThread, &sem); pthread_attr_destroy(&attr); @@ -2029,7 +2031,7 @@ CF_EXPORT CFIndex _CFStreamInstanceSize(void) { #if DEPLOYMENT_TARGET_WINDOWS void __CFStreamCleanup(void) { - __CFSpinLock(&sSourceLock); + __CFLock(&sSourceLock); if (sSharedSources) { CFIndex count = CFDictionaryGetCount(sSharedSources); if (count == 0) { @@ -2054,7 +2056,7 @@ void __CFStreamCleanup(void) { #endif } } - __CFSpinUnlock(&sSourceLock); + __CFUnlock(&sSourceLock); } #endif diff --git a/CFStream.h b/CFStream.h index 36103b4..36cdf25 100644 --- a/CFStream.h +++ b/CFStream.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStream.h - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAM__) @@ -68,8 +68,8 @@ typedef struct { CFStringRef (*copyDescription)(void *info); } CFStreamClientContext; -typedef struct __CFReadStream * CFReadStreamRef; -typedef struct __CFWriteStream * CFWriteStreamRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSInputStream) __CFReadStream * CFReadStreamRef; +typedef struct CF_BRIDGED_MUTABLE_TYPE(NSOutputStream) __CFWriteStream * CFWriteStreamRef; typedef void (*CFReadStreamClientCallBack)(CFReadStreamRef stream, CFStreamEventType type, void *clientCallBackInfo); typedef void (*CFWriteStreamClientCallBack)(CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo); diff --git a/CFStreamAbstract.h b/CFStreamAbstract.h index 1844aad..0098523 100644 --- a/CFStreamAbstract.h +++ b/CFStreamAbstract.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStreamAbstract.h - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAMABSTRACT__) diff --git a/CFStreamInternal.h b/CFStreamInternal.h index 2eeca1b..c8416c2 100644 --- a/CFStreamInternal.h +++ b/CFStreamInternal.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ diff --git a/CFStreamPriv.h b/CFStreamPriv.h index ee28125..9a779bd 100644 --- a/CFStreamPriv.h +++ b/CFStreamPriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStreamPriv.h - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAMPRIV__) diff --git a/CFString.c b/CFString.c index 8009185..af54887 100644 --- a/CFString.c +++ b/CFString.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFString.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Ali Ozer !!! For performance reasons, it's important that all functions marked CF_INLINE in this file are inlined. @@ -70,11 +70,11 @@ CF_PRIVATE const CFStringRef __kCFLocaleCollatorID; #include /* for umask() */ static void __CFRecordStringAllocationEvent(const char *encoding, const char *bytes, CFIndex byteCount) { - static CFSpinLock_t lock = CFSpinLockInit; + static CFLock_t lock = CFLockInit; if (memchr(bytes, '\n', byteCount)) return; //never record string allocation events for strings with newlines, because those confuse our parser and because they'll never go into the ROM - __CFSpinLock(&lock); + __CFLock(&lock); static int fd; if (! fd) { extern char **_NSGetProgname(void); @@ -99,12 +99,10 @@ static void __CFRecordStringAllocationEvent(const char *encoding, const char *by else puts("Couldn't record allocation event"); free(buffer); } - __CFSpinUnlock(&lock); + __CFUnlock(&lock); } #endif //INSTRUMENT_SHARED_STRINGS - - typedef Boolean (*UNI_CHAR_FUNC)(UInt32 flags, UInt8 ch, UniChar *unicodeChar); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI @@ -112,7 +110,7 @@ extern size_t malloc_good_size(size_t size); #endif extern void __CFStrConvertBytesToUnicode(const uint8_t *bytes, UniChar *buffer, CFIndex numChars); -static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFDictionaryRef stringsDictConfig, CFStringRef formatString, CFIndex initialArgPosition, const void *origValues, CFIndex originalValuesSize, va_list args); +static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions, CFDictionaryRef stringsDictConfig, CFStringRef formatString, CFIndex initialArgPosition, const void *origValues, CFIndex originalValuesSize, va_list args); #if defined(DEBUG) @@ -134,6 +132,7 @@ void _CFStringSetCompatibility(CFOptionFlags mask) { _CFStringCompatibilityMask |= mask; } +__attribute__((used)) CF_INLINE Boolean __CFStringGetCompatibility(CFOptionFlags mask) { return (_CFStringCompatibilityMask & mask) == mask; } @@ -264,7 +263,7 @@ CF_INLINE Boolean __CFStrIsConstant(CFStringRef str) { CF_INLINE SInt32 __CFStrSkipAnyLengthByte(CFStringRef str) {return ((str->base._cfinfo[CF_INFO_BITS] & __kCFHasLengthByteMask) == __kCFHasLengthByte) ? 1 : 0;} // Number of bytes to skip over the length byte in the contents -/* Returns ptr to the buffer (which might include the length byte) +/* Returns ptr to the buffer (which might include the length byte). */ CF_INLINE const void *__CFStrContents(CFStringRef str) { if (__CFStrIsInline(str)) { @@ -364,7 +363,7 @@ CF_INLINE Boolean __CFStrIsExternalMutable(CFStringRef str) {return str->variant CF_INLINE Boolean __CFStrHasContentsAllocator(CFStringRef str) {return (str->base._cfinfo[CF_INFO_BITS] & __kCFHasContentsAllocatorMask) == __kCFHasContentsAllocator;} CF_INLINE void __CFStrSetIsFixed(CFMutableStringRef str) {str->variants.notInlineMutable.isFixedCapacity = 1;} CF_INLINE void __CFStrSetIsExternalMutable(CFMutableStringRef str) {str->variants.notInlineMutable.isExternalMutable = 1;} -CF_INLINE void __CFStrSetHasGap(CFMutableStringRef str) {str->variants.notInlineMutable.hasGap = 1;} +//CF_INLINE void __CFStrSetHasGap(CFMutableStringRef str) {str->variants.notInlineMutable.hasGap = 1;} currently unused // If capacity is provided externally, we only change it when we need to grow beyond it CF_INLINE Boolean __CFStrCapacityProvidedExternally(CFStringRef str) {return str->variants.notInlineMutable.capacityProvidedExternally;} @@ -1113,6 +1112,11 @@ CF_INLINE CFHashCode __CFStrHashEightBit(const uint8_t *cContents, CFIndex len) return result + (result << (len & 31)); } +// This is for NSStringROMKeySet. +CF_PRIVATE CFHashCode __CFStrHashEightBit2(const uint8_t *cContents, CFIndex len) { + return __CFStrHashEightBit(cContents, len); +} + CFHashCode CFStringHashISOLatin1CString(const uint8_t *bytes, CFIndex len) { CFHashCode result = len; if (len <= HashEverythingLimit) { @@ -1203,9 +1207,11 @@ static const CFRuntimeClass __CFStringClass = { }; CF_PRIVATE void __CFStringInitialize(void) { - __kCFStringTypeID = _CFRuntimeRegisterClass(&__CFStringClass); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFStringTypeID = _CFRuntimeRegisterClass(&__CFStringClass); }); } + CFTypeID CFStringGetTypeID(void) { return __kCFStringTypeID; } @@ -1216,8 +1222,7 @@ static Boolean CFStrIsUnicode(CFStringRef str) { return __CFStrIsUnicode(str); } - - + #define ALLOCATORSFREEFUNC ((CFAllocatorRef)-1) /* contentsDeallocator indicates how to free the data if it's noCopy == true: @@ -1239,7 +1244,7 @@ CF_PRIVATE CFStringRef __CFStringCreateImmutableFunnel3( Boolean possiblyExternalFormat, Boolean tryToReduceUnicode, Boolean hasLengthByte, Boolean hasNullByte, Boolean noCopy, CFAllocatorRef contentsDeallocator, UInt32 converterFlags) { - CFMutableStringRef str; + CFMutableStringRef str = NULL; CFVarWidthCharBuffer vBuf; CFIndex size; Boolean useLengthByte = false; @@ -1393,122 +1398,139 @@ CF_PRIVATE CFStringRef __CFStringCreateImmutableFunnel3( // At this point, all necessary input arguments have been changed to reflect the new state } - // Now determine the necessary size +#if USE_STRING_ROM || ENABLE_TAGGED_POINTER_STRINGS || INSTRUMENT_SHARED_STRINGS + CFIndex lengthByte = (hasLengthByte ? 1 : 0); + CFIndex realNumBytes = numBytes - lengthByte; + const uint8_t *realBytes = bytes + lengthByte; +#endif + + + if (!str) { + // Now determine the necessary size #if INSTRUMENT_SHARED_STRINGS || USE_STRING_ROM - Boolean stringSupportsROM = stringSupportsEightBitCFRepresentation; + Boolean stringSupportsROM = stringSupportsEightBitCFRepresentation; #endif #if INSTRUMENT_SHARED_STRINGS - if (stringSupportsROM) { - const void *realBytes = (uint8_t *) bytes + (hasLengthByte ? 1 : 0); - CFIndex realNumBytes = numBytes - !! hasLengthByte; - __CFRecordStringAllocationEvent(recordedEncoding, realBytes, realNumBytes); - } + if (stringSupportsROM) __CFRecordStringAllocationEvent(recordedEncoding, realBytes, realNumBytes); #endif #if USE_STRING_ROM - CFStringRef romResult = NULL; + CFStringRef romResult = NULL; - if (stringSupportsROM) { - // Disable the string ROM if necessary - static char sDisableStringROM = -1; - if (sDisableStringROM == -1) sDisableStringROM = !! __CFgetenv("CFStringDisableROM"); + if (stringSupportsROM) { + // Disable the string ROM if necessary + static char sDisableStringROM = -1; + if (sDisableStringROM == -1) sDisableStringROM = !! __CFgetenv("CFStringDisableROM"); - if (sDisableStringROM == 0) romResult = _CFSearchStringROM(bytes + !! hasLengthByte, numBytes - !! hasLengthByte); - } - /* if we get a result from our ROM, and noCopy is set, then deallocate the buffer immediately */ - if (romResult) { - if (noCopy && (contentsDeallocator != kCFAllocatorNull)) { - CFAllocatorDeallocate(contentsDeallocator, (void *)bytes); - } - - /* these don't get used again, but clear them for consistency */ - noCopy = false; - bytes = NULL; - - /* set our result to the ROM result which is not really mutable, of course, but that's OK because we don't try to modify it. */ - str = (CFMutableStringRef)romResult; - } + if (sDisableStringROM == 0) romResult = __CFSearchStringROM((const char *)realBytes, realNumBytes); + } + /* if we get a result from our ROM, and noCopy is set, then deallocate the buffer immediately */ + if (romResult) { + if (noCopy && (contentsDeallocator != kCFAllocatorNull)) { + CFAllocatorDeallocate(contentsDeallocator, (void *)bytes); + } + + /* these don't get used again, but clear them for consistency */ + noCopy = false; + bytes = NULL; + + /* set our result to the ROM result which is not really mutable, of course, but that's OK because we don't try to modify it. */ + str = (CFMutableStringRef)romResult; + +#if INSTRUMENT_TAGGED_POINTER_STRINGS + _CFTaggedPointerStringStats.stringROMCount++; +#endif + } - if (! romResult) { + if (! romResult) { #else - if (1) { + if (1) { +#endif + +#if INSTRUMENT_SHARED_STRINGS + if (stringSupportsROM) __CFRecordStringAllocationEvent(recordedEncoding, realBytes, realNumBytes); #endif - // Now determine the necessary size +#if INSTRUMENT_TAGGED_POINTER_STRINGS + _CFTaggedPointerStringStats.otherStringCount++; +#endif + + // Now determine the necessary size - if (noCopy) { + if (noCopy) { - size = sizeof(void *); // Pointer to the buffer - if ((0) || (contentsDeallocator != alloc && contentsDeallocator != kCFAllocatorNull)) { - size += sizeof(void *); // The contentsDeallocator - } - if (!hasLengthByte) size += sizeof(CFIndex); // Explicit length - useLengthByte = hasLengthByte; - useNullByte = hasNullByte; + size = sizeof(void *); // Pointer to the buffer + if ((0) || (contentsDeallocator != alloc && contentsDeallocator != kCFAllocatorNull)) { + size += sizeof(void *); // The contentsDeallocator + } + if (!hasLengthByte) size += sizeof(CFIndex); // Explicit length + useLengthByte = hasLengthByte; + useNullByte = hasNullByte; - } else { // Inline data; reserve space for it + } else { // Inline data; reserve space for it - useInlineData = true; - size = numBytes; + useInlineData = true; + size = numBytes; - if (hasLengthByte || (encoding != kCFStringEncodingUnicode && __CFCanUseLengthByte(numBytes))) { - useLengthByte = true; - if (!hasLengthByte) size += 1; - } else { - size += sizeof(CFIndex); // Explicit length - } - if (hasNullByte || encoding != kCFStringEncodingUnicode) { - useNullByte = true; - size += 1; - } - } + if (hasLengthByte || (encoding != kCFStringEncodingUnicode && __CFCanUseLengthByte(numBytes))) { + useLengthByte = true; + if (!hasLengthByte) size += 1; + } else { + size += sizeof(CFIndex); // Explicit length + } + if (hasNullByte || encoding != kCFStringEncodingUnicode) { + useNullByte = true; + size += 1; + } + } #ifdef STRING_SIZE_STATS - // Dump alloced CFString size info every so often - static int cnt = 0; - static unsigned sizes[256] = {0}; - int allocedSize = size + sizeof(CFRuntimeBase); - if (allocedSize < 255) sizes[allocedSize]++; else sizes[255]++; - if ((++cnt % 1000) == 0) { - printf ("\nTotal: %d\n", cnt); - int i; for (i = 0; i < 256; i++) printf("%03d: %5d%s", i, sizes[i], ((i % 8) == 7) ? "\n" : " "); - } + // Dump alloced CFString size info every so often + static int cnt = 0; + static unsigned sizes[256] = {0}; + int allocedSize = size + sizeof(CFRuntimeBase); + if (allocedSize < 255) sizes[allocedSize]++; else sizes[255]++; + if ((++cnt % 1000) == 0) { + printf ("\nTotal: %d\n", cnt); + int i; for (i = 0; i < 256; i++) printf("%03d: %5d%s", i, sizes[i], ((i % 8) == 7) ? "\n" : " "); + } #endif - - // Finally, allocate! - - str = (CFMutableStringRef)_CFRuntimeCreateInstance(alloc, __kCFStringTypeID, size, NULL); - if (str) { - if (__CFOASafe) __CFSetLastAllocationEventName(str, "CFString (immutable)"); - - CFOptionFlags allocBits = (0) ? __kCFHasContentsDeallocator : (contentsDeallocator == alloc ? __kCFNotInlineContentsDefaultFree : (contentsDeallocator == kCFAllocatorNull ? __kCFNotInlineContentsNoFree : __kCFNotInlineContentsCustomFree)); - __CFStrSetInfoBits(str, - (useInlineData ? __kCFHasInlineContents : allocBits) | - ((encoding == kCFStringEncodingUnicode) ? __kCFIsUnicode : 0) | - (useNullByte ? __kCFHasNullByte : 0) | - (useLengthByte ? __kCFHasLengthByte : 0)); - - if (!useLengthByte) { - CFIndex length = numBytes - (hasLengthByte ? 1 : 0); - if (encoding == kCFStringEncodingUnicode) length /= sizeof(UniChar); - __CFStrSetExplicitLength(str, length); - } + + // Finally, allocate! + + str = (CFMutableStringRef)_CFRuntimeCreateInstance(alloc, __kCFStringTypeID, size, NULL); + if (str) { + if (__CFOASafe) __CFSetLastAllocationEventName(str, "CFString (immutable)"); + + CFOptionFlags allocBits = (0) ? __kCFHasContentsDeallocator : (contentsDeallocator == alloc ? __kCFNotInlineContentsDefaultFree : (contentsDeallocator == kCFAllocatorNull ? __kCFNotInlineContentsNoFree : __kCFNotInlineContentsCustomFree)); + __CFStrSetInfoBits(str, + (useInlineData ? __kCFHasInlineContents : allocBits) | + ((encoding == kCFStringEncodingUnicode) ? __kCFIsUnicode : 0) | + (useNullByte ? __kCFHasNullByte : 0) | + (useLengthByte ? __kCFHasLengthByte : 0)); + + if (!useLengthByte) { + CFIndex length = numBytes - (hasLengthByte ? 1 : 0); + if (encoding == kCFStringEncodingUnicode) length /= sizeof(UniChar); + __CFStrSetExplicitLength(str, length); + } - if (useInlineData) { - uint8_t *contents = (uint8_t *)__CFStrContents(str); - if (useLengthByte && !hasLengthByte) *contents++ = (uint8_t)numBytes; - memmove(contents, bytes, numBytes); - if (useNullByte) contents[numBytes] = 0; - } else { - __CFStrSetContentPtr(str, bytes); - if (__CFStrHasContentsDeallocator(str)) __CFStrSetContentsDeallocator(str, contentsDeallocator); - } - } else { - if (noCopy && (contentsDeallocator != kCFAllocatorNull)) { - CFAllocatorDeallocate(contentsDeallocator, (void *)bytes); - } - } + if (useInlineData) { + uint8_t *contents = (uint8_t *)__CFStrContents(str); + if (useLengthByte && !hasLengthByte) *contents++ = (uint8_t)numBytes; + memmove(contents, bytes, numBytes); + if (useNullByte) contents[numBytes] = 0; + } else { + __CFStrSetContentPtr(str, bytes); + if (__CFStrHasContentsDeallocator(str)) __CFStrSetContentsDeallocator(str, contentsDeallocator); + } + } else { + if (noCopy && (contentsDeallocator != kCFAllocatorNull)) { + CFAllocatorDeallocate(contentsDeallocator, (void *)bytes); + } + } + } } if (vBuf.shouldFreeChars) CFAllocatorDeallocate(vBuf.allocator, (void *)bytes); @@ -1585,20 +1607,24 @@ CFStringRef CFStringCreateWithBytesNoCopy(CFAllocatorRef alloc, const uint8_t * } CFStringRef CFStringCreateWithFormatAndArguments(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, va_list arguments) { - return _CFStringCreateWithFormatAndArgumentsAux(alloc, NULL, formatOptions, format, arguments); + return _CFStringCreateWithFormatAndArgumentsAux2(alloc, NULL, NULL, formatOptions, format, arguments); } -CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments) { +CFStringRef _CFStringCreateWithFormatAndArgumentsAux2(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, const void *), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool , bool *), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments) { CFStringRef str; CFMutableStringRef outputString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); //should use alloc if no copy/release __CFStrSetDesiredCapacity(outputString, 120); // Given this will be tightened later, choosing a larger working string is fine - __CFStringAppendFormatCore(outputString, copyDescFunc, formatOptions, NULL, format, 0, NULL, 0, arguments); + __CFStringAppendFormatCore(outputString, copyDescFunc, contextDescFunc, formatOptions, NULL, format, 0, NULL, 0, arguments); // ??? copy/release should not be necessary here -- just make immutable, compress if possible // (However, this does make the string inline, and cause the supplied allocator to be used...) str = (CFStringRef)CFStringCreateCopy(alloc, outputString); CFRelease(outputString); return str; } + +CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments) { + return _CFStringCreateWithFormatAndArgumentsAux2(alloc, copyDescFunc, NULL, formatOptions, format, arguments); +} CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...) { CFStringRef result; @@ -1654,7 +1680,7 @@ CFStringRef CFStringCreateCopy(CFAllocatorRef alloc, CFStringRef str) { /* Table which holds constant strings created with CFSTR, when -fconstant-cfstrings option is not used. These dynamically created constant strings are stored in constantStringTable. The keys are the 8-bit constant C-strings from the compiler; the values are the CFStrings created for them. _CFSTRLock protects this table. */ static CFMutableDictionaryRef constantStringTable = NULL; -static CFSpinLock_t _CFSTRLock = CFSpinLockInit; +static CFLock_t _CFSTRLock = CFLockInit; static CFStringRef __cStrCopyDescription(const void *ptr) { return CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault, (const char *)ptr, __CFStringGetEightBitStringEncoding(), kCFAllocatorNull); @@ -1695,74 +1721,77 @@ CFStringRef __CFStringMakeConstantString(const char *cStr) { constantStringValueCallBacks.equal = NULL; // So that we only find strings that are == CFMutableDictionaryRef table = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &constantStringCallBacks, &constantStringValueCallBacks); _CFDictionarySetCapacity(table, 2500); // avoid lots of rehashing - __CFSpinLock(&_CFSTRLock); + __CFLock(&_CFSTRLock); if (constantStringTable == NULL) constantStringTable = table; - __CFSpinUnlock(&_CFSTRLock); + __CFUnlock(&_CFSTRLock); if (constantStringTable != table) CFRelease(table); } - __CFSpinLock(&_CFSTRLock); + __CFLock(&_CFSTRLock); if ((result = (CFStringRef)CFDictionaryGetValue(constantStringTable, cStr))) { - __CFSpinUnlock(&_CFSTRLock); + __CFUnlock(&_CFSTRLock); } else { - __CFSpinUnlock(&_CFSTRLock); + __CFUnlock(&_CFSTRLock); { - char *key; - Boolean isASCII = true; - // Given this code path is rarer these days, OK to do this extra work to verify the strings - const char *tmp = cStr; - while (*tmp) { - if (*(tmp++) & 0x80) { - isASCII = false; - break; - } - } - if (!isASCII) { - CFMutableStringRef ms = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - tmp = cStr; + char *key = NULL; + Boolean isASCII = true; + // Given this code path is rarer these days, OK to do this extra work to verify the strings + const char *tmp = cStr; while (*tmp) { - CFStringAppendFormat(ms, NULL, (*tmp & 0x80) ? CFSTR("\\%3o") : CFSTR("%1c"), *tmp); - tmp++; + if (*(tmp++) & 0x80) { + isASCII = false; + break; + } + } + if (!isASCII) { + CFMutableStringRef ms = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); + tmp = cStr; + while (*tmp) { + CFStringAppendFormat(ms, NULL, (*tmp & 0x80) ? CFSTR("\\%3o") : CFSTR("%1c"), *tmp); + tmp++; + } + CFLog(kCFLogLevelWarning, CFSTR("WARNING: CFSTR(\"%@\") has non-7 bit chars, interpreting using MacOS Roman encoding for now, but this will change. Please eliminate usages of non-7 bit chars (including escaped characters above \\177 octal) in CFSTR()."), ms); + CFRelease(ms); + } + // Treat non-7 bit chars in CFSTR() as MacOSRoman, for compatibility + result = CFStringCreateWithCString(kCFAllocatorSystemDefault, cStr, kCFStringEncodingMacRoman); + if (result == NULL) { + CFLog(__kCFLogAssertion, CFSTR("Can't interpret CFSTR() as MacOS Roman, crashing")); + HALT; + } + Boolean isTaggedPointerString = CF_IS_OBJC(__kCFStringTypeID, result); + + if (!isTaggedPointerString) { + if (__CFOASafe) __CFSetLastAllocationEventName((void *)result, "CFString (CFSTR)"); + if (__CFStrIsEightBit(result)) key = (char *)__CFStrContents(result) + __CFStrSkipAnyLengthByte(result); + } + if (!key) { // Either the string is not 8-bit or it's a tagged pointer string + CFIndex keySize = strlen(cStr) + 1; + key = (char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, keySize, 0); + if (__CFOASafe) __CFSetLastAllocationEventName((void *)key, "CFString (CFSTR key)"); + strlcpy(key, cStr, keySize); // !!! We will leak this, if the string is removed from the table (or table is freed) } - CFLog(kCFLogLevelWarning, CFSTR("WARNING: CFSTR(\"%@\") has non-7 bit chars, interpreting using MacOS Roman encoding for now, but this will change. Please eliminate usages of non-7 bit chars (including escaped characters above \\177 octal) in CFSTR()."), ms); - CFRelease(ms); - } - // Treat non-7 bit chars in CFSTR() as MacOSRoman, for compatibility - result = CFStringCreateWithCString(kCFAllocatorSystemDefault, cStr, kCFStringEncodingMacRoman); - if (result == NULL) { - CFLog(__kCFLogAssertion, CFSTR("Can't interpret CFSTR() as MacOS Roman, crashing")); - HALT; - } - if (__CFOASafe) __CFSetLastAllocationEventName((void *)result, "CFString (CFSTR)"); - if (__CFStrIsEightBit(result)) { - key = (char *)__CFStrContents(result) + __CFStrSkipAnyLengthByte(result); - } else { // For some reason the string is not 8-bit! - CFIndex keySize = strlen(cStr) + 1; - key = (char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, keySize, 0); - if (__CFOASafe) __CFSetLastAllocationEventName((void *)key, "CFString (CFSTR key)"); - strlcpy(key, cStr, keySize); // !!! We will leak this, if the string is removed from the table (or table is freed) - } - { - CFStringRef resultToBeReleased = result; - CFIndex count; - __CFSpinLock(&_CFSTRLock); - count = CFDictionaryGetCount(constantStringTable); - CFDictionaryAddValue(constantStringTable, key, result); - if (CFDictionaryGetCount(constantStringTable) == count) { // add did nothing, someone already put it there - result = (CFStringRef)CFDictionaryGetValue(constantStringTable, key); - } else { + { + CFStringRef resultToBeReleased = result; + CFIndex count; + __CFLock(&_CFSTRLock); + count = CFDictionaryGetCount(constantStringTable); + CFDictionaryAddValue(constantStringTable, key, result); + if (CFDictionaryGetCount(constantStringTable) == count) { // add did nothing, someone already put it there + result = (CFStringRef)CFDictionaryGetValue(constantStringTable, key); + } else if (!isTaggedPointerString) { #if __LP64__ - ((struct __CFString *)result)->base._rc = 0; + ((struct __CFString *)result)->base._rc = 0; #else - ((struct __CFString *)result)->base._cfinfo[CF_RC_BITS] = 0; + ((struct __CFString *)result)->base._cfinfo[CF_RC_BITS] = 0; #endif - } - __CFSpinUnlock(&_CFSTRLock); - // This either eliminates the extra retain on the freshly created string, or frees it, if it was actually not inserted into the table - CFRelease(resultToBeReleased); - } + } + __CFUnlock(&_CFSTRLock); + // This either eliminates the extra retain on the freshly created string, or frees it, if it was actually not inserted into the table + CFRelease(resultToBeReleased); + } } } return result; @@ -1772,9 +1801,9 @@ CFStringRef __CFStringMakeConstantString(const char *cStr) { static Boolean __CFStrIsConstantString(CFStringRef str) { Boolean found = false; if (constantStringTable) { - __CFSpinLock(&_CFSTRLock); + __CFLock(&_CFSTRLock); found = CFDictionaryContainsValue(constantStringTable, str); - __CFSpinUnlock(&_CFSTRLock); + __CFUnlock(&_CFSTRLock); } return found; } @@ -2010,10 +2039,9 @@ int _CFStringCheckAndGetCharacters(CFStringRef str, CFRange range, UniChar *buff CFIndex CFStringGetBytes(CFStringRef str, CFRange range, CFStringEncoding encoding, uint8_t lossByte, Boolean isExternalRepresentation, uint8_t *buffer, CFIndex maxBufLen, CFIndex *usedBufLen) { - /* No objc dispatch needed here since __CFStringEncodeByteStream works with both CFString and NSString */ __CFAssertIsNotNegative(maxBufLen); - - if (!CF_IS_OBJC(__kCFStringTypeID, str)) { // If we can grope the ivars, let's do it... + + { __CFAssertIsString(str); __CFAssertRangeIsInStringBounds(str, range.location, range.length); @@ -2182,60 +2210,55 @@ static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale, bool const char *langID = NULL; static const void *lastLocale = NULL; static const char *lastLangID = NULL; - static CFSpinLock_t lock = CFSpinLockInit; + static CFLock_t lock = CFLockInit; if (__CFLocaleGetNullLocale((struct __CFLocale *)locale)) return NULL; - __CFSpinLock(&lock); + __CFLock(&lock); if ((NULL != lastLocale) && (lastLocale == locale)) { - __CFSpinUnlock(&lock); + __CFUnlock(&lock); return lastLangID; } - __CFSpinUnlock(&lock); + __CFUnlock(&lock); localeID = (CFStringRef)CFLocaleGetValue(locale, __kCFLocaleCollatorID); + CFIndex length = CFStringGetLength(localeID); if (!collatorOnly) { - CFIndex length = __CFStrLength(localeID); - - if ((length < 2) || ((4 == length) && CFEqual(localeID, CFSTR("root")))) localeID = (CFStringRef)CFLocaleGetIdentifier(locale); + if ((length < 2) || ((4 == length) && CFEqual(localeID, CFSTR("root")))) { + localeID = (CFStringRef)CFLocaleGetIdentifier(locale); + length = CFStringGetLength(localeID); + } } - // This is somewhat depending on CFLocale implementation always creating CFString for locale identifer ??? - if (__CFStrLength(localeID) > 1) { - const void *contents = __CFStrContents(localeID); - const char *string; - char buffer[2]; - - if (__CFStrIsEightBit(localeID)) { - string = ((const char *)contents) + __CFStrSkipAnyLengthByte(localeID); - } else { - const UTF16Char *characters = (const UTF16Char *)contents; - - buffer[0] = (char)*(characters++); - buffer[1] = (char)*characters; - string = buffer; + if (length > 1) { + uint8_t buffer[2]; + const uint8_t *contents = (const uint8_t *)CFStringGetCStringPtr(localeID, kCFStringEncodingUTF8); + if (!contents) { + if (2 == CFStringGetBytes(localeID, CFRangeMake(0,2), kCFStringEncodingUTF8, 0, false, buffer, sizeof(buffer), NULL)) contents = buffer; } - - if (!strncmp(string, "az", 2)) { // Azerbaijani - langID = "az"; - } else if (!strncmp(string, "lt", 2)) { // Lithuanian - langID = "lt"; - } else if (!strncmp(string, "tr", 2)) { // Turkish - langID = "tr"; - } else if (!strncmp(string, "nl", 2)) { // Dutch - langID = "nl"; - } else if (!strncmp(string, "el", 2)) { // Greek - langID = "el"; + if (contents) { + const char *string = (const char *)contents; + if (!strncmp(string, "az", 2)) { // Azerbaijani + langID = "az"; + } else if (!strncmp(string, "lt", 2)) { // Lithuanian + langID = "lt"; + } else if (!strncmp(string, "tr", 2)) { // Turkish + langID = "tr"; + } else if (!strncmp(string, "nl", 2)) { // Dutch + langID = "nl"; + } else if (!strncmp(string, "el", 2)) { // Greek + langID = "el"; + } } } if (langID == NULL) __CFLocaleSetNullLocale((struct __CFLocale *)locale); - __CFSpinLock(&lock); + __CFLock(&lock); lastLocale = locale; lastLangID = langID; - __CFSpinUnlock(&lock); + __CFUnlock(&lock); return langID; } @@ -2278,7 +2301,7 @@ static CFIndex __CFStringFoldCharacterClusterAtIndex(UTF32Char character, CFStri graphemeBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, 0); } - ++currentIndex; + currentIndex += ((character > 0xFFFF) ? 2 : 1); if ((character < 0x0080) && ((NULL == langCode) || (character != 'I'))) { // ASCII if ((flags & kCFCompareCaseInsensitive) && (character >= 'A') && (character <= 'Z')) { @@ -2508,7 +2531,6 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr bool equalityOptions = ((compareOptions & (kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive|kCFCompareWidthInsensitive)) ? true : false); bool numerically = ((compareOptions & kCFCompareNumerically) ? true : false); bool forceOrdering = ((compareOptions & kCFCompareForcedOrdering) ? true : false); - const uint8_t *graphemeBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, 0); const uint8_t *langCode; CFComparisonResult compareResult = kCFCompareEqualTo; UTF16Char otherChar; @@ -2607,7 +2629,9 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr return ((0 == cmpResult) ? kCFCompareEqualTo : ((cmpResult < 0) ? kCFCompareLessThan : kCFCompareGreaterThan)); } } - + + const uint8_t *graphemeBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, 0); + CFStringInitInlineBuffer(string, &inlineBuf1, rangeToCompare); CFStringInitInlineBuffer(string2, &inlineBuf2, CFRangeMake(0, str2Len)); @@ -4395,7 +4419,7 @@ void CFStringTrim(CFMutableStringRef string, CFStringRef trimString) { uint8_t *contents = (uint8_t *)__CFStrContents(string) + __CFStrSkipAnyLengthByte(string); length -= newStartIndex; - if (__CFStrLength(trimString) < length) { + if (CFStringGetLength(trimString) < length) { while (CFStringFindWithOptions(string, trimString, CFRangeMake(newStartIndex, length), kCFCompareAnchored|kCFCompareBackwards, &range)) { length = range.location - newStartIndex; } @@ -5303,7 +5327,7 @@ enum { /* Only come in here if spec->type is CFFormatLongType or CFFormatDoubleType. Pass in 0 for width or precision if not specified. Returns false if couldn't do the format (with the assumption the caller falls back to unlocalized). */ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLocaleRef locale, const CFPrintValue *values, const CFFormatSpec *spec, SInt32 width, SInt32 precision, Boolean hasPrecision) { - static CFSpinLock_t formatterLock = CFSpinLockInit; + static CFLock_t formatterLock = CFLockInit; // These formatters are recached if the locale argument is different static CFNumberFormatterRef decimalFormatter = NULL; static CFNumberFormatterRef scientificFormatter = NULL; @@ -5318,7 +5342,7 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca CFNumberFormatterRef formatter; - __CFSpinLock(&formatterLock); // We use the formatter from one thread at one time; if this proves to be a bottleneck we need to get fancier + __CFLock(&formatterLock); // We use the formatter from one thread at one time; if this proves to be a bottleneck we need to get fancier switch (spec->numericFormatStyle) { case CFFormatStyleUnsigned: @@ -5398,26 +5422,6 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca CFRelease(tmp); CFRelease(zero); - - // ??? use the right zero here for Arabic - Boolean padZero = spec->flags & kCFStringFormatZeroFlag; - if (hasPrecision && spec->type == CFFormatLongType) { // if we have precision and %d or %u, we pad 0 - padZero = true; - } - CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingCharacterKey, padZero ? CFSTR("0") : CFSTR(" ")); - - - // Left (default) or right padding - SInt32 p = (spec->flags & kCFStringFormatMinusFlag) ? kCFNumberFormatterPadAfterSuffix : (padZero ? kCFNumberFormatterPadAfterPrefix : kCFNumberFormatterPadBeforePrefix); - if (hasPrecision && spec->type == CFFormatLongType) { - SInt32 tmpP = kCFNumberFormatterPadAfterPrefix; - tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &tmpP); - } else { - tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &p); - } - CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingPositionKey, tmp); - CFRelease(tmp); - Boolean isNegative = false; switch (values[spec->mainArgNum].type) { case CFFormatLongType: @@ -5456,6 +5460,25 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca } CFNumberFormatterSetProperty(formatter, kCFNumberFormatterFormatWidthKey, tmp); CFRelease(tmp); + + // ??? use the right zero here for Arabic + Boolean padZero = spec->flags & kCFStringFormatZeroFlag; + if (hasPrecision && spec->type == CFFormatLongType) { // if we have precision and %d or %u, we pad 0 + padZero = true; + } + CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingCharacterKey, padZero ? CFSTR("0") : CFSTR(" ")); + + + // Left (default) or right padding + SInt32 p = (spec->flags & kCFStringFormatMinusFlag) ? kCFNumberFormatterPadAfterSuffix : (padZero ? kCFNumberFormatterPadAfterPrefix : kCFNumberFormatterPadBeforePrefix); + if (hasPrecision && spec->type == CFFormatLongType) { + SInt32 tmpP = kCFNumberFormatterPadAfterPrefix; + tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &tmpP); + } else { + tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &p); + } + CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingPositionKey, tmp); + CFRelease(tmp); if (spec->numericFormatStyle == CFFormatStyleScientific) { prec++; // for %e, precision+1 is the number of sig fig @@ -5484,7 +5507,7 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca break; } } - __CFSpinUnlock(&formatterLock); + __CFUnlock(&formatterLock); if (localizedNumberString) { // we need to pad space if we have %d or %u @@ -5707,7 +5730,7 @@ reswtch:switch (ch) { /* ??? %s depends on handling of encodings by __CFStringAppendBytes */ void CFStringAppendFormatAndArguments(CFMutableStringRef outputString, CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) { - __CFStringAppendFormatCore(outputString, NULL, formatOptions, NULL, formatString, 0, NULL, 0, args); + __CFStringAppendFormatCore(outputString, NULL, NULL, formatOptions, NULL, formatString, 0, NULL, 0, args); } // Length of the buffer to call sprintf() with @@ -5747,9 +5770,15 @@ void CFStringAppendFormatAndArguments(CFMutableStringRef outputString, CFDiction }} #endif -void _CFStringAppendFormatAndArgumentsAux(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) { __CFStringAppendFormatCore(outputString, copyDescFunc, formatOptions, NULL, formatString, 0, NULL, 0, args); } - -static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFDictionaryRef stringsDictConfig, CFStringRef formatString, CFIndex initialArgPosition, const void *origValues, CFIndex originalValuesSize, va_list args) { +void _CFStringAppendFormatAndArgumentsAux2(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) { + __CFStringAppendFormatCore(outputString, copyDescFunc, contextDescFunc, formatOptions, NULL, formatString, 0, NULL, 0, args); +} + +void _CFStringAppendFormatAndArgumentsAux(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) { + _CFStringAppendFormatAndArgumentsAux2(outputString, copyDescFunc, NULL, formatOptions, formatString, args); +} + +static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions, CFDictionaryRef stringsDictConfig, CFStringRef formatString, CFIndex initialArgPosition, const void *origValues, CFIndex originalValuesSize, va_list args) { SInt32 numSpecs, sizeSpecs, sizeArgNum, formatIdx, curSpec, argNum; CFIndex formatLen; #define FORMAT_BUFFER_LEN 400 @@ -5962,6 +5991,10 @@ static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFString originalValuesSize = sizeArgNum; } + SInt32 numSpecsContext = 0; + CFFormatSpec *specsContext = (CFFormatSpec *)calloc(numSpecs, sizeof(CFFormatSpec)); + static const CFStringRef replacement = CFSTR("%@NSCONTEXT"); + for (curSpec = 0; curSpec < numSpecs; curSpec++) { SInt32 width = 0, precision = 0; UniChar *up, ch; @@ -6166,8 +6199,6 @@ static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFString case CFFormatObjectType: if (specs[curSpec].configDictIndex != -1) { // config dict CFTypeRef object = NULL; - CFStringRef innerFormat = NULL; - switch (values[specs[curSpec].mainArgNum].type) { case CFFormatLongType: object = CFNumberCreate(tmpAlloc, kCFNumberSInt64Type, &(values[specs[curSpec].mainArgNum].value.int64Value)); @@ -6276,14 +6307,25 @@ static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFString } else if (NULL != values[specs[curSpec].mainArgNum].value.pointerValue) { CFStringRef str = NULL; - if (copyDescFunc) { - str = copyDescFunc(values[specs[curSpec].mainArgNum].value.pointerValue, formatOptions); - } else { - str = __CFCopyFormattingDescription(values[specs[curSpec].mainArgNum].value.pointerValue, formatOptions); - if (NULL == str) { - str = CFCopyDescription(values[specs[curSpec].mainArgNum].value.pointerValue); - } - } + if (contextDescFunc) { + bool found = NO; + str = contextDescFunc(values[specs[curSpec].mainArgNum].value.pointerValue, formatString, replacement, NO, &found); + if (found) { + str = CFRetain(replacement); + specsContext[numSpecsContext] = specs[curSpec]; + numSpecsContext++; + } + } + if (!str) { + if (copyDescFunc) { + str = copyDescFunc(values[specs[curSpec].mainArgNum].value.pointerValue, formatOptions); + } else { + str = __CFCopyFormattingDescription(values[specs[curSpec].mainArgNum].value.pointerValue, formatOptions); + if (NULL == str) { + str = CFCopyDescription(values[specs[curSpec].mainArgNum].value.pointerValue); + } + } + } if (str) { CFStringAppend(outputString, str); CFRelease(str); @@ -6296,6 +6338,17 @@ static void __CFStringAppendFormatCore(CFMutableStringRef outputString, CFString break; } } + + for (SInt32 i = 0; i < numSpecsContext; i++) { + CFRange range = CFStringFind(outputString, replacement, 0); + CFStringRef str = contextDescFunc(values[specsContext[i].mainArgNum].value.pointerValue, outputString, replacement, true, NULL); + if (str) { + CFStringReplace(outputString, range, str); + CFRelease(str); + } + } + + free(specsContext); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD // va_copy is a C99 extension. No support on Windows diff --git a/CFString.h b/CFString.h index 61ce9ef..e24bc1f 100644 --- a/CFString.h +++ b/CFString.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFString.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRING__) @@ -398,14 +398,15 @@ typedef CF_OPTIONS(CFOptionFlags, CFStringCompareFlags) { }; /* The main comparison routine; compares specified range of the first string to (the full range of) the second string. -locale == NULL indicates canonical locale (the return value from CFLocaleGetSystem()). -kCFCompareNumerically, added in 10.2, does not work if kCFCompareLocalized is specified on systems before 10.3 -kCFCompareBackwards and kCFCompareAnchored are not applicable. + locale == NULL indicates canonical locale (the return value from CFLocaleGetSystem()). + kCFCompareNumerically, added in 10.2, does not work if kCFCompareLocalized is specified on systems before 10.3 + kCFCompareBackwards and kCFCompareAnchored are not applicable. + rangeToCompare applies to the first string; that is, only the substring of theString1 specified by rangeToCompare is compared against all of theString2. */ CF_EXPORT CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef theString1, CFStringRef theString2, CFRange rangeToCompare, CFStringCompareFlags compareOptions, CFLocaleRef locale) CF_AVAILABLE(10_5, 2_0); -/* Comparison convenience. Uses the current user locale (the return value from CFLocaleCopyCurrent()) if kCFCompareLocalized. +/* Comparison convenience. Uses the current user locale (the return value from CFLocaleCopyCurrent()) if kCFCompareLocalized. Refer to CFStringCompareWithOptionsAndLocale() for more info. */ CF_EXPORT CFComparisonResult CFStringCompareWithOptions(CFStringRef theString1, CFStringRef theString2, CFRange rangeToCompare, CFStringCompareFlags compareOptions); @@ -418,14 +419,15 @@ CF_EXPORT CFComparisonResult CFStringCompare(CFStringRef theString1, CFStringRef theString2, CFStringCompareFlags compareOptions); /* CFStringFindWithOptionsAndLocale() returns the found range in the CFRange * argument; you can pass NULL for simple discovery check. - locale == NULL indicates canonical locale (the return value from CFLocaleGetSystem()). - If stringToFind is the empty string (zero length), nothing is found. - Ignores the kCFCompareNumerically option. + locale == NULL indicates canonical locale (the return value from CFLocaleGetSystem()). + If stringToFind is the empty string (zero length), nothing is found. + Ignores the kCFCompareNumerically option. + Only the substring of theString specified by rangeToSearch is searched for stringToFind. */ CF_EXPORT Boolean CFStringFindWithOptionsAndLocale(CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFLocaleRef locale, CFRange *result) CF_AVAILABLE(10_5, 2_0); -/* Find convenience. Uses the current user locale (the return value from CFLocaleCopyCurrent()) if kCFCompareLocalized. +/* Find convenience. Uses the current user locale (the return value from CFLocaleCopyCurrent()) if kCFCompareLocalized. Refer to CFStringFindWithOptionsAndLocale() for more info. */ CF_EXPORT Boolean CFStringFindWithOptions(CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFRange *result); @@ -437,6 +439,7 @@ Boolean CFStringFindWithOptions(CFStringRef theString, CFStringRef stringToFind, If stringToFind is the empty string (zero length), nothing is found. kCFCompareAnchored causes just the consecutive instances at start (or end, if kCFCompareBackwards) to be reported. So, searching for "AB" in "ABABXAB..." you just get the first two occurrences. Ignores the kCFCompareNumerically option. + Only the substring of theString specified by rangeToSearch is searched for stringToFind. */ CF_EXPORT CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags compareOptions); diff --git a/CFStringDefaultEncoding.h b/CFStringDefaultEncoding.h index 37237a3..e3c035e 100644 --- a/CFStringDefaultEncoding.h +++ b/CFStringDefaultEncoding.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringDefaultEncoding.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGDEFAULTENCODING__) diff --git a/CFStringEncodingConverter.c b/CFStringEncodingConverter.c index c026633..cf9fc3f 100644 --- a/CFStringEncodingConverter.c +++ b/CFStringEncodingConverter.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodingConverter.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -598,7 +598,7 @@ static const _CFEncodingConverter *__CFGetConverter(uint32_t encoding) { const _CFEncodingConverter **commonConverterSlot = NULL; static _CFEncodingConverter *commonConverters[3] = {NULL, NULL, NULL}; // UTF8, MacRoman/WinLatin1, and the default encoding* static CFMutableDictionaryRef mappingTable = NULL; - static CFSpinLock_t lock = CFSpinLockInit; + static OSSpinLock lock = OS_SPINLOCK_INIT; switch (encoding) { case kCFStringEncodingUTF8: commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[0]); break; @@ -616,15 +616,15 @@ static const _CFEncodingConverter *__CFGetConverter(uint32_t encoding) { default: if (CFStringGetSystemEncoding() == encoding) commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[2]); break; } - __CFSpinLock(&lock); + OSSpinLockLock(&lock); converter = ((NULL == commonConverterSlot) ? ((NULL == mappingTable) ? NULL : (const _CFEncodingConverter *)CFDictionaryGetValue(mappingTable, (const void *)(uintptr_t)encoding)) : *commonConverterSlot); - __CFSpinUnlock(&lock); + OSSpinLockUnlock(&lock); if (NULL == converter) { const CFStringEncodingConverter *definition = __CFStringEncodingConverterGetDefinition(encoding); if (NULL != definition) { - __CFSpinLock(&lock); + OSSpinLockLock(&lock); converter = ((NULL == commonConverterSlot) ? ((NULL == mappingTable) ? NULL : (const _CFEncodingConverter *)CFDictionaryGetValue(mappingTable, (const void *)(uintptr_t)encoding)) : *commonConverterSlot); if (NULL == converter) { @@ -638,7 +638,7 @@ static const _CFEncodingConverter *__CFGetConverter(uint32_t encoding) { *commonConverterSlot = converter; } } - __CFSpinUnlock(&lock); + OSSpinLockUnlock(&lock); } } @@ -768,7 +768,9 @@ uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const CFIndex localUsedLen; localUsedByteLen = 0; - while ((usedLen < numChars) && !localUsedByteLen && (localUsedLen = TO_BYTE_FALLBACK(converter, characters + usedLen, numChars - usedLen, NULL, 0, &localUsedByteLen))) usedLen += localUsedLen; + while ((usedLen < numChars && theUsedByteLen < maxByteLen) && !localUsedByteLen && (localUsedLen = TO_BYTE_FALLBACK(converter, characters + usedLen, numChars - usedLen, NULL, 0, &localUsedByteLen))) usedLen += localUsedLen; + + theUsedByteLen += localUsedByteLen; } if (usedLen < numChars) theResult = kCFStringEncodingInsufficientOutputBufferLength; break; @@ -797,7 +799,9 @@ uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const CFIndex localUsedLen; localUsedByteLen = 0; - while ((usedLen < numChars) && !localUsedByteLen && (localUsedLen = TO_BYTE_FALLBACK(converter, characters + usedLen, numChars - usedLen, NULL, 0, &localUsedByteLen))) usedLen += localUsedLen; + while ((usedLen < numChars && theUsedByteLen < maxByteLen) && !localUsedByteLen && (localUsedLen = TO_BYTE_FALLBACK(converter, characters + usedLen, numChars - usedLen, NULL, 0, &localUsedByteLen))) usedLen += localUsedLen; + + theUsedByteLen += localUsedByteLen; } if (usedLen < numChars) theResult = kCFStringEncodingInsufficientOutputBufferLength; } diff --git a/CFStringEncodingConverter.h b/CFStringEncodingConverter.h index 1803c32..f13331a 100644 --- a/CFStringEncodingConverter.h +++ b/CFStringEncodingConverter.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodingConverter.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTER__) diff --git a/CFStringEncodingConverterExt.h b/CFStringEncodingConverterExt.h index 16a1efe..27b1527 100644 --- a/CFStringEncodingConverterExt.h +++ b/CFStringEncodingConverterExt.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodingConverterExt.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERETEREXT__) diff --git a/CFStringEncodingConverterPriv.h b/CFStringEncodingConverterPriv.h index 175a1f3..456a4ce 100644 --- a/CFStringEncodingConverterPriv.h +++ b/CFStringEncodingConverterPriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodingConverterPriv.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTERPRIV__) diff --git a/CFStringEncodingDatabase.c b/CFStringEncodingDatabase.c index 06a206b..b9d93e1 100644 --- a/CFStringEncodingDatabase.c +++ b/CFStringEncodingDatabase.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodingDatabase.c - Copyright (c) 2005-2013, Apple Inc. All rights reserved. + Copyright (c) 2005-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -431,10 +431,10 @@ CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t co return (codepage - ISO8859CODEPAGE_BASE) + 0x0200; } else { static CFMutableDictionaryRef mappingTable = NULL; - static CFSpinLock_t lock = CFSpinLockInit; + static CFLock_t lock = CFLockInit; uintptr_t value; - __CFSpinLock(&lock); + __CFLock(&lock); if (NULL == mappingTable) { CFIndex index, count = sizeof(__CFKnownEncodingList) / sizeof(*__CFKnownEncodingList); @@ -444,7 +444,7 @@ CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t co if (0 != __CFWindowsCPList[index]) CFDictionarySetValue(mappingTable, (const void *)(uintptr_t)__CFWindowsCPList[index], (const void *)(uintptr_t)__CFKnownEncodingList[index]); } } - __CFSpinUnlock(&lock); + __CFUnlock(&lock); if (CFDictionaryGetValueIfPresent(mappingTable, (const void *)(uintptr_t)codepage, (const void **)&value)) return (CFStringEncoding)value; } @@ -527,7 +527,7 @@ CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *c CFStringEncoding encoding; CFIndex prefixLength; static CFMutableDictionaryRef mappingTable = NULL; - static CFSpinLock_t lock = CFSpinLockInit; + static CFLock_t lock = CFLockInit; prefixLength = strlen("iso-8859-"); if (0 == strncasecmp_l(canonicalName, "iso-8859-", prefixLength, NULL)) {// do ISO @@ -550,7 +550,7 @@ CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *c return __CFStringEncodingGetFromWindowsCodePage(encoding); } - __CFSpinLock(&lock); + __CFLock(&lock); if (NULL == mappingTable) { CFIndex index, count = sizeof(__CFKnownEncodingList) / sizeof(*__CFKnownEncodingList); @@ -574,7 +574,7 @@ CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *c if (NULL != __CFCanonicalNameList[index]) CFDictionarySetValue(mappingTable, (const void *)(uintptr_t)__CFCanonicalNameList[index], (const void *)(uintptr_t)__CFKnownEncodingList[index]); } } - __CFSpinUnlock(&lock); + __CFUnlock(&lock); if (0 == strncasecmp_l(canonicalName, "macintosh", sizeof("macintosh") - 1, NULL)) return kCFStringEncodingMacRoman; diff --git a/CFStringEncodingDatabase.h b/CFStringEncodingDatabase.h index c6bd0c9..de2d659 100644 --- a/CFStringEncodingDatabase.h +++ b/CFStringEncodingDatabase.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -26,7 +26,7 @@ * CoreFoundation * * Created by Aki Inoue on 07/12/05. - * Copyright (c) 2007-2013, Apple Inc. All rights reserved. + * Copyright (c) 2007-2014, Apple Inc. All rights reserved. * */ diff --git a/CFStringEncodingExt.h b/CFStringEncodingExt.h index 06668f1..c7ab4b3 100644 --- a/CFStringEncodingExt.h +++ b/CFStringEncodingExt.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodingExt.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGEXT__) diff --git a/CFStringEncodings.c b/CFStringEncodings.c index d19013e..a3d164e 100644 --- a/CFStringEncodings.c +++ b/CFStringEncodings.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringEncodings.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ diff --git a/CFStringScanner.c b/CFStringScanner.c index daff3e6..8298863 100644 --- a/CFStringScanner.c +++ b/CFStringScanner.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringScanner.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ diff --git a/CFStringUtilities.c b/CFStringUtilities.c index ea3939e..46e91a8 100644 --- a/CFStringUtilities.c +++ b/CFStringUtilities.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFStringUtilities.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -72,7 +72,15 @@ const CFStringEncoding* CFStringGetListOfAvailableEncodings() { CFStringRef CFStringGetNameOfEncoding(CFStringEncoding theEncoding) { static CFMutableDictionaryRef mappingTable = NULL; - CFStringRef theName = mappingTable ? (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)(uintptr_t)theEncoding) : NULL; + static OSSpinLock mappingTableLock = OS_SPINLOCK_INIT; + + CFStringRef theName = NULL; + + if (mappingTable) { + OSSpinLockLock(&mappingTableLock); + theName = (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)(uintptr_t)theEncoding); + OSSpinLockUnlock(&mappingTableLock); + } if (!theName) { const char *encodingName = __CFStringEncodingGetName(theEncoding); @@ -82,10 +90,23 @@ CFStringRef CFStringGetNameOfEncoding(CFStringEncoding theEncoding) { } if (theName) { - if (!mappingTable) mappingTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, (const CFDictionaryKeyCallBacks *)NULL, &kCFTypeDictionaryValueCallBacks); + OSSpinLockLock(&mappingTableLock); - CFDictionaryAddValue(mappingTable, (const void*)(uintptr_t)theEncoding, (const void*)theName); - CFRelease(theName); + CFStringRef result = NULL; + if (!mappingTable) { + mappingTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, (const CFDictionaryKeyCallBacks *)NULL, &kCFTypeDictionaryValueCallBacks); + } else { // Check to see if this got in the dictionary in the meantime + result = (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)(uintptr_t)theEncoding); + } + if (!result) { // If not, add it in + CFDictionaryAddValue(mappingTable, (const void*)(uintptr_t)theEncoding, (const void*)theName); + OSSpinLockUnlock(&mappingTableLock); + CFRelease(theName); + } else { // Otherwise use the one already in there + OSSpinLockUnlock(&mappingTableLock); + CFRelease(theName); + theName = result; + } } } @@ -123,9 +144,9 @@ CFStringRef CFStringConvertEncodingToIANACharSetName(CFStringEncoding encoding) CFStringRef name = NULL; CFIndex value = encoding; static CFMutableDictionaryRef mappingTable = NULL; - static CFSpinLock_t lock = CFSpinLockInit; + static CFLock_t lock = CFLockInit; - __CFSpinLock(&lock); + __CFLock(&lock); name = ((NULL == mappingTable) ? NULL : (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)value)); if (NULL == name) { @@ -144,7 +165,7 @@ CFStringRef CFStringConvertEncodingToIANACharSetName(CFStringEncoding encoding) CFRelease(name); } } - __CFSpinUnlock(&lock); + __CFUnlock(&lock); return name; } @@ -386,7 +407,7 @@ static UCollator *__CFStringCreateCollator(CFLocaleRef compareLocale) { static UCollator *__CFDefaultCollators[kCFMaxCachedDefaultCollators]; static CFIndex __CFDefaultCollatorsCount = 0; static const void *__CFDefaultCollatorLocale = NULL; -static CFSpinLock_t __CFDefaultCollatorLock = CFSpinLockInit; +static CFLock_t __CFDefaultCollatorLock = CFLockInit; static UCollator *__CFStringCopyDefaultCollator(CFLocaleRef compareLocale) { CFLocaleRef currentLocale = NULL; @@ -400,14 +421,14 @@ static UCollator *__CFStringCopyDefaultCollator(CFLocaleRef compareLocale) { } } - __CFSpinLock(&__CFDefaultCollatorLock); + __CFLock(&__CFDefaultCollatorLock); if ((NULL != currentLocale) && (__CFDefaultCollatorLocale != currentLocale)) { while (__CFDefaultCollatorsCount > 0) ucol_close(__CFDefaultCollators[--__CFDefaultCollatorsCount]); __CFDefaultCollatorLocale = CFRetain(currentLocale); } if (__CFDefaultCollatorsCount > 0) collator = __CFDefaultCollators[--__CFDefaultCollatorsCount]; - __CFSpinUnlock(&__CFDefaultCollatorLock); + __CFUnlock(&__CFDefaultCollatorLock); if (NULL == collator) { collator = __CFStringCreateCollator(compareLocale); @@ -423,12 +444,12 @@ static void __collatorFinalize(UCollator *collator) { CFLocaleRef locale = _CFGetTSD(__CFTSDKeyCollatorLocale); _CFSetTSD(__CFTSDKeyCollatorUCollator, NULL, NULL); _CFSetTSD(__CFTSDKeyCollatorLocale, NULL, NULL); - __CFSpinLock(&__CFDefaultCollatorLock); + __CFLock(&__CFDefaultCollatorLock); if ((__CFDefaultCollatorLocale == locale) && (__CFDefaultCollatorsCount < kCFMaxCachedDefaultCollators)) { __CFDefaultCollators[__CFDefaultCollatorsCount++] = collator; collator = NULL; } - __CFSpinUnlock(&__CFDefaultCollatorLock); + __CFUnlock(&__CFDefaultCollatorLock); if (NULL != collator) ucol_close(collator); if (locale) CFRelease(locale); } diff --git a/CFSystemDirectories.c b/CFSystemDirectories.c index c3fdfc1..959a4b1 100644 --- a/CFSystemDirectories.c +++ b/CFSystemDirectories.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFSystemDirectories.c - Copyright (c) 1997-2013, Apple Inc. All rights reserved. + Copyright (c) 1997-2014, Apple Inc. All rights reserved. Responsibility: Kevin Perry */ diff --git a/CFTimeZone.c b/CFTimeZone.c index 8c0a7e1..dfe6d68 100644 --- a/CFTimeZone.c +++ b/CFTimeZone.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFTimeZone.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -89,40 +89,40 @@ CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification, "kCFTimeZoneSy static CFTimeZoneRef __CFTimeZoneSystem = NULL; static CFTimeZoneRef __CFTimeZoneDefault = NULL; static CFDictionaryRef __CFTimeZoneAbbreviationDict = NULL; -static CFSpinLock_t __CFTimeZoneAbbreviationLock = CFSpinLockInit; +static CFLock_t __CFTimeZoneAbbreviationLock = CFLockInit; static CFMutableDictionaryRef __CFTimeZoneCompatibilityMappingDict = NULL; -static CFSpinLock_t __CFTimeZoneCompatibilityMappingLock = CFSpinLockInit; +static CFLock_t __CFTimeZoneCompatibilityMappingLock = CFLockInit; static CFArrayRef __CFKnownTimeZoneList = NULL; static CFMutableDictionaryRef __CFTimeZoneCache = NULL; -static CFSpinLock_t __CFTimeZoneGlobalLock = CFSpinLockInit; +static CFLock_t __CFTimeZoneGlobalLock = CFLockInit; #if DEPLOYMENT_TARGET_WINDOWS static CFDictionaryRef __CFTimeZoneWinToOlsonDict = NULL; -static CFSpinLock_t __CFTimeZoneWinToOlsonLock = CFSpinLockInit; +static CFLock_t __CFTimeZoneWinToOlsonLock = CFLockInit; #endif CF_INLINE void __CFTimeZoneLockGlobal(void) { - __CFSpinLock(&__CFTimeZoneGlobalLock); + __CFLock(&__CFTimeZoneGlobalLock); } CF_INLINE void __CFTimeZoneUnlockGlobal(void) { - __CFSpinUnlock(&__CFTimeZoneGlobalLock); + __CFUnlock(&__CFTimeZoneGlobalLock); } CF_INLINE void __CFTimeZoneLockAbbreviations(void) { - __CFSpinLock(&__CFTimeZoneAbbreviationLock); + __CFLock(&__CFTimeZoneAbbreviationLock); } CF_INLINE void __CFTimeZoneUnlockAbbreviations(void) { - __CFSpinUnlock(&__CFTimeZoneAbbreviationLock); + __CFUnlock(&__CFTimeZoneAbbreviationLock); } CF_INLINE void __CFTimeZoneLockCompatibilityMapping(void) { - __CFSpinLock(&__CFTimeZoneCompatibilityMappingLock); + __CFLock(&__CFTimeZoneCompatibilityMappingLock); } CF_INLINE void __CFTimeZoneUnlockCompatibilityMapping(void) { - __CFSpinUnlock(&__CFTimeZoneCompatibilityMappingLock); + __CFUnlock(&__CFTimeZoneCompatibilityMappingLock); } #if DEPLOYMENT_TARGET_WINDOWS @@ -479,11 +479,9 @@ static const CFRuntimeClass __CFTimeZoneClass = { __CFTimeZoneCopyDescription }; -CF_PRIVATE void __CFTimeZoneInitialize(void) { - __kCFTimeZoneTypeID = _CFRuntimeRegisterClass(&__CFTimeZoneClass); -} - CFTypeID CFTimeZoneGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFTimeZoneTypeID = _CFRuntimeRegisterClass(&__CFTimeZoneClass); }); return __kCFTimeZoneTypeID; } @@ -655,11 +653,11 @@ static const char *__CFTimeZoneWinToOlsonDefaults = " "; CF_INLINE void __CFTimeZoneLockWinToOlson(void) { - __CFSpinLock(&__CFTimeZoneWinToOlsonLock); + __CFLock(&__CFTimeZoneWinToOlsonLock); } CF_INLINE void __CFTimeZoneUnlockWinToOlson(void) { - __CFSpinUnlock(&__CFTimeZoneWinToOlsonLock); + __CFUnlock(&__CFTimeZoneWinToOlsonLock); } CFDictionaryRef CFTimeZoneCopyWinToOlsonDictionary(void) { @@ -706,8 +704,8 @@ CFTimeZoneRef CFTimeZoneCreateWithWindowsName(CFAllocatorRef allocator, CFString extern CFStringRef _CFGetWindowsAppleSystemLibraryDirectory(void); void __InitTZStrings(void) { - static CFSpinLock_t __CFTZDirLock = CFSpinLockInit; - __CFSpinLock(&__CFTZDirLock); + static CFLock_t __CFTZDirLock = CFLockInit; + __CFLock(&__CFTZDirLock); if (!__tzZoneInfo) { CFStringRef winDir = _CFGetWindowsAppleSystemLibraryDirectory(); __tzZoneInfo = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\\etc\\zoneinfo"), winDir); @@ -721,7 +719,7 @@ void __InitTZStrings(void) { strcat(__tzDir, "\\zone.tab"); } } - __CFSpinUnlock(&__CFTZDirLock); + __CFUnlock(&__CFTZDirLock); } #endif diff --git a/CFTimeZone.h b/CFTimeZone.h index d31faab..b042cac 100644 --- a/CFTimeZone.h +++ b/CFTimeZone.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFTimeZone.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFTIMEZONE__) diff --git a/CFTree.c b/CFTree.c index 8579864..86dac1f 100644 --- a/CFTree.c +++ b/CFTree.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFTree.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -136,11 +136,9 @@ static const CFRuntimeClass __CFTreeClass = { __CFTreeCopyDescription }; -CF_PRIVATE void __CFTreeInitialize(void) { - __kCFTreeTypeID = _CFRuntimeRegisterClass(&__CFTreeClass); -} - CFTypeID CFTreeGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFTreeTypeID = _CFRuntimeRegisterClass(&__CFTreeClass); }); return __kCFTreeTypeID; } @@ -151,7 +149,7 @@ CFTreeRef CFTreeCreate(CFAllocatorRef allocator, const CFTreeContext *context) { CFAssert1(NULL != context, __kCFLogAssertion, "%s(): pointer to context may not be NULL", __PRETTY_FUNCTION__); CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__); size = sizeof(struct __CFTree) - sizeof(CFRuntimeBase); - memory = (CFTreeRef)_CFRuntimeCreateInstance(allocator, __kCFTreeTypeID, size, NULL); + memory = (CFTreeRef)_CFRuntimeCreateInstance(allocator, CFTreeGetTypeID(), size, NULL); if (NULL == memory) { return NULL; } @@ -168,7 +166,7 @@ CFTreeRef CFTreeCreate(CFAllocatorRef allocator, const CFTreeContext *context) { CFIndex CFTreeGetChildCount(CFTreeRef tree) { SInt32 cnt = 0; - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); tree = tree->_child; while (NULL != tree) { cnt++; @@ -178,22 +176,22 @@ CFIndex CFTreeGetChildCount(CFTreeRef tree) { } CFTreeRef CFTreeGetParent(CFTreeRef tree) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); return tree->_parent; } CFTreeRef CFTreeGetNextSibling(CFTreeRef tree) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); return tree->_sibling; } CFTreeRef CFTreeGetFirstChild(CFTreeRef tree) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); return tree->_child; } CFTreeRef CFTreeFindRoot(CFTreeRef tree) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); while (NULL != tree->_parent) { tree = tree->_parent; } @@ -202,7 +200,7 @@ CFTreeRef CFTreeFindRoot(CFTreeRef tree) { void CFTreeGetContext(CFTreeRef tree, CFTreeContext *context) { const struct __CFTreeCallBacks *cb; - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__); cb = __CFTreeGetCallBacks(tree); context->version = 0; @@ -254,7 +252,7 @@ void CFTreeSetContext(CFTreeRef tree, const CFTreeContext *context) { #if 0 CFTreeRef CFTreeFindNextSibling(CFTreeRef tree, const void *info) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); tree = tree->_sibling; while (NULL != tree) { if (info == tree->_context.info || (tree->_context.equal && tree->_context.equal(info, tree->_context.info))) { @@ -266,7 +264,7 @@ CFTreeRef CFTreeFindNextSibling(CFTreeRef tree, const void *info) { } CFTreeRef CFTreeFindFirstChild(CFTreeRef tree, const void *info) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); tree = tree->_child; while (NULL != tree) { if (info == tree->_context.info || (tree->_context.equal && tree->_context.equal(info, tree->_context.info))) { @@ -278,7 +276,7 @@ CFTreeRef CFTreeFindFirstChild(CFTreeRef tree, const void *info) { } CFTreeRef CFTreeFind(CFTreeRef tree, const void *info) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); if (info == tree->_context.info || (tree->_context.equal && tree->_context.equal(info, tree->info))) { return tree; } @@ -295,7 +293,7 @@ CFTreeRef CFTreeFind(CFTreeRef tree, const void *info) { #endif CFTreeRef CFTreeGetChildAtIndex(CFTreeRef tree, CFIndex idx) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); tree = tree->_child; while (NULL != tree) { if (0 == idx) return tree; @@ -306,7 +304,7 @@ CFTreeRef CFTreeGetChildAtIndex(CFTreeRef tree, CFIndex idx) { } void CFTreeGetChildren(CFTreeRef tree, CFTreeRef *children) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); tree = tree->_child; while (NULL != tree) { *children++ = tree; @@ -315,7 +313,7 @@ void CFTreeGetChildren(CFTreeRef tree, CFTreeRef *children) { } void CFTreeApplyFunctionToChildren(CFTreeRef tree, CFTreeApplierFunction applier, void *context) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); CFAssert1(NULL != applier, __kCFLogAssertion, "%s(): pointer to applier function may not be NULL", __PRETTY_FUNCTION__); tree = tree->_child; while (NULL != tree) { @@ -325,8 +323,8 @@ void CFTreeApplyFunctionToChildren(CFTreeRef tree, CFTreeApplierFunction applier } void CFTreePrependChild(CFTreeRef tree, CFTreeRef newChild) { - __CFGenericValidateType(tree, __kCFTreeTypeID); - __CFGenericValidateType(newChild, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); + __CFGenericValidateType(newChild, CFTreeGetTypeID()); CFAssert1(NULL == newChild->_parent, __kCFLogAssertion, "%s(): must remove newChild from previous parent first", __PRETTY_FUNCTION__); CFAssert1(NULL == newChild->_sibling, __kCFLogAssertion, "%s(): must remove newChild from previous parent first", __PRETTY_FUNCTION__); if (!kCFUseCollectableAllocator) CFRetain(newChild); @@ -340,8 +338,8 @@ void CFTreePrependChild(CFTreeRef tree, CFTreeRef newChild) { void CFTreeAppendChild(CFTreeRef tree, CFTreeRef newChild) { CFAllocatorRef allocator; - __CFGenericValidateType(tree, __kCFTreeTypeID); - __CFGenericValidateType(newChild, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); + __CFGenericValidateType(newChild, CFTreeGetTypeID()); CFAssert1(NULL == newChild->_parent, __kCFLogAssertion, "%s(): must remove newChild from previous parent first", __PRETTY_FUNCTION__); CFAssert1(NULL == newChild->_sibling, __kCFLogAssertion, "%s(): must remove newChild from previous parent first", __PRETTY_FUNCTION__); if (newChild->_parent) { @@ -361,8 +359,8 @@ void CFTreeAppendChild(CFTreeRef tree, CFTreeRef newChild) { void CFTreeInsertSibling(CFTreeRef tree, CFTreeRef newSibling) { CFAllocatorRef allocator; - __CFGenericValidateType(tree, __kCFTreeTypeID); - __CFGenericValidateType(newSibling, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); + __CFGenericValidateType(newSibling, CFTreeGetTypeID()); CFAssert1(NULL != tree->_parent, __kCFLogAssertion, "%s(): tree must have a parent", __PRETTY_FUNCTION__); CFAssert1(NULL == newSibling->_parent, __kCFLogAssertion, "%s(): must remove newSibling from previous parent first", __PRETTY_FUNCTION__); CFAssert1(NULL == newSibling->_sibling, __kCFLogAssertion, "%s(): must remove newSibling from previous parent first", __PRETTY_FUNCTION__); @@ -379,7 +377,7 @@ void CFTreeInsertSibling(CFTreeRef tree, CFTreeRef newSibling) { } void CFTreeRemove(CFTreeRef tree) { - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); if (NULL != tree->_parent) { if (tree == tree->_parent->_child) { __CFAssignWithWriteBarrier((void **)&tree->_parent->_child, tree->_sibling); @@ -406,7 +404,7 @@ void CFTreeRemove(CFTreeRef tree) { void CFTreeRemoveAllChildren(CFTreeRef tree) { CFTreeRef nextChild; - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); nextChild = tree->_child; tree->_child = NULL; tree->_rightmostChild = NULL; @@ -432,7 +430,7 @@ static CFComparisonResult __CFTreeCompareValues(const void *v1, const void *v2, void CFTreeSortChildren(CFTreeRef tree, CFComparatorFunction comparator, void *context) { CFIndex children; - __CFGenericValidateType(tree, __kCFTreeTypeID); + __CFGenericValidateType(tree, CFTreeGetTypeID()); CFAssert1(NULL != comparator, __kCFLogAssertion, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__); children = CFTreeGetChildCount(tree); if (1 < children) { diff --git a/CFTree.h b/CFTree.h index c69b005..4a86686 100644 --- a/CFTree.h +++ b/CFTree.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFTree.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /*! @header CFTree diff --git a/CFURL.c b/CFURL.c index b1f549e..dbb9673 100644 --- a/CFURL.c +++ b/CFURL.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFURL.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. - Responsibility: John Iarocci + Copyright (c) 1998-2014, Apple Inc. All rights reserved. + Responsibility: Jim Luther/Chris Linn */ #include @@ -58,10 +58,6 @@ #endif -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -static CFArrayRef HFSPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir); -static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute); -#endif static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute); static CFStringRef WindowsPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute); static CFStringRef POSIXPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDirectory, Boolean isAbsolute, Boolean *posixAndUrlPathsMatch); @@ -95,7 +91,7 @@ CONST_STRING_DECL(kCFURLLocalhost, "localhost") #if DEBUG_URL_MEMORY_USAGE static uint numURLs = 0; // number of URLs allocated static uint numDealloced = 0; // number of URLs deallocated -static uint numFileURLsParsed = 0; // number of URLs created from a string which had to be parsed +static uint numURLsParsed = 0; // number of URLs created from a string which had to be parsed static uint numExtraDataAllocated = 0; // number of URLs with additional data -- either because URLHandle was used, or because a sanitizedString was needed static uint numURLsWithBaseURL = 0; // number of URLs with a baseURL static uint numNonUTF8EncodedURLs = 0; // number of URLs that don't have UTF8 encoding @@ -112,6 +108,7 @@ static uint numNonUTF8EncodedURLs = 0; // number of URLs that don't have UT #define HAS_PARAMETERS (0x00000040) #define HAS_QUERY (0x00000080) #define HAS_FRAGMENT (0x00000100) +#define MAX_COMPONENTS 9 // various boolean flags #define IS_IPV6_ENCODED (0x00000400) #define IS_DIRECTORY (0x00000800) @@ -124,7 +121,7 @@ static uint numNonUTF8EncodedURLs = 0; // number of URLs that don't have UT #define SCHEME_TYPE_MASK (0xE0000000) #define SCHEME_SHIFT 29 enum { - kHasUncommonScheme = 0, + kHasUncommonScheme = 0, // scheme is uncommon or scheme isn't in the canonical form (all lower case) kHasHttpScheme = 1, kHasHttpsScheme = 2, kHasFileScheme = 3, @@ -193,9 +190,9 @@ struct __CFURL { CFStringEncoding _encoding; // The encoding to use when asked to remove percent escapes CFStringRef _string; // Never NULL CFURLRef _base; - CFRange *_ranges; struct _CFURLAdditionalData* _extra; void *_resourceInfo; // For use by CoreServicesInternal to cache property values. Retained and released by CFURL. + CFRange _ranges[1]; // variable length (1 to 9) array of ranges }; @@ -325,20 +322,16 @@ CF_INLINE void _setSchemeTypeInFlags(UInt32 *flags, UInt32 schemeType) static Boolean _pathHasFileIDPrefix(CFStringRef path); static CFStringRef _resolveFileSystemPaths(CFStringRef relativePath, CFStringRef basePath, Boolean baseIsDir, CFURLPathStyle fsType, CFAllocatorRef alloc); -static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef base, UInt32 *flags, CFRange **range); -static CFRange _rangeForComponent(UInt32 flags, CFRange *ranges, UInt32 compFlag); -static CFRange _netLocationRange(UInt32 flags, CFRange *ranges); +static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef baseURL, UInt32 *theFlags, CFRange *packedRanges, uint8_t *numberOfRanges); +static CFRange _rangeForComponent(UInt32 flags, const CFRange *ranges, UInt32 compFlag); +static CFRange _netLocationRange(UInt32 flags, const CFRange *ranges); static UInt32 _firstResourceSpecifierFlag(UInt32 flags); static void computeSanitizedString(CFURLRef url); static CFStringRef correctedComponent(CFStringRef component, UInt32 compFlag, CFStringEncoding enc); -static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, CFRange *baseRanges); +static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, const CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, const CFRange *baseRanges); static CFStringRef _resolvedPath(UniChar *pathStr, UniChar *end, UniChar pathDelimiter, Boolean stripLeadingDotDots, Boolean stripTrailingDelimiter, CFAllocatorRef alloc); -CF_INLINE void _parseComponentsOfURL(CFURLRef url) { - _parseComponents(CFGetAllocator(url), url->_string, url->_base, &(((struct __CFURL *)url)->_flags), &(((struct __CFURL *)url)->_ranges)); -} - enum { VALID = 1, ALPHA = 2, @@ -489,11 +482,12 @@ CF_INLINE Boolean scheme_valid(UniChar ch) { CF_INLINE Boolean isALPHA(UniChar ch) { return (ch <= 127) ? ((sURLValidCharacters[ch] & ALPHA) != 0) : false; } - +/* + Currently unused, but left in for symmetry/informative purposes CF_INLINE Boolean isPathLegalCharacter(UniChar ch) { return (ch <= 127) ? ((sURLValidCharacters[ch] & PATHVALID) != 0) : false; } - +*/ CF_INLINE Boolean isHexDigit(UniChar ch) { return (ch <= 127) ? ((sURLValidCharacters[ch] & HEXDIGIT) != 0) : false; } @@ -1590,7 +1584,7 @@ static CFStringRef __CFURLCopyDescription(CFTypeRef cf) { #if DEBUG_URL_MEMORY_USAGE extern __attribute((used)) void __CFURLDumpMemRecord(void) { - syslog(LOG_ERR, "%d URLs created; %d destroyed; %d URLs parsed; %d urls had 'extra' data allocated; %d had base urls; %d were not UTF8 encoded", numURLs, numDealloced, numFileURLsParsed, numExtraDataAllocated, numURLsWithBaseURL, numNonUTF8EncodedURLs); + syslog(LOG_ERR, "%d URLs created; %d destroyed; %d URLs parsed; %d urls had 'extra' data allocated; %d had base urls; %d were not UTF8 encoded", numURLs, numDealloced, numURLsParsed, numExtraDataAllocated, numURLsWithBaseURL, numNonUTF8EncodedURLs); } #endif @@ -1604,7 +1598,6 @@ static void __CFURLDeallocate(CFTypeRef cf) { #endif if (url->_string) CFRelease(url->_string); // GC: 3879914 if (url->_base) CFRelease(url->_base); - if (url->_ranges) CFAllocatorDeallocate(alloc, url->_ranges); CFStringRef sanitizedString = _getSanitizedString(url); if (sanitizedString) CFRelease(sanitizedString); if ( url->_extra != NULL ) CFAllocatorDeallocate( alloc, url->_extra ); @@ -1627,17 +1620,15 @@ static const CFRuntimeClass __CFURLClass = { NULL, // refcount }; -CF_PRIVATE void __CFURLInitialize(void) { - __kCFURLTypeID = _CFRuntimeRegisterClass(&__CFURLClass); -} - /* Toll-free bridging support; get the true CFURL from an NSURL */ CF_INLINE CFURLRef _CFURLFromNSURL(CFURLRef url) { - CF_OBJC_FUNCDISPATCHV(__kCFURLTypeID, CFURLRef, (NSURL *)url, _cfurl); + CF_OBJC_FUNCDISPATCHV(CFURLGetTypeID(), CFURLRef, (NSURL *)url, _cfurl); return url; } CFTypeID CFURLGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFURLTypeID = _CFRuntimeRegisterClass(&__CFURLClass); }); return __kCFURLTypeID; } @@ -1647,7 +1638,7 @@ CF_PRIVATE void CFShowURL(CFURLRef url) { return; } fprintf(stdout, "{", (const void*)url); - if (CF_IS_OBJC(__kCFURLTypeID, url)) { + if (CF_IS_OBJC(CFURLGetTypeID(), url)) { fprintf(stdout, "ObjC bridged object}\n"); return; } @@ -1719,17 +1710,18 @@ static void constructBuffers(CFAllocatorRef alloc, CFStringRef string, UInt8 *in } } -static void _parseComponentsCString(CFAllocatorRef alloc, CFURLRef baseURL, UInt32 *theFlags, CFRange **range, CFIndex cfStringLength, const char *characterArray) +static void _parseComponentsCString(CFAllocatorRef alloc, CFURLRef baseURL, CFIndex cfStringLength, const char *characterArray, UInt32 *theFlags, CFRange *packedRanges, uint8_t *numberOfRanges) #define CFURL_INCLUDE_PARSE_COMPONENTS #include "CFURL.inc.h" #undef CFURL_INCLUDE_PARSE_COMPONENTS -static void _parseComponentsUString(CFAllocatorRef alloc, CFURLRef baseURL, UInt32 *theFlags, CFRange **range, CFIndex cfStringLength, const UniChar *characterArray) +static void _parseComponentsUString(CFAllocatorRef alloc, CFURLRef baseURL, CFIndex cfStringLength, const UniChar *characterArray, UInt32 *theFlags, CFRange *packedRanges, uint8_t *numberOfRanges) #define CFURL_INCLUDE_PARSE_COMPONENTS #include "CFURL.inc.h" #undef CFURL_INCLUDE_PARSE_COMPONENTS -static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef baseURL, UInt32 *theFlags, CFRange **range) { +static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef baseURL, UInt32 *theFlags, CFRange *packedRanges, uint8_t *numberOfRanges) +{ CFIndex cfStringLength = CFStringGetLength(string); Boolean useCString, freeCharacters; const char *cstring = NULL; @@ -1740,10 +1732,10 @@ static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef constructBuffers(alloc, string, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); if (useCString) { - _parseComponentsCString(alloc, baseURL, theFlags, range, cfStringLength, cstring); + _parseComponentsCString(alloc, baseURL, cfStringLength, cstring, theFlags, packedRanges, numberOfRanges); } else { - _parseComponentsUString(alloc, baseURL, theFlags, range, cfStringLength, ustring); + _parseComponentsUString(alloc, baseURL, cfStringLength, ustring, theFlags, packedRanges, numberOfRanges); } if (freeCharacters) { @@ -1861,7 +1853,12 @@ static CFStringRef correctedComponent(CFStringRef comp, UInt32 compFlag, CFStrin } -CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator) { +static struct __CFURL * _CFURLAlloc(CFAllocatorRef allocator, uint8_t numberOfRanges); +static CFURLRef _CFURLCreateWithURLString(CFAllocatorRef allocator, CFStringRef string, Boolean checkForLegalCharacters, CFURLRef baseURL); +static CFURLRef _CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef fileSystemPath, CFURLPathStyle pathStyle, Boolean isDirectory, CFURLRef baseURL); +static CFURLRef _CFURLCreateWithFileSystemRepresentation(CFAllocatorRef allocator, const UInt8 *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL); + +static struct __CFURL * _CFURLAlloc(CFAllocatorRef allocator, uint8_t numberOfRanges) { struct __CFURL *url; #if DEBUG_URL_MEMORY_USAGE numURLs ++; @@ -1869,39 +1866,19 @@ CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator) { // __CFURLDumpMemRecord(); // } #endif - url = (struct __CFURL *)_CFRuntimeCreateInstance(allocator, __kCFURLTypeID, sizeof(struct __CFURL) - sizeof(CFRuntimeBase), NULL); + CFIndex extraBytes = offsetof(struct __CFURL, _ranges[numberOfRanges]) - sizeof(CFRuntimeBase); + url = (struct __CFURL *)_CFRuntimeCreateInstance(allocator, CFURLGetTypeID(), extraBytes, NULL); if (url) { url->_flags = 0; url->_encoding = kCFStringEncodingUTF8; url->_string = NULL; url->_base = NULL; - url->_ranges = NULL; url->_extra = NULL; url->_resourceInfo = NULL; } return url; } -// It is the caller's responsibility to guarantee that if URLString is absolute, base is NULL. This is necessary to avoid duplicate processing for file system URLs, which had to decide whether to compute the cwd for the base; we don't want to duplicate that work. If parseURL is false, the caller is responsible for parsing the URL. -static void _CFURLInit(struct __CFURL *url, CFStringRef URLString, CFURLRef base, Boolean parseURL) { - - // Coming in, the url has its allocator flag properly set, and its base initialized, and nothing else. - url->_string = CFStringCreateCopy(CFGetAllocator(url), URLString); - url->_base = base ? CFURLCopyAbsoluteURL(base) : NULL; - -#if DEBUG_URL_MEMORY_USAGE - if ( url->_base ) { - numURLsWithBaseURL ++; - } -#endif - if ( parseURL ) { -#if DEBUG_URL_MEMORY_USAGE - numFileURLsParsed++; -#endif - _parseComponentsOfURL(url); - } -} - static Boolean _CFStringIsLegalURLString(CFStringRef string) { Boolean result = true; if ( string ) { @@ -1993,16 +1970,15 @@ static Boolean _CFStringIsLegalURLString(CFStringRef string) { } /* initializes a URL object with a URL string */ -CF_EXPORT Boolean _CFURLInitWithURLString(CFURLRef uninitializedURL, CFStringRef string, Boolean checkForLegalCharacters, CFURLRef baseURL) +static CFURLRef _CFURLCreateWithURLString(CFAllocatorRef allocator, CFStringRef string, Boolean checkForLegalCharacters, CFURLRef baseURL) { + struct __CFURL *result = NULL; #if DEBUG_URL_INITIALIZER_LOGGING CFStringRef input_string = string ? CFRetain(string) : NULL; Boolean input_checkForLegalCharacters = checkForLegalCharacters; CFURLRef input_baseURL = baseURL ? CFRetain(baseURL) : NULL; #endif - Boolean result = checkForLegalCharacters ? _CFStringIsLegalURLString(string) : true; - - if ( result ) { + if ( checkForLegalCharacters ? _CFStringIsLegalURLString(string) : true ) { // determine if URL is absolute (i.e. it has a scheme and the scheme characters are valid CFStringInlineBuffer stringBuffer; CFIndex length = CFStringGetLength(string); @@ -2028,16 +2004,38 @@ CF_EXPORT Boolean _CFURLInitWithURLString(CFURLRef uninitializedURL, CFStringRef } } if ( isAbsolute ) { + baseURL = NULL; break; } idx += rangeLength; } } - _CFURLInit((struct __CFURL *)uninitializedURL, string, isAbsolute ? NULL : baseURL, TRUE); +#if DEBUG_URL_MEMORY_USAGE + numURLsParsed++; +#endif + // get the range flags, ranges and range count from the parser + uint8_t numberOfRanges; + UInt32 flags = 0; + CFRange packedRanges[MAX_COMPONENTS]; + + _parseComponents(allocator, string, baseURL, &flags, packedRanges, &numberOfRanges); + // allocate the URL object with the appropriate number of ranges + result = _CFURLAlloc(allocator, numberOfRanges); + if ( result ) { + result->_flags = flags; + memcpy(result->_ranges, packedRanges, sizeof(CFRange) * numberOfRanges); + result->_string = CFStringCreateCopy(allocator, string); + result->_base = baseURL ? CFURLCopyAbsoluteURL(baseURL) : NULL; +#if DEBUG_URL_MEMORY_USAGE + if ( url->_base ) { + numURLsWithBaseURL ++; + } +#endif + } } #if DEBUG_URL_INITIALIZER_LOGGING - CFLog(kCFLogLevelError, CFSTR("_CFURLInitWithURLString (in) string '%@', checkForLegalCharacters %@, baseURL %@\n\t_CFURLInitWithURLString (out) result %@, url %@"), input_string, input_checkForLegalCharacters ? CFSTR("YES") : CFSTR("NO"), input_baseURL, result ? CFSTR("YES") : CFSTR("NO"), uninitializedURL); + CFLog(kCFLogLevelError, CFSTR("_CFURLCreateWithURLString (in) string '%@', checkForLegalCharacters %@, baseURL %@\n\t_CFURLCreateWithURLString (out) result %@"), input_string, input_checkForLegalCharacters ? CFSTR("YES") : CFSTR("NO"), input_baseURL, result); if ( input_string ) { CFRelease(input_string); } @@ -2049,7 +2047,7 @@ CF_EXPORT Boolean _CFURLInitWithURLString(CFURLRef uninitializedURL, CFStringRef } /* initializes a URL object with a file system path */ -CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStringRef fileSystemPath, CFURLPathStyle pathStyle, Boolean isDirectory, CFURLRef baseURL) +static CFURLRef _CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef fileSystemPath, CFURLPathStyle pathStyle, Boolean isDirectory, CFURLRef baseURL) { #if DEBUG_URL_INITIALIZER_LOGGING CFStringRef input_fileSystemPath = fileSystemPath ? CFRetain(fileSystemPath) : NULL; @@ -2057,29 +2055,30 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStri Boolean input_isDirectory = isDirectory; CFURLRef input_baseURL = baseURL ? CFRetain(baseURL) : NULL; #endif - Boolean result = false; CFAssert1(fileSystemPath != NULL, __kCFLogAssertion, "%s(): NULL path string not permitted", __PRETTY_FUNCTION__); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated" CFAssert2(pathStyle == kCFURLPOSIXPathStyle || pathStyle == kCFURLHFSPathStyle || pathStyle == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, pathStyle); #pragma GCC diagnostic pop - struct __CFURL *url = (struct __CFURL *)uninitializedURL; - CFAllocatorRef alloc = CFGetAllocator(uninitializedURL); + struct __CFURL *result = NULL; CFStringRef urlString = NULL; Boolean isAbsolute; Boolean isFileReferencePath = false; Boolean posixAndUrlPathsMatch = false; - UniChar pathDelim = '\0'; Boolean releaseBaseURL = false; CFIndex len = CFStringGetLength(fileSystemPath); if (len > 0) { - // determine if fileSystemPath is an absolute path and what pathDelim we're using + // Determine if fileSystemPath is an absolute path. If kCFURLPOSIXPathStyle, determine if it is a file reference path. + // Then, convert the fileSystemPath to a urlString. The urlString returned will have a pathDelim at the end if isDirectory + // was true and no pathDelim if isDirectory was false (unless the urlPath is "/"). + // If isAbsolute, "file://" will be prepended to the urlString. switch (pathStyle) { case kCFURLPOSIXPathStyle: - pathDelim = '/'; - isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(fileSystemPath, 0) == pathDelim); + isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(fileSystemPath, 0) == '/'); + isFileReferencePath = _pathHasFileIDPrefix(fileSystemPath); + urlString = POSIXPathToURLPath(fileSystemPath, allocator, isDirectory, isAbsolute, &posixAndUrlPathsMatch); break; @@ -2092,45 +2091,28 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStri if ( isDrive) { // A disk designator - pathDelim = '\\'; isAbsolute = true; + urlString = WindowsPathToURLPath(fileSystemPath, allocator, isDirectory, isAbsolute); } else if ( firstChar == '\\' ) { // Either a UNC name of any format (which always start with two backslash characters), or an absolute path which starts with a single backslash. - pathDelim = '\\'; isAbsolute = true; + urlString = WindowsPathToURLPath(fileSystemPath, allocator, isDirectory, isAbsolute); } else if (firstChar == '/') { - // We switch to kCFURLPOSIXPathStyle here because there's probably code that passes POSIX paths in but wrongly specifies kCFURLWindowsPathStyle. + // there's probably code that passes POSIX paths in but wrongly specifies kCFURLWindowsPathStyle. pathStyle = kCFURLPOSIXPathStyle; - pathDelim = '/'; isAbsolute = true; + urlString = POSIXPathToURLPath(fileSystemPath, allocator, isDirectory, isAbsolute, &posixAndUrlPathsMatch); } else { - // We switch to kCFURLPOSIXPathStyle here because this is not an absolute path and we're going to set baseURL to the current working directory below, and so we assume the relative path will have to be combined with the base path at some point. - pathStyle = kCFURLPOSIXPathStyle; - pathDelim = '/'; isAbsolute = false; + urlString = WindowsPathToURLPath(fileSystemPath, allocator, isDirectory, isAbsolute); } } break; } - // Convert the fileSystemPath to a urlString and determine if it is a file reference path. - // The urlString returned will have a pathDelim at the end if isDirectory was true and no pathDelim if isDirectory was false (unless the urlPath is "/") - // If isAbsolute, "file://" will be prepended to the urlString. - switch (pathStyle) { - case kCFURLPOSIXPathStyle: - isFileReferencePath = _pathHasFileIDPrefix(fileSystemPath); - urlString = POSIXPathToURLPath(fileSystemPath, alloc, isDirectory, isAbsolute, &posixAndUrlPathsMatch); - break; - - - case kCFURLWindowsPathStyle: - urlString = WindowsPathToURLPath(fileSystemPath, alloc, isDirectory, isAbsolute); - break; - } - CFAssert2(urlString != NULL, __kCFLogAssertion, "%s(): Encountered malformed file system URL %@", __PRETTY_FUNCTION__, urlString); if ( urlString ) { @@ -2140,50 +2122,56 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStri } else if ( baseURL == NULL ) { // if fileSystemPath is a relative path and no baseURL is provided, use the current working directory - baseURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(uninitializedURL)); + baseURL = _CFURLCreateCurrentDirectoryURL(allocator); releaseBaseURL = true; } // override isDirectory if the path is to root - if ( !isDirectory && (len == 1) && (CFStringGetCharacterAtIndex(urlString, 0) == pathDelim) ) { + if ( !isDirectory && (len == 1) && (CFStringGetCharacterAtIndex(urlString, 0) == '/') ) { // Override isDirectory isDirectory = true; } - _CFURLInit(url, urlString, baseURL, FALSE); - - // hard coded parse - if ( isAbsolute ) { - UInt32 flags = IS_DECOMPOSABLE | HAS_SCHEME | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; - flags |= (isDirectory ? IS_DIRECTORY : 0); - if ( isFileReferencePath ) { - // if the URL is a file reference URL, don't set IS_CANONICAL_FILE_URL or POSIX_AND_URL_PATHS_MATCH - flags |= PATH_HAS_FILE_ID; - } - else { - // only posix style paths can be canonical because POSIXPathToURLPath() converts the string to file system representation - flags |= ((pathStyle == kCFURLPOSIXPathStyle) ? IS_CANONICAL_FILE_URL : 0); - flags |= (posixAndUrlPathsMatch ? POSIX_AND_URL_PATHS_MATCH : 0); - } - _setSchemeTypeInFlags(&flags, kHasFileScheme); - - if ( AddAuthorityToFileURL() ) { - url->_flags = flags | HAS_HOST; - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 3, 0); - url->_ranges[0] = CFRangeMake(0, 4); // scheme "file" - url->_ranges[1] = CFRangeMake(7, 9); // host "localhost" - url->_ranges[2] = CFRangeMake(16, CFStringGetLength(urlString)- 16); + // allocate the URL object with the appropriate number of ranges + result = _CFURLAlloc(allocator, isAbsolute ? (AddAuthorityToFileURL() ? 3 : 2) : 1); + if ( result ) { + result->_string = CFStringCreateCopy(allocator, urlString); + result->_base = baseURL ? CFURLCopyAbsoluteURL(baseURL) : NULL; +#if DEBUG_URL_MEMORY_USAGE + if ( url->_base ) { + numURLsWithBaseURL ++; } - else { - url->_flags = flags; - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 2, 0); - url->_ranges[0] = CFRangeMake(0, 4); // scheme "file" - url->_ranges[1] = CFRangeMake(7, CFStringGetLength(urlString)- 7); +#endif + // hard coded parse + if ( isAbsolute ) { + UInt32 flags = IS_DECOMPOSABLE | HAS_SCHEME | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; + flags |= (isDirectory ? IS_DIRECTORY : 0); + if ( isFileReferencePath ) { + // if the URL is a file reference URL, don't set IS_CANONICAL_FILE_URL or POSIX_AND_URL_PATHS_MATCH + flags |= PATH_HAS_FILE_ID; + } + else { + // only posix style paths can be canonical because POSIXPathToURLPath() converts the string to file system representation + flags |= ((pathStyle == kCFURLPOSIXPathStyle) ? IS_CANONICAL_FILE_URL : 0); + flags |= (posixAndUrlPathsMatch ? POSIX_AND_URL_PATHS_MATCH : 0); + } + _setSchemeTypeInFlags(&flags, kHasFileScheme); + + if ( AddAuthorityToFileURL() ) { + result->_flags = flags | HAS_HOST; + result->_ranges[0] = CFRangeMake(0, 4); // scheme "file" + result->_ranges[1] = CFRangeMake(7, 9); // host "localhost" + result->_ranges[2] = CFRangeMake(16, CFStringGetLength(urlString)- 16); + } + else { + result->_flags = flags; + result->_ranges[0] = CFRangeMake(0, 4); // scheme "file" + result->_ranges[1] = CFRangeMake(7, CFStringGetLength(urlString)- 7); + } + } else { + result->_flags = (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; + result->_ranges[0] = CFRangeMake(0, CFStringGetLength(result->_string)); } - } else { - url->_flags = (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0); - *(url->_ranges) = CFRangeMake(0, CFStringGetLength(url->_string)); } if ( releaseBaseURL && baseURL ) { @@ -2191,13 +2179,15 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStri } CFRelease(urlString); - result = true; } } + else if ( baseURL ) { + result = (struct __CFURL *)CFRetain(baseURL); + } #if DEBUG_URL_INITIALIZER_LOGGING #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated" - CFLog(kCFLogLevelError, CFSTR("_CFURLInitWithFileSystemPath (in) fileSystemPath '%@', pathStyle %@, isDirectory %@, baseURL %@\n\t_CFURLInitWithFileSystemPath (out) result %@, url %@"), input_fileSystemPath, input_pathStyle == kCFURLPOSIXPathStyle ? CFSTR("POSIX") : input_pathStyle == kCFURLHFSPathStyle ? CFSTR("HFS"): CFSTR("Windows"), input_isDirectory ? CFSTR("YES") : CFSTR("NO"), input_baseURL, result ? CFSTR("YES") : CFSTR("NO"), uninitializedURL); + CFLog(kCFLogLevelError, CFSTR("_CFURLCreateWithFileSystemPath (in) fileSystemPath '%@', pathStyle %@, isDirectory %@, baseURL %@\n\t_CFURLCreateWithFileSystemPath (out) result %@"), input_fileSystemPath, input_pathStyle == kCFURLPOSIXPathStyle ? CFSTR("POSIX") : input_pathStyle == kCFURLHFSPathStyle ? CFSTR("HFS"): CFSTR("Windows"), input_isDirectory ? CFSTR("YES") : CFSTR("NO"), input_baseURL, result); #pragma GCC diagnostic pop if ( input_fileSystemPath ) { CFRelease(input_fileSystemPath); @@ -2210,7 +2200,7 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStri } /* initializes a URL object with the file system representation */ -CF_EXPORT Boolean _CFURLInitWithFileSystemRepresentation(CFURLRef uninitializedURL, const UInt8 *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL) +static CFURLRef _CFURLCreateWithFileSystemRepresentation(CFAllocatorRef allocator, const UInt8 *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL) { #if DEBUG_URL_INITIALIZER_LOGGING STACK_BUFFER_DECL(UInt8, input_buffer, bufLen); @@ -2219,11 +2209,9 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemRepresentation(CFURLRef uninitializedU CFURLRef input_baseURL = baseURL ? CFRetain(baseURL) : NULL; memcpy(input_buffer, buffer, bufLen); #endif - Boolean result = false; - if ( bufLen > 0 ) { - CFAllocatorRef alloc = CFGetAllocator(uninitializedURL); + struct __CFURL *result = NULL; + if (bufLen > 0) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX - struct __CFURL *url = (struct __CFURL *)uninitializedURL; Boolean isAbsolute = bufLen && (*buffer == '/'); Boolean addedPercentEncoding; Boolean releaseBaseURL = false; @@ -2234,51 +2222,59 @@ CF_EXPORT Boolean _CFURLInitWithFileSystemRepresentation(CFURLRef uninitializedU } else if ( baseURL == NULL ) { // if buffer contains a relative path and no baseURL is provided, use the current working directory - baseURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(uninitializedURL)); + baseURL = _CFURLCreateCurrentDirectoryURL(allocator); releaseBaseURL = true; } - CFStringRef urlString = CreateStringFromFileSystemRepresentationByAddingPercentEscapes(alloc, buffer, bufLen, isDirectory, isAbsolute, false /*windowsPath*/, &addedPercentEncoding); + CFStringRef urlString = CreateStringFromFileSystemRepresentationByAddingPercentEscapes(allocator, buffer, bufLen, isDirectory, isAbsolute, false /*windowsPath*/, &addedPercentEncoding); if ( urlString ) { - _CFURLInit(url, urlString, baseURL, FALSE); - - // hard coded parse - if ( isAbsolute ) { - if ( AddAuthorityToFileURL() ) { - url->_flags = (addedPercentEncoding ? 0 : POSIX_AND_URL_PATHS_MATCH ) | (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_SCHEME | HAS_HOST | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | IS_CANONICAL_FILE_URL; - _setSchemeTypeInFlags(&url->_flags, kHasFileScheme); - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 3, 0); - url->_ranges[0] = CFRangeMake(0, 4); // scheme "file" - url->_ranges[1] = CFRangeMake(7, 9); // host "localhost" - url->_ranges[2] = CFRangeMake(16, CFStringGetLength(urlString)- 16); + // allocate the URL object with the appropriate number of ranges + result = _CFURLAlloc(allocator, isAbsolute ? (AddAuthorityToFileURL() ? 3 : 2) : 1); + if ( result ) { + result->_string = CFStringCreateCopy(allocator, urlString); + result->_base = baseURL ? CFURLCopyAbsoluteURL(baseURL) : NULL; +#if DEBUG_URL_MEMORY_USAGE + if ( result->_base ) { + numURLsWithBaseURL ++; } - else { - url->_flags = (addedPercentEncoding ? 0 : POSIX_AND_URL_PATHS_MATCH ) | (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_SCHEME | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | IS_CANONICAL_FILE_URL; - _setSchemeTypeInFlags(&url->_flags, kHasFileScheme); - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 2, 0); - url->_ranges[0] = CFRangeMake(0, 4); // scheme "file" - url->_ranges[1] = CFRangeMake(7, CFStringGetLength(urlString)- 7); +#endif + // hard coded parse + if ( isAbsolute ) { + if ( AddAuthorityToFileURL() ) { + result->_flags = (addedPercentEncoding ? 0 : POSIX_AND_URL_PATHS_MATCH ) | (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_SCHEME | HAS_HOST | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | IS_CANONICAL_FILE_URL; + _setSchemeTypeInFlags(&result->_flags, kHasFileScheme); + result->_ranges[0] = CFRangeMake(0, 4); // scheme "file" + result->_ranges[1] = CFRangeMake(7, 9); // host "localhost" + result->_ranges[2] = CFRangeMake(16, CFStringGetLength(urlString)- 16); + } + else { + result->_flags = (addedPercentEncoding ? 0 : POSIX_AND_URL_PATHS_MATCH ) | (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_SCHEME | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | IS_CANONICAL_FILE_URL; + _setSchemeTypeInFlags(&result->_flags, kHasFileScheme); + result->_ranges[0] = CFRangeMake(0, 4); // scheme "file" + result->_ranges[1] = CFRangeMake(7, CFStringGetLength(urlString)- 7); + } + } else { + result->_flags = (addedPercentEncoding ? 0 : POSIX_AND_URL_PATHS_MATCH ) | (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; + *(result->_ranges) = CFRangeMake(0, CFStringGetLength(result->_string)); } - } else { - url->_flags = (addedPercentEncoding ? 0 : POSIX_AND_URL_PATHS_MATCH ) | (isDirectory ? IS_DIRECTORY : 0) | IS_DECOMPOSABLE | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0); - *(url->_ranges) = CFRangeMake(0, CFStringGetLength(url->_string)); } if ( releaseBaseURL && baseURL ) { CFRelease(baseURL); } CFRelease(urlString); - result = true; } #elif DEPLOYMENT_TARGET_WINDOWS - CFStringRef filePath = CFStringCreateWithBytes(alloc, buffer, bufLen, CFStringFileSystemEncoding(), false); + CFStringRef filePath = CFStringCreateWithBytes(allocator, buffer, bufLen, CFStringFileSystemEncoding(), false); if ( filePath ) { - result = _CFURLInitWithFileSystemPath(uninitializedURL, filePath, kCFURLWindowsPathStyle, isDirectory, baseURL); + result = _CFURLCreateWithFileSystemPath(allocator, filePath, kCFURLWindowsPathStyle, isDirectory, baseURL); CFRelease(filePath); } #endif } + else if ( baseURL ) { + result = (struct __CFURL *)CFRetain(baseURL); + } #if DEBUG_URL_INITIALIZER_LOGGING - CFLog(kCFLogLevelError, CFSTR("_CFURLInitWithFileSystemRepresentation (in) buffer '%*s', isDirectory %@, baseURL %@\n\t_CFURLInitWithFileSystemRepresentation (out) result %@, url %@"), input_bufLen, input_buffer, input_isDirectory ? CFSTR("YES") : CFSTR("NO"), input_baseURL, result ? CFSTR("YES") : CFSTR("NO"), uninitializedURL); + CFLog(kCFLogLevelError, CFSTR("_CFURLCreateWithFileSystemRepresentation (in) buffer '%*s', isDirectory %@, baseURL %@\n\t_CFURLCreateWithFileSystemRepresentation (out) result %@"), input_bufLen, input_buffer, input_isDirectory ? CFSTR("YES") : CFSTR("NO"), input_baseURL, result); if ( input_baseURL ) { CFRelease(input_baseURL); } @@ -2291,23 +2287,15 @@ CFURLRef CFURLCreateWithBytes(CFAllocatorRef allocator, const uint8_t *URLBytes, CFStringRef urlString = CFStringCreateWithBytes(allocator, URLBytes, length, encoding, false); CFURLRef result = NULL; if ( urlString ) { - if ( baseURL || CFStringGetLength(urlString) != 0 ) { - result = _CFURLAlloc(allocator); - if (result) { - if ( !_CFURLInitWithURLString(result, urlString, false /* checkForLegalCharacters */, baseURL) ) { - CFRelease(result); - result = NULL; - } - else { - if (encoding != kCFStringEncodingUTF8) { - ((struct __CFURL *)result)->_encoding = encoding; + result = _CFURLCreateWithURLString(allocator, urlString, false /* checkForLegalCharacters */, baseURL); + if ( result ) { + if (encoding != kCFStringEncodingUTF8) { + ((struct __CFURL *)result)->_encoding = encoding; #if DEBUG_URL_MEMORY_USAGE - numNonUTF8EncodedURLs++; + numNonUTF8EncodedURLs++; #endif - } } } - } CFRelease(urlString); // it's retained by result, now. } return ( result ); @@ -2327,28 +2315,16 @@ CFDataRef CFURLCreateData(CFAllocatorRef allocator, CFURLRef url, CFStringEncod // Any escape sequences in URLString will be interpreted via UTF-8. CFURLRef CFURLCreateWithString(CFAllocatorRef allocator, CFStringRef URLString, CFURLRef baseURL) { CFURLRef url = NULL; - if ( URLString && (baseURL || CFStringGetLength(URLString) != 0) ) { - url = _CFURLAlloc(allocator); - if (url) { - if ( !_CFURLInitWithURLString(url, URLString, true /* checkForLegalCharacters */, baseURL) ) { - CFRelease(url); - url = NULL; - } - } + if ( URLString ) { + url = _CFURLCreateWithURLString(allocator, URLString, true /* checkForLegalCharacters */, baseURL); } return ( url ); } static CFURLRef _CFURLCreateWithArbitraryString(CFAllocatorRef allocator, CFStringRef URLString, CFURLRef baseURL) { CFURLRef url = NULL; - if ( URLString && (baseURL || CFStringGetLength(URLString) != 0) ) { - url = _CFURLAlloc(allocator); - if (url) { - if ( !_CFURLInitWithURLString(url, URLString, false /* checkForLegalCharacters */, baseURL) ) { - CFRelease(url); - url = NULL; - } - } + if ( URLString ) { + url = _CFURLCreateWithURLString(allocator, URLString, false /* checkForLegalCharacters */, baseURL); } return ( url ); } @@ -2383,7 +2359,8 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela } } else { UInt32 absFlags = 0; - CFRange *absRanges; + CFRange absRanges[MAX_COMPONENTS]; + uint8_t numberOfRanges; CFStringRef absString = NULL; Boolean absStringIsMutable = false; CFURLRef absURL; @@ -2401,7 +2378,7 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela if (ch == '?' || ch == ';' || ch == '#') { // Nothing but parameter + query + fragment; append to the baseURL string CFStringRef baseString; - if (CF_IS_OBJC(__kCFURLTypeID, baseURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), baseURL)) { baseString = CFURLGetString(baseURL); } else { baseString = baseURL->_string; @@ -2412,17 +2389,16 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela absStringIsMutable = true; } else { UInt32 relFlags = 0; - CFRange *relRanges; + CFRange relRanges[MAX_COMPONENTS]; CFStringRef relString = NULL; - _parseComponents(alloc, relativeString, baseURL, &relFlags, &relRanges); + _parseComponents(alloc, relativeString, baseURL, &relFlags, relRanges, &numberOfRanges); if (relFlags & HAS_SCHEME) { CFStringRef baseScheme = CFURLCopyScheme(baseURL); CFRange relSchemeRange = _rangeForComponent(relFlags, relRanges, HAS_SCHEME); if (baseScheme && CFStringGetLength(baseScheme) == relSchemeRange.length && CFStringHasPrefix(relativeString, baseScheme)) { relString = CFStringCreateWithSubstring(alloc, relativeString, CFRangeMake(relSchemeRange.length+1, CFStringGetLength(relativeString) - relSchemeRange.length - 1)); - CFAllocatorDeallocate(alloc, relRanges); relFlags = 0; - _parseComponents(alloc, relString, baseURL, &relFlags, &relRanges); + _parseComponents(alloc, relString, baseURL, &relFlags, relRanges, &numberOfRanges); } else { // Discard the base string; the relative string is absolute and we're not in the funky edge case where the schemes match CFRetain(relativeString); @@ -2434,31 +2410,29 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela relString = relativeString; } if (!absString) { - if (!CF_IS_OBJC(__kCFURLTypeID, baseURL)) { + if (!CF_IS_OBJC(CFURLGetTypeID(), baseURL)) { absString = resolveAbsoluteURLString(alloc, relString, relFlags, relRanges, baseURL->_string, baseURL->_flags, baseURL->_ranges); } else { CFStringRef baseString; UInt32 baseFlags = 0; - CFRange *baseRanges; - if (CF_IS_OBJC(__kCFURLTypeID, baseURL)) { + CFRange baseRanges[MAX_COMPONENTS]; + if (CF_IS_OBJC(CFURLGetTypeID(), baseURL)) { baseString = CFURLGetString(baseURL); } else { baseString = baseURL->_string; } - _parseComponents(alloc, baseString, NULL, &baseFlags, &baseRanges); + _parseComponents(alloc, baseString, NULL, &baseFlags, baseRanges, &numberOfRanges); absString = resolveAbsoluteURLString(alloc, relString, relFlags, relRanges, baseString, baseFlags, baseRanges); - CFAllocatorDeallocate(alloc, baseRanges); } absStringIsMutable = true; } if (relString) CFRelease(relString); - CFAllocatorDeallocate(alloc, relRanges); } CFRelease(relativeString); } } if ( absString ) { - _parseComponents(alloc, absString, NULL, &absFlags, &absRanges); + _parseComponents(alloc, absString, NULL, &absFlags, absRanges, &numberOfRanges); if (absFlags & HAS_PATH) { CFRange pathRg = _rangeForComponent(absFlags, absRanges, HAS_PATH); // This is expensive, but it allows us to reuse _resolvedPath. It should be cleaned up to get this allocation removed at some point. - REW @@ -2478,7 +2452,6 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela CFRelease(newPath); // Do not deallocate buf; newPath took ownership of it. } - CFAllocatorDeallocate(alloc, absRanges); absURL = _CFURLCreateWithArbitraryString(alloc, absString, NULL); CFRelease(absString); if (absURL) { @@ -2566,7 +2539,7 @@ static CFStringRef _resolvedPath(UniChar *pathStr, UniChar *end, UniChar pathDel return CFStringCreateWithCharactersNoCopy(alloc, pathStr, end >= pathStr ? end - pathStr : 0, alloc); } -static CFMutableStringRef resolveAbsoluteURLStringBuffer(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, CFRange *baseRanges, UniChar *buf) +static CFMutableStringRef resolveAbsoluteURLStringBuffer(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, const CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, const CFRange *baseRanges, UniChar *buf) { CFStringAppendBuffer appendBuffer; UniChar chars[2]; @@ -2712,7 +2685,7 @@ static CFMutableStringRef resolveAbsoluteURLStringBuffer(CFAllocatorRef alloc, C return CFStringCreateMutableWithAppendBuffer(&appendBuffer); } -static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, CFRange *baseRanges) { +static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, const CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, const CFRange *baseRanges) { CFMutableStringRef result; CFIndex bufLen = CFStringGetLength(baseString) + CFStringGetLength(relString); // Overkill, but guarantees we never allocate again if ( bufLen <= 1024 ) { @@ -2733,23 +2706,40 @@ CFURLRef CFURLCopyAbsoluteURL(CFURLRef relativeURL) { CFAllocatorRef alloc = CFGetAllocator(relativeURL); CFStringRef baseString, newString; UInt32 baseFlags; - CFRange *baseRanges; + CFRange ranges[MAX_COMPONENTS]; + uint8_t numberOfRanges; + const CFRange *baseRanges; Boolean baseIsObjC; - +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED + Boolean filePathURLCreated = false; +#endif + CFAssert1(relativeURL != NULL, __kCFLogAssertion, "%s(): Cannot create an absolute URL from a NULL relative URL", __PRETTY_FUNCTION__); - if (CF_IS_OBJC(__kCFURLTypeID, relativeURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), relativeURL)) { anURL = (CFURLRef) CF_OBJC_CALLV((NSURL *)relativeURL, absoluteURL); if (anURL) CFRetain(anURL); return anURL; } - __CFGenericValidateType(relativeURL, __kCFURLTypeID); + __CFGenericValidateType(relativeURL, CFURLGetTypeID()); base = relativeURL->_base; if (!base) { return (CFURLRef)CFRetain(relativeURL); } - baseIsObjC = CF_IS_OBJC(__kCFURLTypeID, base); +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED + else if ( CFURLIsFileReferenceURL(base) && !CFURLHasDirectoryPath(base) ) { + // 16695827 - If the base URL is a file reference URL which doesn't end with a slash, we have to convert it to a file path URL before we can make it absolute. + base = CFURLCreateFilePathURL(alloc, base, NULL); + if ( !base ) { + // could not convert file reference URL to file path URL -- fail will NULL + return NULL; + } + filePathURLCreated = true; + } +#endif + + baseIsObjC = CF_IS_OBJC(CFURLGetTypeID(), base); if (!baseIsObjC) { baseString = base->_string; @@ -2758,14 +2748,11 @@ CFURLRef CFURLCopyAbsoluteURL(CFURLRef relativeURL) { } else { baseString = CFURLGetString(base); baseFlags = 0; - baseRanges = NULL; - _parseComponents(alloc, baseString, NULL, &baseFlags, &baseRanges); + _parseComponents(alloc, baseString, NULL, &baseFlags, ranges, &numberOfRanges); + baseRanges = ranges; } newString = resolveAbsoluteURLString(alloc, relativeURL->_string, relativeURL->_flags, relativeURL->_ranges, baseString, baseFlags, baseRanges); - if (baseIsObjC) { - CFAllocatorDeallocate(alloc, baseRanges); - } anURL = _CFURLCreateWithArbitraryString(alloc, newString, NULL); CFRelease(newString); ((struct __CFURL *)anURL)->_encoding = relativeURL->_encoding; @@ -2774,6 +2761,13 @@ CFURLRef CFURLCopyAbsoluteURL(CFURLRef relativeURL) { numNonUTF8EncodedURLs++; } #endif + +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED + if ( filePathURLCreated ) { + CFRelease(base); + } +#endif + return anURL; } @@ -2791,7 +2785,7 @@ Boolean CFURLCanBeDecomposed(CFURLRef anURL) { } CFStringRef CFURLGetString(CFURLRef url) { - CF_OBJC_FUNCDISPATCHV(__kCFURLTypeID, CFStringRef, (NSURL *)url, relativeString); + CF_OBJC_FUNCDISPATCHV(CFURLGetTypeID(), CFStringRef, (NSURL *)url, relativeString); if (!_haveTestedOriginalString(url)) { computeSanitizedString(url); } @@ -2806,7 +2800,7 @@ CFIndex CFURLGetBytes(CFURLRef url, UInt8 *buffer, CFIndex bufferLength) { CFIndex length, charsConverted, usedLength; CFStringRef string; CFStringEncoding enc; - if (CF_IS_OBJC(__kCFURLTypeID, url)) { + if (CF_IS_OBJC(CFURLGetTypeID(), url)) { string = CFURLGetString(url); enc = kCFStringEncodingUTF8; } else { @@ -2823,12 +2817,12 @@ CFIndex CFURLGetBytes(CFURLRef url, UInt8 *buffer, CFIndex bufferLength) { } CFURLRef CFURLGetBaseURL(CFURLRef anURL) { - CF_OBJC_FUNCDISPATCHV(__kCFURLTypeID, CFURLRef, (NSURL *)anURL, baseURL); + CF_OBJC_FUNCDISPATCHV(CFURLGetTypeID(), CFURLRef, (NSURL *)anURL, baseURL); return anURL->_base; } // Assumes the URL is already parsed -static CFRange _rangeForComponent(UInt32 flags, CFRange *ranges, UInt32 compFlag) { +static CFRange _rangeForComponent(UInt32 flags, const CFRange *ranges, UInt32 compFlag) { UInt32 idx = 0; if (!(flags & compFlag)) return CFRangeMake(kCFNotFound, 0); while (!(compFlag & 1)) { @@ -2911,7 +2905,7 @@ static CFStringRef _retainedComponentString(CFURLRef url, UInt32 compFlag, Boole CFStringRef CFURLCopyScheme(CFURLRef anURL) { CFStringRef scheme; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { scheme = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, scheme); if ( scheme ) { CFRetain(scheme); @@ -2954,7 +2948,7 @@ CFStringRef CFURLCopyScheme(CFURLRef anURL) { return ( scheme ); } -static CFRange _netLocationRange(UInt32 flags, CFRange *ranges) { +static CFRange _netLocationRange(UInt32 flags, const CFRange *ranges) { CFRange netRgs[4]; CFRange netRg = {kCFNotFound, 0}; CFIndex i, c = 4; @@ -3035,7 +3029,8 @@ CFStringRef CFURLCopyStrictPath(CFURLRef anURL, Boolean *isAbsolute) { } Boolean CFURLHasDirectoryPath(CFURLRef anURL) { - __CFGenericValidateType(anURL, __kCFURLTypeID); + anURL = _CFURLFromNSURL(anURL); + __CFGenericValidateType(anURL, CFURLGetTypeID()); if (!anURL->_base || (anURL->_flags & (HAS_PATH | NET_LOCATION_MASK))) { return ((anURL->_flags & IS_DIRECTORY) != 0); } @@ -3058,7 +3053,7 @@ static UInt32 _firstResourceSpecifierFlag(UInt32 flags) { CFStringRef CFURLCopyResourceSpecifier(CFURLRef anURL) { anURL = _CFURLFromNSURL(anURL); - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); if (!(anURL->_flags & IS_DECOMPOSABLE)) { CFRange schemeRg = _rangeForComponent(anURL->_flags, anURL->_ranges, HAS_SCHEME); CFIndex base = schemeRg.location + schemeRg.length + 1; @@ -3119,11 +3114,11 @@ CFStringRef CFURLCopyResourceSpecifier(CFURLRef anURL) { } else { // Must compute the correct string to return; just reparse.... UInt32 sanFlags = 0; - CFRange *sanRanges = NULL; - CFRange rg; - _parseComponents(alloc, sanitizedString, anURL->_base, &sanFlags, &sanRanges); + CFRange sanRanges[MAX_COMPONENTS]; + uint8_t numberOfRanges; + CFRange rg; + _parseComponents(alloc, sanitizedString, anURL->_base, &sanFlags, sanRanges, &numberOfRanges); rg = _rangeForComponent(sanFlags, sanRanges, firstRsrcSpecFlag); - CFAllocatorDeallocate(alloc, sanRanges); rg.location --; // Include the character that demarcates the component rg.length = CFStringGetLength(sanitizedString) - rg.location; return CFStringCreateWithSubstring(CFGetAllocator(anURL), sanitizedString, rg); @@ -3142,12 +3137,12 @@ CFStringRef CFURLCopyResourceSpecifier(CFURLRef anURL) { // For the next four methods, it is important to realize that, if a URL supplies any part of the net location (host, user, port, or password), it must supply all of the net location (i.e. none of it comes from its base URL). Also, it is impossible for a URL to be relative, supply none of the net location, and still have its (empty) net location take precedence over its base URL (because there's nothing that precedes the net location except the scheme, and if the URL supplied the scheme, it would be absolute, and there would be no base). CFStringRef CFURLCopyHostName(CFURLRef anURL) { CFStringRef tmp; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { tmp = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, host); if (tmp) CFRetain(tmp); return tmp; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); tmp = _retainedComponentString(anURL, HAS_HOST, true, true); if (tmp) { if (anURL->_flags & IS_IPV6_ENCODED) { @@ -3168,13 +3163,13 @@ CFStringRef CFURLCopyHostName(CFURLRef anURL) { // Return -1 to indicate no port is specified SInt32 CFURLGetPortNumber(CFURLRef anURL) { CFStringRef port; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { CFNumberRef cfPort = (CFNumberRef) CF_OBJC_CALLV((NSURL *)anURL, port); SInt32 num; if (cfPort && CFNumberGetValue(cfPort, kCFNumberSInt32Type, &num)) return num; return -1; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); port = _retainedComponentString(anURL, HAS_PORT, true, false); if (port) { SInt32 portNum, idx, length = CFStringGetLength(port); @@ -3195,12 +3190,12 @@ SInt32 CFURLGetPortNumber(CFURLRef anURL) { CFStringRef CFURLCopyUserName(CFURLRef anURL) { CFStringRef user; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { user = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, user); if (user) CFRetain(user); return user; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); user = _retainedComponentString(anURL, HAS_USER, true, true); if (user) { return user; @@ -3213,12 +3208,12 @@ CFStringRef CFURLCopyUserName(CFURLRef anURL) { CFStringRef CFURLCopyPassword(CFURLRef anURL) { CFStringRef passwd; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { passwd = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, password); if (passwd) CFRetain(passwd); return passwd; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); passwd = _retainedComponentString(anURL, HAS_PASSWORD, true, true); if (passwd) { return passwd; @@ -3233,12 +3228,12 @@ CFStringRef CFURLCopyPassword(CFURLRef anURL) { static CFStringRef _unescapedParameterString(CFURLRef anURL) { CFStringRef str; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { str = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, parameterString); if (str) CFRetain(str); return str; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); str = _retainedComponentString(anURL, HAS_PARAMETERS, false, false); if (str) return str; if (!(anURL->_flags & IS_DECOMPOSABLE)) return NULL; @@ -3266,12 +3261,12 @@ CFStringRef CFURLCopyParameterString(CFURLRef anURL, CFStringRef charactersToL static CFStringRef _unescapedQueryString(CFURLRef anURL) { CFStringRef str; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { str = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, query); if (str) CFRetain(str); return str; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); str = _retainedComponentString(anURL, HAS_QUERY, false, false); if (str) return str; if (!(anURL->_flags & IS_DECOMPOSABLE)) return NULL; @@ -3299,12 +3294,12 @@ CFStringRef CFURLCopyQueryString(CFURLRef anURL, CFStringRef charactersToLeav // Fragments are NEVER taken from a base URL static CFStringRef _unescapedFragment(CFURLRef anURL) { CFStringRef str; - if (CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (CF_IS_OBJC(CFURLGetTypeID(), anURL)) { str = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, fragment); if (str) CFRetain(str); return str; } - __CFGenericValidateType(anURL, __kCFURLTypeID); + __CFGenericValidateType(anURL, CFURLGetTypeID()); str = _retainedComponentString(anURL, HAS_FRAGMENT, false, false); return str; } @@ -3359,7 +3354,7 @@ static CFRange _CFURLGetCharRangeForMask(CFURLRef url, CFOptionFlags mask, CFRan Boolean haveReachedMask = false; CFIndex beforeMask = 0; CFIndex afterMask = kCFNotFound; - CFRange *currRange = url->_ranges; + const CFRange *currRange = url->_ranges; CFRange maskRange = {kCFNotFound, 0}; for (currentOption = 1; currentOption <= HAS_FRAGMENT; currentOption = currentOption << 1) { if (!haveReachedMask && (currentOption & mask) != 0) { @@ -3770,19 +3765,30 @@ CFURLRef _CFURLCreateFromComponents(CFAllocatorRef alloc, CFURLComponentDecompos } CF_EXPORT void *__CFURLReservedPtr(CFURLRef url) { + // called with CFURL (not NSURL) from Foundation return _getReserved(url); } CF_EXPORT void __CFURLSetReservedPtr(CFURLRef url, void *ptr) { + // called with CFURL (not NSURL) from Foundation _setReserved ( (struct __CFURL*) url, ptr ); } CF_EXPORT void *__CFURLResourceInfoPtr(CFURLRef url) { - return _getResourceInfo(url); + if ( url ) { + url = _CFURLFromNSURL(url); + return _getResourceInfo(url); + } + else { + return NULL; + } } CF_EXPORT void __CFURLSetResourceInfoPtr(CFURLRef url, void *ptr) { - _setResourceInfo ( (struct __CFURL*) url, ptr ); + if ( url ) { + url = _CFURLFromNSURL(url); + _setResourceInfo ( (struct __CFURL*) url, ptr ); + } } /* File system stuff */ @@ -4134,13 +4140,7 @@ CFURLRef _CFURLCreateCurrentDirectoryURL(CFAllocatorRef allocator) { CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle fsType, Boolean isDirectory) { CFURLRef result; - result = _CFURLAlloc(allocator); - if ( result ) { - if ( !_CFURLInitWithFileSystemPath(result, filePath, fsType, isDirectory, NULL) ) { - CFRelease(result); - result = NULL; - } - } + result = _CFURLCreateWithFileSystemPath(allocator, filePath, fsType, isDirectory, NULL); return ( result ); } @@ -4148,14 +4148,8 @@ CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef fil CF_EXPORT CFURLRef CFURLCreateWithFileSystemPathRelativeToBase(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle fsType, Boolean isDirectory, CFURLRef baseURL) { CFURLRef result; - result = _CFURLAlloc(allocator); - if ( result ) { - if ( !_CFURLInitWithFileSystemPath(result, filePath, fsType, isDirectory, baseURL) ) { - CFRelease(result); - result = NULL; - } - } - + result = _CFURLCreateWithFileSystemPath(allocator, filePath, fsType, isDirectory, baseURL); + return ( result ); } @@ -4169,14 +4163,6 @@ static Boolean _pathHasFileIDPrefix( CFStringRef path ) return path && CFStringHasPrefix( path, fileIDPrefix ) && CFStringGetLength( path ) > CFStringGetLength( fileIDPrefix ); } -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -static Boolean _pathHasFileIDOnly( CFStringRef path ) -{ - // Is file ID rooted and contains no additonal path segments - CFRange slashRange; - return _pathHasFileIDPrefix( path ) && ( !CFStringFindWithOptions( path, CFSTR("/"), CFRangeMake( sizeof(FILE_ID_PREFIX) + 1, CFStringGetLength( path ) - sizeof(FILE_ID_PREFIX) - 1), 0, &slashRange ) || slashRange.location == CFStringGetLength( path ) - 1 ); -} -#endif CF_EXPORT CFStringRef CFURLCopyFileSystemPath(CFURLRef anURL, CFURLPathStyle pathStyle) { #pragma GCC diagnostic push @@ -4190,7 +4176,7 @@ CF_EXPORT CFStringRef CFURLCopyFileSystemPath(CFURLRef anURL, CFURLPathStyle pat Boolean isCanonicalFileURL = false; if ( (pathStyle == kCFURLPOSIXPathStyle) && (CFURLGetBaseURL(anURL) == NULL) ) { - if ( !CF_IS_OBJC(__kCFURLTypeID, anURL) ) { + if ( !CF_IS_OBJC(CFURLGetTypeID(), anURL) ) { // We can grope the ivars isCanonicalFileURL = ((anURL->_flags & IS_CANONICAL_FILE_URL) != 0); if ( isCanonicalFileURL ) { @@ -4219,7 +4205,7 @@ CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLR CFStringRef basePath = base ? CFURLCreateStringWithFileSystemPath(allocator, base, fsType, false) : NULL; CFStringRef relPath = NULL; - if (!CF_IS_OBJC(__kCFURLTypeID, anURL)) { + if (!CF_IS_OBJC(CFURLGetTypeID(), anURL)) { // We can grope the ivars if (fsType == kCFURLPOSIXPathStyle) { if (anURL->_flags & POSIX_AND_URL_PATHS_MATCH) { @@ -4263,7 +4249,9 @@ CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLR } if ( relPath ) { - if ( basePath && (CFStringGetCharacterAtIndex(relPath, 0) != '/') ) { + // relPath is not absolute if it is zero length or doesn't start with a slash + Boolean relPathIsRelative = ((CFStringGetLength(relPath) != 0) ? (CFStringGetCharacterAtIndex(relPath, 0) != '/') : TRUE); + if ( basePath && relPathIsRelative ) { // we have both basePath and relPath, and relPath is not absolute -- resolve them CFStringRef result = _resolveFileSystemPaths(relPath, basePath, CFURLHasDirectoryPath(base), fsType, allocator); CFRelease(basePath); @@ -4297,7 +4285,7 @@ Boolean CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBas #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX if ( !resolveAgainstBase || (CFURLGetBaseURL(url) == NULL) ) { - if (!CF_IS_OBJC(__kCFURLTypeID, url)) { + if (!CF_IS_OBJC(CFURLGetTypeID(), url)) { // We can grope the ivars if ( url->_flags & IS_CANONICAL_FILE_URL ) { return CanonicalFileURLStringToFileSystemRepresentation(url->_string, buffer, bufLen); @@ -4353,13 +4341,7 @@ CF_EXPORT Boolean _CFURLGetWideFileSystemRepresentation(CFURLRef url, Boolean re CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory) { CFURLRef result; - result = _CFURLAlloc(allocator); - if ( result ) { - if ( !_CFURLInitWithFileSystemRepresentation(result, buffer, bufLen, isDirectory, NULL) ) { - CFRelease(result); - result = NULL; - } - } + result = _CFURLCreateWithFileSystemRepresentation(allocator, buffer, bufLen, isDirectory, NULL); return ( result ); } @@ -4367,13 +4349,7 @@ CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const CF_EXPORT CFURLRef CFURLCreateFromFileSystemRepresentationRelativeToBase(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL) { CFURLRef result; - result = _CFURLAlloc(allocator); - if ( result ) { - if ( !_CFURLInitWithFileSystemRepresentation(result, buffer, bufLen, isDirectory, baseURL) ) { - CFRelease(result); - result = NULL; - } - } + result = _CFURLCreateWithFileSystemRepresentation(allocator, buffer, bufLen, isDirectory, baseURL); return ( result ); } @@ -4412,7 +4388,7 @@ static CFRange _rangeOfLastPathComponent(CFURLRef url) { CFStringRef CFURLCopyLastPathComponent(CFURLRef url) { CFStringRef result; - if (CF_IS_OBJC(__kCFURLTypeID, url)) { + if (CF_IS_OBJC(CFURLGetTypeID(), url)) { CFStringRef path = CFURLCreateStringWithFileSystemPath(CFGetAllocator(url), url, kCFURLPOSIXPathStyle, false); CFIndex length; CFRange rg, compRg; @@ -4510,7 +4486,7 @@ CFStringRef CFURLCopyPathExtension(CFURLRef url) { CFURLRef CFURLCreateCopyAppendingPathComponent(CFAllocatorRef allocator, CFURLRef url, CFStringRef pathComponent, Boolean isDirectory) { CFURLRef result; url = _CFURLFromNSURL(url); - __CFGenericValidateType(url, __kCFURLTypeID); + __CFGenericValidateType(url, CFURLGetTypeID()); CFAssert1(pathComponent != NULL, __kCFLogAssertion, "%s(): Cannot be called with a NULL component to append", __PRETTY_FUNCTION__); Boolean filePathURLCreated = false; @@ -4561,7 +4537,7 @@ CFURLRef CFURLCreateCopyDeletingLastPathComponent(CFAllocatorRef allocator, CFUR url = _CFURLFromNSURL(url); CFAssert1(url != NULL, __kCFLogAssertion, "%s(): NULL argument not allowed", __PRETTY_FUNCTION__); - __CFGenericValidateType(url, __kCFURLTypeID); + __CFGenericValidateType(url, CFURLGetTypeID()); Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED @@ -4637,7 +4613,7 @@ CFURLRef CFURLCreateCopyAppendingPathExtension(CFAllocatorRef allocator, CFURLRe CFAssert1(url != NULL && extension != NULL, __kCFLogAssertion, "%s(): NULL argument not allowed", __PRETTY_FUNCTION__); url = _CFURLFromNSURL(url); - __CFGenericValidateType(url, __kCFURLTypeID); + __CFGenericValidateType(url, CFURLGetTypeID()); __CFGenericValidateType(extension, CFStringGetTypeID()); Boolean filePathURLCreated = false; @@ -4682,7 +4658,7 @@ CFURLRef CFURLCreateCopyDeletingPathExtension(CFAllocatorRef allocator, CFURLRef CFAssert1(url != NULL, __kCFLogAssertion, "%s(): NULL argument not allowed", __PRETTY_FUNCTION__); url = _CFURLFromNSURL(url); - __CFGenericValidateType(url, __kCFURLTypeID); + __CFGenericValidateType(url, CFURLGetTypeID()); Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED @@ -4718,130 +4694,6 @@ CFURLRef CFURLCreateCopyDeletingPathExtension(CFAllocatorRef allocator, CFURLRef } -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -static CFArrayRef HFSPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) { - CFArrayRef components = CFStringCreateArrayBySeparatingStrings(alloc, path, CFSTR(":")); - CFMutableArrayRef newComponents = CFArrayCreateMutableCopy(alloc, 0, components); - Boolean doSpecialLeadingColon = false; - UniChar firstChar = CFStringGetCharacterAtIndex(path, 0); - UInt32 i, cnt; - CFRelease(components); - - - if (!doSpecialLeadingColon && firstChar != ':') { - CFArrayInsertValueAtIndex(newComponents, 0, CFSTR("")); - } else if (firstChar != ':') { - // see what we need to add at the beginning. Under MacOS, if the - // first character isn't a ':', then the first component is the - // volume name, and we need to find the mount point. Bleah. If we - // don't find a mount point, we're going to have to lie, and make something up. - CFStringRef firstComp = (CFStringRef)CFArrayGetValueAtIndex(newComponents, 0); - if (CFStringGetLength(firstComp) == 1 && CFStringGetCharacterAtIndex(firstComp, 0) == '/') { - // "/" is the "magic" path for a UFS root directory - CFArrayRemoveValueAtIndex(newComponents, 0); - CFArrayInsertValueAtIndex(newComponents, 0, CFSTR("")); - } else { - // See if we can get a mount point. - Boolean foundMountPoint = false; - if (!foundMountPoint) { - // Fall back to treating the volume name as the top level directory - CFArrayInsertValueAtIndex(newComponents, 0, CFSTR("")); - } - } - } else { - CFArrayRemoveValueAtIndex(newComponents, 0); - } - - cnt = CFArrayGetCount(newComponents); - for (i = 0; i < cnt; i ++) { - CFStringRef comp = (CFStringRef)CFArrayGetValueAtIndex(newComponents, i); - CFStringRef newComp = NULL; - CFRange searchRg, slashRg; - searchRg.location = 0; - searchRg.length = CFStringGetLength(comp); - while (CFStringFindWithOptions(comp, CFSTR("/"), searchRg, 0, &slashRg)) { - if (!newComp) { - newComp = CFStringCreateMutableCopy(alloc, searchRg.location + searchRg.length, comp); - } - CFStringReplace((CFMutableStringRef)newComp, slashRg, CFSTR(":")); - searchRg.length = searchRg.location + searchRg.length - slashRg.location - 1; - searchRg.location = slashRg.location + 1; - } - if (newComp) { - CFArraySetValueAtIndex(newComponents, i, newComp); - CFRelease(newComp); - } - } - if (isDir && CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(newComponents, cnt-1)) != 0) { - CFArrayAppendValue(newComponents, CFSTR("")); - } - return newComponents; -} - -typedef CFStringRef (*StringTransformation)(CFAllocatorRef, CFStringRef, CFIndex); -static CFArrayRef copyStringArrayWithTransformation(CFArrayRef array, StringTransformation transformation) { - CFAllocatorRef alloc = CFGetAllocator(array); - CFMutableArrayRef mArray = NULL; - CFIndex i, c = CFArrayGetCount(array); - for (i = 0; i < c; i ++) { - CFStringRef origComp = (CFStringRef)CFArrayGetValueAtIndex(array, i); - CFStringRef unescapedComp = transformation(alloc, origComp, i); - if (!unescapedComp) { - break; - } - if (unescapedComp != origComp) { - if (!mArray) { - mArray = CFArrayCreateMutableCopy(alloc, c, array); - } - CFArraySetValueAtIndex(mArray, i, unescapedComp); - } - CFRelease(unescapedComp); - } - if (i != c) { - if (mArray) CFRelease(mArray); - return NULL; - } else if (mArray) { - return mArray; - } else { - CFRetain(array); - return array; - } -} - -static CFStringRef escapePathComponent(CFAllocatorRef alloc, CFStringRef origComponent, CFIndex componentIndex) { - return CFURLCreateStringByAddingPercentEscapes(alloc, origComponent, NULL, CFSTR(";?/"), kCFStringEncodingUTF8); -} - -static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute) { - CFArrayRef components = HFSPathToURLComponents(path, alloc, isDir); - CFArrayRef newComponents = components ? copyStringArrayWithTransformation(components, escapePathComponent) : NULL; - CFIndex cnt; - CFStringRef result; - if (components) CFRelease(components); - if (!newComponents) return NULL; - - cnt = CFArrayGetCount(newComponents); - if (cnt == 1 && CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(newComponents, 0)) == 0) { - result = (CFStringRef)CFRetain(CFSTR("/")); - } else { - result = CFStringCreateByCombiningStrings(alloc, newComponents, CFSTR("/")); - } - if ( isAbsolute && result ) { - CFStringRef temp = result; - if ( AddAuthorityToFileURL() ) { - result = CFStringCreateWithFormat(alloc, 0, CFSTR(FILE_PREFIX_WITH_AUTHORITY "%@"), temp); - } - else { - result = CFStringCreateWithFormat(alloc, 0, CFSTR(FILE_PREFIX "%@"), temp); - } - CFRelease(temp); - } - CFRelease(newComponents); - return result; -} -#endif - - // keys and vals must have space for at least 4 key/value pairs. No argument can be NULL. // Caller must release values, but not keys @@ -4852,7 +4704,7 @@ static void __CFURLCopyPropertyListKeysAndValues(CFURLRef url, CFTypeRef *keys, keys[1] = CFSTR("_CFURLString"); keys[2] = CFSTR("_CFURLBaseStringType"); keys[3] = CFSTR("_CFURLBaseURLString"); - if (CF_IS_OBJC(__kCFURLTypeID, url)) { + if (CF_IS_OBJC(CFURLGetTypeID(), url)) { SInt32 urlType = FULL_URL_REPRESENTATION; vals[0] = CFNumberCreate(alloc, kCFNumberSInt32Type, &urlType); vals[1] = CFURLGetString(url); @@ -4874,7 +4726,7 @@ static void __CFURLCopyPropertyListKeysAndValues(CFURLRef url, CFTypeRef *keys, } } if (base != NULL) { - if (CF_IS_OBJC(__kCFURLTypeID, base)) { + if (CF_IS_OBJC(CFURLGetTypeID(), base)) { SInt32 urlType = FULL_URL_REPRESENTATION; vals[2] = CFNumberCreate(alloc, kCFNumberSInt32Type, &urlType); vals[3] = CFURLGetString(base); @@ -4979,7 +4831,7 @@ Boolean CFURLIsFileReferenceURL(CFURLRef url) result = CFURLIsFileReferenceURL(baseURL); } else { - if ( CF_IS_OBJC(__kCFURLTypeID, url) ) { + if ( CF_IS_OBJC(CFURLGetTypeID(), url) ) { result = (Boolean) CF_OBJC_CALLV((NSURL *)url, isFileReferenceURL); } else { @@ -4998,7 +4850,8 @@ static Boolean _CFURLHasFileURLScheme(CFURLRef url, Boolean *hasScheme) result = _CFURLHasFileURLScheme(baseURL, hasScheme); } else { - if ( CF_IS_OBJC(__kCFURLTypeID, url) ) { + if ( CF_IS_OBJC(CFURLGetTypeID(), url) || (_getSchemeTypeFromFlags(url->_flags) == kHasUncommonScheme) ) { + // if it's not a CFURL or the scheme is not a common canonical-form scheme, determine the scheme the slower way. CFStringRef scheme = CFURLCopyScheme(url); if ( scheme ) { if ( scheme == kCFURLFileScheme ) { @@ -5067,7 +4920,24 @@ CFURLRef CFURLCreateFilePathURL(CFAllocatorRef alloc, CFURLRef url, CFErrorRef * } if ( fsPath ) { CFStringRef urlPath = _replacePathIllegalCharacters( fsPath, alloc, true ); - newURLString = CFStringCreateWithFormat( alloc, NULL, CFSTR(FILE_PREFIX "%@%@%@%@"), (netLoc ? netLoc : CFSTR("")), urlPath, ((CFStringCompare(urlPath, CFSTR("/"), 0) != kCFCompareEqualTo) ? (CFURLHasDirectoryPath( url ) ? CFSTR("/") : CFSTR("")) : CFSTR("")), (rSpec ? rSpec : CFSTR(""))); + + CFStringAppendBuffer appendBuffer; + CFStringInitAppendBuffer(alloc, &appendBuffer); + CFStringAppendStringToAppendBuffer(&appendBuffer, CFSTR(FILE_PREFIX)); + if ( netLoc ) { + CFStringAppendStringToAppendBuffer(&appendBuffer, netLoc); + } + CFStringAppendStringToAppendBuffer(&appendBuffer, urlPath); + // if original url had a directory path and the path isn't "/", append a slash + if ( CFURLHasDirectoryPath(url) && (CFStringCompare(urlPath, CFSTR("/"), 0) != kCFCompareEqualTo) ) { + UniChar slashUniChar = '/'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, &slashUniChar, 1); + } + if ( rSpec ) { + CFStringAppendStringToAppendBuffer(&appendBuffer, rSpec); + } + newURLString = CFStringCreateMutableWithAppendBuffer(&appendBuffer); + result = CFURLCreateWithString( alloc, newURLString, NULL ); CFRelease( newURLString ); CFRelease( urlPath ); diff --git a/CFURL.h b/CFURL.h index ad91941..46a1481 100644 --- a/CFURL.h +++ b/CFURL.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFURL.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFURL__) @@ -42,7 +42,7 @@ typedef CF_ENUM(CFIndex, CFURLPathStyle) { kCFURLWindowsPathStyle }; -typedef const struct __CFURL * CFURLRef; +typedef const struct CF_BRIDGED_TYPE(NSURL) __CFURL * CFURLRef; /* CFURLs are composed of two fundamental pieces - their string, and a */ /* (possibly NULL) base URL. A relative URL is one in which the string */ @@ -831,6 +831,22 @@ CF_EXPORT const CFStringRef kCFURLIsMountTriggerKey CF_AVAILABLE(10_7, 4_0); /* true if this URL is a file system trigger directory. Traversing or opening a file system trigger will cause an attempt to mount a file system on the trigger directory. (Read-only, value type CFBoolean) */ +CF_EXPORT +const CFStringRef kCFURLGenerationIdentifierKey CF_AVAILABLE(10_10, 8_0); + /* An opaque generation identifier which can be compared using CFEqual() to determine if the data in a document has been modified. For URLs which refer to the same file inode, the generation identifier will change when the data in the file's data fork is changed (changes to extended attributes or other file system metadata do not change the generation identifier). For URLs which refer to the same directory inode, the generation identifier will change when direct children of that directory are added, removed or renamed (changes to the data of the direct children of that directory will not change the generation identifier). The generation identifier is persistent across system restarts. The generation identifier is tied to a specific document on a specific volume and is not transferred when the document is copied to another volume. This property is not supported by all volumes. (Read-only, value type CFType) */ + +CF_EXPORT +const CFStringRef kCFURLDocumentIdentifierKey CF_AVAILABLE(10_10, 8_0); + /* The document identifier -- a value assigned by the kernel to a document (which can be either a file or directory) and is used to identify the document regardless of where it gets moved on a volume. The document identifier survives "safe save” operations; i.e it is sticky to the path it was assigned to (-replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error: is the preferred safe-save API). The document identifier is persistent across system restarts. The document identifier is not transferred when the file is copied. Document identifiers are only unique within a single volume. This property is not supported by all volumes. (Read-only, value type CFNumber) */ + +CF_EXPORT +const CFStringRef kCFURLAddedToDirectoryDateKey CF_AVAILABLE(10_10, 8_0); + /* The date the resource was created, or renamed into or within its parent directory. Note that inconsistent behavior may be observed when this attribute is requested on hard-linked items. This property is not supported by all volumes. (Read-only, value type CFDate) */ + +CF_EXPORT +const CFStringRef kCFURLQuarantinePropertiesKey CF_AVAILABLE(10_10, NA); + /* The quarantine properties as defined in LSQuarantine.h. To remove quarantine information from a file, pass kCFNull as the value when setting this property. (Read-write, value type CFDictionary) */ + CF_EXPORT const CFStringRef kCFURLFileResourceTypeKey CF_AVAILABLE(10_7, 5_0); /* Returns the file system object type. (Read-only, value type CFString) */ @@ -1044,11 +1060,11 @@ const CFStringRef kCFURLUbiquitousItemDownloadingStatusKey CF_AVAILABLE(10_9, 7_ CF_EXPORT const CFStringRef kCFURLUbiquitousItemDownloadingErrorKey CF_AVAILABLE(10_9, 7_0); - /* returns the error when downloading the item from iCloud failed. See the NSUbiquitousFile section in FoundationErrors.h. */ + /* returns the error when downloading the item from iCloud failed. See the NSUbiquitousFile section in FoundationErrors.h. (Read-only, value type CFError) */ CF_EXPORT const CFStringRef kCFURLUbiquitousItemUploadingErrorKey CF_AVAILABLE(10_9, 7_0); - /* returns the error when uploading the item to iCloud failed. See the NSUbiquitousFile section in FoundationErrors.h. */ + /* returns the error when uploading the item to iCloud failed. See the NSUbiquitousFile section in FoundationErrors.h. (Read-only, value type CFError) */ /* The values returned for kCFURLUbiquitousItemDownloadingStatusKey */ @@ -1066,145 +1082,74 @@ const CFStringRef kCFURLUbiquitousItemDownloadingStatusCurrent CF_AVAILABLE(10_9 typedef CF_OPTIONS(CFOptionFlags, CFURLBookmarkCreationOptions) { - kCFURLBookmarkCreationPreferFileIDResolutionMask CF_ENUM_DEPRECATED(10_6, 10_9, 4_0, 7_0, "kCFURLBookmarkCreationPreferFileIDResolutionMask does nothing and has no effect on bookmark resolution" ) = ( 1UL << 8 ), // This option does nothing and has no effect on bookmark resolution - kCFURLBookmarkCreationMinimalBookmarkMask = ( 1UL << 9 ), // Creates a bookmark with "less" information, which may be smaller but still be able to resolve in certain ways - kCFURLBookmarkCreationSuitableForBookmarkFile = ( 1UL << 10 ), // includes in the created bookmark those properties which are needed for a bookmark/alias file - kCFURLBookmarkCreationWithSecurityScope CF_ENUM_AVAILABLE(10_7,NA) = ( 1UL << 11 ), // Mac OS X 10.7.3 and later, include information in the bookmark data which allows the same sandboxed process to access the resource after being relaunched - kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess CF_ENUM_AVAILABLE(10_7,NA) = ( 1UL << 12 ), // Mac OS X 10.7.3 and later, if used with kCFURLBookmarkCreationWithSecurityScope, at resolution time only read access to the resource will be granted -}; - -enum { - kCFBookmarkResolutionWithoutUIMask = ( 1UL << 8 ), // don't perform any UI during bookmark resolution - kCFBookmarkResolutionWithoutMountingMask = ( 1UL << 9 ), // don't mount a volume during bookmark resolution -}; - -enum { - kCFURLBookmarkResolutionWithSecurityScope CF_ENUM_AVAILABLE(10_7,NA) = ( 1UL << 10 ), // Mac OS X 10.7.3 and later, extract the security scope included at creation time to provide the ability to access the resource. -}; - -typedef CFOptionFlags CFURLBookmarkResolutionOptions; + kCFURLBookmarkCreationMinimalBookmarkMask = ( 1UL << 9 ), // creates bookmark data with "less" information, which may be smaller but still be able to resolve in certain ways + kCFURLBookmarkCreationSuitableForBookmarkFile = ( 1UL << 10 ), // include the properties required by CFURLWriteBookmarkDataToFile() in the bookmark data created + kCFURLBookmarkCreationWithSecurityScope CF_ENUM_AVAILABLE(10_7, NA) = ( 1UL << 11 ), // Mac OS X 10.7.3 and later, include information in the bookmark data which allows the same sandboxed process to access the resource after being relaunched + kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess CF_ENUM_AVAILABLE(10_7, NA) = ( 1UL << 12 ), // Mac OS X 10.7.3 and later, if used with kCFURLBookmarkCreationWithSecurityScope, at resolution time only read access to the resource will be granted + + // deprecated + kCFURLBookmarkCreationPreferFileIDResolutionMask CF_ENUM_DEPRECATED(10_6, 10_9, 4_0, 7_0, "kCFURLBookmarkCreationPreferFileIDResolutionMask does nothing and has no effect on bookmark resolution" ) = ( 1UL << 8 ), +} CF_ENUM_AVAILABLE(10_6, 4_0); + +typedef CF_OPTIONS(CFOptionFlags, CFURLBookmarkResolutionOptions) { + kCFURLBookmarkResolutionWithoutUIMask = ( 1UL << 8 ), // don't perform any user interaction during bookmark resolution + kCFURLBookmarkResolutionWithoutMountingMask = ( 1UL << 9 ), // don't mount a volume during bookmark resolution + kCFURLBookmarkResolutionWithSecurityScope CF_ENUM_AVAILABLE(10_7, NA) = ( 1UL << 10 ), // Mac OS X 10.7.3 and later, use the secure information included at creation time to provide the ability to access the resource in a sandboxed process. + + kCFBookmarkResolutionWithoutUIMask = kCFURLBookmarkResolutionWithoutUIMask, + kCFBookmarkResolutionWithoutMountingMask = kCFURLBookmarkResolutionWithoutMountingMask, +} CF_ENUM_AVAILABLE(10_6, 4_0); typedef CFOptionFlags CFURLBookmarkFileCreationOptions; CF_IMPLICIT_BRIDGING_DISABLED -/* @function CFURLCreateBookmarkData - @discussion Create a CFDataRef containing an externalizable representation from a CFURLRef, modified with the given options, including ( at the minimum ) any - properties in the propertiesToInclude array which are retrievable from the given url. - @param allocator the CFAllocator to use to create this object - @param url the CFURLRef to create a bookmark data from. - @param options a set of options which control creation of the bookmark data - @param resourcePropertiesToInclude If non-NULL, an CFArrayRef of additional properties copied from the url to include in the created bookmark data. - @param relativeToURL If non-NULL, the created bookmark will be relative to the given url. If kCFURLBookmarkCreationWithSecurityScope is given as - an option and relativeToURL is non-NULL, then a collection-scoped bookmark is created which enables future access to url provided the caller has - access to relativeURL. - @param error If non-NULL, on exit will be filled in with a CFErrorRef representing any error which occured during creation of the bookmark data - @result A CFDataRef containing an data, which can be later be passed to CFURLCreateByResolvingBookmarkData() or to CFURLCopyPropertiesForKeysFromBookmarkData() / CFURLCopyPropertyForKeyFromBookmarkData() */ +/* Returns bookmark data for the URL, created with specified options and resource properties. If this function returns NULL, the optional error is populated. + */ CF_EXPORT CFDataRef CFURLCreateBookmarkData ( CFAllocatorRef allocator, CFURLRef url, CFURLBookmarkCreationOptions options, CFArrayRef resourcePropertiesToInclude, CFURLRef relativeToURL, CFErrorRef* error ) CF_AVAILABLE(10_6, 4_0); -/* @function CFURLCreateByResolvingBookmarkData - @discussion Given a CFDataRef created with CFURLCreateBookmarkRepresentation(), return a CFURLRef of the item it was a bookmark to, and - attempt to pre-cache those properties in propertiesToInclude in the resulting url. If in the process of resolving the bookmark into the CFURLRef - it points to this determines that some properties in the bookmark are out of date or not correct for the item it resolves to, set *isStale to YES, - which the client may want to use to decide to make a new bookmark from the returned item and replace the saved bookmark it has. If the bookmarked - item cannot be found, return NULL. A bookmark created with security scope may fail to resolve if the caller does not have the same code signing identity - as the caller which created the bookmark. - After resolving a security scoped bookmark, the caller must call CFURLStartAccessingSecurityScopedResource() in order to gain access to the resource. - If an error ( other than "original item can not be found" ) occurs during the process, return NULL and fill in error ) - @param allocator the CFAllocator to use to create this object - @param bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData - @param options options which affect the resolution - @param relativeToURL If non-NULL, and if the bookmark was created relative to another url, then resolve it relative to this url. If - kCFURLBookmarkCreationWithSecurityScope was provided at creation, and kCFURLBookmarkResolutionWithSecurityScope is set, then relativeURL - should point to the same item which was passed as relavitiveURL at creation time. - @param resourcePropertiesToInclude If non-NULL, a CFArray containing those properties which the caller would like to already be cached on the given url - @param isStale If non-NULL, on exit will be set to true if during resolution any of the properties in the bookmark no longer seemed to match the - corresponding properties on the returned file. Clients, upon seeing a stale representation, may want to replace whatever stored bookmark data they - have saved and create a new one. - @param error If non-NULL, on exit will be filled in with a CFErrorRef representing any error which occured during resolution of the bookmark data - @result A CFURLRef of a file which is the closest match to the file the bookmark data */ +/* Return a URL that refers to a location specified by resolving bookmark data. If this function returns NULL, the optional error is populated. + */ CF_EXPORT CFURLRef CFURLCreateByResolvingBookmarkData ( CFAllocatorRef allocator, CFDataRef bookmark, CFURLBookmarkResolutionOptions options, CFURLRef relativeToURL, CFArrayRef resourcePropertiesToInclude, Boolean* isStale, CFErrorRef* error ) CF_AVAILABLE(10_6, 4_0); -/* @function CFURLCreatePropertiesForKeysFromBookmarkData - @discussion Given a bookmark, return a dictionary of properties . - This returns only the properties stored within the bookmark and will not attempt to resolve the bookmark or do i/o. - @param allocator the CFAllocator to use to create this object - @param bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData - @param propertiesToReturn a CFArrayRef of the properties of the bookmark data which the client would like returned. - @result a CFDictionaryRef containing the values for the properties passed in obtained from the bookmark data ( not by attempting to resolve it or do i/o in any way ) */ +/* Returns the resource propertyies identified by a specified array of keys contained in specified bookmark data. If the result dictionary does not contain a resource value for one or more of the requested resource keys, it means those resource properties are not available in the bookmark data. + */ CF_EXPORT CFDictionaryRef CFURLCreateResourcePropertiesForKeysFromBookmarkData ( CFAllocatorRef allocator, CFArrayRef resourcePropertiesToReturn, CFDataRef bookmark ) CF_AVAILABLE(10_6, 4_0); -/* @function CFURLCreatePropertyForKeyFromBookmarkData - @discussion Given a bookmark, return the value for a given property from the bookmark data - This returns only the properties stored within the bookmark and will not attempt to resolve the bookmark or do i/o. - @param allocator the CFAllocator to use to create this object - @param bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData - @param propertyKey the property key to return. - @result a CFTypeRef value for the property passed in obtained from the bookmark data ( not by attempting to resolve it or do i/o in any way ) */ +/* Returns the resource property identified by a given resource key contained in specified bookmark data. If this function returns NULL, it means the resource property is not available in the bookmark data. + */ CF_EXPORT CFTypeRef CFURLCreateResourcePropertyForKeyFromBookmarkData( CFAllocatorRef allocator, CFStringRef resourcePropertyKey, CFDataRef bookmark ) CF_AVAILABLE(10_6, 4_0); -/*! @function CFURLCreateBookmarkDataFromFile - @description Given a fileURL of a file which is a Finder "alias" file, return a CFDataRef with the bookmark data from the file. If urlRef points to an alias file - created before SnowLeopard which contains Alias Manager information and no bookmark data, then a CFDataRef will be synthesized which contains - a approximation of the alias information in a format which can be used to resolve the bookmark. If an error prevents reading the data or - if it is corrupt, NULL will be returned and error will be filled in if errorRef is non-NULL. - @param allocator the CFAllocator to use to create this object - @param fileURL a CFURLRef to to the alias file to create the bookmark data from - @param errorRef if non-NULL, on exit will be filled in with a CFErrorRef representing any error which occurred during the creation of the bookmark data from the file - @result A CFDataRef containing bookmark data, or NULL if there was an error creating bookmark data from the file, such as if the file is not an alias file. +/* Returns bookmark data derived from an alias file referred to by fileURL. If fileURL refers to an alias file created prior to OS X v10.6 that contains Alias Manager information but no bookmark data, this method synthesizes bookmark data for the file. If this method returns NULL, the optional error is populated. */ CF_EXPORT CFDataRef CFURLCreateBookmarkDataFromFile(CFAllocatorRef allocator, CFURLRef fileURL, CFErrorRef *errorRef ) CF_AVAILABLE(10_6, 5_0); -/*! @function CFURLWriteBookmarkDataToFile - @description Given a created bookmarkData object, create a new Finder "alias" file at fileURL which contains the bookmark data. If fileURL is a url to a directory, an alias file - will be created with the same name as the bookmarked item and a ".alias" extension. If fileURL is a url for a file and it exists it will be overwritten. If a - .alias extension is not present it will be added. In addition to the bookmark data, sufficient pre-SnowLeopard alias data will added to the file to allow - systems running something before SnowLeopard to resolve this file using Alias Manager routines and get back the same file as the bookmark routines. - The bookmark data must have been created with the kCFURLBookmarkCreationSuitableForBookmarkFile option and an error will be returned if not. - @param allocator the CFAllocator to use to create this object - @param bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData - @param options options flags - @param errorRef if non-NULL, on exit will be filled in with a CFErrorRef representing any error which occurred during the creation of the alias file +/* Creates an alias file on disk at a specified location with specified bookmark data. The bookmark data must have been created with the kCFURLBookmarkCreationSuitableForBookmarkFile option. fileURL must either refer to an existing file (which will be overwritten), or to location in an existing directory. If this method returns FALSE, the optional error is populated. */ CF_EXPORT Boolean CFURLWriteBookmarkDataToFile( CFDataRef bookmarkRef, CFURLRef fileURL, CFURLBookmarkFileCreationOptions options, CFErrorRef *errorRef ) CF_AVAILABLE(10_6, 5_0); -/*! @function CFURLCreateBookmarkDataFromAliasRecord - @discussion Create a CFDataRef containing bookmarkdata by converting the alias data in aliasRecordDataRef, which should be the contents of an AliasRecord copied into a CFDataRef object. - The created bookmarkdata can be passed into CFURLCreateByResolvingBookmarkData() to resolve the item into a CFURLRef, or a small set of information can be returned from - CFURLCreateResourcePropertiesForKeysFromBookmarkData() / CFURLCreateResourcePropertyForKeyFromBookmarkData(). - @param allocator the CFAllocator to use to create this object - @param aliasRecordDataRef the contents of an AliasRecord to create bookmark data for - @result A CFDataRef containing an data, which can be later be passed to CFURLCreateByResolvingBookmarkData() or to CFURLCopyPropertiesForKeysFromBookmarkData() / CFURLCopyPropertyForKeyFromBookmarkData() +/* Returns bookmark data derived from an alias record. */ CF_EXPORT CFDataRef CFURLCreateBookmarkDataFromAliasRecord ( CFAllocatorRef allocatorRef, CFDataRef aliasRecordDataRef ) CF_AVAILABLE_MAC(10_6); CF_IMPLICIT_BRIDGING_ENABLED -/*! @function CFURLStartAccessingSecurityScopedResource - @discussion Given a CFURLRef created by resolving a bookmark data created with security scope, make the resource referenced by the - url accessible to the process. When access to this resource is no longer needed the client should call - CFURLStopAccessingSecurityScopedResource(). Each call to CFURLStartAccessingSecurityScopedResource() must be balanced - with a call to CFURLStopAccessingSecurityScopedResource(). - @param url the CFURLRef for the resource returned by CFURLCreateByResolvingBookmarkData() using kCFURLBookmarkResolutionWithSecurityScope. - @result returns TRUE if access was granted and FALSE if the url does not reference a security scoped resource, or if some error occurred - which didn't allow access to be granted +/* Given a CFURLRef created by resolving a bookmark data created with security scope, make the resource referenced by the url accessible to the process. When access to this resource is no longer needed the client must call CFURLStopAccessingSecurityScopedResource(). Each call to CFURLStartAccessingSecurityScopedResource() must be balanced with a call to CFURLStopAccessingSecurityScopedResource() (Note: this is not reference counted). */ CF_EXPORT -Boolean CFURLStartAccessingSecurityScopedResource(CFURLRef url) CF_AVAILABLE(10_7, NA); // Available in MacOS X 10.7.3 and later +Boolean CFURLStartAccessingSecurityScopedResource(CFURLRef url) CF_AVAILABLE(10_7, 8_0); // On OSX, available in MacOS X 10.7.3 and later -/*! @function CFURLStopAccessingSecurityScopedResource - @discussion Revokes the access granted to the url by a prior successful call to CFURLStartAccessingSecurityScopedResource(). - @param url the CFURLRef for the resource to stop accessing. +/* Revokes the access granted to the url by a prior successful call to CFURLStartAccessingSecurityScopedResource(). */ CF_EXPORT -void CFURLStopAccessingSecurityScopedResource(CFURLRef url) CF_AVAILABLE(10_7, NA); +void CFURLStopAccessingSecurityScopedResource(CFURLRef url) CF_AVAILABLE(10_7, 8_0); // On OSX, available in MacOS X 10.7.3 and later #endif /* TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE */ diff --git a/CFURL.inc.h b/CFURL.inc.h index 93d73c5..2ac827d 100644 --- a/CFURL.inc.h +++ b/CFURL.inc.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFURL.inc.h - Copyright (c) 2012-2013, Apple Inc. All rights reserved. - Responsibility: Jim Luther + Copyright (c) 2012-2014, Apple Inc. All rights reserved. + Responsibility: Jim Luther/Chris Linn */ @@ -42,13 +42,25 @@ */ /* - static void _parseComponentsCString(CFAllocatorRef alloc, CFURLRef baseURL, UInt32 *theFlags, CFRange **range, CFIndex cfStringLength, const char *characterArray) - static void _parseComponentsUString(CFAllocatorRef alloc, CFURLRef baseURL, UInt32 *theFlags, CFRange **range, CFIndex cfStringLength, const UniChar *characterArray) + static void _parseComponentsCString(CFAllocatorRef alloc, CFURLRef baseURL, CFIndex cfStringLength, const char *characterArray, UInt32 *theFlags, CFRange *packedRanges, uint8_t *numberOfRanges) + or + static void _parseComponentsUString(CFAllocatorRef alloc, CFURLRef baseURL, CFIndex cfStringLength, const UniChar *characterArray, UInt32 *theFlags, CFRange *packedRanges, uint8_t *numberOfRanges) */ #ifdef CFURL_INCLUDE_PARSE_COMPONENTS // defined when we want this block of code included { - CFRange ranges[9]; /* index gives the URL part involved; to calculate the correct range index, use the number of the bit of the equivalent flag (i.e. the host flag is HAS_HOST, which is 0x8. so the range index for the host is 3.) Note that this is true in this function ONLY, since the ranges stored in (*range) are actually packed, skipping those URL components that don't exist. This is why the indices are hard-coded in this function. */ + enum { + scheme_index = 0, + user_index = 1, + password_index = 2, + host_index = 3, + port_index = 4, + path_index = 5, + parameters_index = 6, + query_index = 7, + fragment_index = 8, + }; + CFRange unpackedRanges[MAX_COMPONENTS]; CFIndex idx, base_idx = 0; CFIndex string_length; @@ -63,8 +75,8 @@ for (idx = base_idx; idx < string_length; idx++) { if ('#' == characterArray[idx]) { flags |= HAS_FRAGMENT; - ranges[8].location = idx + 1; - ranges[8].length = string_length - (idx + 1); + unpackedRanges[fragment_index].location = idx + 1; + unpackedRanges[fragment_index].length = string_length - (idx + 1); numRanges ++; string_length = idx; // remove fragment from parse string break; @@ -75,8 +87,8 @@ UniChar ch = characterArray[idx]; if (':' == ch) { flags |= HAS_SCHEME; - ranges[0].location = base_idx; - ranges[0].length = idx; + unpackedRanges[scheme_index].location = base_idx; + unpackedRanges[scheme_index].length = idx; numRanges ++; base_idx = idx + 1; // optimization for ftp urls @@ -127,178 +139,178 @@ string_length = cfStringLength; } (*theFlags) = flags; - (*range) = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0); - (*range)->location = ranges[0].location; - (*range)->length = ranges[0].length; - - return; + packedRanges[scheme_index].location = unpackedRanges[scheme_index].location; + packedRanges[scheme_index].length = unpackedRanges[scheme_index].length; + *numberOfRanges = 1; } - // URL is 1808-compliant - flags |= IS_DECOMPOSABLE; - - // 3: parse the network location and login - if (2 <= (string_length - base_idx) && '/' == characterArray[base_idx] && '/' == characterArray[base_idx+1]) { - CFIndex base = 2 + base_idx, extent; - for (idx = base; idx < string_length; idx++) { - if ('/' == characterArray[idx] || '?' == characterArray[idx]) { - break; - } - } - extent = idx; + else { + // URL is 1808-compliant + flags |= IS_DECOMPOSABLE; - // net_loc parts extend from base to extent (but not including), which might be to end of string - // net location is ":@:" - if (extent != base) { - for (idx = base; idx < extent; idx++) { - if ('@' == characterArray[idx]) { // there is a user - CFIndex idx2; - flags |= HAS_USER; - numRanges ++; - ranges[1].location = base; // base of the user - for (idx2 = base; idx2 < idx; idx2++) { - if (':' == characterArray[idx2]) { // found a password separator - flags |= HAS_PASSWORD; - numRanges ++; - ranges[2].location = idx2+1; // base of the password - ranges[2].length = idx-(idx2+1); // password extent - ranges[1].length = idx2 - base; // user extent - break; - } - } - if (!(flags & HAS_PASSWORD)) { - // user extends to the '@' - ranges[1].length = idx - base; // user extent - } - base = idx + 1; + // 3: parse the network location and login + if (2 <= (string_length - base_idx) && '/' == characterArray[base_idx] && '/' == characterArray[base_idx+1]) { + CFIndex base = 2 + base_idx, extent; + for (idx = base; idx < string_length; idx++) { + if ('/' == characterArray[idx] || '?' == characterArray[idx]) { break; } } - flags |= HAS_HOST; - numRanges ++; - ranges[3].location = base; // base of host + extent = idx; - // base has been advanced past the user and password if they existed - for (idx = base; idx < extent; idx++) { - // IPV6 support (RFC 2732) DCJ June/10/2002 - if ('[' == characterArray[idx]) { // starting IPV6 explicit address - // Find the ']' terminator of the IPv6 address, leave idx pointing to ']' or end - for ( ; idx < extent; ++ idx ) { - if ( ']' == characterArray[idx]) { - flags |= IS_IPV6_ENCODED; - break; + // net_loc parts extend from base to extent (but not including), which might be to end of string + // net location is ":@:" + if (extent != base) { + for (idx = base; idx < extent; idx++) { + if ('@' == characterArray[idx]) { // there is a user + CFIndex idx2; + flags |= HAS_USER; + numRanges ++; + unpackedRanges[user_index].location = base; // base of the user + for (idx2 = base; idx2 < idx; idx2++) { + if (':' == characterArray[idx2]) { // found a password separator + flags |= HAS_PASSWORD; + numRanges ++; + unpackedRanges[password_index].location = idx2+1; // base of the password + unpackedRanges[password_index].length = idx-(idx2+1); // password extent + unpackedRanges[user_index].length = idx2 - base; // user extent + break; + } } + if (!(flags & HAS_PASSWORD)) { + // user extends to the '@' + unpackedRanges[user_index].length = idx - base; // user extent + } + base = idx + 1; + break; } } - // there is a port if we see a colon. Only the last one is the port, though. - else if ( ':' == characterArray[idx]) { - flags |= HAS_PORT; - numRanges ++; - ranges[4].location = idx+1; // base of port - ranges[4].length = extent - (idx+1); // port extent - ranges[3].length = idx - base; // host extent - break; + flags |= HAS_HOST; + numRanges ++; + unpackedRanges[host_index].location = base; // base of host + + // base has been advanced past the user and password if they existed + for (idx = base; idx < extent; idx++) { + // IPV6 support (RFC 2732) DCJ June/10/2002 + if ('[' == characterArray[idx]) { // starting IPV6 explicit address + // Find the ']' terminator of the IPv6 address, leave idx pointing to ']' or end + for ( ; idx < extent; ++ idx ) { + if ( ']' == characterArray[idx]) { + flags |= IS_IPV6_ENCODED; + break; + } + } + } + // there is a port if we see a colon. Only the last one is the port, though. + else if ( ':' == characterArray[idx]) { + flags |= HAS_PORT; + numRanges ++; + unpackedRanges[port_index].location = idx+1; // base of port + unpackedRanges[port_index].length = extent - (idx+1); // port extent + unpackedRanges[host_index].length = idx - base; // host extent + break; + } + } + if (!(flags & HAS_PORT)) { + unpackedRanges[host_index].length = extent - base; // host extent } } - if (!(flags & HAS_PORT)) { - ranges[3].length = extent - base; // host extent - } + base_idx = extent; } - base_idx = extent; - } - - // 4: parse the query; remainder after left-most "?" is query - for (idx = base_idx; idx < string_length; idx++) { - if ('?' == characterArray[idx]) { - flags |= HAS_QUERY; - numRanges ++; - ranges[7].location = idx + 1; - ranges[7].length = string_length - (idx+1); - string_length = idx; // remove query from parse string - break; + + // 4: parse the query; remainder after left-most "?" is query + for (idx = base_idx; idx < string_length; idx++) { + if ('?' == characterArray[idx]) { + flags |= HAS_QUERY; + numRanges ++; + unpackedRanges[query_index].location = idx + 1; + unpackedRanges[query_index].length = string_length - (idx+1); + string_length = idx; // remove query from parse string + break; + } } - } - - // 5: parse the parameters; remainder after left-most ";" is parameters - for (idx = base_idx; idx < string_length; idx++) { - if (';' == characterArray[idx]) { - flags |= HAS_PARAMETERS; - numRanges ++; - ranges[6].location = idx + 1; - ranges[6].length = string_length - (idx+1); - string_length = idx; // remove parameters from parse string - break; + + // 5: parse the parameters; remainder after left-most ";" is parameters + for (idx = base_idx; idx < string_length; idx++) { + if (';' == characterArray[idx]) { + flags |= HAS_PARAMETERS; + numRanges ++; + unpackedRanges[parameters_index].location = idx + 1; + unpackedRanges[parameters_index].length = string_length - (idx+1); + string_length = idx; // remove parameters from parse string + break; + } } - } - - // 6: parse the path; it's whatever's left between string_length & base_idx - if (string_length - base_idx != 0 || (flags & NET_LOCATION_MASK)) - { - // If we have a net location, we are 1808-compliant, and an empty path substring implies a path of "/" - UniChar ch; - Boolean isDir; - CFRange pathRg; - flags |= HAS_PATH; - numRanges ++; - pathRg.location = base_idx; - pathRg.length = string_length - base_idx; - ranges[5] = pathRg; - if (pathRg.length > 0) { - Boolean sawPercent = FALSE; - for (idx = pathRg.location; idx < string_length; idx++) { - if ('%' == characterArray[idx]) { - sawPercent = TRUE; - break; + // 6: parse the path; it's whatever's left between string_length & base_idx + if (string_length - base_idx != 0 || (flags & NET_LOCATION_MASK)) + { + // If we have a net location, we are 1808-compliant, and an empty path substring implies a path of "/" + UniChar ch; + Boolean isDir; + CFRange pathRg; + flags |= HAS_PATH; + numRanges ++; + pathRg.location = base_idx; + pathRg.length = string_length - base_idx; + unpackedRanges[path_index] = pathRg; + + if (pathRg.length > 0) { + Boolean sawPercent = FALSE; + for (idx = pathRg.location; idx < string_length; idx++) { + if ('%' == characterArray[idx]) { + sawPercent = TRUE; + break; + } } - } #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - if (pathRg.length > 6 && characterArray[pathRg.location] == '/' && characterArray[pathRg.location + 1] == '.' && characterArray[pathRg.location + 2] == 'f' && characterArray[pathRg.location + 3] == 'i' && characterArray[pathRg.location + 4] == 'l' && characterArray[pathRg.location + 5] == 'e' && characterArray[pathRg.location + 6] == '/') { - flags |= PATH_HAS_FILE_ID; - } else if (!sawPercent) { - flags |= POSIX_AND_URL_PATHS_MATCH; - } + if (pathRg.length > 6 && characterArray[pathRg.location] == '/' && characterArray[pathRg.location + 1] == '.' && characterArray[pathRg.location + 2] == 'f' && characterArray[pathRg.location + 3] == 'i' && characterArray[pathRg.location + 4] == 'l' && characterArray[pathRg.location + 5] == 'e' && characterArray[pathRg.location + 6] == '/') { + flags |= PATH_HAS_FILE_ID; + } else if (!sawPercent) { + flags |= POSIX_AND_URL_PATHS_MATCH; + } #elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS - if (!sawPercent) { - flags |= POSIX_AND_URL_PATHS_MATCH; - } + if (!sawPercent) { + flags |= POSIX_AND_URL_PATHS_MATCH; + } #endif - - ch = characterArray[pathRg.location + pathRg.length - 1]; - if (ch == '/') { - isDir = true; - } else if (ch == '.') { - if (pathRg.length == 1) { + + ch = characterArray[pathRg.location + pathRg.length - 1]; + if (ch == '/') { isDir = true; - } else { - ch = characterArray[pathRg.location + pathRg.length - 2]; - if (ch == '/') { - isDir = true; - } else if (ch != '.') { - isDir = false; - } else if (pathRg.length == 2) { + } else if (ch == '.') { + if (pathRg.length == 1) { isDir = true; } else { - isDir = (characterArray[pathRg.location + pathRg.length - 3] == '/'); + ch = characterArray[pathRg.location + pathRg.length - 2]; + if (ch == '/') { + isDir = true; + } else if (ch != '.') { + isDir = false; + } else if (pathRg.length == 2) { + isDir = true; + } else { + isDir = (characterArray[pathRg.location + pathRg.length - 3] == '/'); + } } + } else { + isDir = false; } } else { - isDir = false; + isDir = (baseURL != NULL) ? CFURLHasDirectoryPath(baseURL) : false; + } + if (isDir) { + flags |= IS_DIRECTORY; } - } else { - isDir = (baseURL != NULL) ? CFURLHasDirectoryPath(baseURL) : false; - } - if (isDir) { - flags |= IS_DIRECTORY; } - } - - (*theFlags) = flags; - (*range) = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange)*numRanges, 0); - numRanges = 0; - for (idx = 0, flags = 1; flags != (1<<9); flags = (flags<<1), idx ++) { - if ((*theFlags) & flags) { - (*range)[numRanges] = ranges[idx]; - numRanges ++; + + (*theFlags) = flags; + *numberOfRanges = numRanges; + numRanges = 0; + for (idx = 0, flags = 1; flags != (1<<9); flags = (flags<<1), idx ++) { + if ((*theFlags) & flags) { + packedRanges[numRanges] = unpackedRanges[idx]; + numRanges ++; + } } } } diff --git a/CFURLAccess.c b/CFURLAccess.c index 91efeee..33e15d1 100644 --- a/CFURLAccess.c +++ b/CFURLAccess.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFURLAccess.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. - Responsibility: Chris Linn + Copyright (c) 1999-2014, Apple Inc. All rights reserved. + Responsibility: Jim Luther/Chris Linn */ /*------ diff --git a/CFURLAccess.h b/CFURLAccess.h index 1d57379..1552a4c 100644 --- a/CFURLAccess.h +++ b/CFURLAccess.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,14 +17,14 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFURLAccess.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. - CFURLAccess is deprecated as of Mac OS X 10.9 and iOS 7.0. The suggested replacement for URLs with network schemes (http, https, ftp, data) is the NSURLConnection class. The suggested replacement for URLs with the file scheme are the foundation classes NSFileManager, NSFileHandle and NSURL, or the CoreFoundation classes CFStream and CFURL. + CFURLAccess is deprecated as of Mac OS X 10.9 and iOS 7.0. The suggested replacement for URLs with network schemes (http, https, ftp, data) are the NSURLSession or NSURLConnection classes. The suggested replacement for URLs with the file scheme are the foundation classes NSFileManager, NSFileHandle and NSURL, or the CoreFoundation classes CFStream and CFURL. */ #if !defined(__COREFOUNDATION_CFURLACCESS__) @@ -38,6 +38,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN @@ -66,7 +67,7 @@ large files. */ /* Deprecated -- see top of this file for suggested replacement classes */ CF_EXPORT -Boolean CFURLCreateDataAndPropertiesFromResource(CFAllocatorRef alloc, CFURLRef url, CFDataRef *resourceData, CFDictionaryRef *properties, CFArrayRef desiredProperties, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +Boolean CFURLCreateDataAndPropertiesFromResource(CFAllocatorRef alloc, CFURLRef url, CFDataRef *resourceData, CFDictionaryRef *properties, CFArrayRef desiredProperties, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "For resource data, use the CFReadStream API. For file resource properties, use CFURLCopyResourcePropertiesForKeys."); /* Attempts to write the given data and properties to the given URL. If dataToWrite is NULL, only properties are written out (use @@ -78,21 +79,21 @@ CFURLCreateDataAndPropertiesFromResource(), above. */ /* Deprecated -- see top of this file for suggested replacement classes */ CF_EXPORT -Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef dataToWrite, CFDictionaryRef propertiesToWrite, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef dataToWrite, CFDictionaryRef propertiesToWrite, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "For resource data, use the CFWriteStream API. For file resource properties, use CFURLSetResourcePropertiesForKeys."); /* Destroys the resource indicated by url. Returns success or failure; errorCode set as above. */ /* Deprecated -- see top of this file for suggested replacement classes */ CF_EXPORT -Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use CFURLGetFileSystemRepresentation and removefile(3) instead."); /* Convenience method which calls through to CFURLCreateDataAndPropertiesFromResource(). Returns NULL on error and sets errorCode accordingly. */ /* Deprecated -- see top of this file for suggested replacement classes */ CF_EXPORT -CFTypeRef CFURLCreatePropertyFromResource(CFAllocatorRef alloc, CFURLRef url, CFStringRef property, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +CFTypeRef CFURLCreatePropertyFromResource(CFAllocatorRef alloc, CFURLRef url, CFStringRef property, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "For file resource properties, use CFURLCopyResourcePropertyForKey."); /* Common error codes (returned only by the older APIs that predate CFError) */ @@ -111,21 +112,21 @@ typedef CF_ENUM(CFIndex, CFURLError) { /* Older property keys */ CF_EXPORT -const CFStringRef kCFURLFileExists CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLFileExists CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use CFURLResourceIsReachable instead."); CF_EXPORT -const CFStringRef kCFURLFileDirectoryContents CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLFileDirectoryContents CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use the CFURLEnumerator API instead."); CF_EXPORT -const CFStringRef kCFURLFileLength CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLFileLength CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use CFURLCopyResourcePropertyForKey with kCFURLFileSizeKey instead."); CF_EXPORT -const CFStringRef kCFURLFileLastModificationTime CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLFileLastModificationTime CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use CFURLCopyResourcePropertyForKey with kCFURLContentModificationDateKey instead."); CF_EXPORT -const CFStringRef kCFURLFilePOSIXMode CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLFilePOSIXMode CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use CFURLCopyResourcePropertyForKey with kCFURLFileSecurityKey and then the CFFileSecurity API instead."); CF_EXPORT -const CFStringRef kCFURLFileOwnerID CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLFileOwnerID CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use CFURLCopyResourcePropertyForKey with kCFURLFileSecurityKey and then the CFFileSecurity API instead."); CF_EXPORT -const CFStringRef kCFURLHTTPStatusCode CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLHTTPStatusCode CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use NSHTTPURLResponse methods instead."); CF_EXPORT -const CFStringRef kCFURLHTTPStatusLine CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); +const CFStringRef kCFURLHTTPStatusLine CF_DEPRECATED(10_0, 10_9, 2_0, 7_0, "Use NSHTTPURLResponse methods instead."); /* The value of kCFURLFileExists is a CFBoolean */ /* The value of kCFURLFileDirectoryContents is a CFArray containing CFURLs. An empty array means the directory exists, but is empty */ @@ -139,6 +140,7 @@ const CFStringRef kCFURLHTTPStatusLine CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); /* The value of kCFURLHTTPStatusLine is a CFString */ CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFURLACCESS__ */ diff --git a/CFURLPriv.h b/CFURLPriv.h index 26ec2f2..720df11 100644 --- a/CFURLPriv.h +++ b/CFURLPriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFURLPriv.h - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. + Responsibility: Jim Luther/Chris Linn */ #if !defined(__COREFOUNDATION_CFURLPRIV__) @@ -34,18 +35,16 @@ #include #include #include -#if TARGET_OS_MAC -#include -#include #include #include #include +#if TARGET_OS_MAC +#include #endif CF_EXTERN_C_BEGIN -#if TARGET_OS_MAC - +// The kCFURLxxxxError enums are error codes in the Cocoa error domain and they mirror the exact same codes in (i.e. kCFURLReadNoPermissionError = NSFileReadNoPermissionError = 257). They were added to CFURLPriv.h so that CarbonCore and later CoreServicesInternal could return these error codes in the Cocoa error domain. If your code links with Foundation, you should use the codes in , not these codes. enum { // Resource I/O related errors, with kCFErrorURLKey containing URL kCFURLNoSuchResourceError = 4, // Attempt to do a file system operation on a non-existent file @@ -132,6 +131,9 @@ CF_EXPORT const CFStringRef _kCFURLFileAllocatedSizeOfResourceForkKey CF_AVAILAB CF_EXPORT const CFStringRef _kCFURLEffectiveIconImageDataKey CF_AVAILABLE(10_6, 4_0); /* Icon image data, i.e. raw pixel data (CFData) */ +CF_EXPORT const CFStringRef _kCFURLTypeBindingKey CF_AVAILABLE(10_10, 8_0); + /* Type binding for icon (Read-only, value type CFData) */ + CF_EXPORT const CFStringRef _kCFURLCustomIconImageDataKey CF_AVAILABLE(10_6, 4_0); /* Icon image data of the item's custom icon, if any (CFData) */ @@ -257,6 +259,12 @@ CF_EXPORT const CFStringRef _kCFURLVolumeIOMediaIconFamilyNameKey CF_AVAILABLE(1 CF_EXPORT const CFStringRef _kCFURLVolumeIOMediaIconBundleIdentifierKey CF_AVAILABLE(10_9, NA); /* Volume's IOMediaIconBundleIdentifier. (CFStringRef) */ +CF_EXPORT const CFStringRef _kCFURLVolumeQuarantinePropertiesKey CF_AVAILABLE(10_10, NA); + /* The quarantine properties for the volume on which the resource resides as defined in LSQuarantine.h.=To remove quarantine information from a volume, pass kCFNull as the value when setting this property. (Read-write, value type CFDictionary) */ + +CF_EXPORT const CFStringRef _kCFURLVolumeOpenFolderURLKey CF_AVAILABLE(10_10, NA); + /* Returns a URL to the folder the Finder should open when a HFS volume is mounted, or NULL if there is none. (Read-only, value type CFURL) */ + CF_EXPORT const CFStringRef _kCFURLResolvedFromBookmarkDataKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); /* Deprecated and scheduled for removal later in 10.9/7.0 since it is unused (*/ @@ -267,8 +275,28 @@ CF_EXPORT const CFStringRef _kCFURLCompleteMountURLKey CF_DEPRECATED(10_6, 10_9, /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeURLForRemountingKey or NSURLVolumeURLForRemountingKey public property keys */ CF_EXPORT const CFStringRef _kCFURLUbiquitousItemDownloadRequestedKey CF_AVAILABLE(10_9, 7_0); + /* Is this Ubiquity item scheduled for download? (this is also true for items that are already downloaded). Use startDownloadingUbiquitousItemAtURL:error: to make this true (Read-only, value type CFBoolean) */ + +CF_EXPORT const CFStringRef _kCFURLCloudDocsPlaceholderDictionaryKey CF_AVAILABLE(10_10, 8_0); + /* Returns the placeholder dictionary for a side-fault file (Read-only, value type CFDictionary) */ + +CF_EXPORT const CFStringRef _kCFURLCloudDocsPlaceholderLogicalNameKey CF_AVAILABLE(10_10, 8_0); + /* Returns the placeholder dictionary for a side-fault file (Read-only, value type CFString) */ + +// Temporary holding place for future API. + +CF_EXPORT const CFStringRef kCFURLUbiquitousItemDownloadRequestedKey CF_AVAILABLE(10_9, 7_0); /* Is this Ubiquity item scheduled for download? (this is also true for items that are already downloaded). Use startDownloadingUbiquitousItemAtURL:error: to make this true (Read-only, value type CFBoolean) */ +CF_EXPORT const CFStringRef kCFURLUbiquitousItemContainerDisplayNameKey CF_AVAILABLE(10_10, 8_0); + /* Returns the localized name of the ubiquity container that contains this item (Read-only, value type CFString) */ + +// these keys are defined here, not in CFURL.h, because they return NSImage values which can only be used by Foundation +CF_EXPORT const CFStringRef kCFURLThumbnailDictionaryKey CF_AVAILABLE(10_10, 8_0); +CF_EXPORT const CFStringRef kCFURLThumbnailKey CF_AVAILABLE(10_10, 8_0); +// The values of thumbnails in the dictionary returned by NSURLThumbnailDictionaryKey +CF_EXPORT const CFStringRef kCFThumbnail1024x1024SizeKey CF_AVAILABLE(10_10, 8_0); + /* Some common boolean properties can be accessed as a bitfield @@ -493,18 +521,6 @@ Boolean _CFURLCacheResourcePropertyForKey(CFURLRef url, CFStringRef key, CFError CF_EXPORT Boolean _CFURLCacheResourcePropertiesForKeys(CFURLRef url, CFArrayRef keys, CFErrorRef *error) CF_AVAILABLE(10_8, NA); - -/* - _CFURLSetResourcePropertyForKeyAndUpdateFileCache - Works mostly like CFURLSetResourcePropertyForKey - except that file system properties are updated in the URL's file cache (if it has a valid cache) - and dependant properties are not flushed. This means that values in the cache may not match what - is on the file system (see for details). - - Only for use by DesktopServices! - */ -CF_EXPORT -Boolean _CFURLSetResourcePropertyForKeyAndUpdateFileCache(CFURLRef url, CFStringRef key, CFTypeRef propertyValue, CFErrorRef *error) CF_AVAILABLE(10_7, NA); - /* _CFURLCreateDisplayPathComponentsArray() @@ -572,29 +588,54 @@ enum { _CFURLItemReplacementWithoutDeletingBackupItem = 1 << 4 }; +/* _CFURLReplaceObject is the underlying implementation for -[NSFileManager replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:] with one additional argument: newName. The optional newName argument can be used to rename the replacement (for example, when replacing "document.rtf" with "document.rtfd") while still preserving the document's metadata. If newName is used, there must be a file or directory at originalItemURL -- if originalItemURL does not exist and newName is not NULL, an error will be returned. + */ CF_EXPORT Boolean _CFURLReplaceObject( CFAllocatorRef allocator, CFURLRef originalItemURL, CFURLRef newItemURL, CFStringRef newName, CFStringRef backupItemName, CFOptionFlags options, CFURLRef *resultingURL, CFErrorRef *error ) CF_AVAILABLE(10_7, 5_0); +CF_EXPORT +Boolean _CFURLIsProtectedDirectory(CFURLRef directoryURL) CF_AVAILABLE(10_10, NA); + +/* _CFURLAttachSecurityScopeToFileURL attaches a sandbox extension to the file URL object. The URL object will then be security-scoped and will be usable with the NSURL's -startAccessingSecurityScopedResource method and CFURL's CFURLStartAccessingSecurityScopedResource() function. The URL object must be a file URL. If the URL object already has a sandbox extension attached, the new extension replaces the previous sandbox extension. If NULL is passed for the sandboxExtension, the sandbox extension (if any) is removed from the URL object. Callers would be responsible for ensuring the sandbox extension matches the URL's file system path. + */ +CF_EXPORT +void _CFURLAttachSecurityScopeToFileURL(CFURLRef url, CFDataRef sandboxExtension) CF_AVAILABLE(10_10, 8_0); + +/* _CFURLCopySecurityScopeFromFileURL copies the sandbox extension attached to the file URL object. If the URL is not a file URL or doesn't have a sandbox extension, NULL will be returned. + */ +CF_EXPORT +CFDataRef _CFURLCopySecurityScopeFromFileURL(CFURLRef url) CF_AVAILABLE(10_10, 8_0); + +CF_EXPORT +void _CFURLSetPermanentResourcePropertyForKey(CFURLRef url, CFStringRef key, CFTypeRef propertyValue) CF_AVAILABLE(10_10, 8_0); -#if (TARGET_OS_MAC) || CF_BUILDING_CF || NSBUILDINGFOUNDATION CF_EXPORT CFURLEnumeratorResult _CFURLEnumeratorGetURLsBulk(CFURLEnumeratorRef enumerator, CFIndex maximumURLs, CFIndex *actualURLs, CFURLRef *urls, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0); -#endif -#if TARGET_OS_MAC +// Returns a string describing the bookmark data. For debugging purposes only. +CF_EXPORT +CFStringRef _CFURLBookmarkCopyDescription(CFDataRef bookmarkRef) CF_AVAILABLE(10_10, 8_0); + +// private CFURLBookmarkCreationOptions +enum { + kCFURLBookmarkCreationWithFileProvider CF_ENUM_AVAILABLE(10_10, 8_0) = ( 1UL << 26 ), // private option to create bookmarks with file provider string. The file provider string overrides the rest of the bookmark data at resolution time. + kCFURLBookmarkOperatingInsideScopedBookmarksAgent = (1UL << 27), // private option used internally by ScopedBookmarkAgent to prevent recursion between the agent and the framework code. Available 10_7, NA + kCFURLBookmarkCreationAllowCreationIfResourceDoesNotExistMask = ( 1UL << 28 ), // allow creation of a bookmark to a file: scheme with a CFURLRef of item which may not exist. If the filesystem item does not exist, the created bookmark contains essentially no properties beyond the url string. Available 10_7, 5_0. + kCFURLBookmarkCreationDoNotIncludeSandboxExtensionsMask = ( 1UL << 29 ), // If set, sandbox extensions are not included in created bookmarks. Ordinarily, bookmarks (except those created suitable for putting into a bookmark file) will have a sandbox extension added for the item. Available 10_7, NA. + kCFURLBookmarkCreationSuitableForOdocAppleEvent = ( 1UL << 31 ), // add properties we guarantee will be in an odoc AppleEvent. Available 10_10, NA (but supported back to 10.6). +}; +// private CFURLBookmarkFileCreationOptions enum { + // FIXME: These three options (kCFBookmarkFileCreationWithoutOverwritingExistingFile, kCFBookmarkFileCreationWithoutAppendingAliasExtension, and kCFBookmarkFileCreationWithoutCreatingResourceFork) are not implemented and have never been used. kCFBookmarkFileCreationWithoutOverwritingExistingFile = ( 1UL << 8 ), // if destination file already exists don't overwrite it and return an error kCFBookmarkFileCreationWithoutAppendingAliasExtension = ( 1UL << 9 ), // don't add / change whatever extension is on the created alias file kCFBookmarkFileCreationWithoutCreatingResourceFork = ( 1UL << 10 ), // don't create the resource-fork half of the alias file - - kCFURLBookmarkCreationAllowCreationIfResourceDoesNotExistMask = ( 1 << 28 ), // allow creation of a bookmark to a file: scheme with a CFURLRef of item which may not exist. If the filesystem item does not exist, the created bookmark contains essentially no properties beyond the url string. - - kCFURLBookmarkCreationDoNotIncludeSandboxExtensionsMask = ( 1 << 29 ), // If set, sandbox extensions are not included in created bookmarks. Ordinarily, bookmarks ( except those created suitable for putting into a bookmark file ) will have a sandbox extension added for the item }; +// private CFURLBookmarkResolutionOptions enum { - kCFBookmarkResolutionPerformRelativeResolutionFirstMask CF_ENUM_AVAILABLE(10_8,6_0) = ( 1 << 11 ), // perform relative resolution before absolute resolution. If this bit is set, for this to be useful a relative URL must also have been passed in and the bookmark when created must have been created relative to another url. + kCFBookmarkResolutionPerformRelativeResolutionFirstMask CF_ENUM_AVAILABLE(10_8, 6_0) = ( 1UL << 11 ), // perform relative resolution before absolute resolution. If this bit is set, for this to be useful a relative URL must also have been passed in and the bookmark when created must have been created relative to another url. }; typedef CF_ENUM(CFIndex, CFURLBookmarkMatchResult) { @@ -604,7 +645,7 @@ typedef CF_ENUM(CFIndex, CFURLBookmarkMatchResult) { kCFURLBookmarkComparisonLikelyToMatch = 0x00004000, /* it is likely that the two items refer to the same filesystem item ( but, they may not ) */ kCFURLBookmarkComparisonMatch = 0x00008000, /* the two items refer to the same item, but other information in the bookmarks may not match */ kCFURLBookmarkComparisonExactMatch = 0x0000f000 /* the two bookmarks are identical */ -}; +}; // Available 10_7, NA. /* The relativeToURL and matchingPropertyKeys parameters are not used and are ignored */ CF_EXPORT @@ -613,7 +654,8 @@ CFURLBookmarkMatchResult _CFURLBookmarkDataCompare(CFDataRef bookmark1Ref, CFDat CF_EXPORT OSStatus _CFURLBookmarkDataToAliasHandle(CFDataRef bookmarkRef, void* aliasHandleP) CF_AVAILABLE(10_7, NA); -#endif +CF_EXPORT +CFURLRef _CFURLCreateByResolvingAliasFile(CFAllocatorRef allocator, CFURLRef url, CFURLBookmarkResolutionOptions options, CFArrayRef propertiesToInclude, CFErrorRef *error ) CF_AVAILABLE(10_10, 8_0); /* The following are properties that can be asked of bookmark data objects in addition to the resource properties @@ -625,8 +667,7 @@ extern const CFStringRef kCFURLBookmarkOriginalRelativePathKey CF_AVAILABLE(10_7 extern const CFStringRef kCFURLBookmarkOriginalRelativePathComponentsArrayKey CF_AVAILABLE(10_7, 5_0); extern const CFStringRef kCFURLBookmarkOriginalVolumeNameKey CF_AVAILABLE(10_7, 5_0); extern const CFStringRef kCFURLBookmarkOriginalVolumeCreationDateKey CF_AVAILABLE(10_7, 5_0); - -#endif /* TARGET_OS_MAC */ +extern const CFStringRef kCFURLBookmarkFileProviderStringKey CF_AVAILABLE(10_10, 8_0); CF_EXTERN_C_END diff --git a/CFUUID.c b/CFUUID.c index 68d9f46..c8786f8 100644 --- a/CFUUID.c +++ b/CFUUID.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUUID.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -36,7 +36,10 @@ static CFMutableDictionaryRef _uniquedUUIDs = NULL; CF_INLINE void LOCKED(dispatch_block_t work) { static dispatch_once_t guard; static dispatch_queue_t CFUUIDGlobalDataLock; - dispatch_once(&guard, ^{ CFUUIDGlobalDataLock = dispatch_queue_create("CFUUID global uniquing table lock", 0); }); + dispatch_once(&guard, ^{ + dispatch_queue_attr_t dqattr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qos_class_main(), 0); + CFUUIDGlobalDataLock = dispatch_queue_create("com.apple.CFUUID", dqattr); + }); dispatch_sync(CFUUIDGlobalDataLock, work); } @@ -44,12 +47,12 @@ CF_INLINE void LOCKED(dispatch_block_t work) { // Platforms without dispatch static CFMutableDictionaryRef _uniquedUUIDs = NULL; -static CFSpinLock_t _uniquedUUIDsLock = CFSpinLockInit; +static CFLock_t _uniquedUUIDsLock = CFLockInit; CF_INLINE void LOCKED(void (^work)(void)) { - __CFSpinLock(&_uniquedUUIDsLock); + __CFLock(&_uniquedUUIDsLock); work(); - __CFSpinUnlock(&_uniquedUUIDsLock); + __CFUnlock(&_uniquedUUIDsLock); } #endif @@ -232,11 +235,9 @@ static const CFRuntimeClass __CFUUIDClass = { __CFUUIDCopyDescription }; -CF_PRIVATE void __CFUUIDInitialize(void) { - __kCFUUIDTypeID = _CFRuntimeRegisterClass(&__CFUUIDClass); -} - CFTypeID CFUUIDGetTypeID(void) { + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFUUIDTypeID = _CFRuntimeRegisterClass(&__CFUUIDClass); }); return __kCFUUIDTypeID; } @@ -247,7 +248,7 @@ static CFUUIDRef __CFUUIDCreateWithBytesPrimitive(CFAllocatorRef allocator, CFUU if (!uuid) { size_t size; size = sizeof(__CFUUID_t) - sizeof(CFRuntimeBase); - uuid = (__CFUUID_t *)_CFRuntimeCreateInstance(kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : allocator, __kCFUUIDTypeID, size, NULL); + uuid = (__CFUUID_t *)_CFRuntimeCreateInstance(kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : allocator, CFUUIDGetTypeID(), size, NULL); if (!uuid) return; diff --git a/CFUUID.h b/CFUUID.h index 885873a..e404661 100644 --- a/CFUUID.h +++ b/CFUUID.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUUID.h - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUUID__) diff --git a/CFUniChar.c b/CFUniChar.c index 6693809..a37f9d5 100644 --- a/CFUniChar.c +++ b/CFUniChar.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUniChar.c - Copyright (c) 2001-2013, Apple Inc. All rights reserved. + Copyright (c) 2001-2014, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -287,9 +287,11 @@ static bool __CFUniCharLoadFile(const wchar_t *bitmapName, const void **bytes, i } // Bitmap functions -CF_INLINE bool isControl(UTF32Char theChar, uint16_t charset, const void *data) { // ISO Control +/* + Currently unused but left in for symmetry/informative purposes + CF_INLINE bool isControl(UTF32Char theChar, uint16_t charset, const void *data) { // ISO Control return (((theChar <= 0x001F) || (theChar >= 0x007F && theChar <= 0x009F)) ? true : false); -} +}*/ CF_INLINE bool isWhitespace(UTF32Char theChar, uint16_t charset, const void *data) { // Space return (((theChar == 0x0020) || (theChar == 0x0009) || (theChar == 0x00A0) || (theChar == 0x1680) || (theChar >= 0x2000 && theChar <= 0x200B) || (theChar == 0x202F) || (theChar == 0x205F) || (theChar == 0x3000)) ? true : false); @@ -344,7 +346,7 @@ static char __CFUniCharUnicodeVersionString[8] = {0, 0, 0, 0, 0, 0, 0, 0}; static uint32_t __CFUniCharNumberOfBitmaps = 0; static __CFUniCharBitmapData *__CFUniCharBitmapDataArray = NULL; -static CFSpinLock_t __CFUniCharBitmapLock = CFSpinLockInit; +static CFLock_t __CFUniCharBitmapLock = CFLockInit; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #if !defined(CF_UNICHAR_BITMAP_FILE) @@ -374,10 +376,10 @@ static bool __CFUniCharLoadBitmapData(void) { int idx, bitmapIndex; int64_t fileSize; - __CFSpinLock(&__CFUniCharBitmapLock); + __CFLock(&__CFUniCharBitmapLock); if (__CFUniCharBitmapDataArray || !__CFUniCharLoadFile(CF_UNICHAR_BITMAP_FILE, &bytes, &fileSize) || !__CFSimpleFileSizeVerification(bytes, fileSize)) { - __CFSpinUnlock(&__CFUniCharBitmapLock); + __CFUnlock(&__CFUniCharBitmapLock); return false; } @@ -425,7 +427,7 @@ static bool __CFUniCharLoadBitmapData(void) { __CFUniCharBitmapDataArray = array; - __CFSpinUnlock(&__CFUniCharBitmapLock); + __CFUnlock(&__CFUniCharBitmapLock); return true; } @@ -649,7 +651,7 @@ CF_PRIVATE uint32_t CFUniCharGetNumberOfPlanes(uint32_t charset) { // Mapping data loading static const void **__CFUniCharMappingTables = NULL; -static CFSpinLock_t __CFUniCharMappingTableLock = CFSpinLockInit; +static CFLock_t __CFUniCharMappingTableLock = CFLockInit; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #if __CF_BIG_ENDIAN__ @@ -685,7 +687,7 @@ static CFSpinLock_t __CFUniCharMappingTableLock = CFSpinLockInit; CF_PRIVATE const void *CFUniCharGetMappingData(uint32_t type) { - __CFSpinLock(&__CFUniCharMappingTableLock); + __CFLock(&__CFUniCharMappingTableLock); if (NULL == __CFUniCharMappingTables) { const void *bytes; @@ -695,7 +697,7 @@ CF_PRIVATE const void *CFUniCharGetMappingData(uint32_t type) { int64_t fileSize; if (!__CFUniCharLoadFile(MAPPING_TABLE_FILE, &bytes, &fileSize) || !__CFSimpleFileSizeVerification(bytes, fileSize)) { - __CFSpinUnlock(&__CFUniCharMappingTableLock); + __CFUnlock(&__CFUniCharMappingTableLock); return NULL; } @@ -722,7 +724,7 @@ CF_PRIVATE const void *CFUniCharGetMappingData(uint32_t type) { } } - __CFSpinUnlock(&__CFUniCharMappingTableLock); + __CFUnlock(&__CFUniCharMappingTableLock); return __CFUniCharMappingTables[type]; } @@ -766,10 +768,10 @@ static bool __CFUniCharLoadCaseMappingTable(void) { if (NULL == __CFUniCharMappingTables) (void)CFUniCharGetMappingData(kCFUniCharToLowercase); if (NULL == __CFUniCharMappingTables) return false; - __CFSpinLock(&__CFUniCharMappingTableLock); + __CFLock(&__CFUniCharMappingTableLock); if (__CFUniCharCaseMappingTableCounts) { - __CFSpinUnlock(&__CFUniCharMappingTableLock); + __CFUnlock(&__CFUniCharMappingTableLock); return true; } @@ -785,7 +787,7 @@ static bool __CFUniCharLoadCaseMappingTable(void) { __CFUniCharCaseMappingTableCounts = countArray; - __CFSpinUnlock(&__CFUniCharMappingTableLock); + __CFUnlock(&__CFUniCharMappingTableLock); return true; } @@ -1178,7 +1180,7 @@ CF_PRIVATE uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char theChar, U static __CFUniCharBitmapData *__CFUniCharUnicodePropertyTable = NULL; static int __CFUniCharUnicodePropertyTableCount = 0; -static CFSpinLock_t __CFUniCharPropTableLock = CFSpinLockInit; +static CFLock_t __CFUniCharPropTableLock = CFLockInit; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #if USE_MACHO_SEGMENT @@ -1198,7 +1200,7 @@ static CFSpinLock_t __CFUniCharPropTableLock = CFSpinLockInit; const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint32_t plane) { - __CFSpinLock(&__CFUniCharPropTableLock); + __CFLock(&__CFUniCharPropTableLock); if (NULL == __CFUniCharUnicodePropertyTable) { __CFUniCharBitmapData *table; @@ -1212,7 +1214,7 @@ const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint3 int64_t fileSize; if (!__CFUniCharLoadFile(PROP_DB_FILE, &bytes, &fileSize) || !__CFSimpleFileSizeVerification(bytes, fileSize)) { - __CFSpinUnlock(&__CFUniCharPropTableLock); + __CFUnlock(&__CFUniCharPropTableLock); return NULL; } @@ -1262,7 +1264,7 @@ const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint3 __CFUniCharUnicodePropertyTable = table; } - __CFSpinUnlock(&__CFUniCharPropTableLock); + __CFUnlock(&__CFUniCharPropTableLock); return (plane < __CFUniCharUnicodePropertyTable[propertyType]._numPlanes ? __CFUniCharUnicodePropertyTable[propertyType]._planes[plane] : NULL); } @@ -1406,7 +1408,7 @@ void __CFUniCharCleanup(void) int idx; // cleanup memory allocated by __CFUniCharLoadBitmapData() - __CFSpinLock(&__CFUniCharBitmapLock); + __CFLock(&__CFUniCharBitmapLock); if (__CFUniCharBitmapDataArray != NULL) { for (idx = 0; idx < (int)__CFUniCharNumberOfBitmaps; idx++) { @@ -1419,10 +1421,10 @@ void __CFUniCharCleanup(void) __CFUniCharNumberOfBitmaps = 0; } - __CFSpinUnlock(&__CFUniCharBitmapLock); + __CFUnlock(&__CFUniCharBitmapLock); // cleanup memory allocated by CFUniCharGetMappingData() - __CFSpinLock(&__CFUniCharMappingTableLock); + __CFLock(&__CFUniCharMappingTableLock); if (__CFUniCharMappingTables != NULL) { CFAllocatorDeallocate(kCFAllocatorSystemDefault, __CFUniCharMappingTables); @@ -1438,10 +1440,10 @@ void __CFUniCharCleanup(void) __CFUniCharCaseMappingExtraTable = NULL; } - __CFSpinUnlock(&__CFUniCharMappingTableLock); + __CFUnlock(&__CFUniCharMappingTableLock); // cleanup memory allocated by CFUniCharGetUnicodePropertyDataForPlane() - __CFSpinLock(&__CFUniCharPropTableLock); + __CFLock(&__CFUniCharPropTableLock); if (__CFUniCharUnicodePropertyTable != NULL) { for (idx = 0; idx < __CFUniCharUnicodePropertyTableCount; idx++) { @@ -1454,7 +1456,7 @@ void __CFUniCharCleanup(void) __CFUniCharUnicodePropertyTableCount = 0; } - __CFSpinUnlock(&__CFUniCharPropTableLock); + __CFUnlock(&__CFUniCharPropTableLock); } #endif diff --git a/CFUniChar.h b/CFUniChar.h index 7b95573..9bcd896 100644 --- a/CFUniChar.h +++ b/CFUniChar.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUniChar.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUNICHAR__) diff --git a/CFUniCharPriv.h b/CFUniCharPriv.h index b285a15..e332fe1 100644 --- a/CFUniCharPriv.h +++ b/CFUniCharPriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUniCharPriv.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUNICHARPRIV__) diff --git a/CFUniCharPropertyDatabase.data b/CFUniCharPropertyDatabase.data index 2cc8e6e0369bfb94d9e7df89ae4fb64e185ad792..e5de170467bdc85f12cf3cd3791aa17a6df8e632 100644 GIT binary patch delta 62 zcmZ4TgK^0ZMkX`kjZ6mij9ilqZDvh=U?woxKrel=i^K29iyf^uS2+r>vM>O_jDCkHrlZ2se>VG01e5EaV+ delta 66 zcmZ4TgK^0ZMkX_(jZ6mij69PKZDvh=U?woxKrel=i^K294wjNYw$kP*M*&tAMj)8n U=N35mk(header.msgh_size > sizeof(mach_msg_base_t)) { CFDataRef responseData = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)msg + sizeof(mach_msg_base_t), msg->header.msgh_size - sizeof(mach_msg_base_t)); if (responseData) { - userNotification->_responseDictionary = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, responseData, kCFPropertyListImmutable, NULL); + userNotification->_responseDictionary = CFPropertyListCreateWithData(kCFAllocatorSystemDefault, responseData, kCFPropertyListImmutable, NULL, NULL); CFRelease(responseData); } } @@ -341,7 +338,7 @@ SInt32 CFUserNotificationReceiveResponse(CFUserNotificationRef userNotification, if (msg->header.msgh_size > sizeof(mach_msg_base_t)) { responseData = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)msg + sizeof(mach_msg_base_t), msg->header.msgh_size - sizeof(mach_msg_base_t)); if (responseData) { - userNotification->_responseDictionary = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, responseData, kCFPropertyListImmutable, NULL); + userNotification->_responseDictionary = CFPropertyListCreateWithData(kCFAllocatorSystemDefault, responseData, kCFPropertyListImmutable, NULL, NULL); CFRelease(responseData); } } diff --git a/CFUserNotification.h b/CFUserNotification.h index ae1a2d0..81271f8 100644 --- a/CFUserNotification.h +++ b/CFUserNotification.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUserNotification.h - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUSERNOTIFICATION__) @@ -35,6 +35,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFUserNotification * CFUserNotificationRef; @@ -198,6 +199,7 @@ const CFStringRef kCFUserNotificationKeyboardTypesKey; #endif CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFUSERNOTIFICATION__ */ diff --git a/CFUtilities.c b/CFUtilities.c index cedf97f..9e5dc68 100644 --- a/CFUtilities.c +++ b/CFUtilities.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUtilities.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -35,8 +35,6 @@ #endif #include #include -#include -#include #if DEPLOYMENT_TARGET_WINDOWS #include #endif @@ -51,6 +49,7 @@ #define ASL_LEVEL_DEBUG 7 #endif + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI #include #include @@ -180,51 +179,6 @@ CF_PRIVATE void __CFDumpAllPointerLocations(uintptr_t ptr) { } #endif -#if DEPLOYMENT_TARGET_WINDOWS -struct _args { - void *func; - void *arg; - HANDLE handle; -}; -static unsigned __stdcall __CFWinThreadFunc(void *arg) { - struct _args *args = (struct _args*)arg; - ((void (*)(void *))args->func)(args->arg); - CloseHandle(args->handle); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, arg); - _endthreadex(0); - return 0; -} -#endif - -CF_PRIVATE void *__CFStartSimpleThread(void *func, void *arg) { -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD - pthread_attr_t attr; - pthread_t tid = 0; - pthread_attr_init(&attr); - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&attr, 60 * 1024); // 60K stack for our internal threads is sufficient - OSMemoryBarrier(); // ensure arg is fully initialized and set in memory - pthread_create(&tid, &attr, func, arg); - pthread_attr_destroy(&attr); -//warning CF: we dont actually know that a pthread_t is the same size as void * - return (void *)tid; -#elif DEPLOYMENT_TARGET_WINDOWS - unsigned tid; - struct _args *args = (struct _args*)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(struct _args), 0); - if (__CFOASafe) __CFSetLastAllocationEventName(args, "CFUtilities (thread-args)"); - HANDLE handle; - args->func = func; - args->arg = arg; - /* The thread is created suspended, because otherwise there would be a race between the assignment below of the handle field, and it's possible use in the thread func above. */ - args->handle = (HANDLE)_beginthreadex(NULL, 0, __CFWinThreadFunc, args, CREATE_SUSPENDED, &tid); - handle = args->handle; - ResumeThread(handle); - return handle; -#endif -} - - // Looks for localized version of "nonLocalized" in the SystemVersion bundle // If not found, and returnNonLocalizedFlag == true, will return the non localized string (retained of course), otherwise NULL // If bundlePtr != NULL, will use *bundlePtr and will return the bundle in there; otherwise bundle is created and released @@ -259,7 +213,7 @@ static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) { #pragma GCC diagnostic ignored "-Wdeprecated" if (url && CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, url, &data, NULL, NULL, NULL)) { #pragma GCC diagnostic pop - plist = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListMutableContainers, NULL); + plist = CFPropertyListCreateWithData(kCFAllocatorSystemDefault, data, kCFPropertyListMutableContainers, NULL, NULL); CFRelease(data); } if (url) CFRelease(url); @@ -341,15 +295,29 @@ CFStringRef CFCopySystemVersionString(void) { // Proper caching and testing to see if the file has changed, without race // conditions, would require semi-convoluted use of fstat(). +static CFStringRef copySystemVersionPath(CFStringRef suffix) { +#if TARGET_IPHONE_SIMULATOR + const char *simulatorRoot = getenv("IPHONE_SIMULATOR_ROOT"); + if (!simulatorRoot) simulatorRoot = getenv("CFFIXED_USER_HOME"); + if (!simulatorRoot) simulatorRoot = "/"; + return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%s%@"), simulatorRoot, suffix); +#else + return suffix; +#endif +} + + CFDictionaryRef _CFCopySystemVersionDictionary(void) { - CFPropertyListRef plist = NULL; - plist = _CFCopyVersionDictionary(CFSTR("/System/Library/CoreServices/SystemVersion.plist")); + CFStringRef path = copySystemVersionPath(CFSTR("/System/Library/CoreServices/SystemVersion.plist")); + CFPropertyListRef plist = _CFCopyVersionDictionary(path); + CFRelease(path); return (CFDictionaryRef)plist; } CFDictionaryRef _CFCopyServerVersionDictionary(void) { - CFPropertyListRef plist = NULL; - plist = _CFCopyVersionDictionary(CFSTR("/System/Library/CoreServices/ServerVersion.plist")); + CFStringRef path = copySystemVersionPath(CFSTR("/System/Library/CoreServices/ServerVersion.plist")); + CFPropertyListRef plist = _CFCopyVersionDictionary(path); + CFRelease(path); return (CFDictionaryRef)plist; } @@ -417,15 +385,6 @@ CF_PRIVATE void *__CFLookupCFNetworkFunction(const char *name) { } #endif - -#ifndef __CFGetSessionID_defined - -CF_PRIVATE uint32_t __CFGetSessionID(void) { - return 0; -} - -#endif - CF_PRIVATE CFIndex __CFActiveProcessorCount() { int32_t pcnt; #if DEPLOYMENT_TARGET_WINDOWS @@ -603,24 +562,22 @@ static void __CFLogCString(int32_t lev, const char *message, size_t length, char #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX // The banner path may use CF functions, but the rest of this function should not. It may be called at times when CF is not fully setup or torn down. if (withBanner) { + double dummy; CFAbsoluteTime at = CFAbsoluteTimeGetCurrent(); - CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian); - if (!calendar) goto after_banner; - CFTimeZoneRef tz = CFTimeZoneCopySystem(); - if (!tz) { - CFRelease(calendar); - goto after_banner; - } - CFCalendarSetTimeZone(calendar, tz); - CFRelease(tz); - int32_t year, month, day, hour, minute, second; - Boolean dec = CFCalendarDecomposeAbsoluteTime(calendar, at, "yMdHms", &year, &month, &day, &hour, &minute, &second); - CFRelease(calendar); - if (!dec) goto after_banner; - double atf; - int32_t ms = (int32_t)floor(1000.0 * modf(at, &atf)); + time_t tv = floor(at + kCFAbsoluteTimeIntervalSince1970); + struct tm mine; + localtime_r(&tv, &mine); + int32_t year = mine.tm_year + 1900; + int32_t month = mine.tm_mon + 1; + int32_t day = mine.tm_mday; + int32_t hour = mine.tm_hour; + int32_t minute = mine.tm_min; + int32_t second = mine.tm_sec; + int32_t ms = (int32_t)floor(1000.0 * modf(at, &dummy)); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - asprintf(&banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), pthread_mach_thread_np(pthread_self())); + uint64_t tid = 0; + if (0 != pthread_threadid_np(NULL, &tid)) tid = pthread_mach_thread_np(pthread_self()); + asprintf(&banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%llu] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), tid); asprintf(&thread, "%x", pthread_mach_thread_np(pthread_self())); #elif DEPLOYMENT_TARGET_WINDOWS bannerLen = asprintf(&banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), GetCurrentThreadId()); @@ -632,7 +589,6 @@ static void __CFLogCString(int32_t lev, const char *message, size_t length, char asprintf(&time, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, minute, second, ms); } - after_banner:; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS uid_t euid; __CFGetUGIDs(&euid, NULL); @@ -661,10 +617,10 @@ static void __CFLogCString(int32_t lev, const char *message, size_t length, char v[2].iov_base = "\n"; v[2].iov_len = (message[length - 1] != '\n') ? 1 : 0; int nv = (v[0].iov_base ? 1 : 0) + 1 + (v[2].iov_len ? 1 : 0); - static CFSpinLock_t lock = CFSpinLockInit; - __CFSpinLock(&lock); + static CFLock_t lock = CFLockInit; + __CFLock(&lock); writev(STDERR_FILENO, v[0].iov_base ? v : v + 1, nv); - __CFSpinUnlock(&lock); + __CFUnlock(&lock); #elif DEPLOYMENT_TARGET_WINDOWS size_t bufLen = bannerLen + length + 1; char *buf = (char *)malloc(sizeof(char) * bufLen); @@ -705,14 +661,14 @@ static void __CFLogCString(int32_t lev, const char *message, size_t length, char if (banner) free(banner); if (uid) free(uid); } - -CF_EXPORT void _CFLogvEx(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, int32_t lev, CFStringRef format, va_list args) { + +CF_EXPORT void _CFLogvEx2(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, const void *), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions, int32_t lev, CFStringRef format, va_list args) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI uintptr_t val = (uintptr_t)_CFGetTSD(__CFTSDKeyIsInCFLog); if (3 < val) return; // allow up to 4 nested invocations _CFSetTSD(__CFTSDKeyIsInCFLog, (void *)(val + 1), NULL); #endif - CFStringRef str = format ? _CFStringCreateWithFormatAndArgumentsAux(kCFAllocatorSystemDefault, copyDescFunc, formatOptions, (CFStringRef)format, args) : 0; + CFStringRef str = format ? _CFStringCreateWithFormatAndArgumentsAux2(kCFAllocatorSystemDefault, copyDescFunc, contextDescFunc, formatOptions, (CFStringRef)format, args) : 0; CFIndex blen = str ? CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1 : 0; char *buf = str ? (char *)malloc(blen) : 0; if (str && buf) { @@ -729,6 +685,10 @@ CF_EXPORT void _CFLogvEx(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, co _CFSetTSD(__CFTSDKeyIsInCFLog, (void *)val, NULL); #endif } + +CF_EXPORT void _CFLogvEx(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, int32_t lev, CFStringRef format, va_list args) { + _CFLogvEx2(logit, copyDescFunc, NULL, formatOptions, lev, format, args); +} // This CF-only log function uses no CF functionality, so it may be called anywhere within CF - including thread teardown or prior to full CF setup CF_PRIVATE void _CFLogSimple(int32_t lev, char *format, ...) { @@ -745,7 +705,7 @@ CF_PRIVATE void _CFLogSimple(int32_t lev, char *format, ...) { void CFLog(int32_t lev, CFStringRef format, ...) { va_list args; va_start(args, format); - _CFLogvEx(NULL, NULL, NULL, lev, format, args); + _CFLogvEx2(NULL, NULL, NULL, NULL, lev, format, args); va_end(args); } @@ -814,20 +774,20 @@ kern_return_t _CFDiscorporateMemoryMaterialize(CFDiscorporateMemory *hm) { #if SUDDEN_TERMINATION_ENABLE_VPROC -static CFSpinLock_t __CFProcessKillingLock = CFSpinLockInit; +static OSSpinLock __CFProcessKillingLock = OS_SPINLOCK_INIT; static CFIndex __CFProcessKillingDisablingCount = 1; static Boolean __CFProcessKillingWasTurnedOn = false; void _CFSuddenTerminationDisable(void) { - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); __CFProcessKillingDisablingCount++; _vproc_transaction_begin(); - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } void _CFSuddenTerminationEnable(void) { // In our model the first call of _CFSuddenTerminationEnable() that does not balance a previous call of _CFSuddenTerminationDisable() actually enables sudden termination so we have to keep a count that's almost redundant with vproc's. - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); __CFProcessKillingDisablingCount--; if (__CFProcessKillingDisablingCount==0 && !__CFProcessKillingWasTurnedOn) { _vproc_transactions_enable(); @@ -840,26 +800,25 @@ void _CFSuddenTerminationEnable(void) { CFLog(kCFLogLevelError, CFSTR("-[NSProcessInfo enableSuddenTermination] has been invoked more times than necessary to balance invocations of -[NSProcessInfo disableSuddenTermination]. Ignoring.")); } } - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus) { // This is for when the caller wants to try to exit quickly if possible but not automatically exit the process when it next becomes clean, because quitting might still be cancelled by the user. - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); // Check _vproc_transaction_count() because other code in the process might go straight to the vproc APIs but also check __CFProcessKillingWasTurnedOn because _vproc_transaction_count() can return 0 when transactions didn't even get enabled. - if (_vproc_transaction_count()==0 && __CFProcessKillingWasTurnedOn) { - _exit(exitStatus); + if (__CFProcessKillingWasTurnedOn) { + _vproc_transaction_try_exit(exitStatus); } - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus) { // The user has had their final opportunity to cancel quitting. Exit as soon as the process is clean. Same carefulness as in _CFSuddenTerminationExitIfTerminationEnabled(). - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); if (__CFProcessKillingWasTurnedOn) { - _vproc_transaction_try_exit(exitStatus); } - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } size_t _CFSuddenTerminationDisablingCount(void) { @@ -871,7 +830,7 @@ size_t _CFSuddenTerminationDisablingCount(void) { #warning Building with vproc sudden termination API disabled. -static CFSpinLock_t __CFProcessKillingLock = CFSpinLockInit; +static OSSpinLockUnlock __CFProcessKillingLock = OS_SPINLOCK_INIT; static size_t __CFProcessKillingDisablingCount = 1; static Boolean __CFProcessExitNextTimeKillingIsEnabled = false; static int32_t __CFProcessExitStatus = 0; @@ -896,16 +855,16 @@ CF_PRIVATE void _CFSetSuddenTerminationEnabled(Boolean isEnabled) { } void _CFSuddenTerminationDisable(void) { - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); if (__CFProcessKillingDisablingCount == 0) { _CFSetSuddenTerminationEnabled(false); } __CFProcessKillingDisablingCount++; - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } void _CFSuddenTerminationEnable(void) { - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); __CFProcessKillingDisablingCount--; if (__CFProcessKillingDisablingCount == 0) { if (__CFProcessExitNextTimeKillingIsEnabled) { @@ -914,26 +873,26 @@ void _CFSuddenTerminationEnable(void) { _CFSetSuddenTerminationEnabled(true); } } - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus) { - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); if (__CFProcessKillingDisablingCount == 0) { _exit(exitStatus); } - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus) { - __CFSpinLock(&__CFProcessKillingLock); + OSSpinLockLock(&__CFProcessKillingLock); if (__CFProcessKillingDisablingCount == 0) { _exit(exitStatus); } else { __CFProcessExitNextTimeKillingIsEnabled = YES; __CFProcessExitStatus = exitStatus; } - __CFSpinUnlock(&__CFProcessKillingLock); + OSSpinLockUnlock(&__CFProcessKillingLock); } size_t _CFSuddenTerminationDisablingCount(void) { diff --git a/CFUtilities.h b/CFUtilities.h index aac9687..a191b89 100644 --- a/CFUtilities.h +++ b/CFUtilities.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFUtilities.h - Copyright (c) 2005-2013, Apple Inc. All rights reserved. + Copyright (c) 2005-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUTILITIES__) diff --git a/CFVersion.c b/CFVersion.c index e118b14..3f134d6 100644 --- a/CFVersion.c +++ b/CFVersion.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFVersion.c - Copyright 2009-2011, Apple Inc. All rights reserved. + Copyright 2009-2014, Apple Inc. All rights reserved. Responsibility: CFLite Team */ -const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-855.14 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n"; -double kCFCoreFoundationVersionNumber = (double)855.14; +const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-1151.16 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n"; +double kCFCoreFoundationVersionNumber = (double)1151.16; diff --git a/CFWindowsUtilities.c b/CFWindowsUtilities.c index 2996b71..b108d85 100644 --- a/CFWindowsUtilities.c +++ b/CFWindowsUtilities.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,13 +17,13 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFWindowsUtilities.c - Copyright (c) 2008-2013, Apple Inc. All rights reserved. + Copyright (c) 2008-2014, Apple Inc. All rights reserved. Responsibility: Tony Parker */ diff --git a/CFXMLInputStream.c b/CFXMLInputStream.c index 7a737dc..49ef2dd 100644 --- a/CFXMLInputStream.c +++ b/CFXMLInputStream.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLInputStream.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ diff --git a/CFXMLInputStream.h b/CFXMLInputStream.h index b17d6d1..9a2d4a7 100644 --- a/CFXMLInputStream.h +++ b/CFXMLInputStream.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLInputStream.h - Copyright (c) 2000-2013, Apple Inc. All rights reserved. + Copyright (c) 2000-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFXMLINPUTSTREAM__) diff --git a/CFXMLNode.c b/CFXMLNode.c index e71981c..2ec2579 100644 --- a/CFXMLNode.c +++ b/CFXMLNode.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLNode.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -223,12 +223,9 @@ static const CFRuntimeClass __CFXMLNodeClass = { __CFXMLNodeCopyDescription }; -static void __CFXMLNodeInitialize(void) { - __kCFXMLNodeTypeID = _CFRuntimeRegisterClass(&__CFXMLNodeClass); -} - CFTypeID CFXMLNodeGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFXMLNodeTypeID) __CFXMLNodeInitialize(); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFXMLNodeTypeID = _CFRuntimeRegisterClass(&__CFXMLNodeClass); }); return __kCFXMLNodeTypeID; } diff --git a/CFXMLNode.h b/CFXMLNode.h index 3f3db7d..a6ec0b8 100644 --- a/CFXMLNode.h +++ b/CFXMLNode.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLNode.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /* CFXMLParser (and thus CFXMLNode) are deprecated as of Mac OS X 10.8 and iOS 6.0. The suggested replacements are the Foundation classes NSXMLParser and NSXMLDocument, or the libxml2 library. */ @@ -36,6 +36,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN enum { @@ -203,6 +204,7 @@ CF_EXPORT CFXMLNodeRef CFXMLTreeGetNode(CFXMLTreeRef xmlTree) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0); CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFXMLNODE__ */ diff --git a/CFXMLParser.c b/CFXMLParser.c index f4635ca..a128343 100644 --- a/CFXMLParser.c +++ b/CFXMLParser.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLParser.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -89,12 +89,9 @@ static const CFRuntimeClass __CFXMLParserClass = { __CFXMLParserCopyDescription }; -static void __CFXMLParserInitialize(void) { - __kCFXMLParserTypeID = _CFRuntimeRegisterClass(&__CFXMLParserClass); -} - CFTypeID CFXMLParserGetTypeID(void) { - if (_kCFRuntimeNotATypeID == __kCFXMLParserTypeID) __CFXMLParserInitialize(); + static dispatch_once_t initOnce; + dispatch_once(&initOnce, ^{ __kCFXMLParserTypeID = _CFRuntimeRegisterClass(&__CFXMLParserClass); }); return __kCFXMLParserTypeID; } diff --git a/CFXMLParser.h b/CFXMLParser.h index b77f978..bf472ec 100644 --- a/CFXMLParser.h +++ b/CFXMLParser.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLParser.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ /* CFXMLParser is deprecated as of Mac OS X 10.8. The suggested replacements are the Foundation classes NSXMLParser and NSXMLDocument, or the libxml2 library. */ @@ -38,6 +38,7 @@ #include #include +CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN typedef struct __CFXMLParser * CFXMLParserRef; @@ -287,6 +288,7 @@ CF_EXPORT const CFStringRef kCFXMLTreeErrorStatusCode; /* value is a CFNumber containing the error status code. */ CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED #endif /* ! __COREFOUNDATION_CFXMLPARSER__ */ diff --git a/CFXMLPreferencesDomain.c b/CFXMLPreferencesDomain.c index 80bacb7..4387a8b 100644 --- a/CFXMLPreferencesDomain.c +++ b/CFXMLPreferencesDomain.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLPreferencesDomain.c - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -48,7 +48,7 @@ typedef struct { CFMutableDictionaryRef _domainDict; // Current value of the domain dictionary CFMutableArrayRef _dirtyKeys; // The array of keys which must be synchronized CFAbsoluteTime _lastReadTime; // The last time we synchronized with the disk - CFSpinLock_t _lock; // Lock for accessing fields in the domain + CFLock_t _lock; // Lock for accessing fields in the domain Boolean _isWorldReadable; // HACK - this is because we have no good way to propogate the kCFPreferencesAnyUser information from the upper level CFPreferences routines REW, 1/13/00 char _padding[3]; } _CFXMLPreferencesDomain; @@ -80,12 +80,12 @@ static void __CFMilliSleep(uint32_t msecs) { #endif } -static CFSpinLock_t _propDictLock = CFSpinLockInit; // Annoying that we need this, but otherwise we have a multithreading risk +static CFLock_t _propDictLock = CFLockInit; // Annoying that we need this, but otherwise we have a multithreading risk CF_INLINE CFDictionaryRef URLPropertyDictForPOSIXMode(SInt32 mode) { static CFMutableDictionaryRef _propertyDict = NULL; CFNumberRef num = CFNumberCreate(__CFPreferencesAllocator(), kCFNumberSInt32Type, &mode); - __CFSpinLock(&_propDictLock); + __CFLock(&_propDictLock); if (!_propertyDict) { _propertyDict = CFDictionaryCreateMutable(__CFPreferencesAllocator(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } @@ -95,7 +95,7 @@ CF_INLINE CFDictionaryRef URLPropertyDictForPOSIXMode(SInt32 mode) { } CF_INLINE void URLPropertyDictRelease(void) { - __CFSpinUnlock(&_propDictLock); + __CFUnlock(&_propDictLock); } // Asssumes caller already knows the directory doesn't exist. @@ -138,7 +138,7 @@ static void *createXMLDomain(CFAllocatorRef allocator, CFTypeRef context) { domain->_lastReadTime = 0.0; domain->_domainDict = NULL; domain->_dirtyKeys = CFArrayCreateMutable(allocator, 0, & kCFTypeArrayCallBacks); - const CFSpinLock_t lock = CFSpinLockInit; + const CFLock_t lock = CFLockInit; domain->_lock = lock; domain->_isWorldReadable = false; return domain; @@ -218,11 +218,11 @@ static CFTypeRef fetchXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef k CFTypeRef result; // Never reload if we've looked at the file system within the last 5 seconds. - __CFSpinLock(&domain->_lock); + __CFLock(&domain->_lock); if (domain->_domainDict == NULL) _loadXMLDomainIfStale((CFURLRef )context, domain); result = CFDictionaryGetValue(domain->_domainDict, key); if (result) CFRetain(result); - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); return result; } @@ -405,7 +405,7 @@ static void writeXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key, C _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; const void *existing = NULL; - __CFSpinLock(&domain->_lock); + __CFLock(&domain->_lock); if (domain->_domainDict == NULL) { _loadXMLDomainIfStale((CFURLRef )context, domain); } @@ -416,12 +416,12 @@ static void writeXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key, C // these things are no-ops, and should not dirty the domain if (CFDictionaryGetValueIfPresent(domain->_domainDict, key, &existing)) { if (NULL != value && (existing == value || CFEqual(existing, value))) { - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); return; } } else { if (NULL == value) { - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); return; } } @@ -440,13 +440,13 @@ static void writeXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key, C } else { CFDictionaryRemoveValue(domain->_domainDict, key); } - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); } static void getXMLKeysAndValues(CFAllocatorRef alloc, CFTypeRef context, void *xmlDomain, void **buf[], CFIndex *numKeyValuePairs) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFIndex count; - __CFSpinLock(&domain->_lock); + __CFLock(&domain->_lock); if (!domain->_domainDict) { _loadXMLDomainIfStale((CFURLRef )context, domain); } @@ -465,21 +465,21 @@ static void getXMLKeysAndValues(CFAllocatorRef alloc, CFTypeRef context, void *x } } *numKeyValuePairs = count; - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); } static CFDictionaryRef copyXMLDomainDictionary(CFTypeRef context, void *xmlDomain) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFDictionaryRef result; - __CFSpinLock(&domain->_lock); + __CFLock(&domain->_lock); if(!domain->_domainDict) { _loadXMLDomainIfStale((CFURLRef)context, domain); } result = (CFDictionaryRef)CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), domain->_domainDict, kCFPropertyListImmutable); - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); return result; } @@ -495,7 +495,7 @@ static Boolean synchronizeXMLDomain(CFTypeRef context, void *xmlDomain) { SInt32 idx, count; Boolean success, tryAgain; - __CFSpinLock(&domain->_lock); + __CFLock(&domain->_lock); cachedDict = domain->_domainDict; changedKeys = domain->_dirtyKeys; count = CFArrayGetCount(changedKeys); @@ -506,7 +506,7 @@ static Boolean synchronizeXMLDomain(CFTypeRef context, void *xmlDomain) { CFRelease(cachedDict); domain->_domainDict = NULL; } - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); return true; } @@ -532,7 +532,7 @@ static Boolean synchronizeXMLDomain(CFTypeRef context, void *xmlDomain) { CFArrayRemoveAllValues(domain->_dirtyKeys); } domain->_lastReadTime = CFAbsoluteTimeGetCurrent(); - __CFSpinUnlock(&domain->_lock); + __CFUnlock(&domain->_lock); return success; } diff --git a/CFXMLTree.c b/CFXMLTree.c index 127f09d..fa999a0 100644 --- a/CFXMLTree.c +++ b/CFXMLTree.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CFXMLTree.c - Copyright (c) 1999-2013, Apple Inc. All rights reserved. + Copyright (c) 1999-2014, Apple Inc. All rights reserved. Responsibility: David Smith */ diff --git a/CoreFoundation.h b/CoreFoundation.h index f20a355..01c13d9 100644 --- a/CoreFoundation.h +++ b/CoreFoundation.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CoreFoundation.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_COREFOUNDATION__) diff --git a/CoreFoundation_Prefix.h b/CoreFoundation_Prefix.h index 0fad0bd..2dcfa15 100644 --- a/CoreFoundation_Prefix.h +++ b/CoreFoundation_Prefix.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* CoreFoundation_Prefix.h - Copyright (c) 2005-2013, Apple Inc. All rights reserved. + Copyright (c) 2005-2014, Apple Inc. All rights reserved. */ @@ -39,6 +39,17 @@ extern "C" { #endif +#if DEPLOYMENT_TARGET_IPHONESIMULATOR // work around +#include +#define qos_class_self() (QOS_CLASS_UTILITY) +#define qos_class_main() (QOS_CLASS_UTILITY) +#define pthread_set_qos_class_self_np(A, B) do {} while (0) +#define pthread_override_qos_class_start_np(A, B, C) (NULL) +#define pthread_override_qos_class_end_np(A) do {} while (0) +#elif (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED) +#include +#endif + #define SystemIntegrityCheck(A, B) do {} while (0) @@ -48,10 +59,16 @@ extern "C" { typedef signed char BOOL; typedef char * id; typedef char * Class; +#ifndef YES #define YES (BOOL)1 +#endif +#ifndef NO #define NO (BOOL)0 +#endif +#ifndef nil #define nil NULL #endif +#endif #define CRSetCrashLogMessage(A) do {} while (0) #define CRSetCrashLogMessage2(A) do {} while (0) @@ -72,7 +89,7 @@ typedef char * Class; static dispatch_queue_t __ ## PREFIX ## Queue(void) { \ static volatile dispatch_queue_t __ ## PREFIX ## dq = NULL; \ if (!__ ## PREFIX ## dq) { \ - dispatch_queue_t dq = dispatch_queue_create(# QNAME, NULL); \ + dispatch_queue_t dq = dispatch_queue_create("com.apple." # QNAME, NULL); \ void * volatile *loc = (void * volatile *)&__ ## PREFIX ## dq; \ if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dq, loc)) { \ dispatch_release(dq); \ @@ -273,8 +290,8 @@ typedef int gid_t; #define malloc_zone_free(zone,ptr) free(ptr) // implemented in CFInternal.h -#define OSSpinLockLock(A) __CFSpinLock(A) -#define OSSpinLockUnlock(A) __CFSpinUnlock(A) +#define OSSpinLockLock(A) __CFLock(A) +#define OSSpinLockUnlock(A) __CFUnlock(A) typedef int32_t OSSpinLock; diff --git a/Examples/plconvert.c b/Examples/plconvert.c index 6a2b81e..883413d 100644 --- a/Examples/plconvert.c +++ b/Examples/plconvert.c @@ -1,5 +1,8 @@ -// Mac OS X: llvm-gcc -F -framework CoreFoundation Examples/plconvert.c -o plconvert - +// Mac OS X: clang -F -framework CoreFoundation Examples/plconvert.c -o plconvert +// note: When running this sample, be sure to set the environment variable DYLD_FRAMEWORK_PATH to point to the directory containing your new version of CoreFoundation. +// e.g. +// DYLD_FRAMEWORK_PATH=/tmp/CF-Root ./plconvert +// // Linux: clang -I/usr/local/include -L/usr/local/lib -lCoreFoundation plconvert.c -o plconvert /* diff --git a/ForFoundationOnly.h b/ForFoundationOnly.h index 0ffe6d0..2cc2de0 100644 --- a/ForFoundationOnly.h +++ b/ForFoundationOnly.h @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,12 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ /* ForFoundationOnly.h - Copyright (c) 1998-2013, Apple Inc. All rights reserved. + Copyright (c) 1998-2014, Apple Inc. All rights reserved. */ #if !CF_BUILDING_CF && !NSBUILDINGFOUNDATION @@ -43,6 +43,7 @@ #include #include #include +#include #include // NOTE: miscellaneous declarations are at the end @@ -77,11 +78,9 @@ CF_EXPORT const CFStringRef _kCFBundleResolvedPathKey; CF_EXPORT const CFStringRef _kCFBundlePrincipalClassKey; #if __BLOCKS__ -CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subPath, CFStringRef lproj, Boolean returnArray, Boolean localized, Boolean (^predicate)(CFStringRef filename, Boolean *stop)); +CF_EXPORT CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef _unused_pass_null_, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subPath, CFStringRef lproj, Boolean returnArray, Boolean localized, Boolean (^predicate)(CFStringRef filename, Boolean *stop)); #endif -CF_EXPORT CFArrayRef _CFBundleGetLanguageSearchList(CFBundleRef bundle); - CF_EXPORT Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error); CF_EXPORT CFErrorRef _CFBundleCreateError(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code); @@ -181,13 +180,13 @@ CF_EXTERN_C_END #define NSSTRING_INDEXERROR(index, len) \ [NSException raise:NSRangeException format:@"%@: Index %lu out of bounds; string length %lu", __CFExceptionProem((id)self, _cmd), (unsigned long)index, (unsigned long)len] -// This can be made into an exception for post-10.9 apps +// This can be made into an exception for post-10.10 apps #define NSSTRING_POSSIBLE_RANGEERROR(range, len) \ if (__CFStringNoteErrors()) { \ static bool warnonce = false; \ if (!warnonce) { \ warnonce = true; \ - CFLog(kCFLogLevelWarning, CFSTR("*** %@: Range {%lu, %lu} out of bounds; string length %lu. This will become an exception for apps linked after 10.9. Warning shown once per app execution."), __CFExceptionProem((id)self, _cmd), (unsigned long)range.location, (unsigned long)range.length, (unsigned long)len); \ + CFLog(kCFLogLevelWarning, CFSTR("*** %@: Range {%lu, %lu} out of bounds; string length %lu. This will become an exception for apps linked after 10.10 and iOS 8. Warning shown once per app execution."), __CFExceptionProem((id)self, _cmd), (unsigned long)range.location, (unsigned long)range.length, (unsigned long)len); \ } \ } @@ -344,6 +343,9 @@ CF_INLINE UniChar __CFStringGetCharacterFromInlineBufferQuick(CFStringInlineBuff CF_EXPORT void _CFStringAppendFormatAndArgumentsAux(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *loc), CFDictionaryRef formatOptions, CFStringRef formatString, va_list args); CF_EXPORT CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, const void *loc), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments); +CF_EXPORT void _CFStringAppendFormatAndArgumentsAux2(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *loc), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions, CFStringRef formatString, va_list args); +CF_EXPORT CFStringRef _CFStringCreateWithFormatAndArgumentsAux2(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, const void *loc), CFStringRef (*contextDescFunc)(void *, const void *, const void *, bool, bool *), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments); + /* For NSString (and NSAttributedString) usage, mutate with isMutable check */ enum {_CFStringErrNone = 0, _CFStringErrNotMutable = 1, _CFStringErrNilArg = 2, _CFStringErrBounds = 3}; @@ -524,10 +526,6 @@ CF_EXPORT CFStringRef _CFErrorCreateLocalizedFailureReason(CFErrorRef err); CF_EXPORT CFStringRef _CFErrorCreateLocalizedRecoverySuggestion(CFErrorRef err); CF_EXPORT CFStringRef _CFErrorCreateDebugDescription(CFErrorRef err); -CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator); -CF_EXPORT Boolean _CFURLInitWithURLString(CFURLRef uninitializedURL, CFStringRef string, Boolean checkForLegalCharacters, CFURLRef baseURL); -CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStringRef fileSystemPath, CFURLPathStyle pathStyle, Boolean isDirectory, CFURLRef baseURL); -CF_EXPORT Boolean _CFURLInitWithFileSystemRepresentation(CFURLRef uninitializedURL, const UInt8 *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL); CF_EXPORT void *__CFURLReservedPtr(CFURLRef url); CF_EXPORT void __CFURLSetReservedPtr(CFURLRef url, void *ptr); CF_EXPORT CFStringEncoding _CFURLGetEncoding(CFURLRef url); @@ -560,6 +558,9 @@ enum { kCFNumberFormatterDurationStyle = 7, }; +// This is for NSNumberFormatter use only! +CF_EXPORT void *_CFNumberFormatterGetFormatter(CFNumberFormatterRef formatter); + CF_EXPORT CFRange _CFDataFindBytes(CFDataRef data, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions); diff --git a/Makefile b/Makefile index 1052254..36e39c1 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ include MakefileVersion -MIN_MACOSX_VERSION=10.9 -MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_9 +MIN_MACOSX_VERSION=10.10 +MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_10 OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c)) OBJECTS += CFBasicHash.o @@ -28,7 +28,7 @@ INSTALLNAME=/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreF CC = /usr/bin/clang -CFLAGS=-c -x c -pipe -std=gnu99 -Wmost -Wno-trigraphs -mmacosx-version-min=$(MIN_MACOSX_VERSION) -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=$(MAX_MACOSX_VERSION) -DU_SHOW_DRAFT_API=1 -DU_SHOW_CPLUSPLUS_API=0 -I$(OBJBASE) -DVERSION=$(VERSION) -include CoreFoundation_Prefix.h +CFLAGS=-c -x c -pipe -std=gnu99 -Wmost -Wno-trigraphs -Wno-deprecated -mmacosx-version-min=$(MIN_MACOSX_VERSION) -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=$(MAX_MACOSX_VERSION) -DU_SHOW_DRAFT_API=1 -DU_SHOW_CPLUSPLUS_API=0 -I$(OBJBASE) -DVERSION=$(VERSION) -include CoreFoundation_Prefix.h LFLAGS=-dynamiclib -mmacosx-version-min=$(MIN_MACOSX_VERSION) -twolevel_namespace -fexceptions -init ___CFInitialize -compatibility_version 150 -current_version $(VERSION) -Wl,-alias_list,SymbolAliases -sectcreate __UNICODE __csbitmaps CFCharacterSetBitmaps.bitmap -sectcreate __UNICODE __properties CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data $(call unicode_data_file_name,$(MACHINE_TYPE)) -segprot __UNICODE r r diff --git a/MakefileVersion b/MakefileVersion index 440f667..6a390b2 100644 --- a/MakefileVersion +++ b/MakefileVersion @@ -1 +1 @@ -VERSION=855.15 +VERSION=1151.16 diff --git a/SymbolAliases b/SymbolAliases index 6380cdb..8b55d33 100644 --- a/SymbolAliases +++ b/SymbolAliases @@ -9,6 +9,8 @@ _kCFCalendarIdentifierIslamicCivil _kCFIslamicCivilCalendar _kCFCalendarIdentifierJapanese _kCFJapaneseCalendar _kCFCalendarIdentifierPersian _kCFPersianCalendar _kCFCalendarIdentifierRepublicOfChina _kCFRepublicOfChinaCalendar +_kCFCalendarIdentifierIslamicTabular _kCFIslamicTabularCalendar +_kCFCalendarIdentifierIslamicUmmAlQura _kCFIslamicUmmAlQuraCalendar _kCFLocaleCalendarIdentifierKey _kCFLocaleCalendarIdentifier diff --git a/TargetConditionals.h b/TargetConditionals.h index 80cb7a3..e9f4c6e 100644 --- a/TargetConditionals.h +++ b/TargetConditionals.h @@ -1,5 +1,5 @@ /* TargetConditionals.h - Copyright (c) 2010-2013, Apple Inc. All rights reserved. + Copyright (c) 2010-2014, Apple Inc. All rights reserved. For CF on Linux ONLY */ diff --git a/plconvert.c b/plconvert.c index 2361478..7f06529 100644 --- a/plconvert.c +++ b/plconvert.c @@ -2,14 +2,14 @@ * Copyright (c) 2014 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,12 +17,15 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ -// Mac OS X: llvm-gcc -F -framework CoreFoundation Examples/plconvert.c -o plconvert - +// Mac OS X: clang -F -framework CoreFoundation Examples/plconvert.c -o plconvert +// note: When running this sample, be sure to set the environment variable DYLD_FRAMEWORK_PATH to point to the directory containing your new version of CoreFoundation. +// e.g. +// DYLD_FRAMEWORK_PATH=/tmp/CF-Root ./plconvert +// // Linux: clang -I/usr/local/include -L/usr/local/lib -lCoreFoundation plconvert.c -o plconvert /* -- 2.45.2