From a48904a4f619920580dd9527a6e6f20b2e3e1ec7 Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 11 Oct 2013 21:48:24 +0000 Subject: [PATCH] CF-855.11.tar.gz --- CFApplicationPreferences.c | 10 +- CFArray.c | 37 +- CFArray.h | 4 +- CFAvailability.h | 197 ++ CFBag.c | 398 +--- CFBag.h | 4 +- CFBase.c | 78 +- CFBase.h | 111 +- CFBasicHash.c | 281 +-- CFBasicHash.h | 37 +- CFBasicHashFindBucket.m | 6 +- CFBigNumber.c | 29 +- CFBigNumber.h | 4 +- CFBinaryHeap.c | 12 +- CFBinaryHeap.h | 4 +- CFBinaryPList.c | 569 +---- CFBitVector.c | 24 +- CFBitVector.h | 4 +- CFBuiltinConverters.c | 16 +- CFBundle.c | 611 ++---- CFBundle.h | 4 +- CFBundlePriv.h | 13 +- CFBundle_BinaryTypes.h | 4 +- CFBundle_InfoPlist.c | 822 +++++++ CFBundle_Internal.h | 139 +- CFBundle_Resources.c | 3541 +++++++++---------------------- CFBurstTrie.c | 37 +- CFBurstTrie.h | 6 +- CFByteOrder.h | 4 +- CFCalendar.c | 8 +- CFCalendar.h | 4 +- CFCharacterSet.c | 89 +- CFCharacterSet.h | 4 +- CFCharacterSetPriv.h | 4 +- CFConcreteStreams.c | 40 +- CFData.c | 26 +- CFData.h | 4 +- CFDate.c | 45 +- CFDate.h | 49 +- CFDateFormatter.c | 1234 +++++++---- CFDateFormatter.h | 4 +- CFDictionary.c | 396 +--- CFDictionary.h | 4 +- CFError.c | 8 +- CFError.h | 4 +- CFError_Private.h | 4 +- CFFileUtilities.c | 332 ++- CFICUConverters.c | 26 +- CFICUConverters.h | 18 +- CFICULogging.h | 115 + CFInternal.h | 182 +- CFLocale.c | 105 +- CFLocale.h | 4 +- CFLocaleIdentifier.c | 4 +- CFLocaleInternal.h | 6 +- CFLocaleKeys.c | 8 +- CFLogUtilities.h | 4 +- CFMachPort.c | 107 +- CFMachPort.h | 4 +- CFMessagePort.c | 14 +- CFMessagePort.h | 4 +- CFNumber.c | 144 +- CFNumber.h | 4 +- CFNumberFormatter.c | 246 ++- CFNumberFormatter.h | 4 +- CFOldStylePList.c | 20 +- CFPlatform.c | 42 +- CFPlatformConverters.c | 20 +- CFPlugIn.c | 6 +- CFPlugIn.h | 93 +- CFPlugInCOM.h | 4 +- CFPlugIn_Factory.c | 34 +- CFPlugIn_Factory.h | 4 +- CFPlugIn_Instance.c | 9 +- CFPlugIn_PlugIn.c | 22 +- CFPreferences.c | 26 +- CFPreferences.h | 6 +- CFPriv.h | 121 +- CFPropertyList.c | 182 +- CFPropertyList.h | 4 +- CFRunLoop.c | 786 ++++--- CFRunLoop.h | 9 +- CFRuntime.c | 200 +- CFRuntime.h | 52 +- CFSet.c | 400 +--- CFSet.h | 4 +- CFSocket.c | 131 +- CFSocket.h | 4 +- CFSocketStream.c | 8 +- CFSortFunctions.c | 4 +- CFStorage.c | 10 +- CFStorage.h | 4 +- CFStream.c | 511 ++++- CFStream.h | 47 +- CFStreamAbstract.h | 4 +- CFStreamInternal.h | 6 +- CFStreamPriv.h | 20 +- CFString.c | 177 +- CFString.h | 25 +- CFStringDefaultEncoding.h | 4 +- CFStringEncodingConverter.c | 16 +- CFStringEncodingConverter.h | 4 +- CFStringEncodingConverterExt.h | 4 +- CFStringEncodingConverterPriv.h | 4 +- CFStringEncodingDatabase.c | 16 +- CFStringEncodingDatabase.h | 16 +- CFStringEncodingExt.h | 4 +- CFStringEncodings.c | 10 +- CFStringScanner.c | 10 +- CFStringUtilities.c | 11 +- CFSystemDirectories.c | 6 +- CFTimeZone.c | 6 +- CFTimeZone.h | 4 +- CFTree.c | 8 +- CFTree.h | 4 +- CFURL.c | 2785 ++++++++++++------------ CFURL.h | 75 +- CFURL.inc.h | 352 +++ CFURLAccess.c | 8 +- CFURLAccess.h | 46 +- CFURLPriv.h | 245 ++- CFUUID.c | 6 +- CFUUID.h | 4 +- CFUniChar.c | 55 +- CFUniChar.h | 6 +- CFUniCharPriv.h | 4 +- CFUnicodeDecomposition.c | 6 +- CFUnicodeDecomposition.h | 4 +- CFUnicodePrecomposition.c | 6 +- CFUnicodePrecomposition.h | 4 +- CFUserNotification.c | 22 +- CFUserNotification.h | 4 +- CFUtilities.c | 64 +- CFUtilities.h | 45 + CFVersion.c | 6 +- CFWindowsUtilities.c | 4 +- CFXMLInputStream.c | 44 +- CFXMLInputStream.h | 4 +- CFXMLNode.c | 6 +- CFXMLNode.h | 4 +- CFXMLParser.c | 4 +- CFXMLParser.h | 4 +- CFXMLPreferencesDomain.c | 6 +- CFXMLTree.c | 10 +- CoreFoundation.h | 4 +- CoreFoundation_Prefix.h | 93 +- ForFoundationOnly.h | 58 +- Info.plist | 10 +- Makefile | 8 +- MakefileLinux | 8 +- MakefileVersion | 2 +- SymbolAliases | 2 + TargetConditionals.h | 2 +- plconvert.c | 2 +- 154 files changed, 9000 insertions(+), 8408 deletions(-) create mode 100644 CFAvailability.h create mode 100644 CFBundle_InfoPlist.c create mode 100644 CFICULogging.h create mode 100644 CFURL.inc.h create mode 100644 CFUtilities.h diff --git a/CFApplicationPreferences.c b/CFApplicationPreferences.c index 937d7cd..ab38b88 100644 --- a/CFApplicationPreferences.c +++ b/CFApplicationPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFApplicationPreferences.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -106,7 +106,7 @@ CF_EXPORT Boolean CFPreferencesAppBooleanValue(CFStringRef key, CFStringRef appN return result; } -__private_extern__ CFIndex CFPreferencesAppIntegerValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) { +CF_PRIVATE CFIndex CFPreferencesAppIntegerValue(CFStringRef key, CFStringRef appName, Boolean *keyExistsAndHasValidFormat) { CFPropertyListRef value; CFIndex result; CFTypeID typeID = 0; @@ -303,7 +303,7 @@ void _CFApplicationPreferencesUpdate(_CFApplicationPreferences *self) { CF_EXPORT CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences *self); -__private_extern__ CFDictionaryRef __CFApplicationPreferencesCopyCurrentState(void) { +CF_PRIVATE CFDictionaryRef __CFApplicationPreferencesCopyCurrentState(void) { _CFApplicationPreferences *self = _CFStandardApplicationPreferences(kCFPreferencesCurrentApplication); CFDictionaryRef result = _CFApplicationPreferencesCopyRepresentation(self); return result; @@ -436,7 +436,7 @@ void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences *a #undef ADD_DOMAIN -__private_extern__ _CFApplicationPreferences *_CFStandardApplicationPreferences(CFStringRef appName) { +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); diff --git a/CFArray.c b/CFArray.c index ff1bc59..c49eb78 100644 --- a/CFArray.c +++ b/CFArray.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFArray.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -141,7 +141,7 @@ CF_INLINE struct __CFArrayBucket *__CFArrayGetBucketAtIndex(CFArrayRef array, CF return NULL; } -__private_extern__ CFArrayCallBacks *__CFArrayGetCallBacks(CFArrayRef array) { +CF_PRIVATE CFArrayCallBacks *__CFArrayGetCallBacks(CFArrayRef array) { CFArrayCallBacks *result = NULL; switch (__CFBitfieldGetValue(((const CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS], 3, 2)) { case __kCFArrayHasNullCallBacks: @@ -229,7 +229,7 @@ static void __CFArrayReleaseValues(CFArrayRef array, CFRange range, bool release } if (releaseStorageIfPossible && 0 == range.location && __CFArrayGetCount(array) == range.length) { allocator = __CFGetAllocator(array); - if (NULL != deque && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, deque); + if (NULL != deque) if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, deque); __CFArraySetCount(array, 0); // GC: _count == 0 ==> _store == NULL. ((struct __CFArray *)array)->_store = NULL; } @@ -287,10 +287,10 @@ static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) { result = CFStringCreateMutable(allocator, 0); switch (__CFArrayGetType(array)) { case __kCFArrayImmutable: - CFStringAppendFormat(result, NULL, CFSTR("{type = immutable, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : ""); + CFStringAppendFormat(result, NULL, CFSTR("{type = immutable, count = %lu, values = (%s"), cf, allocator, (unsigned long)cnt, cnt ? "\n" : ""); break; case __kCFArrayDeque: - CFStringAppendFormat(result, NULL, CFSTR("{type = mutable-small, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : ""); + CFStringAppendFormat(result, NULL, CFSTR("{type = mutable-small, count = %lu, values = (%s"), cf, allocator, (unsigned long)cnt, cnt ? "\n" : ""); break; } cb = __CFArrayGetCallBacks(array); @@ -301,10 +301,10 @@ static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) { desc = (CFStringRef)INVOKE_CALLBACK1(cb->copyDescription, val); } if (NULL != desc) { - CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@\n"), idx, desc); + CFStringAppendFormat(result, NULL, CFSTR("\t%lu : %@\n"), (unsigned long)idx, desc); CFRelease(desc); } else { - CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, val); + CFStringAppendFormat(result, NULL, CFSTR("\t%lu : <%p>\n"), (unsigned long)idx, val); } } CFStringAppend(result, CFSTR(")}")); @@ -355,7 +355,7 @@ static const CFRuntimeClass __CFArrayClass = { __CFArrayCopyDescription }; -__private_extern__ void __CFArrayInitialize(void) { +CF_PRIVATE void __CFArrayInitialize(void) { __kCFArrayTypeID = _CFRuntimeRegisterClass(&__CFArrayClass); } @@ -418,7 +418,7 @@ static CFArrayRef __CFArrayInit(CFAllocatorRef allocator, UInt32 flags, CFIndex return (CFArrayRef)memory; } -__private_extern__ CFArrayRef __CFArrayCreateTransfer(CFAllocatorRef allocator, const void **values, CFIndex numValues) { +CF_PRIVATE CFArrayRef __CFArrayCreateTransfer(CFAllocatorRef allocator, const void **values, CFIndex numValues) { CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__, numValues); UInt32 flags = __kCFArrayImmutable; __CFBitfieldSetValue(flags, 31, 2, 0); @@ -436,7 +436,7 @@ __private_extern__ CFArrayRef __CFArrayCreateTransfer(CFAllocatorRef allocator, return (CFArrayRef)memory; } -__private_extern__ CFArrayRef __CFArrayCreate0(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks) { +CF_PRIVATE CFArrayRef __CFArrayCreate0(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks) { CFArrayRef result; const CFArrayCallBacks *cb; struct __CFArrayBucket *buckets; @@ -467,13 +467,13 @@ __private_extern__ CFArrayRef __CFArrayCreate0(CFAllocatorRef allocator, const v return result; } -__private_extern__ CFMutableArrayRef __CFArrayCreateMutable0(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks) { +CF_PRIVATE CFMutableArrayRef __CFArrayCreateMutable0(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks) { CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFAssert2(capacity <= LONG_MAX / sizeof(void *), __kCFLogAssertion, "%s(): capacity (%d) is too large for this architecture", __PRETTY_FUNCTION__, capacity); return (CFMutableArrayRef)__CFArrayInit(allocator, __kCFArrayDeque, capacity, callBacks); } -__private_extern__ CFArrayRef __CFArrayCreateCopy0(CFAllocatorRef allocator, CFArrayRef array) { +CF_PRIVATE CFArrayRef __CFArrayCreateCopy0(CFAllocatorRef allocator, CFArrayRef array) { CFArrayRef result; const CFArrayCallBacks *cb; struct __CFArrayBucket *buckets; @@ -503,7 +503,7 @@ __private_extern__ CFArrayRef __CFArrayCreateCopy0(CFAllocatorRef allocator, CFA return result; } -__private_extern__ CFMutableArrayRef __CFArrayCreateMutableCopy0(CFAllocatorRef allocator, CFIndex capacity, CFArrayRef array) { +CF_PRIVATE CFMutableArrayRef __CFArrayCreateMutableCopy0(CFAllocatorRef allocator, CFIndex capacity, CFArrayRef array) { CFMutableArrayRef result; const CFArrayCallBacks *cb; CFIndex idx, numValues = CFArrayGetCount(array); @@ -798,7 +798,6 @@ static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange ran CFIndex capacity = __CFArrayDequeRoundUpCapacity(futureCnt + wiggle); CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket); CFAllocatorRef allocator = __CFGetAllocator(array); - allocator = _CFConvertAllocatorToGCRefZeroEquivalent(allocator); Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator); struct __CFArrayDeque *newDeque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); if (__CFOASafe) __CFSetLastAllocationEventName(newDeque, "CFArray (store-deque)"); @@ -813,6 +812,7 @@ static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange ran if (0 < C) objc_memmove_collectable(newBuckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket)); __CFAssignWithWriteBarrier((void **)&array->_store, (void *)newDeque); if (!collectableMemory && deque) CFAllocatorDeallocate(allocator, deque); + if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) auto_zone_release(objc_collectableZone(), newDeque); //printf("3: array %p store is now %p (%lx)\n", array, array->_store, *(unsigned long *)(array->_store)); return; } @@ -885,7 +885,6 @@ void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) { CFIndex capacity = __CFArrayDequeRoundUpCapacity(cap); CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket); CFAllocatorRef allocator = __CFGetAllocator(array); - allocator = _CFConvertAllocatorToGCRefZeroEquivalent(allocator); Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator); if (NULL == deque) { deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); @@ -903,6 +902,7 @@ void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) { } deque->_capacity = capacity; __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque); + if (collectableMemory) auto_zone_release(objc_collectableZone(), deque); } END_MUTATION(array); } @@ -965,11 +965,12 @@ void _CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void ** struct __CFArrayDeque *deque; CFIndex capacity = __CFArrayDequeRoundUpCapacity(futureCnt); CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket); - deque = (struct __CFArrayDeque *)CFAllocatorAllocate(_CFConvertAllocatorToGCRefZeroEquivalent(allocator), size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); + deque = (struct __CFArrayDeque *)CFAllocatorAllocate((allocator), size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0); if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)"); deque->_leftIdx = (capacity - newCount) / 2; deque->_capacity = capacity; __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque); + if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) auto_zone_release(objc_collectableZone(), deque); // GC: now safe to unroot the array body. } } else { // Deque // reposition regions A and C for new region B elements in gap @@ -1017,7 +1018,7 @@ CF_INLINE void __CFZSort(CFMutableArrayRef array, CFRange range, CFComparatorFun } } -__private_extern__ void _CFArraySortValues(CFMutableArrayRef array, CFComparatorFunction comparator, void *context) { +CF_PRIVATE void _CFArraySortValues(CFMutableArrayRef array, CFComparatorFunction comparator, void *context) { CFRange range = {0, CFArrayGetCount(array)}; if (range.length < 2) { return; diff --git a/CFArray.h b/CFArray.h index 020cece..2eaa4f0 100644 --- a/CFArray.h +++ b/CFArray.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFArray.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /*! diff --git a/CFAvailability.h b/CFAvailability.h new file mode 100644 index 0000000..aaf0236 --- /dev/null +++ b/CFAvailability.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2013 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@ + */ + +/* CFAvailability.h + Copyright (c) 2013-2013, Apple Inc. All rights reserved. +*/ + +#if !defined(__COREFOUNDATION_CFAVAILABILITY__) +#define __COREFOUNDATION_CFAVAILABILITY__ 1 + +#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 + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif +#ifndef __has_extension +#define __has_extension(x) 0 +#endif + +// The arguments to these availability macros is a version number, e.g. 10_6, 3_0 or 'NA' +// To use a deprecation message with the macro, add a string as the last argument. +#if __has_feature(attribute_availability_with_message) + +#define __NSi_2_0 introduced=2.0 +#define __NSi_2_1 introduced=2.1 +#define __NSi_2_2 introduced=2.2 +#define __NSi_3_0 introduced=3.0 +#define __NSi_3_1 introduced=3.1 +#define __NSi_3_2 introduced=3.2 +#define __NSi_4_0 introduced=4.0 +#define __NSi_4_1 introduced=4.1 +#define __NSi_4_2 introduced=4.2 +#define __NSi_4_3 introduced=4.3 +#define __NSi_5_0 introduced=5.0 +#define __NSi_5_1 introduced=5.1 +#define __NSi_6_0 introduced=6.0 +#define __NSi_6_1 introduced=6.1 +#define __NSi_7_0 introduced=7.0 +#define __NSi_8_0 introduced=8.0 +#define __NSi_9_0 introduced=9.0 +#define __NSi_10_0 introduced=10.0 +#define __NSi_10_1 introduced=10.1 +#define __NSi_10_2 introduced=10.2 +#define __NSi_10_3 introduced=10.3 +#define __NSi_10_4 introduced=10.4 +#define __NSi_10_5 introduced=10.5 +#define __NSi_10_6 introduced=10.6 +#define __NSi_10_7 introduced=10.7 +#define __NSi_10_8 introduced=10.8 +#define __NSi_10_9 introduced=10.9 + +#define __NSd_2_0 ,deprecated=2.0 +#define __NSd_2_1 ,deprecated=2.1 +#define __NSd_2_2 ,deprecated=2.2 +#define __NSd_3_0 ,deprecated=3.0 +#define __NSd_3_1 ,deprecated=3.1 +#define __NSd_3_2 ,deprecated=3.2 +#define __NSd_4_0 ,deprecated=4.0 +#define __NSd_4_1 ,deprecated=4.1 +#define __NSd_4_2 ,deprecated=4.2 +#define __NSd_4_3 ,deprecated=4.3 +#define __NSd_5_0 ,deprecated=5.0 +#define __NSd_5_1 ,deprecated=5.1 +#define __NSd_6_0 ,deprecated=6.0 +#define __NSd_6_1 ,deprecated=6.1 +#define __NSd_7_0 ,deprecated=7.0 +#define __NSd_8_0 ,deprecated=8.0 +#define __NSd_9_0 ,deprecated=9.0 +#define __NSd_10_0 ,deprecated=10.0 +#define __NSd_10_1 ,deprecated=10.1 +#define __NSd_10_2 ,deprecated=10.2 +#define __NSd_10_3 ,deprecated=10.3 +#define __NSd_10_4 ,deprecated=10.4 +#define __NSd_10_5 ,deprecated=10.5 +#define __NSd_10_6 ,deprecated=10.6 +#define __NSd_10_7 ,deprecated=10.7 +#define __NSd_10_8 ,deprecated=10.8 +#define __NSd_10_9 ,deprecated=10.9 + +#define __NSi_NA unavailable +#define __NSd_NA + +// Do not use TBD as an argument to NS_AVAILABLE +#define __NSi_TBD introduced=9876.5 + +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +// This section is for compilers targeting OS X which support attribute_availability_with_message + +#define CF_AVAILABLE(_mac, _ios) __attribute__((availability(macosx,__NSi_##_mac))) +#define CF_AVAILABLE_MAC(_mac) __attribute__((availability(macosx,__NSi_##_mac))) +#define CF_AVAILABLE_IOS(_ios) __attribute__((availability(macosx,unavailable))) +#define CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) __attribute__((availability(macosx,__NSi_##_macIntro __NSd_##_macDep,message="" __VA_ARGS__))) +#define CF_DEPRECATED_MAC(_macIntro, _macDep, ...) __attribute__((availability(macosx,__NSi_##_macIntro __NSd_##_macDep,message="" __VA_ARGS__))) +#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) __attribute__((availability(macosx,unavailable))) + +#elif (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) +// This section is for compilers targeting iOS which support attribute_availability_with_message + +#define CF_AVAILABLE(_mac, _ios) __attribute__((availability(ios,__NSi_##_ios))) +#define CF_AVAILABLE_MAC(_mac) __attribute__((availability(ios,unavailable))) +#define CF_AVAILABLE_IOS(_ios) __attribute__((availability(ios,__NSi_##_ios))) +#define CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) __attribute__((availability(ios,__NSi_##_iosIntro __NSd_##_iosDep,message="" __VA_ARGS__))) +#define CF_DEPRECATED_MAC(_macIntro, _macDep, ...) __attribute__((availability(ios,unavailable))) +#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) __attribute__((availability(ios,__NSi_##_iosIntro __NSd_##_iosDep,message="" __VA_ARGS__))) + +#endif + +#elif (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) +// This section is for OS X or iOS, and compilers without support for attribute_availability_with_message. We fall back to Availability.h. + +#ifndef __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_0 +#define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_0 __AVAILABILITY_INTERNAL_DEPRECATED +#endif + +#define CF_AVAILABLE(_mac, _ios) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_##_ios) +#define CF_AVAILABLE_MAC(_mac) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_NA) +#define CF_AVAILABLE_IOS(_ios) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios) +#define CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_##_macIntro, __MAC_##_macDep, __IPHONE_##_iosIntro, __IPHONE_##_iosDep) +#define CF_DEPRECATED_MAC(_macIntro, _macDep, ...) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_##_macIntro, __MAC_##_macDep, __IPHONE_NA, __IPHONE_NA) +#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA, __MAC_NA, __IPHONE_##_iosIntro, __IPHONE_##_iosDep) + +#endif // __has_feature(attribute_availability_with_message) + +#ifndef CF_AVAILABLE +// This section is for platforms which do not support availability +#define CF_AVAILABLE(_mac, _ios) +#define CF_AVAILABLE_MAC(_mac) +#define CF_AVAILABLE_IOS(_ios) +#define CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) +#define CF_DEPRECATED_MAC(_macIntro, _macDep, ...) +#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) +#endif + +// Older versions of these macros; use iOS versions instead +#define CF_AVAILABLE_IPHONE(_ios) CF_AVAILABLE_IOS(_ios) +#define CF_DEPRECATED_IPHONE(_iosIntro, _iosDep) CF_DEPRECATED_IOS(_iosIntro, _iosDep) + +// Enum availability macros +#if __has_feature(enumerator_attributes) && __has_attribute(availability) +#define CF_ENUM_AVAILABLE(_mac, _ios) CF_AVAILABLE(_mac, _ios) +#define CF_ENUM_AVAILABLE_MAC(_mac) CF_AVAILABLE_MAC(_mac) +#define CF_ENUM_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios) +#define CF_ENUM_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, __VA_ARGS__) +#define CF_ENUM_DEPRECATED_MAC(_macIntro, _macDep, ...) CF_DEPRECATED_MAC(_macIntro, _macDep, __VA_ARGS__) +#define CF_ENUM_DEPRECATED_IOS(_iosIntro, _iosDep, ...) CF_DEPRECATED_IOS(_iosIntro, _iosDep, __VA_ARGS__) +#else +#define CF_ENUM_AVAILABLE(_mac, _ios) +#define CF_ENUM_AVAILABLE_MAC(_mac) +#define CF_ENUM_AVAILABLE_IOS(_ios) +#define CF_ENUM_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) +#define CF_ENUM_DEPRECATED_MAC(_macIntro, _macDep, ...) +#define CF_ENUM_DEPRECATED_IOS(_iosIntro, _iosDep, ...) +#endif + +// Enums and Options +#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum)) +#define CF_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#if (__cplusplus) +#define CF_OPTIONS(_type, _name) _type _name; enum : _type +#else +#define CF_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type +#endif +#else +#define CF_ENUM(_type, _name) _type _name; enum +#define CF_OPTIONS(_type, _name) _type _name; enum +#endif + +#endif // __COREFOUNDATION_CFAVAILABILITY__ diff --git a/CFBag.c b/CFBag.c index da9e336..15e0a7a 100644 --- a/CFBag.c +++ b/CFBag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBag.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane Machine generated from Notes/HashingCode.template */ @@ -47,7 +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}; -__private_extern__ const CFBagValueCallBacks kCFTypeBagValueCompactableCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; static const CFBagKeyCallBacks __kCFNullBagKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; static const CFBagValueCallBacks __kCFNullBagValueCallBacks = {0, NULL, NULL, NULL, NULL}; @@ -133,328 +132,131 @@ CFTypeID CFBagGetTypeID(void) { return __kCFBagTypeID; } -#define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B) -#define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B) - -static uintptr_t __CFBagStandardRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0100) return stack_value; - return (CFBasicHashHasStrongValues(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_value) : (uintptr_t)CFRetain((CFTypeRef)stack_value); -} - -static uintptr_t __CFBagStandardRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0001) return stack_key; - return (CFBasicHashHasStrongKeys(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_key) : (uintptr_t)CFRetain((CFTypeRef)stack_key); -} - -static void __CFBagStandardReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0200) return; - if (CFBasicHashHasStrongValues(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_value); else CFRelease((CFTypeRef)stack_value); -} - -static void __CFBagStandardReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0002) return; - if (CFBasicHashHasStrongKeys(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_key); else CFRelease((CFTypeRef)stack_key); -} - -static Boolean __CFBagStandardEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - if (CFBasicHashGetSpecialBits(ht) & 0x0400) return coll_value1 == stack_value2; - return CFEqual((CFTypeRef)coll_value1, (CFTypeRef)stack_value2); -} - -static Boolean __CFBagStandardEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - if (CFBasicHashGetSpecialBits(ht) & 0x0004) return coll_key1 == stack_key2; - return CFEqual((CFTypeRef)coll_key1, (CFTypeRef)stack_key2); -} - -static uintptr_t __CFBagStandardHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0008) return stack_key; - return (uintptr_t)CFHash((CFTypeRef)stack_key); -} - -static uintptr_t __CFBagStandardGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFBagStandardCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0800) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value); - return CFCopyDescription((CFTypeRef)stack_value); -} - -static CFStringRef __CFBagStandardCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0010) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key); - return CFCopyDescription((CFTypeRef)stack_key); -} - -static CFBasicHashCallbacks *__CFBagStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); -static void __CFBagStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); - -static const CFBasicHashCallbacks CFBagStandardCallbacks = { - __CFBagStandardCopyCallbacks, - __CFBagStandardFreeCallbacks, - __CFBagStandardRetainValue, - __CFBagStandardRetainKey, - __CFBagStandardReleaseValue, - __CFBagStandardReleaseKey, - __CFBagStandardEquateValues, - __CFBagStandardEquateKeys, - __CFBagStandardHashKey, - __CFBagStandardGetIndirectKey, - __CFBagStandardCopyValueDescription, - __CFBagStandardCopyKeyDescription -}; - -static CFBasicHashCallbacks *__CFBagStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - return (CFBasicHashCallbacks *)&CFBagStandardCallbacks; -} - -static void __CFBagStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { -} - - -static CFBasicHashCallbacks *__CFBagCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - CFBasicHashCallbacks *newcb = NULL; - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); - } else { - newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); - } - if (!newcb) return NULL; - memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *)); - return newcb; -} - -static void __CFBagFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - } else { - CFAllocatorDeallocate(allocator, cb); - } -} - -static uintptr_t __CFBagRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0]; - if (NULL == value_retain) return stack_value; - return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_value); -} - -static uintptr_t __CFBagRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1]; - if (NULL == key_retain) return stack_key; - return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_key); -} - -static void __CFBagReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2]; - if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t) stack_value); -} - -static void __CFBagReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3]; - if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t) stack_key); -} - -static Boolean __CFBagEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4]; - if (NULL == value_equal) return (coll_value1 == stack_value2); - return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t) coll_value1, (const_any_pointer_t) stack_value2) ? 1 : 0; -} - -static Boolean __CFBagEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5]; - if (NULL == key_equal) return (coll_key1 == stack_key2); - return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t) coll_key1, (const_any_pointer_t) stack_key2) ? 1 : 0; -} - -static uintptr_t __CFBagHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6]; - if (NULL == hash) return stack_key; - return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t) stack_key); -} - -static uintptr_t __CFBagGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFBagCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8]; - if (NULL == value_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_value); - return (CFStringRef)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t) stack_value); -} - -static CFStringRef __CFBagCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[9]; - if (NULL == key_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_key); - return (CFStringRef)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t) stack_key); -} static CFBasicHashRef __CFBagCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) { CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); - CFBasicHashCallbacks *cb = NULL; - Boolean std_cb = false; - uint16_t specialBits = 0; - const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; - void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL; - const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; - void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL; - - if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) { - Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain; - Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release; - Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal; - Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash; - Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription; - - Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull); - Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull); - Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull); - Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull); - - Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain; - Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release; - Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal; - Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash; - Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription; - - Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd); - Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd); - Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd); - Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd); - - if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) { - cb = (CFBasicHashCallbacks *)&CFBagStandardCallbacks; - if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) { - std_cb = true; + if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { // all this crap is just for figuring out two flags for GC in the way done historically; it probably simplifies down to three lines, but we let the compiler worry about that + Boolean set_cb = false; + Boolean std_cb = false; + const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; + void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL; + const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; + void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL; + + if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) { + Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain; + Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release; + Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal; + Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash; + Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription; + + Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull); + Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull); + Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull); + Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull); + + Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain; + Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release; + Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal; + Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash; + Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription; + + Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd); + Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd); + Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd); + Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd); + + if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) { + set_cb = true; + if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) { + std_cb = true; + } else { + // just set these to tickle the GC Strong logic below in a way that mimics past practice + key_retain = keyCallBacks ? keyCallBacks->retain : NULL; + key_release = keyCallBacks ? keyCallBacks->release : NULL; + if (useValueCB) { + value_retain = valueCallBacks ? valueCallBacks->retain : NULL; + value_release = valueCallBacks ? valueCallBacks->release : NULL; + } else { + value_retain = key_retain; + value_release = key_release; + } + } + } + } + + if (!set_cb) { + key_retain = keyCallBacks ? keyCallBacks->retain : NULL; + key_release = keyCallBacks ? keyCallBacks->release : NULL; + if (useValueCB) { + value_retain = valueCallBacks ? valueCallBacks->retain : NULL; + value_release = valueCallBacks ? valueCallBacks->release : NULL; } else { - // just set these to tickle the GC Strong logic below in a way that mimics past practice - key_retain = keyCallBacks ? keyCallBacks->retain : NULL; - key_release = keyCallBacks ? keyCallBacks->release : NULL; - if (useValueCB) { - value_retain = valueCallBacks ? valueCallBacks->retain : NULL; - value_release = valueCallBacks ? valueCallBacks->release : NULL; - } else { - value_retain = key_retain; - value_release = key_release; - } + value_retain = key_retain; + value_release = key_release; } - if (keyRetainNull) specialBits |= 0x0001; - if (keyReleaseNull) specialBits |= 0x0002; - if (keyEquateNull) specialBits |= 0x0004; - if (keyHashNull) specialBits |= 0x0008; - if (keyDescribeNull) specialBits |= 0x0010; - if (valueRetainNull) specialBits |= 0x0100; - if (valueReleaseNull) specialBits |= 0x0200; - if (valueEquateNull) specialBits |= 0x0400; - if (valueDescribeNull) specialBits |= 0x0800; - } - } - - if (!cb) { - Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL; - Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL; - CFStringRef (*key_describe)(const_any_pointer_t) = NULL; - CFStringRef (*value_describe)(const_any_pointer_t) = NULL; - CFHashCode (*hash_key)(const_any_pointer_t) = NULL; - key_retain = keyCallBacks ? keyCallBacks->retain : NULL; - key_release = keyCallBacks ? keyCallBacks->release : NULL; - key_equal = keyCallBacks ? keyCallBacks->equal : NULL; - key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL; - if (useValueCB) { - value_retain = valueCallBacks ? valueCallBacks->retain : NULL; - value_release = valueCallBacks ? valueCallBacks->release : NULL; - value_equal = valueCallBacks ? valueCallBacks->equal : NULL; - value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL; - } else { - value_retain = key_retain; - value_release = key_release; - value_equal = key_equal; - value_describe = key_describe; - } - hash_key = keyCallBacks ? keyCallBacks->hash : NULL; - - CFBasicHashCallbacks *newcb = NULL; - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); - } else { - newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); } - if (!newcb) return NULL; - newcb->copyCallbacks = __CFBagCopyCallbacks; - newcb->freeCallbacks = __CFBagFreeCallbacks; - newcb->retainValue = __CFBagRetainValue; - newcb->retainKey = __CFBagRetainKey; - newcb->releaseValue = __CFBagReleaseValue; - newcb->releaseKey = __CFBagReleaseKey; - newcb->equateValues = __CFBagEquateValues; - newcb->equateKeys = __CFBagEquateKeys; - newcb->hashKey = __CFBagHashKey; - newcb->getIndirectKey = __CFBagGetIndirectKey; - newcb->copyValueDescription = __CFBagCopyValueDescription; - newcb->copyKeyDescription = __CFBagCopyKeyDescription; - newcb->context[0] = (uintptr_t)value_retain; - newcb->context[1] = (uintptr_t)key_retain; - newcb->context[2] = (uintptr_t)value_release; - newcb->context[3] = (uintptr_t)key_release; - newcb->context[4] = (uintptr_t)value_equal; - newcb->context[5] = (uintptr_t)key_equal; - newcb->context[6] = (uintptr_t)hash_key; - newcb->context[8] = (uintptr_t)value_describe; - newcb->context[9] = (uintptr_t)key_describe; - cb = newcb; - } - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { if (std_cb || value_retain != NULL || value_release != NULL) { flags |= kCFBasicHashStrongValues; } if (std_cb || key_retain != NULL || key_release != NULL) { flags |= kCFBasicHashStrongKeys; } -#if CFDictionary - if (valueCallBacks == &kCFTypeDictionaryValueCompactableCallBacks) { - // Foundation allocated collections will have compactable values - flags |= kCFBasicHashCompactableValues; - } -#endif } - CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); - if (ht) CFBasicHashSetSpecialBits(ht, specialBits); - if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb); + + CFBasicHashCallbacks callbacks; + callbacks.retainKey = keyCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))keyCallBacks->retain : NULL; + callbacks.releaseKey = keyCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))keyCallBacks->release : NULL; + callbacks.equateKeys = keyCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))keyCallBacks->equal : NULL; + callbacks.hashKey = keyCallBacks ? (CFHashCode (*)(uintptr_t))keyCallBacks->hash : NULL; + callbacks.getIndirectKey = NULL; + callbacks.copyKeyDescription = keyCallBacks ? (CFStringRef (*)(uintptr_t))keyCallBacks->copyDescription : NULL; + callbacks.retainValue = useValueCB ? (valueCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))valueCallBacks->retain : NULL) : (callbacks.retainKey); + callbacks.releaseValue = useValueCB ? (valueCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))valueCallBacks->release : NULL) : (callbacks.releaseKey); + callbacks.equateValues = useValueCB ? (valueCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))valueCallBacks->equal : NULL) : (callbacks.equateKeys); + callbacks.copyValueDescription = useValueCB ? (valueCallBacks ? (CFStringRef (*)(uintptr_t))valueCallBacks->copyDescription : NULL) : (callbacks.copyKeyDescription); + + CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); return ht; } #if CFDictionary -__private_extern__ CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { +CF_PRIVATE CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { #endif #if CFSet || CFBag -__private_extern__ CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { +CF_PRIVATE CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { const_any_pointer_t *vlist = klist; #endif CFTypeID typeID = CFBagGetTypeID(); CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues); CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); - CFBasicHashCallbacks *cb = (CFBasicHashCallbacks *)&CFBagStandardCallbacks; - CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); - CFBasicHashSetSpecialBits(ht, 0x0303); + + CFBasicHashCallbacks callbacks; + callbacks.retainKey = (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeBagKeyCallBacks.retain; + callbacks.releaseKey = (void (*)(CFAllocatorRef, uintptr_t))kCFTypeBagKeyCallBacks.release; + callbacks.equateKeys = (Boolean (*)(uintptr_t, uintptr_t))kCFTypeBagKeyCallBacks.equal; + callbacks.hashKey = (CFHashCode (*)(uintptr_t))kCFTypeBagKeyCallBacks.hash; + callbacks.getIndirectKey = NULL; + callbacks.copyKeyDescription = (CFStringRef (*)(uintptr_t))kCFTypeBagKeyCallBacks.copyDescription; + callbacks.retainValue = CFDictionary ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeBagValueCallBacks.retain : callbacks.retainKey; + callbacks.releaseValue = CFDictionary ? (void (*)(CFAllocatorRef, uintptr_t))kCFTypeBagValueCallBacks.release : callbacks.releaseKey; + callbacks.equateValues = CFDictionary ? (Boolean (*)(uintptr_t, uintptr_t))kCFTypeBagValueCallBacks.equal : callbacks.equateKeys; + callbacks.copyValueDescription = CFDictionary ? (CFStringRef (*)(uintptr_t))kCFTypeBagValueCallBacks.copyDescription : callbacks.copyKeyDescription; + + CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); + CFBasicHashSuppressRC(ht); if (0 < numValues) CFBasicHashSetCapacity(ht, numValues); for (CFIndex idx = 0; idx < numValues; idx++) { CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); } - CFBasicHashSetSpecialBits(ht, 0x0000); + CFBasicHashUnsuppressRC(ht); CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)"); return (CFHashRef)ht; } @@ -476,8 +278,7 @@ CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIn CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); } CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)"); return (CFHashRef)ht; } @@ -493,8 +294,7 @@ CFMutableHashRef CFBagCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFBasicHashRef ht = __CFBagCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); if (!ht) return NULL; - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)"); return (CFMutableHashRef)ht; } @@ -528,8 +328,7 @@ CFHashRef CFBagCreateCopy(CFAllocatorRef allocator, CFHashRef other) { } if (!ht) return NULL; CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)"); return (CFHashRef)ht; } @@ -563,8 +362,7 @@ CFMutableHashRef CFBagCreateMutableCopy(CFAllocatorRef allocator, CFIndex capaci ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); } if (!ht) return NULL; - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)"); return (CFMutableHashRef)ht; } @@ -799,7 +597,7 @@ 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 (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); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); diff --git a/CFBag.h b/CFBag.h index a6e60d5..1547816 100644 --- a/CFBag.h +++ b/CFBag.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBag.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBAG__) diff --git a/CFBase.c b/CFBase.c index 2ed181d..84cb602 100644 --- a/CFBase.c +++ b/CFBase.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBase.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -116,7 +116,7 @@ CF_INLINE CFAllocatorPreferredSizeCallBack __CFAllocatorGetPreferredSizeFunction #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -__private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf); +CF_PRIVATE void __CFAllocatorDeallocate(CFTypeRef cf); static kern_return_t __CFAllocatorZoneIntrospectNoOp(void) { return 0; @@ -404,12 +404,12 @@ static CFStringRef __CFAllocatorCopyDescription(CFTypeRef cf) { // remember to release value returned from copydescr function when this happens } -__private_extern__ CFAllocatorRef __CFAllocatorGetAllocator(CFTypeRef cf) { +CF_PRIVATE CFAllocatorRef __CFAllocatorGetAllocator(CFTypeRef cf) { CFAllocatorRef allocator = (CFAllocatorRef)cf; return (kCFAllocatorUseContext == allocator->_allocator) ? allocator : allocator->_allocator; } -__private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf) { +CF_PRIVATE void __CFAllocatorDeallocate(CFTypeRef cf) { CFAllocatorRef self = (CFAllocatorRef)cf; CFAllocatorRef allocator = self->_allocator; CFAllocatorReleaseCallBack releaseFunc = __CFAllocatorGetReleaseFunction(&self->_context); @@ -446,31 +446,31 @@ static const CFRuntimeClass __CFAllocatorClass = { __CFAllocatorCopyDescription }; -__private_extern__ void __CFAllocatorInitialize(void) { +static void _CFAllocatorSetInstanceTypeIDAndIsa(struct __CFAllocator *memory) { + _CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID); + memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); +} + +CF_PRIVATE void __CFAllocatorInitialize(void) { __kCFAllocatorTypeID = _CFRuntimeRegisterClass(&__CFAllocatorClass); - _CFRuntimeSetInstanceTypeID(&__kCFAllocatorSystemDefault, __kCFAllocatorTypeID); - __kCFAllocatorSystemDefault._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorSystemDefault); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI __kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? objc_collectableZone() : malloc_default_zone()); #endif __kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault; - _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMalloc, __kCFAllocatorTypeID); - __kCFAllocatorMalloc._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMalloc); __kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMallocZone, __kCFAllocatorTypeID); - __kCFAllocatorMallocZone._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorMallocZone); __kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault; __kCFAllocatorMallocZone._context.info = malloc_default_zone(); #endif - _CFRuntimeSetInstanceTypeID(&__kCFAllocatorNull, __kCFAllocatorTypeID); - __kCFAllocatorNull._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); + _CFAllocatorSetInstanceTypeIDAndIsa(&__kCFAllocatorNull); __kCFAllocatorNull._allocator = kCFAllocatorSystemDefault; - } CFTypeID CFAllocatorGetTypeID(void) { @@ -482,9 +482,6 @@ CFAllocatorRef CFAllocatorGetDefault(void) { } void CFAllocatorSetDefault(CFAllocatorRef allocator) { - if (kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator) { - HALT; - } CFAllocatorRef current = __CFGetDefaultAllocator(); #if defined(DEBUG) if (NULL != allocator) { @@ -543,15 +540,13 @@ static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorC if (__CFOASafe) __CFSetLastAllocationEventName(memory, "CFAllocator"); } memset(memory, 0, sizeof(CFRuntimeBase)); - memory->_base._cfisa = 0; #if __LP64__ memory->_base._rc = 1; #else memory->_base._cfinfo[CF_RC_BITS] = 1; #endif memory->_base._cfinfo[CF_INFO_BITS] = 0; - _CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID); - memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID); + _CFAllocatorSetInstanceTypeIDAndIsa(memory); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI memory->size = __CFAllocatorCustomSize; memory->malloc = __CFAllocatorCustomMalloc; @@ -596,14 +591,7 @@ void *CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags void *newptr = NULL; Boolean initialRefcountOne = true; - if (kCFAllocatorSystemDefaultGCRefZero == allocator) { - allocator = kCFAllocatorSystemDefault; - initialRefcountOne = false; - } else if (kCFAllocatorDefaultGCRefZero == allocator) { - // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested - allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator(); - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) initialRefcountOne = false; - } else if (NULL == allocator) { + if (NULL == allocator) { allocator = __CFGetDefaultAllocator(); } @@ -638,10 +626,9 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize CFAllocatorDeallocateCallBack deallocateFunc; void *newptr; - if (kCFAllocatorSystemDefaultGCRefZero == allocator) { + if (0) { allocator = kCFAllocatorSystemDefault; - } else if (kCFAllocatorDefaultGCRefZero == allocator) { - // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested + } else if (0) { allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator(); } else if (NULL == allocator) { allocator = __CFGetDefaultAllocator(); @@ -699,11 +686,9 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize void CFAllocatorDeallocate(CFAllocatorRef allocator, void *ptr) { CFAllocatorDeallocateCallBack deallocateFunc; - if (kCFAllocatorSystemDefaultGCRefZero == allocator) { - if (_CFAllocatorIsGCRefZero(allocator)) return; + if (0) { allocator = kCFAllocatorSystemDefault; - } else if (kCFAllocatorDefaultGCRefZero == allocator) { - // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested + } else if (0) { allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator(); if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) return; } else if (NULL == allocator) { @@ -736,10 +721,9 @@ CFIndex CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex siz CFAllocatorPreferredSizeCallBack prefFunc; CFIndex newsize = 0; - if (kCFAllocatorSystemDefaultGCRefZero == allocator) { + if (0) { allocator = kCFAllocatorSystemDefault; - } else if (kCFAllocatorDefaultGCRefZero == allocator) { - // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested + } else if (0) { allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator(); } else if (NULL == allocator) { allocator = __CFGetDefaultAllocator(); @@ -766,10 +750,9 @@ CFIndex CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex siz } void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context) { - if (kCFAllocatorSystemDefaultGCRefZero == allocator) { + if (0) { allocator = kCFAllocatorSystemDefault; - } else if (kCFAllocatorDefaultGCRefZero == allocator) { - // Under GC, we can't use just any old allocator when the GCRefZero allocator was requested + } else if (0) { allocator = kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : __CFGetDefaultAllocator(); } else if (NULL == allocator) { allocator = __CFGetDefaultAllocator(); @@ -799,7 +782,7 @@ void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context context->preferredSize = __CFAllocatorGetPreferredSizeFunction(&allocator->_context); } -__private_extern__ void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) +CF_PRIVATE void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint) { if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) return auto_zone_allocate_object((auto_zone_t*)kCFAllocatorSystemDefault->_context.info, size, CF_GET_GC_MEMORY_TYPE(hint), false, false); @@ -807,7 +790,7 @@ __private_extern__ void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFInde return CFAllocatorAllocate(allocator, size, hint); } -__private_extern__ void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint) +CF_PRIVATE void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint) { if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { if (ptr && (newsize == 0)) { @@ -821,7 +804,7 @@ __private_extern__ void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void return CFAllocatorReallocate(allocator, ptr, newsize, hint); } -__private_extern__ void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr) +CF_PRIVATE void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr) { // when running GC, don't deallocate. if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, ptr); @@ -873,10 +856,9 @@ static const CFRuntimeClass __CFNullClass = { __CFNullCopyDescription }; -__private_extern__ void __CFNullInitialize(void) { +CF_PRIVATE void __CFNullInitialize(void) { __kCFNullTypeID = _CFRuntimeRegisterClass(&__CFNullClass); - _CFRuntimeSetInstanceTypeID(&__kCFNull, __kCFNullTypeID); - __kCFNull._base._cfisa = __CFISAForTypeID(__kCFNullTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNull, __kCFNullTypeID); } CFTypeID CFNullGetTypeID(void) { diff --git a/CFBase.h b/CFBase.h index e2d7aca..7a83135 100644 --- a/CFBase.h +++ b/CFBase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,13 +22,14 @@ */ /* CFBase.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBASE__) #define __COREFOUNDATION_CFBASE__ 1 #include +#include #if (defined(__CYGWIN32__) || defined(_WIN32)) && !defined(__WIN32__) #define __WIN32__ 1 @@ -85,85 +86,6 @@ #include #endif -// The arguments to these availability macros is a version number, e.g. 10_6, 3_0 -#if (TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) -#include -#include - -#ifndef __IPHONE_5_0 -#define __IPHONE_5_0 50000 -#endif - -#ifndef __IPHONE_6_0 -#define __IPHONE_6_0 60000 -#endif - -// Available on MacOS and iOS -#define CF_AVAILABLE(_mac, _ios) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_##_ios) - -// Available on MacOS only -#define CF_AVAILABLE_MAC(_mac) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_NA) - -// Available on iOS only -#define CF_AVAILABLE_IOS(_ios) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios) - -// Deprecated on either MacOS or iOS, or deprecated on both (check version numbers for details) -#define CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_##_macIntro, __MAC_##_macDep, __IPHONE_##_iosIntro, __IPHONE_##_iosDep) - -// Deprecated on MacOS, unavailable on iOS -#define CF_DEPRECATED_MAC(_macIntro, _macDep) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_##_macIntro, __MAC_##_macDep, __IPHONE_NA, __IPHONE_NA) - -// Unavailable on MacOS, deprecated on iOS -#define CF_DEPRECATED_IOS(_iosIntro, _iosDep) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA, __MAC_NA, __IPHONE_##_iosIntro, __IPHONE_##_iosDep) - -#else - -#if TARGET_OS_WIN32 -#include -#include -#endif - -#define CF_AVAILABLE(_mac, _ios) -#define CF_AVAILABLE_MAC(_mac) -#define CF_AVAILABLE_IOS(_ios) -#define CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep) -#define CF_DEPRECATED_MAC(_macIntro, _macDep) -#define CF_DEPRECATED_IOS(_iosIntro, _iosDep) - -#endif - -#if __has_feature(enumerator_attributes) && __has_attribute(availability) -#define CF_ENUM_AVAILABLE(_mac, _ios) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_##_ios) -#define CF_ENUM_AVAILABLE_MAC(_mac) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_NA) -#define CF_ENUM_AVAILABLE_IOS(_ios) __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_##_ios) -#define CF_ENUM_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_##_macIntro, __MAC_##_macDep, __IPHONE_##_iosIntro, __IPHONE_##_iosDep) -#define CF_ENUM_DEPRECATED_MAC(_macIntro, _macDep) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_##_macIntro, __MAC_##_macDep, __IPHONE_NA, __IPHONE_NA) -#define CF_ENUM_DEPRECATED_IOS(_iosIntro, _iosDep) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA, __MAC_NA, __IPHONE_##_iosIntro, __IPHONE_##_iosDep) -#else -#define CF_ENUM_AVAILABLE(_mac, _ios) -#define CF_ENUM_AVAILABLE_MAC(_mac) -#define CF_ENUM_AVAILABLE_IOS(_ios) -#define CF_ENUM_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep) -#define CF_ENUM_DEPRECATED_MAC(_macIntro, _macDep) -#define CF_ENUM_DEPRECATED_IOS(_iosIntro, _iosDep) -#endif - -#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum)) -#define CF_ENUM(_type, _name) enum _name : _type _name; enum _name : _type -#if (__cplusplus) -#define CF_OPTIONS(_type, _name) _type _name; enum : _type -#else -#define CF_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type -#endif -#else -#define CF_ENUM(_type, _name) _type _name; enum -#define CF_OPTIONS(_type, _name) _type _name; enum -#endif - -// Older versions of these macro; use IOS versions instead -#define CF_AVAILABLE_IPHONE(_ios) CF_AVAILABLE_IOS(_ios) -#define CF_DEPRECATED_IPHONE(_iosIntro, _iosDep) CF_DEPRECATED_IOS(_iosIntro, _iosDep) - #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) #include #endif @@ -396,6 +318,12 @@ CF_EXPORT double kCFCoreFoundationVersionNumber; #define kCFCoreFoundationVersionNumber10_7_2 635.15 #define kCFCoreFoundationVersionNumber10_7_3 635.19 #define kCFCoreFoundationVersionNumber10_7_4 635.21 +#define kCFCoreFoundationVersionNumber10_7_5 635.21 +#define kCFCoreFoundationVersionNumber10_8 744.00 +#define kCFCoreFoundationVersionNumber10_8_1 744.00 +#define kCFCoreFoundationVersionNumber10_8_2 744.12 +#define kCFCoreFoundationVersionNumber10_8_3 744.18 +#define kCFCoreFoundationVersionNumber10_8_4 744.19 #endif #if TARGET_OS_IPHONE @@ -409,8 +337,10 @@ CF_EXPORT double kCFCoreFoundationVersionNumber; #define kCFCoreFoundationVersionNumber_iOS_4_1 550.38 #define kCFCoreFoundationVersionNumber_iOS_4_2 550.52 #define kCFCoreFoundationVersionNumber_iOS_4_3 550.52 -#define kCFCoreFoundationVersionNumber_iOS_5_0 675 -#define kCFCoreFoundationVersionNumber_iOS_5_1 690.1 +#define kCFCoreFoundationVersionNumber_iOS_5_0 675.00 +#define kCFCoreFoundationVersionNumber_iOS_5_1 690.10 +#define kCFCoreFoundationVersionNumber_iOS_6_0 793.00 +#define kCFCoreFoundationVersionNumber_iOS_6_1 793.00 #endif #if __LLP64__ @@ -494,8 +424,6 @@ const CFNullRef kCFNull; // the singleton null instance argument indicates "use the default"; this is the same as using kCFAllocatorDefault or the return value from CFAllocatorGetDefault(). This assures that you will use the allocator in effect at that time. - - You should rarely use kCFAllocatorSystemDefault, the default default allocator. */ typedef const struct __CFAllocator * CFAllocatorRef; @@ -609,6 +537,8 @@ void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context /* Polymorphic CF functions */ +CF_IMPLICIT_BRIDGING_ENABLED + CF_EXPORT CFTypeID CFGetTypeID(CFTypeRef cf); @@ -622,11 +552,10 @@ CF_EXPORT void CFRelease(CFTypeRef cf); CF_EXPORT -CFIndex CFGetRetainCount(CFTypeRef cf); +CFTypeRef CFAutorelease(CFTypeRef CF_RELEASES_ARGUMENT arg) CF_AVAILABLE(10_9, 7_0); -// This function is unavailable in ARC mode. Use CFBridgingRelease instead. CF_EXPORT -CFTypeRef CFMakeCollectable(CFTypeRef cf) CF_AUTOMATED_REFCOUNT_UNAVAILABLE; +CFIndex CFGetRetainCount(CFTypeRef cf); CF_EXPORT Boolean CFEqual(CFTypeRef cf1, CFTypeRef cf2); @@ -640,6 +569,12 @@ CFStringRef CFCopyDescription(CFTypeRef cf); CF_EXPORT CFAllocatorRef CFGetAllocator(CFTypeRef cf); +CF_IMPLICIT_BRIDGING_DISABLED + +// This function is unavailable in ARC mode. +CF_EXPORT +CFTypeRef CFMakeCollectable(CFTypeRef cf) CF_AUTOMATED_REFCOUNT_UNAVAILABLE; + CF_EXTERN_C_END #endif /* ! __COREFOUNDATION_CFBASE__ */ diff --git a/CFBasicHash.c b/CFBasicHash.c index 6e94e1a..074a505 100644 --- a/CFBasicHash.c +++ b/CFBasicHash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBasicHash.m - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -31,6 +31,9 @@ #import #import #import +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED +#import +#endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED #define __SetLastAllocationEventName(A, B) do { if (__CFOASafe && (A)) __CFSetLastAllocationEventName(A, B); } while (0) @@ -38,9 +41,6 @@ #define __SetLastAllocationEventName(A, B) do { } while (0) #endif -#define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B) -#define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B) - #define __AssignWithWriteBarrier(location, value) objc_assign_strongCast((id)value, (id *)location) #define ENABLE_DTRACE_PROBES 0 @@ -307,9 +307,9 @@ typedef union { struct __CFBasicHash { CFRuntimeBase base; - struct { // 128 bits + struct { // 192 bits + uint16_t mutations; uint8_t hash_style:2; - uint8_t fast_grow:1; uint8_t keys_offset:1; uint8_t counts_offset:2; uint8_t counts_width:2; @@ -321,49 +321,71 @@ struct __CFBasicHash { uint8_t int_values:1; uint8_t int_keys:1; uint8_t indirect_keys:1; - uint8_t compactable_keys:1; - uint8_t compactable_values:1; - uint8_t finalized:1; - uint8_t __2:4; - uint8_t num_buckets_idx; /* index to number of buckets */ - uint32_t used_buckets; /* number of used buckets */ - uint8_t __8:8; - uint8_t __9:8; - uint16_t special_bits; - uint16_t deleted; - uint16_t mutations; + uint32_t used_buckets; /* number of used buckets */ + uint64_t deleted:16; + uint64_t num_buckets_idx:8; /* index to number of buckets */ + uint64_t __kret:10; + uint64_t __vret:10; + uint64_t __krel:10; + uint64_t __vrel:10; + uint64_t __:1; + uint64_t null_rc:1; + uint64_t fast_grow:1; + uint64_t finalized:1; + uint64_t __kdes:10; + uint64_t __vdes:10; + uint64_t __kequ:10; + uint64_t __vequ:10; + uint64_t __khas:10; + uint64_t __kget:10; } bits; - __strong CFBasicHashCallbacks *callbacks; void *pointers[1]; }; -__private_extern__ Boolean CFBasicHashHasStrongValues(CFConstBasicHashRef ht) { -#if DEPLOYMENT_TARGET_MACOSX - return ht->bits.strong_values ? true : false; -#else - return false; -#endif -} +static void *CFBasicHashCallBackPtrs[(1UL << 10)]; +static int32_t CFBasicHashCallBackPtrsCount = 0; -__private_extern__ Boolean CFBasicHashHasStrongKeys(CFConstBasicHashRef ht) { -#if DEPLOYMENT_TARGET_MACOSX - return ht->bits.strong_keys ? true : false; -#else - return false; -#endif +static int32_t CFBasicHashGetPtrIndex(void *ptr) { + static dispatch_once_t once; + dispatch_once(&once, ^{ + CFBasicHashCallBackPtrs[0] = NULL; + CFBasicHashCallBackPtrs[1] = (void *)CFCopyDescription; + CFBasicHashCallBackPtrs[2] = (void *)__CFTypeCollectionRelease; + CFBasicHashCallBackPtrs[3] = (void *)__CFTypeCollectionRetain; + CFBasicHashCallBackPtrs[4] = (void *)CFEqual; + CFBasicHashCallBackPtrs[5] = (void *)CFHash; + CFBasicHashCallBackPtrs[6] = (void *)__CFStringCollectionCopy; + CFBasicHashCallBackPtrs[7] = NULL; + CFBasicHashCallBackPtrsCount = 8; + }); + + // The uniquing here is done locklessly for best performance, and in + // a way that will keep multiple threads from stomping each other's + // newly registered values, but may result in multiple slots + // containing the same pointer value. + + int32_t idx; + for (idx = 0; idx < CFBasicHashCallBackPtrsCount; idx++) { + if (CFBasicHashCallBackPtrs[idx] == ptr) return idx; + } + + if (1000 < CFBasicHashCallBackPtrsCount) HALT; + idx = OSAtomicIncrement32(&CFBasicHashCallBackPtrsCount); // returns new value + CFBasicHashCallBackPtrs[idx - 1] = ptr; + return idx - 1; } -CF_INLINE Boolean __CFBasicHashHasCompactableKeys(CFConstBasicHashRef ht) { +CF_PRIVATE Boolean CFBasicHashHasStrongValues(CFConstBasicHashRef ht) { #if DEPLOYMENT_TARGET_MACOSX - return ht->bits.compactable_keys ? true : false; + return ht->bits.strong_values ? true : false; #else return false; #endif } -CF_INLINE Boolean __CFBasicHashHasCompactableValues(CFConstBasicHashRef ht) { +CF_PRIVATE Boolean CFBasicHashHasStrongKeys(CFConstBasicHashRef ht) { #if DEPLOYMENT_TARGET_MACOSX - return ht->bits.compactable_values ? true : false; + return ht->bits.strong_keys ? true : false; #else return false; #endif @@ -394,36 +416,71 @@ CF_INLINE Boolean __CFBasicHashHasHashCache(CFConstBasicHashRef ht) { } CF_INLINE uintptr_t __CFBasicHashImportValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - return ht->callbacks->retainValue(ht, stack_value); + uintptr_t (*func)(CFAllocatorRef, uintptr_t) = (uintptr_t (*)(CFAllocatorRef, uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__vret]; + if (!func || ht->bits.null_rc) return stack_value; + CFAllocatorRef alloc = CFGetAllocator(ht); + return func(alloc, stack_value); } CF_INLINE uintptr_t __CFBasicHashImportKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - return ht->callbacks->retainKey(ht, stack_key); + uintptr_t (*func)(CFAllocatorRef, uintptr_t) = (uintptr_t (*)(CFAllocatorRef, uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__kret]; + if (!func || ht->bits.null_rc) return stack_key; + CFAllocatorRef alloc = CFGetAllocator(ht); + return func(alloc, stack_key); } CF_INLINE void __CFBasicHashEjectValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - ht->callbacks->releaseValue(ht, stack_value); + void (*func)(CFAllocatorRef, uintptr_t) = (void (*)(CFAllocatorRef, uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__vrel]; + if (!func || ht->bits.null_rc) return; + CFAllocatorRef alloc = CFGetAllocator(ht); + func(alloc, stack_value); } CF_INLINE void __CFBasicHashEjectKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - ht->callbacks->releaseKey(ht, stack_key); + void (*func)(CFAllocatorRef, uintptr_t) = (void (*)(CFAllocatorRef, uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__krel]; + if (!func || ht->bits.null_rc) return; + CFAllocatorRef alloc = CFGetAllocator(ht); + func(alloc, stack_key); +} + +CF_INLINE CFStringRef __CFBasicHashDescValue(CFConstBasicHashRef ht, uintptr_t stack_value) { + CFStringRef (*func)(uintptr_t) = (CFStringRef (*)(uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__vdes]; + if (!func) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value); + return func(stack_value); +} + +CF_INLINE CFStringRef __CFBasicHashDescKey(CFConstBasicHashRef ht, uintptr_t stack_key) { + CFStringRef (*func)(uintptr_t) = (CFStringRef (*)(uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__kdes]; + if (!func) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key); + return func(stack_key); } CF_INLINE Boolean __CFBasicHashTestEqualValue(CFConstBasicHashRef ht, uintptr_t stack_value_a, uintptr_t stack_value_b) { - return ht->callbacks->equateValues(ht, stack_value_a, stack_value_b); + Boolean (*func)(uintptr_t, uintptr_t) = (Boolean (*)(uintptr_t, uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__vequ]; + if (!func) return (stack_value_a == stack_value_b); + return func(stack_value_a, stack_value_b); } CF_INLINE Boolean __CFBasicHashTestEqualKey(CFConstBasicHashRef ht, uintptr_t in_coll_key, uintptr_t stack_key) { COCOA_HASHTABLE_TEST_EQUAL(ht, in_coll_key, stack_key); - return ht->callbacks->equateKeys(ht, in_coll_key, stack_key); + Boolean (*func)(uintptr_t, uintptr_t) = (Boolean (*)(uintptr_t, uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__kequ]; + if (!func) return (in_coll_key == stack_key); + return func(in_coll_key, stack_key); } CF_INLINE CFHashCode __CFBasicHashHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - CFHashCode hash_code = (CFHashCode)ht->callbacks->hashKey(ht, stack_key); + CFHashCode (*func)(uintptr_t) = (CFHashCode (*)(uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__khas]; + CFHashCode hash_code = func ? func(stack_key) : stack_key; COCOA_HASHTABLE_HASH_KEY(ht, stack_key, hash_code); return hash_code; } +CF_INLINE uintptr_t __CFBasicHashGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_key) { + uintptr_t (*func)(uintptr_t) = (uintptr_t (*)(uintptr_t))CFBasicHashCallBackPtrs[ht->bits.__kget]; + if (!func) return coll_key; + return func(coll_key); +} + CF_INLINE CFBasicHashValue *__CFBasicHashGetValues(CFConstBasicHashRef ht) { return (CFBasicHashValue *)ht->pointers[0]; } @@ -481,7 +538,7 @@ CF_INLINE uintptr_t __CFBasicHashGetKey(CFConstBasicHashRef ht, CFIndex idx) { } if (ht->bits.indirect_keys) { uintptr_t stack_value = __CFBasicHashGetValue(ht, idx); - return ht->callbacks->getIndirectKey(ht, stack_value); + return __CFBasicHashGetIndirectKey(ht, stack_value); } return __CFBasicHashGetValue(ht, idx); } @@ -666,11 +723,11 @@ CF_INLINE CFIndex __CFBasicHashGetNumBucketsIndexForCapacity(CFConstBasicHashRef return 0; } -__private_extern__ CFIndex CFBasicHashGetNumBuckets(CFConstBasicHashRef ht) { +CF_PRIVATE CFIndex CFBasicHashGetNumBuckets(CFConstBasicHashRef ht) { return __CFBasicHashTableSizes[ht->bits.num_buckets_idx]; } -__private_extern__ CFIndex CFBasicHashGetCapacity(CFConstBasicHashRef ht) { +CF_PRIVATE CFIndex CFBasicHashGetCapacity(CFConstBasicHashRef ht) { return __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx); } @@ -679,7 +736,7 @@ __private_extern__ CFIndex CFBasicHashGetCapacity(CFConstBasicHashRef ht) { // the found bucket or the index of the bucket which should be filled by // an add operation. For a set or multiset, the .weak_key and .weak_value // are the same. -__private_extern__ CFBasicHashBucket CFBasicHashGetBucket(CFConstBasicHashRef ht, CFIndex idx) { +CF_PRIVATE CFBasicHashBucket CFBasicHashGetBucket(CFConstBasicHashRef ht, CFIndex idx) { CFBasicHashBucket result; result.idx = idx; if (__CFBasicHashIsEmptyOrDeleted(ht, idx)) { @@ -860,7 +917,7 @@ CF_INLINE CFIndex __CFBasicHashFindBucket_NoCollision(CFConstBasicHashRef ht, ui return kCFNotFound; } -__private_extern__ CFBasicHashBucket CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key) { +CF_PRIVATE CFBasicHashBucket CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key) { if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) { CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0}; return result; @@ -868,22 +925,18 @@ __private_extern__ CFBasicHashBucket CFBasicHashFindBucket(CFConstBasicHashRef h return __CFBasicHashFindBucket(ht, stack_key); } -__private_extern__ uint16_t CFBasicHashGetSpecialBits(CFConstBasicHashRef ht) { - return ht->bits.special_bits; +CF_PRIVATE void CFBasicHashSuppressRC(CFBasicHashRef ht) { + ht->bits.null_rc = 1; } -__private_extern__ uint16_t CFBasicHashSetSpecialBits(CFBasicHashRef ht, uint16_t bits) { - uint16_t old = ht->bits.special_bits; - ht->bits.special_bits = bits; - return old; +CF_PRIVATE void CFBasicHashUnsuppressRC(CFBasicHashRef ht) { + ht->bits.null_rc = 0; } -__private_extern__ CFOptionFlags CFBasicHashGetFlags(CFConstBasicHashRef ht) { +CF_PRIVATE CFOptionFlags CFBasicHashGetFlags(CFConstBasicHashRef ht) { CFOptionFlags flags = (ht->bits.hash_style << 13); if (CFBasicHashHasStrongValues(ht)) flags |= kCFBasicHashStrongValues; if (CFBasicHashHasStrongKeys(ht)) flags |= kCFBasicHashStrongKeys; - if (__CFBasicHashHasCompactableKeys(ht)) flags |= kCFBasicHashCompactableKeys; - if (__CFBasicHashHasCompactableValues(ht)) flags |= kCFBasicHashCompactableValues; if (ht->bits.fast_grow) flags |= kCFBasicHashAggressiveGrowth; if (ht->bits.keys_offset) flags |= kCFBasicHashHasKeys; if (ht->bits.counts_offset) flags |= kCFBasicHashHasCounts; @@ -891,11 +944,7 @@ __private_extern__ CFOptionFlags CFBasicHashGetFlags(CFConstBasicHashRef ht) { return flags; } -__private_extern__ const CFBasicHashCallbacks *CFBasicHashGetCallbacks(CFConstBasicHashRef ht) { - return ht->callbacks; -} - -__private_extern__ CFIndex CFBasicHashGetCount(CFConstBasicHashRef ht) { +CF_PRIVATE CFIndex CFBasicHashGetCount(CFConstBasicHashRef ht) { if (ht->bits.counts_offset) { CFIndex total = 0L; CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx]; @@ -907,7 +956,7 @@ __private_extern__ CFIndex CFBasicHashGetCount(CFConstBasicHashRef ht) { return (CFIndex)ht->bits.used_buckets; } -__private_extern__ CFIndex CFBasicHashGetCountOfKey(CFConstBasicHashRef ht, uintptr_t stack_key) { +CF_PRIVATE CFIndex CFBasicHashGetCountOfKey(CFConstBasicHashRef ht, uintptr_t stack_key) { if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) { return 0L; } @@ -917,7 +966,7 @@ __private_extern__ CFIndex CFBasicHashGetCountOfKey(CFConstBasicHashRef ht, uint return __CFBasicHashFindBucket(ht, stack_key).count; } -__private_extern__ CFIndex CFBasicHashGetCountOfValue(CFConstBasicHashRef ht, uintptr_t stack_value) { +CF_PRIVATE CFIndex CFBasicHashGetCountOfValue(CFConstBasicHashRef ht, uintptr_t stack_value) { if (__CFBasicHashSubABZero == stack_value) { return 0L; } @@ -935,7 +984,7 @@ __private_extern__ CFIndex CFBasicHashGetCountOfValue(CFConstBasicHashRef ht, ui return total; } -__private_extern__ Boolean CFBasicHashesAreEqual(CFConstBasicHashRef ht1, CFConstBasicHashRef ht2) { +CF_PRIVATE Boolean CFBasicHashesAreEqual(CFConstBasicHashRef ht1, CFConstBasicHashRef ht2) { CFIndex cnt1 = CFBasicHashGetCount(ht1); if (cnt1 != CFBasicHashGetCount(ht2)) return false; if (0 == cnt1) return true; @@ -955,7 +1004,7 @@ __private_extern__ Boolean CFBasicHashesAreEqual(CFConstBasicHashRef ht1, CFCons return equal; } -__private_extern__ void CFBasicHashApply(CFConstBasicHashRef ht, Boolean (^block)(CFBasicHashBucket)) { +CF_PRIVATE void CFBasicHashApply(CFConstBasicHashRef ht, Boolean (^block)(CFBasicHashBucket)) { CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx]; for (CFIndex idx = 0; 0 < used && idx < cnt; idx++) { CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx); @@ -968,7 +1017,7 @@ __private_extern__ void CFBasicHashApply(CFConstBasicHashRef ht, Boolean (^block } } -__private_extern__ void CFBasicHashApplyIndexed(CFConstBasicHashRef ht, CFRange range, Boolean (^block)(CFBasicHashBucket)) { +CF_PRIVATE void CFBasicHashApplyIndexed(CFConstBasicHashRef ht, CFRange range, Boolean (^block)(CFBasicHashBucket)) { if (range.length < 0) HALT; if (range.length == 0) return; CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx]; @@ -983,7 +1032,7 @@ __private_extern__ void CFBasicHashApplyIndexed(CFConstBasicHashRef ht, CFRange } } -__private_extern__ void CFBasicHashGetElements(CFConstBasicHashRef ht, CFIndex bufferslen, uintptr_t *weak_values, uintptr_t *weak_keys) { +CF_PRIVATE void CFBasicHashGetElements(CFConstBasicHashRef ht, CFIndex bufferslen, uintptr_t *weak_values, uintptr_t *weak_keys) { CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx]; CFIndex offset = 0; for (CFIndex idx = 0; 0 < used && idx < cnt && offset < bufferslen; idx++) { @@ -999,10 +1048,10 @@ __private_extern__ void CFBasicHashGetElements(CFConstBasicHashRef ht, CFIndex b } } -__private_extern__ unsigned long __CFBasicHashFastEnumeration(CFConstBasicHashRef ht, struct __objcFastEnumerationStateEquivalent2 *state, void *stackbuffer, unsigned long count) { +CF_PRIVATE unsigned long __CFBasicHashFastEnumeration(CFConstBasicHashRef ht, struct __objcFastEnumerationStateEquivalent2 *state, void *stackbuffer, unsigned long count) { /* copy as many as count items over */ if (0 == state->state) { /* first time */ - state->mutationsPtr = (unsigned long *)&ht->bits + (__LP64__ ? 1 : 3); + state->mutationsPtr = (unsigned long *)&ht->bits; } state->itemsPtr = (unsigned long *)stackbuffer; CFIndex cntx = 0; @@ -1078,10 +1127,6 @@ static void __CFBasicHashDrain(CFBasicHashRef ht, Boolean forFinalization) { } } - if (forFinalization) { - ht->callbacks->freeCallbacks(ht, allocator, ht->callbacks); - } - if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { CFAllocatorDeallocate(allocator, old_values); CFAllocatorDeallocate(allocator, old_keys); @@ -1121,12 +1166,12 @@ static void __CFBasicHashRehash(CFBasicHashRef ht, CFIndex newItemCount) { uintptr_t *new_hashes = NULL; if (0 < new_num_buckets) { - new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongValues(ht), __CFBasicHashHasCompactableValues(ht)); + new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongValues(ht), 0); if (!new_values) HALT; __SetLastAllocationEventName(new_values, "CFBasicHash (value-store)"); memset(new_values, 0, new_num_buckets * sizeof(CFBasicHashValue)); if (ht->bits.keys_offset) { - new_keys = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongKeys(ht), __CFBasicHashHasCompactableKeys(ht)); + new_keys = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongKeys(ht), 0); if (!new_keys) HALT; __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)"); memset(new_keys, 0, new_num_buckets * sizeof(CFBasicHashValue)); @@ -1180,7 +1225,7 @@ static void __CFBasicHashRehash(CFBasicHashRef ht, CFIndex newItemCount) { if (__CFBasicHashSubABOne == stack_key) stack_key = ~0UL; } if (ht->bits.indirect_keys) { - stack_key = ht->callbacks->getIndirectKey(ht, stack_value); + stack_key = __CFBasicHashGetIndirectKey(ht, stack_value); } CFIndex bkt_idx = __CFBasicHashFindBucket_NoCollision(ht, stack_key, old_hashes ? old_hashes[idx] : 0UL); __CFBasicHashSetValue(ht, bkt_idx, stack_value, false, false); @@ -1219,7 +1264,7 @@ static void __CFBasicHashRehash(CFBasicHashRef ht, CFIndex newItemCount) { #endif } -__private_extern__ void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity) { +CF_PRIVATE void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity) { if (!CFBasicHashIsMutable(ht)) HALT; if (ht->bits.used_buckets < capacity) { ht->bits.mutations++; @@ -1300,7 +1345,7 @@ static void __CFBasicHashRemoveValue(CFBasicHashRef ht, CFIndex bkt_idx) { } } -__private_extern__ Boolean CFBasicHashAddValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) { +CF_PRIVATE Boolean CFBasicHashAddValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) { if (!CFBasicHashIsMutable(ht)) HALT; if (__CFBasicHashSubABZero == stack_key) HALT; if (__CFBasicHashSubABOne == stack_key) HALT; @@ -1320,7 +1365,7 @@ __private_extern__ Boolean CFBasicHashAddValue(CFBasicHashRef ht, uintptr_t stac return false; } -__private_extern__ void CFBasicHashReplaceValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) { +CF_PRIVATE void CFBasicHashReplaceValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) { if (!CFBasicHashIsMutable(ht)) HALT; if (__CFBasicHashSubABZero == stack_key) HALT; if (__CFBasicHashSubABOne == stack_key) HALT; @@ -1332,7 +1377,7 @@ __private_extern__ void CFBasicHashReplaceValue(CFBasicHashRef ht, uintptr_t sta } } -__private_extern__ void CFBasicHashSetValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) { +CF_PRIVATE void CFBasicHashSetValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) { if (!CFBasicHashIsMutable(ht)) HALT; if (__CFBasicHashSubABZero == stack_key) HALT; if (__CFBasicHashSubABOne == stack_key) HALT; @@ -1346,7 +1391,7 @@ __private_extern__ void CFBasicHashSetValue(CFBasicHashRef ht, uintptr_t stack_k } } -__private_extern__ CFIndex CFBasicHashRemoveValue(CFBasicHashRef ht, uintptr_t stack_key) { +CF_PRIVATE CFIndex CFBasicHashRemoveValue(CFBasicHashRef ht, uintptr_t stack_key) { if (!CFBasicHashIsMutable(ht)) HALT; if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) return 0; CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key); @@ -1361,7 +1406,7 @@ __private_extern__ CFIndex CFBasicHashRemoveValue(CFBasicHashRef ht, uintptr_t s return bkt.count; } -__private_extern__ CFIndex CFBasicHashRemoveValueAtIndex(CFBasicHashRef ht, CFIndex idx) { +CF_PRIVATE CFIndex CFBasicHashRemoveValueAtIndex(CFBasicHashRef ht, CFIndex idx) { if (!CFBasicHashIsMutable(ht)) HALT; CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx); if (1 < bkt.count) { @@ -1375,13 +1420,13 @@ __private_extern__ CFIndex CFBasicHashRemoveValueAtIndex(CFBasicHashRef ht, CFIn return bkt.count; } -__private_extern__ void CFBasicHashRemoveAllValues(CFBasicHashRef ht) { +CF_PRIVATE void CFBasicHashRemoveAllValues(CFBasicHashRef ht) { if (!CFBasicHashIsMutable(ht)) HALT; if (0 == ht->bits.num_buckets_idx) return; __CFBasicHashDrain(ht, false); } -Boolean CFBasicHashAddIntValueAndInc(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t int_value) { +CF_PRIVATE Boolean CFBasicHashAddIntValueAndInc(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t int_value) { if (!CFBasicHashIsMutable(ht)) HALT; if (__CFBasicHashSubABZero == stack_key) HALT; if (__CFBasicHashSubABOne == stack_key) HALT; @@ -1413,7 +1458,7 @@ Boolean CFBasicHashAddIntValueAndInc(CFBasicHashRef ht, uintptr_t stack_key, uin return false; } -void CFBasicHashRemoveIntValueAndDec(CFBasicHashRef ht, uintptr_t int_value) { +CF_PRIVATE void CFBasicHashRemoveIntValueAndDec(CFBasicHashRef ht, uintptr_t int_value) { if (!CFBasicHashIsMutable(ht)) HALT; if (__CFBasicHashSubABZero == int_value) HALT; if (__CFBasicHashSubABOne == int_value) HALT; @@ -1435,7 +1480,7 @@ void CFBasicHashRemoveIntValueAndDec(CFBasicHashRef ht, uintptr_t int_value) { __CFBasicHashRemoveValue(ht, bkt_idx); } -__private_extern__ size_t CFBasicHashGetSize(CFConstBasicHashRef ht, Boolean total) { +CF_PRIVATE size_t CFBasicHashGetSize(CFConstBasicHashRef ht, Boolean total) { size_t size = sizeof(struct __CFBasicHash); if (ht->bits.keys_offset) size += sizeof(CFBasicHashValue *); if (ht->bits.counts_offset) size += sizeof(void *); @@ -1447,21 +1492,20 @@ __private_extern__ size_t CFBasicHashGetSize(CFConstBasicHashRef ht, Boolean tot if (ht->bits.keys_offset) size += malloc_size(__CFBasicHashGetKeys(ht)); if (ht->bits.counts_offset) size += malloc_size(__CFBasicHashGetCounts(ht)); if (__CFBasicHashHasHashCache(ht)) size += malloc_size(__CFBasicHashGetHashes(ht)); - size += malloc_size((void *)ht->callbacks); } } return size; } -__private_extern__ CFStringRef CFBasicHashCopyDescription(CFConstBasicHashRef ht, Boolean detailed, CFStringRef prefix, CFStringRef entryPrefix, Boolean describeElements) { +CF_PRIVATE CFStringRef CFBasicHashCopyDescription(CFConstBasicHashRef ht, Boolean detailed, CFStringRef prefix, CFStringRef entryPrefix, Boolean describeElements) { CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); CFStringAppendFormat(result, NULL, CFSTR("%@{type = %s %s%s, count = %ld,\n"), prefix, (CFBasicHashIsMutable(ht) ? "mutable" : "immutable"), ((ht->bits.counts_offset) ? "multi" : ""), ((ht->bits.keys_offset) ? "dict" : "set"), CFBasicHashGetCount(ht)); if (detailed) { const char *cb_type = "custom"; CFStringAppendFormat(result, NULL, CFSTR("%@hash cache = %s, strong values = %s, strong keys = %s, cb = %s,\n"), prefix, (__CFBasicHashHasHashCache(ht) ? "yes" : "no"), (CFBasicHashHasStrongValues(ht) ? "yes" : "no"), (CFBasicHashHasStrongKeys(ht) ? "yes" : "no"), cb_type); - CFStringAppendFormat(result, NULL, CFSTR("%@num bucket index = %d, num buckets = %ld, capacity = %d, num buckets used = %u,\n"), prefix, ht->bits.num_buckets_idx, CFBasicHashGetNumBuckets(ht), CFBasicHashGetCapacity(ht), ht->bits.used_buckets); + CFStringAppendFormat(result, NULL, CFSTR("%@num bucket index = %d, num buckets = %ld, capacity = %ld, num buckets used = %u,\n"), prefix, ht->bits.num_buckets_idx, CFBasicHashGetNumBuckets(ht), (long)CFBasicHashGetCapacity(ht), ht->bits.used_buckets); CFStringAppendFormat(result, NULL, CFSTR("%@counts width = %d, finalized = %s,\n"), prefix,((ht->bits.counts_offset) ? (1 << ht->bits.counts_width) : 0), (ht->bits.finalized ? "yes" : "no")); - CFStringAppendFormat(result, NULL, CFSTR("%@num mutations = %ld, num deleted = %ld, size = %ld, total size = %ld,\n"), prefix, ht->bits.mutations, ht->bits.deleted, CFBasicHashGetSize(ht, false), CFBasicHashGetSize(ht, true)); + CFStringAppendFormat(result, NULL, CFSTR("%@num mutations = %ld, num deleted = %ld, size = %ld, total size = %ld,\n"), prefix, (long)ht->bits.mutations, (long)ht->bits.deleted, CFBasicHashGetSize(ht, false), CFBasicHashGetSize(ht, true)); CFStringAppendFormat(result, NULL, CFSTR("%@values ptr = %p, keys ptr = %p, counts ptr = %p, hashes ptr = %p,\n"), prefix, __CFBasicHashGetValues(ht), ((ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : NULL), ((ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht) : NULL), (__CFBasicHashHasHashCache(ht) ? __CFBasicHashGetHashes(ht) : NULL)); } CFStringAppendFormat(result, NULL, CFSTR("%@entries =>\n"), prefix); @@ -1473,9 +1517,9 @@ __private_extern__ CFStringRef CFBasicHashCopyDescription(CFConstBasicHashRef ht kDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)bkt.weak_key); } } else { - vDesc = ht->callbacks->copyValueDescription(ht, bkt.weak_value); + vDesc = __CFBasicHashDescValue(ht, bkt.weak_value); if (ht->bits.keys_offset) { - kDesc = ht->callbacks->copyKeyDescription(ht, bkt.weak_key); + kDesc = __CFBasicHashDescKey(ht, bkt.weak_key); } } if (ht->bits.keys_offset && ht->bits.counts_offset) { @@ -1495,25 +1539,25 @@ __private_extern__ CFStringRef CFBasicHashCopyDescription(CFConstBasicHashRef ht return result; } -__private_extern__ void CFBasicHashShow(CFConstBasicHashRef ht) { +CF_PRIVATE void CFBasicHashShow(CFConstBasicHashRef ht) { CFStringRef str = CFBasicHashCopyDescription(ht, true, CFSTR(""), CFSTR("\t"), false); CFShow(str); CFRelease(str); } -__private_extern__ Boolean __CFBasicHashEqual(CFTypeRef cf1, CFTypeRef cf2) { +CF_PRIVATE Boolean __CFBasicHashEqual(CFTypeRef cf1, CFTypeRef cf2) { CFBasicHashRef ht1 = (CFBasicHashRef)cf1; CFBasicHashRef ht2 = (CFBasicHashRef)cf2; //#warning this used to require that the key and value equal callbacks were pointer identical return CFBasicHashesAreEqual(ht1, ht2); } -__private_extern__ CFHashCode __CFBasicHashHash(CFTypeRef cf) { +CF_PRIVATE CFHashCode __CFBasicHashHash(CFTypeRef cf) { CFBasicHashRef ht = (CFBasicHashRef)cf; return CFBasicHashGetCount(ht); } -__private_extern__ CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf) { +CF_PRIVATE CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf) { CFBasicHashRef ht = (CFBasicHashRef)cf; CFStringRef desc = CFBasicHashCopyDescription(ht, false, CFSTR(""), CFSTR("\t"), true); CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@"), cf, CFGetAllocator(cf), desc); @@ -1521,7 +1565,7 @@ __private_extern__ CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf) { return result; } -__private_extern__ void __CFBasicHashDeallocate(CFTypeRef cf) { +CF_PRIVATE void __CFBasicHashDeallocate(CFTypeRef cf) { CFBasicHashRef ht = (CFBasicHashRef)cf; if (ht->bits.finalized) HALT; ht->bits.finalized = 1; @@ -1546,12 +1590,12 @@ static const CFRuntimeClass __CFBasicHashClass = { __CFBasicHashCopyDescription }; -__private_extern__ CFTypeID CFBasicHashGetTypeID(void) { +CF_PRIVATE CFTypeID CFBasicHashGetTypeID(void) { if (_kCFRuntimeNotATypeID == __kCFBasicHashTypeID) __kCFBasicHashTypeID = _CFRuntimeRegisterClass(&__CFBasicHashClass); return __kCFBasicHashTypeID; } -CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, const CFBasicHashCallbacks *cb) { +CF_PRIVATE CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, const CFBasicHashCallbacks *cb) { size_t size = sizeof(struct __CFBasicHash) - sizeof(CFRuntimeBase); if (flags & kCFBasicHashHasKeys) size += sizeof(CFBasicHashValue *); // keys if (flags & kCFBasicHashHasCounts) size += sizeof(void *); // counts @@ -1570,11 +1614,6 @@ CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, ht->bits.int_values = (flags & kCFBasicHashIntegerValues) ? 1 : 0; ht->bits.int_keys = (flags & kCFBasicHashIntegerKeys) ? 1 : 0; ht->bits.indirect_keys = (flags & kCFBasicHashIndirectKeys) ? 1 : 0; - ht->bits.compactable_keys = (flags & kCFBasicHashCompactableKeys) ? 1 : 0; - ht->bits.compactable_values = (flags & kCFBasicHashCompactableValues) ? 1 : 0; - ht->bits.__2 = 0; - ht->bits.__8 = 0; - ht->bits.__9 = 0; ht->bits.num_buckets_idx = 0; ht->bits.used_buckets = 0; ht->bits.deleted = 0; @@ -1603,7 +1642,17 @@ CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, ht->bits.weak_keys = 0; #endif - __AssignWithWriteBarrier(&ht->callbacks, cb); + ht->bits.__kret = CFBasicHashGetPtrIndex((void *)cb->retainKey); + ht->bits.__vret = CFBasicHashGetPtrIndex((void *)cb->retainValue); + ht->bits.__krel = CFBasicHashGetPtrIndex((void *)cb->releaseKey); + ht->bits.__vrel = CFBasicHashGetPtrIndex((void *)cb->releaseValue); + ht->bits.__kdes = CFBasicHashGetPtrIndex((void *)cb->copyKeyDescription); + ht->bits.__vdes = CFBasicHashGetPtrIndex((void *)cb->copyValueDescription); + ht->bits.__kequ = CFBasicHashGetPtrIndex((void *)cb->equateKeys); + ht->bits.__vequ = CFBasicHashGetPtrIndex((void *)cb->equateValues); + ht->bits.__khas = CFBasicHashGetPtrIndex((void *)cb->hashKey); + ht->bits.__kget = CFBasicHashGetPtrIndex((void *)cb->getIndirectKey); + for (CFIndex idx = 0; idx < offset; idx++) { ht->pointers[idx] = NULL; } @@ -1619,13 +1668,8 @@ CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, return ht; } -CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashRef src_ht) { +CF_PRIVATE CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashRef src_ht) { size_t size = CFBasicHashGetSize(src_ht, false) - sizeof(CFRuntimeBase); - CFBasicHashCallbacks *newcb = src_ht->callbacks->copyCallbacks(src_ht, allocator, src_ht->callbacks); - if (NULL == newcb) { - return NULL; - } - CFIndex new_num_buckets = __CFBasicHashTableSizes[src_ht->bits.num_buckets_idx]; CFBasicHashValue *new_values = NULL, *new_keys = NULL; void *new_counts = NULL; @@ -1634,8 +1678,7 @@ CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashR if (0 < new_num_buckets) { Boolean strongValues = CFBasicHashHasStrongValues(src_ht) && !(kCFUseCollectableAllocator && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)); Boolean strongKeys = CFBasicHashHasStrongKeys(src_ht) && !(kCFUseCollectableAllocator && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)); - Boolean compactableValues = __CFBasicHashHasCompactableValues(src_ht) && !(kCFUseCollectableAllocator && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)); - new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory2(allocator, new_num_buckets, sizeof(CFBasicHashValue), strongValues, compactableValues); + new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory2(allocator, new_num_buckets, sizeof(CFBasicHashValue), strongValues, 0); if (!new_values) return NULL; // in this unusual circumstance, leak previously allocated blocks for now __SetLastAllocationEventName(new_values, "CFBasicHash (value-store)"); if (src_ht->bits.keys_offset) { @@ -1667,7 +1710,6 @@ CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashR } ht->bits.finalized = 0; ht->bits.mutations = 1; - __AssignWithWriteBarrier(&ht->callbacks, newcb); if (0 == new_num_buckets) { #if ENABLE_MEMORY_COUNTERS @@ -1740,13 +1782,4 @@ CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashR return ht; } -__private_extern__ void __CFBasicHashSetCallbacks(CFBasicHashRef ht, const CFBasicHashCallbacks *cb) { - __AssignWithWriteBarrier(&ht->callbacks, cb); -} - -void _CFbhx588461(CFBasicHashRef ht, Boolean growth) { - if (!CFBasicHashIsMutable(ht)) HALT; - if (ht->bits.finalized) HALT; - ht->bits.fast_grow = growth ? 1 : 0; -} diff --git a/CFBasicHash.h b/CFBasicHash.h index eb85edf..362d6c9 100644 --- a/CFBasicHash.h +++ b/CFBasicHash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBasicHash.h - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. */ #include @@ -65,9 +65,6 @@ enum { kCFBasicHashExponentialHashing = (__kCFBasicHashExponentialHashingValue << 13), kCFBasicHashAggressiveGrowth = (1UL << 15), - - kCFBasicHashCompactableValues = (1UL << 16), - kCFBasicHashCompactableKeys = (1UL << 17), }; // Note that for a hash table without keys, the value is treated as the key, @@ -96,33 +93,26 @@ CF_INLINE void CFBasicHashMakeImmutable(CFBasicHashRef ht) { typedef struct __CFBasicHashCallbacks CFBasicHashCallbacks; struct __CFBasicHashCallbacks { - CFBasicHashCallbacks *(*copyCallbacks)(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); // Return new value - void (*freeCallbacks)(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); - uintptr_t (*retainValue)(CFConstBasicHashRef ht, uintptr_t stack_value); // Return 2nd arg or new value - uintptr_t (*retainKey)(CFConstBasicHashRef ht, uintptr_t stack_key); // Return 2nd arg or new key - void (*releaseValue)(CFConstBasicHashRef ht, uintptr_t stack_value); - void (*releaseKey)(CFConstBasicHashRef ht, uintptr_t stack_key); - Boolean (*equateValues)(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2); // 2nd arg is in-collection value, 3rd arg is probe parameter OR in-collection value for a second collection - Boolean (*equateKeys)(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2); // 2nd arg is in-collection key, 3rd arg is probe parameter - uintptr_t (*hashKey)(CFConstBasicHashRef ht, uintptr_t stack_key); - uintptr_t (*getIndirectKey)(CFConstBasicHashRef ht, uintptr_t coll_value); // Return key; 2nd arg is in-collection value - CFStringRef (*copyValueDescription)(CFConstBasicHashRef ht, uintptr_t stack_value); - CFStringRef (*copyKeyDescription)(CFConstBasicHashRef ht, uintptr_t stack_key); - uintptr_t context[0]; // variable size; any pointers in here must remain valid as long as the CFBasicHash + uintptr_t (*retainValue)(CFAllocatorRef alloc, uintptr_t stack_value); // Return 2nd arg or new value + uintptr_t (*retainKey)(CFAllocatorRef alloc, uintptr_t stack_key); // Return 2nd arg or new key + void (*releaseValue)(CFAllocatorRef alloc, uintptr_t stack_value); + void (*releaseKey)(CFAllocatorRef alloc, uintptr_t stack_key); + Boolean (*equateValues)(uintptr_t coll_value1, uintptr_t stack_value2); // 1st arg is in-collection value, 2nd arg is probe parameter OR in-collection value for a second collection + Boolean (*equateKeys)(uintptr_t coll_key1, uintptr_t stack_key2); // 1st arg is in-collection key, 2nd arg is probe parameter + CFHashCode (*hashKey)(uintptr_t stack_key); + uintptr_t (*getIndirectKey)(uintptr_t coll_value); // Return key; 1st arg is in-collection value + CFStringRef (*copyValueDescription)(uintptr_t stack_value); + CFStringRef (*copyKeyDescription)(uintptr_t stack_key); }; Boolean CFBasicHashHasStrongValues(CFConstBasicHashRef ht); Boolean CFBasicHashHasStrongKeys(CFConstBasicHashRef ht); -uint16_t CFBasicHashGetSpecialBits(CFConstBasicHashRef ht); -uint16_t CFBasicHashSetSpecialBits(CFBasicHashRef ht, uint16_t bits); - CFOptionFlags CFBasicHashGetFlags(CFConstBasicHashRef ht); CFIndex CFBasicHashGetNumBuckets(CFConstBasicHashRef ht); CFIndex CFBasicHashGetCapacity(CFConstBasicHashRef ht); void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity); -const CFBasicHashCallbacks *CFBasicHashGetCallbacks(CFConstBasicHashRef ht); CFIndex CFBasicHashGetCount(CFConstBasicHashRef ht); CFBasicHashBucket CFBasicHashGetBucket(CFConstBasicHashRef ht, CFIndex idx); CFBasicHashBucket CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key); @@ -144,6 +134,8 @@ Boolean CFBasicHashAddIntValueAndInc(CFBasicHashRef ht, uintptr_t stack_key, uin void CFBasicHashRemoveIntValueAndDec(CFBasicHashRef ht, uintptr_t int_value); size_t CFBasicHashGetSize(CFConstBasicHashRef ht, Boolean total); +void CFBasicHashSuppressRC(CFBasicHashRef ht); +void CFBasicHashUnsuppressRC(CFBasicHashRef ht); CFStringRef CFBasicHashCopyDescription(CFConstBasicHashRef ht, Boolean detailed, CFStringRef linePrefix, CFStringRef entryLinePrefix, Boolean describeElements); @@ -158,7 +150,6 @@ extern unsigned long __CFBasicHashFastEnumeration(CFConstBasicHashRef ht, struct // creation functions create mutable CFBasicHashRefs CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, const CFBasicHashCallbacks *cb); CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashRef ht); -void __CFBasicHashSetCallbacks(CFBasicHashRef ht, const CFBasicHashCallbacks *cb); CF_EXTERN_C_END diff --git a/CFBasicHashFindBucket.m b/CFBasicHashFindBucket.m index ccbcb69..bbc87a9 100644 --- a/CFBasicHashFindBucket.m +++ b/CFBasicHashFindBucket.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBasicHashFindBucket.m - Copyright (c) 2009-2012, Apple Inc. All rights reserved. + Copyright (c) 2009-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -132,7 +132,7 @@ FIND_BUCKET_NAME (CFConstBasicHashRef ht, uintptr_t stack_key if (__CFBasicHashSubABOne == curr_key) curr_key = ~0UL; #if FIND_BUCKET_FOR_INDIRECT_KEY // curr_key holds the value coming in here - curr_key = ht->callbacks->getIndirectKey(ht, curr_key); + curr_key = __CFBasicHashGetIndirectKey(ht, curr_key); #endif if (curr_key == stack_key || ((!hashes || hashes[probe] == hash_code) && __CFBasicHashTestEqualKey(ht, curr_key, stack_key))) { COCOA_HASHTABLE_PROBING_END(ht, idx + 1); diff --git a/CFBigNumber.c b/CFBigNumber.c index 62ea129..cfe2c77 100644 --- a/CFBigNumber.c +++ b/CFBigNumber.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBigNumber.c - Copyright (c) 2012-2012, Apple Inc. All rights reserved. + Copyright (c) 2012-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane Original author: Zhi Feng Huang */ @@ -35,8 +35,15 @@ #include "CFInternal.h" +typedef struct { + int64_t high; + uint64_t low; +} CFSInt128Struct; + #define kCFNumberSInt128Type 17 +CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number); + #if __LP64__ #ifndef _INT128_T @@ -286,11 +293,13 @@ __uint128_t _CFBigNumGetUInt128(const _CFBigNum *num) { void _CFBigNumInitWithCFNumber(_CFBigNum *r, CFNumberRef inNum) { - uint8_t bytes[128]; + uint8_t bytes[128 + 16]; memset(bytes, 0, sizeof(bytes)); - CFNumberType type = CFNumberGetType(inNum); - CFNumberGetValue(inNum, type, (void *)bytes); - _CFBigNumInitWithBytes(r, (const void *)bytes, type); + // round bytes up to next multiple of 16; compiler attributes won't always guarantee big alignment + void *bytesa = (uint8_t *)(((uintptr_t)bytes / 16) * 16 + 16); + CFNumberType type = _CFNumberGetType2(inNum); + CFNumberGetValue(inNum, type, bytesa); + _CFBigNumInitWithBytes(r, bytesa, type); } void _CFBigNumInitWithBytes(_CFBigNum *r, const void *bytes, CFNumberType type) { @@ -341,9 +350,13 @@ void _CFBigNumInitWithBytes(_CFBigNum *r, const void *bytes, CFNumberType type) } return; #if __LP64__ - case kCFNumberSInt128Type: - _CFBigNumInitWithInt128(r, *(__int128_t *)bytes); + case kCFNumberSInt128Type: { + CFSInt128Struct s; + memmove(&s, bytes, sizeof(CFSInt128Struct)); // the hard way because bytes might not be aligned + __int128_t val = (__int128_t)s.low + ((__int128_t)s.high << 64); + _CFBigNumInitWithInt128(r, val); return; + } #endif default: return; diff --git a/CFBigNumber.h b/CFBigNumber.h index 7fc0a89..26ec11f 100644 --- a/CFBigNumber.h +++ b/CFBigNumber.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBigNumber.h - Copyright (c) 2012-2012, Apple Inc. All rights reserved. + Copyright (c) 2012-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBIGNUMBER__) diff --git a/CFBinaryHeap.c b/CFBinaryHeap.c index f711b8f..06a98e7 100644 --- a/CFBinaryHeap.c +++ b/CFBinaryHeap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBinaryHeap.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -156,7 +156,7 @@ static CFStringRef __CFBinaryHeapCopyDescription(CFTypeRef cf) { const void **list, *buffer[256]; cnt = __CFBinaryHeapCount(heap); result = CFStringCreateMutable(CFGetAllocator(heap), 0); - CFStringAppendFormat(result, NULL, CFSTR("{count = %u, capacity = %u, objects = (\n"), cf, CFGetAllocator(heap), cnt, __CFBinaryHeapCapacity(heap)); + CFStringAppendFormat(result, NULL, CFSTR("{count = %lu, capacity = %lu, objects = (\n"), cf, CFGetAllocator(heap), (unsigned long)cnt, (unsigned long)__CFBinaryHeapCapacity(heap)); list = (cnt <= 128) ? (const void **)buffer : (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0); // GC OK if (__CFOASafe && list != buffer) __CFSetLastAllocationEventName(list, "CFBinaryHeap (temp)"); CFBinaryHeapGetValues(heap, list); @@ -167,10 +167,10 @@ static CFStringRef __CFBinaryHeapCopyDescription(CFTypeRef cf) { desc = heap->_callbacks.copyDescription(item); } if (NULL != desc) { - CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@\n"), idx, desc); + CFStringAppendFormat(result, NULL, CFSTR("\t%lu : %@\n"), (unsigned long)idx, desc); CFRelease(desc); } else { - CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, item); + CFStringAppendFormat(result, NULL, CFSTR("\t%lu : <%p>\n"), (unsigned long)idx, item); } } CFStringAppend(result, CFSTR(")}")); @@ -207,7 +207,7 @@ static const CFRuntimeClass __CFBinaryHeapClass = { __CFBinaryHeapCopyDescription }; -__private_extern__ void __CFBinaryHeapInitialize(void) { +CF_PRIVATE void __CFBinaryHeapInitialize(void) { __kCFBinaryHeapTypeID = _CFRuntimeRegisterClass(&__CFBinaryHeapClass); } diff --git a/CFBinaryHeap.h b/CFBinaryHeap.h index da94e9a..ccccf55 100644 --- a/CFBinaryHeap.h +++ b/CFBinaryHeap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBinaryHeap.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /*! @header CFBinaryHeap diff --git a/CFBinaryPList.c b/CFBinaryPList.c index ed1a854..8a1e56a 100644 --- a/CFBinaryPList.c +++ b/CFBinaryPList.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBinaryPList.c - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -128,7 +128,7 @@ static const CFRuntimeClass __CFKeyedArchiverUIDClass = { __CFKeyedArchiverUIDCopyDescription }; -__private_extern__ void __CFKeyedArchiverUIDInitialize(void) { +CF_PRIVATE void __CFKeyedArchiverUIDInitialize(void) { __kCFKeyedArchiverUIDTypeID = _CFRuntimeRegisterClass(&__CFKeyedArchiverUIDClass); } @@ -154,10 +154,12 @@ uint32_t _CFKeyedArchiverUIDGetValue(CFKeyedArchiverUIDRef uid) { #pragma mark - #pragma mark Writing -__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...); +CF_PRIVATE CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...); typedef struct { CFTypeRef stream; + void *databytes; + uint64_t datalen; CFErrorRef error; uint64_t written; int32_t used; @@ -168,19 +170,26 @@ typedef struct { static void writeBytes(__CFBinaryPlistWriteBuffer *buf, const UInt8 *bytes, CFIndex length) { if (0 == length) return; if (buf->error) return; + if (buf->databytes) { + if (buf->datalen < buf->written + length) { + buf->error = __CFPropertyListCreateError(kCFPropertyListWriteStreamError, CFSTR("Binary property list writing could not be completed because databytes is full.")); + return; + } + memmove((char *)buf->databytes + buf->written, bytes, length); + } if (buf->streamIsData) { - CFDataAppendBytes((CFMutableDataRef)buf->stream, bytes, length); + if (buf->stream) CFDataAppendBytes((CFMutableDataRef)buf->stream, bytes, length); buf->written += length; } else { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS while (0 < length) { - CFIndex ret = CFWriteStreamWrite((CFWriteStreamRef)buf->stream, bytes, length); + CFIndex ret = buf->stream ? CFWriteStreamWrite((CFWriteStreamRef)buf->stream, bytes, length) : length; if (ret == 0) { buf->error = __CFPropertyListCreateError(kCFPropertyListWriteStreamError, CFSTR("Binary property list writing could not be completed because stream is full.")); return; } if (ret < 0) { - CFErrorRef err = CFWriteStreamCopyError((CFWriteStreamRef)buf->stream); + CFErrorRef err = buf->stream ? CFWriteStreamCopyError((CFWriteStreamRef)buf->stream) : NULL; buf->error = err ? err : __CFPropertyListCreateError(kCFPropertyListWriteStreamError, CFSTR("Binary property list writing could not be completed because the stream had an unknown error.")); return; } @@ -194,47 +203,53 @@ static void writeBytes(__CFBinaryPlistWriteBuffer *buf, const UInt8 *bytes, CFIn } } +static void bufferFlush(__CFBinaryPlistWriteBuffer *buf) { + writeBytes(buf, buf->buffer, buf->used); + buf->used = 0; +} + static void bufferWrite(__CFBinaryPlistWriteBuffer *buf, const uint8_t *buffer, CFIndex count) { if (0 == count) return; if ((CFIndex)sizeof(buf->buffer) <= count) { - writeBytes(buf, buf->buffer, buf->used); - buf->used = 0; + bufferFlush(buf); writeBytes(buf, buffer, count); return; } CFIndex copyLen = __CFMin(count, (CFIndex)sizeof(buf->buffer) - buf->used); - memmove(buf->buffer + buf->used, buffer, copyLen); + if (buf->stream || buf->databytes) { + switch (copyLen) { + case 4: buf->buffer[buf->used + 3] = buffer[3]; /* FALLTHROUGH */ + case 3: buf->buffer[buf->used + 2] = buffer[2]; /* FALLTHROUGH */ + case 2: buf->buffer[buf->used + 1] = buffer[1]; /* FALLTHROUGH */ + case 1: buf->buffer[buf->used] = buffer[0]; break; + default: memmove(buf->buffer + buf->used, buffer, copyLen); + } + } buf->used += copyLen; if (sizeof(buf->buffer) == buf->used) { writeBytes(buf, buf->buffer, sizeof(buf->buffer)); - memmove(buf->buffer, buffer + copyLen, count - copyLen); + if (buf->stream || buf->databytes) { + memmove(buf->buffer, buffer + copyLen, count - copyLen); + } buf->used = count - copyLen; } } -static void bufferFlush(__CFBinaryPlistWriteBuffer *buf) { - writeBytes(buf, buf->buffer, buf->used); - buf->used = 0; -} - /* HEADER magic number ("bplist") - file format version - byte length of plist incl. header, an encoded int number object (as below) [v.2+ only] - 32-bit CRC (ISO/IEC 8802-3:1989) of plist bytes w/o CRC, encoded always as - "0x12 0x__ 0x__ 0x__ 0x__", big-endian, may be 0 to indicate no CRC [v.2+ only] + file format version (currently "0?") OBJECT TABLE variable-sized objects Object Formats (marker byte followed by additional info in some cases) - null 0000 0000 // null object [v1+ only] + null 0000 0000 // null object [v"1?"+ only] bool 0000 1000 // false bool 0000 1001 // true - url 0000 1100 string // URL with no base URL, recursive encoding of URL string [v1+ only] - url 0000 1101 base string // URL with base URL, recursive encoding of base URL, then recursive encoding of URL string [v1+ only] - uuid 0000 1110 // 16-byte UUID [v1+ only] + url 0000 1100 string // URL with no base URL, recursive encoding of URL string [v"1?"+ only] + url 0000 1101 base string // URL with base URL, recursive encoding of base URL, then recursive encoding of URL string [v"1?"+ only] + uuid 0000 1110 // 16-byte UUID [v"1?"+ only] fill 0000 1111 // fill byte int 0001 0nnn ... // # of bytes is 2^nnn, big-endian bytes real 0010 0nnn ... // # of bytes is 2^nnn, big-endian bytes @@ -242,12 +257,12 @@ OBJECT TABLE data 0100 nnnn [int] ... // nnnn is number of bytes unless 1111 then int count follows, followed by bytes string 0101 nnnn [int] ... // ASCII string, nnnn is # of chars, else 1111 then int count, then bytes string 0110 nnnn [int] ... // Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte uint16_t - 0111 xxxx // unused + string 0111 nnnn [int] ... // UTF8 string, nnnn is # of chars, else 1111 then int count, then bytes [v"1?"+ only] uid 1000 nnnn ... // nnnn+1 is # of bytes 1001 xxxx // unused array 1010 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows - ordset 1011 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows [v1+ only] - set 1100 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows [v1+ only] + ordset 1011 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows [v"1?"+ only] + set 1100 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows [v"1?"+ only] dict 1101 nnnn [int] keyref* objref* // nnnn is count, unless '1111', then int count follows 1110 xxxx // unused 1111 xxxx // unused @@ -264,11 +279,6 @@ TRAILER element # in offset table which is top level object offset table offset -Version 1.5 binary plists do not use object references (uid), -but instead inline the object serialization itself at that point. -It also doesn't use an offset table or a trailer. It does have -an extended header, and the top-level object follows the header. - */ @@ -363,7 +373,7 @@ static void _appendString(__CFBinaryPlistWriteBuffer *buf, CFStringRef str) { CFIndex ret, count = CFStringGetLength(str); CFIndex needed, idx2; uint8_t *bytes, buffer[1024]; - bytes = (count <= 1024) ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, count, 0); + bytes = (count <= 1024) ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count, 0); // presumption, believed to be true, is that ASCII encoding may need // less bytes, but will not need greater, than the # of unichars ret = CFStringGetBytes(str, CFRangeMake(0, count), kCFStringEncodingASCII, 0, false, bytes, count, &needed); @@ -381,15 +391,15 @@ static void _appendString(__CFBinaryPlistWriteBuffer *buf, CFStringRef str) { if (15 <= count) { _appendInt(buf, (uint64_t)count); } - chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, count * sizeof(UniChar), 0); + chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(UniChar), 0); CFStringGetCharacters(str, CFRangeMake(0, count), chars); for (idx2 = 0; idx2 < count; idx2++) { chars[idx2] = CFSwapInt16HostToBig(chars[idx2]); } bufferWrite(buf, (uint8_t *)chars, count * sizeof(UniChar)); - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, chars); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, chars); } - if (bytes != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, bytes); + if (bytes != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, bytes); } CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number); @@ -442,7 +452,6 @@ static void _appendNumber(__CFBinaryPlistWriteBuffer *buf, CFNumberRef num) { } } -// 0 == objRefSize means version 1.5, else version 0.0 or 0.1 static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFDictionaryRef objtable, uint32_t objRefSize) { uint64_t refnum; CFIndex idx2; @@ -454,9 +463,6 @@ static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFD } else if (booltype == type) { uint8_t marker = CFBooleanGetValue((CFBooleanRef)obj) ? kCFBinaryPlistMarkerTrue : kCFBinaryPlistMarkerFalse; bufferWrite(buf, &marker, 1); - } else if (0 == objRefSize && nulltype == type) { - uint8_t marker = 0x00; - bufferWrite(buf, &marker, 1); } else if (datatype == type) { CFIndex count = CFDataGetLength((CFDataRef)obj); uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerData | (count < 15 ? count : 0xf)); @@ -479,7 +485,7 @@ static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFD _appendInt(buf, (uint64_t)count); } CFPropertyListRef *list, buffer[512]; - list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); + list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); CFDictionaryGetKeysAndValues((CFDictionaryRef)obj, list, list + count); for (idx2 = 0; idx2 < 2 * count; idx2++) { CFPropertyListRef value = list[idx2]; @@ -492,12 +498,12 @@ static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFD } else { Boolean ret = _appendObject(buf, value, objtable, objRefSize); if (!ret) { - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); return false; } } } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); } else if (arraytype == type) { CFIndex count = CFArrayGetCount((CFArrayRef)obj); CFPropertyListRef *list, buffer[256]; @@ -506,7 +512,7 @@ static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFD if (15 <= count) { _appendInt(buf, (uint64_t)count); } - list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); + list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); CFArrayGetValues((CFArrayRef)obj, CFRangeMake(0, count), list); for (idx2 = 0; idx2 < count; idx2++) { CFPropertyListRef value = list[idx2]; @@ -519,61 +525,13 @@ static Boolean _appendObject(__CFBinaryPlistWriteBuffer *buf, CFTypeRef obj, CFD } else { Boolean ret = _appendObject(buf, value, objtable, objRefSize); if (!ret) { - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); return false; } } } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); - } else if (0 == objRefSize && settype == type) { - CFIndex count = CFSetGetCount((CFSetRef)obj); - CFPropertyListRef *list, buffer[256]; - uint8_t marker = (uint8_t)(0xc0 | (count < 15 ? count : 0xf)); - bufferWrite(buf, &marker, 1); - if (15 <= count) { - _appendInt(buf, (uint64_t)count); - } - list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); - CFSetGetValues((CFSetRef)obj, list); - for (idx2 = 0; idx2 < count; idx2++) { - CFPropertyListRef value = list[idx2]; - if (objtable) { - uint32_t swapped = 0; - uint8_t *source = (uint8_t *)&swapped; - refnum = (uint32_t)(uintptr_t)CFDictionaryGetValue(objtable, value); - swapped = CFSwapInt32HostToBig((uint32_t)refnum); - bufferWrite(buf, source + sizeof(swapped) - objRefSize, objRefSize); - } else { - Boolean ret = _appendObject(buf, value, objtable, objRefSize); - if (!ret) { - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); - return false; - } - } - } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); - } else if (0 == objRefSize && osettype == type) { - // Not actually implemented - } else if (0 == objRefSize && uuidtype == type) { - uint8_t marker = (uint8_t)(0x0e); - bufferWrite(buf, &marker, 1); - { - CFUUIDBytes uu = CFUUIDGetUUIDBytes((CFUUIDRef)obj); - bufferWrite(buf, (const uint8_t *)&uu, 16); - } - } else if (0 == objRefSize && urltype == type) { - CFStringRef string = CFURLGetString((CFURLRef)obj); - if (!string) { - return false; - } - CFURLRef base = CFURLGetBaseURL((CFURLRef)obj); - uint8_t marker = (uint8_t)(0x00 | (base ? 0xd : 0xc)); - bufferWrite(buf, &marker, 1); - if (base) { - _appendObject(buf, base, objtable, objRefSize); - } - _appendObject(buf, string, objtable, objRefSize); - } else if (0 != objRefSize && _CFKeyedArchiverUIDGetTypeID() == type) { + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); + } else if (_CFKeyedArchiverUIDGetTypeID() == type) { _appendUID(buf, (CFKeyedArchiverUIDRef)obj); } else { return false; @@ -609,20 +567,20 @@ static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CF CFDictionaryAddValue(objtable, plist, (const void *)(uintptr_t)refnum); if (dicttype == type) { CFIndex count = CFDictionaryGetCount((CFDictionaryRef)plist); - list = (count <= 128) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); + 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++) { _flattenPlist(list[idx], objlist, objtable, uniquingset); } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); } else if (arraytype == type) { CFIndex count = CFArrayGetCount((CFArrayRef)plist); - list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); + list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); CFArrayGetValues((CFArrayRef)plist, CFRangeMake(0, count), list); for (idx = 0; idx < count; idx++) { _flattenPlist(list[idx], objlist, objtable, uniquingset); } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); } } @@ -681,10 +639,12 @@ CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t CFRelease(uniquingset); cnt = CFArrayGetCount(objlist); - offsets = (uint64_t *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, (CFIndex)(cnt * sizeof(*offsets)), 0); + offsets = (uint64_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, (CFIndex)(cnt * sizeof(*offsets)), 0); - buf = (__CFBinaryPlistWriteBuffer *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, sizeof(__CFBinaryPlistWriteBuffer), 0); + buf = (__CFBinaryPlistWriteBuffer *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__CFBinaryPlistWriteBuffer), 0); buf->stream = stream; + buf->databytes = NULL; + buf->datalen = 0; buf->error = NULL; buf->streamIsData = (CFGetTypeID(stream) == CFDataGetTypeID()); buf->written = 0; @@ -709,8 +669,8 @@ CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t // caller is not interested in error, release it here CFRelease(buf->error); } - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, buf); - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, offsets); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, offsets); return 0; } } @@ -727,7 +687,7 @@ CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t bufferWrite(buf, source + sizeof(*offsets) - trailer._offsetIntSize, trailer._offsetIntSize); } length_so_far += cnt * trailer._offsetIntSize; - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, offsets); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, offsets); bufferWrite(buf, (uint8_t *)&trailer, sizeof(trailer)); bufferFlush(buf); @@ -739,10 +699,10 @@ CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t } else { CFRelease(buf->error); } - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, buf); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf); return 0; } - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, buf); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf); return (CFIndex)length_so_far; } @@ -761,43 +721,6 @@ CFIndex __CFBinaryPlistWriteToStreamWithOptions(CFPropertyListRef plist, CFTypeR return __CFBinaryPlistWrite(plist, stream, estimate, options, NULL); } -// Write a version 1.5 plist to the data; extra objects + inlined objects (no references, no uniquing) -__private_extern__ Boolean __CFBinaryPlistWrite15(CFPropertyListRef plist, CFMutableDataRef data, CFErrorRef *error) { - initStatics(); - - __CFBinaryPlistWriteBuffer *buf = (__CFBinaryPlistWriteBuffer *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__CFBinaryPlistWriteBuffer), 0); - memset(buf, 0, sizeof(__CFBinaryPlistWriteBuffer)); - buf->stream = data; - buf->error = NULL; - buf->streamIsData = 1; - buf->written = 0; - buf->used = 0; - - bufferWrite(buf, (uint8_t *)"bplist15", 8); // header - bufferWrite(buf, (uint8_t *)"\023\000\000\000\000\000\000\000\000", 9); // header (byte length) - bufferWrite(buf, (uint8_t *)"\022\000\000\000\000", 5); // header (crc) - - Boolean success = _appendObject(buf, plist, NULL, 0); - if (!success) { - if (error && buf->error) { - // caller will release error - *error = buf->error; - } else if (buf->error) { - // caller is not interested in error, release it here - CFRelease(buf->error); - } - CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf); - return false; - } - bufferFlush(buf); - - uint64_t swapped_len = CFSwapInt64HostToBig(buf->written); - CFDataReplaceBytes(data, CFRangeMake(9, 8), (uint8_t *)&swapped_len, (CFIndex)sizeof(swapped_len)); - - CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf); - return true; -} - #pragma mark - #pragma mark Reading @@ -805,7 +728,7 @@ __private_extern__ Boolean __CFBinaryPlistWrite15(CFPropertyListRef plist, CFMut #define FAIL_FALSE do { return false; } while (0) #define FAIL_MAXOFFSET do { return UINT64_MAX; } while (0) -__private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist); +CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist); /* Grab a valSize-bytes integer out of the buffer pointed at by data and return it. */ @@ -843,7 +766,7 @@ bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen, // Leopard will parse "bplist00" or "bplist01" // SnowLeopard will parse "bplist0?" where ? is any one character if (0 != memcmp("bplist0", databytes, 7)) { - return false; + FAIL_FALSE; } memmove(&trail, databytes + datalen - sizeof(trail), sizeof(trail)); // In Leopard, the unused bytes in the trailer must be 0 or the parse will fail @@ -899,13 +822,11 @@ bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen, if (trail._offsetIntSize < 8 && (1ULL << (8 * trail._offsetIntSize)) <= trail._offsetTableOffset) FAIL_FALSE; - const uint8_t *objectsFirstByte; - objectsFirstByte = check_ptr_add(databytes, 8, &err); + (void)check_ptr_add(databytes, 8, &err); if (CF_NO_ERROR != err) FAIL_FALSE; const uint8_t *offsetsFirstByte = check_ptr_add(databytes, trail._offsetTableOffset, &err); if (CF_NO_ERROR != err) FAIL_FALSE; - const uint8_t *offsetsLastByte; - offsetsLastByte = check_ptr_add(offsetsFirstByte, offsetTableSize - 1, &err); + (void)check_ptr_add(offsetsFirstByte, offsetTableSize - 1, &err); if (CF_NO_ERROR != err) FAIL_FALSE; const uint8_t *bytesptr = databytes + trail._offsetTableOffset; @@ -1113,7 +1034,7 @@ bool __CFBinaryPlistGetOffsetForValueFromDictionary3(const uint8_t *databytes, u keyInData = NULL; if (!__CFBinaryPlistCreateObjectFiltered(databytes, datalen, off, trailer, kCFAllocatorSystemDefault, kCFPropertyListImmutable, NULL /*objects*/, NULL, 0, NULL, &keyInData) || !_plistIsPrimitive(keyInData)) { if (keyInData) CFRelease(keyInData); - return false; + FAIL_FALSE; } match = CFEqual(key, keyInData); @@ -1129,27 +1050,27 @@ bool __CFBinaryPlistGetOffsetForValueFromDictionary3(const uint8_t *databytes, u ptr += trailer->_objectRefSize; } - return false; + FAIL_FALSE; } extern CFDictionaryRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const void * *klist, const void * *vlist, CFIndex numValues); extern CFSetRef __CFSetCreateTransfer(CFAllocatorRef allocator, const void * *klist, CFIndex numValues); extern CFArrayRef __CFArrayCreateTransfer(CFAllocatorRef allocator, const void * *klist, CFIndex numValues); -__private_extern__ void __CFPropertyListCreateSplitKeypaths(CFAllocatorRef allocator, CFSetRef currentKeys, CFSetRef *theseKeys, CFSetRef *nextKeys); +CF_PRIVATE void __CFPropertyListCreateSplitKeypaths(CFAllocatorRef allocator, CFSetRef currentKeys, CFSetRef *theseKeys, CFSetRef *nextKeys); -__private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist) { +CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist) { if (objects) { *plist = CFDictionaryGetValue(objects, (const void *)(uintptr_t)startOffset); if (*plist) { // have to assume that '*plist' was previously created with same allocator that is now being passed in - if (!_CFAllocatorIsGCRefZero(allocator)) CFRetain(*plist); + CFRetain(*plist); return true; } } // at any one invocation of this function, set should contain the offsets in the "path" down to this object - if (set && CFSetContainsValue(set, (const void *)(uintptr_t)startOffset)) return false; + if (set && CFSetContainsValue(set, (const void *)(uintptr_t)startOffset)) FAIL_FALSE; // databytes is trusted to be at least datalen bytes long // *trailer contents are trusted, even for overflows -- was checked when the trailer was parsed @@ -1167,10 +1088,10 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab *plist = kCFNull; return true; case kCFBinaryPlistMarkerFalse: - *plist = !_CFAllocatorIsGCRefZero(allocator) ? CFRetain(kCFBooleanFalse) : kCFBooleanFalse; + *plist = !(0) ? CFRetain(kCFBooleanFalse) : kCFBooleanFalse; return true; case kCFBinaryPlistMarkerTrue: - *plist = !_CFAllocatorIsGCRefZero(allocator) ? CFRetain(kCFBooleanTrue) : kCFBooleanTrue; + *plist = !(0) ? CFRetain(kCFBooleanTrue) : kCFBooleanTrue; return true; } FAIL_FALSE; @@ -1190,7 +1111,6 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab // negative 1, 2, 4-byte integers are always emitted as 8 bytes in format '00' // integers are not required to be in the most compact possible representation, but only the last 64 bits are significant currently uint64_t bigint = _getSizedInt(ptr, cnt); - ptr += cnt; if (8 < cnt) { CFSInt128Struct val; val.high = 0; @@ -1311,7 +1231,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) { CFStringRef str = CFStringCreateWithBytes(allocator, ptr, cnt, kCFStringEncodingASCII, false); *plist = str ? CFStringCreateMutableCopy(allocator, 0, str) : NULL; - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(str); + if (str) CFRelease(str); } else { *plist = CFStringCreateWithBytes(allocator, ptr, cnt, kCFStringEncodingASCII, false); } @@ -1338,7 +1258,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (databytes + objectsRangeEnd < extent) FAIL_FALSE; size_t byte_cnt = check_size_t_mul(cnt, sizeof(UniChar), &err); if (CF_NO_ERROR != err) FAIL_FALSE; - UniChar *chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, 0); + UniChar *chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, 0); if (!chars) FAIL_FALSE; memmove(chars, ptr, byte_cnt); for (CFIndex idx = 0; idx < cnt; idx++) { @@ -1347,11 +1267,11 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) { CFStringRef str = CFStringCreateWithCharacters(allocator, chars, cnt); *plist = str ? CFStringCreateMutableCopy(allocator, 0, str) : NULL; - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(str); + if (str) CFRelease(str); } else { *plist = CFStringCreateWithCharacters(allocator, chars, cnt); } - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, chars); + CFAllocatorDeallocate(kCFAllocatorSystemDefault, chars); if (objects && *plist && (mutabilityOption != kCFPropertyListMutableContainersAndLeaves)) { CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist); } @@ -1368,7 +1288,6 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (databytes + objectsRangeEnd < extent) FAIL_FALSE; // uids are not required to be in the most compact possible representation, but only the last 64 bits are significant currently uint64_t bigint = _getSizedInt(ptr, cnt); - ptr += cnt; if (UINT32_MAX < bigint) FAIL_FALSE; *plist = _CFKeyedArchiverUIDCreate(allocator, (uint32_t)bigint); // these are always immutable @@ -1397,7 +1316,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (databytes + objectsRangeEnd < extent) FAIL_FALSE; byte_cnt = check_size_t_mul(arrayCount, sizeof(CFPropertyListRef), &err); if (CF_NO_ERROR != err) FAIL_FALSE; - list = (arrayCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, __kCFAllocatorGCScannedMemory); + list = (arrayCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory); if (!list) FAIL_FALSE; Boolean madeSet = false; if (!set && 15 < curDepth) { @@ -1446,12 +1365,12 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (!(mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves)) { // make immutable *plist = CFArrayCreateCopy(allocator, array); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(array); + CFRelease(array); } else { *plist = array; } } else if (array) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(array); + CFRelease(array); } } else { for (CFIndex idx = 0; idx < arrayCount; idx++) { @@ -1459,9 +1378,9 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab off = _getOffsetOfRefAt(databytes, ptr, trailer); if (!__CFBinaryPlistCreateObjectFiltered(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, NULL, &pl)) { while (idx--) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); FAIL_FALSE; } __CFAssignWithWriteBarrier((void **)list + idx, (void *)pl); @@ -1472,7 +1391,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab *plist = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); CFArrayReplaceValues((CFMutableArrayRef)*plist, CFRangeMake(0, 0), list, arrayCount); for (CFIndex idx = 0; idx < arrayCount; idx++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } } else { if (!kCFUseCollectableAllocator) { @@ -1480,7 +1399,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab } else { *plist = CFArrayCreate(allocator, list, arrayCount, &kCFTypeArrayCallBacks); for (CFIndex idx = 0; idx < arrayCount; idx++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } } } @@ -1491,7 +1410,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab CFSetAddValue((CFMutableSetRef)*plist, list[idx]); } for (CFIndex idx = 0; idx < arrayCount; idx++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } } else { if (!kCFUseCollectableAllocator) { @@ -1499,7 +1418,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab } else { *plist = CFSetCreate(allocator, list, arrayCount, &kCFTypeSetCallBacks); for (CFIndex idx = 0; idx < arrayCount; idx++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } } } @@ -1513,7 +1432,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) { CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist); } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); return (*plist) ? true : false; } case kCFBinaryPlistMarkerDict: { @@ -1537,7 +1456,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (databytes + objectsRangeEnd < extent) FAIL_FALSE; byte_cnt = check_size_t_mul(dictionaryCount, sizeof(CFPropertyListRef), &err); if (CF_NO_ERROR != err) FAIL_FALSE; - list = (dictionaryCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, __kCFAllocatorGCScannedMemory); + list = (dictionaryCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory); if (!list) FAIL_FALSE; Boolean madeSet = false; if (!set && 15 < curDepth) { @@ -1581,23 +1500,23 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (!(mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves)) { // make immutable *plist = CFDictionaryCreateCopy(allocator, dict); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(dict); + CFRelease(dict); } else { *plist = dict; } } else if (dict) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(dict); + CFRelease(dict); } } else { for (CFIndex idx = 0; idx < dictionaryCount; idx++) { CFPropertyListRef pl = NULL; off = _getOffsetOfRefAt(databytes, ptr, trailer); if (!__CFBinaryPlistCreateObjectFiltered(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, NULL, &pl) || (idx < dictionaryCount / 2 && !_plistIsPrimitive(pl))) { - if (pl && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(pl); + if (pl && !(0)) CFRelease(pl); while (idx--) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); FAIL_FALSE; } __CFAssignWithWriteBarrier((void **)list + idx, (void *)pl); @@ -1609,7 +1528,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab CFDictionaryAddValue((CFMutableDictionaryRef)*plist, list[idx], list[idx + dictionaryCount / 2]); } for (CFIndex idx = 0; idx < dictionaryCount; idx++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } } else { if (!kCFUseCollectableAllocator) { @@ -1617,7 +1536,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab } else { *plist = CFDictionaryCreate(allocator, list, list + dictionaryCount / 2, dictionaryCount / 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); for (CFIndex idx = 0; idx < dictionaryCount; idx++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]); + CFRelease(list[idx]); } } } @@ -1630,7 +1549,7 @@ __private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *datab if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) { CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist); } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list); + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); return (*plist) ? true : false; } } @@ -1642,7 +1561,7 @@ bool __CFBinaryPlistCreateObject(const uint8_t *databytes, uint64_t datalen, uin return __CFBinaryPlistCreateObjectFiltered(databytes, datalen, startOffset, trailer, allocator, mutabilityOption, objects, NULL, 0, NULL, plist); } -__private_extern__ bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFPropertyListRef *plist, CFStringRef *errorString) { +CF_PRIVATE bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFPropertyListRef *plist, CFStringRef *errorString) { uint8_t marker; CFBinaryPlistTrailer trailer; uint64_t offset; @@ -1656,285 +1575,33 @@ __private_extern__ bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFData // be malformed and contain hash-equal keys for the same dictionary (for example) // and the later key will cause the previous one to be released when we set the second // in the dictionary. - CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, NULL, &kCFTypeDictionaryValueCallBacks); + CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); _CFDictionarySetCapacity(objects, trailer._numObjects); CFPropertyListRef pl = NULL; bool result = true; if (__CFBinaryPlistCreateObjectFiltered(databytes, datalen, offset, &trailer, allocator, option, objects, NULL, 0, NULL, &pl)) { if (plist) *plist = pl; +#if 0 +// code to check the 1.5 version code against any binary plist successfully parsed above +extern size_t __CFBinaryPlistWrite15(CFPropertyListRef plist, CFMutableDataRef data, CFErrorRef *error); +extern CFPropertyListRef __CFBinaryPlistCreate15(const uint8_t *databytes, uint64_t datalen, CFErrorRef *error); + +CFMutableDataRef mdata = CFDataCreateMutable(0, 0); +size_t s = __CFBinaryPlistWrite15(pl, mdata, NULL); +//double ratio = (double)s / (double)datalen; +//if (ratio < 0.75 || ratio > 4.0) CFLog(4, CFSTR("@@@ note: Binary plist of %ld bytes is %ld bytes (%f) in version 1.5"), datalen, s, ratio); +if (s != CFDataGetLength(mdata)) CFLog(3, CFSTR("### error: returned length not equal to data length (%ld != %ld)"), s, CFDataGetLength(mdata)); +CFPropertyListRef pl2 = __CFBinaryPlistCreate15((const uint8_t *)CFDataGetBytePtr(mdata), CFDataGetLength(mdata), NULL); +if (!CFEqual(pl, pl2)) CFLog(3, CFSTR("*** error: plists before and after are not equal\n--------\n%@\n--------\n%@\n--------"), pl, pl2); +#endif } else { if (plist) *plist = NULL; if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("binary data is corrupt")); result = false; } - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(objects); + CFRelease(objects); return result; } - return false; -} - - -static CFPropertyListRef __CFBinaryPlistCreateObject15(const uint8_t *databytes, uint64_t datalen, const uint8_t **ptr) { - const uint8_t *objectsRangeStart = databytes + 22, *objectsRangeEnd = databytes + datalen - 1; - if (*ptr < objectsRangeStart || objectsRangeEnd < *ptr) return NULL; - uint8_t marker = **ptr; - int32_t err = CF_NO_ERROR; - *ptr = check_ptr_add(*ptr, 1, &err); - if (CF_NO_ERROR != err) return NULL; - switch (marker & 0xf0) { - case 0x0: - switch (marker) { - case kCFBinaryPlistMarkerNull: - return kCFNull; - case kCFBinaryPlistMarkerFalse: - return kCFBooleanFalse; - case kCFBinaryPlistMarkerTrue: - return kCFBooleanTrue; - case 0x0c: { - CFStringRef string = (CFStringRef)__CFBinaryPlistCreateObject15(databytes, datalen, ptr); - if (!string) { - return NULL; - } - CFURLRef result = CFURLCreateWithString(kCFAllocatorSystemDefault, string, NULL); - CFRelease(string); - return result; - } - case 0x0d: { - CFURLRef base = (CFURLRef)__CFBinaryPlistCreateObject15(databytes, datalen, ptr); - if (!base) return NULL; - CFStringRef string = (CFStringRef)__CFBinaryPlistCreateObject15(databytes, datalen, ptr); - if (!string) { - CFRelease(base); - return NULL; - } - CFURLRef result = CFURLCreateWithString(kCFAllocatorSystemDefault, string, base); - CFRelease(base); - CFRelease(string); - return result; - } - case 0x0e: { - int32_t err = CF_NO_ERROR; - const uint8_t *extent = check_ptr_add(*ptr, 16, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - CFUUIDBytes uuid; - memmove(&uuid, *ptr, 16); - *ptr = extent + 1; - return CFUUIDCreateFromUUIDBytes(kCFAllocatorSystemDefault, uuid); - } - case 0x0f: - break; - } - return NULL; - case kCFBinaryPlistMarkerInt: { - int32_t err = CF_NO_ERROR; - uint64_t cnt = 1 << (marker & 0x0f); - const uint8_t *extent = check_ptr_add(*ptr, cnt, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - if (16 < cnt) return NULL; - // in format version '15', 1, 2, and 4-byte integers have to be interpreted as unsigned, - // whereas 8-byte integers are signed (and 16-byte when available) - // negative 1, 2, 4-byte integers are always emitted as 8 bytes in format '15' - // integers are not required to be in the most compact possible representation, but only the last 64 bits are significant currently - uint64_t bigint = _getSizedInt(*ptr, cnt); - *ptr = extent + 1; - CFPropertyListRef plist = NULL; - if (8 < cnt) { - CFSInt128Struct val; - val.high = 0; - val.low = bigint; - plist = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt128Type, &val); - } else { - plist = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt64Type, &bigint); - } - return plist; - } - case kCFBinaryPlistMarkerReal: - switch (marker & 0x0f) { - case 2: { - int32_t err = CF_NO_ERROR; - const uint8_t *extent = check_ptr_add(*ptr, 4, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - CFSwappedFloat32 swapped32; - memmove(&swapped32, *ptr, 4); - *ptr = extent + 1; - float f = CFConvertFloat32SwappedToHost(swapped32); - CFPropertyListRef plist = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberFloat32Type, &f); - return plist; - } - case 3: { - int32_t err = CF_NO_ERROR; - const uint8_t *extent = check_ptr_add(*ptr, 8, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - CFSwappedFloat64 swapped64; - memmove(&swapped64, *ptr, 8); - *ptr = extent + 1; - double d = CFConvertFloat64SwappedToHost(swapped64); - CFPropertyListRef plist = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberFloat64Type, &d); - return plist; - } - } - return NULL; - case kCFBinaryPlistMarkerDate & 0xf0: - switch (marker) { - case kCFBinaryPlistMarkerDate: { - int32_t err = CF_NO_ERROR; - const uint8_t *extent = check_ptr_add(*ptr, 8, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - CFSwappedFloat64 swapped64; - memmove(&swapped64, *ptr, 8); - *ptr = extent + 1; - double d = CFConvertFloat64SwappedToHost(swapped64); - CFPropertyListRef plist = CFDateCreate(kCFAllocatorSystemDefault, d); - return plist; - } - } - return NULL; - case kCFBinaryPlistMarkerData: { - int32_t err = CF_NO_ERROR; - CFIndex cnt = marker & 0x0f; - if (0xf == cnt) { - uint64_t bigint = 0; - if (!_readInt(*ptr, objectsRangeEnd, &bigint, ptr)) return NULL; - if (LONG_MAX < bigint) return NULL; - cnt = (CFIndex)bigint; - } - const uint8_t *extent = check_ptr_add(*ptr, cnt, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - CFPropertyListRef plist = CFDataCreate(kCFAllocatorSystemDefault, *ptr, cnt); - *ptr = extent + 1; - return plist; - } - case kCFBinaryPlistMarkerASCIIString: { - int32_t err = CF_NO_ERROR; - CFIndex cnt = marker & 0x0f; - if (0xf == cnt) { - uint64_t bigint = 0; - if (!_readInt(*ptr, objectsRangeEnd, &bigint, ptr)) return NULL; - if (LONG_MAX < bigint) return NULL; - cnt = (CFIndex)bigint; - } - const uint8_t *extent = check_ptr_add(*ptr, cnt, &err) - 1; - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - CFPropertyListRef plist = CFStringCreateWithBytes(kCFAllocatorSystemDefault, *ptr, cnt, kCFStringEncodingASCII, false); - *ptr = extent + 1; - return plist; - } - case kCFBinaryPlistMarkerUnicode16String: { - int32_t err = CF_NO_ERROR; - CFIndex cnt = marker & 0x0f; - if (0xf == cnt) { - uint64_t bigint = 0; - if (!_readInt(*ptr, objectsRangeEnd, &bigint, ptr)) return NULL; - if (LONG_MAX < bigint) return NULL; - cnt = (CFIndex)bigint; - } - const uint8_t *extent = check_ptr_add(*ptr, cnt, &err) - 1; - extent = check_ptr_add(extent, cnt, &err); // 2 bytes per character - if (CF_NO_ERROR != err) return NULL; - if (objectsRangeEnd < extent) return NULL; - size_t byte_cnt = check_size_t_mul(cnt, sizeof(UniChar), &err); - if (CF_NO_ERROR != err) return NULL; - UniChar *chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, 0); - if (!chars) return NULL; - memmove(chars, *ptr, byte_cnt); - for (CFIndex idx = 0; idx < cnt; idx++) { - chars[idx] = CFSwapInt16BigToHost(chars[idx]); - } - CFPropertyListRef plist = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, chars, cnt); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, chars); - *ptr = extent + 1; - return plist; - } - case kCFBinaryPlistMarkerArray: - case 0xb0: // ordset - case kCFBinaryPlistMarkerSet: - case kCFBinaryPlistMarkerDict: { - int32_t err = CF_NO_ERROR; - CFIndex cnt = marker & 0x0f; - if (0xf == cnt) { - uint64_t bigint = 0; - if (!_readInt(*ptr, objectsRangeEnd, &bigint, ptr)) return NULL; - if (LONG_MAX < bigint) return NULL; - cnt = (CFIndex)bigint; - } - if ((marker & 0xf0) == kCFBinaryPlistMarkerDict) { - cnt = check_size_t_mul(cnt, 2, &err); - if (CF_NO_ERROR != err) return NULL; - } - size_t byte_cnt = check_size_t_mul(cnt, sizeof(CFPropertyListRef), &err); // check now for a later overflow - if (CF_NO_ERROR != err) return NULL; - CFPropertyListRef *list, buffer[256]; - list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, 0); - if (!list) return NULL; - - CFMutableArrayRef tmparray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - for (CFIndex idx = 0; idx < cnt; idx++) { - CFPropertyListRef pl = __CFBinaryPlistCreateObject15(databytes, datalen, ptr); - if (!pl) { - CFRelease(tmparray); - return NULL; - } - if ((marker & 0xf0) == kCFBinaryPlistMarkerDict) { - if (idx < cnt / 2 && !_plistIsPrimitive(pl)) { - CFRelease(pl); - CFRelease(tmparray); - return NULL; - } - } - CFArrayAppendValue(tmparray, pl); -// CFRelease(pl); // don't release pl here, we're going to transfer the retain to the ultimate collection owner - } - CFArrayGetValues(tmparray, CFRangeMake(0, cnt), list); - CFPropertyListRef plist = NULL; - if ((marker & 0xf0) == kCFBinaryPlistMarkerArray) { - plist = __CFArrayCreateTransfer(kCFAllocatorSystemDefault, list, cnt); - } else if ((marker & 0xf0) == 0xb0) { - plist = NULL; // Not actually implemented - // leaks contents of tmparray, but this path shouldn't be exercised anyway - } else if ((marker & 0xf0) == kCFBinaryPlistMarkerSet) { - plist = __CFSetCreateTransfer(kCFAllocatorSystemDefault, list, cnt); - } else { - plist = __CFDictionaryCreateTransfer(kCFAllocatorSystemDefault, list, list + cnt / 2, cnt / 2); - } - CFRelease(tmparray); - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); - return plist; - } - default: - break; - } - return NULL; -} - -// *error is currently never set -__private_extern__ CFPropertyListRef __CFBinaryPlistCreate15(CFDataRef data, CFErrorRef *error) { - initStatics(); - const uint8_t *databytes = CFDataGetBytePtr(data); - uint64_t datalen = CFDataGetLength(data); - if (23 <= datalen) { // header is 22 bytes, plus 1 byte minimum for smallest object - const uint8_t *ptr = databytes; - if (0 != memcmp((uint8_t *)"bplist15", ptr, 8)) return NULL; - ptr += 8; - if (*ptr != (kCFBinaryPlistMarkerInt | 3)) return NULL; - ptr += 1; - uint64_t swapped_len; - memmove(&swapped_len, ptr, 8); - uint64_t bytelen = CFSwapInt64BigToHost(swapped_len); - if (bytelen != datalen) return NULL; - ptr += 8; - if (*ptr != (kCFBinaryPlistMarkerInt | 2)) return NULL; - ptr += 5; // skip crc - CFPropertyListRef pl = __CFBinaryPlistCreateObject15(databytes, datalen, &ptr); - // ptr should equal (databytes+datalen) if there is no junk at the end of top-level object - return pl; - } - return NULL; + FAIL_FALSE; } diff --git a/CFBitVector.c b/CFBitVector.c index 6043b9f..983369e 100644 --- a/CFBitVector.c +++ b/CFBitVector.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBitVector.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -176,24 +176,24 @@ static CFStringRef __CFBitVectorCopyDescription(CFTypeRef cf) { cnt = __CFBitVectorCount(bv); buckets = bv->_buckets; result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - CFStringAppendFormat(result, NULL, CFSTR("{count = %u, capacity = %u, objects = (\n"), cf, CFGetAllocator(bv), cnt, __CFBitVectorCapacity(bv)); + CFStringAppendFormat(result, NULL, CFSTR("{count = %lu, capacity = %lu, objects = (\n"), cf, CFGetAllocator(bv), (unsigned long)cnt, __CFBitVectorCapacity(bv)); for (idx = 0; idx < (cnt / 64); idx++) { /* Print groups of 64 */ CFIndex idx2; - CFStringAppendFormat(result, NULL, CFSTR("\t%u : "), (idx * 64)); + CFStringAppendFormat(result, NULL, CFSTR("\t%lu : "), (unsigned long)(idx * 64)); for (idx2 = 0; idx2 < 64; idx2 += 4) { CFIndex bucketIdx = (idx << 6) + idx2; - CFStringAppendFormat(result, NULL, CFSTR("%d%d%d%d"), - __CFBitVectorBit(buckets, bucketIdx + 0), - __CFBitVectorBit(buckets, bucketIdx + 1), - __CFBitVectorBit(buckets, bucketIdx + 2), - __CFBitVectorBit(buckets, bucketIdx + 3)); + CFStringAppendFormat(result, NULL, CFSTR("%u%u%u%u"), + (unsigned int)__CFBitVectorBit(buckets, bucketIdx + 0), + (unsigned int)__CFBitVectorBit(buckets, bucketIdx + 1), + (unsigned int)__CFBitVectorBit(buckets, bucketIdx + 2), + (unsigned int)__CFBitVectorBit(buckets, bucketIdx + 3)); } CFStringAppend(result, CFSTR("\n")); } if (idx * 64 < cnt) { - CFStringAppendFormat(result, NULL, CFSTR("\t%u : "), (idx * 64)); + CFStringAppendFormat(result, NULL, CFSTR("\t%lu : "), (unsigned long)(idx * 64)); for (idx = (idx * 64); idx < cnt; idx++) { /* Print remainder */ - CFStringAppendFormat(result, NULL, CFSTR("%d"), __CFBitVectorBit(buckets, idx)); + CFStringAppendFormat(result, NULL, CFSTR("%u"), (unsigned int)__CFBitVectorBit(buckets, idx)); } } CFStringAppend(result, CFSTR("\n)}")); @@ -225,7 +225,7 @@ static const CFRuntimeClass __CFBitVectorClass = { __CFBitVectorCopyDescription }; -__private_extern__ void __CFBitVectorInitialize(void) { +CF_PRIVATE void __CFBitVectorInitialize(void) { __kCFBitVectorTypeID = _CFRuntimeRegisterClass(&__CFBitVectorClass); } diff --git a/CFBitVector.h b/CFBitVector.h index 4b44927..c8b8614 100644 --- a/CFBitVector.h +++ b/CFBitVector.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBitVector.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBITVECTOR__) diff --git a/CFBuiltinConverters.c b/CFBuiltinConverters.c index 279f063..cc2bdb0 100644 --- a/CFBuiltinConverters.c +++ b/CFBuiltinConverters.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBuiltinConverters.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -106,7 +106,7 @@ static bool __CFFromASCII(uint32_t flags, uint8_t byte, UniChar *character) { } -__private_extern__ const CFStringEncodingConverter __CFConverterASCII = { +CF_PRIVATE const CFStringEncodingConverter __CFConverterASCII = { __CFToASCII, __CFFromASCII, 1, 1, kCFStringEncodingConverterCheapEightBit, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -142,7 +142,7 @@ static CFIndex __CFToISOLatin1Precompose(uint32_t flags, const UniChar *characte } } -__private_extern__ const CFStringEncodingConverter __CFConverterISOLatin1 = { +CF_PRIVATE const CFStringEncodingConverter __CFConverterISOLatin1 = { __CFToISOLatin1, __CFFromISOLatin1, 1, 1, kCFStringEncodingConverterCheapEightBit, NULL, NULL, NULL, NULL, __CFToISOLatin1Precompose, CFStringEncodingIsValidCombiningCharacterForLatin1, }; @@ -439,7 +439,7 @@ static CFIndex __CFToMacRomanPrecompose(uint32_t flags, const UniChar *character } } -__private_extern__ const CFStringEncodingConverter __CFConverterMacRoman = { +CF_PRIVATE const CFStringEncodingConverter __CFConverterMacRoman = { __CFToMacRoman, __CFFromMacRoman, 1, 1, kCFStringEncodingConverterCheapEightBit, NULL, NULL, NULL, NULL, __CFToMacRomanPrecompose, CFStringEncodingIsValidCombiningCharacterForLatin1, }; @@ -537,7 +537,7 @@ static CFIndex __CFToWinLatin1Precompose(uint32_t flags, const UniChar *characte } } -__private_extern__ const CFStringEncodingConverter __CFConverterWinLatin1 = { +CF_PRIVATE const CFStringEncodingConverter __CFConverterWinLatin1 = { __CFToWinLatin1, __CFFromWinLatin1, 1, 1, kCFStringEncodingConverterCheapEightBit, NULL, NULL, NULL, NULL, __CFToWinLatin1Precompose, CFStringEncodingIsValidCombiningCharacterForLatin1, }; @@ -837,7 +837,7 @@ static CFIndex __CFToNextStepLatinPrecompose(uint32_t flags, const UniChar *char } } -__private_extern__ const CFStringEncodingConverter __CFConverterNextStepLatin = { +CF_PRIVATE const CFStringEncodingConverter __CFConverterNextStepLatin = { __CFToNextStepLatin, __CFFromNextStepLatin, 1, 1, kCFStringEncodingConverterCheapEightBit, NULL, NULL, NULL, NULL, __CFToNextStepLatinPrecompose, CFStringEncodingIsValidCombiningCharacterForLatin1, }; @@ -1191,7 +1191,7 @@ static CFIndex __CFFromUTF8Len(uint32_t flags, const uint8_t *source, CFIndex nu return theUsedCharLen; } -__private_extern__ const CFStringEncodingConverter __CFConverterUTF8 = { +CF_PRIVATE const CFStringEncodingConverter __CFConverterUTF8 = { __CFToUTF8, __CFFromUTF8, 3, 2, kCFStringEncodingConverterStandard, __CFToUTF8Len, __CFFromUTF8Len, NULL, NULL, NULL, NULL, }; diff --git a/CFBundle.c b/CFBundle.c index 254fd92..a5b64b5 100644 --- a/CFBundle.c +++ b/CFBundle.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBundle.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -84,6 +84,7 @@ #define stat(x,y) _NS_stat(x,y) #endif + #if DEPLOYMENT_TARGET_WINDOWS #define statinfo _stat @@ -97,11 +98,6 @@ static inline BOOL isspace(char c) { #define statinfo stat #endif -__private_extern__ void _processInfoDictionary(CFMutableDictionaryRef dict, CFStringRef platformSuffix, CFStringRef productSuffix); -CF_EXPORT CFStringRef _CFGetProductName(void); -CF_EXPORT CFStringRef _CFGetPlatformName(void); -CF_EXPORT CFStringRef _CFGetAlternatePlatformName(void); - static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean alreadyLocked); #define LOG_BUNDLE_LOAD 0 @@ -171,63 +167,13 @@ CONST_STRING_DECL(_kCFBundleResourcesFileMappedKey, "CSResourcesFileMapped") CONST_STRING_DECL(_kCFBundleCFMLoadAsBundleKey, "CFBundleCFMLoadAsBundle") // Keys used by NSBundle for loaded Info plists. -CONST_STRING_DECL(_kCFBundleInitialPathKey, "NSBundleInitialPath") -CONST_STRING_DECL(_kCFBundleResolvedPathKey, "NSBundleResolvedPath") CONST_STRING_DECL(_kCFBundlePrincipalClassKey, "NSPrincipalClass") static char __CFBundleMainID__[1026] = {0}; -__private_extern__ char *__CFBundleMainID = __CFBundleMainID__; +CF_PRIVATE char *__CFBundleMainID = __CFBundleMainID__; static CFTypeID __kCFBundleTypeID = _kCFRuntimeNotATypeID; -struct __CFBundle { - CFRuntimeBase _base; - - CFURLRef _url; - CFDateRef _modDate; - - __strong CFDictionaryRef _infoDict; // the ref stored in here must always be allocated with kCFAllocatorSystemDefaultGCRefZero - __strong CFDictionaryRef _localInfoDict; // the ref stored in here must always be allocated with kCFAllocatorSystemDefaultGCRefZero - CFArrayRef _searchLanguages; - - __CFPBinaryType _binaryType; - Boolean _isLoaded; - uint8_t _version; - Boolean _sharesStringsFiles; - char _padding[1]; - - /* CFM goop */ - void *_connectionCookie; - - /* DYLD goop */ - const void *_imageCookie; - const void *_moduleCookie; - - /* dlfcn goop */ - void *_handleCookie; - - /* CFM<->DYLD glue */ - CFMutableDictionaryRef _glueDict; - - /* Resource fork goop */ - _CFResourceData _resourceData; - - _CFPlugInData _plugInData; - - pthread_mutex_t _bundleLoadingLock; - - // ZFH - /* resouce fast lookup*/ - CFSpinLock_t _queryLock; - CFMutableDictionaryRef _queryTable; - CFStringRef _bundleBasePath; - -#if defined(BINARY_SUPPORT_DLL) - HMODULE _hModule; -#endif /* BINARY_SUPPORT_DLL */ - -}; - static pthread_mutex_t CFBundleGlobalDataLock = PTHREAD_MUTEX_INITIALIZER; static CFMutableDictionaryRef _bundlesByIdentifier = NULL; @@ -243,18 +189,16 @@ static Boolean _scheduledBundlesAreUnloading = false; static Boolean _initedMainBundle = false; static CFBundleRef _mainBundle = NULL; -static CFStringRef _defaultLocalization = NULL; // Forward declares functions. static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, Boolean alreadyLocked, Boolean doFinalProcessing); -static CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict); static CFURLRef _CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle); 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 _CFBundleGrokInfoDictFromMainExecutable(void); +static CFMutableDictionaryRef _CFBundleCreateInfoDictFromMainExecutable(void); static Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags); static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p); #if !defined(BINARY_SUPPORT_DLFCN) @@ -845,8 +789,8 @@ static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef } #if defined(BINARY_SUPPORT_DYLD) if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary) { - if (_mainBundle->_infoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(_mainBundle->_infoDict); - _mainBundle->_infoDict = (CFDictionaryRef)_CFBundleGrokInfoDictFromMainExecutable(); + if (_mainBundle->_infoDict && !(0)) CFRelease(_mainBundle->_infoDict); + _mainBundle->_infoDict = (CFDictionaryRef)_CFBundleCreateInfoDictFromMainExecutable(); } #endif /* BINARY_SUPPORT_DYLD */ } else { @@ -855,18 +799,20 @@ static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef // if dyld and not main executable for bundle, prefer info dictionary from executable CFStringRef executableName = _CFBundleCopyExecutableName(_mainBundle, NULL, NULL); if (!executableName || !executablePath || !CFStringHasSuffix(executablePath, executableName)) { - CFDictionaryRef infoDictFromExecutable = (CFDictionaryRef)_CFBundleGrokInfoDictFromMainExecutable(); + CFDictionaryRef infoDictFromExecutable = (CFDictionaryRef)_CFBundleCreateInfoDictFromMainExecutable(); if (infoDictFromExecutable && CFDictionaryGetCount(infoDictFromExecutable) > 0) { - if (_mainBundle->_infoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(_mainBundle->_infoDict); + if (_mainBundle->_infoDict) CFRelease(_mainBundle->_infoDict); _mainBundle->_infoDict = infoDictFromExecutable; + } else if (infoDictFromExecutable) { + CFRelease(infoDictFromExecutable); } } if (executableName) CFRelease(executableName); } #endif /* BINARY_SUPPORT_DYLD */ } - if (!_mainBundle->_infoDict) _mainBundle->_infoDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (!CFDictionaryGetValue(_mainBundle->_infoDict, _kCFBundleExecutablePathKey)) CFDictionarySetValue((CFMutableDictionaryRef)(_mainBundle->_infoDict), _kCFBundleExecutablePathKey, executablePath); + if (!_mainBundle->_infoDict) _mainBundle->_infoDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!_mainBundle->_executablePath && executablePath) _mainBundle->_executablePath = (CFStringRef)CFRetain(executablePath); CFStringRef bundleID = (CFStringRef)CFDictionaryGetValue(_mainBundle->_infoDict, kCFBundleIdentifierKey); if (bundleID) { if (!CFStringGetCString(bundleID, __CFBundleMainID__, sizeof(__CFBundleMainID__) - 2, kCFStringEncodingUTF8)) { @@ -879,12 +825,19 @@ static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean CFDictionaryRef oldInfoDict = bundle->_infoDict; CFTypeRef val; - _CFBundleFlushCachesForURL(bundle->_url); bundle->_infoDict = NULL; if (bundle->_localInfoDict) { - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(bundle->_localInfoDict); + CFRelease(bundle->_localInfoDict); bundle->_localInfoDict = NULL; } + if (bundle->_developmentRegion) { + CFRelease(bundle->_developmentRegion); + bundle->_developmentRegion = NULL; + } + if (bundle->_executablePath) { + CFRelease(bundle->_executablePath); + bundle->_executablePath = NULL; + } if (bundle->_searchLanguages) { CFRelease(bundle->_searchLanguages); bundle->_searchLanguages = NULL; @@ -894,7 +847,7 @@ static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean bundle->_resourceData._stringTableCache = NULL; } if (bundle == _mainBundle) { - CFStringRef executablePath = oldInfoDict ? (CFStringRef)CFDictionaryGetValue(oldInfoDict, _kCFBundleExecutablePathKey) : NULL; + CFStringRef executablePath = bundle->_executablePath; if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock); _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(executablePath); if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock); @@ -902,15 +855,16 @@ static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean CFBundleGetInfoDictionary(bundle); } if (oldInfoDict) { - if (!bundle->_infoDict) bundle->_infoDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - val = CFDictionaryGetValue(oldInfoDict, _kCFBundleInitialPathKey); - if (val) CFDictionarySetValue((CFMutableDictionaryRef)bundle->_infoDict, _kCFBundleInitialPathKey, val); - val = CFDictionaryGetValue(oldInfoDict, _kCFBundleResolvedPathKey); - if (val) CFDictionarySetValue((CFMutableDictionaryRef)bundle->_infoDict, _kCFBundleResolvedPathKey, val); + if (!bundle->_infoDict) bundle->_infoDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); val = CFDictionaryGetValue(oldInfoDict, _kCFBundlePrincipalClassKey); if (val) CFDictionarySetValue((CFMutableDictionaryRef)bundle->_infoDict, _kCFBundlePrincipalClassKey, val); - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(oldInfoDict); + CFRelease(oldInfoDict); } + __CFSpinLock(&bundle->_queryLock); + if (bundle->_queryTable) { + CFDictionaryRemoveAllValues(bundle->_queryTable); + } + __CFSpinUnlock(&bundle->_queryLock); } CF_EXPORT void _CFBundleFlushBundleCaches(CFBundleRef bundle) { @@ -1082,23 +1036,26 @@ static void __CFBundleDeallocate(CFTypeRef cf) { CFBundleUnloadExecutable(bundle); _CFBundleDeallocatePlugIn(bundle); if (bundleURL) { - _CFBundleFlushCachesForURL(bundleURL); CFRelease(bundleURL); } - if (bundle->_infoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(bundle->_infoDict); + if (bundle->_infoDict && !(0)) CFRelease(bundle->_infoDict); if (bundle->_modDate) CFRelease(bundle->_modDate); - if (bundle->_localInfoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(bundle->_localInfoDict); + if (bundle->_localInfoDict && !(0)) CFRelease(bundle->_localInfoDict); if (bundle->_searchLanguages) CFRelease(bundle->_searchLanguages); + if (bundle->_executablePath) CFRelease(bundle->_executablePath); + if (bundle->_developmentRegion) CFRelease(bundle->_developmentRegion); if (bundle->_glueDict) { CFDictionaryApplyFunction(bundle->_glueDict, _CFBundleDeallocateGlue, (void *)CFGetAllocator(bundle)); CFRelease(bundle->_glueDict); } if (bundle->_resourceData._stringTableCache) CFRelease(bundle->_resourceData._stringTableCache); - // ZFH if (bundle->_bundleBasePath) CFRelease(bundle->_bundleBasePath); if (bundle->_queryTable) CFRelease(bundle->_queryTable); + if (bundle->_localizations) CFRelease(bundle->_localizations); + if (bundle->_resourceDirectoryContents) CFRelease(bundle->_resourceDirectoryContents); + pthread_mutex_destroy(&(bundle->_bundleLoadingLock)); } @@ -1115,9 +1072,9 @@ static const CFRuntimeClass __CFBundleClass = { }; // From CFBundle_Resources.c -__private_extern__ void _CFBundleResourcesInitialize(); +CF_PRIVATE void _CFBundleResourcesInitialize(); -__private_extern__ void __CFBundleInitialize(void) { +CF_PRIVATE void __CFBundleInitialize(void) { __kCFBundleTypeID = _CFRuntimeRegisterClass(&__CFBundleClass); _CFBundleResourcesInitialize(); } @@ -1142,7 +1099,6 @@ CFBundleRef _CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL) { } static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, Boolean alreadyLocked, Boolean doFinalProcessing) { - allocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); CFBundleRef bundle = NULL; char buff[CFMaxPathSize]; CFDateRef modDate = NULL; // do not actually fetch the modDate, since that can cause something like 7609956, unless absolutely found to be necessary in the future @@ -1161,8 +1117,8 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, return bundle; } - if (!_CFBundleURLLooksLikeBundleVersion(newURL, &localVersion)) { - localVersion = 3; + localVersion = _CFBundleGetBundleVersionForURL(newURL); + if (localVersion == 3) { SInt32 res = _CFGetPathProperties(allocator, (char *)buff, &exists, &mode, NULL, NULL, NULL, NULL); #if DEPLOYMENT_TARGET_WINDOWS if (!(res == 0 && exists && ((mode & S_IFMT) == S_IFDIR))) { @@ -1202,7 +1158,9 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, bundle->_infoDict = NULL; bundle->_localInfoDict = NULL; bundle->_searchLanguages = NULL; - + bundle->_executablePath = NULL; + bundle->_developmentRegion = NULL; + bundle->_developmentRegionCalculated = false; #if defined(BINARY_SUPPORT_DYLD) /* We'll have to figure it out later */ bundle->_binaryType = __CFBundleUnknownBinary; @@ -1250,8 +1208,12 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, CFLog(4, CFSTR("%s: failed to initialize bundle loading lock for bundle %@."), __PRETTY_FUNCTION__, bundle); } - // ZFH - /* resource fast look up */ + bundle->_lock = CFSpinLockInit; + bundle->_resourceDirectoryContents = NULL; + + bundle->_localizations = NULL; + bundle->_lookedForLocalizations = false; + bundle->_queryLock = CFSpinLockInit; bundle->_queryTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFURLRef absoURL = CFURLCopyAbsoluteURL(bundle->_url); @@ -1278,9 +1240,8 @@ CFBundleRef CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL) { } CFArrayRef CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc, CFURLRef directoryURL, CFStringRef bundleType) { - alloc = _CFConvertAllocatorToNonGCRefZeroEquivalent(alloc); CFMutableArrayRef bundles = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks); - CFArrayRef URLs = _CFContentsOfDirectory(alloc, NULL, NULL, directoryURL, bundleType); + CFArrayRef URLs = _CFCreateContentsOfDirectory(alloc, NULL, NULL, directoryURL, bundleType); if (URLs) { CFIndex i, c = CFArrayGetCount(URLs); CFURLRef curURL; @@ -1302,141 +1263,6 @@ CFURLRef CFBundleCopyBundleURL(CFBundleRef bundle) { return bundle->_url; } -void _CFBundleSetDefaultLocalization(CFStringRef localizationName) { - CFStringRef newLocalization = localizationName ? (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, localizationName) : NULL; - if (_defaultLocalization) CFRelease(_defaultLocalization); - _defaultLocalization = newLocalization; -} - -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 - _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version, bundle->_infoDict, 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, bundle->_version, bundle->_infoDict, 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 - CFArrayRef localizations = CFBundleCopyBundleLocalizations(bundle); - if (localizations) { - if (CFArrayGetCount(localizations) > 0) _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version, bundle->_infoDict, langs, (CFStringRef)CFArrayGetValueAtIndex(localizations, 0)); - CFRelease(localizations); - } - } - - 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) { - // Or if there is no devLang, try some variation of English that is present - CFArrayRef localizations = CFBundleCopyBundleLocalizations(bundle); - if (localizations) { - CFStringRef en_US = CFSTR("en_US"), en = CFSTR("en"), English = CFSTR("English"); - CFRange range = CFRangeMake(0, CFArrayGetCount(localizations)); - if (CFArrayContainsValue(localizations, range, en)) { - if (!CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), en)) CFArrayAppendValue(langs, en); - } else if (CFArrayContainsValue(localizations, range, English)) { - if (!CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), English)) CFArrayAppendValue(langs, English); - } else if (CFArrayContainsValue(localizations, range, en_US)) { - if (!CFArrayContainsValue(langs, CFRangeMake(0, CFArrayGetCount(langs)), en_US)) CFArrayAppendValue(langs, en_US); - } - CFRelease(localizations); - } - } - 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; -} - -CFDictionaryRef CFBundleCopyInfoDictionaryInDirectory(CFURLRef url) { - CFDictionaryRef dict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero, url, NULL); - if (dict && _CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRetain(dict); // conditionally put on a retain for a Copy function - return dict; -} - -CFDictionaryRef CFBundleGetInfoDictionary(CFBundleRef bundle) { - if (!bundle->_infoDict) bundle->_infoDict = _CFBundleCopyInfoDictionaryInDirectoryWithVersion(kCFAllocatorSystemDefaultGCRefZero, bundle->_url, bundle->_version); - return bundle->_infoDict; -} - -CFDictionaryRef _CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { - return CFBundleGetLocalInfoDictionary(bundle); -} - -CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { - static pthread_mutex_t CFBundleLocalInfoLock = PTHREAD_MUTEX_INITIALIZER; - CFDictionaryRef localInfoDict = bundle->_localInfoDict; - if (!localInfoDict) { - CFURLRef url = CFBundleCopyResourceURL(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL); - if (url) { - CFDataRef data; - SInt32 errCode; - CFStringRef errStr = NULL; - - if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, url, &data, NULL, NULL, &errCode)) { - localInfoDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefaultGCRefZero, data, kCFPropertyListMutableContainers, &errStr); - if (errStr) CFRelease(errStr); - if (localInfoDict && CFDictionaryGetTypeID() != CFGetTypeID(localInfoDict)) { - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(localInfoDict); - localInfoDict = NULL; - } - CFRelease(data); - } - CFRelease(url); - } - if (localInfoDict) _processInfoDictionary((CFMutableDictionaryRef)localInfoDict, _CFGetPlatformName(), _CFGetProductName()); - pthread_mutex_lock(&CFBundleLocalInfoLock); - if (!bundle->_localInfoDict) { - bundle->_localInfoDict = localInfoDict; - } else { - if (localInfoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(localInfoDict); - localInfoDict = bundle->_localInfoDict; - } - pthread_mutex_unlock(&CFBundleLocalInfoLock); - } - return localInfoDict; -} - -CFPropertyListRef _CFBundleGetValueForInfoKey(CFBundleRef bundle, CFStringRef key) { - return (CFPropertyListRef)CFBundleGetValueForInfoDictionaryKey(bundle, key); -} - -CFTypeRef CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle, CFStringRef key) { - // Look in InfoPlist.strings first. Then look in Info.plist - CFTypeRef result = NULL; - if (bundle && key) { - CFDictionaryRef dict = CFBundleGetLocalInfoDictionary(bundle); - if (dict) result = CFDictionaryGetValue(dict, key); - if (!result) { - dict = CFBundleGetInfoDictionary(bundle); - if (dict) result = CFDictionaryGetValue(dict, key); - } - } - return result; -} - -CFStringRef CFBundleGetIdentifier(CFBundleRef bundle) { - CFStringRef bundleID = NULL; - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - if (infoDict) bundleID = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleIdentifierKey); - return bundleID; -} - #define DEVELOPMENT_STAGE 0x20 #define ALPHA_STAGE 0x40 #define BETA_STAGE 0x60 @@ -1446,7 +1272,7 @@ CFStringRef CFBundleGetIdentifier(CFBundleRef bundle) { CF_INLINE Boolean _isDigit(UniChar aChar) {return ((aChar >= (UniChar)'0' && aChar <= (UniChar)'9') ? true : false);} -__private_extern__ CFStringRef _CFCreateStringFromVersionNumber(CFAllocatorRef alloc, UInt32 vers) { +CF_PRIVATE CFStringRef _CFCreateStringFromVersionNumber(CFAllocatorRef alloc, UInt32 vers) { CFStringRef result = NULL; uint8_t major1, major2, minor1, minor2, stage, build; @@ -1465,15 +1291,15 @@ __private_extern__ CFStringRef _CFCreateStringFromVersionNumber(CFAllocatorRef a } } else { if (major1 > 0) { - result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d%d.%d.%d%C%d"), major1, major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build); + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d%d.%d.%d%c%d"), major1, major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build); } else { - result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d.%d.%d%C%d"), major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build); + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d.%d.%d%c%d"), major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build); } } return result; } -__private_extern__ UInt32 _CFVersionNumberFromString(CFStringRef versStr) { +CF_PRIVATE UInt32 _CFVersionNumberFromString(CFStringRef versStr) { // Parse version number from string. // String can begin with "." for major version number 0. String can end at any point, but elements within the string cannot be skipped. UInt32 major1 = 0, major2 = 0, minor1 = 0, minor2 = 0, stage = RELEASE_STAGE, build = 0; @@ -1632,40 +1458,32 @@ __private_extern__ UInt32 _CFVersionNumberFromString(CFStringRef versStr) { UInt32 CFBundleGetVersionNumber(CFBundleRef bundle) { CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - CFTypeRef unknownVersionValue = CFDictionaryGetValue(infoDict, _kCFBundleNumericVersionKey); - CFNumberRef versNum; + CFNumberRef versionValue = (CFNumberRef)CFDictionaryGetValue(infoDict, _kCFBundleNumericVersionKey); + if (!versionValue || CFGetTypeID(versionValue) != CFNumberGetTypeID()) return 0; + UInt32 vers = 0; - - if (!unknownVersionValue) unknownVersionValue = CFDictionaryGetValue(infoDict, kCFBundleVersionKey); - if (unknownVersionValue) { - if (CFGetTypeID(unknownVersionValue) == CFStringGetTypeID()) { - // Convert a string version number into a numeric one. - vers = _CFVersionNumberFromString((CFStringRef)unknownVersionValue); - - versNum = CFNumberCreate(CFGetAllocator(bundle), kCFNumberSInt32Type, &vers); - CFDictionarySetValue((CFMutableDictionaryRef)infoDict, _kCFBundleNumericVersionKey, versNum); - CFRelease(versNum); - } else if (CFGetTypeID(unknownVersionValue) == CFNumberGetTypeID()) { - CFNumberGetValue((CFNumberRef)unknownVersionValue, kCFNumberSInt32Type, &vers); - } else { - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleNumericVersionKey); - } - } + CFNumberGetValue(versionValue, kCFNumberSInt32Type, &vers); return vers; } CFStringRef CFBundleGetDevelopmentRegion(CFBundleRef bundle) { - CFStringRef devLang = NULL; - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - if (infoDict) { - devLang = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); - if (devLang && (CFGetTypeID(devLang) != CFStringGetTypeID() || CFStringGetLength(devLang) == 0)) { - devLang = NULL; - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, kCFBundleDevelopmentRegionKey); + CFStringRef devRegion = NULL; + devRegion = bundle->_developmentRegion; + + if (!devRegion && !bundle->_developmentRegionCalculated) { + CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); + if (infoDict) { + devRegion = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); + if (devRegion && (CFGetTypeID(devRegion) != CFStringGetTypeID() || CFStringGetLength(devRegion) == 0)) { + devRegion = NULL; + } } + + if (devRegion) bundle->_developmentRegion = (CFStringRef)CFRetain(devRegion); + bundle->_developmentRegionCalculated = true; } - return devLang; + return devRegion; } Boolean _CFBundleGetHasChanged(CFBundleRef bundle) { @@ -1720,7 +1538,7 @@ static Boolean _binaryLoadable(CFURLRef url) { return loadable; } -__private_extern__ CFURLRef _CFBundleCopySupportFilesDirectoryURLInDirectory(CFURLRef bundleURL, uint8_t version) { +CF_PRIVATE CFURLRef _CFBundleCopySupportFilesDirectoryURLInDirectory(CFURLRef bundleURL, uint8_t version) { CFURLRef result = NULL; if (bundleURL) { if (1 == version) { @@ -1738,7 +1556,7 @@ CF_EXPORT CFURLRef CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle) { return _CFBundleCopySupportFilesDirectoryURLInDirectory(bundle->_url, bundle->_version); } -__private_extern__ CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundleURL, uint8_t version) { +CF_PRIVATE CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundleURL, uint8_t version) { CFURLRef result = NULL; if (bundleURL) { if (0 == version) { @@ -1758,7 +1576,7 @@ CFURLRef CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) { return _CFBundleCopyResourcesDirectoryURLInDirectory(bundle->_url, bundle->_version); } -__private_extern__ CFURLRef _CFBundleCopyAppStoreReceiptURLInDirectory(CFURLRef bundleURL, uint8_t version) { +CF_PRIVATE CFURLRef _CFBundleCopyAppStoreReceiptURLInDirectory(CFURLRef bundleURL, uint8_t version) { CFURLRef result = NULL; if (bundleURL) { if (0 == version) { @@ -1852,7 +1670,7 @@ static CFURLRef _CFBundleCopyExecutableURLRaw(CFURLRef urlPath, CFStringRef exeN return executableURL; } -static CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict) { +CF_PRIVATE CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict) { CFStringRef executableName = NULL; if (!infoDict && bundle) infoDict = CFBundleGetInfoDictionary(bundle); @@ -1876,16 +1694,13 @@ static CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFStringRef bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); CFRelease(absoluteURL); if (bundlePath) { - UniChar buff[CFMaxPathSize]; CFIndex len = CFStringGetLength(bundlePath); - CFIndex startOfBundleName, endOfBundleName; - - if (len > CFMaxPathSize) len = CFMaxPathSize; - CFStringGetCharacters(bundlePath, CFRangeMake(0, len), buff); - startOfBundleName = _CFStartOfLastPathComponent(buff, len); - endOfBundleName = _CFLengthAfterDeletingPathExtension(buff, len); + CFIndex startOfBundleName = _CFStartOfLastPathComponent2(bundlePath); + CFIndex endOfBundleName = _CFLengthAfterDeletingPathExtension2(bundlePath); - if (startOfBundleName <= len && endOfBundleName <= len && startOfBundleName < endOfBundleName) executableName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfBundleName]), endOfBundleName - startOfBundleName); + if (startOfBundleName <= len && endOfBundleName <= len && startOfBundleName < endOfBundleName) { + executableName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, bundlePath, CFRangeMake(startOfBundleName, endOfBundleName - startOfBundleName)); + } CFRelease(bundlePath); } } @@ -1893,76 +1708,6 @@ static CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, return executableName; } -__private_extern__ CFURLRef _CFBundleCopyResourceForkURLWithoutLocal(CFBundleRef bundle) { - CFStringRef executableName = _CFBundleCopyExecutableName(bundle, NULL, NULL); - CFURLRef resourceForkURL = NULL; - if (executableName) { - UniChar *path = (UniChar *) CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * CFMaxPathSize, 0); - CFIndex pathLen = CFStringGetLength(bundle->_bundleBasePath); - CFStringGetCharacters(bundle->_bundleBasePath, CFRangeMake(0, CFStringGetLength(bundle->_bundleBasePath)), path); - _CFBundleSetResourceDir(path, &pathLen, CFMaxPathSize, bundle->_version); - _CFAppendTrailingPathSlash(path, &pathLen, CFMaxPathSize); - CFStringGetCharacters(executableName, CFRangeMake(0, CFStringGetLength(executableName)), path+pathLen); - pathLen += CFStringGetLength(executableName); - path[pathLen++] = '.'; - CFStringGetCharacters(CFSTR("rsrc"), CFRangeMake(0, 4), path+pathLen); - pathLen += 4; - CFStringRef pathStr = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, path, pathLen); - Boolean found = false; - found = _CFIsResourceAtPath(pathStr, NULL); - if (found) { - resourceForkURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, pathStr, PLATFORM_PATH_STYLE, false); - } - CFRelease(pathStr); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, path); - CFRelease(executableName); - } - - return resourceForkURL; -} - -__private_extern__ CFURLRef _CFBundleCopyResourceForkURLMayBeLocal(CFBundleRef bundle, Boolean mayBeLocal) { - CFStringRef executableName = _CFBundleCopyExecutableName(bundle, NULL, NULL); - CFURLRef resourceForkURL = NULL; - if (executableName) { - CFStringRef type = CFSTR("rsrc"); -#ifdef CFBUNDLE_NEWLOOKUP - if (mayBeLocal) { - resourceForkURL = (CFURLRef) _CFBundleCopyFindResourcesWithNoBlock(bundle, NULL, NULL, executableName, type, NULL, NULL, NO, NO); - } else { - CFArrayRef languages = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks); - resourceForkURL = (CFURLRef) _CFBundleCopyFindResourcesWithNoBlock(bundle, NULL, languages, executableName, type, NULL, NULL, NO, NO); - CFRelease(languages); - } -#else - CFArrayRef types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&type, 1, &kCFTypeArrayCallBacks); - CFArrayRef array = NULL; - if (mayBeLocal) { - CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle); - array = _CFFindBundleResourcesNoBlock(bundle, NULL, NULL, languages, executableName, types, 1, _CFBundleLayoutVersion(bundle)); - if (array) { - if (CFArrayGetCount(array) > 0) resourceForkURL = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0)); - CFRelease(array); - } - } else { - array = _CFFindBundleResourcesNoBlock(bundle, NULL, NULL, NULL, executableName, types, 1, _CFBundleLayoutVersion(bundle)); - if (array) { - if (CFArrayGetCount(array) > 0) resourceForkURL = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0)); - CFRelease(array); - } - } - CFRelease(types); -#endif - CFRelease(executableName); - } - - return resourceForkURL; -} - -CFURLRef _CFBundleCopyResourceForkURL(CFBundleRef bundle) { - return _CFBundleCopyResourceForkURLMayBeLocal(bundle, true); -} - static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURLRef url, CFStringRef executableName, Boolean ignoreCache, Boolean useOtherPlatform) { uint8_t version = 0; CFDictionaryRef infoDict = NULL; @@ -1970,38 +1715,33 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL CFURLRef executableURL = NULL; Boolean foundIt = false; Boolean lookupMainExe = (executableName ? false : true); - static CFSpinLock_t CFBundleExecutablePathLock = CFSpinLockInit; if (bundle) { infoDict = CFBundleGetInfoDictionary(bundle); version = bundle->_version; } else { - infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero, url, &version); + infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, &version); } - + // If we have a bundle instance and an info dict, see if we have already cached the path - if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && infoDict) { - __CFSpinLock(&CFBundleExecutablePathLock); - executablePath = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleExecutablePathKey); + if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && bundle->_executablePath) { + __CFSpinLock(&bundle->_lock); + executablePath = bundle->_executablePath; if (executablePath) CFRetain(executablePath); - __CFSpinUnlock(&CFBundleExecutablePathLock); + __CFSpinUnlock(&bundle->_lock); if (executablePath) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, executablePath, kCFURLPOSIXPathStyle, false); #elif DEPLOYMENT_TARGET_WINDOWS executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, executablePath, kCFURLWindowsPathStyle, false); -#endif +#endif if (executableURL) { foundIt = true; - } else { - __CFSpinLock(&CFBundleExecutablePathLock); - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleExecutablePathKey); - __CFSpinUnlock(&CFBundleExecutablePathLock); } CFRelease(executablePath); } } - + if (!foundIt) { if (lookupMainExe) executableName = _CFBundleCopyExecutableName(bundle, url, infoDict); if (executableName) { @@ -2014,7 +1754,7 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL if (doExecSearch && 0 != version) { CFURLRef exeDirURL = NULL; CFURLRef exeSubdirURL; - + if (1 == version) { exeDirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleExecutablesURLFromBase1, url); } else if (2 == version) { @@ -2057,10 +1797,10 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL CFRelease(exeDirURL); CFRelease(exeSubdirURL); } - + // If this was an old bundle, or we did not find the executable in the Executables subdirectory, look directly in the bundle wrapper. if (!executableURL) executableURL = _CFBundleCopyExecutableURLRaw(url, executableName); - + #if DEPLOYMENT_TARGET_WINDOWS // Windows only: If we still haven't found the exe, look in the Executables folder. // But only for the main bundle exe @@ -2070,8 +1810,8 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL CFRelease(exeDirURL); } #endif - - if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && infoDict && executableURL) { + + if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && executableURL) { // We found it. Cache the path. CFURLRef absURL = CFURLCopyAbsoluteURL(executableURL); #if DEPLOYMENT_TARGET_WINDOWS @@ -2080,19 +1820,20 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL executablePath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle); #endif CFRelease(absURL); - __CFSpinLock(&CFBundleExecutablePathLock); - CFDictionarySetValue((CFMutableDictionaryRef)infoDict, _kCFBundleExecutablePathKey, executablePath); - __CFSpinUnlock(&CFBundleExecutablePathLock); + __CFSpinLock(&bundle->_lock); + bundle->_executablePath = (CFStringRef)CFRetain(executablePath); + __CFSpinUnlock(&bundle->_lock); CFRelease(executablePath); } if (lookupMainExe && !useOtherPlatform && bundle && !executableURL) bundle->_binaryType = __CFBundleNoBinary; if (lookupMainExe) CFRelease(executableName); } } - if (!bundle && infoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(infoDict); + if (!bundle && infoDict && !(0)) CFRelease(infoDict); return executableURL; } + CFURLRef _CFBundleCopyExecutableURLInDirectory(CFURLRef url) { return _CFBundleCopyExecutableURLInDirectory2(NULL, url, NULL, true, false); } @@ -2218,23 +1959,22 @@ static const char * __CFBundleODExtensionsArray = "odc\0\0" "odf\0\0" "odg\0\0" 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;} -// returns zero-ref dictionary under GC -static CFMutableDictionaryRef _CFBundleGrokInfoDictFromData(const char *bytes, uint32_t length) { +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(kCFAllocatorSystemDefaultGCRefZero, infoData, kCFPropertyListMutableContainers, NULL); + result = (CFMutableDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, infoData, kCFPropertyListMutableContainers, NULL); if (result && CFDictionaryGetTypeID() != CFGetTypeID(result)) { CFRelease(result); result = NULL; } CFRelease(infoData); } - if (!result) result = CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!result) result = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } - if (result) _processInfoDictionary((CFMutableDictionaryRef)result, _CFGetPlatformName(), _CFGetProductName()); + if (result) _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); return result; } @@ -2266,12 +2006,11 @@ static char *_CFBundleGetSectData(const char *segname, const char *sectname, uns return retval; } -// returns zero-ref dictionary under GC -static CFMutableDictionaryRef _CFBundleGrokInfoDictFromMainExecutable() { +static CFMutableDictionaryRef _CFBundleCreateInfoDictFromMainExecutable() { char *bytes = NULL; unsigned long length = 0; if (getsegbyname(TEXT_SEGMENT)) bytes = _CFBundleGetSectData(TEXT_SEGMENT, PLIST_SECTION, &length); - return _CFBundleGrokInfoDictFromData(bytes, length); + return _CFBundleCreateInfoDictFromData(bytes, length); } static Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags) { @@ -2344,8 +2083,7 @@ static Boolean _CFBundleGrokX11FromFile(int fd, const void *bytes, CFIndex lengt return result; } -// returns zero-ref dictionary under GC -static CFDictionaryRef _CFBundleGrokInfoDictFromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour) { +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; @@ -2379,7 +2117,7 @@ static CFDictionaryRef _CFBundleGrokInfoDictFromFile(int fd, const void *bytes, 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)_CFBundleGrokInfoDictFromData(sectbytes, sectlength); + 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)); @@ -2403,7 +2141,7 @@ static CFDictionaryRef _CFBundleGrokInfoDictFromFile(int fd, const void *bytes, 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)_CFBundleGrokInfoDictFromData(sectbytes, sectlength); + if (loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleCreateInfoDictFromData(sectbytes, sectlength); foundit = true; } sp = (struct section *)((char *)sp + sizeof(struct section)); @@ -2496,7 +2234,6 @@ static void _CFBundleGrokObjcImageInfoFromFile(int fd, const void *bytes, CFInde if (objcFlags) *objcFlags = localFlags; } -// returns zero-ref dictionary in *infodict under GC 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]; @@ -2548,22 +2285,22 @@ static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex 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 = _CFBundleGrokInfoDictFromFile(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 = _CFBundleGrokInfoDictFromFile(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 = _CFBundleGrokInfoDictFromFile(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 = _CFBundleGrokInfoDictFromFile(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); } } @@ -2571,7 +2308,6 @@ static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex return machtype; } -// returns zero-ref dictionary in *infodict under GC 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; @@ -2587,28 +2323,28 @@ static UInt32 _CFBundleGrokMachType(int fd, const void *bytes, CFIndex length, B 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 = _CFBundleGrokInfoDictFromFile(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 = _CFBundleGrokInfoDictFromFile(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 = _CFBundleGrokInfoDictFromFile(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 = _CFBundleGrokInfoDictFromFile(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); @@ -2798,7 +2534,6 @@ static const char *_CFBundleGrokFileTypeForOLEFile(int fd, const void *bytes, CF return ext; } -// returns zero-ref dictionary in *infodict under GC 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; @@ -3053,14 +2788,13 @@ CFStringRef _CFBundleCopyFileTypeForFileData(CFDataRef data) { return extension; } -// returns zero-ref dictionary under GC -__private_extern__ CFDictionaryRef _CFBundleCopyInfoDictionaryInExecutable(CFURLRef url) { +CF_PRIVATE CFDictionaryRef _CFBundleCopyInfoDictionaryInExecutable(CFURLRef url) { CFDictionaryRef result = NULL; (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, NULL, &result, NULL, NULL, NULL); return result; } -__private_extern__ CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef url) { +CF_PRIVATE CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef url) { CFArrayRef result = NULL; (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, &result, NULL, NULL, NULL, NULL); return result; @@ -3076,7 +2810,7 @@ static Boolean _CFBundleGetObjCImageInfoForExecutable(CFURLRef url, uint32_t *ob #if defined(BINARY_SUPPORT_DYLD) -__private_extern__ __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableURL) { +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; @@ -3108,6 +2842,9 @@ void _CFBundleSetCFMConnectionID(CFBundleRef bundle, void *connectionID) { 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; @@ -3204,7 +2941,6 @@ static CFErrorRef _CFBundleCreateErrorDebug(CFAllocatorRef allocator, CFBundleRe } CFErrorRef _CFBundleCreateError(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code) { - allocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); return _CFBundleCreateErrorDebug(allocator, bundle, code, NULL); } @@ -3213,6 +2949,7 @@ Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceG CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); + pthread_mutex_lock(&(bundle->_bundleLoadingLock)); if (!executableURL) bundle->_binaryType = __CFBundleNoBinary; // make sure we know whether bundle is already loaded or not @@ -3493,7 +3230,7 @@ void CFBundleUnloadExecutable(CFBundleRef bundle) { #if AVOID_WEAK_COLLECTIONS -__private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleScheduleForUnloading(CFBundleRef bundle) { pthread_mutex_lock(&CFBundleGlobalDataLock); if (!_bundlesToUnload) { CFSetCallBacks nonRetainingCallbacks = kCFTypeSetCallBacks; @@ -3505,13 +3242,13 @@ __private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) { pthread_mutex_unlock(&CFBundleGlobalDataLock); } -__private_extern__ void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) { pthread_mutex_lock(&CFBundleGlobalDataLock); if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle); pthread_mutex_unlock(&CFBundleGlobalDataLock); } -__private_extern__ void _CFBundleUnloadScheduledBundles(void) { +CF_PRIVATE void _CFBundleUnloadScheduledBundles(void) { pthread_mutex_lock(&CFBundleGlobalDataLock); if (_bundlesToUnload) { CFIndex i, c = CFSetGetCount(_bundlesToUnload); @@ -3532,20 +3269,20 @@ __private_extern__ void _CFBundleUnloadScheduledBundles(void) { #else /* AVOID_WEAK_COLLECTIONS */ -__private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleScheduleForUnloading(CFBundleRef bundle) { pthread_mutex_lock(&CFBundleGlobalDataLock); if (!_bundlesToUnload) _bundlesToUnload = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0]; [_bundlesToUnload addObject:(id)bundle]; pthread_mutex_unlock(&CFBundleGlobalDataLock); } -__private_extern__ void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) { pthread_mutex_lock(&CFBundleGlobalDataLock); if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle]; pthread_mutex_unlock(&CFBundleGlobalDataLock); } -__private_extern__ void _CFBundleUnloadScheduledBundles(void) { +CF_PRIVATE void _CFBundleUnloadScheduledBundles(void) { pthread_mutex_lock(&CFBundleGlobalDataLock); if (_bundlesToUnload && [_bundlesToUnload count] > 0) { CFIndex i, c; @@ -3687,7 +3424,7 @@ void CFBundleGetDataPointersForNames(CFBundleRef bundle, CFArrayRef symbolNames, for (i = 0; i < c; i++) stbl[i] = CFBundleGetDataPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(symbolNames, i)); } -__private_extern__ _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle) { +CF_PRIVATE _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle) { return &(bundle->_resourceData); } @@ -3695,11 +3432,11 @@ CFPlugInRef CFBundleGetPlugIn(CFBundleRef bundle) { return (bundle->_plugInData._isPlugIn) ? (CFPlugInRef)bundle : NULL; } -__private_extern__ _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle) { +CF_PRIVATE _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle) { return &(bundle->_plugInData); } -__private_extern__ Boolean _CFBundleCouldBeBundle(CFURLRef url) { +CF_PRIVATE Boolean _CFBundleCouldBeBundle(CFURLRef url) { Boolean result = false; Boolean exists; SInt32 mode; @@ -3941,7 +3678,7 @@ CF_EXPORT CFArrayRef _CFBundleCopyAllBundles(void) { return bundles; } -uint8_t _CFBundleLayoutVersion(CFBundleRef bundle) { +CF_PRIVATE uint8_t _CFBundleLayoutVersion(CFBundleRef bundle) { return bundle->_version; } @@ -3979,7 +3716,7 @@ static void __addPlatformAndProductNamesToKeys(const void *value, void *context) } // from CFUtilities.c -__private_extern__ Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, Boolean uncached, void **outBytes, CFIndex *outLength, CFErrorRef *errorPtr); +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) { @@ -4014,7 +3751,7 @@ static CFPropertyListRef _CFBundleCreateFilteredInfoPlistWithURL(CFURLRef infoPl if (!success) { result = CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } else { - _processInfoDictionary((CFMutableDictionaryRef)result, _CFGetPlatformName(), _CFGetProductName()); + _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); } CFRelease(newKeyPaths); @@ -4103,7 +3840,7 @@ CF_EXPORT CFURLRef CFBundleCopySharedSupportURL(CFBundleRef bundle) { return result; } -__private_extern__ CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) { +CF_PRIVATE CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) { return CFBundleCopyBuiltInPlugInsURL(bundle); } @@ -4138,7 +3875,7 @@ CF_EXPORT CFURLRef CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) { #if defined(BINARY_SUPPORT_DYLD) -__private_extern__ CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint) { +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); @@ -4194,7 +3931,7 @@ static char *_cleanedPathForPath(const char *curName) { return thePath; } -__private_extern__ CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void) { +CF_PRIVATE CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void) { // This returns an array of the paths of all the dyld images in the process. These paths may not be absolute, they may point at things that are not bundles, they may be staticly linked bundles or dynamically loaded bundles, they may be NULL. uint32_t i, numImages = _dyld_image_count(); CFMutableArrayRef result = NULL; @@ -4306,7 +4043,7 @@ static const void *__CFBundleDYLDFindImage(char *buff) { return (numMatches == 1) ? header : NULL; } -__private_extern__ Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle) { +CF_PRIVATE Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle) { if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); char buff[CFMaxPathSize]; @@ -4333,7 +4070,7 @@ __private_extern__ Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle) { return bundle->_isLoaded; } -__private_extern__ Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { +CF_PRIVATE Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); NSLinkEditErrors c = NSLinkEditUndefinedError; int errorNumber = 0; @@ -4422,7 +4159,7 @@ __private_extern__ Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean f return bundle->_isLoaded; } -__private_extern__ Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErrorRef *error) { +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; @@ -4474,7 +4211,7 @@ __private_extern__ Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErro return bundle->_isLoaded; } -__private_extern__ void _CFBundleDYLDUnloadBundle(CFBundleRef bundle) { +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); @@ -4490,7 +4227,7 @@ __private_extern__ void _CFBundleDYLDUnloadBundle(CFBundleRef bundle) { } } -__private_extern__ void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { +CF_PRIVATE void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { return _CFBundleDYLDGetSymbolByNameWithSearch(bundle, symbolName, false); } @@ -4536,7 +4273,7 @@ static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFString #if defined(BINARY_SUPPORT_DLFCN) -__private_extern__ Boolean _CFBundleDlfcnCheckLoaded(CFBundleRef bundle) { +CF_PRIVATE Boolean _CFBundleDlfcnCheckLoaded(CFBundleRef bundle) { if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); char buff[CFMaxPathSize]; @@ -4618,7 +4355,7 @@ CF_EXPORT Boolean _CFBundleDlfcnPreflight(CFBundleRef bundle, CFErrorRef *error) return retval; } -__private_extern__ Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { +CF_PRIVATE Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); @@ -4673,7 +4410,7 @@ __private_extern__ Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean return bundle->_isLoaded; } -__private_extern__ Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErrorRef *error) { +CF_PRIVATE Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErrorRef *error) { CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); @@ -4728,7 +4465,7 @@ __private_extern__ Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErr return bundle->_isLoaded; } -__private_extern__ void _CFBundleDlfcnUnload(CFBundleRef bundle) { +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); @@ -4743,7 +4480,7 @@ __private_extern__ void _CFBundleDlfcnUnload(CFBundleRef bundle) { } } -__private_extern__ void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { +CF_PRIVATE void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, symbolName, false); } @@ -4781,7 +4518,7 @@ static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p) { #if defined(BINARY_SUPPORT_DLL) -__private_extern__ Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *error) { +CF_PRIVATE Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *error) { CFErrorRef localError = NULL; if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); @@ -4811,7 +4548,7 @@ __private_extern__ Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *erro return bundle->_isLoaded; } -__private_extern__ void _CFBundleDLLUnload(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleDLLUnload(CFBundleRef bundle) { if (bundle->_isLoaded) { FreeLibrary(bundle->_hModule); bundle->_hModule = NULL; @@ -4819,7 +4556,7 @@ __private_extern__ void _CFBundleDLLUnload(CFBundleRef bundle) { } } -__private_extern__ void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) { +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); @@ -4830,50 +4567,6 @@ __private_extern__ void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle, CFStrin /* Workarounds to be applied in the presence of certain bundles can go here. This is called on every bundle creation. */ - -// ZFH -__private_extern__ CFStringRef _CFBundleGetBundlePath(CFBundleRef bundle){ - return bundle->_bundleBasePath; -} - -// caller need to release the table -__private_extern__ CFDictionaryRef _CFBundleCopyQueryTable(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, UniChar *resDir, CFIndex resDirLen, UniChar *subDirBuffer, CFIndex subDirLen) -{ - CFDictionaryRef subTable = NULL; - CFIndex savedResDirLen = resDirLen; - Boolean appendSucc = true; - - if (subDirLen > 0) { - appendSucc = _CFAppendPathComponent(resDir, &resDirLen, CFMaxPathSize, subDirBuffer, subDirLen); - } - - if (appendSucc) { - CFStringRef argDirStr = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, resDir, resDirLen, CFMaxPathSize, kCFAllocatorNull); - // take the lock - if (bundle) { - __CFSpinLock(&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, resDir, savedResDirLen, subDirBuffer, subDirLen); - - CFDictionarySetValue(bundle->_queryTable, argDirStr, subTable); - } else { - CFRetain(subTable); - } - __CFSpinUnlock(&bundle->_queryLock); - } else { - subTable = _CFBundleCreateQueryTableAtPath(NULL, bundleURL, languages, resDir, savedResDirLen, subDirBuffer, subDirLen); - } - CFRelease(argDirStr); - } - - return subTable; -} - diff --git a/CFBundle.h b/CFBundle.h index 304ab6a..99d33e2 100644 --- a/CFBundle.h +++ b/CFBundle.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBundle.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLE__) diff --git a/CFBundlePriv.h b/CFBundlePriv.h index 97b5402..b989e7a 100644 --- a/CFBundlePriv.h +++ b/CFBundlePriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBundlePriv.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLEPRIV__) @@ -163,7 +163,7 @@ CFBundleRef _CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef alloc /* Functions for examining the structure of a bundle */ CF_EXPORT -CFURLRef _CFBundleCopyResourceForkURL(CFBundleRef bundle); +CFURLRef _CFBundleCopyResourceForkURL(CFBundleRef bundle) CF_AVAILABLE_MAC(10_0); CF_EXPORT CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle); @@ -228,10 +228,10 @@ CF_EXPORT Boolean _CFBundleGetHasChanged(CFBundleRef bundle); CF_EXPORT -void _CFBundleFlushCaches(void); +void _CFBundleFlushCaches(void) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0); CF_EXPORT -void _CFBundleFlushCachesForURL(CFURLRef url); +void _CFBundleFlushCachesForURL(CFURLRef url) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0); CF_EXPORT void _CFBundleFlushBundleCaches(CFBundleRef bundle); // The previous two functions flush cached resource paths; this one also flushes bundle-specific caches such as the info dictionary and strings files @@ -275,9 +275,6 @@ CFURLRef _CFBundleCopySharedSupportURL(CFBundleRef bundle); // deprecated in fa CF_EXPORT CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle); // deprecated in favor of CFBundleCopyBuiltInPlugInsURL -CF_EXPORT -CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle); // deprecated in favor of CFBundleCopyBundleLocalizations - CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language); // deprecated in favor of CFBundleCopyResourceURLForLocalization diff --git a/CFBundle_BinaryTypes.h b/CFBundle_BinaryTypes.h index a85bae6..b1cc238 100644 --- a/CFBundle_BinaryTypes.h +++ b/CFBundle_BinaryTypes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBundle_BinaryTypes.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLE_BINARYTYPES__) diff --git a/CFBundle_InfoPlist.c b/CFBundle_InfoPlist.c new file mode 100644 index 0000000..f7d51a7 --- /dev/null +++ b/CFBundle_InfoPlist.c @@ -0,0 +1,822 @@ +/* + * Copyright (c) 2013 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_InfoPlist.c +// CoreFoundation +// +// Created by Tony Parker on 5/30/12. +// +// + +#include +#include +#include "CFBundle_Internal.h" +#include "CFByteOrder.h" +#include "CFURLAccess.h" + +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_EMBEDDED_MINI +#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 +#if !__CONSTANT_STRINGS__ + +#define _CFBundleNumberOfPlatforms 7 +static CFStringRef _CFBundleSupportedPlatforms[_CFBundleNumberOfPlatforms] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; +static const char *_CFBundleSupportedPlatformStrings[_CFBundleNumberOfPlatforms] = { "iphoneos", "macos", "windows", "linux", "freebsd", "solaris", "hpux" }; + +#define _CFBundleNumberOfProducts 3 +static CFStringRef _CFBundleSupportedProducts[_CFBundleNumberOfProducts] = { NULL, NULL, NULL }; +static const char *_CFBundleSupportedProductStrings[_CFBundleNumberOfProducts] = { "iphone", "ipod", "ipad" }; + +#define _CFBundleNumberOfiPhoneOSPlatformProducts 3 +static CFStringRef _CFBundleSupportediPhoneOSPlatformProducts[_CFBundleNumberOfiPhoneOSPlatformProducts] = { NULL, NULL, NULL }; +static const char *_CFBundleSupportediPhoneOSPlatformProductStrings[_CFBundleNumberOfiPhoneOSPlatformProducts] = { "iphone", "ipod", "ipad" }; + +CF_PRIVATE void _CFBundleResourcesInitialize() { + for (unsigned int i = 0; i < _CFBundleNumberOfPlatforms; i++) _CFBundleSupportedPlatforms[i] = CFStringCreateWithCString(kCFAllocatorSystemDefault, _CFBundleSupportedPlatformStrings[i], kCFStringEncodingUTF8); + + for (unsigned int i = 0; i < _CFBundleNumberOfProducts; i++) _CFBundleSupportedProducts[i] = CFStringCreateWithCString(kCFAllocatorSystemDefault, _CFBundleSupportedProductStrings[i], kCFStringEncodingUTF8); + + for (unsigned int i = 0; i < _CFBundleNumberOfiPhoneOSPlatformProducts; i++) _CFBundleSupportediPhoneOSPlatformProducts[i] = CFStringCreateWithCString(kCFAllocatorSystemDefault, _CFBundleSupportediPhoneOSPlatformProductStrings[i], kCFStringEncodingUTF8); +} + +#else + +#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +// On iOS, we only support one platform +#define _CFBundleNumberOfPlatforms 1 +static CFStringRef _CFBundleSupportedPlatforms[_CFBundleNumberOfPlatforms] = { CFSTR("iphoneos") }; +#else +// On other platforms, we support the following platforms +#define _CFBundleNumberOfPlatforms 7 +static CFStringRef _CFBundleSupportedPlatforms[_CFBundleNumberOfPlatforms] = { CFSTR("iphoneos"), CFSTR("macos"), CFSTR("windows"), CFSTR("linux"), CFSTR("freebsd"), CFSTR("solaris"), CFSTR("hpux") }; +#endif + +#define _CFBundleNumberOfProducts 3 +static CFStringRef _CFBundleSupportedProducts[_CFBundleNumberOfProducts] = { CFSTR("iphone"), CFSTR("ipod"), CFSTR("ipad") }; + +#define _CFBundleNumberOfiPhoneOSPlatformProducts 3 +static CFStringRef _CFBundleSupportediPhoneOSPlatformProducts[_CFBundleNumberOfiPhoneOSPlatformProducts] = { CFSTR("iphone"), CFSTR("ipod"), CFSTR("ipad") }; + +CF_PRIVATE void _CFBundleResourcesInitialize() { } +#endif + +#pragma mark - +#pragma mark Product and Platform Getters - Exported + +static CFStringRef _cfBundlePlatform = NULL; +CF_EXPORT void _CFSetProductName(CFStringRef str) { + // TODO: This should be removed. The "CLASSIC" check below removes the need to set the product name manually. + if (str) CFRetain(str); + _cfBundlePlatform = str; + // Note that the previous value is leaked, which is fine normally + // because the initial values would tend to be the constant strings + // below. That is required for thread-safety value due to the Get + // function [not being Copy]. It is also fine because people + // shouldn't be screwing around with this value casually. +} + +CF_EXPORT CFStringRef _CFGetProductName(void) { +#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + if (!_cfBundlePlatform) { + const char *isClassic = __CFgetenv("CLASSIC"); + if (isClassic && strnlen(isClassic, 1) >= 1 && isClassic[0] == '1') { + _cfBundlePlatform = CFSTR("iphone"); + } else { + char buffer[256]; + memset(buffer, 0, sizeof(buffer)); + size_t buflen = sizeof(buffer); + int ret = sysctlbyname("hw.machine", buffer, &buflen, NULL, 0); + if (0 == ret || (-1 == ret && ENOMEM == errno)) { + if (6 <= buflen && 0 == memcmp(buffer, "iPhone", 6)) { + _cfBundlePlatform = CFSTR("iphone"); + } else if (4 <= buflen && 0 == memcmp(buffer, "iPod", 4)) { + _cfBundlePlatform = CFSTR("ipod"); + } else if (4 <= buflen && 0 == memcmp(buffer, "iPad", 4)) { + _cfBundlePlatform = CFSTR("ipad"); + } else { + const char *env = __CFgetenv("IPHONE_SIMULATOR_DEVICE"); + if (env) { + if (0 == strcmp(env, "iPhone")) { + _cfBundlePlatform = CFSTR("iphone"); + } else if (0 == strcmp(env, "iPad")) { + _cfBundlePlatform = CFSTR("ipad"); + } else { + // fallback, unrecognized IPHONE_SIMULATOR_DEVICE + } + } else { + // fallback, unrecognized hw.machine and no IPHONE_SIMULATOR_DEVICE + } + } + } + } + if (!_cfBundlePlatform) _cfBundlePlatform = CFSTR("iphone"); // fallback + } + return _cfBundlePlatform; +#endif + return CFSTR(""); +} + +// All new-style bundles will have these extensions. +CF_EXPORT CFStringRef _CFGetPlatformName(void) { +#if DEPLOYMENT_TARGET_MACOSX + return _CFBundleMacOSXPlatformName; +#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + return _CFBundleiPhoneOSPlatformName; +#elif DEPLOYMENT_TARGET_WINDOWS + return _CFBundleWindowsPlatformName; +#elif DEPLOYMENT_TARGET_SOLARIS + return _CFBundleSolarisPlatformName; +#elif DEPLOYMENT_TARGET_HPUX + return _CFBundleHPUXPlatformName; +#elif DEPLOYMENT_TARGET_LINUX + return _CFBundleLinuxPlatformName; +#elif DEPLOYMENT_TARGET_FREEBSD + return _CFBundleFreeBSDPlatformName; +#else +#error Unknown or unspecified DEPLOYMENT_TARGET +#endif +} + +CF_EXPORT CFStringRef _CFGetAlternatePlatformName(void) { +#if DEPLOYMENT_TARGET_MACOSX + return _CFBundleAlternateMacOSXPlatformName; +#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + return _CFBundleMacOSXPlatformName; +#elif DEPLOYMENT_TARGET_WINDOWS + return CFSTR(""); +#else +#error Unknown or unspecified DEPLOYMENT_TARGET +#endif +} + +#pragma mark - +#pragma mark Product and Platform Suffix Processing - Internal + +// TODO: Merge with below function, they do the same thing +static Boolean _isValidPlatformSuffix(CFStringRef suffix) { + for (CFIndex idx = 0; idx < _CFBundleNumberOfPlatforms; idx++) { + if (CFEqual(suffix, _CFBundleSupportedPlatforms[idx])) return true; + } + return false; +} + +// Returns true if the searchRange of the fileName is equal to a valid platform name (e.g., macos, iphoneos) +CF_PRIVATE Boolean _CFBundleSupportedPlatformName(CFStringRef fileName, CFRange searchRange) { + for (CFIndex i = 0; i < _CFBundleNumberOfPlatforms; i++) { + if (CFStringFindWithOptions(fileName, _CFBundleSupportedPlatforms[i], searchRange, kCFCompareAnchored, NULL)) { + return true; + } + } + return false; +} + +// TODO: Merge with below function, they do the same thing +static Boolean _isValidProductSuffix(CFStringRef suffix) { + for (CFIndex idx = 0; idx < _CFBundleNumberOfProducts; idx++) { + if (CFEqual(suffix, _CFBundleSupportedProducts[idx])) return true; + } + return false; +} + +// Returns true if the searchRange of the fileName is equal to a a valid product name (e.g., ipod, ipad) +CF_PRIVATE Boolean _CFBundleSupportedProductName(CFStringRef fileName, CFRange searchRange) { + for (CFIndex i = 0; i < _CFBundleNumberOfProducts; i++) { + if (CFStringFindWithOptions(fileName, _CFBundleSupportedProducts[i], searchRange, kCFCompareAnchored, NULL)) { + return true; + } + } + return false; +} + +static Boolean _isValidiPhoneOSPlatformProductSuffix(CFStringRef suffix) { + for (CFIndex idx = 0; idx < _CFBundleNumberOfiPhoneOSPlatformProducts; idx++) { + if (CFEqual(suffix, _CFBundleSupportediPhoneOSPlatformProducts[idx])) return true; + } + return false; +} + +static Boolean _isValidPlatformAndProductSuffixPair(CFStringRef platform, CFStringRef product) { + if (!platform && !product) return true; + if (!platform) { + return _isValidProductSuffix(product); + } + if (!product) { + return _isValidPlatformSuffix(platform); + } + if (CFEqual(platform, _CFBundleiPhoneOSPlatformName)) { + return _isValidiPhoneOSPlatformProductSuffix(product); + } + return false; +} + +static Boolean _isBlacklistedKey(CFStringRef keyName) { +#if __CONSTANT_STRINGS__ +#define _CFBundleNumberOfBlacklistedInfoDictionaryKeys 2 + static const CFStringRef _CFBundleBlacklistedInfoDictionaryKeys[_CFBundleNumberOfBlacklistedInfoDictionaryKeys] = { CFSTR("CFBundleExecutable"), CFSTR("CFBundleIdentifier") }; + + for (CFIndex idx = 0; idx < _CFBundleNumberOfBlacklistedInfoDictionaryKeys; idx++) { + if (CFEqual(keyName, _CFBundleBlacklistedInfoDictionaryKeys[idx])) return true; + } +#endif + return false; +} + +static Boolean _isOverrideKey(CFStringRef fullKey, CFStringRef *outBaseKey, CFStringRef *outPlatformSuffix, CFStringRef *outProductSuffix) { + if (outBaseKey) { + *outBaseKey = NULL; + } + if (outPlatformSuffix) { + *outPlatformSuffix = NULL; + } + if (outProductSuffix) { + *outProductSuffix = NULL; + } + if (!fullKey) + return false; + CFRange minusRange = CFStringFind(fullKey, CFSTR("-"), kCFCompareBackwards); + CFRange tildeRange = CFStringFind(fullKey, CFSTR("~"), kCFCompareBackwards); + if (minusRange.location == kCFNotFound && tildeRange.location == kCFNotFound) return false; + // minus must come before tilde if both are present + if (minusRange.location != kCFNotFound && tildeRange.location != kCFNotFound && tildeRange.location <= minusRange.location) return false; + + CFIndex strLen = CFStringGetLength(fullKey); + CFRange baseKeyRange = (minusRange.location != kCFNotFound) ? CFRangeMake(0, minusRange.location) : CFRangeMake(0, tildeRange.location); + CFRange platformRange = CFRangeMake(kCFNotFound, 0); + CFRange productRange = CFRangeMake(kCFNotFound, 0); + if (minusRange.location != kCFNotFound) { + platformRange.location = minusRange.location + minusRange.length; + platformRange.length = ((tildeRange.location != kCFNotFound) ? tildeRange.location : strLen) - platformRange.location; + } + if (tildeRange.location != kCFNotFound) { + productRange.location = tildeRange.location + tildeRange.length; + productRange.length = strLen - productRange.location; + } + if (baseKeyRange.length < 1) return false; + if (platformRange.location != kCFNotFound && platformRange.length < 1) return false; + if (productRange.location != kCFNotFound && productRange.length < 1) return false; + + CFStringRef platform = (platformRange.location != kCFNotFound) ? CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fullKey, platformRange) : NULL; + CFStringRef product = (productRange.location != kCFNotFound) ? CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fullKey, productRange) : NULL; + Boolean result = _isValidPlatformAndProductSuffixPair(platform, product); + + if (result) { + if (outBaseKey) { + *outBaseKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fullKey, baseKeyRange); + } + if (outPlatformSuffix) { + *outPlatformSuffix = platform; + } else { + if (platform && !(0)) CFRelease(platform); + } + if (outProductSuffix) { + *outProductSuffix = product; + } else { + if (product && !(0)) CFRelease(product); + } + } else { + if (platform && !(0)) CFRelease(platform); + if (product && !(0)) CFRelease(product); + } + return result; +} + +static Boolean _isCurrentPlatformAndProduct(CFStringRef platform, CFStringRef product) { + if (!platform && !product) return true; + if (!platform) { + return CFEqual(_CFGetProductName(), product); + } + if (!product) { + return CFEqual(_CFGetPlatformName(), platform); + } + + return CFEqual(_CFGetProductName(), product) && CFEqual(_CFGetPlatformName(), platform); +} + +static CFArrayRef _CopySortedOverridesForBaseKey(CFStringRef keyName, CFDictionaryRef dict) { + CFMutableArrayRef overrides = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + CFStringRef keyNameWithBoth = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@~%@"), keyName, _CFGetPlatformName(), _CFGetProductName()); + CFStringRef keyNameWithProduct = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@~%@"), keyName, _CFGetProductName()); + CFStringRef keyNameWithPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@"), keyName, _CFGetPlatformName()); + + CFIndex count = CFDictionaryGetCount(dict); + + if (count > 0) { + CFTypeRef *keys = (CFTypeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0); + CFTypeRef *values = &(keys[count]); + + CFDictionaryGetKeysAndValues(dict, keys, values); + for (CFIndex idx = 0; idx < count; idx++) { + if (CFEqual(keys[idx], keyNameWithBoth)) { + CFArrayAppendValue(overrides, keys[idx]); + break; + } + } + for (CFIndex idx = 0; idx < count; idx++) { + if (CFEqual(keys[idx], keyNameWithProduct)) { + CFArrayAppendValue(overrides, keys[idx]); + break; + } + } + for (CFIndex idx = 0; idx < count; idx++) { + if (CFEqual(keys[idx], keyNameWithPlatform)) { + CFArrayAppendValue(overrides, keys[idx]); + break; + } + } + for (CFIndex idx = 0; idx < count; idx++) { + if (CFEqual(keys[idx], keyName)) { + CFArrayAppendValue(overrides, keys[idx]); + break; + } + } + + CFAllocatorDeallocate(kCFAllocatorSystemDefault, keys); + } + + CFRelease(keyNameWithProduct); + CFRelease(keyNameWithPlatform); + CFRelease(keyNameWithBoth); + + return overrides; +} + +CF_PRIVATE void _CFBundleInfoPlistProcessInfoDictionary(CFMutableDictionaryRef dict) { + CFIndex count = CFDictionaryGetCount(dict); + + if (count > 0) { + CFTypeRef *keys = (CFTypeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0); + CFTypeRef *values = &(keys[count]); + CFMutableArrayRef guard = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + + CFDictionaryGetKeysAndValues(dict, keys, values); + for (CFIndex idx = 0; idx < count; idx++) { + CFStringRef keyPlatformSuffix, keyProductSuffix, keyName; + if (_isOverrideKey((CFStringRef)keys[idx], &keyName, &keyPlatformSuffix, &keyProductSuffix)) { + CFArrayRef keysForBaseKey = NULL; + if (_isCurrentPlatformAndProduct(keyPlatformSuffix, keyProductSuffix) && !_isBlacklistedKey(keyName) && CFDictionaryContainsKey(dict, keys[idx])) { + keysForBaseKey = _CopySortedOverridesForBaseKey(keyName, dict); + CFIndex keysForBaseKeyCount = CFArrayGetCount(keysForBaseKey); + + //make sure the other keys for this base key don't get released out from under us until we're done + CFArrayAppendValue(guard, keysForBaseKey); + + //the winner for this base key will be sorted to the front, do the override with it + CFTypeRef highestPriorityKey = CFArrayGetValueAtIndex(keysForBaseKey, 0); + CFDictionarySetValue(dict, keyName, CFDictionaryGetValue(dict, highestPriorityKey)); + + //remove everything except the now-overridden key; this will cause them to fail the CFDictionaryContainsKey(dict, keys[idx]) check in the enclosing if() and not be reprocessed + for (CFIndex presentKeysIdx = 0; presentKeysIdx < keysForBaseKeyCount; presentKeysIdx++) { + CFStringRef currentKey = (CFStringRef)CFArrayGetValueAtIndex(keysForBaseKey, presentKeysIdx); + if (!CFEqual(currentKey, keyName)) + CFDictionaryRemoveValue(dict, currentKey); + } + } else { + CFDictionaryRemoveValue(dict, keys[idx]); + } + + + if (keyPlatformSuffix) CFRelease(keyPlatformSuffix); + if (keyProductSuffix) CFRelease(keyProductSuffix); + CFRelease(keyName); + if (keysForBaseKey) CFRelease(keysForBaseKey); + } + } + + CFAllocatorDeallocate(kCFAllocatorSystemDefault, keys); + CFRelease(guard); + } +} + +#pragma mark - +#pragma mark Info Plist Functions + +CF_PRIVATE CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) { + CFDictionaryRef dict = NULL; + unsigned char buff[CFMaxPathSize]; + uint8_t localVersion = 0; + + if (CFURLGetFileSystemRepresentation(url, true, buff, CFMaxPathSize)) { + CFURLRef newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, buff, strlen((char *)buff), true); + if (!newURL) newURL = (CFURLRef)CFRetain(url); + + localVersion = _CFBundleGetBundleVersionForURL(newURL); + + dict = _CFBundleCopyInfoDictionaryInDirectoryWithVersion(alloc, newURL, localVersion); + CFRelease(newURL); + } + if (version) *version = localVersion; + return dict; +} + +CF_PRIVATE CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectoryWithVersion(CFAllocatorRef alloc, CFURLRef url, uint8_t version) { + // We only return NULL for a bad URL, otherwise we create a dummy dictionary + if (!url) return NULL; + + CFDictionaryRef result = NULL; + + // We're going to search for two files here - Info.plist and Info-macos.plist (platform specific). The platform-specific one takes precedence. + // First, construct the URL to the directory we'll search by using the passed in URL as a base + CFStringRef platformInfoURLFromBase = _CFBundlePlatformInfoURLFromBase0; + CFStringRef infoURLFromBase = _CFBundleInfoURLFromBase0; + CFURLRef directoryURL = NULL; + + if (0 == version) { + directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleResourcesURLFromBase0, url); + platformInfoURLFromBase = _CFBundlePlatformInfoURLFromBase0; + infoURLFromBase = _CFBundleInfoURLFromBase0; + } else if (1 == version) { + directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase1, url); + platformInfoURLFromBase = _CFBundlePlatformInfoURLFromBase1; + infoURLFromBase = _CFBundleInfoURLFromBase1; + } else if (2 == version) { + directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase2, url); + platformInfoURLFromBase = _CFBundlePlatformInfoURLFromBase2; + infoURLFromBase = _CFBundleInfoURLFromBase2; + } else if (3 == version) { + CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + // this test is necessary to exclude the case where a bundle is spuriously created from the innards of another bundle + if (path) { + if (!(CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(path, _CFBundleResourcesDirectoryName))) { + directoryURL = (CFURLRef)CFRetain(url); + platformInfoURLFromBase = _CFBundlePlatformInfoURLFromBase3; + infoURLFromBase = _CFBundleInfoURLFromBase3; + } + CFRelease(path); + } + } + + CFURLRef absoluteURL; + if (directoryURL) { + absoluteURL = CFURLCopyAbsoluteURL(directoryURL); + CFStringRef directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); + CFRelease(absoluteURL); + + __block CFURLRef infoPlistURL = NULL; + __block CFURLRef platformInfoPlistURL = NULL; + + CFIndex infoPlistLength = CFStringGetLength(_CFBundleInfoPlistName); + CFIndex platformInfoPlistLength = CFStringGetLength(_CFBundlePlatformInfoPlistName); + + // Look inside this directory for the platform-specific and global Info.plist + // For compatability reasons, we support case-insensitive versions of Info.plist. That means that we must do a search of all the file names in the directory so we can compare. Otherwise, perhaps a couple of stats would be more efficient than the readdir. + _CFIterateDirectory(directoryPath, ^Boolean(CFStringRef fileName, uint8_t fileType) { + // Only do the platform check on platforms where the string is different than the normal one + if (_CFBundlePlatformInfoPlistName != _CFBundleInfoPlistName) { + if (!platformInfoPlistURL && CFStringGetLength(fileName) == platformInfoPlistLength && CFStringCompareWithOptions(fileName, _CFBundlePlatformInfoPlistName, CFRangeMake(0, platformInfoPlistLength), kCFCompareCaseInsensitive | kCFCompareAnchored) == kCFCompareEqualTo) { + // Make a URL out of this file + platformInfoPlistURL = CFURLCreateWithString(kCFAllocatorSystemDefault, platformInfoURLFromBase, url); + } + } + + if (!infoPlistURL && CFStringGetLength(fileName) == infoPlistLength && CFStringCompareWithOptions(fileName, _CFBundleInfoPlistName, CFRangeMake(0, infoPlistLength), kCFCompareCaseInsensitive | kCFCompareAnchored) == kCFCompareEqualTo) { + // Make a URL out of this file + infoPlistURL = CFURLCreateWithString(kCFAllocatorSystemDefault, infoURLFromBase, url); + } + + // If by some chance we have both URLs, just bail early (or just the infoPlistURL on platforms that have no platform-specific name) + if (_CFBundlePlatformInfoPlistName != _CFBundleInfoPlistName) { + if (infoPlistURL && platformInfoPlistURL) return false; + } else { + if (infoPlistURL) return false; + } + + return true; + }); + + CFRelease(directoryPath); + CFRelease(directoryURL); + + // Attempt to read in the data from the Info.plist we found - first the platform-specific one. + CFDataRef infoData = NULL; + CFURLRef finalInfoPlistURL = NULL; + if (platformInfoPlistURL) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, platformInfoPlistURL, &infoData, NULL, NULL, NULL); +#pragma GCC diagnostic pop + if (infoData) finalInfoPlistURL = platformInfoPlistURL; + } + + if (!infoData && infoPlistURL) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, infoPlistURL, &infoData, NULL, NULL, NULL); +#pragma GCC diagnostic pop + if (infoData) finalInfoPlistURL = infoPlistURL; + } + + if (infoData) { + CFErrorRef error = NULL; + result = (CFDictionaryRef)CFPropertyListCreateWithData(alloc, infoData, kCFPropertyListMutableContainers, NULL, &error); + if (result) { + if (CFDictionaryGetTypeID() == CFGetTypeID(result)) { + CFDictionarySetValue((CFMutableDictionaryRef)result, _kCFBundleInfoPlistURLKey, finalInfoPlistURL); + } else { + CFRelease(result); + result = NULL; + } + } else if (error) { + CFDictionaryRef userInfo = CFErrorCopyUserInfo(error); + CFLog(kCFLogLevelError, CFSTR("There was an error parsing the Info.plist for the bundle at URL %@\n %@\n %@"), infoPlistURL, error, userInfo); + if (userInfo) CFRelease(userInfo); + CFRelease(error); + } + + if (!result) { + result = CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue((CFMutableDictionaryRef)result, _kCFBundleRawInfoPlistURLKey, finalInfoPlistURL); + } + + CFRelease(infoData); + } + + if (platformInfoPlistURL) CFRelease(platformInfoPlistURL); + if (infoPlistURL) CFRelease(infoPlistURL); + } + + if (!result) { + result = CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + // process ~ipad, ~iphone, etc. + _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)result); + + return result; +} + +CF_EXPORT CFDictionaryRef CFBundleCopyInfoDictionaryForURL(CFURLRef url) { + CFDictionaryRef result = NULL; + Boolean isDir = false; + if (_CFIsResourceAtURL(url, &isDir)) { + if (isDir) { + result = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, NULL); + } else { + result = _CFBundleCopyInfoDictionaryInExecutable(url); + } + } + if (result && (0)) CFRetain(result); // conditionally put on a retain for a Copy function + return result; +} + +static Boolean _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(CFAllocatorRef alloc, CFURLRef url, CFDictionaryRef infoDict, UInt32 *packageType, UInt32 *packageCreator) { + Boolean retVal = false, hasType = false, hasCreator = false, releaseInfoDict = false; + CFURLRef tempURL; + CFDataRef pkgInfoData = NULL; + + // Check for a "real" new bundle + tempURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundlePkgInfoURLFromBase2, url); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tempURL, &pkgInfoData, NULL, NULL, NULL); +#pragma GCC diagnostic pop + CFRelease(tempURL); + if (!pkgInfoData) { + tempURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundlePkgInfoURLFromBase1, url); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tempURL, &pkgInfoData, NULL, NULL, NULL); +#pragma GCC diagnostic pop + CFRelease(tempURL); + } + if (!pkgInfoData) { + // Check for a "pseudo" new bundle + tempURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundlePseudoPkgInfoURLFromBase, url); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tempURL, &pkgInfoData, NULL, NULL, NULL); +#pragma GCC diagnostic pop + CFRelease(tempURL); + } + + // Now, either we have a pkgInfoData or not. If not, then is it because this is a new bundle without one (do we allow this?), or is it dbecause it is an old bundle. + // If we allow new bundles to not have a PkgInfo (because they already have the same data in the Info.plist), then we have to go read the info plist which makes failure expensive. + // drd: So we assume that a new bundle _must_ have a PkgInfo if they have this data at all, otherwise we manufacture it from the extension. + + if (pkgInfoData && CFDataGetLength(pkgInfoData) >= (int)(sizeof(UInt32) * 2)) { + UInt32 *pkgInfo = (UInt32 *)CFDataGetBytePtr(pkgInfoData); + if (packageType) *packageType = CFSwapInt32BigToHost(pkgInfo[0]); + if (packageCreator) *packageCreator = CFSwapInt32BigToHost(pkgInfo[1]); + retVal = hasType = hasCreator = true; + } + if (pkgInfoData) CFRelease(pkgInfoData); + if (!retVal) { + if (!infoDict) { + infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, NULL); + releaseInfoDict = true; + } + if (infoDict) { + CFStringRef typeString = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundlePackageTypeKey), creatorString = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleSignatureKey); + UInt32 tmp; + CFIndex usedBufLen = 0; + if (typeString && CFGetTypeID(typeString) == CFStringGetTypeID() && CFStringGetLength(typeString) == 4 && 4 == CFStringGetBytes(typeString, CFRangeMake(0, 4), kCFStringEncodingMacRoman, 0, false, (UInt8 *)&tmp, 4, &usedBufLen) && 4 == usedBufLen) { + if (packageType) *packageType = CFSwapInt32BigToHost(tmp); + retVal = hasType = true; + } + if (creatorString && CFGetTypeID(creatorString) == CFStringGetTypeID() && CFStringGetLength(creatorString) == 4 && 4 == CFStringGetBytes(creatorString, CFRangeMake(0, 4), kCFStringEncodingMacRoman, 0, false, (UInt8 *)&tmp, 4, &usedBufLen) && 4 == usedBufLen) { + if (packageCreator) *packageCreator = CFSwapInt32BigToHost(tmp); + retVal = hasCreator = true; + } + if (releaseInfoDict && !(0)) CFRelease(infoDict); + } + } + if (!hasType || !hasCreator) { + // If this looks like a bundle then manufacture the type and creator. + if (retVal || _CFBundleURLLooksLikeBundle(url)) { + if (packageCreator && !hasCreator) *packageCreator = 0x3f3f3f3f; // '????' + if (packageType && !hasType) { + CFStringRef urlStr; + UniChar buff[CFMaxPathSize]; + CFIndex strLen, startOfExtension; + CFURLRef absoluteURL; + + // Detect "app", "debug", "profile", or "framework" extensions + absoluteURL = CFURLCopyAbsoluteURL(url); + urlStr = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); + CFRelease(absoluteURL); + strLen = CFStringGetLength(urlStr); + if (strLen > CFMaxPathSize) strLen = CFMaxPathSize; + CFStringGetCharacters(urlStr, CFRangeMake(0, strLen), buff); + CFRelease(urlStr); + startOfExtension = _CFStartOfPathExtension(buff, strLen); + if ((strLen - startOfExtension == 4 || strLen - startOfExtension == 5) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'a' && buff[startOfExtension+2] == (UniChar)'p' && buff[startOfExtension+3] == (UniChar)'p' && (strLen - startOfExtension == 4 || buff[startOfExtension+4] == (UniChar)PATH_SEP)) { + // This is an app + *packageType = 0x4150504c; // 'APPL' + } else if ((strLen - startOfExtension == 6 || strLen - startOfExtension == 7) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'d' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'b' && buff[startOfExtension+4] == (UniChar)'u' && buff[startOfExtension+5] == (UniChar)'g' && (strLen - startOfExtension == 6 || buff[startOfExtension+6] == (UniChar)PATH_SEP)) { + // This is an app (debug version) + *packageType = 0x4150504c; // 'APPL' + } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'p' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'o' && buff[startOfExtension+4] == (UniChar)'f' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'l' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)PATH_SEP)) { + // This is an app (profile version) + *packageType = 0x4150504c; // 'APPL' + } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'s' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'r' && buff[startOfExtension+4] == (UniChar)'v' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'c' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)PATH_SEP)) { + // This is a service + *packageType = 0x4150504c; // 'APPL' + } else if ((strLen - startOfExtension == 10 || strLen - startOfExtension == 11) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'f' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'a' && buff[startOfExtension+4] == (UniChar)'m' && buff[startOfExtension+5] == (UniChar)'e' && buff[startOfExtension+6] == (UniChar)'w' && buff[startOfExtension+7] == (UniChar)'o' && buff[startOfExtension+8] == (UniChar)'r' && buff[startOfExtension+9] == (UniChar)'k' && (strLen - startOfExtension == 10 || buff[startOfExtension+10] == (UniChar)PATH_SEP)) { + // This is a framework + *packageType = 0x464d574b; // 'FMWK' + } else { + // Default to BNDL for generic bundle + *packageType = 0x424e444c; // 'BNDL' + } + } + retVal = true; + } + } + return retVal; +} + +CF_EXPORT Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) { + return _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(alloc, url, NULL, packageType, packageCreator); +} + +CF_EXPORT void CFBundleGetPackageInfo(CFBundleRef bundle, UInt32 *packageType, UInt32 *packageCreator) { + CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); + if (!_CFBundleGetPackageInfoInDirectoryWithInfoDictionary(kCFAllocatorSystemDefault, bundleURL, CFBundleGetInfoDictionary(bundle), packageType, packageCreator)) { + if (packageType) *packageType = 0x424e444c; // 'BNDL' + if (packageCreator) *packageCreator = 0x3f3f3f3f; // '????' + } + if (bundleURL) CFRelease(bundleURL); +} + +CF_EXPORT Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) { + return _CFBundleGetPackageInfoInDirectory(kCFAllocatorSystemDefault, url, packageType, packageCreator); +} + +CFDictionaryRef CFBundleCopyInfoDictionaryInDirectory(CFURLRef url) { + CFDictionaryRef dict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, NULL); + return dict; +} + +// The Info.plist should NOT be mutated after being created. If there is any fixing up of the info dictionary to do, do it here. +// Call with bundle lock +static void _CFBundleInfoPlistFixupInfoDictionary(CFBundleRef bundle, CFMutableDictionaryRef infoDict) { + // Version number + CFTypeRef unknownVersionValue = CFDictionaryGetValue(infoDict, _kCFBundleNumericVersionKey); + CFNumberRef versNum; + UInt32 vers = 0; + + if (!unknownVersionValue) unknownVersionValue = CFDictionaryGetValue(infoDict, kCFBundleVersionKey); + if (unknownVersionValue) { + if (CFGetTypeID(unknownVersionValue) == CFStringGetTypeID()) { + // Convert a string version number into a numeric one. + vers = _CFVersionNumberFromString((CFStringRef)unknownVersionValue); + + versNum = CFNumberCreate(CFGetAllocator(bundle), kCFNumberSInt32Type, &vers); + CFDictionarySetValue(infoDict, _kCFBundleNumericVersionKey, versNum); + CFRelease(versNum); + } else if (CFGetTypeID(unknownVersionValue) == CFNumberGetTypeID()) { + // Nothing to do here + } else { + CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleNumericVersionKey); + } + } +} + +CFDictionaryRef CFBundleGetInfoDictionary(CFBundleRef bundle) { + __CFSpinLock(&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); + + return bundle->_infoDict; +} + +CFDictionaryRef _CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { + return CFBundleGetLocalInfoDictionary(bundle); +} + +CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) { + CFDictionaryRef localInfoDict = NULL; + __CFSpinLock(&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); + CFURLRef url = CFBundleCopyResourceURL(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL); + if (url) { + CFDataRef data; + SInt32 errCode; + CFStringRef errStr = NULL; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, url, &data, NULL, NULL, &errCode)) { + localInfoDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListMutableContainers, &errStr); + if (errStr) CFRelease(errStr); + if (localInfoDict && CFDictionaryGetTypeID() != CFGetTypeID(localInfoDict)) { + CFRelease(localInfoDict); + localInfoDict = NULL; + } + CFRelease(data); + } +#pragma GCC diagnostic pop + CFRelease(url); + } + if (localInfoDict) _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef)localInfoDict); + // remain locked here until we exit the if statement. + __CFSpinLock(&bundle->_lock); + if (!bundle->_localInfoDict) { + // Still have no info dictionary, so set it + bundle->_localInfoDict = localInfoDict; + } else { + // Oops, some other thread created an info dictionary too. We'll just release this one and use that one. + if (localInfoDict) CFRelease(localInfoDict); + localInfoDict = bundle->_localInfoDict; + } + } + __CFSpinUnlock(&bundle->_lock); + + return localInfoDict; +} + +CFPropertyListRef _CFBundleGetValueForInfoKey(CFBundleRef bundle, CFStringRef key) { + return (CFPropertyListRef)CFBundleGetValueForInfoDictionaryKey(bundle, key); +} + +CFTypeRef CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle, CFStringRef key) { + // Look in InfoPlist.strings first. Then look in Info.plist + CFTypeRef result = NULL; + if (bundle && key) { + CFDictionaryRef dict = CFBundleGetLocalInfoDictionary(bundle); + if (dict) result = CFDictionaryGetValue(dict, key); + if (!result) { + dict = CFBundleGetInfoDictionary(bundle); + if (dict) result = CFDictionaryGetValue(dict, key); + } + } + return result; +} + +CFStringRef CFBundleGetIdentifier(CFBundleRef bundle) { + CFStringRef bundleID = NULL; + CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); + if (infoDict) bundleID = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleIdentifierKey); + return bundleID; +} diff --git a/CFBundle_Internal.h b/CFBundle_Internal.h index b612fd9..1d1ca84 100644 --- a/CFBundle_Internal.h +++ b/CFBundle_Internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBundle_Internal.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBUNDLE_INTERNAL__) @@ -54,9 +54,6 @@ CF_EXTERN_C_BEGIN #define CFBundleExecutableLoadError 3587 #define CFBundleExecutableLinkError 3588 -// uncomment this to enable the new look up algorithm -#define CFBUNDLE_NEWLOOKUP - // uncomment this to enable the checking for 8302591 //#define CFBUNDLE_NO_TRAVERSE_OUTSIDE @@ -78,30 +75,93 @@ typedef struct __CFPlugInData { CFMutableArrayRef _factories; } _CFPlugInData; +struct __CFBundle { + CFRuntimeBase _base; + + CFURLRef _url; + CFDateRef _modDate; + + __strong CFDictionaryRef _infoDict; + __strong CFDictionaryRef _localInfoDict; + CFArrayRef _searchLanguages; + + __CFPBinaryType _binaryType; + Boolean _isLoaded; + uint8_t _version; + Boolean _sharesStringsFiles; + char _padding[1]; + + /* CFM goop */ + void *_connectionCookie; + + /* DYLD goop */ + const void *_imageCookie; + const void *_moduleCookie; + + /* dlfcn goop */ + void *_handleCookie; + + /* CFM<->DYLD glue */ + CFMutableDictionaryRef _glueDict; + + /* Resource fork goop */ + _CFResourceData _resourceData; + + _CFPlugInData _plugInData; + + pthread_mutex_t _bundleLoadingLock; + + CFStringRef _executablePath; // Calculated and cached here + CFStringRef _developmentRegion; // Calculated and cached here + Boolean _developmentRegionCalculated; + + CFSpinLock_t _lock; + + CFArrayRef _localizations; // List of localizations, including the development language fallback if required + Boolean _lookedForLocalizations; + + CFMutableDictionaryRef _resourceDirectoryContents; + + CFSpinLock_t _queryLock; + CFMutableDictionaryRef _queryTable; + CFStringRef _bundleBasePath; + +#if defined(BINARY_SUPPORT_DLL) + HMODULE _hModule; +#endif /* BINARY_SUPPORT_DLL */ + +}; + extern _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle); /* Private CFBundle API */ +CF_PRIVATE void _CFBundleInfoPlistProcessInfoDictionary(CFMutableDictionaryRef dict); +CF_PRIVATE Boolean _CFBundleSupportedProductName(CFStringRef fileName, CFRange searchRange); +CF_PRIVATE Boolean _CFBundleSupportedPlatformName(CFStringRef fileName, CFRange searchRange); + +CF_EXPORT CFStringRef _CFGetProductName(void); +CF_EXPORT CFStringRef _CFGetPlatformName(void); +CF_EXPORT CFStringRef _CFGetAlternatePlatformName(void); + extern Boolean _CFIsResourceAtURL(CFURLRef url, Boolean *isDir); extern Boolean _CFIsResourceAtPath(CFStringRef path, Boolean *isDir); -extern Boolean _CFBundleURLLooksLikeBundleVersion(CFURLRef url, UInt8 *version); +CF_PRIVATE uint8_t _CFBundleGetBundleVersionForURL(CFURLRef url); extern CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt8 *version); extern CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectoryWithVersion(CFAllocatorRef alloc, CFURLRef url, UInt8 version); extern CFURLRef _CFBundleCopySupportFilesDirectoryURLInDirectory(CFURLRef bundleURL, UInt8 version); extern CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundleURL, UInt8 version); extern Boolean _CFBundleCouldBeBundle(CFURLRef url); -extern CFURLRef _CFBundleCopyResourceForkURLMayBeLocal(CFBundleRef bundle, Boolean mayBeLocal); extern CFDictionaryRef _CFBundleCopyInfoDictionaryInResourceForkWithAllocator(CFAllocatorRef alloc, CFURLRef url); +CF_PRIVATE CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict); #if DEPLOYMENT_TARGET_MACOSX -__private_extern__ CFStringRef _CFBundleCopyBundleDevelopmentRegionFromVersResource(CFBundleRef bundle); +CF_PRIVATE CFStringRef _CFBundleCopyBundleDevelopmentRegionFromVersResource(CFBundleRef bundle); #endif extern CFDictionaryRef _CFBundleCopyInfoDictionaryInExecutable(CFURLRef url); extern CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef url); -extern void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, UInt8 version, CFDictionaryRef infoDict, CFMutableArrayRef lprojNames, CFStringRef devLang); - extern CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void); extern CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirectoryName(void); extern CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryName(void); @@ -114,13 +174,9 @@ extern void _CFBundleScheduleForUnloading(CFBundleRef bundle); extern void _CFBundleUnscheduleForUnloading(CFBundleRef bundle); extern void _CFBundleUnloadScheduledBundles(void); -__private_extern__ CFStringRef _CFBundleGetBundlePath(CFBundleRef bundle); -__private_extern__ void _CFBundleSetResourceDir(UniChar *buffer, CFIndex *currLen, CFIndex maxLen, uint8_t version); -__private_extern__ CFURLRef _CFBundleCopyResourceForkURLWithoutLocal(CFBundleRef bundle); -__private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, UniChar *resDir, CFIndex resDirLen, UniChar *subDir, CFIndex subDirLen); -__private_extern__ CFDictionaryRef _CFBundleCopyQueryTable(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, UniChar *resDir, CFIndex resDirLen, UniChar *subDirBuffer, CFIndex subDirLen); -__private_extern__ CFArrayRef _CFFindBundleResourcesNoBlock(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef subDirName, CFArrayRef searchLanguages, CFStringRef resName, CFArrayRef resTypes, CFIndex limit, uint8_t version); -__private_extern__ CFTypeRef _CFBundleCopyFindResourcesWithNoBlock(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subPath, CFStringRef lproj, Boolean returnArray, Boolean localized); +CF_PRIVATE void _CFBundleAppendResourceDir(CFMutableStringRef path, uint8_t version); + +CF_PRIVATE UInt8 _CFBundleLayoutVersion(CFBundleRef bundle); #if defined(BINARY_SUPPORT_DYLD) // DYLD API @@ -176,6 +232,14 @@ extern void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory); #define _CFBundleExecutablesDirectoryName CFSTR("Executables") #define _CFBundleNonLocalizedResourcesDirectoryName CFSTR("Non-localized Resources") +#if DEPLOYMENT_TARGET_WINDOWS +#define _CFBundleSupportFilesDirectoryName1WithResources CFSTR("Support Files\\Resources") +#define _CFBundleSupportFilesDirectoryName2WithResources CFSTR("Contents\\Resources") +#else +#define _CFBundleSupportFilesDirectoryName1WithResources CFSTR("Support Files/Resources") +#define _CFBundleSupportFilesDirectoryName2WithResources CFSTR("Contents/Resources") +#endif + #define _CFBundleSupportFilesURLFromBase1 CFSTR("Support%20Files/") #define _CFBundleSupportFilesURLFromBase2 CFSTR("Contents/") #define _CFBundleResourcesURLFromBase0 CFSTR("Resources/") @@ -186,15 +250,42 @@ extern void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory); #define _CFBundleAppStoreReceiptURLFromBase2 CFSTR("Contents/_MASReceipt/receipt") #define _CFBundleExecutablesURLFromBase1 CFSTR("Support%20Files/Executables/") #define _CFBundleExecutablesURLFromBase2 CFSTR("Contents/") + #define _CFBundleInfoURLFromBase0 CFSTR("Resources/Info.plist") #define _CFBundleInfoURLFromBase1 CFSTR("Support%20Files/Info.plist") #define _CFBundleInfoURLFromBase2 CFSTR("Contents/Info.plist") #define _CFBundleInfoURLFromBase3 CFSTR("Info.plist") -#define _CFBundleInfoFileName CFSTR("Info.plist") -#define _CFBundleInfoURLFromBaseNoExtension0 CFSTR("Resources/Info") -#define _CFBundleInfoURLFromBaseNoExtension1 CFSTR("Support%20Files/Info") -#define _CFBundleInfoURLFromBaseNoExtension2 CFSTR("Contents/Info") #define _CFBundleInfoURLFromBaseNoExtension3 CFSTR("Info") + +#if DEPLOYMENT_TARGET_MACOSX +#define _CFBundlePlatformInfoURLFromBase0 CFSTR("Resources/Info-macos.plist") +#define _CFBundlePlatformInfoURLFromBase1 CFSTR("Support%20Files/Info-macos.plist") +#define _CFBundlePlatformInfoURLFromBase2 CFSTR("Contents/Info-macos.plist") +#define _CFBundlePlatformInfoURLFromBase3 CFSTR("Info-macos.plist") +#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#define _CFBundlePlatformInfoURLFromBase0 CFSTR("Resources/Info-iphoneos.plist") +#define _CFBundlePlatformInfoURLFromBase1 CFSTR("Support%20Files/Info-iphoneos.plist") +#define _CFBundlePlatformInfoURLFromBase2 CFSTR("Contents/Info-iphoneos.plist") +#define _CFBundlePlatformInfoURLFromBase3 CFSTR("Info-iphoneos.plist") +#else +// No platform-specific variants in these cases +#define _CFBundlePlatformInfoURLFromBase0 _CFBundleInfoURLFromBase0 +#define _CFBundlePlatformInfoURLFromBase1 _CFBundleInfoURLFromBase1 +#define _CFBundlePlatformInfoURLFromBase2 _CFBundleInfoURLFromBase2 +#define _CFBundlePlatformInfoURLFromBase3 _CFBundleInfoURLFromBase3 +#endif + +#define _CFBundleInfoPlistName CFSTR("Info.plist") + +#if DEPLOYMENT_TARGET_MACOSX +#define _CFBundlePlatformInfoPlistName CFSTR("Info-macos.plist") +#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#define _CFBundlePlatformInfoPlistName CFSTR("Info-iphoneos.plist") +#else +// No platform-specific Info.plist for these +#define _CFBundlePlatformInfoPlistName _CFBundleInfoPlistName +#endif + #define _CFBundleInfoExtension CFSTR("plist") #define _CFBundleLocalInfoName CFSTR("InfoPlist") #define _CFBundlePkgInfoURLFromBase1 CFSTR("Support%20Files/PkgInfo") @@ -246,12 +337,6 @@ extern void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory); #define _CFBundleWindowsResourceDirectoryExtension CFSTR("resources") -/* Old platform names (no longer used) */ -#define _CFBundleMacOSXPlatformName_OLD CFSTR("macintosh") -#define _CFBundleAlternateMacOSXPlatformName_OLD CFSTR("nextstep") -#define _CFBundleWindowsPlatformName_OLD CFSTR("windows") -#define _CFBundleAlternateWindowsPlatformName_OLD CFSTR("winnt") - #define _CFBundleMacOSXInfoPlistPlatformName_OLD CFSTR("macos") #define _CFBundleWindowsInfoPlistPlatformName_OLD CFSTR("win32") diff --git a/CFBundle_Resources.c b/CFBundle_Resources.c index 903cff6..4bc74f5 100644 --- a/CFBundle_Resources.c +++ b/CFBundle_Resources.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,12 +22,10 @@ */ /* CFBundle_Resources.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ -#define READ_DIRECTORIES_CACHE_CAPACITY 128 - #include "CFBundle_Internal.h" #include #include @@ -74,452 +72,15 @@ #endif -CF_EXPORT bool CFDictionaryGetKeyIfPresent(CFDictionaryRef dict, const void *key, const void **actualkey); - -extern void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len); - - -static inline Boolean _CFBundleSortedArrayContains(CFArrayRef arr, CFStringRef target) { - CFRange arrRange = CFRangeMake(0, CFArrayGetCount(arr)); - CFIndex itemIdx = CFArrayBSearchValues(arr, arrRange, target, (CFComparatorFunction)CFStringCompare, NULL); - return itemIdx < arrRange.length && CFEqual(CFArrayGetValueAtIndex(arr, itemIdx), target); -} - -// 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 -#if !__CONSTANT_STRINGS__ - -#define _CFBundleNumberOfPlatforms 7 -static CFStringRef _CFBundleSupportedPlatforms[_CFBundleNumberOfPlatforms] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static const char *_CFBundleSupportedPlatformStrings[_CFBundleNumberOfPlatforms] = { "iphoneos", "macos", "windows", "linux", "freebsd", "solaris", "hpux" }; - -#define _CFBundleNumberOfProducts 3 -static CFStringRef _CFBundleSupportedProducts[_CFBundleNumberOfProducts] = { NULL, NULL, NULL }; -static const char *_CFBundleSupportedProductStrings[_CFBundleNumberOfProducts] = { "iphone", "ipod", "ipad" }; - -#define _CFBundleNumberOfiPhoneOSPlatformProducts 3 -static CFStringRef _CFBundleSupportediPhoneOSPlatformProducts[_CFBundleNumberOfiPhoneOSPlatformProducts] = { NULL, NULL, NULL }; -static const char *_CFBundleSupportediPhoneOSPlatformProductStrings[_CFBundleNumberOfiPhoneOSPlatformProducts] = { "iphone", "ipod", "ipad" }; - -__private_extern__ void _CFBundleResourcesInitialize() { - for (unsigned int i = 0; i < _CFBundleNumberOfPlatforms; i++) _CFBundleSupportedPlatforms[i] = CFStringCreateWithCString(kCFAllocatorSystemDefault, _CFBundleSupportedPlatformStrings[i], kCFStringEncodingUTF8); - - for (unsigned int i = 0; i < _CFBundleNumberOfProducts; i++) _CFBundleSupportedProducts[i] = CFStringCreateWithCString(kCFAllocatorSystemDefault, _CFBundleSupportedProductStrings[i], kCFStringEncodingUTF8); - - for (unsigned int i = 0; i < _CFBundleNumberOfiPhoneOSPlatformProducts; i++) _CFBundleSupportediPhoneOSPlatformProducts[i] = CFStringCreateWithCString(kCFAllocatorSystemDefault, _CFBundleSupportediPhoneOSPlatformProductStrings[i], kCFStringEncodingUTF8); -} - -#else - -#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -// On iOS, we only support one platform -#define _CFBundleNumberOfPlatforms 1 -static CFStringRef _CFBundleSupportedPlatforms[_CFBundleNumberOfPlatforms] = { CFSTR("iphoneos") }; -#else -// On other platforms, we support the following platforms -#define _CFBundleNumberOfPlatforms 7 -static CFStringRef _CFBundleSupportedPlatforms[_CFBundleNumberOfPlatforms] = { CFSTR("iphoneos"), CFSTR("macos"), CFSTR("windows"), CFSTR("linux"), CFSTR("freebsd"), CFSTR("solaris"), CFSTR("hpux") }; -#endif - -#define _CFBundleNumberOfProducts 3 -static CFStringRef _CFBundleSupportedProducts[_CFBundleNumberOfProducts] = { CFSTR("iphone"), CFSTR("ipod"), CFSTR("ipad") }; - -#define _CFBundleNumberOfiPhoneOSPlatformProducts 3 -static CFStringRef _CFBundleSupportediPhoneOSPlatformProducts[_CFBundleNumberOfiPhoneOSPlatformProducts] = { CFSTR("iphone"), CFSTR("ipod"), CFSTR("ipad") }; - -__private_extern__ void _CFBundleResourcesInitialize() { } -#endif - -static CFStringRef platform = NULL; - -void _CFSetProductName(CFStringRef str) { - if (str) CFRetain(str); - platform = str; - // Note that the previous value is leaked, which is fine normally - // because the initial values would tend to be the constant strings - // below. That is required for thread-safety value due to the Get - // function [not being Copy]. It is also fine because people - // shouldn't be screwing around with this value casually. -} - -CF_EXPORT CFStringRef _CFGetProductName(void) { -#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - if (!platform) { - char buffer[256]; - memset(buffer, 0, sizeof(buffer)); - size_t buflen = sizeof(buffer); - int ret = sysctlbyname("hw.machine", buffer, &buflen, NULL, 0); - if (0 == ret || (-1 == ret && ENOMEM == errno)) { - if (6 <= buflen && 0 == memcmp(buffer, "iPhone", 6)) { - platform = CFSTR("iphone"); - } else if (4 <= buflen && 0 == memcmp(buffer, "iPod", 4)) { - platform = CFSTR("ipod"); - } else if (4 <= buflen && 0 == memcmp(buffer, "iPad", 4)) { - platform = CFSTR("ipad"); - } else { - const char *env = __CFgetenv("IPHONE_SIMULATOR_DEVICE"); - if (env) { - if (0 == strcmp(env, "iPhone")) { - platform = CFSTR("iphone"); - } else if (0 == strcmp(env, "iPad")) { - platform = CFSTR("ipad"); - } else { - // fallback, unrecognized IPHONE_SIMULATOR_DEVICE - } - } else { - // fallback, unrecognized hw.machine and no IPHONE_SIMULATOR_DEVICE - } - } - } - if (!platform) platform = CFSTR("iphone"); // fallback - } - return platform; -#endif - return CFSTR(""); -} - -// All new-style bundles will have these extensions. -CF_EXPORT CFStringRef _CFGetPlatformName(void) { -#if DEPLOYMENT_TARGET_MACOSX - return _CFBundleMacOSXPlatformName; -#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - return _CFBundleiPhoneOSPlatformName; -#elif DEPLOYMENT_TARGET_WINDOWS - return _CFBundleWindowsPlatformName; -#elif DEPLOYMENT_TARGET_SOLARIS - return _CFBundleSolarisPlatformName; -#elif DEPLOYMENT_TARGET_HPUX - return _CFBundleHPUXPlatformName; -#elif DEPLOYMENT_TARGET_LINUX - return _CFBundleLinuxPlatformName; -#elif DEPLOYMENT_TARGET_FREEBSD - return _CFBundleFreeBSDPlatformName; -#else -#error Unknown or unspecified DEPLOYMENT_TARGET -#endif -} - -CF_EXPORT CFStringRef _CFGetAlternatePlatformName(void) { -#if DEPLOYMENT_TARGET_MACOSX - return _CFBundleAlternateMacOSXPlatformName; -#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - return _CFBundleMacOSXPlatformName; -#elif DEPLOYMENT_TARGET_WINDOWS - return CFSTR(""); -#else -#error Unknown or unspecified DEPLOYMENT_TARGET -#endif -} - -static UniChar *_AppSupportUniChars1 = NULL; -static CFIndex _AppSupportLen1 = 0; -static UniChar *_AppSupportUniChars2 = NULL; -static CFIndex _AppSupportLen2 = 0; -static UniChar *_ResourcesUniChars = NULL; -static CFIndex _ResourcesLen = 0; -static UniChar *_PlatformUniChars = NULL; -static CFIndex _PlatformLen = 0; -static UniChar *_AlternatePlatformUniChars = NULL; -static CFIndex _AlternatePlatformLen = 0; -static UniChar *_LprojUniChars = NULL; -static CFIndex _LprojLen = 0; -static UniChar *_BaseUniChars = NULL; -static CFIndex _BaseLen; -static UniChar *_GlobalResourcesUniChars = NULL; -static CFIndex _GlobalResourcesLen = 0; -static UniChar *_InfoExtensionUniChars = NULL; -static CFIndex _InfoExtensionLen = 0; - -#if 0 -static UniChar _ResourceSuffix3[32]; -static CFIndex _ResourceSuffix3Len = 0; -#endif -static UniChar _ResourceSuffix2[16]; -static CFIndex _ResourceSuffix2Len = 0; -static UniChar _ResourceSuffix1[16]; -static CFIndex _ResourceSuffix1Len = 0; - -static void _CFBundleInitStaticUniCharBuffers(void) { - CFStringRef appSupportStr1 = _CFBundleSupportFilesDirectoryName1; - CFStringRef appSupportStr2 = _CFBundleSupportFilesDirectoryName2; - CFStringRef resourcesStr = _CFBundleResourcesDirectoryName; - CFStringRef platformStr = _CFGetPlatformName(); - CFStringRef alternatePlatformStr = _CFGetAlternatePlatformName(); - CFStringRef lprojStr = _CFBundleLprojExtension; - CFStringRef globalResourcesStr = _CFBundleNonLocalizedResourcesDirectoryName; - CFStringRef infoExtensionStr = _CFBundleInfoExtension; - CFStringRef baseStr = _CFBundleBaseDirectory; - - _AppSupportLen1 = CFStringGetLength(appSupportStr1); - _AppSupportLen2 = CFStringGetLength(appSupportStr2); - _ResourcesLen = CFStringGetLength(resourcesStr); - _PlatformLen = CFStringGetLength(platformStr); - _AlternatePlatformLen = CFStringGetLength(alternatePlatformStr); - _LprojLen = CFStringGetLength(lprojStr); - _GlobalResourcesLen = CFStringGetLength(globalResourcesStr); - _InfoExtensionLen = CFStringGetLength(infoExtensionStr); - _BaseLen = CFStringGetLength(baseStr); - - _AppSupportUniChars1 = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * (_AppSupportLen1 + _AppSupportLen2 + _ResourcesLen + _PlatformLen + _AlternatePlatformLen + _LprojLen + _GlobalResourcesLen + _InfoExtensionLen + _BaseLen), 0); - _AppSupportUniChars2 = _AppSupportUniChars1 + _AppSupportLen1; - _ResourcesUniChars = _AppSupportUniChars2 + _AppSupportLen2; - _PlatformUniChars = _ResourcesUniChars + _ResourcesLen; - _AlternatePlatformUniChars = _PlatformUniChars + _PlatformLen; - _LprojUniChars = _AlternatePlatformUniChars + _AlternatePlatformLen; - _GlobalResourcesUniChars = _LprojUniChars + _LprojLen; - _InfoExtensionUniChars = _GlobalResourcesUniChars + _GlobalResourcesLen; - _BaseUniChars = _InfoExtensionUniChars + _InfoExtensionLen; - - if (_AppSupportLen1 > 0) CFStringGetCharacters(appSupportStr1, CFRangeMake(0, _AppSupportLen1), _AppSupportUniChars1); - if (_AppSupportLen2 > 0) CFStringGetCharacters(appSupportStr2, CFRangeMake(0, _AppSupportLen2), _AppSupportUniChars2); - if (_ResourcesLen > 0) CFStringGetCharacters(resourcesStr, CFRangeMake(0, _ResourcesLen), _ResourcesUniChars); - if (_PlatformLen > 0) CFStringGetCharacters(platformStr, CFRangeMake(0, _PlatformLen), _PlatformUniChars); - if (_AlternatePlatformLen > 0) CFStringGetCharacters(alternatePlatformStr, CFRangeMake(0, _AlternatePlatformLen), _AlternatePlatformUniChars); - if (_LprojLen > 0) CFStringGetCharacters(lprojStr, CFRangeMake(0, _LprojLen), _LprojUniChars); - if (_GlobalResourcesLen > 0) CFStringGetCharacters(globalResourcesStr, CFRangeMake(0, _GlobalResourcesLen), _GlobalResourcesUniChars); - if (_InfoExtensionLen > 0) CFStringGetCharacters(infoExtensionStr, CFRangeMake(0, _InfoExtensionLen), _InfoExtensionUniChars); - if (_BaseLen > 0) CFStringGetCharacters(baseStr, CFRangeMake(0, _BaseLen), _BaseUniChars); - - _ResourceSuffix1Len = CFStringGetLength(platformStr); - if (_ResourceSuffix1Len > 0) _ResourceSuffix1[0] = '-'; - if (_ResourceSuffix1Len > 0) CFStringGetCharacters(platformStr, CFRangeMake(0, _ResourceSuffix1Len), _ResourceSuffix1 + 1); - if (_ResourceSuffix1Len > 0) _ResourceSuffix1Len++; - CFStringRef productStr = _CFGetProductName(); - if (CFEqual(productStr, CFSTR("ipod"))) { // For now, for resource lookups, hide ipod distinction and make it look for iphone resources - productStr = CFSTR("iphone"); - } - _ResourceSuffix2Len = CFStringGetLength(productStr); - if (_ResourceSuffix2Len > 0) _ResourceSuffix2[0] = '~'; - if (_ResourceSuffix2Len > 0) CFStringGetCharacters(productStr, CFRangeMake(0, _ResourceSuffix2Len), _ResourceSuffix2 + 1); - if (_ResourceSuffix2Len > 0) _ResourceSuffix2Len++; -#if 0 - if (_ResourceSuffix1Len > 1 && _ResourceSuffix2Len > 1) { - _ResourceSuffix3Len = _ResourceSuffix1Len + _ResourceSuffix2Len; - memmove(_ResourceSuffix3, _ResourceSuffix1, sizeof(UniChar) * _ResourceSuffix1Len); - memmove(_ResourceSuffix3 + _ResourceSuffix1Len, _ResourceSuffix2, sizeof(UniChar) * _ResourceSuffix2Len); - } -#endif -} - -CF_INLINE void _CFEnsureStaticBuffersInited(void) { - static dispatch_once_t once = 0; - dispatch_once(&once, ^{ - _CFBundleInitStaticUniCharBuffers(); - }); -} - -static CFSpinLock_t _cacheLock = CFSpinLockInit; -static CFMutableDictionaryRef _contentsCache = NULL; -static CFMutableDictionaryRef _directoryContentsCache = NULL; -static CFMutableDictionaryRef _unknownContentsCache = NULL; - -typedef enum { - _CFBundleAllContents = 0, - _CFBundleDirectoryContents = 1, - _CFBundleUnknownContents = 2 -} _CFBundleDirectoryContentsType; - -extern void _CFArraySortValues(CFMutableArrayRef array, CFComparatorFunction comparator, void *context); - -static CFArrayRef _CFBundleCopySortedDirectoryContentsAtPath(CFStringRef path, _CFBundleDirectoryContentsType contentsType) { - CFArrayRef result = NULL; - - if (!path) { - // Return an empty result. It's mutable because the other arrays returned from this function are mutable, so may as well go for maximum compatibility. - result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - return result; - } - - __CFSpinLock(&_cacheLock); - if (contentsType == _CFBundleUnknownContents) { - if (_unknownContentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(_unknownContentsCache, path); - } else if (contentsType == _CFBundleDirectoryContents) { - if (_directoryContentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(_directoryContentsCache, path); - } else { - if (_contentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(_contentsCache, path); - } - if (result) CFRetain(result); - __CFSpinUnlock(&_cacheLock); - - if (!result) { - Boolean tryToOpen = false, allDots = true; - char cpathBuff[CFMaxPathSize]; - CFIndex cpathLen = 0, idx, lastSlashIdx = 0; - CFMutableArrayRef contents = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks), directoryContents = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks), unknownContents = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFStringRef dirName, name; - - cpathBuff[0] = '\0'; - if (CFStringGetFileSystemRepresentation(path, cpathBuff, CFMaxPathSize)) { - tryToOpen = true; - cpathLen = strlen(cpathBuff); - - // First see whether we already know that the directory doesn't exist - for (idx = cpathLen; lastSlashIdx == 0 && idx-- > 0;) { - if (cpathBuff[idx] == PATH_SEP) lastSlashIdx = idx; - else if (cpathBuff[idx] != '.') allDots = false; - } - if (lastSlashIdx > 0 && lastSlashIdx + 1 < cpathLen && !allDots) { - cpathBuff[lastSlashIdx] = '\0'; - dirName = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, cpathBuff); - if (dirName) { - name = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, cpathBuff + lastSlashIdx + 1); - if (name) { - // ??? we might like to use _directoryContentsCache rather than _contentsCache here, but we cannot unless we resolve DT_LNKs below - CFArrayRef dirDirContents = NULL; - - __CFSpinLock(&_cacheLock); - if (_contentsCache) dirDirContents = (CFArrayRef)CFDictionaryGetValue(_contentsCache, dirName); - if (dirDirContents) { - Boolean foundIt = false; - CFIndex dirDirIdx, dirDirLength = CFArrayGetCount(dirDirContents); - for (dirDirIdx = 0; !foundIt && dirDirIdx < dirDirLength; dirDirIdx++) if (kCFCompareEqualTo == CFStringCompare(name, (CFStringRef)CFArrayGetValueAtIndex(dirDirContents, dirDirIdx), kCFCompareCaseInsensitive)) foundIt = true; - if (!foundIt) tryToOpen = false; - } - __CFSpinUnlock(&_cacheLock); - CFRelease(name); - } - CFRelease(dirName); - } - cpathBuff[lastSlashIdx] = PATH_SEP; - } - } -#if DEPLOYMENT_TARGET_WINDOWS - // Make sure there is room for the additional space we need in the win32 api - if (tryToOpen && cpathLen + 2 < CFMaxPathSize) { - WIN32_FIND_DATAW file; - HANDLE handle; - - cpathBuff[cpathLen++] = '\\'; - cpathBuff[cpathLen++] = '*'; - cpathBuff[cpathLen] = '\0'; - - // Convert UTF8 buffer to windows appropriate UTF-16LE - // Get the real length of the string in UTF16 characters - CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, cpathBuff, kCFStringEncodingUTF8); - cpathLen = CFStringGetLength(cfStr); - // Allocate a wide buffer to hold the converted string, including space for a NULL terminator - wchar_t *wideBuf = (wchar_t *)malloc((cpathLen + 1) * sizeof(wchar_t)); - // Copy the string into the buffer and terminate - CFStringGetCharacters(cfStr, CFRangeMake(0, cpathLen), (UniChar *)wideBuf); - wideBuf[cpathLen] = 0; - CFRelease(cfStr); - - handle = FindFirstFileW(wideBuf, (LPWIN32_FIND_DATAW)&file); - if (handle != INVALID_HANDLE_VALUE) { - do { - CFIndex nameLen = wcslen(file.cFileName); - if (0 == nameLen || ('.' == file.cFileName[0] && (1 == nameLen || (2 == nameLen && '.' == file.cFileName[1]) || '_' == file.cFileName[1]))) continue; - name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const uint8_t *)file.cFileName, nameLen * sizeof(wchar_t), kCFStringEncodingUTF16, NO); - if (name) { - CFArrayAppendValue(contents, name); - if (file.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { - CFArrayAppendValue(directoryContents, name); - } /* else if (file.dwFileAttributes == DT_UNKNOWN) { - CFArrayAppendValue(unknownContents, name); - } */ - CFRelease(name); - } - } while (FindNextFileW(handle, &file)); - - FindClose(handle); - } - free(wideBuf); - } -#else - DIR *dirp = NULL; - struct dirent *dent; - if (tryToOpen && (dirp = opendir(cpathBuff))) { - while ((dent = readdir(dirp))) { - CFIndex nameLen = dent->d_namlen; - if (0 == nameLen || 0 == dent->d_fileno || ('.' == dent->d_name[0] && (1 == nameLen || (2 == nameLen && '.' == dent->d_name[1]) || '_' == dent->d_name[1]))) continue; - name = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dent->d_name); - if (name) { - // ??? should we follow links for DT_LNK? unless we do, results are approximate, but for performance reasons we do not - // ??? likewise for DT_UNKNOWN - // ??? the utility of distinguishing directories from other contents is somewhat doubtful anyway - CFArrayAppendValue(contents, name); - if (dent->d_type == DT_DIR) { - CFArrayAppendValue(directoryContents, name); - } else if (dent->d_type == DT_UNKNOWN) { - CFArrayAppendValue(unknownContents, name); - } - CFRelease(name); - } - } - (void)closedir(dirp); - } -#endif - - _CFArraySortValues(contents, (CFComparatorFunction)CFStringCompare, NULL); - _CFArraySortValues(directoryContents, (CFComparatorFunction)CFStringCompare, NULL); - _CFArraySortValues(unknownContents, (CFComparatorFunction)CFStringCompare, NULL); - - __CFSpinLock(&_cacheLock); - if (!_contentsCache) _contentsCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, READ_DIRECTORIES_CACHE_CAPACITY, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (READ_DIRECTORIES_CACHE_CAPACITY <= CFDictionaryGetCount(_contentsCache)) CFDictionaryRemoveAllValues(_contentsCache); - CFDictionaryAddValue(_contentsCache, path, contents); - - if (!_directoryContentsCache) _directoryContentsCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, READ_DIRECTORIES_CACHE_CAPACITY, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (READ_DIRECTORIES_CACHE_CAPACITY <= CFDictionaryGetCount(_directoryContentsCache)) CFDictionaryRemoveAllValues(_directoryContentsCache); - CFDictionaryAddValue(_directoryContentsCache, path, directoryContents); - - if (!_unknownContentsCache) _unknownContentsCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, READ_DIRECTORIES_CACHE_CAPACITY, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (READ_DIRECTORIES_CACHE_CAPACITY <= CFDictionaryGetCount(_unknownContentsCache)) CFDictionaryRemoveAllValues(_unknownContentsCache); - CFDictionaryAddValue(_unknownContentsCache, path, unknownContents); - - if (contentsType == _CFBundleUnknownContents) { - result = (CFArrayRef)CFRetain(unknownContents); - } else if (contentsType == _CFBundleDirectoryContents) { - result = (CFArrayRef)CFRetain(directoryContents); - } else { - result = (CFArrayRef)CFRetain(contents); - } - - CFRelease(contents); - CFRelease(directoryContents); - CFRelease(unknownContents); - __CFSpinUnlock(&_cacheLock); - } - return result; -} - -static void _CFBundleFlushContentsCaches(void) { - __CFSpinLock(&_cacheLock); - if (_contentsCache) CFDictionaryRemoveAllValues(_contentsCache); - if (_directoryContentsCache) CFDictionaryRemoveAllValues(_directoryContentsCache); - if (_unknownContentsCache) CFDictionaryRemoveAllValues(_unknownContentsCache); - __CFSpinUnlock(&_cacheLock); -} - -static void _CFBundleFlushContentsCacheForPath(CFMutableDictionaryRef cache, CFStringRef path) { - CFStringRef keys[READ_DIRECTORIES_CACHE_CAPACITY]; - unsigned i, count = CFDictionaryGetCount(cache); - if (count <= READ_DIRECTORIES_CACHE_CAPACITY) { - CFDictionaryGetKeysAndValues(cache, (const void **)keys, NULL); - for (i = 0; i < count; i++) { - if (CFStringFindWithOptions(keys[i], path, CFRangeMake(0, CFStringGetLength(keys[i])), kCFCompareAnchored|kCFCompareCaseInsensitive, NULL)) CFDictionaryRemoveValue(cache, keys[i]); - } - } -} - -static void _CFBundleFlushContentsCachesForPath(CFStringRef path) { - __CFSpinLock(&_cacheLock); - if (_contentsCache) _CFBundleFlushContentsCacheForPath(_contentsCache, path); - if (_directoryContentsCache) _CFBundleFlushContentsCacheForPath(_directoryContentsCache, path); - if (_unknownContentsCache) _CFBundleFlushContentsCacheForPath(_unknownContentsCache, path); - __CFSpinUnlock(&_cacheLock); -} +#pragma mark - +#pragma mark Directory Contents and Caches -CF_EXPORT void _CFBundleFlushCachesForURL(CFURLRef url) { - CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url); - CFStringRef path = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - _CFBundleFlushContentsCachesForPath(path); - CFRelease(path); - CFRelease(absoluteURL); -} +// These are here for compatibility, but they do nothing anymore +CF_EXPORT void _CFBundleFlushCachesForURL(CFURLRef url) { } +CF_EXPORT void _CFBundleFlushCaches(void) { } -CF_EXPORT void _CFBundleFlushCaches(void) { - _CFBundleFlushContentsCaches(); -} +#pragma mark - +#pragma mark Resource URL Lookup static inline Boolean _CFIsResourceCommon(char *path, Boolean *isDir) { Boolean exists; @@ -531,608 +92,58 @@ static inline Boolean _CFIsResourceCommon(char *path, Boolean *isDir) { return false; } -__private_extern__ Boolean _CFIsResourceAtURL(CFURLRef url, Boolean *isDir) { +CF_PRIVATE Boolean _CFIsResourceAtURL(CFURLRef url, Boolean *isDir) { char path[CFMaxPathSize]; if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathLength)) return false; return _CFIsResourceCommon(path, isDir); } -__private_extern__ Boolean _CFIsResourceAtPath(CFStringRef path, Boolean *isDir) { +CF_PRIVATE Boolean _CFIsResourceAtPath(CFStringRef path, Boolean *isDir) { char pathBuf[CFMaxPathSize]; if (!CFStringGetFileSystemRepresentation(path, pathBuf, CFMaxPathSize)) return false; return _CFIsResourceCommon(pathBuf, isDir); } -__private_extern__ void _CFBundleSetResourceDir(UniChar *buffer, CFIndex *currLen, CFIndex maxLen, uint8_t version){ + +static CFStringRef _CFBundleGetResourceDirForVersion(uint8_t version) { if (1 == version) { - _CFAppendPathComponent(buffer, currLen, maxLen, _AppSupportUniChars1, _AppSupportLen1); + return _CFBundleSupportFilesDirectoryName1WithResources; } else if (2 == version) { - _CFAppendPathComponent(buffer, currLen, maxLen, _AppSupportUniChars2, _AppSupportLen2); - } - if (0 == version || 1 == version || 2 == version) _CFAppendPathComponent(buffer, currLen, maxLen, _ResourcesUniChars, _ResourcesLen); -} - -static CFArrayRef _CFCopyTypesForSearchBundleDirectory(CFAllocatorRef alloc, UniChar *pathUniChars, CFIndex pathLen, UniChar *nameUniChars, CFIndex nameLen, CFArrayRef resTypes, CFMutableStringRef cheapStr, CFMutableStringRef tmpString, uint8_t version) { - CFMutableArrayRef result = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks); - CFArrayRef contents; - CFRange contentsRange, resultRange = CFRangeMake(0, 0); - CFIndex dirPathLen = pathLen, numResTypes = CFArrayGetCount(resTypes), i, j; - - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, dirPathLen, dirPathLen); - CFStringReplaceAll(cheapStr, tmpString); - //fprintf(stderr, "looking in ");CFShow(cheapStr); - contents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleAllContents); - contentsRange = CFRangeMake(0, CFArrayGetCount(contents)); - - CFStringSetExternalCharactersNoCopy(tmpString, nameUniChars, nameLen, nameLen); - CFStringReplaceAll(cheapStr, tmpString); - for (i = 0; i < contentsRange.length; i++) { - CFStringRef content = (CFStringRef)CFArrayGetValueAtIndex(contents, i); - if (CFStringHasPrefix(content, cheapStr)) { - //fprintf(stderr, "found ");CFShow(content); - for (j = 0; j < numResTypes; j++) { - CFStringRef resType = (CFStringRef)CFArrayGetValueAtIndex(resTypes, j); - if (!CFArrayContainsValue(result, resultRange, resType) && CFStringHasSuffix(content, resType)) { - CFArrayAppendValue(result, resType); - resultRange.length = CFArrayGetCount(result); - } - } - } - } - //fprintf(stderr, "result ");CFShow(result); - CFRelease(contents); - return result; -} - -#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -static void _CFSearchBundleDirectory2(CFAllocatorRef alloc, CFMutableArrayRef result, UniChar *pathUniChars, CFIndex pathLen, UniChar *nameUniChars, CFIndex nameLen, UniChar *typeUniChars, CFIndex typeLen, CFMutableStringRef cheapStr, CFMutableStringRef tmpString, uint8_t version) { - // pathUniChars is the full path to the directory we are searching. - // nameUniChars is what we are looking for. - // typeUniChars is the type we are looking for. - // platformUniChars is the platform name. - // cheapStr is available for our use for whatever we want. - // URLs for found resources get added to result. - - Boolean appendSucceeded = true; - if (nameLen > 0) appendSucceeded = _CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, nameUniChars, nameLen); - if (! appendSucceeded) return; - CFIndex savedPathLen = pathLen; - - // Try in order: - // NAME-PLATFORM~PRODUCT.TYPE (disabled for now) - // NAME~PRODUCT.TYPE - // NAME-PLATFORM.TYPE (disabled for now) - // NAME.TYPE - -#if 0 - appendSucceeded = (pathLen + _ResourceSuffix3Len < CFMaxPathSize); - if (appendSucceeded) { - memmove(pathUniChars + pathLen, _ResourceSuffix3, _ResourceSuffix3Len * sizeof(UniChar)); - pathLen += _ResourceSuffix3Len; - } - if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen); - if (appendSucceeded) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - Boolean Found = false, IsDir = false; - Found = _CFIsResourceAtPath(cheapStr, &IsDir); - if (Found) { - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, IsDir); - CFArrayAppendValue(result, url); - CFRelease(url); - return; - } - } -#endif - - pathLen = savedPathLen; - appendSucceeded = (pathLen + _ResourceSuffix2Len < CFMaxPathSize); - if (appendSucceeded) { - memmove(pathUniChars + pathLen, _ResourceSuffix2, _ResourceSuffix2Len * sizeof(UniChar)); - pathLen += _ResourceSuffix2Len; - } - if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen); - if (appendSucceeded) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - Boolean Found = false, IsDir = false; - Found = _CFIsResourceAtPath(cheapStr, &IsDir); - if (Found) { - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, IsDir); - CFArrayAppendValue(result, url); - CFRelease(url); - return; - } - } - -#if 0 - pathLen = savedPathLen; - appendSucceeded = (pathLen + _ResourceSuffix1Len < CFMaxPathSize); - if (appendSucceeded) { - memmove(pathUniChars + pathLen, _ResourceSuffix1, _ResourceSuffix1Len * sizeof(UniChar)); - pathLen += _ResourceSuffix1Len; - } - if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen); - if (appendSucceeded) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - Boolean Found = false, IsDir = false; - Found = _CFIsResourceAtPath(cheapStr, &IsDir); - if (Found) { - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, IsDir); - CFArrayAppendValue(result, url); - CFRelease(url); - return; - } - } -#endif - - pathLen = savedPathLen; - appendSucceeded = true; - if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen); - if (appendSucceeded) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - Boolean Found = false, IsDir = false; - Found = _CFIsResourceAtPath(cheapStr, &IsDir); - if (Found) { - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, IsDir); - CFArrayAppendValue(result, url); - CFRelease(url); - return; - } - } -} -#endif - -static void _CFSearchBundleDirectory(CFAllocatorRef alloc, CFMutableArrayRef result, UniChar *pathUniChars, CFIndex pathLen, UniChar *nameUniChars, CFIndex nameLen, UniChar *typeUniChars, CFIndex typeLen, CFMutableStringRef cheapStr, CFMutableStringRef tmpString, uint8_t version) { - -#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - _CFSearchBundleDirectory2(alloc, result, pathUniChars, pathLen, nameUniChars, nameLen, typeUniChars, typeLen, cheapStr, tmpString, version); -#else - // pathUniChars is the full path to the directory we are searching. - // nameUniChars is what we are looking for. - // typeUniChars is the type we are looking for. - // platformUniChars is the platform name. - // cheapStr is available for our use for whatever we want. - // URLs for found resources get added to result. - CFIndex savedPathLen; - Boolean appendSucceeded = true, platformGenericFound = false, platformSpecificFound = false, platformGenericIsDir = false, platformSpecificIsDir = false; - Boolean platformGenericIsUnknown = false, platformSpecificIsUnknown = false; - CFStringRef platformGenericStr = NULL; - - CFIndex dirPathLen = pathLen; - CFArrayRef contents, directoryContents, unknownContents; - CFRange contentsRange, directoryContentsRange, unknownContentsRange; - - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, dirPathLen, dirPathLen); - CFStringReplaceAll(cheapStr, tmpString); - //fprintf(stderr, "looking in ");CFShow(cheapStr); - contents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleAllContents); - contentsRange = CFRangeMake(0, CFArrayGetCount(contents)); - directoryContents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleDirectoryContents); - directoryContentsRange = CFRangeMake(0, CFArrayGetCount(directoryContents)); - unknownContents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleUnknownContents); - unknownContentsRange = CFRangeMake(0, CFArrayGetCount(unknownContents)); - - if (nameLen > 0) appendSucceeded = _CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, nameUniChars, nameLen); - savedPathLen = pathLen; - if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen); - if (appendSucceeded) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + dirPathLen + 1, pathLen - dirPathLen - 1, pathLen - dirPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - platformGenericFound = _CFBundleSortedArrayContains(contents, cheapStr); - platformGenericIsDir = _CFBundleSortedArrayContains(directoryContents, cheapStr); - platformGenericIsUnknown = _CFBundleSortedArrayContains(unknownContents, cheapStr); - //fprintf(stderr, "looking for ");CFShow(cheapStr);if (platformGenericFound) fprintf(stderr, "found it\n"); if (platformGenericIsDir) fprintf(stderr, "a directory\n"); - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - if (platformGenericFound && platformGenericIsUnknown) { - (void)_CFIsResourceAtPath(cheapStr, &platformGenericIsDir); - //if (platformGenericIsDir) fprintf(stderr, "a directory after all\n"); else fprintf(stderr, "not a directory after all\n"); - } - } - - // Check for platform specific. - if (platformGenericFound) { - platformGenericStr = (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, cheapStr); - if (!platformSpecificFound && (_PlatformLen > 0)) { - pathLen = savedPathLen; - pathUniChars[pathLen++] = (UniChar)'-'; - memmove(pathUniChars + pathLen, _PlatformUniChars, _PlatformLen * sizeof(UniChar)); - pathLen += _PlatformLen; - if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen); - if (appendSucceeded) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + dirPathLen + 1, pathLen - dirPathLen - 1, pathLen - dirPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - platformSpecificFound = _CFBundleSortedArrayContains(contents, cheapStr); - platformSpecificIsDir = _CFBundleSortedArrayContains(directoryContents, cheapStr); - platformSpecificIsUnknown = _CFBundleSortedArrayContains(unknownContents, cheapStr); - //fprintf(stderr, "looking for ");CFShow(cheapStr);if (platformSpecificFound) fprintf(stderr, "found it\n"); if (platformSpecificIsDir) fprintf(stderr, "a directory\n"); - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - if (platformSpecificFound && platformSpecificIsUnknown) { - (void)_CFIsResourceAtPath(cheapStr, &platformSpecificIsDir); - //if (platformSpecificIsDir) fprintf(stderr, "a directory after all\n"); else fprintf(stderr, "not a directory after all\n"); - } - } - } - } - if (platformSpecificFound) { - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, platformSpecificIsDir); - CFArrayAppendValue(result, url); - CFRelease(url); - } else if (platformGenericFound) { - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, platformGenericStr ? platformGenericStr : cheapStr, PLATFORM_PATH_STYLE, platformGenericIsDir); - CFArrayAppendValue(result, url); - CFRelease(url); - } - if (platformGenericStr) CFRelease(platformGenericStr); - CFRelease(contents); - CFRelease(directoryContents); - CFRelease(unknownContents); -#endif -} - -static void _CFSearchBundleDirectoryWithPredicate(CFAllocatorRef alloc, CFMutableArrayRef result, UniChar *pathUniChars, CFIndex dirPathLen, Boolean (^predicate)(CFStringRef filename, Boolean *stop), CFMutableStringRef cheapStr, CFMutableStringRef tmpString, Boolean *stopLooking, uint8_t version) { - - // pathUniChars is the full path to the directory we are searching. - // platformUniChars is the platform name. - // predicate is a block that evaluates a given filename to see if it's a match. - // cheapStr is available for our use for whatever we want. - // URLs for found resources get added to result. - - // get the contents of the directory - CFArrayRef contents, directoryContents, unknownContents; - CFRange contentsRange; - - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, dirPathLen, dirPathLen); - CFStringReplaceAll(cheapStr, tmpString); - - if (!_CFAppendTrailingPathSlash(pathUniChars, &dirPathLen, CFMaxPathSize)) { - return; - } - - //fprintf(stderr, "looking in ");CFShow(cheapStr); - contents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleAllContents); - contentsRange = CFRangeMake(0, CFArrayGetCount(contents)); - directoryContents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleDirectoryContents); - unknownContents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleUnknownContents); - - // scan directory contents for matches against predicate - for (int i = 0; i < contentsRange.length; i++) { - CFStringRef candidateFilename = (CFStringRef)CFArrayGetValueAtIndex(contents, i); - if (predicate(candidateFilename, stopLooking)) { - // we want this resource, though possibly a platform specific version of it - // unpack candidateFilename string into pathUniChars after verifying that we have enough space in the buffer - CFIndex candidateFilenameLength = CFStringGetLength(candidateFilename); - if ((dirPathLen + candidateFilenameLength < CFMaxPathSize)) { - CFStringGetCharacters(candidateFilename, CFRangeMake(0, candidateFilenameLength), pathUniChars + dirPathLen); - - // is there a platform specific version available? if so update pathUniChars to contain it and candidateFilenameLength to describe its length. - static const int platformSeparatorLen = 1; // the length of '-', as appears in foo-macos.tiff. sugar to make the following easier to read. - if (_PlatformLen && (dirPathLen + candidateFilenameLength + platformSeparatorLen + _PlatformLen < CFMaxPathSize)) { - CFIndex candidateFilenameWithoutExtensionLen = _CFLengthAfterDeletingPathExtension(pathUniChars + dirPathLen, candidateFilenameLength); - CFIndex extensionLen = candidateFilenameLength - candidateFilenameWithoutExtensionLen; - // shift the extension over to make space for the platform - memmove(pathUniChars + dirPathLen + candidateFilenameWithoutExtensionLen + platformSeparatorLen + _PlatformLen, pathUniChars + dirPathLen + candidateFilenameWithoutExtensionLen, extensionLen * sizeof(UniChar)); - // write the platform into the middle of the string - pathUniChars[dirPathLen + candidateFilenameWithoutExtensionLen] = (UniChar)'-'; - memcpy(pathUniChars + dirPathLen + candidateFilenameWithoutExtensionLen + platformSeparatorLen, _PlatformUniChars, _PlatformLen * sizeof(UniChar)); - // pack it up as a CFStringRef - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + dirPathLen, candidateFilenameLength + platformSeparatorLen + _PlatformLen, candidateFilenameLength + _PlatformLen); - CFStringReplaceAll(cheapStr, tmpString); - // is the platform specialized version there? - if (_CFBundleSortedArrayContains(contents, cheapStr)) { - // woo. update the candidateFilenameLength. we'll update the candidateFilename too for consistency, but we don't actually use it again. - // the pathUniChars now contains the full path to the file - candidateFilename = cheapStr; - candidateFilenameLength = candidateFilenameLength + _PlatformLen + platformSeparatorLen; - } else { - // nope, no platform specific resource. Put the pathUniChars back how they were before, without the platform. - memmove(pathUniChars + dirPathLen + candidateFilenameWithoutExtensionLen, pathUniChars + dirPathLen + candidateFilenameWithoutExtensionLen + platformSeparatorLen + _PlatformLen, extensionLen * sizeof(UniChar)); - } - } - - // get the full path into cheapStr - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, dirPathLen + candidateFilenameLength, dirPathLen + candidateFilenameLength); - CFStringReplaceAll(cheapStr, tmpString); - - // is the resource a directory? we need to know so that we can avoid file access when making a URL. - Boolean isDir = 0; - if (_CFBundleSortedArrayContains(directoryContents, cheapStr)) { - isDir = 1; - } else if (_CFBundleSortedArrayContains(unknownContents, cheapStr)) { - _CFIsResourceAtPath(cheapStr, &isDir); - } - - CFURLRef url = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, isDir); - CFArrayAppendValue(result, url); - CFRelease(url); - } - } - - if (*stopLooking) break; - } - - CFRelease(contents); - CFRelease(directoryContents); - CFRelease(unknownContents); -} - - -static void _CFFindBundleResourcesInRawDir(CFAllocatorRef alloc, UniChar *workingUniChars, CFIndex workingLen, UniChar *nameUniChars, CFIndex nameLen, CFArrayRef resTypes, CFIndex limit, Boolean *stopLooking, Boolean (^predicate)(CFStringRef filename, Boolean *stop), uint8_t version, CFMutableStringRef cheapStr, CFMutableStringRef tmpString, CFMutableArrayRef result) { - if (predicate) { - _CFSearchBundleDirectoryWithPredicate(alloc, result, workingUniChars, workingLen, predicate, cheapStr, tmpString, stopLooking, version); - return; - } - if (nameLen > 0) { - // If we have a resName, just call the search API. We may have to loop over the resTypes. - if (!resTypes) { - _CFSearchBundleDirectory(alloc, result, workingUniChars, workingLen, nameUniChars, nameLen, NULL, 0, cheapStr, tmpString, version); - } else { - CFArrayRef subResTypes = resTypes; - Boolean releaseSubResTypes = false; - CFIndex i, c = CFArrayGetCount(resTypes); - if (c > 2) { - // this is an optimization we employ when searching for large numbers of types, if the directory contents are available - // we scan the directory contents and restrict the list of resTypes to the types that might actually occur with the specified name - subResTypes = _CFCopyTypesForSearchBundleDirectory(alloc, workingUniChars, workingLen, nameUniChars, nameLen, resTypes, cheapStr, tmpString, version); - c = CFArrayGetCount(subResTypes); - releaseSubResTypes = true; - } - for (i = 0; i < c; i++) { - CFStringRef curType = (CFStringRef)CFArrayGetValueAtIndex(subResTypes, i); - CFIndex typeLen = CFStringGetLength(curType); - STACK_BUFFER_DECL(UniChar, typeChars, typeLen); - CFStringGetCharacters(curType, CFRangeMake(0, typeLen), typeChars); - _CFSearchBundleDirectory(alloc, result, workingUniChars, workingLen, nameUniChars, nameLen, typeChars, typeLen, cheapStr, tmpString, version); - if (limit <= CFArrayGetCount(result)) break; - } - if (releaseSubResTypes) CFRelease(subResTypes); - } - } else { - // If we have no resName, do it by hand. We may have to loop over the resTypes. - char cpathBuff[CFMaxPathSize]; - CFIndex cpathLen; - CFMutableArrayRef children; - - CFStringSetExternalCharactersNoCopy(tmpString, workingUniChars, workingLen, workingLen); - if (!CFStringGetFileSystemRepresentation(tmpString, cpathBuff, CFMaxPathSize)) return; - cpathLen = strlen(cpathBuff); - - if (!resTypes) { - // ??? should this use _CFBundleCopyDirectoryContentsAtPath? - children = _CFContentsOfDirectory(alloc, cpathBuff, NULL, NULL, NULL); - if (children) { - CFIndex childIndex, childCount = CFArrayGetCount(children); - for (childIndex = 0; childIndex < childCount; childIndex++) CFArrayAppendValue(result, CFArrayGetValueAtIndex(children, childIndex)); - CFRelease(children); - } - } else { - CFIndex i, c = CFArrayGetCount(resTypes); - for (i = 0; i < c; i++) { - CFStringRef curType = (CFStringRef)CFArrayGetValueAtIndex(resTypes, i); - - // ??? should this use _CFBundleCopyDirectoryContentsAtPath? - children = _CFContentsOfDirectory(alloc, cpathBuff, NULL, NULL, curType); - if (children) { - CFIndex childIndex, childCount = CFArrayGetCount(children); - for (childIndex = 0; childIndex < childCount; childIndex++) CFArrayAppendValue(result, CFArrayGetValueAtIndex(children, childIndex)); - CFRelease(children); - } - if (limit <= CFArrayGetCount(result)) break; - } - } + return _CFBundleSupportFilesDirectoryName2WithResources; + } else if (0 == version) { + return _CFBundleResourcesDirectoryName; } + return CFSTR(""); } - -static void _CFFindBundleResourcesInResourcesDir(CFAllocatorRef alloc, UniChar *workingUniChars, CFIndex workingLen, UniChar *subDirUniChars, CFIndex subDirLen, CFArrayRef searchLanguages, UniChar *nameUniChars, CFIndex nameLen, CFArrayRef resTypes, CFIndex limit, Boolean (^predicate)(CFStringRef filename, Boolean *stop), uint8_t version, CFMutableStringRef cheapStr, CFMutableStringRef tmpString, CFMutableArrayRef result) { - CFIndex savedWorkingLen = workingLen; - Boolean stopLooking = false; // for predicate based-queries, we set stopLooking instead of using a limit - // Look directly in the directory specified in workingUniChars. as if it is a Resources directory. +CF_PRIVATE void _CFBundleAppendResourceDir(CFMutableStringRef path, uint8_t version) { if (1 == version) { - // Add the non-localized resource directory. - Boolean appendSucceeded = _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _GlobalResourcesUniChars, _GlobalResourcesLen); - if (appendSucceeded && subDirLen > 0) appendSucceeded = _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, subDirUniChars, subDirLen); - if (appendSucceeded) _CFFindBundleResourcesInRawDir(alloc, workingUniChars, workingLen, nameUniChars, nameLen, resTypes, limit, &stopLooking, predicate, version, cheapStr, tmpString, result); - // Strip the non-localized resource directory. - workingLen = savedWorkingLen; - } - - if (CFArrayGetCount(result) < limit && !stopLooking) { - Boolean appendSucceeded = true; - if (subDirLen > 0) appendSucceeded = _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, subDirUniChars, subDirLen); - if (appendSucceeded) _CFFindBundleResourcesInRawDir(alloc, workingUniChars, workingLen, nameUniChars, nameLen, resTypes, limit, &stopLooking, predicate, version, cheapStr, tmpString, result); - } - - // Now search the first localized resources (user language). - CFIndex langCount = (searchLanguages ? CFArrayGetCount(searchLanguages) : 0); - UniChar curLangUniChars[255]; - - workingLen = savedWorkingLen; - if (CFArrayGetCount(result) < limit && !stopLooking && langCount >= 1) { - CFIndex numResults = CFArrayGetCount(result); - CFStringRef curLangStr = (CFStringRef)CFArrayGetValueAtIndex(searchLanguages, 0); - CFIndex curLangLen = MIN(CFStringGetLength(curLangStr), 255); - CFStringGetCharacters(curLangStr, CFRangeMake(0, curLangLen), curLangUniChars); - - savedWorkingLen = workingLen; - if (_CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, curLangUniChars, curLangLen) && - _CFAppendPathExtension(workingUniChars, &workingLen, CFMaxPathSize, _LprojUniChars, _LprojLen) && - (subDirLen == 0 || (subDirLen > 0 && _CFAppendPathExtension(workingUniChars, &workingLen, CFMaxPathSize, subDirUniChars, subDirLen)))) { - - _CFFindBundleResourcesInRawDir(alloc, workingUniChars, workingLen, nameUniChars, nameLen, resTypes, limit, &stopLooking, predicate, version, cheapStr, tmpString, result); - - if (CFArrayGetCount(result) != numResults) { - // We found resources in a language we already searched. Don't look any farther. - // We also don't need to check the limit, since if the count changed at all, we are bailing. - return; - } - } - } - - workingLen = savedWorkingLen; - // Now search the Base.lproj directory - if (CFArrayGetCount(result) < limit && !stopLooking) { - CFIndex numResults = CFArrayGetCount(result); - savedWorkingLen = workingLen; - if (_CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _BaseUniChars, _BaseLen) && - _CFAppendPathExtension(workingUniChars, &workingLen, CFMaxPathSize, _LprojUniChars, _LprojLen) && - (subDirLen == 0 || (subDirLen > 0 && _CFAppendPathExtension(workingUniChars, &workingLen, CFMaxPathSize, subDirUniChars, subDirLen)))) { - - _CFFindBundleResourcesInRawDir(alloc, workingUniChars, workingLen, nameUniChars, nameLen, resTypes, limit, &stopLooking, predicate, version, cheapStr, tmpString, result); - - if (CFArrayGetCount(result) != numResults) { - // We found resources in a language we already searched. Don't look any farther. - // We also don't need to check the limit, since if the count changed at all, we are bailing. - return; - } - } - } - - // Now search remaining localized resources (developer language) - workingLen = savedWorkingLen; - if (CFArrayGetCount(result) < limit && !stopLooking && langCount >= 2) { - // MF:??? OK to hard-wire this length? - CFIndex numResults = CFArrayGetCount(result); - - // start after 1st language - for (CFIndex langIndex = 1; langIndex < langCount; langIndex++) { - CFStringRef curLangStr = (CFStringRef)CFArrayGetValueAtIndex(searchLanguages, langIndex); - CFIndex curLangLen = MIN(CFStringGetLength(curLangStr), 255); - CFStringGetCharacters(curLangStr, CFRangeMake(0, curLangLen), curLangUniChars); - savedWorkingLen = workingLen; - if (!_CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, curLangUniChars, curLangLen)) { - workingLen = savedWorkingLen; - continue; - } - if (!_CFAppendPathExtension(workingUniChars, &workingLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) { - workingLen = savedWorkingLen; - continue; - } - if (subDirLen > 0) { - if (!_CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, subDirUniChars, subDirLen)) { - workingLen = savedWorkingLen; - continue; - } - } - _CFFindBundleResourcesInRawDir(alloc, workingUniChars, workingLen, nameUniChars, nameLen, resTypes, limit, &stopLooking, predicate, version, cheapStr, tmpString, result); - - // Back off this lproj component - workingLen = savedWorkingLen; - if (CFArrayGetCount(result) != numResults) { - // We found resources in a language we already searched. Don't look any farther. - // We also don't need to check the limit, since if the count changed at all, we are bailing. - break; - } - } - } -} - -CFArrayRef _CFFindBundleResources(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef subDirName, CFArrayRef searchLanguages, CFStringRef resName, CFArrayRef resTypes, CFIndex limit, Boolean (^predicate)(CFStringRef filename, Boolean *stop), uint8_t version) { - CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - - // Build an absolute path to the base directory. - // If no URL was passed, we get it from the bundle. - CFURLRef baseURL = bundleURL ? (CFURLRef)CFRetain(bundleURL) : (bundle ? CFBundleCopyBundleURL(bundle) : NULL); - CFURLRef absoluteURL = baseURL ? CFURLCopyAbsoluteURL(baseURL) : NULL; - CFStringRef basePath = absoluteURL ? CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE) : NULL; - if (absoluteURL) CFRelease(absoluteURL); - if (baseURL) CFRelease(baseURL); - baseURL = absoluteURL = bundleURL = NULL; - bundle = NULL; - // bundle and bundleURL arguments are not used any further - - if (!basePath) return result; - - - UniChar *workingUniChars, *nameUniChars, *subDirUniChars; - CFIndex nameLen = 0; - CFIndex workingLen, savedWorkingLen; - CFMutableStringRef cheapStr, tmpString; - - if (resName) { - char buff[CFMaxPathSize]; - CFStringRef newResName = NULL; - if (CFStringGetFileSystemRepresentation(resName, buff, CFMaxPathSize)) newResName = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); - resName = newResName ? newResName : (CFStringRef)CFRetain(resName); - nameLen = CFStringGetLength(resName); + // /path/to/bundle/Support Files/ + CFStringAppend(path, _CFBundleSupportFilesDirectoryName1); + _CFAppendTrailingPathSlash2(path); + } else if (2 == version) { + // /path/to/bundle/Contents/ + CFStringAppend(path, _CFBundleSupportFilesDirectoryName2); + _CFAppendTrailingPathSlash2(path); } - - // Init the one-time-only unichar buffers. - _CFEnsureStaticBuffersInited(); - - // Build UniChar buffers for some of the string pieces we need. - CFIndex subDirLen = (subDirName ? CFStringGetLength(subDirName) : 0); - nameUniChars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * (nameLen + subDirLen + CFMaxPathSize), 0); - if (nameUniChars) { - subDirUniChars = nameUniChars + nameLen; - workingUniChars = subDirUniChars + subDirLen; - - if (nameLen > 0) CFStringGetCharacters(resName, CFRangeMake(0, nameLen), nameUniChars); - if (subDirLen > 0) CFStringGetCharacters(subDirName, CFRangeMake(0, subDirLen), subDirUniChars); - - if ((workingLen = CFStringGetLength(basePath)) > 0) CFStringGetCharacters(basePath, CFRangeMake(0, workingLen), workingUniChars); - savedWorkingLen = workingLen; - _CFBundleSetResourceDir(workingUniChars, &workingLen, CFMaxPathSize, version); - - // both of these used for temp string operations, for slightly different purposes, where each type is appropriate - cheapStr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - _CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize); - tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull); - - _CFFindBundleResourcesInResourcesDir(kCFAllocatorSystemDefault, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, predicate, version, cheapStr, tmpString, result); - - CFRelease(cheapStr); - CFRelease(tmpString); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, nameUniChars); + if (0 == version || 1 == version || 2 == version) { + // /path/to/bundle//Resources + CFStringAppend(path, _CFBundleResourcesDirectoryName); } - if (resName) CFRelease(resName); - if (basePath) CFRelease(basePath); - return result; -} - -__private_extern__ CFArrayRef _CFFindBundleResourcesNoBlock(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef subDirName, CFArrayRef searchLanguages, CFStringRef resName, CFArrayRef resTypes, CFIndex limit, uint8_t version){ - return _CFFindBundleResources(bundle, bundleURL, subDirName, searchLanguages, resName, resTypes, limit, NULL, version); } CF_EXPORT CFURLRef CFBundleCopyResourceURL(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) { if (!bundle) return NULL; -#ifdef CFBUNDLE_NEWLOOKUP CFURLRef result = (CFURLRef) _CFBundleCopyFindResources(bundle, NULL, NULL, resourceName, resourceType, subDirName, NULL, NO, NO, NULL); return result; -#else - CFURLRef result = NULL; - CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle), types = NULL, array; - if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks); - array = _CFFindBundleResources(bundle, NULL, subDirName, languages, resourceName, types, 1, NULL, _CFBundleLayoutVersion(bundle)); - if (types) CFRelease(types); - if (array) { - if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0)); - CFRelease(array); - } - return result; -#endif } CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfType(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName) { -#ifdef CFBUNDLE_NEWLOOKUP if (!bundle) return CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); CFArrayRef result = (CFArrayRef) _CFBundleCopyFindResources(bundle, NULL, NULL, NULL, resourceType, subDirName, NULL, YES, NO, NULL); return result; -#else - CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle), types = NULL, array; - if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks); - // MF:!!! Better "limit" than 1,000,000? - array = _CFFindBundleResources(bundle, NULL, subDirName, languages, NULL, types, 1000000, NULL, _CFBundleLayoutVersion(bundle)); - if (types) CFRelease(types); - - return array; -#endif } CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) { @@ -1140,25 +151,9 @@ CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStr } CF_EXPORT CFURLRef CFBundleCopyResourceURLForLocalization(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) { -#ifdef CFBUNDLE_NEWLOOKUP if (!bundle) return NULL; CFURLRef result = (CFURLRef) _CFBundleCopyFindResources(bundle, NULL, NULL, resourceName, resourceType, subDirName, localizationName, NO, YES, NULL); return result; -#else - CFURLRef result = NULL; - CFArrayRef languages = NULL, types = NULL, array; - - if (localizationName) languages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&localizationName, 1, &kCFTypeArrayCallBacks); - if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks); - array = _CFFindBundleResources(bundle, NULL, subDirName, languages, resourceName, types, 1, NULL, _CFBundleLayoutVersion(bundle)); - if (array) { - if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0)); - CFRelease(array); - } - if (types) CFRelease(types); - if (languages) CFRelease(languages); - return result; -#endif } CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) { @@ -1166,129 +161,22 @@ CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bund } CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeForLocalization(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) { -#ifdef CFBUNDLE_NEWLOOKUP if (!bundle) return CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); CFArrayRef result = (CFArrayRef) _CFBundleCopyFindResources(bundle, NULL, NULL, NULL, resourceType, subDirName, localizationName, YES, YES, NULL); return result; -#else - CFArrayRef languages = NULL, types = NULL, array; - - if (localizationName) languages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&localizationName, 1, &kCFTypeArrayCallBacks); - if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks); - // MF:!!! Better "limit" than 1,000,000? - array = _CFFindBundleResources(bundle, NULL, subDirName, languages, NULL, types, 1000000, NULL, _CFBundleLayoutVersion(bundle)); - if (types) CFRelease(types); - if (languages) CFRelease(languages); - return array; -#endif -} - - -static Boolean CFBundleAllowMixedLocalizations(void); - -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; - if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tableURL, &tableData, NULL, NULL, &errCode)) { - 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; } CF_EXPORT CFURLRef CFBundleCopyResourceURLInDirectory(CFURLRef bundleURL, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) { CFURLRef result = NULL; unsigned char buff[CFMaxPathSize]; CFURLRef newURL = NULL; - + if (!CFURLGetFileSystemRepresentation(bundleURL, true, buff, CFMaxPathSize)) return NULL; - + newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, buff, strlen((char *)buff), true); if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL); if (_CFBundleCouldBeBundle(newURL)) { -#ifdef CFBUNDLE_NEWLOOKUP result = (CFURLRef) _CFBundleCopyFindResources(NULL, bundleURL, NULL, resourceName, resourceType, subDirName, NULL, NO, NO, NULL); -#else - uint8_t version = 0; - CFArrayRef languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, newURL, &version), types = NULL, array; - if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks); - array = _CFFindBundleResources(NULL, newURL, subDirName, languages, resourceName, types, 1, NULL, version); - if (types) CFRelease(types); - if (languages) CFRelease(languages); - if (array) { - if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0)); - CFRelease(array); - } -#endif } if (newURL) CFRelease(newURL); return result; @@ -1298,28 +186,21 @@ CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeInDirectory(CFURLRef bundleUR CFArrayRef array = NULL; unsigned char buff[CFMaxPathSize]; CFURLRef newURL = NULL; - + if (!CFURLGetFileSystemRepresentation(bundleURL, true, buff, CFMaxPathSize)) return NULL; - + newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, buff, strlen((char *)buff), true); if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL); if (_CFBundleCouldBeBundle(newURL)) { -#ifdef CFBUNDLE_NEWLOOKUP array = (CFArrayRef) _CFBundleCopyFindResources(NULL, bundleURL, NULL, NULL, resourceType, subDirName, NULL, YES, NO, NULL); -#else - uint8_t version = 0; - CFArrayRef languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, newURL, &version), types = NULL; - if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks); - // MF:!!! Better "limit" than 1,000,000? - array = _CFFindBundleResources(NULL, newURL, subDirName, languages, NULL, types, 1000000, NULL, version); - if (types) CFRelease(types); - if (languages) CFRelease(languages); -#endif } 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" @@ -1556,7 +437,7 @@ static SInt32 _CFBundleGetRegionCodeForLocalization(CFStringRef localizationName return result; } -static CFStringRef _CFBundleCopyLocaleAbbreviationForRegionCode(SInt32 regionCode) { +CF_PRIVATE CFStringRef _CFBundleCopyLocaleAbbreviationForRegionCode(SInt32 regionCode) { CFStringRef result = NULL; if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) { const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH; @@ -1567,7 +448,7 @@ static CFStringRef _CFBundleCopyLocaleAbbreviationForRegionCode(SInt32 regionCod return result; } -Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName, SInt32 *languageCode, SInt32 *regionCode, SInt32 *scriptCode, CFStringEncoding *stringEncoding) { +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; @@ -1578,7 +459,7 @@ Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName, languages = _CFBundleGetLanguageSearchList(mainBundle); if (languages) CFRetain(languages); } - if (!languages) languages = _CFBundleCopyUserLanguages(false); + if (!languages) languages = _CFBundleCopyUserLanguages(); if (languages && CFArrayGetCount(languages) > 0) localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); } if (localizationName) { @@ -1634,20 +515,179 @@ CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SIn 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; + 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); } - localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(language); - if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(encodingLanguage); - if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(scriptLanguage); } - return localizationName; + return result; } extern void *__CFAppleLanguages; -__private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops) { +CF_PRIVATE CFArrayRef _CFBundleCopyUserLanguages() { static CFArrayRef _CFBundleUserLanguages = NULL; static dispatch_once_t once = 0; dispatch_once(&once, ^{ @@ -1695,7 +735,7 @@ CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 * languages = _CFBundleGetLanguageSearchList(mainBundle); if (languages) CFRetain(languages); } - if (!languages) languages = _CFBundleCopyUserLanguages(false); + if (!languages) languages = _CFBundleCopyUserLanguages(); if (languages && CFArrayGetCount(languages) > 0) { CFStringRef localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); Boolean retval = false; @@ -1722,55 +762,86 @@ CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 * } -static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc, UniChar *pathUniChars, CFIndex pathLen, uint8_t version, CFDictionaryRef infoDict, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) { - CFIndex curLangLen = CFStringGetLength(curLangStr), savedPathLen; - UniChar curLangUniChars[255]; - CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL; - CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL, predefinedCanonicalLanguageIdentifiers = NULL; + +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; - CFArrayRef predefinedLocalizations = NULL; - CFRange predefinedLocalizationsRange; - CFMutableStringRef cheapStr, tmpString; - CFArrayRef contents; - CFRange contentsRange; - - // both of these used for temp string operations, for slightly - // different purposes, where each type is appropriate - cheapStr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - _CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize); - tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull); - - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen); - CFStringReplaceAll(cheapStr, tmpString); - contents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleAllContents); - contentsRange = CFRangeMake(0, CFArrayGetCount(contents)); + CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL; + CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL; - if (infoDict) { - predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); - if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) != CFArrayGetTypeID()) { - predefinedLocalizations = NULL; - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, kCFBundleLocalizationsKey); + 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; } } - predefinedLocalizationsRange = CFRangeMake(0, predefinedLocalizations ? CFArrayGetCount(predefinedLocalizations) : 0); - if (curLangLen > 255) curLangLen = 255; - CFStringGetCharacters(curLangStr, CFRangeMake(0, curLangLen), curLangUniChars); - savedPathLen = pathLen; - if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + savedPathLen + 1, pathLen - savedPathLen - 1, pathLen - savedPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, curLangStr)) || (version != 4 && _CFBundleSortedArrayContains(contents, cheapStr))) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), curLangStr)) CFArrayAppendValue(lprojNames, curLangStr); + 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 (CFStringGetLength(curLangStr) <= 2) { - CFRelease(cheapStr); - CFRelease(tmpString); - CFRelease(contents); - return foundOne; - } } } + 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; @@ -1781,83 +852,34 @@ static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc } #endif /* __CONSTANT_CFSTRINGS__ */ if (foundOne && altLangStr) { - CFRelease(cheapStr); - CFRelease(tmpString); - CFRelease(contents); return foundOne; } if (altLangStr) { - curLangLen = CFStringGetLength(altLangStr); - if (curLangLen > 255) curLangLen = 255; - CFStringGetCharacters(altLangStr, CFRangeMake(0, curLangLen), curLangUniChars); - pathLen = savedPathLen; - if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + savedPathLen + 1, pathLen - savedPathLen - 1, pathLen - savedPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, altLangStr)) || (version != 4 && _CFBundleSortedArrayContains(contents, cheapStr))) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), altLangStr)) CFArrayAppendValue(lprojNames, altLangStr); - foundOne = true; - CFRelease(cheapStr); - CFRelease(tmpString); - CFRelease(contents); - return foundOne; - } - } - } - if (!foundOne && (!predefinedLocalizations || CFArrayGetCount(predefinedLocalizations) == 0)) { - Boolean hasLocalizations = false; - CFIndex idx; - for (idx = 0; !hasLocalizations && idx < contentsRange.length; idx++) { - CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(contents, idx); - if (CFStringHasSuffix(name, _CFBundleLprojExtensionWithDot)) hasLocalizations = true; - } - if (!hasLocalizations) { - CFRelease(cheapStr); - CFRelease(tmpString); - CFRelease(contents); + 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))) { - curLangLen = CFStringGetLength(modifiedLangStr); - if (curLangLen > 255) curLangLen = 255; - CFStringGetCharacters(modifiedLangStr, CFRangeMake(0, curLangLen), curLangUniChars); - pathLen = savedPathLen; - if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + savedPathLen + 1, pathLen - savedPathLen - 1, pathLen - savedPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, modifiedLangStr)) || (version != 4 && _CFBundleSortedArrayContains(contents, cheapStr))) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), modifiedLangStr)) CFArrayAppendValue(lprojNames, modifiedLangStr); - foundOne = true; - } + 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)) { - curLangLen = CFStringGetLength(languageAbbreviation); - if (curLangLen > 255) curLangLen = 255; - CFStringGetCharacters(languageAbbreviation, CFRangeMake(0, curLangLen), curLangUniChars); - pathLen = savedPathLen; - if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + savedPathLen + 1, pathLen - savedPathLen - 1, pathLen - savedPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, languageAbbreviation)) || (version != 4 && _CFBundleSortedArrayContains(contents, cheapStr))) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageAbbreviation)) CFArrayAppendValue(lprojNames, languageAbbreviation); - foundOne = true; - } + 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)) { - curLangLen = CFStringGetLength(languageName); - if (curLangLen > 255) curLangLen = 255; - CFStringGetCharacters(languageName, CFRangeMake(0, curLangLen), curLangUniChars); - pathLen = savedPathLen; - if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) { - CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + savedPathLen + 1, pathLen - savedPathLen - 1, pathLen - savedPathLen - 1); - CFStringReplaceAll(cheapStr, tmpString); - if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, languageName)) || (version != 4 && _CFBundleSortedArrayContains(contents, cheapStr))) { - if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName); - foundOne = true; - } + if (CFArrayContainsValue(localizations, localizationsRange, languageName)) { + if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName); + foundOne = true; } } if (modifiedLangStr) CFRelease(modifiedLangStr); @@ -1865,36 +887,10 @@ static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc if (languageName) CFRelease(languageName); if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier); if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers); - if (predefinedCanonicalLanguageIdentifiers) CFRelease(predefinedCanonicalLanguageIdentifiers); if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation); - CFRelease(cheapStr); - CFRelease(tmpString); - CFRelease(contents); return foundOne; } -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; -} - static Boolean _CFBundleLocalizationsHaveCommonPrefix(CFStringRef loc1, CFStringRef loc2) { Boolean result = false; CFIndex length1 = CFStringGetLength(loc1), length2 = CFStringGetLength(loc2), idx; @@ -1912,34 +908,13 @@ static Boolean _CFBundleLocalizationsHaveCommonPrefix(CFStringRef loc1, CFString return result; } -__private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, uint8_t version, CFDictionaryRef infoDict, CFMutableArrayRef lprojNames, CFStringRef devLang) { +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. - CFURLRef resourcesURL = _CFBundleCopyResourcesDirectoryURLInDirectory(bundleURL, version); - CFURLRef absoluteURL; - CFIndex idx, startIdx; - CFIndex count; - CFStringRef resourcesPath; - UniChar pathUniChars[CFMaxPathSize]; - CFIndex pathLen; - CFStringRef curLangStr, nextLangStr; + Boolean foundOne = false; - CFArrayRef userLanguages; - // Init the one-time-only unichar buffers. - _CFEnsureStaticBuffersInited(); - - // Get the path to the resources and extract into a buffer. - absoluteURL = CFURLCopyAbsoluteURL(resourcesURL); - resourcesPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - CFRelease(absoluteURL); - pathLen = CFStringGetLength(resourcesPath); - if (pathLen > CFMaxPathSize) pathLen = CFMaxPathSize; - CFStringGetCharacters(resourcesPath, CFRangeMake(0, pathLen), pathUniChars); - CFRelease(resourcesURL); - CFRelease(resourcesPath); - // First check the main bundle. if (!CFBundleAllowMixedLocalizations()) { CFBundleRef mainBundle = CFBundleGetMainBundle(); @@ -1950,8 +925,8 @@ __private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRe // 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)) { - curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0); - foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true); + CFStringRef curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0); + foundOne = _CFBundleTryOnePreferredLprojNameInURL(kCFAllocatorSystemDefault, localizations, curLangStr, lprojNames, true); } } CFRelease(mainBundleURL); @@ -1961,86 +936,80 @@ __private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRe if (!foundOne) { // If we didn't find the main bundle's preferred language, look at the users' prefs again and find the best one. - userLanguages = _CFBundleCopyUserLanguages(true); - count = (userLanguages ? CFArrayGetCount(userLanguages) : 0); - for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) { - curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx); - nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx + 1) : NULL; - if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) { - foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, false); - if (startIdx < 0) startIdx = idx; - } else if (startIdx >= 0 && startIdx <= idx) { - foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, false); - for (; !foundOne && startIdx <= idx; startIdx++) { - curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, startIdx); - foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true); + 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; } - startIdx = -1; - } else { - foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true); - startIdx = -1; } } // use development region and U.S. English as backstops - if (!foundOne && devLang) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, devLang, lprojNames, true); - if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(kCFAllocatorSystemDefault, pathUniChars, pathLen, version, infoDict, CFSTR("en_US"), lprojNames, true); + 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 Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) { - Boolean foundOne = false, specifiesScript = false; - CFRange range = CFRangeMake(0, CFArrayGetCount(array)); - CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL; - CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL; +static CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) { + uint8_t localVersion = 0; + CFDictionaryRef infoDict = _CFBundleCopyInfoDictionaryInDirectory(alloc, url, &localVersion); - if (range.length == 0) return foundOne; - 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]; - } - } -#endif /* __CONSTANT_CFSTRINGS__ */ - if (foundOne && altLangStr) return foundOne; - 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; + 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); } } - 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; - } + + 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); } - 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; + + 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) { @@ -2060,7 +1029,7 @@ static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, if (!foundOne) { CFStringRef curLangStr, nextLangStr; if (!prefArray) { - prefArray = _CFBundleCopyUserLanguages(true); + prefArray = _CFBundleCopyUserLanguages(); if (prefArray) releasePrefArray = true; } count = (prefArray ? CFArrayGetCount(prefArray) : 0); @@ -2094,36 +1063,84 @@ static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, 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); + 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; } -__private_extern__ CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) { - CFMutableArrayRef langs = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks); - uint8_t localVersion = 0; - CFDictionaryRef infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero, url, &localVersion); - CFStringRef devLang = NULL; - if (infoDict) devLang = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey); - if (devLang && (CFGetTypeID(devLang) != CFStringGetTypeID() || CFStringGetLength(devLang) == 0)) devLang = NULL; - - _CFBundleAddPreferredLprojNamesInDirectory(alloc, url, localVersion, infoDict, langs, devLang); - - 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 && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(infoDict); - if (version) *version = localVersion; - return langs; -} +#pragma mark - CF_EXPORT Boolean _CFBundleURLLooksLikeBundle(CFURLRef url) { Boolean result = false; @@ -2135,6 +1152,7 @@ CF_EXPORT Boolean _CFBundleURLLooksLikeBundle(CFURLRef url) { return result; } +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS // Note that subDirName is expected to be the string for a URL CF_INLINE Boolean _CFBundleURLHasSubDir(CFURLRef url, CFStringRef subDirName) { Boolean isDir = false, result = false; @@ -2145,8 +1163,9 @@ CF_INLINE Boolean _CFBundleURLHasSubDir(CFURLRef url, CFStringRef subDirName) { } return result; } +#endif -__private_extern__ Boolean _CFBundleURLLooksLikeBundleVersion(CFURLRef url, uint8_t *version) { +CF_PRIVATE uint8_t _CFBundleGetBundleVersionForURL(CFURLRef url) { // check for existence of "Resources" or "Contents" or "Support Files" // but check for the most likely one first // version 0: old-style "Resources" bundles @@ -2154,28 +1173,69 @@ __private_extern__ Boolean _CFBundleURLLooksLikeBundleVersion(CFURLRef url, uint // version 2: modern "Contents" bundles // version 3: none of the above (see below) // version 4: not a bundle (for main bundle only) - uint8_t localVersion = 3; + CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url); CFStringRef directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - CFArrayRef contents = _CFBundleCopySortedDirectoryContentsAtPath(directoryPath, _CFBundleAllContents); + CFRelease(absoluteURL); + Boolean hasFrameworkSuffix = CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/")); #if DEPLOYMENT_TARGET_WINDOWS hasFrameworkSuffix = hasFrameworkSuffix || CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework\\")); #endif + + /* + #define _CFBundleSupportFilesDirectoryName1 CFSTR("Support Files") + #define _CFBundleSupportFilesDirectoryName2 CFSTR("Contents") + #define _CFBundleResourcesDirectoryName CFSTR("Resources") + #define _CFBundleExecutablesDirectoryName CFSTR("Executables") + #define _CFBundleNonLocalizedResourcesDirectoryName CFSTR("Non-localized Resources") + */ + __block uint8_t localVersion = 3; + CFIndex resourcesDirectoryLength = CFStringGetLength(_CFBundleResourcesDirectoryName); + CFIndex contentsDirectoryLength = CFStringGetLength(_CFBundleSupportFilesDirectoryName2); + CFIndex supportFilesDirectoryLength = CFStringGetLength(_CFBundleSupportFilesDirectoryName1); + + __block Boolean foundResources = false; + __block Boolean foundSupportFiles2 = false; + __block Boolean foundSupportFiles1 = false; + + _CFIterateDirectory(directoryPath, ^Boolean (CFStringRef fileName, uint8_t fileType) { + // We're looking for a few different names, and also some info on if it's a directory or not. + // We don't stop looking once we find one of the names. Otherwise we could run into the situation where we have both "Contents" and "Resources" in a framework, and we see Contents first but Resources is more important. + if (fileType == DT_DIR || fileType == DT_LNK) { + CFIndex fileNameLen = CFStringGetLength(fileName); + if (fileNameLen == resourcesDirectoryLength && CFStringCompareWithOptions(fileName, _CFBundleResourcesDirectoryName, CFRangeMake(0, resourcesDirectoryLength), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + foundResources = true; + } else if (fileNameLen == contentsDirectoryLength && CFStringCompareWithOptions(fileName, _CFBundleSupportFilesDirectoryName2, CFRangeMake(0, contentsDirectoryLength), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + foundSupportFiles2 = true; + } else if (fileNameLen == supportFilesDirectoryLength && CFStringCompareWithOptions(fileName, _CFBundleSupportFilesDirectoryName1, CFRangeMake(0, supportFilesDirectoryLength), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + foundSupportFiles1 = true; + } + } + return true; + }); + // The order of these if statements is important - the Resources directory presence takes precedence over Contents, and so forth. if (hasFrameworkSuffix) { - if (_CFBundleSortedArrayContains(contents, _CFBundleResourcesDirectoryName)) localVersion = 0; - else if (_CFBundleSortedArrayContains(contents, _CFBundleSupportFilesDirectoryName2)) localVersion = 2; - else if (_CFBundleSortedArrayContains(contents, _CFBundleSupportFilesDirectoryName1)) localVersion = 1; + if (foundResources) { + localVersion = 0; + } else if (foundSupportFiles2) { + localVersion = 2; + } else if (foundSupportFiles1) { + localVersion = 1; + } } else { - if (_CFBundleSortedArrayContains(contents, _CFBundleSupportFilesDirectoryName2)) localVersion = 2; - else if (_CFBundleSortedArrayContains(contents, _CFBundleResourcesDirectoryName)) localVersion = 0; - else if (_CFBundleSortedArrayContains(contents, _CFBundleSupportFilesDirectoryName1)) localVersion = 1; + if (foundSupportFiles2) { + localVersion = 2; + } else if (foundResources) { + localVersion = 0; + } else if (foundSupportFiles1) { + localVersion = 1; + } } - if (contents) CFRelease(contents); - if (directoryPath) CFRelease(directoryPath); - if (absoluteURL) CFRelease(absoluteURL); + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS + // Do a more substantial check for the subdirectories that make up version 0/1/2 bundles. These are sometimes symlinks (like in Frameworks) and they would have been missed by our check above. Perhaps we can do a check for DT_LNK there as well, if it's sufficient instead of looking at the actual contents. if (localVersion == 3) { if (hasFrameworkSuffix) { if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0; @@ -2188,478 +1248,13 @@ __private_extern__ Boolean _CFBundleURLLooksLikeBundleVersion(CFURLRef url, uint } } #endif - if (version) *version = localVersion; - return (localVersion != 3); -} - -static Boolean _isValidPlatformSuffix(CFStringRef suffix) { - for (CFIndex idx = 0; idx < _CFBundleNumberOfPlatforms; idx++) { - if (CFEqual(suffix, _CFBundleSupportedPlatforms[idx])) return true; - } - return false; -} - -static Boolean _isValidProductSuffix(CFStringRef suffix) { - for (CFIndex idx = 0; idx < _CFBundleNumberOfProducts; idx++) { - if (CFEqual(suffix, _CFBundleSupportedProducts[idx])) return true; - } - return false; -} - -static Boolean _isValidiPhoneOSPlatformProductSuffix(CFStringRef suffix) { - for (CFIndex idx = 0; idx < _CFBundleNumberOfiPhoneOSPlatformProducts; idx++) { - if (CFEqual(suffix, _CFBundleSupportediPhoneOSPlatformProducts[idx])) return true; - } - return false; -} - -static Boolean _isValidPlatformAndProductSuffixPair(CFStringRef platform, CFStringRef product) { - if (!platform && !product) return true; - if (!platform) { - return _isValidProductSuffix(product); - } - if (!product) { - return _isValidPlatformSuffix(platform); - } - if (CFEqual(platform, _CFBundleiPhoneOSPlatformName)) { - return _isValidiPhoneOSPlatformProductSuffix(product); - } - return false; -} - -static Boolean _isBlacklistedKey(CFStringRef keyName) { -#if __CONSTANT_STRINGS__ -#define _CFBundleNumberOfBlacklistedInfoDictionaryKeys 2 - static const CFStringRef _CFBundleBlacklistedInfoDictionaryKeys[_CFBundleNumberOfBlacklistedInfoDictionaryKeys] = { CFSTR("CFBundleExecutable"), CFSTR("CFBundleIdentifier") }; - - for (CFIndex idx = 0; idx < _CFBundleNumberOfBlacklistedInfoDictionaryKeys; idx++) { - if (CFEqual(keyName, _CFBundleBlacklistedInfoDictionaryKeys[idx])) return true; - } -#endif - return false; -} - -static Boolean _isOverrideKey(CFStringRef fullKey, CFStringRef *outBaseKey, CFStringRef *outPlatformSuffix, CFStringRef *outProductSuffix) { - if (outBaseKey) { - *outBaseKey = NULL; - } - if (outPlatformSuffix) { - *outPlatformSuffix = NULL; - } - if (outProductSuffix) { - *outProductSuffix = NULL; - } - if (!fullKey) - return false; - CFRange minusRange = CFStringFind(fullKey, CFSTR("-"), kCFCompareBackwards); - CFRange tildeRange = CFStringFind(fullKey, CFSTR("~"), kCFCompareBackwards); - if (minusRange.location == kCFNotFound && tildeRange.location == kCFNotFound) return false; - // minus must come before tilde if both are present - if (minusRange.location != kCFNotFound && tildeRange.location != kCFNotFound && tildeRange.location <= minusRange.location) return false; - - CFIndex strLen = CFStringGetLength(fullKey); - CFRange baseKeyRange = (minusRange.location != kCFNotFound) ? CFRangeMake(0, minusRange.location) : CFRangeMake(0, tildeRange.location); - CFRange platformRange = CFRangeMake(kCFNotFound, 0); - CFRange productRange = CFRangeMake(kCFNotFound, 0); - if (minusRange.location != kCFNotFound) { - platformRange.location = minusRange.location + minusRange.length; - platformRange.length = ((tildeRange.location != kCFNotFound) ? tildeRange.location : strLen) - platformRange.location; - } - if (tildeRange.location != kCFNotFound) { - productRange.location = tildeRange.location + tildeRange.length; - productRange.length = strLen - productRange.location; - } - if (baseKeyRange.length < 1) return false; - if (platformRange.location != kCFNotFound && platformRange.length < 1) return false; - if (productRange.location != kCFNotFound && productRange.length < 1) return false; - - CFStringRef platform = (platformRange.location != kCFNotFound) ? CFStringCreateWithSubstring(kCFAllocatorSystemDefaultGCRefZero, fullKey, platformRange) : NULL; - CFStringRef product = (productRange.location != kCFNotFound) ? CFStringCreateWithSubstring(kCFAllocatorSystemDefaultGCRefZero, fullKey, productRange) : NULL; - Boolean result = _isValidPlatformAndProductSuffixPair(platform, product); - - if (result) { - if (outBaseKey) { - *outBaseKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefaultGCRefZero, fullKey, baseKeyRange); - } - if (outPlatformSuffix) { - *outPlatformSuffix = platform; - } else { - if (platform && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(platform); - } - if (outProductSuffix) { - *outProductSuffix = product; - } else { - if (product && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(product); - } - } else { - if (platform && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(platform); - if (product && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(product); - } - return result; -} - -static Boolean _isCurrentPlatformAndProduct(CFStringRef platform, CFStringRef product) { - if (!platform && !product) return true; - if (!platform) { - return CFEqual(_CFGetProductName(), product); - } - if (!product) { - return CFEqual(_CFGetPlatformName(), platform); - } - - return CFEqual(_CFGetProductName(), product) && CFEqual(_CFGetPlatformName(), platform); -} - -static CFArrayRef _CopySortedOverridesForBaseKey(CFStringRef keyName, CFDictionaryRef dict) { - CFMutableArrayRef overrides = CFArrayCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, &kCFTypeArrayCallBacks); - CFStringRef keyNameWithBoth = CFStringCreateWithFormat(kCFAllocatorSystemDefaultGCRefZero, NULL, CFSTR("%@-%@~%@"), keyName, _CFGetPlatformName(), _CFGetProductName()); - CFStringRef keyNameWithProduct = CFStringCreateWithFormat(kCFAllocatorSystemDefaultGCRefZero, NULL, CFSTR("%@~%@"), keyName, _CFGetProductName()); - CFStringRef keyNameWithPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefaultGCRefZero, NULL, CFSTR("%@-%@"), keyName, _CFGetPlatformName()); - - CFIndex count = CFDictionaryGetCount(dict); - - if (count > 0) { - CFTypeRef *keys = (CFTypeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 2 * count * sizeof(CFTypeRef), 0); - CFTypeRef *values = &(keys[count]); - - CFDictionaryGetKeysAndValues(dict, keys, values); - for (CFIndex idx = 0; idx < count; idx++) { - if (CFEqual(keys[idx], keyNameWithBoth)) { - CFArrayAppendValue(overrides, keys[idx]); - break; - } - } - for (CFIndex idx = 0; idx < count; idx++) { - if (CFEqual(keys[idx], keyNameWithProduct)) { - CFArrayAppendValue(overrides, keys[idx]); - break; - } - } - for (CFIndex idx = 0; idx < count; idx++) { - if (CFEqual(keys[idx], keyNameWithPlatform)) { - CFArrayAppendValue(overrides, keys[idx]); - break; - } - } - for (CFIndex idx = 0; idx < count; idx++) { - if (CFEqual(keys[idx], keyName)) { - CFArrayAppendValue(overrides, keys[idx]); - break; - } - } - - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) { - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, keys); - } - } - - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) { - CFRelease(keyNameWithProduct); - CFRelease(keyNameWithPlatform); - CFRelease(keyNameWithBoth); - } - - return overrides; -} - -__private_extern__ void _processInfoDictionary(CFMutableDictionaryRef dict, CFStringRef platformSuffix, CFStringRef productSuffix) { - CFIndex count = CFDictionaryGetCount(dict); - - if (count > 0) { - CFTypeRef *keys = (CFTypeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 2 * count * sizeof(CFTypeRef), 0); - CFTypeRef *values = &(keys[count]); - CFMutableArrayRef guard = CFArrayCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, &kCFTypeArrayCallBacks); - - CFDictionaryGetKeysAndValues(dict, keys, values); - for (CFIndex idx = 0; idx < count; idx++) { - CFStringRef keyPlatformSuffix, keyProductSuffix, keyName; - if (_isOverrideKey((CFStringRef)keys[idx], &keyName, &keyPlatformSuffix, &keyProductSuffix)) { - CFArrayRef keysForBaseKey = NULL; - if (_isCurrentPlatformAndProduct(keyPlatformSuffix, keyProductSuffix) && !_isBlacklistedKey(keyName) && CFDictionaryContainsKey(dict, keys[idx])) { - keysForBaseKey = _CopySortedOverridesForBaseKey(keyName, dict); - CFIndex keysForBaseKeyCount = CFArrayGetCount(keysForBaseKey); - - //make sure the other keys for this base key don't get released out from under us until we're done - CFArrayAppendValue(guard, keysForBaseKey); - - //the winner for this base key will be sorted to the front, do the override with it - CFTypeRef highestPriorityKey = CFArrayGetValueAtIndex(keysForBaseKey, 0); - CFDictionarySetValue(dict, keyName, CFDictionaryGetValue(dict, highestPriorityKey)); - - //remove everything except the now-overridden key; this will cause them to fail the CFDictionaryContainsKey(dict, keys[idx]) check in the enclosing if() and not be reprocessed - for (CFIndex presentKeysIdx = 0; presentKeysIdx < keysForBaseKeyCount; presentKeysIdx++) { - CFStringRef currentKey = (CFStringRef)CFArrayGetValueAtIndex(keysForBaseKey, presentKeysIdx); - if (!CFEqual(currentKey, keyName)) - CFDictionaryRemoveValue(dict, currentKey); - } - } else { - CFDictionaryRemoveValue(dict, keys[idx]); - } - - - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) { - if (keyPlatformSuffix) CFRelease(keyPlatformSuffix); - if (keyProductSuffix) CFRelease(keyProductSuffix); - CFRelease(keyName); - if (keysForBaseKey) CFRelease(keysForBaseKey); - } - } - } - - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) { - CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, keys); - CFRelease(guard); - } - } -} - -// returns zero-ref dictionary under GC if given kCFAllocatorSystemDefaultGCRefZero -__private_extern__ CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) { - CFDictionaryRef dict = NULL; - unsigned char buff[CFMaxPathSize]; - uint8_t localVersion = 0; - - if (CFURLGetFileSystemRepresentation(url, true, buff, CFMaxPathSize)) { - CFURLRef newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, buff, strlen((char *)buff), true); - if (!newURL) newURL = (CFURLRef)CFRetain(url); - - // version 3 is for flattened pseudo-bundles with no Contents, Support Files, or Resources directories - if (!_CFBundleURLLooksLikeBundleVersion(newURL, &localVersion)) localVersion = 3; - - dict = _CFBundleCopyInfoDictionaryInDirectoryWithVersion(alloc, newURL, localVersion); - CFRelease(newURL); - } - if (version) *version = localVersion; - return dict; -} - -// returns zero-ref dictionary under GC if given kCFAllocatorSystemDefaultGCRefZero -__private_extern__ CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectoryWithVersion(CFAllocatorRef alloc, CFURLRef url, uint8_t version) { - CFDictionaryRef result = NULL; - if (url) { - CFURLRef infoURL = NULL, rawInfoURL = NULL; - CFDataRef infoData = NULL; - UniChar buff[CFMaxPathSize]; - CFIndex len; - CFMutableStringRef cheapStr; - CFStringRef infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension0, infoURLFromBase = _CFBundleInfoURLFromBase0; - Boolean tryPlatformSpecific = true, tryGlobal = true; - CFURLRef directoryURL = NULL, absoluteURL; - CFStringRef directoryPath; - CFArrayRef contents = NULL; - CFRange contentsRange = CFRangeMake(0, 0); - - _CFEnsureStaticBuffersInited(); - - if (0 == version) { - directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleResourcesURLFromBase0, url); - infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension0; - infoURLFromBase = _CFBundleInfoURLFromBase0; - } else if (1 == version) { - directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase1, url); - infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension1; - infoURLFromBase = _CFBundleInfoURLFromBase1; - } else if (2 == version) { - directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase2, url); - infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension2; - infoURLFromBase = _CFBundleInfoURLFromBase2; - } else if (3 == version) { - CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - // this test is necessary to exclude the case where a bundle is spuriously created from the innards of another bundle - if (path) { - if (!(CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(path, _CFBundleResourcesDirectoryName))) { - directoryURL = (CFURLRef)CFRetain(url); - infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension3; - infoURLFromBase = _CFBundleInfoURLFromBase3; - } - CFRelease(path); - } - } - if (directoryURL) { - absoluteURL = CFURLCopyAbsoluteURL(directoryURL); - directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - contents = _CFBundleCopySortedDirectoryContentsAtPath(directoryPath, _CFBundleAllContents); - contentsRange = CFRangeMake(0, CFArrayGetCount(contents)); - if (directoryPath) CFRelease(directoryPath); - if (absoluteURL) CFRelease(absoluteURL); - if (directoryURL) CFRelease(directoryURL); - } - - len = CFStringGetLength(infoURLFromBaseNoExtension); - CFStringGetCharacters(infoURLFromBaseNoExtension, CFRangeMake(0, len), buff); - buff[len++] = (UniChar)'-'; - memmove(buff + len, _PlatformUniChars, _PlatformLen * sizeof(UniChar)); - len += _PlatformLen; - _CFAppendPathExtension(buff, &len, CFMaxPathSize, _InfoExtensionUniChars, _InfoExtensionLen); - cheapStr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - CFStringAppendCharacters(cheapStr, buff, len); - infoURL = CFURLCreateWithString(kCFAllocatorSystemDefault, cheapStr, url); - if (contents) { - CFIndex resourcesLen, idx; - for (resourcesLen = len; resourcesLen > 0; resourcesLen--) if (buff[resourcesLen - 1] == PATH_SEP) break; - CFStringDelete(cheapStr, CFRangeMake(0, CFStringGetLength(cheapStr))); - CFStringAppendCharacters(cheapStr, buff + resourcesLen, len - resourcesLen); - for (tryPlatformSpecific = false, idx = 0; !tryPlatformSpecific && idx < contentsRange.length; idx++) { - // Need to do this case-insensitive to accommodate Palm - if (kCFCompareEqualTo == CFStringCompare(cheapStr, (CFStringRef)CFArrayGetValueAtIndex(contents, idx), kCFCompareCaseInsensitive)) tryPlatformSpecific = true; - } - } - if (tryPlatformSpecific) CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, infoURL, &infoData, NULL, NULL, NULL); - //fprintf(stderr, "looking for ");CFShow(infoURL);fprintf(stderr, infoData ? "found it\n" : (tryPlatformSpecific ? "missed it\n" : "skipped it\n")); - CFRelease(cheapStr); - if (!infoData) { - // Check for global Info.plist - CFRelease(infoURL); - infoURL = CFURLCreateWithString(kCFAllocatorSystemDefault, infoURLFromBase, url); - if (contents) { - CFIndex idx; - for (tryGlobal = false, idx = 0; !tryGlobal && idx < contentsRange.length; idx++) { - // Need to do this case-insensitive to accommodate Palm - if (kCFCompareEqualTo == CFStringCompare(_CFBundleInfoFileName, (CFStringRef)CFArrayGetValueAtIndex(contents, idx), kCFCompareCaseInsensitive)) tryGlobal = true; - } - } - if (tryGlobal) CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, infoURL, &infoData, NULL, NULL, NULL); - //fprintf(stderr, "looking for ");CFShow(infoURL);fprintf(stderr, infoData ? "found it\n" : (tryGlobal ? "missed it\n" : "skipped it\n")); - } - - if (infoData) { - result = (CFDictionaryRef)CFPropertyListCreateFromXMLData(alloc, infoData, kCFPropertyListMutableContainers, NULL); - if (result) { - if (CFDictionaryGetTypeID() == CFGetTypeID(result)) { - CFDictionarySetValue((CFMutableDictionaryRef)result, _kCFBundleInfoPlistURLKey, infoURL); - } else { - if (!_CFAllocatorIsGCRefZero(alloc)) CFRelease(result); - result = NULL; - } - } - if (!result) rawInfoURL = infoURL; - CFRelease(infoData); - } - if (!result) { - result = CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (rawInfoURL) CFDictionarySetValue((CFMutableDictionaryRef)result, _kCFBundleRawInfoPlistURLKey, rawInfoURL); - } - - CFRelease(infoURL); - if (contents) CFRelease(contents); - } - _processInfoDictionary((CFMutableDictionaryRef)result, _CFGetPlatformName(), _CFGetProductName()); - return result; -} - -static Boolean _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(CFAllocatorRef alloc, CFURLRef url, CFDictionaryRef infoDict, UInt32 *packageType, UInt32 *packageCreator) { - Boolean retVal = false, hasType = false, hasCreator = false, releaseInfoDict = false; - CFURLRef tempURL; - CFDataRef pkgInfoData = NULL; - - // Check for a "real" new bundle - tempURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundlePkgInfoURLFromBase2, url); - CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tempURL, &pkgInfoData, NULL, NULL, NULL); - CFRelease(tempURL); - if (!pkgInfoData) { - tempURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundlePkgInfoURLFromBase1, url); - CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tempURL, &pkgInfoData, NULL, NULL, NULL); - CFRelease(tempURL); - } - if (!pkgInfoData) { - // Check for a "pseudo" new bundle - tempURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundlePseudoPkgInfoURLFromBase, url); - CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, tempURL, &pkgInfoData, NULL, NULL, NULL); - CFRelease(tempURL); - } - - // Now, either we have a pkgInfoData or not. If not, then is it because this is a new bundle without one (do we allow this?), or is it dbecause it is an old bundle. - // If we allow new bundles to not have a PkgInfo (because they already have the same data in the Info.plist), then we have to go read the info plist which makes failure expensive. - // drd: So we assume that a new bundle _must_ have a PkgInfo if they have this data at all, otherwise we manufacture it from the extension. - - if (pkgInfoData && CFDataGetLength(pkgInfoData) >= (int)(sizeof(UInt32) * 2)) { - UInt32 *pkgInfo = (UInt32 *)CFDataGetBytePtr(pkgInfoData); - if (packageType) *packageType = CFSwapInt32BigToHost(pkgInfo[0]); - if (packageCreator) *packageCreator = CFSwapInt32BigToHost(pkgInfo[1]); - retVal = hasType = hasCreator = true; - } - if (pkgInfoData) CFRelease(pkgInfoData); - if (!retVal) { - if (!infoDict) { - infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero, url, NULL); - releaseInfoDict = true; - } - if (infoDict) { - CFStringRef typeString = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundlePackageTypeKey), creatorString = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleSignatureKey); - UInt32 tmp; - CFIndex usedBufLen = 0; - if (typeString && CFGetTypeID(typeString) == CFStringGetTypeID() && CFStringGetLength(typeString) == 4 && 4 == CFStringGetBytes(typeString, CFRangeMake(0, 4), kCFStringEncodingMacRoman, 0, false, (UInt8 *)&tmp, 4, &usedBufLen) && 4 == usedBufLen) { - if (packageType) *packageType = CFSwapInt32BigToHost(tmp); - retVal = hasType = true; - } - if (creatorString && CFGetTypeID(creatorString) == CFStringGetTypeID() && CFStringGetLength(creatorString) == 4 && 4 == CFStringGetBytes(creatorString, CFRangeMake(0, 4), kCFStringEncodingMacRoman, 0, false, (UInt8 *)&tmp, 4, &usedBufLen) && 4 == usedBufLen) { - if (packageCreator) *packageCreator = CFSwapInt32BigToHost(tmp); - retVal = hasCreator = true; - } - if (releaseInfoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(infoDict); - } - } - if (!hasType || !hasCreator) { - // If this looks like a bundle then manufacture the type and creator. - if (retVal || _CFBundleURLLooksLikeBundle(url)) { - if (packageCreator && !hasCreator) *packageCreator = 0x3f3f3f3f; // '????' - if (packageType && !hasType) { - CFStringRef urlStr; - UniChar buff[CFMaxPathSize]; - CFIndex strLen, startOfExtension; - CFURLRef absoluteURL; - - // Detect "app", "debug", "profile", or "framework" extensions - absoluteURL = CFURLCopyAbsoluteURL(url); - urlStr = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - CFRelease(absoluteURL); - strLen = CFStringGetLength(urlStr); - if (strLen > CFMaxPathSize) strLen = CFMaxPathSize; - CFStringGetCharacters(urlStr, CFRangeMake(0, strLen), buff); - CFRelease(urlStr); - startOfExtension = _CFStartOfPathExtension(buff, strLen); - if ((strLen - startOfExtension == 4 || strLen - startOfExtension == 5) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'a' && buff[startOfExtension+2] == (UniChar)'p' && buff[startOfExtension+3] == (UniChar)'p' && (strLen - startOfExtension == 4 || buff[startOfExtension+4] == (UniChar)PATH_SEP)) { - // This is an app - *packageType = 0x4150504c; // 'APPL' - } else if ((strLen - startOfExtension == 6 || strLen - startOfExtension == 7) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'d' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'b' && buff[startOfExtension+4] == (UniChar)'u' && buff[startOfExtension+5] == (UniChar)'g' && (strLen - startOfExtension == 6 || buff[startOfExtension+6] == (UniChar)PATH_SEP)) { - // This is an app (debug version) - *packageType = 0x4150504c; // 'APPL' - } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'p' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'o' && buff[startOfExtension+4] == (UniChar)'f' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'l' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)PATH_SEP)) { - // This is an app (profile version) - *packageType = 0x4150504c; // 'APPL' - } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'s' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'r' && buff[startOfExtension+4] == (UniChar)'v' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'c' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)PATH_SEP)) { - // This is a service - *packageType = 0x4150504c; // 'APPL' - } else if ((strLen - startOfExtension == 10 || strLen - startOfExtension == 11) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'f' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'a' && buff[startOfExtension+4] == (UniChar)'m' && buff[startOfExtension+5] == (UniChar)'e' && buff[startOfExtension+6] == (UniChar)'w' && buff[startOfExtension+7] == (UniChar)'o' && buff[startOfExtension+8] == (UniChar)'r' && buff[startOfExtension+9] == (UniChar)'k' && (strLen - startOfExtension == 10 || buff[startOfExtension+10] == (UniChar)PATH_SEP)) { - // This is a framework - *packageType = 0x464d574b; // 'FMWK' - } else { - // Default to BNDL for generic bundle - *packageType = 0x424e444c; // 'BNDL' - } - } - retVal = true; - } - } - return retVal; -} -CF_EXPORT Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) { - return _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(alloc, url, NULL, packageType, packageCreator); + CFRelease(directoryPath); + return localVersion; } -CF_EXPORT void CFBundleGetPackageInfo(CFBundleRef bundle, UInt32 *packageType, UInt32 *packageCreator) { - CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); - if (!_CFBundleGetPackageInfoInDirectoryWithInfoDictionary(kCFAllocatorSystemDefault, bundleURL, CFBundleGetInfoDictionary(bundle), packageType, packageCreator)) { - if (packageType) *packageType = 0x424e444c; // 'BNDL' - if (packageCreator) *packageCreator = 0x3f3f3f3f; // '????' - } - if (bundleURL) CFRelease(bundleURL); -} - -CF_EXPORT Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) { - return _CFBundleGetPackageInfoInDirectory(kCFAllocatorSystemDefault, url, packageType, packageCreator); -} +#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); @@ -2742,7 +1337,7 @@ CF_EXPORT CFStringRef _CFBundleGetCurrentPlatform(void) { #endif } -__private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) { +CF_PRIVATE CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI return CFSTR("MacOS"); #elif DEPLOYMENT_TARGET_WINDOWS @@ -2760,7 +1355,7 @@ __private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(v #endif } -__private_extern__ CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirectoryName(void) { +CF_PRIVATE CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirectoryName(void) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI return CFSTR("Mac OS X"); #elif DEPLOYMENT_TARGET_WINDOWS @@ -2778,7 +1373,7 @@ __private_extern__ CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirect #endif } -__private_extern__ CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryName(void) { +CF_PRIVATE CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryName(void) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI return CFSTR("MacOSClassic"); #elif DEPLOYMENT_TARGET_WINDOWS @@ -2796,7 +1391,7 @@ __private_extern__ CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryN #endif } -__private_extern__ CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName(void) { +CF_PRIVATE CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName(void) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI return CFSTR("Mac OS 8"); #elif DEPLOYMENT_TARGET_WINDOWS @@ -2814,79 +1409,6 @@ __private_extern__ CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubd #endif } -__private_extern__ CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle) { - return CFBundleCopyBundleLocalizations(bundle); -} - -CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) { - CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); - CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); - CFURLRef absoluteURL; - CFStringRef directoryPath; - CFArrayRef contents; - CFRange contentsRange; - CFIndex idx; - CFArrayRef predefinedLocalizations = NULL; - CFMutableArrayRef result = NULL; - - if (infoDict) { - predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey); - if (predefinedLocalizations && CFGetTypeID(predefinedLocalizations) != CFArrayGetTypeID()) { - predefinedLocalizations = NULL; - CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, kCFBundleLocalizationsKey); - } - if (predefinedLocalizations) { - CFIndex i, c = CFArrayGetCount(predefinedLocalizations); - if (c > 0 && !result) result = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &kCFTypeArrayCallBacks); - for (i = 0; i < c; i++) CFArrayAppendValue(result, CFArrayGetValueAtIndex(predefinedLocalizations, i)); - } - } - - if (resourcesURL) { - absoluteURL = CFURLCopyAbsoluteURL(resourcesURL); - directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE); - contents = _CFBundleCopySortedDirectoryContentsAtPath(directoryPath, _CFBundleAllContents); - contentsRange = CFRangeMake(0, CFArrayGetCount(contents)); - for (idx = 0; idx < contentsRange.length; idx++) { - CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(contents, idx); - if (CFStringHasSuffix(name, _CFBundleLprojExtensionWithDot)) { - CFStringRef localization = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, name, CFRangeMake(0, CFStringGetLength(name) - 6)); - if (!result) result = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(result, localization); - CFRelease(localization); - } - } - if (contents) CFRelease(contents); - if (directoryPath) CFRelease(directoryPath); - if (absoluteURL) CFRelease(absoluteURL); - } - - if (!result) { - CFStringRef developmentLocalization = CFBundleGetDevelopmentRegion(bundle); - if (developmentLocalization) { - result = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(result, developmentLocalization); - } - } - if (resourcesURL) CFRelease(resourcesURL); - return result; -} - - -CF_EXPORT CFDictionaryRef CFBundleCopyInfoDictionaryForURL(CFURLRef url) { - CFDictionaryRef result = NULL; - Boolean isDir = false; - if (_CFIsResourceAtURL(url, &isDir)) { - if (isDir) { - result = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero, url, NULL); - } else { - result = _CFBundleCopyInfoDictionaryInExecutable(url); // return zero-ref dictionary under GC - } - } - if (result && _CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRetain(result); // conditionally put on a retain for a Copy function - return result; -} - CFArrayRef CFBundleCopyExecutableArchitecturesForURL(CFURLRef url) { CFArrayRef result = NULL; CFBundleRef bundle = CFBundleCreate(kCFAllocatorSystemDefault, url); @@ -2899,30 +1421,29 @@ CFArrayRef CFBundleCopyExecutableArchitecturesForURL(CFURLRef url) { 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); // return zero-ref dictionary under GC - 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); - } - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(infoDict); - } +#pragma mark - +#pragma mark Resource Lookup - Query Table + +static void _CFBundleAddValueForType(CFStringRef type, CFMutableDictionaryRef queryTable, CFMutableDictionaryRef typeDir, CFTypeRef value, CFMutableDictionaryRef addedTypes, Boolean firstLproj) { + CFMutableArrayRef tFiles = (CFMutableArrayRef) CFDictionaryGetValue(typeDir, type); + if (!tFiles) { + CFStringRef key = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@.%@"), _CFBundleTypeIndicator, type); + tFiles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + CFDictionarySetValue(queryTable, key, tFiles); + CFDictionarySetValue(typeDir, type, tFiles); + CFRelease(tFiles); + CFRelease(key); + } + if (!addedTypes) { + CFArrayAppendValue(tFiles, value); + } else if (firstLproj) { + CFDictionarySetValue(addedTypes, type, type); + CFArrayAppendValue(tFiles, value); + } else if (!(CFDictionaryGetValue(addedTypes, type))) { + CFArrayAppendValue(tFiles, value); } - return result; } - - CF_INLINE Boolean _CFBundleFindCharacterInStr(const UniChar *str, UniChar c, Boolean backward, CFIndex start, CFIndex length, CFRange *result){ *result = CFRangeMake(kCFNotFound, 0); Boolean found = false; @@ -2946,7 +1467,6 @@ CF_INLINE Boolean _CFBundleFindCharacterInStr(const UniChar *str, UniChar c, Boo return found; } - typedef enum { _CFBundleFileVersionNoProductNoPlatform = 1, _CFBundleFileVersionWithProductNoPlatform, @@ -2955,52 +1475,31 @@ typedef enum { _CFBundleFileVersionUnmatched } _CFBundleFileVersion; -static _CFBundleFileVersion _CFBundleCheckFileProductAndPlatform(CFStringRef file, UniChar *fileBuffer1, CFIndex fileLen, CFRange searchRange, CFStringRef product, CFStringRef platform, CFRange* prodp, CFRange* platp, CFIndex prodLen) +static _CFBundleFileVersion _CFBundleCheckFileProductAndPlatform(CFStringRef file, CFRange searchRange, CFStringRef product, CFStringRef platform) { _CFBundleFileVersion version; - CFRange found; Boolean foundprod, foundplat; foundplat = foundprod = NO; - UniChar fileBuffer2[CFMaxPathSize]; - UniChar *fileBuffer; Boolean wrong = false; - if (fileBuffer1) { - fileBuffer = fileBuffer1; - }else{ - fileLen = CFStringGetLength(file); - if (fileLen > CFMaxPathSize) fileLen = CFMaxPathSize; - CFStringGetCharacters(file, CFRangeMake(0, fileLen), fileBuffer2); - fileBuffer = fileBuffer2; - } - - if (_CFBundleFindCharacterInStr(fileBuffer, '~', NO, searchRange.location, searchRange.length, &found)) { - if (prodLen != 1) { - if (CFStringFindWithOptions(file, product, searchRange, kCFCompareEqualTo, prodp)) { + if (CFStringFindWithOptions(file, CFSTR("~"), searchRange, 0, NULL)) { + if (CFStringGetLength(product) != 1) { + // todo: really, search the same range again? + if (CFStringFindWithOptions(file, product, searchRange, kCFCompareEqualTo, NULL)) { foundprod = YES; } } if (!foundprod) { - for (CFIndex i = 0; i < _CFBundleNumberOfProducts; i++) { - if (CFStringFindWithOptions(file, _CFBundleSupportedProducts[i], searchRange, kCFCompareEqualTo, &found)) { - wrong = true; - break; - } - } + wrong = _CFBundleSupportedProductName(file, searchRange); } } - - if (!wrong && _CFBundleFindCharacterInStr(fileBuffer, '-', NO, searchRange.location, searchRange.length, &found)) { - if (CFStringFindWithOptions(file, platform, searchRange, kCFCompareEqualTo, platp)) { + + if (!wrong && CFStringFindWithOptions(file, CFSTR("-"), searchRange, 0, NULL)) { + if (CFStringFindWithOptions(file, platform, searchRange, kCFCompareEqualTo, NULL)) { foundplat = YES; } if (!foundplat) { - for (CFIndex i = 0; i < _CFBundleNumberOfPlatforms; i++) { - if (CFStringFindWithOptions(file, _CFBundleSupportedPlatforms[i], searchRange, kCFCompareEqualTo, &found)) { - wrong = true; - break; - } - } + wrong = _CFBundleSupportedPlatformName(file, searchRange); } } @@ -3008,9 +1507,57 @@ static _CFBundleFileVersion _CFBundleCheckFileProductAndPlatform(CFStringRef fil version = _CFBundleFileVersionUnmatched; } else if (foundplat && foundprod) { version = _CFBundleFileVersionWithProductWithPlatform; - } else if (foundplat) { + } else if (foundplat) { + version = _CFBundleFileVersionNoProductWithPlatform; + } else if (foundprod) { + version = _CFBundleFileVersionWithProductNoPlatform; + } else { + version = _CFBundleFileVersionNoProductNoPlatform; + } + return version; +} + +static _CFBundleFileVersion _CFBundleVersionForFileName(CFStringRef fileName, CFStringRef expectedProduct, CFStringRef expectedPlatform, CFRange *outProductRange, CFRange *outPlatformRange) { + // Search for a product name, e.g.: foo~iphone.jpg or bar~ipad + Boolean foundProduct = false; + Boolean foundPlatform = false; + CFIndex fileNameLen = CFStringGetLength(fileName); + CFRange productRange; + CFRange platformRange; + + CFIndex dotLocation = fileNameLen; + for (CFIndex i = fileNameLen - 1; i > 0; i--) { + UniChar c = CFStringGetCharacterAtIndex(fileName, i); + if (c == '.') { + dotLocation = i; + } +#if DEPLOYMENT_TARGET_EMBEDDED + // Product names are only supported on iOS + // ref docs here: "iOS Supports Device-Specific Resources" in "Resource Programming Guide" + else if (c == '~' && !foundProduct) { + productRange = CFRangeMake(i, dotLocation - i); + foundProduct = (CFStringCompareWithOptions(fileName, expectedProduct, productRange, kCFCompareAnchored) == kCFCompareEqualTo); + if (foundProduct && outProductRange) *outProductRange = productRange; + } +#endif + else if (c == '-') { + if (foundProduct) { + platformRange = CFRangeMake(i, productRange.location - i); + } else { + platformRange = CFRangeMake(i, dotLocation - i); + } + foundPlatform = (CFStringCompareWithOptions(fileName, expectedPlatform, platformRange, kCFCompareAnchored) == kCFCompareEqualTo); + if (foundPlatform && outPlatformRange) *outPlatformRange = platformRange; + break; + } + } + + _CFBundleFileVersion version; + if (foundPlatform && foundProduct) { + version = _CFBundleFileVersionWithProductWithPlatform; + } else if (foundPlatform) { version = _CFBundleFileVersionNoProductWithPlatform; - } else if (foundprod) { + } else if (foundProduct) { version = _CFBundleFileVersionWithProductNoPlatform; } else { version = _CFBundleFileVersionNoProductNoPlatform; @@ -3018,290 +1565,217 @@ static _CFBundleFileVersion _CFBundleCheckFileProductAndPlatform(CFStringRef fil return version; } +// Splits up a string into its various parts. Note that the out-types must be released by the caller if they exist. +static void _CFBundleSplitFileName(CFStringRef fileName, CFStringRef *noProductOrPlatform, CFStringRef *endType, CFStringRef *startType, CFStringRef expectedProduct, CFStringRef expectedPlatform, _CFBundleFileVersion *version) { + CFIndex fileNameLen = CFStringGetLength(fileName); -// ZFH + if (endType || startType) { + // Search for the type from the end (type defined as everything after the last '.') + // e.g., a file name like foo.jpg has a type of 'jpg' + Boolean foundDot = false; + uint16_t dotLocation = 0; + for (CFIndex i = fileNameLen; i > 0; i--) { + if (CFStringGetCharacterAtIndex(fileName, i - 1) == '.') { + foundDot = true; + dotLocation = i - 1; + break; + } + } + + if (foundDot && dotLocation != fileNameLen - 1) { + if (endType) *endType = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fileName, CFRangeMake(dotLocation + 1, CFStringGetLength(fileName) - dotLocation - 1)); + } + + // Search for the type from the beginning (type defined as everything after the first '.') + // e.g., a file name like foo.jpg.gz has a type of 'jpg.gz' + if (startType) { + for (CFIndex i = 0; i < fileNameLen; i++) { + if (CFStringGetCharacterAtIndex(fileName, i) == '.') { + // no need to create this again if it's the same as previous + if (i != dotLocation) { + *startType = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, fileName, CFRangeMake(i + 1, CFStringGetLength(fileName) - i - 1)); + } + break; + } + } + } + } + CFRange productRange, platformRange; + *version = _CFBundleVersionForFileName(fileName, expectedProduct, expectedPlatform, &productRange, &platformRange); -static void _CFBundleAddValueForType(CFMutableStringRef type, UniChar* fileNameBuffer, CFMutableDictionaryRef queryTable, CFRange dotPosition, CFIndex fileLen, CFMutableDictionaryRef typeDir, CFTypeRef value, CFMutableDictionaryRef addedTypes, Boolean firstLproj){ - CFIndex typeLen = fileLen - dotPosition.location - 1; - CFStringSetExternalCharactersNoCopy(type, fileNameBuffer+dotPosition.location+1, typeLen, typeLen); - CFMutableArrayRef tFiles = (CFMutableArrayRef) CFDictionaryGetValue(typeDir, type); - if (!tFiles) { - CFStringRef key = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@.%@"), _CFBundleTypeIndicator, type); - tFiles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFDictionarySetValue(queryTable, key, tFiles); - CFDictionarySetValue(typeDir, type, tFiles); - CFRelease(tFiles); - CFRelease(key); - } - if (!addedTypes) { - CFArrayAppendValue(tFiles, value); - } else if (firstLproj) { - CFDictionarySetValue(addedTypes, type, type); - CFArrayAppendValue(tFiles, value); - } else if (!(CFDictionaryGetValue(addedTypes, type))) { - CFArrayAppendValue(tFiles, value); - } + Boolean foundPlatform = (*version == _CFBundleFileVersionNoProductWithPlatform || *version == _CFBundleFileVersionWithProductWithPlatform); + Boolean foundProduct = (*version == _CFBundleFileVersionWithProductNoPlatform || *version == _CFBundleFileVersionWithProductWithPlatform); + // Create a string that excludes both platform and product name + // e.g., foo-iphone~iphoneos.jpg -> foo.jpg + if (foundPlatform || foundProduct) { + CFMutableStringRef fileNameScratch = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, fileName); + CFIndex start, length = 0; + + // Because the platform always comes first and is immediately followed by product if it exists, we'll use the platform start location as the start of our range to delete. + if (foundPlatform) { + start = platformRange.location; + } else { + start = productRange.location; + } + + if (foundPlatform && foundProduct) { + length = platformRange.length + productRange.length; + } else if (foundPlatform) { + length = platformRange.length; + } else if (foundProduct) { + length = productRange.length; + } + CFStringDelete(fileNameScratch, CFRangeMake(start, length)); + *noProductOrPlatform = (CFStringRef)fileNameScratch; + } } -static Boolean _CFBundleReadDirectory(CFStringRef pathOfDir, CFBundleRef bundle, CFURLRef bundleURL, UniChar *resDir, UniChar *subDir, CFIndex subDirLen, CFMutableArrayRef allFiles, Boolean hasFileAdded, CFMutableStringRef type, CFMutableDictionaryRef queryTable, CFMutableDictionaryRef typeDir, CFMutableDictionaryRef addedTypes, Boolean firstLproj, CFStringRef product, CFStringRef platform, CFStringRef lprojName, Boolean appendLprojCharacters) { - - Boolean result = true; - - const CFIndex cPathBuffLen = CFStringGetMaximumSizeOfFileSystemRepresentation(pathOfDir) + 1; - const CFIndex valueBufferLen = cPathBuffLen + 1 + CFMaxPathSize; - UniChar *valueBuff = (UniChar *) CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * valueBufferLen, 0); - CFMutableStringRef valueStr = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull); - CFIndex pathOfDirWithSlashLen = 0; - - CFIndex productLen = CFStringGetLength(product); - CFIndex platformLen = CFStringGetLength(platform); +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) { + Boolean result = true; + CFMutableStringRef pathPrefix = NULL; if (lprojName) { - // valueBuff is allocated with the actual length of lprojTarget - CFRange lprojRange = CFRangeMake(0, CFStringGetLength(lprojName)); - CFStringGetCharacters(lprojName, lprojRange, valueBuff); - pathOfDirWithSlashLen += lprojRange.length; - if (appendLprojCharacters) _CFAppendPathExtension(valueBuff, &pathOfDirWithSlashLen, valueBufferLen, _LprojUniChars, _LprojLen); - _CFAppendTrailingPathSlash(valueBuff, &pathOfDirWithSlashLen, valueBufferLen); + pathPrefix = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, lprojName); + if (appendLprojCharacters) _CFAppendPathExtension2(pathPrefix, _CFBundleLprojExtension); + _CFAppendTrailingPathSlash2(pathPrefix); } - - if (subDirLen) { - memmove(valueBuff+pathOfDirWithSlashLen, subDir, subDirLen*sizeof(UniChar)); - pathOfDirWithSlashLen += subDirLen; - if (subDir[subDirLen-1] != _CFGetSlash()) { - _CFAppendTrailingPathSlash(valueBuff, &pathOfDirWithSlashLen, valueBufferLen); + if (subdirectory) { + if (pathPrefix) { + CFStringAppend(pathPrefix, subdirectory); + } else { + pathPrefix = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, subdirectory); + } + UniChar lastChar = CFStringGetCharacterAtIndex(subdirectory, CFStringGetLength(subdirectory)-1); + if (lastChar != _CFGetSlash()) { + _CFAppendTrailingPathSlash2(pathPrefix); } } - UniChar *fileNameBuffer = valueBuff + pathOfDirWithSlashLen; - char *cPathBuff = (char *)malloc(sizeof(char) * cPathBuffLen); - - if (CFStringGetFileSystemRepresentation(pathOfDir, cPathBuff, cPathBuffLen)) { -// this is a fix for traversing ouside of a bundle security issue: 8302591 -// it will be enabled after the bug 10956699 gets fixed -#ifdef CFBUNDLE_NO_TRAVERSE_OUTSIDE -#endif // CFBUNDLE_NO_TRAVERSE_OUTSIDE + _CFIterateDirectory(pathOfDir, ^Boolean(CFStringRef fileName, uint8_t fileType) { + CFStringRef startType = NULL, endType = NULL, noProductOrPlatform = NULL; + _CFBundleFileVersion fileVersion; + _CFBundleSplitFileName(fileName, &noProductOrPlatform, &endType, &startType, product, platform, &fileVersion); -#if DEPLOYMENT_TARGET_WINDOWS - wchar_t pathBuf[CFMaxPathSize]; - CFStringRef pathInUTF8 = CFStringCreateWithCString(kCFAllocatorSystemDefault, cPathBuff, kCFStringEncodingUTF8); - CFIndex pathInUTF8Len = CFStringGetLength(pathInUTF8); - if (pathInUTF8Len > CFMaxPathSize) pathInUTF8Len = CFMaxPathSize; - - CFStringGetCharacters(pathInUTF8, CFRangeMake(0, pathInUTF8Len), (UniChar *)pathBuf); - pathBuf[pathInUTF8Len] = 0; - CFRelease(pathInUTF8); - WIN32_FIND_DATAW filePt; - HANDLE handle; + CFStringRef pathToFile; + if (pathPrefix && CFStringGetLength(pathPrefix) > 0) { + CFMutableStringRef tmp = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, pathPrefix); + CFStringAppend(tmp, fileName); + pathToFile = (CFStringRef)tmp; + } else { + pathToFile = (CFStringRef)CFRetain(fileName); + } + + // If this file is a directory, the path needs to include a trailing slash so we can later create the right kind of CFURL object + Boolean appendSlash = false; + if (fileType == DT_DIR) { + appendSlash = true; + } +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD + else if (fileType == DT_UNKNOWN) { + Boolean isDir = false; + char subdirPath[CFMaxPathLength]; + struct stat statBuf; + if (CFStringGetFileSystemRepresentation(pathOfDir, subdirPath, sizeof(subdirPath))) { + strlcat(subdirPath, "/", sizeof(subdirPath)); + char fileNameBuf[CFMaxPathLength]; + if (CFStringGetFileSystemRepresentation(fileName, fileNameBuf, sizeof(fileNameBuf))) { + strlcat(subdirPath, fileNameBuf, sizeof(subdirPath)); + if (stat(subdirPath, &statBuf) == 0) { + isDir = ((statBuf.st_mode & S_IFMT) == S_IFDIR); + } + if (isDir) { + appendSlash = true; + } + } + } + } +#endif + if (appendSlash) { + // This is fairly inefficient + CFMutableStringRef tmp = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, pathToFile); + _CFAppendTrailingPathSlash2(tmp); + CFRelease(pathToFile); + pathToFile = (CFStringRef)tmp; + } - if (pathInUTF8Len + 2 >= CFMaxPathLength) { - result = false; + // put it into all file array + if (!hasFileAdded) { + CFArrayAppendValue(allFiles, pathToFile); } - pathBuf[pathInUTF8Len] = '\\'; - pathBuf[pathInUTF8Len + 1] = '*'; - pathBuf[pathInUTF8Len + 2] = '\0'; - handle = FindFirstFileW(pathBuf, (LPWIN32_FIND_DATAW)&filePt); - if (INVALID_HANDLE_VALUE == handle) { - pathBuf[pathInUTF8Len] = '\0'; - result = false; - } - if (!result) { - free(cPathBuff); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, valueBuff); - CFRelease(valueStr); - return result; + if (startType) { + _CFBundleAddValueForType(startType, queryTable, typeDir, pathToFile, addedTypes, firstLproj); } - do { - CFIndex nameLen = wcslen(filePt.cFileName); - if (filePt.cFileName[0] == '.' && (nameLen == 1 || (nameLen == 2 && filePt.cFileName[1] == '.'))) { - continue; + if (endType) { + _CFBundleAddValueForType(endType, queryTable, typeDir, pathToFile, addedTypes, firstLproj); + } + + if (fileVersion == _CFBundleFileVersionNoProductNoPlatform || fileVersion == _CFBundleFileVersionUnmatched) { + // No product/no platform, or unmatched files get added directly to the query table. + CFStringRef prevPath = (CFStringRef)CFDictionaryGetValue(queryTable, fileName); + if (!prevPath) { + CFDictionarySetValue(queryTable, fileName, pathToFile); + } + } else { + // If the file has a product or platform extension, we add the full name to the query table so that it may be found using that name. But only if it doesn't already exist. + CFStringRef prevPath = (CFStringRef)CFDictionaryGetValue(queryTable, fileName); + if (!prevPath) { + CFDictionarySetValue(queryTable, fileName, pathToFile); } - CFStringRef file = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const uint8_t *)filePt.cFileName, nameLen * sizeof(wchar_t), kCFStringEncodingUTF16, NO); -#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD - DIR *dirp = NULL; - struct dirent* dent; - if ( result && (dirp = opendir(cPathBuff))) { - while ((dent = readdir(dirp))) { - -#if DEPLOYMENT_TARGET_LINUX - CFIndex nameLen = strlen(dent->d_name); -#else - CFIndex nameLen = dent->d_namlen; -#endif - if (0 == nameLen || 0 == dent->d_fileno || ('.' == dent->d_name[0] && (1 == nameLen || (2 == nameLen && '.' == dent->d_name[1]) || '_' == dent->d_name[1]))) - continue; - - CFStringRef file = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dent->d_name); -#else -#error unknown architecture, not implemented -#endif - if (file) { - - CFIndex fileNameLen = CFStringGetLength(file); - if (fileNameLen > CFMaxPathSize) fileNameLen = CFMaxPathSize; - CFStringGetCharacters(file, CFRangeMake(0, fileNameLen), fileNameBuffer); - CFIndex valueTotalLen = pathOfDirWithSlashLen + fileNameLen; - -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD - // construct the path for a file, which is the value in the query table - // if it is a dir - if (dent->d_type == DT_DIR) { - _CFAppendTrailingPathSlash(valueBuff, &valueTotalLen, valueBufferLen); - } else if (dent->d_type == DT_UNKNOWN) { - Boolean isDir = false; - char subdirPath[CFMaxPathLength]; - struct stat statBuf; - strlcpy(subdirPath, cPathBuff, sizeof(subdirPath)); - strlcat(subdirPath, "/", sizeof(subdirPath)); - strlcat(subdirPath, dent->d_name, sizeof(subdirPath)); - if (stat(subdirPath, &statBuf) == 0) { - isDir = ((statBuf.st_mode & S_IFMT) == S_IFDIR); - } - if (isDir) { - _CFAppendTrailingPathSlash(valueBuff, &valueTotalLen, valueBufferLen); - } - } -#elif DEPLOYMENT_TARGET_WINDOWS - if ((filePt.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - _CFAppendTrailingPathSlash(valueBuff, &valueTotalLen, valueBufferLen); - } -#endif - CFStringSetExternalCharactersNoCopy(valueStr, valueBuff, valueTotalLen, valueBufferLen); - CFTypeRef value = CFStringCreateCopy(kCFAllocatorSystemDefault, valueStr); - - // put it into all file array - if (!hasFileAdded) { - CFArrayAppendValue(allFiles, value); - } - - // put it into type array - // search the type from the end - CFRange backDotPosition, dotPosition; - Boolean foundDot = _CFBundleFindCharacterInStr(fileNameBuffer, '.', YES, fileNameLen-1, fileNameLen, &backDotPosition); - - if (foundDot && backDotPosition.location != (fileNameLen-1)) { - _CFBundleAddValueForType(type, fileNameBuffer, queryTable, backDotPosition, fileNameLen, typeDir, value, addedTypes, firstLproj); - } - - // search the type from the beginning - //CFRange dotPosition = CFStringFind(file, _CFBundleDot, kCFCompareEqualTo); - foundDot = _CFBundleFindCharacterInStr(fileNameBuffer, '.', NO, 0, fileNameLen, &dotPosition); - if (dotPosition.location != backDotPosition.location && foundDot) { - _CFBundleAddValueForType(type, fileNameBuffer, queryTable, dotPosition, fileNameLen, typeDir, value, addedTypes, firstLproj); - } - - // check if the file is product and platform specific - CFRange productRange, platformRange; - _CFBundleFileVersion fileVersion = _CFBundleCheckFileProductAndPlatform(file, fileNameBuffer, fileNameLen, CFRangeMake(0, fileNameLen), product, platform, &productRange, &platformRange, productLen); - - if (fileVersion == _CFBundleFileVersionNoProductNoPlatform || fileVersion == _CFBundleFileVersionUnmatched) { - // No product/no platform, or unmatched files get added directly to the query table. - CFStringRef prevPath = (CFStringRef)CFDictionaryGetValue(queryTable, file); - if (!prevPath) { - CFDictionarySetValue(queryTable, file, value); + // Then we add the more specific name as well, replacing the existing one if this is a more specific version. + if (noProductOrPlatform) { + // add the path of the key into the query table + prevPath = (CFStringRef) CFDictionaryGetValue(queryTable, noProductOrPlatform); + if (!prevPath) { + CFDictionarySetValue(queryTable, noProductOrPlatform, pathToFile); + } else { + if (!lprojName || CFStringHasPrefix(prevPath, lprojName)) { + // we need to know the version of exisiting path to see if we can replace it by the current path + CFRange searchRange; + if (lprojName) { + searchRange.location = CFStringGetLength(lprojName); + searchRange.length = CFStringGetLength(prevPath) - searchRange.location; + } else { + searchRange.location = 0; + searchRange.length = CFStringGetLength(prevPath); } - } else { - // If the file has a product or platform extension, we add the full name to the query table so that it may be found using that name. - // Then we add the more specific name as well. - CFDictionarySetValue(queryTable, file, value); - - CFIndex searchOffset = platformLen; - CFStringRef key = NULL; - - // set the key accordining to the version of the file (product and platform) - switch (fileVersion) { + _CFBundleFileVersion prevFileVersion = _CFBundleCheckFileProductAndPlatform(prevPath, searchRange, product, platform); + switch (prevFileVersion) { + case _CFBundleFileVersionNoProductNoPlatform: + CFDictionarySetValue(queryTable, noProductOrPlatform, pathToFile); + break; case _CFBundleFileVersionWithProductNoPlatform: - platformRange = productRange; - searchOffset = productLen; + if (fileVersion == _CFBundleFileVersionWithProductWithPlatform) CFDictionarySetValue(queryTable, noProductOrPlatform, pathToFile); + break; case _CFBundleFileVersionNoProductWithPlatform: - case _CFBundleFileVersionWithProductWithPlatform: - foundDot = _CFBundleFindCharacterInStr(fileNameBuffer, '.', NO, platformRange.location+searchOffset, fileNameLen-platformRange.location-searchOffset, &dotPosition); - if (foundDot) { - CFMutableStringRef mutableKey = CFStringCreateMutable(kCFAllocatorSystemDefault, platformRange.location + (fileNameLen - dotPosition.location)); - CFStringAppendCharacters(mutableKey, fileNameBuffer, platformRange.location); - CFStringAppendCharacters(mutableKey, fileNameBuffer+dotPosition.location, fileNameLen - dotPosition.location); - key = (CFStringRef)mutableKey; - } else { - key = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, fileNameBuffer, platformRange.location); - } + CFDictionarySetValue(queryTable, noProductOrPlatform, pathToFile); break; default: - CFLog(kCFLogLevelError, CFSTR("CFBundle: Unknown kind of file (%d) when creating CFBundle: %@"), pathOfDir); break; } - - if (key) { - // add the path of the key into the query table - CFStringRef prevPath = (CFStringRef) CFDictionaryGetValue(queryTable, key); - if (!prevPath) { - CFDictionarySetValue(queryTable, key, value); - } else { - if (!lprojName || CFStringHasPrefix(prevPath, lprojName)) { - // we need to know the version of exisiting path to see if we can replace it by the current path - CFRange searchRange; - if (lprojName) { - searchRange.location = CFStringGetLength(lprojName); - searchRange.length = CFStringGetLength(prevPath) - searchRange.location; - } else { - searchRange.location = 0; - searchRange.length = CFStringGetLength(prevPath); - } - _CFBundleFileVersion prevFileVersion = _CFBundleCheckFileProductAndPlatform(prevPath, NULL, 0, searchRange, product, platform, &productRange, &platformRange, productLen); - switch (prevFileVersion) { - case _CFBundleFileVersionNoProductNoPlatform: - CFDictionarySetValue(queryTable, key, value); - break; - case _CFBundleFileVersionWithProductNoPlatform: - if (fileVersion == _CFBundleFileVersionWithProductWithPlatform) CFDictionarySetValue(queryTable, key, value); - break; - case _CFBundleFileVersionNoProductWithPlatform: - CFDictionarySetValue(queryTable, key, value); - break; - default: - break; - } - } - } - - CFRelease(key); - } } - - CFRelease(value); - CFRelease(file); } - - -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD } - closedir(dirp); - } else { // opendir - result = false; - } -#elif DEPLOYMENT_TARGET_WINDOWS - } while ((FindNextFileW(handle, &filePt))); - FindClose(handle); - pathBuf[pathInUTF8Len] = '\0'; -#endif - - } else { // the path counld not be resolved to be a file system representation - result = false; - } + } + + if (pathToFile) CFRelease(pathToFile); + if (startType) CFRelease(startType); + if (endType) CFRelease(endType); + if (noProductOrPlatform) CFRelease(noProductOrPlatform); + + return true; + }); - free(cPathBuff); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, valueBuff); - CFRelease(valueStr); + if (pathPrefix) CFRelease(pathPrefix); return result; } -__private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, UniChar *resDir, CFIndex resDirLen, UniChar *subDir, CFIndex subDirLen) + +static CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourcesDirectory, CFStringRef subdirectory) { - const CFIndex pathBufferSize = 2*CFMaxPathSize+resDirLen+subDirLen+2; - UniChar *pathBuffer = (UniChar *) CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * pathBufferSize, 0); CFMutableDictionaryRef queryTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFMutableArrayRef allFiles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); @@ -3316,37 +1790,30 @@ __private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef b CFStringRef product = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("~%@"), productName); CFStringRef platform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("-%@"), platformName); - CFStringRef bundlePath = NULL; + CFMutableStringRef path = NULL; if (bundle) { - bundlePath = _CFBundleGetBundlePath(bundle); - CFRetain(bundlePath); + path = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, bundle->_bundleBasePath); } else { CFURLRef url = CFURLCopyAbsoluteURL(bundleURL); - bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE); + CFStringRef bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE); CFRelease(url); + path = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, bundlePath); + CFRelease(bundlePath); } - // bundlePath is an actual path, so it should not have a length greater than CFMaxPathSize - CFIndex pathLen = CFStringGetLength(bundlePath); - CFStringGetCharacters(bundlePath, CFRangeMake(0, pathLen), pathBuffer); - CFRelease(bundlePath); - Boolean appendSucc = true; - if (resDirLen > 0) { // should not fail, buffer has enought space - appendSucc = _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, resDir, resDirLen); + if (resourcesDirectory) { + _CFAppendPathComponent2(path, resourcesDirectory); } - CFStringRef basePath = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathBuffer, pathLen); + // Record the length of the base path, so we can strip off the stuff we'll be appending later + CFIndex basePathLen = CFStringGetLength(path); - if (subDirLen > 0) { // should not fail, buffer has enought space - appendSucc = _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, subDir, subDirLen); + if (subdirectory) { + _CFAppendPathComponent2(path, subdirectory); } - - CFStringRef pathToRead = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathBuffer, pathLen); - // read the content in sub dir and put them into query table - _CFBundleReadDirectory(pathToRead, bundle, bundleURL, resDir, subDir, subDirLen, allFiles, false, type, queryTable, typeDir, NULL, false, product, platform, NULL, false); - - CFRelease(pathToRead); + _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, false, type, 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); @@ -3356,28 +1823,20 @@ __private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef b CFIndex numLprojs = languages ? CFArrayGetCount(languages) : 0; CFMutableDictionaryRef addedTypes = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFIndex basePathLen = CFStringGetLength(basePath); Boolean hasFileAdded = false; Boolean firstLproj = true; - + // First, search lproj for user's chosen language if (numLprojs >= 1) { CFStringRef lprojTarget = (CFStringRef)CFArrayGetValueAtIndex(languages, 0); - // lprojTarget is from _CFBundleGetLanguageSearchList, so it should not have a length greater than CFMaxPathSize - UniChar lprojBuffer[CFMaxPathSize]; - CFIndex lprojLen = CFStringGetLength(lprojTarget); - CFStringGetCharacters(lprojTarget, CFRangeMake(0, lprojLen), lprojBuffer); - - pathLen = basePathLen; - _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, lprojBuffer, lprojLen); - _CFAppendPathExtension(pathBuffer, &pathLen, pathBufferSize, _LprojUniChars, _LprojLen); - if (subDirLen > 0) { - _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, subDir, subDirLen); - } - pathToRead = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathBuffer, pathLen); - _CFBundleReadDirectory(pathToRead, bundle, bundleURL, resDir, subDir, subDirLen, allFiles, hasFileAdded, type, queryTable, typeDir, addedTypes, firstLproj, product, platform, lprojTarget, true); - CFRelease(pathToRead); - + _CFAppendPathComponent2(path, lprojTarget); + _CFAppendPathExtension2(path, _CFBundleLprojExtension); + if (subdirectory) { + _CFAppendPathComponent2(path, subdirectory); + } + _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, hasFileAdded, type, 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)) { hasFileAdded = true; } @@ -3385,39 +1844,30 @@ __private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef b } // Next, search Base.lproj folder - pathLen = basePathLen; - _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, _BaseUniChars, _BaseLen); - _CFAppendPathExtension(pathBuffer, &pathLen, pathBufferSize, _LprojUniChars, _LprojLen); - if (subDirLen > 0) { - _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, subDir, subDirLen); + _CFAppendPathComponent2(path, _CFBundleBaseDirectory); + _CFAppendPathExtension2(path, _CFBundleLprojExtension); + if (subdirectory) { + _CFAppendPathComponent2(path, subdirectory); } - pathToRead = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathBuffer, pathLen); - _CFBundleReadDirectory(pathToRead, bundle, bundleURL, resDir, subDir, subDirLen, allFiles, hasFileAdded, type, queryTable, typeDir, addedTypes, YES, product, platform, _CFBundleBaseDirectory, true); - CFRelease(pathToRead); + _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, hasFileAdded, type, 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)) { hasFileAdded = true; } - + // Finally, search remaining languages (development language first) if (numLprojs >= 2) { // for each lproj we are interested in, read the content and put them into query table for (CFIndex i = 1; i < CFArrayGetCount(languages); i++) { CFStringRef lprojTarget = (CFStringRef) CFArrayGetValueAtIndex(languages, i); - // lprojTarget is from _CFBundleGetLanguageSearchList, so it should not have a length greater than CFMaxPathSize - UniChar lprojBuffer[CFMaxPathSize]; - CFIndex lprojLen = CFStringGetLength(lprojTarget); - CFStringGetCharacters(lprojTarget, CFRangeMake(0, lprojLen), lprojBuffer); - - pathLen = basePathLen; - _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, lprojBuffer, lprojLen); - _CFAppendPathExtension(pathBuffer, &pathLen, pathBufferSize, _LprojUniChars, _LprojLen); - if (subDirLen > 0) { - _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, subDir, subDirLen); + _CFAppendPathComponent2(path, lprojTarget); + _CFAppendPathExtension2(path, _CFBundleLprojExtension); + if (subdirectory) { + _CFAppendPathComponent2(path, subdirectory); } - pathToRead = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathBuffer, pathLen); - _CFBundleReadDirectory(pathToRead, bundle, bundleURL, resDir, subDir, subDirLen, allFiles, hasFileAdded, type, queryTable, typeDir, addedTypes, false, product, platform, lprojTarget, true); - CFRelease(pathToRead); + _CFBundleReadDirectory(path, bundle, subdirectory, allFiles, hasFileAdded, type, 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)) { hasFileAdded = true; @@ -3426,6 +1876,7 @@ __private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef b } CFRelease(addedTypes); + CFRelease(path); // put the array of all files in sub dir to the query table if (CFArrayGetCount(allFiles) > 0) { @@ -3437,28 +1888,48 @@ __private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef b CFRelease(allFiles); CFRelease(typeDir); CFRelease(type); - CFRelease(basePath); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, pathBuffer); + return queryTable; } - -static CFURLRef _CFBundleCreateURLFromPath(CFStringRef path, UniChar slash, UniChar *urlBuffer, CFIndex urlBufferLen, CFMutableStringRef urlStr) + +// caller need to release the table +static CFDictionaryRef _CFBundleCopyQueryTable(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourcesDirectory, CFStringRef subdirectory) { - CFURLRef url = NULL; - // path is a part of an actual path in the query table, so it should not have a length greater than the buffer size - CFIndex pathLen = CFStringGetLength(path); - CFStringGetCharacters(path, CFRangeMake(0, pathLen), urlBuffer+urlBufferLen); - CFStringSetExternalCharactersNoCopy(urlStr, urlBuffer, urlBufferLen+pathLen, CFMaxPathSize); - if (CFStringGetCharacterAtIndex(path, pathLen-1) == slash) { - url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, YES); + CFDictionaryRef subTable = NULL; + + // take the lock + if (bundle) { + CFMutableStringRef argDirStr = NULL; + if (subdirectory) { + argDirStr = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, resourcesDirectory); + _CFAppendPathComponent2(argDirStr, subdirectory); + } else { + argDirStr = (CFMutableStringRef)CFRetain(resourcesDirectory); + } + + __CFSpinLock(&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); + + CFDictionarySetValue(bundle->_queryTable, argDirStr, subTable); + } else { + CFRetain(subTable); + } + __CFSpinUnlock(&bundle->_queryLock); + CFRelease(argDirStr); } else { - url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, NO); + subTable = _CFBundleCreateQueryTableAtPath(NULL, bundleURL, languages, resourcesDirectory, subdirectory); } - return url; + return subTable; } - + static CFURLRef _CFBundleCreateRelativeURLFromBaseAndPath(CFStringRef path, CFURLRef base, UniChar slash, CFStringRef slashStr) { CFURLRef url = NULL; @@ -3472,9 +1943,9 @@ static CFURLRef _CFBundleCreateRelativeURLFromBaseAndPath(CFStringRef path, CFUR needToRelease = true; } if (CFStringGetCharacterAtIndex(path, CFStringGetLength(path)-1) == slash) { - url = (CFURLRef)CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, path, PLATFORM_PATH_STYLE, YES, base); + url = (CFURLRef)CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, path, PLATFORM_PATH_STYLE, true, base); } else { - url = (CFURLRef)CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, path, PLATFORM_PATH_STYLE, NO, base); + url = (CFURLRef)CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, path, PLATFORM_PATH_STYLE, false, base); } if (needToRelease) { CFRelease(base); @@ -3482,7 +1953,7 @@ static CFURLRef _CFBundleCreateRelativeURLFromBaseAndPath(CFStringRef path, CFUR } return url; } - + static void _CFBundleFindResourcesWithPredicate(CFMutableArrayRef interResult, CFDictionaryRef queryTable, Boolean (^predicate)(CFStringRef filename, Boolean *stop), Boolean *stop) { CFIndex dictSize = CFDictionaryGetCount(queryTable); @@ -3504,32 +1975,31 @@ static void _CFBundleFindResourcesWithPredicate(CFMutableArrayRef interResult, C if (*stop) break; } } - -static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, UniChar *resDir, CFIndex resDirLen, UniChar *subDirBuffer, CFIndex subDirLen, CFStringRef subDir, CFStringRef key, CFStringRef lproj, UniChar *lprojBuff, Boolean returnArray, Boolean localized, uint8_t bundleVersion, Boolean (^predicate)(CFStringRef filename, Boolean *stop)) + +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)) { CFTypeRef value = NULL; Boolean stop = false; // for predicate CFMutableArrayRef interResult = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); CFDictionaryRef subTable = NULL; - + + CFMutableStringRef path = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, resourcesDirectory); if (1 == bundleVersion) { - CFIndex savedResDirLen = resDirLen; + CFIndex savedPathLength = CFStringGetLength(path); // add the non-localized resource dir - Boolean appendSucc = _CFAppendPathComponent(resDir, &resDirLen, CFMaxPathSize, _GlobalResourcesUniChars, _GlobalResourcesLen); - if (appendSucc) { - subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, resDir, resDirLen, subDirBuffer, subDirLen); - if (predicate) { - _CFBundleFindResourcesWithPredicate(interResult, subTable, predicate, &stop); - } else { - value = CFDictionaryGetValue(subTable, key); - } + _CFAppendPathComponent2(path, _CFBundleNonLocalizedResourcesDirectoryName); + subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, path, subDir); + if (predicate) { + _CFBundleFindResourcesWithPredicate(interResult, subTable, predicate, &stop); + } else { + value = CFDictionaryGetValue(subTable, key); } - resDirLen = savedResDirLen; + CFStringDelete(path, CFRangeMake(savedPathLength, CFStringGetLength(path) - savedPathLength)); // Strip the string back to the base path } if (!value && !stop) { if (subTable) CFRelease(subTable); - subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, resDir, resDirLen, subDirBuffer, subDirLen); + subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, path, subDir); if (predicate) { _CFBundleFindResourcesWithPredicate(interResult, subTable, predicate, &stop); } else { @@ -3561,11 +2031,11 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, // if we have subdir, we find the subdir and see if it is after the base path (bundle path + res dir) Boolean searchForLocalization = false; - if (subDirLen) { + if (subDir && CFStringGetLength(subDir) > 0) { if (CFStringFindWithOptions(pathValue, subDir, searchRange, kCFCompareEqualTo, &resultRange) && resultRange.location != searchRange.location) { searchForLocalization = true; } - } else if (!subDirLen && searchRange.length != 0) { + } else if (!(subDir && CFStringGetLength(subDir) > 0) && searchRange.length != 0) { if (CFStringFindWithOptions(pathValue, _CFBundleLprojExtensionWithDot, searchRange, kCFCompareEqualTo, &resultRange) && resultRange.location + 7 < pathValueLen) { searchForLocalization = true; } @@ -3599,16 +2069,13 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, // we fetch the result for a given lproj and join them with the nonlocalized result fetched above if (lpLen && checkLP) { - CFIndex lprojBuffLen = lpLen; - // lprojBuff is allocated with the actual size of lproj - CFStringGetCharacters(lproj, CFRangeMake(0, lpLen), lprojBuff); - _CFAppendPathExtension(lprojBuff, &lprojBuffLen, lprojBuffLen+7, _LprojUniChars, _LprojLen); - - if (subDirLen) { - _CFAppendTrailingPathSlash(lprojBuff, &lprojBuffLen, lprojBuffLen+1); + CFMutableStringRef lprojSubdirName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, lproj); + _CFAppendPathExtension2(lprojSubdirName, _CFBundleLprojExtension); + if (subDir && CFStringGetLength(subDir) > 0) { + _CFAppendTrailingPathSlash2(lprojSubdirName); } - subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, resDir, resDirLen, lprojBuff, subDirLen+lprojBuffLen); - + subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, path, lprojSubdirName); + CFRelease(lprojSubdirName); value = CFDictionaryGetValue(subTable, key); if (value) { @@ -3626,25 +2093,22 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFTypeRef result = NULL; if (CFArrayGetCount(interResult) > 0) { UniChar slash = _CFGetSlash(); - UniChar *urlBuffer = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * CFMaxPathSize, 0); - CFMutableStringRef urlStr = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull); - CFStringRef bundlePath = NULL; + CFMutableStringRef urlStr = NULL; if (bundle) { - bundlePath = _CFBundleGetBundlePath(bundle); - CFRetain(bundlePath); + urlStr = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, bundle->_bundleBasePath); } else { CFURLRef url = CFURLCopyAbsoluteURL(bundleURL); - bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE); + CFStringRef bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE); + urlStr = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, bundlePath); CFRelease(url); + CFRelease(bundlePath); } - CFIndex urlBufferLen = CFStringGetLength(bundlePath); - CFStringGetCharacters(bundlePath, CFRangeMake(0, urlBufferLen), urlBuffer); - CFRelease(bundlePath); - if (resDirLen) { - _CFAppendPathComponent(urlBuffer, &urlBufferLen, CFMaxPathSize, resDir, resDirLen); + if (resourcesDirectory && CFStringGetLength(resourcesDirectory)) { + _CFAppendPathComponent2(urlStr, resourcesDirectory); } - _CFAppendTrailingPathSlash(urlBuffer, &urlBufferLen, CFMaxPathSize); + + _CFAppendTrailingPathSlash2(urlStr); if (!returnArray) { Boolean isOnlyTypeOrAllFiles = CFStringHasPrefix(key, _CFBundleTypeIndicator); @@ -3652,25 +2116,27 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef resultPath = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)interResult, 0); if (!isOnlyTypeOrAllFiles) { - result = (CFURLRef)_CFBundleCreateURLFromPath((CFStringRef)resultPath, slash, urlBuffer, urlBufferLen, urlStr); - } else { // need to create relative URLs for binary compatibility issues - CFStringSetExternalCharactersNoCopy(urlStr, urlBuffer, urlBufferLen, CFMaxPathSize); - CFURLRef base = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, YES); - CFStringRef slashStr = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &slash, 1); - result = (CFURLRef)_CFBundleCreateRelativeURLFromBaseAndPath(resultPath, base, slash, slashStr); - CFRelease(slashStr); + // path is a part of an actual path in the query table, so it should not have a length greater than the buffer size + CFStringAppend(urlStr, resultPath); + if (CFStringGetCharacterAtIndex(resultPath, CFStringGetLength(resultPath)-1) == slash) { + result = (CFURLRef)CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, true); + } else { + result = (CFURLRef)CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, false); + } + } else { + // need to create relative URLs for binary compatibility issues + CFURLRef base = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, true); + result = (CFURLRef)_CFBundleCreateRelativeURLFromBaseAndPath(resultPath, base, slash, _CFGetSlashStr()); CFRelease(base); } } else { // need to create relative URLs for binary compatibility issues CFIndex numOfPaths = CFArrayGetCount((CFArrayRef)interResult); - CFStringSetExternalCharactersNoCopy(urlStr, urlBuffer, urlBufferLen, CFMaxPathSize); - CFURLRef base = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, YES); - CFStringRef slashStr = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &slash, 1); + CFURLRef base = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, true); CFMutableArrayRef urls = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); for (CFIndex i = 0; i < numOfPaths; i++) { CFStringRef path = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)interResult, i); - CFURLRef url = _CFBundleCreateRelativeURLFromBaseAndPath(path, base, slash, slashStr); + CFURLRef url = _CFBundleCreateRelativeURLFromBaseAndPath(path, base, slash, _CFGetSlashStr()); CFArrayAppendValue(urls, url); CFRelease(url); } @@ -3678,121 +2144,87 @@ static CFTypeRef _CFBundleCopyURLsOfKey(CFBundleRef bundle, CFURLRef bundleURL, CFRelease(base); } CFRelease(urlStr); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, urlBuffer); } else if (returnArray) { result = CFRetain(interResult); } - + if (path) CFRelease(path); CFRelease(interResult); return result; } -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)) +#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)) { - CFIndex rnameLen = 0; - CFIndex typeLen = resourceType ? CFStringGetLength(resourceType) : 0; - CFIndex lprojLen = lproj ? CFStringGetLength(lproj) + 7 : 0; // 7 is the length of ".lproj/" + + // Don't use any path info passed into the resource name + CFStringRef realResourceName = NULL; CFStringRef subPathFromResourceName = NULL; - CFIndex subPathFromResourceNameLen = 0; + if (resourceName) { - UniChar tmpNameBuffer[CFMaxPathSize]; - rnameLen = CFStringGetLength(resourceName); - if (rnameLen > CFMaxPathSize) rnameLen = CFMaxPathSize; - CFStringGetCharacters(resourceName, CFRangeMake(0, rnameLen), tmpNameBuffer); - CFIndex rnameIndex = _CFStartOfLastPathComponent(tmpNameBuffer, rnameLen); - if (rnameIndex != 0) { - resourceName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, tmpNameBuffer+rnameIndex, rnameLen - rnameIndex); - subPathFromResourceName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, tmpNameBuffer, rnameIndex-1); - subPathFromResourceNameLen = rnameIndex-1; - } else { - CFRetain(resourceName); + CFIndex slashLocation = -1; + realResourceName = _CFCreateLastPathComponent(kCFAllocatorSystemDefault, resourceName, &slashLocation); + if (slashLocation > 0) { + // do not include the / + subPathFromResourceName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, resourceName, CFRangeMake(0, slashLocation)); } + // 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]; - CFStringRef newResName = NULL; - if (CFStringGetFileSystemRepresentation(resourceName, buff, CFMaxPathSize)) { - newResName = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); - } - CFStringRef tmpStr = resourceName; - resourceName = newResName ? newResName : (CFStringRef)CFRetain(resourceName); - rnameLen = CFStringGetLength(resourceName); - CFRelease(tmpStr); - } - CFIndex subDirLen = subPath ? CFStringGetLength(subPath) : 0; - if (subDirLen == 0) subPath = NULL; - if (subDirLen && subPathFromResourceName) { - subDirLen += (subPathFromResourceNameLen + 1); - } else if (subPathFromResourceNameLen) { - subDirLen = subPathFromResourceNameLen; - } - - // the nameBuff have the format: [resourceName].[resourceType][lprojName.lproj/][subPath][resource dir] - UniChar *nameBuff = (UniChar *) CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * (rnameLen + 1 + typeLen + subDirLen + lprojLen + CFMaxPathSize), 0); - UniChar *typeBuff = rnameLen ? nameBuff + rnameLen + 1 : nameBuff + CFStringGetLength(_CFBundleTypeIndicator) + 1; - UniChar *lprojBuffer = typeBuff + typeLen; - UniChar *subDirBuffer = lprojBuffer + lprojLen; - UniChar *resDir = subDirBuffer + subDirLen; - - CFStringRef key = NULL; - - CFIndex typeP = 0; - if (typeLen && CFStringGetCharacterAtIndex(resourceType, 0) == '.') { - typeP = 1; - typeLen--; - } - if (rnameLen && typeLen) { - CFStringGetCharacters(resourceName, CFRangeMake(0, rnameLen), nameBuff); - nameBuff[rnameLen] = '.'; - CFStringGetCharacters(resourceType, CFRangeMake(typeP, typeLen), typeBuff); - key = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, nameBuff, rnameLen+typeLen+1); - } else if (rnameLen) { - CFStringGetCharacters(resourceName, CFRangeMake(0, rnameLen), nameBuff); - key = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, nameBuff, rnameLen); - } else if (typeLen) { - rnameLen = CFStringGetLength(_CFBundleTypeIndicator); - CFStringGetCharacters(_CFBundleTypeIndicator, CFRangeMake(0, rnameLen), nameBuff); - nameBuff[rnameLen] = '.'; - CFStringGetCharacters(resourceType, CFRangeMake(typeP, typeLen), typeBuff); - key = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, nameBuff, rnameLen+typeLen+1); + if (CFStringGetFileSystemRepresentation(realResourceName, buff, CFMaxPathSize)) { + CFRelease(realResourceName); + realResourceName = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff); + } + } + + CFMutableStringRef key = NULL; + const static UniChar extensionSep = '.'; + + if (realResourceName && CFStringGetLength(realResourceName) > 0 && resourceType && CFStringGetLength(resourceType) > 0) { + // Testing shows that using a mutable string here is significantly faster than using the format functions. + key = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, realResourceName); + // Don't re-append a . if the resource name already has one + if (CFStringGetCharacterAtIndex(resourceType, 0) != '.') CFStringAppendCharacters(key, &extensionSep, 1); + CFStringAppend(key, resourceType); + } else if (realResourceName && CFStringGetLength(realResourceName) > 0) { + key = (CFMutableStringRef)CFRetain(realResourceName); + } else if (resourceType && CFStringGetLength(resourceType) > 0) { + key = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, _CFBundleTypeIndicator); + // Don't re-append a . if the resource name already has one + if (CFStringGetCharacterAtIndex(resourceType, 0) != '.') CFStringAppendCharacters(key, &extensionSep, 1); + CFStringAppend(key, resourceType); } else { - key = (CFStringRef)CFRetain(_CFBundleAllFiles); + key = (CFMutableStringRef)CFRetain(_CFBundleAllFiles); } - if (subDirLen) { - CFIndex subPathLen = 0; - if (subPath) { - subPathLen = CFStringGetLength(subPath); - CFStringGetCharacters(subPath, CFRangeMake(0, subPathLen), subDirBuffer); - if (subPathFromResourceName) _CFAppendTrailingPathSlash(subDirBuffer, &subPathLen, subDirLen); - } - if (subPathFromResourceName) { - CFStringGetCharacters(subPathFromResourceName, CFRangeMake(0, subPathFromResourceNameLen), subDirBuffer+subPathLen); - subPathLen += subPathFromResourceNameLen; - subPath = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, subDirBuffer, subPathLen); - } else { - CFRetain(subPath); - } - } + CFStringRef realSubdirectory = NULL; - // Init the one-time-only unichar buffers. - _CFEnsureStaticBuffersInited(); + if (subPath && CFStringGetLength(subPath) && !subPathFromResourceName) { + realSubdirectory = (CFStringRef)CFRetain(subPath); + } else if (subPathFromResourceName && CFStringGetLength(subPathFromResourceName)) { + realSubdirectory = (CFStringRef)CFRetain(subPathFromResourceName); + } - CFIndex resDirLen = 0; uint8_t bundleVersion = bundle ? _CFBundleLayoutVersion(bundle) : 0; if (bundleURL && !languages) { languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, bundleURL, &bundleVersion); } else if (languages) { CFRetain(languages); } - - _CFBundleSetResourceDir(resDir, &resDirLen, CFMaxPathSize, bundleVersion); - CFTypeRef returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, languages, resDir, resDirLen, subDirBuffer, subDirLen, subPath, key, lproj, lprojBuffer, returnArray, localized, bundleVersion, predicate); - + CFStringRef resDir = _CFBundleGetResourceDirForVersion(bundleVersion); + + CFTypeRef returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, languages, resDir, realSubdirectory, key, lproj, returnArray, localized, bundleVersion, predicate); + if ((!returnValue || (CFGetTypeID(returnValue) == CFArrayGetTypeID() && CFArrayGetCount((CFArrayRef)returnValue) == 0)) && (0 == bundleVersion || 2 == bundleVersion)) { CFStringRef bundlePath = NULL; if (bundle) { - bundlePath = _CFBundleGetBundlePath(bundle); + bundlePath = bundle->_bundleBasePath; CFRetain(bundlePath); } else { CFURLRef absoluteURL = CFURLCopyAbsoluteURL(bundleURL); @@ -3803,36 +2235,117 @@ CFTypeRef _CFBundleCopyFindResources(CFBundleRef bundle, CFURLRef bundleURL, CFA if (returnValue) CFRelease(returnValue); CFRange found; // 9 is the length of "Resources" - if ((bundleVersion == 0 && subPath && CFEqual(subPath, CFSTR("Resources"))) || (bundleVersion == 2 && subPath && CFEqual(subPath, CFSTR("Contents/Resources")))){ - subDirLen = 0; - } else if ((bundleVersion == 0 && subPath && CFStringFindWithOptions(subPath, CFSTR("Resources/"), CFRangeMake(0, 10), kCFCompareEqualTo, &found) && found.location+10 < subDirLen)) { - subDirBuffer = subDirBuffer + 10; - subDirLen -= 10; - } else if ((bundleVersion == 2 && subPath && CFStringFindWithOptions(subPath, CFSTR("Contents/Resources/"), CFRangeMake(0, 19), kCFCompareEqualTo, &found) && found.location+19 < subDirLen)) { - subDirBuffer = subDirBuffer + 19; - subDirLen -= 19; + if ((bundleVersion == 0 && realSubdirectory && CFEqual(realSubdirectory, CFSTR("Resources"))) || (bundleVersion == 2 && realSubdirectory && CFEqual(realSubdirectory, CFSTR("Contents/Resources")))) { + if (realSubdirectory) CFRelease(realSubdirectory); + realSubdirectory = CFSTR(""); + } else if ((bundleVersion == 0 && realSubdirectory && CFStringFindWithOptions(realSubdirectory, CFSTR("Resources/"), CFRangeMake(0, 10), kCFCompareEqualTo, &found) && found.location+10 < CFStringGetLength(realSubdirectory))) { + CFStringRef tmpRealSubdirectory = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, realSubdirectory, CFRangeMake(10, CFStringGetLength(realSubdirectory) - 10)); + if (realSubdirectory) CFRelease(realSubdirectory); + realSubdirectory = tmpRealSubdirectory; + } else if ((bundleVersion == 2 && realSubdirectory && CFStringFindWithOptions(realSubdirectory, CFSTR("Contents/Resources/"), CFRangeMake(0, 19), kCFCompareEqualTo, &found) && found.location+19 < CFStringGetLength(realSubdirectory))) { + CFStringRef tmpRealSubdirectory = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, realSubdirectory, CFRangeMake(19, CFStringGetLength(realSubdirectory) - 19)); + if (realSubdirectory) CFRelease(realSubdirectory); + realSubdirectory = tmpRealSubdirectory; } else { - resDirLen = 0; + // Assume no resources directory + resDir = CFSTR(""); } - if (subDirLen > 0) { - CFRelease(subPath); - subPath = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, subDirBuffer, subDirLen); - } - returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, languages, resDir, resDirLen, subDirBuffer, subDirLen, subPath, key, lproj, lprojBuffer, returnArray, localized, bundleVersion, predicate); + returnValue = _CFBundleCopyURLsOfKey(bundle, bundleURL, languages, resDir, realSubdirectory, key, lproj, returnArray, localized, bundleVersion, predicate); } CFRelease(bundlePath); } - - if (resourceName) CFRelease(resourceName); - if (subPath) CFRelease(subPath); + + if (realResourceName) CFRelease(realResourceName); + if (realSubdirectory) CFRelease(realSubdirectory); if (subPathFromResourceName) CFRelease(subPathFromResourceName); if (languages) CFRelease(languages); - CFAllocatorDeallocate(kCFAllocatorSystemDefault, nameBuff); CFRelease(key); return returnValue; } -__private_extern__ CFTypeRef _CFBundleCopyFindResourcesWithNoBlock(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subPath, CFStringRef lproj, Boolean returnArray, Boolean localized) -{ - return _CFBundleCopyFindResources(bundle, bundleURL, languages, resourceName, resourceType, subPath, lproj, returnArray, localized, NULL); +#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; } + diff --git a/CFBurstTrie.c b/CFBurstTrie.c index b723321..16fa515 100644 --- a/CFBurstTrie.c +++ b/CFBurstTrie.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBurstTrie.c - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. Responsibility: Jennifer Moore */ @@ -36,7 +36,7 @@ #include #include #include -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #include #include #include @@ -282,7 +282,7 @@ typedef struct _TraverseContext { void (*callback)(void*, const UInt8*, uint32_t, uint32_t); } TraverseContext; -bool foundKey(void *context, const uint8_t *key, uint32_t payload, bool exact) +static bool foundKey(void *context, const uint8_t *key, uint32_t payload, bool exact) { if (context != NULL) { TraverseContext *ctx = (TraverseContext *)context; @@ -317,8 +317,8 @@ static void finalizeCFBurstTrieList(ListNodeRef node); static int nodeWeightCompare(const void *a, const void *b); static int nodeStringCompare(const void *a, const void *b); -bool foundKey(void *context, const uint8_t *key, uint32_t payload, bool exact); -bool containsKey(void *context, const uint8_t *key, uint32_t payload, bool exact); +static bool foundKey(void *context, const uint8_t *key, uint32_t payload, bool exact); +static bool containsKey(void *context, const uint8_t *key, uint32_t payload, bool exact); static CFIndex burstTrieConvertCharactersToUTF8(UniChar *chars, CFIndex numChars, UInt8 *buffer); @@ -330,27 +330,6 @@ static void traverseFromMapCursor(CFBurstTrieRef trie, CompactMapCursor *cursor, static Boolean getMapCursorPayloadFromPackedPageEntry(PageEntryPacked *entry, const CompactMapCursor *cursor, uint32_t *payload); static Boolean getMapCursorPayloadFromPageEntry(PageEntry *entry, const CompactMapCursor *cursor, uint32_t *payload); -#if 0 -#pragma mark - -#pragma mark Core Foundation boilerplate -#endif - -static const void *_CFBurstTrieRetainCallback(CFAllocatorRef allocator, const void *value) { - CFBurstTrieRetain((CFBurstTrieRef)value); - return value; -} - -static void _CFBurstTrieReleaseCallback(CFAllocatorRef allocator, const void *value) { - CFBurstTrieRelease((CFBurstTrieRef)value); -} - -const CFDictionaryValueCallBacks kCFBurstTrieValueCallbacks = {0, _CFBurstTrieRetainCallback, _CFBurstTrieReleaseCallback, NULL, NULL}; - -#if 0 -#pragma mark - -#pragma mark Public Interface -#endif - CFBurstTrieRef CFBurstTrieCreateWithOptions(CFDictionaryRef options) { CFBurstTrieRef trie = NULL; trie = (CFBurstTrieRef) calloc(1, sizeof(struct _CFBurstTrie)); @@ -1891,7 +1870,7 @@ static void serializeCFBurstTrieList(CFBurstTrieRef trie, ListNodeRef listNode, } char _buffer[MAX_BUFFER_SIZE]; - char bufferSize = (sizeof(Page) + size * (sizeof(PageEntryPacked) + MAX_STRING_SIZE)); + size_t bufferSize = (sizeof(Page) + size * (sizeof(PageEntryPacked) + MAX_STRING_SIZE)); char *buffer = bufferSize < MAX_BUFFER_SIZE ? _buffer : (char *) malloc(bufferSize); Page *page = (Page *)buffer; @@ -2058,7 +2037,7 @@ static int nodeStringCompare(const void *a, const void *b) { return result; } -bool containsKey(void *context, const uint8_t *key, uint32_t payload, bool exact) +static bool containsKey(void *context, const uint8_t *key, uint32_t payload, bool exact) { uint32_t *ctx = (uint32_t *)context; if (exact) *ctx = payload; diff --git a/CFBurstTrie.h b/CFBurstTrie.h index e6c8830..161a349 100644 --- a/CFBurstTrie.h +++ b/CFBurstTrie.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFBurstTrie.h - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBURSTTRIE__) @@ -194,8 +194,6 @@ void CFBurstTrieTraverseFromCursor(CFBurstTrieCursorRef cursor, void *ctx, CFBur CF_EXPORT void CFBurstTrieCursorRelease(CFBurstTrieCursorRef cursor) CF_AVAILABLE(10_8, 6_0); -__private_extern__ const CFDictionaryValueCallBacks kCFBurstTrieValueCallbacks; - CF_EXTERN_C_END #endif /* __COREFOUNDATION_CFBURSTTRIE__ */ diff --git a/CFByteOrder.h b/CFByteOrder.h index d7d506e..ea507a3 100644 --- a/CFByteOrder.h +++ b/CFByteOrder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFByteOrder.h - Copyright (c) 1995-2012, Apple Inc. All rights reserved. + Copyright (c) 1995-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFBYTEORDER__) diff --git a/CFCalendar.c b/CFCalendar.c index c3a1920..cde70e7 100644 --- a/CFCalendar.c +++ b/CFCalendar.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFCalendar.c - Copyright (c) 2004-2012, Apple Inc. All rights reserved. + Copyright (c) 2004-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -83,7 +83,7 @@ static const CFRuntimeClass __CFCalendarClass = { __CFCalendarCopyDescription }; -__private_extern__ void __CFCalendarInitialize(void) { +CF_PRIVATE void __CFCalendarInitialize(void) { __kCFCalendarTypeID = _CFRuntimeRegisterClass(&__CFCalendarClass); } @@ -92,7 +92,7 @@ CFTypeID CFCalendarGetTypeID(void) { return __kCFCalendarTypeID; } -__private_extern__ UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz) { +CF_PRIVATE UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz) { if (calendarID) { CFDictionaryRef components = CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault, localeID); CFMutableDictionaryRef mcomponents = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, 0, components); diff --git a/CFCalendar.h b/CFCalendar.h index 8cee565..ac2b379 100644 --- a/CFCalendar.h +++ b/CFCalendar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFCalendar.h - Copyright (c) 2004-2012, Apple Inc. All rights reserved. + Copyright (c) 2004-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFCALENDAR__) diff --git a/CFCharacterSet.c b/CFCharacterSet.c index 771ee4d..8c55bbf 100644 --- a/CFCharacterSet.c +++ b/CFCharacterSet.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFCharacterSet.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -145,7 +145,7 @@ CF_INLINE void __CFCSetPutIsInverted(CFMutableCharacterSetRef cset, Boolean isIn CF_INLINE void __CFCSetPutHasHashValue(CFMutableCharacterSetRef cset, Boolean hasHash) {(hasHash ? (cset->_base._cfinfo[CF_INFO_BITS] |= __kCFCharSetHasHashValue) : (cset->_base._cfinfo[CF_INFO_BITS] &= ~__kCFCharSetHasHashValue));} CF_INLINE void __CFCSetPutClassType(CFMutableCharacterSetRef cset, UInt32 classType) {cset->_base._cfinfo[CF_INFO_BITS] &= ~__kCFCharSetClassTypeMask; cset->_base._cfinfo[CF_INFO_BITS] |= classType;} -__private_extern__ Boolean __CFCharacterSetIsMutable(CFCharacterSetRef cset) {return __CFCSetIsMutable(cset);} +CF_PRIVATE Boolean __CFCharacterSetIsMutable(CFCharacterSetRef cset) {return __CFCSetIsMutable(cset);} /* Inline contents accessor macros */ @@ -911,7 +911,7 @@ static Boolean __CFCharacterSetEqual(CFTypeRef cf1, CFTypeRef cf2) { if (__CFCSetHasHashValue((CFCharacterSetRef)cf1) && __CFCSetHasHashValue((CFCharacterSetRef)cf2) && ((CFCharacterSetRef)cf1)->_hashValue != ((CFCharacterSetRef)cf2)->_hashValue) return false; if (__CFCSetIsEmpty((CFCharacterSetRef)cf1) && __CFCSetIsEmpty((CFCharacterSetRef)cf2) && !isInvertStateIdentical) return false; - if (__CFCSetClassType((CFCharacterSetRef)cf1) == __CFCSetClassType((CFCharacterSetRef)cf2)) { // Types are identical, we can do it fast + if ((__CFCSetClassType((CFCharacterSetRef)cf1) == __CFCSetClassType((CFCharacterSetRef)cf2)) && !__CFCSetIsCompactBitmap((CFCharacterSetRef)cf1)) { // Types are identical, we can do it fast switch (__CFCSetClassType((CFCharacterSetRef)cf1)) { case __kCFCharSetClassBuiltin: return (__CFCSetBuiltinType((CFCharacterSetRef)cf1) == __CFCSetBuiltinType((CFCharacterSetRef)cf2) && isInvertStateIdentical ? true : false); @@ -920,12 +920,21 @@ static Boolean __CFCharacterSetEqual(CFTypeRef cf1, CFTypeRef cf2) { return (__CFCSetRangeFirstChar((CFCharacterSetRef)cf1) == __CFCSetRangeFirstChar((CFCharacterSetRef)cf2) && __CFCSetRangeLength((CFCharacterSetRef)cf1) && __CFCSetRangeLength((CFCharacterSetRef)cf2) && isInvertStateIdentical ? true : false); case __kCFCharSetClassString: - if (__CFCSetStringLength((CFCharacterSetRef)cf1) == __CFCSetStringLength((CFCharacterSetRef)cf2) && isInvertStateIdentical) { + if (isInvertStateIdentical) { const UniChar *buf1 = __CFCSetStringBuffer((CFCharacterSetRef)cf1); + const UniChar *buf1End = buf1 + __CFCSetStringLength((CFCharacterSetRef)cf1); const UniChar *buf2 = __CFCSetStringBuffer((CFCharacterSetRef)cf2); - CFIndex length = __CFCSetStringLength((CFCharacterSetRef)cf1); + const UniChar *buf2End = buf2 + __CFCSetStringLength((CFCharacterSetRef)cf2); - while (length--) if (*buf1++ != *buf2++) return false; + while ((buf1 < buf1End) && (buf2 < buf2End)) { + UniChar char1 = *buf1; + UniChar char2 = *buf2; + + if (char1 != char2) return false; + + do { ++buf1; } while ((buf1 < buf1End) && (char1 == *buf1)); + do { ++buf2; } while ((buf2 < buf2End) && (char2 == *buf2)); + } } else { return false; } @@ -1232,7 +1241,7 @@ static CFStringRef __CFCharacterSetCopyDescription(CFTypeRef cf) { break; case __kCFCharSetClassRange: - return CFStringCreateWithFormat(CFGetAllocator((CFCharacterSetRef)cf), NULL, CFSTR(""), __CFCSetRangeFirstChar((CFCharacterSetRef)cf), __CFCSetRangeLength((CFCharacterSetRef)cf)); + return CFStringCreateWithFormat(CFGetAllocator((CFCharacterSetRef)cf), NULL, CFSTR(""), (unsigned int)__CFCSetRangeFirstChar((CFCharacterSetRef)cf), (long)__CFCSetRangeLength((CFCharacterSetRef)cf)); case __kCFCharSetClassString: { CFStringRef format = CFSTR(""(2) CFStringAppend(string, format); for (idx = 0;idx < length;idx++) { - CFStringAppendFormat(string, NULL, CFSTR("%sU+%04X"), (idx > 0 ? " " : ""), (UInt32)((__CFCSetStringBuffer((CFCharacterSetRef)cf))[idx])); + CFStringAppendFormat(string, NULL, CFSTR("%sU+%04X"), (idx > 0 ? " " : ""), (unsigned int)((__CFCSetStringBuffer((CFCharacterSetRef)cf))[idx])); } CFStringAppend(string, CFSTR(")>")); return string; @@ -1288,7 +1297,7 @@ static const CFRuntimeClass __CFCharacterSetClass = { static bool __CFCheckForExapendedSet = false; -__private_extern__ void __CFCharacterSetInitialize(void) { +CF_PRIVATE void __CFCharacterSetInitialize(void) { const char *checkForExpandedSet = __CFgetenv("__CF_DEBUG_EXPANDED_SET"); __kCFCharacterSetTypeID = _CFRuntimeRegisterClass(&__CFCharacterSetClass); @@ -2064,6 +2073,14 @@ void CFCharacterSetAddCharactersInRange(CFMutableCharacterSetRef theSet, CFRange __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); __CFCSetValidateRange(theRange, __PRETTY_FUNCTION__); + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } + if (!theRange.length || (__CFCSetIsInverted(theSet) && __CFCSetIsEmpty(theSet))) return; // Inverted && empty set contains all char if (!__CFCSetIsInverted(theSet)) { @@ -2121,6 +2138,14 @@ void CFCharacterSetRemoveCharactersInRange(CFMutableCharacterSetRef theSet, CFRa __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); __CFCSetValidateRange(theRange, __PRETTY_FUNCTION__); + + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } if (!theRange.length || (!__CFCSetIsInverted(theSet) && __CFCSetIsEmpty(theSet))) return; // empty set @@ -2187,6 +2212,14 @@ void CFCharacterSetAddCharactersInString(CFMutableCharacterSetRef theSet, CFStr CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, addCharactersInString:(NSString *)theString); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); + + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } if ((__CFCSetIsEmpty(theSet) && __CFCSetIsInverted(theSet)) || !(length = CFStringGetLength(theString))) return; @@ -2271,6 +2304,14 @@ void CFCharacterSetRemoveCharactersInString(CFMutableCharacterSetRef theSet, CFS CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, removeCharactersInString:(NSString *)theString); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); + + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } if ((__CFCSetIsEmpty(theSet) && !__CFCSetIsInverted(theSet)) || !(length = CFStringGetLength(theString))) return; @@ -2347,6 +2388,14 @@ void CFCharacterSetUnion(CFMutableCharacterSetRef theSet, CFCharacterSetRef theO CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, formUnionWithCharacterSet:(NSCharacterSet *)theOtherSet); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); + + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } if (__CFCSetIsEmpty(theSet) && __CFCSetIsInverted(theSet)) return; // Inverted empty set contains all char @@ -2470,6 +2519,14 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, formIntersectionWithCharacterSet:(NSCharacterSet *)theOtherSet); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); + + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } if (__CFCSetIsEmpty(theSet) && !__CFCSetIsInverted(theSet)) return; // empty set @@ -2569,7 +2626,9 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef for (idx = 1;idx <= MAX_ANNEX_PLANE;idx++) { if ((otherSetPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theOtherSet, idx))) { annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); CFCharacterSetIntersect(annexPlane, otherSetPlane); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); } else if (__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); @@ -2618,7 +2677,9 @@ 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(theSet)) CFCharacterSetInvert(annexPlane); CFCharacterSetIntersect(annexPlane, otherSetPlane); + if (__CFCSetAnnexIsInverted(theSet)) CFCharacterSetInvert(annexPlane); if (__CFCSetIsEmpty(annexPlane) && !__CFCSetIsInverted(annexPlane)) __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); } else if (__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, idx)) { __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, idx); @@ -2651,6 +2712,14 @@ void CFCharacterSetInvert(CFMutableCharacterSetRef theSet) { CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, invert); __CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__); + + if (__CFCSetIsBuiltin((CFCharacterSetRef)theSet) && !__CFCSetIsMutable((CFCharacterSetRef)theSet) && !__CFCSetIsInverted((CFCharacterSetRef)theSet)) { + CFCharacterSetRef sharedSet = CFCharacterSetGetPredefined(__CFCSetBuiltinType((CFCharacterSetRef)theSet)); + if (sharedSet == theSet) { // We're trying to dealloc the builtin set + CFAssert1(0, __kCFLogAssertion, "%s: Trying to mutable predefined set.", __PRETTY_FUNCTION__); + return; // We don't mutate builtin set + } + } __CFCSetPutHasHashValue(theSet, false); diff --git a/CFCharacterSet.h b/CFCharacterSet.h index f499893..f31eff4 100644 --- a/CFCharacterSet.h +++ b/CFCharacterSet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFCharacterSet.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ /*! diff --git a/CFCharacterSetPriv.h b/CFCharacterSetPriv.h index a9e9572..cd3dfd0 100644 --- a/CFCharacterSetPriv.h +++ b/CFCharacterSetPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFCharacterSetPriv.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFCHARACTERSETPRIV__) diff --git a/CFConcreteStreams.c b/CFConcreteStreams.c index c2f9c71..00ff49a 100644 --- a/CFConcreteStreams.c +++ b/CFConcreteStreams.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFConcreteStreams.c - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. Responsibility: John Iarocci */ @@ -168,7 +168,7 @@ static Boolean fileOpen(struct _CFStream *stream, CFStreamError *errorCode, Bool return TRUE; } -__private_extern__ CFIndex fdRead(int fd, UInt8 *buffer, CFIndex bufferLength, CFStreamError *errorCode, Boolean *atEOF) { +CF_PRIVATE CFIndex fdRead(int fd, UInt8 *buffer, CFIndex bufferLength, CFStreamError *errorCode, Boolean *atEOF) { CFIndex bytesRead = read(fd, buffer, bufferLength); if (bytesRead < 0) { errorCode->error = errno; @@ -213,7 +213,7 @@ static CFIndex fileRead(CFReadStreamRef stream, UInt8 *buffer, CFIndex bufferLen } #ifdef REAL_FILE_SCHEDULING -__private_extern__ Boolean fdCanRead(int fd) { +CF_PRIVATE Boolean fdCanRead(int fd) { struct timeval timeout = {0, 0}; fd_set *readSetPtr; fd_set readSet; @@ -246,7 +246,7 @@ static Boolean fileCanRead(CFReadStreamRef stream, void *info) { #endif } -__private_extern__ CFIndex fdWrite(int fd, const UInt8 *buffer, CFIndex bufferLength, CFStreamError *errorCode) { +CF_PRIVATE CFIndex fdWrite(int fd, const UInt8 *buffer, CFIndex bufferLength, CFStreamError *errorCode) { CFIndex bytesWritten = write(fd, buffer, bufferLength); if (bytesWritten < 0) { errorCode->error = errno; @@ -277,7 +277,7 @@ static CFIndex fileWrite(CFWriteStreamRef stream, const UInt8 *buffer, CFIndex b } #ifdef REAL_FILE_SCHEDULING -__private_extern__ Boolean fdCanWrite(int fd) { +CF_PRIVATE Boolean fdCanWrite(int fd) { struct timeval timeout = {0, 0}; fd_set *writeSetPtr; fd_set writeSet; @@ -676,13 +676,19 @@ static CFIndex dataWrite(CFWriteStreamRef stream, const UInt8 *buffer, CFIndex b if (bufferLength > 0) { CFIndex bufSize = BUF_SIZE > bufferLength ? BUF_SIZE : bufferLength; _CFStreamByteBuffer *newBuf = (_CFStreamByteBuffer *)CFAllocatorAllocate(dataStream->bufferAllocator, sizeof(_CFStreamByteBuffer) + bufSize, 0); - newBuf->bytes = (UInt8 *)(newBuf + 1); - newBuf->capacity = bufSize; - newBuf->length = 0; - newBuf->next = NULL; - dataStream->currentBuf->next = newBuf; - dataStream->currentBuf = newBuf; - freeSpace = bufSize; + if (newBuf == NULL) { + errorCode->error = ENOMEM; + errorCode->domain = kCFStreamErrorDomainPOSIX; + return -1; + } else { + newBuf->bytes = (UInt8 *)(newBuf + 1); + newBuf->capacity = bufSize; + newBuf->length = 0; + newBuf->next = NULL; + dataStream->currentBuf->next = newBuf; + dataStream->currentBuf = newBuf; + freeSpace = bufSize; + } } } errorCode->error = 0; @@ -712,7 +718,6 @@ static CFPropertyListRef dataCopyProperty(struct _CFStream *stream, CFStringRef for (buf = dataStream->firstBuf; buf != NULL; buf = buf->next) { size += buf->length; } - if (size == 0) return NULL; bytes = (UInt8 *)CFAllocatorAllocate(alloc, size, 0); currByte = bytes; for (buf = dataStream->firstBuf; buf != NULL; buf = buf->next) { @@ -867,13 +872,6 @@ CFWriteStreamRef CFWriteStreamCreateWithBuffer(CFAllocatorRef alloc, UInt8 *buff } CF_EXPORT CFWriteStreamRef CFWriteStreamCreateWithAllocatedBuffers(CFAllocatorRef alloc, CFAllocatorRef bufferAllocator) { - if (!(bufferAllocator == NULL || bufferAllocator == kCFAllocatorNull)) { - // If there is a real bufferAllocator, then we don't allow the - // CFStream or the contents to be allocated with one of the special - // *GCRefZero allocators for now. - bufferAllocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(bufferAllocator); - alloc = _CFConvertAllocatorToNonGCRefZeroEquivalent(alloc); - } _CFWriteDataStreamContext ctxt; ctxt.firstBuf = NULL; ctxt.currentBuf = NULL; diff --git a/CFData.c b/CFData.c index b6528f5..9d2732b 100644 --- a/CFData.c +++ b/CFData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFData.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Kevin Perry */ @@ -195,7 +195,7 @@ static void __CFDataHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) { if(0 < numBytes && numBytes <= CFDATA_MAX_SIZE) { msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFData failed"), numBytes); } else { - msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFData failed. Maximum size: %ld"), numBytes, CFDATA_MAX_SIZE); + msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFData failed. Maximum size: %lld"), numBytes, CFDATA_MAX_SIZE); } { CFLog(kCFLogLevelCritical, CFSTR("%@"), msg); @@ -239,7 +239,7 @@ static CFStringRef __CFDataCopyDescription(CFTypeRef cf) { len = __CFDataLength(data); bytes = CFDataGetBytePtr(data); result = CFStringCreateMutable(CFGetAllocator(data), 0); - CFStringAppendFormat(result, NULL, CFSTR("{length = %u, capacity = %u, bytes = 0x"), cf, CFGetAllocator(data), len, __CFDataCapacity(data)); + CFStringAppendFormat(result, NULL, CFSTR("{length = %lu, capacity = %lu, bytes = 0x"), cf, CFGetAllocator(data), (unsigned long)len, (unsigned long)__CFDataCapacity(data)); if (24 < len) { for (idx = 0; idx < 16; idx += 4) { CFStringAppendFormat(result, NULL, CFSTR("%02x%02x%02x%02x"), bytes[idx], bytes[idx + 1], bytes[idx + 2], bytes[idx + 3]); @@ -307,7 +307,7 @@ static void __CFDataDeallocate(CFTypeRef cf) { CFAllocatorRef deallocator = data->_bytesDeallocator; if (deallocator != NULL) { _CFAllocatorDeallocateGC(deallocator, data->_bytes); - if (!_CFAllocatorIsGCRefZero(deallocator)) CFRelease(deallocator); + CFRelease(deallocator); data->_bytes = NULL; } else { if (__CFDataUseAllocator(data)) { @@ -334,7 +334,7 @@ static const CFRuntimeClass __CFDataClass = { __CFDataCopyDescription }; -__private_extern__ void __CFDataInitialize(void) { +CF_PRIVATE void __CFDataInitialize(void) { __kCFDataTypeID = _CFRuntimeRegisterClass(&__CFDataClass); } @@ -411,14 +411,14 @@ static CFMutableDataRef __CFDataInit(CFAllocatorRef allocator, CFOptionFlags fla if (noCopy) { __CFAssignWithWriteBarrier((void **)&memory->_bytes, (uint8_t *)bytes); if (finalize) { - if (_CFAllocatorIsGCRefZero(bytesDeallocator)) { + if ((0)) { memory->_bytesDeallocator = bytesDeallocator; } else { - memory->_bytesDeallocator = (CFAllocatorRef)CFRetain(_CFConvertAllocatorToNonGCRefZeroEquivalent(bytesDeallocator)); + memory->_bytesDeallocator = (CFAllocatorRef)CFRetain(bytesDeallocator); } } - if (CF_IS_COLLECTABLE_ALLOCATOR(bytesDeallocator) && !_CFAllocatorIsGCRefZero(bytesDeallocator)) { - // When given a GC allocator which is not one of the GCRefZero ones as the deallocator, we assume that the no-copy memory is GC-allocated with a retain count of (at least) 1 and we should release it now instead of waiting until __CFDataDeallocate. + if (CF_IS_COLLECTABLE_ALLOCATOR(bytesDeallocator) && !(0)) { + // we assume that the no-copy memory is GC-allocated with a retain count of (at least) 1 and we should release it now instead of waiting until __CFDataDeallocate. auto_zone_release(objc_collectableZone(), memory->_bytes); } __CFDataSetNumBytesUsed(memory, length); @@ -470,8 +470,7 @@ CFMutableDataRef CFDataCreateMutable(CFAllocatorRef allocator, CFIndex capacity) // Do not allow magic allocator for now for mutable datas, because it // isn't remembered for proper handling later when growth of the buffer // has to occur. - Boolean wasMagic = _CFAllocatorIsGCRefZero(allocator); - if (0 == capacity) allocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); + Boolean wasMagic = (0); CFMutableDataRef r = (CFMutableDataRef)__CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, NULL, 0, NULL); if (wasMagic) CFMakeCollectable(r); return r; @@ -481,8 +480,7 @@ CFMutableDataRef CFDataCreateMutableCopy(CFAllocatorRef allocator, CFIndex capac // Do not allow magic allocator for now for mutable datas, because it // isn't remembered for proper handling later when growth of the buffer // has to occur. - Boolean wasMagic = _CFAllocatorIsGCRefZero(allocator); - if (0 == capacity) allocator = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); + Boolean wasMagic = (0); CFMutableDataRef r = (CFMutableDataRef) __CFDataInit(allocator, (0 == capacity) ? kCFMutable : kCFFixedMutable, capacity, CFDataGetBytePtr(data), CFDataGetLength(data), NULL); if (wasMagic) CFMakeCollectable(r); return r; diff --git a/CFData.h b/CFData.h index 8647e6e..7b2394b 100644 --- a/CFData.h +++ b/CFData.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFData.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFDATA__) diff --git a/CFDate.c b/CFDate.c index 766ebda..be8b511 100644 --- a/CFDate.c +++ b/CFDate.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFDate.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -34,6 +34,8 @@ #include #include "CFInternal.h" #include +#include + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX #include #endif @@ -48,18 +50,45 @@ const CFTimeInterval kCFAbsoluteTimeIntervalSince1970 = 978307200.0L; const CFTimeInterval kCFAbsoluteTimeIntervalSince1904 = 3061152000.0L; -__private_extern__ double __CFTSRRate = 0.0; +CF_PRIVATE double __CFTSRRate = 0.0; static double __CF1_TSRRate = 0.0; -__private_extern__ int64_t __CFTimeIntervalToTSR(CFTimeInterval ti) { +CF_PRIVATE uint64_t __CFTimeIntervalToTSR(CFTimeInterval ti) { if ((ti * __CFTSRRate) > INT64_MAX / 2) return (INT64_MAX / 2); - return (int64_t)(ti * __CFTSRRate); + return (uint64_t)(ti * __CFTSRRate); } -__private_extern__ CFTimeInterval __CFTSRToTimeInterval(int64_t tsr) { +CF_PRIVATE CFTimeInterval __CFTSRToTimeInterval(uint64_t tsr) { return (CFTimeInterval)((double)tsr * __CF1_TSRRate); } +CF_PRIVATE CFTimeInterval __CFTimeIntervalUntilTSR(uint64_t tsr) { + CFDateGetTypeID(); + uint64_t now = mach_absolute_time(); + if (tsr >= now) { + return __CFTSRToTimeInterval(tsr - now); + } else { + return -__CFTSRToTimeInterval(now - tsr); + } +} + +// Technically this is 'TSR units' not a strict 'TSR' absolute time +CF_PRIVATE uint64_t __CFTSRToNanoseconds(uint64_t tsr) { + double tsrInNanoseconds = floor(tsr * __CF1_TSRRate * NSEC_PER_SEC); + uint64_t ns = (uint64_t)tsrInNanoseconds; + return ns; +} + +CF_PRIVATE dispatch_time_t __CFTSRToDispatchTime(uint64_t tsr) { + uint64_t tsrInNanoseconds = __CFTSRToNanoseconds(tsr); + + // It's important to clamp this value to INT64_MAX or it will become interpreted by dispatch_time as a relative value instead of absolute time + if (tsrInNanoseconds > INT64_MAX - 1) tsrInNanoseconds = INT64_MAX - 1; + + // 2nd argument of dispatch_time is a value in nanoseconds, but tsr does not equal nanoseconds on all platforms. + return dispatch_time(1, (int64_t)tsrInNanoseconds); +} + CFAbsoluteTime CFAbsoluteTimeGetCurrent(void) { CFAbsoluteTime ret; struct timeval tv; @@ -69,7 +98,7 @@ CFAbsoluteTime CFAbsoluteTimeGetCurrent(void) { return ret; } -__private_extern__ void __CFDateInitialize(void) { +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); @@ -84,7 +113,7 @@ __private_extern__ void __CFDateInitialize(void) { __CF1_TSRRate = 1.0 / __CFTSRRate; #elif DEPLOYMENT_TARGET_LINUX struct timespec res; - if (!clock_getres(CLOCK_MONOTONIC, &res)) { + if (clock_getres(CLOCK_MONOTONIC, &res) != 0) { HALT; } __CFTSRRate = res.tv_sec + (1000000000 * res.tv_nsec); diff --git a/CFDate.h b/CFDate.h index fada953..f019e0a 100644 --- a/CFDate.h +++ b/CFDate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFDate.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFDATE__) @@ -67,6 +67,17 @@ CF_IMPLICIT_BRIDGING_DISABLED typedef const struct __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 { SInt32 year; SInt8 month; @@ -74,7 +85,7 @@ typedef struct { SInt8 hour; SInt8 minute; double second; -} CFGregorianDate; +} CFGregorianDate CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); typedef struct { SInt32 years; @@ -83,41 +94,41 @@ typedef struct { SInt32 hours; SInt32 minutes; double seconds; -} CFGregorianUnits; +} CFGregorianUnits CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); typedef CF_OPTIONS(CFOptionFlags, CFGregorianUnitFlags) { - kCFGregorianUnitsYears = (1UL << 0), - kCFGregorianUnitsMonths = (1UL << 1), - kCFGregorianUnitsDays = (1UL << 2), - kCFGregorianUnitsHours = (1UL << 3), - kCFGregorianUnitsMinutes = (1UL << 4), - kCFGregorianUnitsSeconds = (1UL << 5), - kCFGregorianAllUnits = 0x00FFFFFF + 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 }; CF_EXPORT -Boolean CFGregorianDateIsValid(CFGregorianDate gdate, CFOptionFlags unitFlags); +Boolean CFGregorianDateIsValid(CFGregorianDate gdate, CFOptionFlags unitFlags) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFAbsoluteTime CFGregorianDateGetAbsoluteTime(CFGregorianDate gdate, CFTimeZoneRef tz); +CFAbsoluteTime CFGregorianDateGetAbsoluteTime(CFGregorianDate gdate, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFGregorianDate CFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeZoneRef tz); +CFGregorianDate CFAbsoluteTimeGetGregorianDate(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -CFAbsoluteTime CFAbsoluteTimeAddGregorianUnits(CFAbsoluteTime at, CFTimeZoneRef tz, CFGregorianUnits units); +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"); CF_EXPORT -CFGregorianUnits CFAbsoluteTimeGetDifferenceAsGregorianUnits(CFAbsoluteTime at1, CFAbsoluteTime at2, CFTimeZoneRef tz, CFOptionFlags unitFlags); +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"); CF_EXPORT -SInt32 CFAbsoluteTimeGetDayOfWeek(CFAbsoluteTime at, CFTimeZoneRef tz); +SInt32 CFAbsoluteTimeGetDayOfWeek(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -SInt32 CFAbsoluteTimeGetDayOfYear(CFAbsoluteTime at, CFTimeZoneRef tz); +SInt32 CFAbsoluteTimeGetDayOfYear(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); CF_EXPORT -SInt32 CFAbsoluteTimeGetWeekOfYear(CFAbsoluteTime at, CFTimeZoneRef tz); +SInt32 CFAbsoluteTimeGetWeekOfYear(CFAbsoluteTime at, CFTimeZoneRef tz) CF_CALENDAR_DEPRECATED(10_4, 10_9, 2_0, 7_0, "Use CFCalendar or NSCalendar API instead"); CF_EXTERN_C_END diff --git a/CFDateFormatter.c b/CFDateFormatter.c index 1b14265..80f2701 100644 --- a/CFDateFormatter.c +++ b/CFDateFormatter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFDateFormatter.c - Copyright (c) 2002-2012, Apple Inc. All rights reserved. + Copyright (c) 2002-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -36,11 +36,11 @@ #include "CFPriv.h" #include "CFInternal.h" #include "CFLocaleInternal.h" -#include -#include +#include "CFICULogging.h" #include #include + typedef CF_ENUM(CFIndex, CFDateFormatterAmbiguousYearHandling) { kCFDateFormatterAmbiguousYearFailToParse = 0, // fail the parse; the default formatter behavior kCFDateFormatterAmbiguousYearAssumeToNone = 1, // default to assuming era 1, or the year 0-99 @@ -53,7 +53,6 @@ typedef CF_ENUM(CFIndex, CFDateFormatterAmbiguousYearHandling) { }; extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz); -static void __CFDateFormatterCustomize(CFDateFormatterRef formatter); CF_EXPORT const CFStringRef kCFDateFormatterCalendarIdentifierKey; @@ -71,6 +70,37 @@ CFArrayRef CFDateFormatterCreateDateFormatsFromTemplates(CFAllocatorRef allocato return (CFArrayRef)CFDateFormatterCreateDateFormatFromTemplate(allocator, (CFStringRef)tmplates, options, locale); } +static Boolean useTemplatePatternGenerator(const char *localeName, void(^work)(UDateTimePatternGenerator *ptg)) { + static UDateTimePatternGenerator *ptg; + static pthread_mutex_t ptgLock = PTHREAD_MUTEX_INITIALIZER; + static const char *ptgLocaleName; + + static void (^flushCache)() = ^{ + __cficu_udatpg_close(ptg); + ptg = NULL; + free((void *)ptgLocaleName); + ptgLocaleName = NULL; + }; + pthread_mutex_lock(&ptgLock); + if (ptgLocaleName && strcmp(ptgLocaleName, localeName) != 0) { + flushCache(); + } + UErrorCode status = U_ZERO_ERROR; + if (!ptg) { + ptg = __cficu_udatpg_open(localeName, &status); + if (ptg && !U_FAILURE(status)) { + ptgLocaleName = strdup(localeName); + } + } + Boolean result = (NULL != ptg && !U_FAILURE(status)); + if (result && work) { + work(ptg); + } + pthread_mutex_unlock(&ptgLock); + return result; +} + + CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator, CFStringRef tmplate, CFOptionFlags options, CFLocaleRef locale) { if (allocator) __CFGenericValidateType(allocator, CFAllocatorGetTypeID()); if (locale) __CFGenericValidateType(locale, CFLocaleGetTypeID()); @@ -88,62 +118,63 @@ CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator if (NULL == cstr) { return NULL; } - - UErrorCode status = U_ZERO_ERROR; - UDateTimePatternGenerator *ptg = udatpg_open(cstr, &status); - if (NULL == ptg || U_FAILURE(status)) { - return NULL; - } - - CFTypeRef result = tmplateIsString ? NULL : (CFTypeRef)CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); - - 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); - - CFIndex jCount = 0; // the only interesting cases are 0, 1, and 2 (adjacent) - CFRange r = CFStringFind(tmplateString, CFSTR("j"), 0); - if (kCFNotFound != r.location) { - jCount++; - if ((r.location + 1 < CFStringGetLength(tmplateString)) && ('j' == CFStringGetCharacterAtIndex(tmplateString, r.location + 1))) { + + __block CFTypeRef result = tmplateIsString ? NULL : (CFTypeRef)CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks); + + Boolean success = useTemplatePatternGenerator(cstr, ^(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); + + CFIndex jCount = 0; // the only interesting cases are 0, 1, and 2 (adjacent) + CFRange r = CFStringFind(tmplateString, CFSTR("j"), 0); + if (kCFNotFound != r.location) { jCount++; + if ((r.location + 1 < CFStringGetLength(tmplateString)) && ('j' == CFStringGetCharacterAtIndex(tmplateString, r.location + 1))) { + jCount++; + } } - } - - UChar pattern[BUFFER_SIZE], skel[BUFFER_SIZE], bpat[BUFFER_SIZE]; - CFIndex tmpltLen = CFStringGetLength(tmplateString); - if (BUFFER_SIZE < tmpltLen) tmpltLen = BUFFER_SIZE; - CFStringGetCharacters(tmplateString, CFRangeMake(0, tmpltLen), (UniChar *)pattern); - CFRelease(tmplateString); - - int32_t patlen = tmpltLen; - status = U_ZERO_ERROR; - int32_t skellen = 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'; - } - - status = U_ZERO_ERROR; - int32_t bpatlen = udatpg_getBestPattern(ptg, skel, skellen, bpat, sizeof(bpat) / sizeof(bpat[0]), &status); + + UChar pattern[BUFFER_SIZE], skel[BUFFER_SIZE], bpat[BUFFER_SIZE]; + CFIndex tmpltLen = CFStringGetLength(tmplateString); + if (BUFFER_SIZE < tmpltLen) tmpltLen = BUFFER_SIZE; + CFStringGetCharacters(tmplateString, CFRangeMake(0, tmpltLen), (UniChar *)pattern); + CFRelease(tmplateString); + + int32_t patlen = tmpltLen; + UErrorCode status = U_ZERO_ERROR; + int32_t skellen = __cficu_udatpg_getSkeleton(ptg, pattern, patlen, skel, sizeof(skel) / sizeof(skel[0]), &status); if (!U_FAILURE(status)) { - resultString = CFStringCreateWithCharacters(allocator, (const UniChar *)bpat, bpatlen); + if ((0 < jCount) && (skellen + jCount < (sizeof(skel) / sizeof(skel[0])))) { + skel[skellen++] = 'j'; + if (1 < jCount) skel[skellen++] = 'j'; + } + + status = U_ZERO_ERROR; + int32_t bpatlen = __cficu_udatpg_getBestPattern(ptg, skel, skellen, bpat, sizeof(bpat) / sizeof(bpat[0]), &status); + if (!U_FAILURE(status)) { + resultString = CFStringCreateWithCharacters(allocator, (const UniChar *)bpat, bpatlen); + } + } + + if (tmplateIsString) { + result = (CFTypeRef)resultString; + } else { + CFArrayAppendValue((CFMutableArrayRef)result, resultString ? (CFTypeRef)resultString : (CFTypeRef)kCFNull); + if (resultString) CFRelease(resultString); } } - - if (tmplateIsString) { - result = (CFTypeRef)resultString; - } else { - CFArrayAppendValue((CFMutableArrayRef)result, resultString ? (CFTypeRef)resultString : (CFTypeRef)kCFNull); - if (resultString) CFRelease(resultString); - } + }); + + if (!success) { + CFRelease(result); + result = NULL; } - - udatpg_close(ptg); - + return (CFStringRef)result; } @@ -186,6 +217,36 @@ struct __CFDateFormatter { CFStringRef _AMSymbol; CFStringRef _PMSymbol; CFNumberRef _AmbiguousYearStrategy; + CFBooleanRef _UsesCharacterDirection; + + // the following are from preferences + CFArrayRef _CustomEraSymbols; + CFArrayRef _CustomLongEraSymbols; + CFArrayRef _CustomMonthSymbols; + CFArrayRef _CustomShortMonthSymbols; + CFArrayRef _CustomVeryShortMonthSymbols; + CFArrayRef _CustomStandaloneMonthSymbols; + CFArrayRef _CustomShortStandaloneMonthSymbols; + CFArrayRef _CustomVeryShortStandaloneMonthSymbols; + CFArrayRef _CustomWeekdaySymbols; + CFArrayRef _CustomShortWeekdaySymbols; + CFArrayRef _CustomVeryShortWeekdaySymbols; + CFArrayRef _CustomStandaloneWeekdaySymbols; + CFArrayRef _CustomShortStandaloneWeekdaySymbols; + CFArrayRef _CustomVeryShortStandaloneWeekdaySymbols; + CFArrayRef _CustomQuarterSymbols; + CFArrayRef _CustomShortQuarterSymbols; + CFArrayRef _CustomStandaloneQuarterSymbols; + CFArrayRef _CustomShortStandaloneQuarterSymbols; + CFStringRef _CustomDateFormat; + CFStringRef _CustomTimeFormat; + CFBooleanRef _Custom24Hour; + CFBooleanRef _Custom12Hour; + CFStringRef _CustomAMSymbol; + CFStringRef _CustomPMSymbol; + CFDictionaryRef _CustomFirstWeekday; + CFDictionaryRef _CustomMinDaysInFirstWeek; + } _property; }; @@ -196,7 +257,7 @@ static CFStringRef __CFDateFormatterCopyDescription(CFTypeRef cf) { static void __CFDateFormatterDeallocate(CFTypeRef cf) { CFDateFormatterRef formatter = (CFDateFormatterRef)cf; - if (formatter->_df) udat_close(formatter->_df); + if (formatter->_df) __cficu_udat_close(formatter->_df); if (formatter->_locale) CFRelease(formatter->_locale); if (formatter->_format) CFRelease(formatter->_format); if (formatter->_defformat) CFRelease(formatter->_defformat); @@ -229,19 +290,275 @@ static void __CFDateFormatterDeallocate(CFTypeRef cf) { CFReleaseIfNotNull(formatter->_property._AMSymbol); CFReleaseIfNotNull(formatter->_property._PMSymbol); CFReleaseIfNotNull(formatter->_property._AmbiguousYearStrategy); + CFReleaseIfNotNull(formatter->_property._UsesCharacterDirection); + CFReleaseIfNotNull(formatter->_property._CustomEraSymbols); + CFReleaseIfNotNull(formatter->_property._CustomMonthSymbols); + CFReleaseIfNotNull(formatter->_property._CustomShortMonthSymbols); + CFReleaseIfNotNull(formatter->_property._CustomWeekdaySymbols); + CFReleaseIfNotNull(formatter->_property._CustomShortWeekdaySymbols); + CFReleaseIfNotNull(formatter->_property._CustomLongEraSymbols); + CFReleaseIfNotNull(formatter->_property._CustomVeryShortMonthSymbols); + CFReleaseIfNotNull(formatter->_property._CustomVeryShortWeekdaySymbols); + CFReleaseIfNotNull(formatter->_property._CustomStandaloneMonthSymbols); + CFReleaseIfNotNull(formatter->_property._CustomShortStandaloneMonthSymbols); + CFReleaseIfNotNull(formatter->_property._CustomVeryShortStandaloneMonthSymbols); + CFReleaseIfNotNull(formatter->_property._CustomStandaloneWeekdaySymbols); + CFReleaseIfNotNull(formatter->_property._CustomShortStandaloneWeekdaySymbols); + CFReleaseIfNotNull(formatter->_property._CustomVeryShortStandaloneWeekdaySymbols); + CFReleaseIfNotNull(formatter->_property._CustomQuarterSymbols); + CFReleaseIfNotNull(formatter->_property._CustomShortQuarterSymbols); + CFReleaseIfNotNull(formatter->_property._CustomShortStandaloneQuarterSymbols); + CFReleaseIfNotNull(formatter->_property._CustomDateFormat); + CFReleaseIfNotNull(formatter->_property._CustomTimeFormat); + CFReleaseIfNotNull(formatter->_property._Custom24Hour); + CFReleaseIfNotNull(formatter->_property._Custom12Hour); + CFReleaseIfNotNull(formatter->_property._CustomAMSymbol); + CFReleaseIfNotNull(formatter->_property._CustomPMSymbol); + CFReleaseIfNotNull(formatter->_property._CustomFirstWeekday); + CFReleaseIfNotNull(formatter->_property._CustomMinDaysInFirstWeek); } static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef formatter, CFStringRef inString); static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringRef key, CFTypeRef value, Boolean directToICU); - +static void __CFDateFormatterStoreSymbolPrefs(const void *key, const void *value, void *context); +extern CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale); +static void __substituteFormatStringFromPrefsDFRelative(CFDateFormatterRef formatter); +static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter, bool doTime); +static void __CFDateFormatterSetSymbolsArray(UDateFormat *icudf, int32_t icucode, int index_base, CFTypeRef value); + +static void __ReadCustomUDateFormatProperty(CFDateFormatterRef formatter) { + CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale); + CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUDateTimeSymbols")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { + CFDictionaryApplyFunction((CFDictionaryRef)metapref, __CFDateFormatterStoreSymbolPrefs, formatter); + } + metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleFirstWeekday")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { + formatter->_property._CustomFirstWeekday = (CFDictionaryRef)CFRetain(metapref); + } + metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleMinDaysInFirstWeek")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { + formatter->_property._CustomMinDaysInFirstWeek = (CFDictionaryRef)CFRetain(metapref); + } + metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce24HourTime")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFBooleanGetTypeID()) { + formatter->_property._Custom24Hour = (CFBooleanRef)CFRetain(metapref); + } + metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce12HourTime")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFBooleanGetTypeID()) { + formatter->_property._Custom12Hour = (CFBooleanRef)CFRetain(metapref); + } + metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUDateFormatStrings")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { + CFStringRef key; + switch (formatter->_dateStyle) { + case kCFDateFormatterShortStyle: key = CFSTR("1"); break; + case kCFDateFormatterMediumStyle: key = CFSTR("2"); break; + case kCFDateFormatterLongStyle: key = CFSTR("3"); break; + case kCFDateFormatterFullStyle: key = CFSTR("4"); break; + default: key = CFSTR("0"); break; + } + CFStringRef dateFormat = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key); + if (NULL != dateFormat && CFGetTypeID(dateFormat) == CFStringGetTypeID()) { + formatter->_property._CustomDateFormat = (CFStringRef)CFRetain(dateFormat); + } + } + metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUTimeFormatStrings")) : NULL; + if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { + CFStringRef key; + switch (formatter->_timeStyle) { + case kCFDateFormatterShortStyle: key = CFSTR("1"); break; + case kCFDateFormatterMediumStyle: key = CFSTR("2"); break; + case kCFDateFormatterLongStyle: key = CFSTR("3"); break; + case kCFDateFormatterFullStyle: key = CFSTR("4"); break; + default: key = CFSTR("0"); break; + } + CFStringRef timeFormat = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key); + if (NULL != timeFormat && CFGetTypeID(timeFormat) == CFStringGetTypeID()) { + formatter->_property._CustomTimeFormat = (CFStringRef)CFRetain(timeFormat); + } + } +} + +static void __ApplyUDateFormatSymbol(CFDateFormatterRef formatter) { + UDateFormatSymbolType types[18] = {UDAT_ERAS, + UDAT_ERA_NAMES, + UDAT_MONTHS, + UDAT_SHORT_MONTHS, + UDAT_NARROW_MONTHS, + UDAT_STANDALONE_MONTHS, + UDAT_STANDALONE_SHORT_MONTHS, + UDAT_STANDALONE_NARROW_MONTHS, + UDAT_WEEKDAYS, + UDAT_SHORT_WEEKDAYS, + UDAT_NARROW_WEEKDAYS, + UDAT_STANDALONE_WEEKDAYS, + UDAT_STANDALONE_SHORT_WEEKDAYS, + UDAT_STANDALONE_NARROW_WEEKDAYS, + UDAT_QUARTERS, + UDAT_SHORT_QUARTERS, + UDAT_STANDALONE_QUARTERS, + UDAT_STANDALONE_SHORT_QUARTERS}; + int offsets[18] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}; + CFArrayRef symbols[18] = {formatter->_property._EraSymbols, + formatter->_property._LongEraSymbols, + formatter->_property._MonthSymbols, + formatter->_property._ShortMonthSymbols, + formatter->_property._VeryShortMonthSymbols, + formatter->_property._StandaloneMonthSymbols, + formatter->_property._ShortStandaloneMonthSymbols, + formatter->_property._VeryShortStandaloneMonthSymbols, + formatter->_property._WeekdaySymbols, + formatter->_property._ShortWeekdaySymbols, + formatter->_property._VeryShortWeekdaySymbols, + formatter->_property._StandaloneWeekdaySymbols, + formatter->_property._ShortStandaloneWeekdaySymbols, + formatter->_property._VeryShortStandaloneWeekdaySymbols, + formatter->_property._QuarterSymbols, + formatter->_property._ShortQuarterSymbols, + formatter->_property._StandaloneQuarterSymbols, + formatter->_property._ShortStandaloneQuarterSymbols + }; + CFArrayRef customSymbols[18] = {formatter->_property._CustomEraSymbols, + formatter->_property._CustomLongEraSymbols, + formatter->_property._CustomMonthSymbols, + formatter->_property._CustomShortMonthSymbols, + formatter->_property._CustomVeryShortMonthSymbols, + formatter->_property._CustomStandaloneMonthSymbols, + formatter->_property._CustomShortStandaloneMonthSymbols, + formatter->_property._CustomVeryShortStandaloneMonthSymbols, + formatter->_property._CustomWeekdaySymbols, + formatter->_property._CustomShortWeekdaySymbols, + formatter->_property._CustomVeryShortWeekdaySymbols, + formatter->_property._CustomStandaloneWeekdaySymbols, + formatter->_property._CustomShortStandaloneWeekdaySymbols, + formatter->_property._CustomVeryShortStandaloneWeekdaySymbols, + formatter->_property._CustomQuarterSymbols, + formatter->_property._CustomShortQuarterSymbols, + formatter->_property._CustomStandaloneQuarterSymbols, + formatter->_property._CustomShortStandaloneQuarterSymbols + }; + + for (CFIndex i = 0; i < 18; i++) { + if (symbols[i] != NULL) { + __CFDateFormatterSetSymbolsArray(formatter->_df, types[i], offsets[i], symbols[i]); + } else if (customSymbols[i] != NULL) { + __CFDateFormatterSetSymbolsArray(formatter->_df, types[i], offsets[i], customSymbols[i]); + } + } + + CFStringRef ampm[2]; + ampm[0] = NULL; + ampm[1] = NULL; + + if (formatter->_property._AMSymbol != NULL) { + ampm[0] = formatter->_property._AMSymbol; + } else if (formatter->_property._CustomAMSymbol != NULL) { + ampm[0] = formatter->_property._CustomAMSymbol; + } + if (formatter->_property._PMSymbol != NULL) { + ampm[1] = formatter->_property._PMSymbol; + } else if (formatter->_property._CustomPMSymbol != NULL) { + ampm[1] = formatter->_property._CustomPMSymbol; + } + for (CFIndex i = 0; i < 2; i++) { + CFStringRef sym = ampm[i]; + if (sym != NULL) { + CFIndex item_cnt = CFStringGetLength(sym); + STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt)); + UChar *item_ustr = (UChar *)CFStringGetCharactersPtr(sym); + if (NULL == item_ustr) { + item_cnt = __CFMin(BUFFER_SIZE, item_cnt); + CFStringGetCharacters(sym, CFRangeMake(0, item_cnt), (UniChar *)item_buffer); + item_ustr = item_buffer; + } + UErrorCode status = U_ZERO_ERROR; + __cficu_udat_setSymbols(formatter->_df, UDAT_AM_PMS, i, item_ustr, item_cnt, &status); + } + } +} + +static void __SetCalendarProperties(CFDateFormatterRef df) { + CFStringRef calName = df->_property._CalendarName ? (df->_property._CalendarName) : NULL; + if (!calName) { + calName = (CFStringRef)CFLocaleGetValue(df->_locale, kCFLocaleCalendarIdentifierKey); + } + UErrorCode status = U_ZERO_ERROR; + const UCalendar *cal = __cficu_udat_getCalendar(df->_df); + UCalendar *new_cal = NULL; + + if (df->_property._Calendar != NULL || df->_property._CalendarName != NULL) { + UCalendar *caltmp = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(df->_locale), df->_property._TimeZone); + if (caltmp) { + new_cal = caltmp; + } + } + if (new_cal == NULL) { + new_cal = __cficu_ucal_clone(cal, &status); + } + + if (df->_property._IsLenient != NULL) { + status = U_ZERO_ERROR; + CFBooleanRef value = df->_property._IsLenient; + __cficu_ucal_setAttribute(new_cal, UCAL_LENIENT, (kCFBooleanTrue == value)); + } + if (df->_property._TimeZone != NULL) { + status = U_ZERO_ERROR; + UChar ubuffer[BUFFER_SIZE]; + CFStringRef tznam = CFTimeZoneGetName(df->_property._TimeZone); + CFIndex ucnt = CFStringGetLength(tznam); + if (BUFFER_SIZE < ucnt) ucnt = BUFFER_SIZE; + CFStringGetCharacters(tznam, CFRangeMake(0, ucnt), (UniChar *)ubuffer); + __cficu_ucal_setTimeZone(new_cal, ubuffer, ucnt, &status); + } + if (df->_property._GregorianStartDate != NULL) { + status = U_ZERO_ERROR; + CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)df->_property._GregorianStartDate); + UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0; + __cficu_ucal_setGregorianChange(new_cal, udate, &status); + } else if (calName && CFEqual(calName, kCFCalendarIdentifierGregorian)) { + status = U_ZERO_ERROR; + UDate udate = __cficu_ucal_getGregorianChange(cal, &status); + CFAbsoluteTime at = U_SUCCESS(status) ? (udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970) : -13197600000.0; // Oct 15, 1582 + udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0; + status = U_ZERO_ERROR; + __cficu_ucal_setGregorianChange(new_cal, udate, &status); + } + if (df->_property._Calendar != NULL) { + __cficu_ucal_setAttribute(new_cal, UCAL_FIRST_DAY_OF_WEEK, CFCalendarGetFirstWeekday((CFCalendarRef)df->_property._Calendar)); + } else if (df->_property._CustomFirstWeekday != NULL) { + CFNumberRef firstWeekday = (CFNumberRef)CFDictionaryGetValue(df->_property._CustomFirstWeekday, calName); + if (NULL != firstWeekday && CFGetTypeID(firstWeekday) == CFNumberGetTypeID()) { + CFIndex wkdy; + if (CFNumberGetValue((CFNumberRef)firstWeekday, kCFNumberCFIndexType, &wkdy)) { + status = U_ZERO_ERROR; + __cficu_ucal_setAttribute(new_cal, UCAL_FIRST_DAY_OF_WEEK, wkdy); + } + } + } + + if (df->_property._Calendar != NULL) { + __cficu_ucal_setAttribute(new_cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, CFCalendarGetMinimumDaysInFirstWeek((CFCalendarRef)df->_property._Calendar)); + } else if (df->_property._CustomMinDaysInFirstWeek != NULL) { + CFNumberRef minDays = (CFNumberRef)CFDictionaryGetValue(df->_property._CustomMinDaysInFirstWeek, calName); + if (NULL != minDays && CFGetTypeID(minDays) == CFNumberGetTypeID()) { + CFIndex mwd; + if (CFNumberGetValue((CFNumberRef)minDays, kCFNumberCFIndexType, &mwd)) { + status = U_ZERO_ERROR; + __cficu_ucal_setAttribute(new_cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, mwd); + } + } + } + __cficu_udat_setCalendar(df->_df, new_cal); + __cficu_ucal_close(new_cal); +} + #define RESET_PROPERTY(C, K) \ if (df->_property. C) __CFDateFormatterSetProperty(df, K, df->_property. C, true); -// This blows away any custom format string the client may have set -// on the date formatter with CFDateFormatterSetFormat(). static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomFormat) { - if (df->_df) udat_close(df->_df); + if (df->_df) __cficu_udat_close(df->_df); df->_df = NULL; // uses _timeStyle, _dateStyle, _locale, _property._TimeZone; sets _df, _format, _defformat @@ -255,9 +572,7 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF CFStringRef tmpTZName = df->_property._TimeZone ? CFTimeZoneGetName(df->_property._TimeZone) : CFSTR("GMT"); CFStringGetCharacters(tmpTZName, CFRangeMake(0, CFStringGetLength(tmpTZName)), (UniChar *)tz_buffer); - df->_property._HasCustomFormat = NULL; - - int32_t udstyle = 0, utstyle = 0; + int32_t udstyle = 0, utstyle = 0; // effectively this makes UDAT_FULL the default for unknown dateStyle/timeStyle values switch (df->_dateStyle) { case kCFDateFormatterNoStyle: udstyle = UDAT_NONE; break; case kCFDateFormatterShortStyle: udstyle = UDAT_SHORT; break; @@ -279,34 +594,61 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF } UErrorCode status = U_ZERO_ERROR; - UDateFormat *icudf = udat_open((UDateFormatStyle)utstyle, (UDateFormatStyle)udstyle, loc_buffer, tz_buffer, CFStringGetLength(tmpTZName), NULL, 0, &status); + 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; } - udat_setLenient(icudf, 0); + if (df->_property._IsLenient != NULL) { + __cficu_udat_setLenient(icudf, (kCFBooleanTrue == df->_property._IsLenient)); + } else { + __cficu_udat_setLenient(icudf, 0); + } if (kCFDateFormatterNoStyle == df->_dateStyle && kCFDateFormatterNoStyle == df->_timeStyle) { if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != df->_dateStyle) { UErrorCode s = U_ZERO_ERROR; - udat_applyPatternRelative(icudf, NULL, 0, NULL, 0, &s); + __cficu_udat_applyPatternRelative(icudf, NULL, 0, NULL, 0, &s); } else { - udat_applyPattern(icudf, false, NULL, 0); + __cficu_udat_applyPattern(icudf, false, NULL, 0); } } + if (!wantRelative && df->_property._HasCustomFormat == kCFBooleanTrue) { + CFIndex cnt = CFStringGetLength(df->_format); + STACK_BUFFER_DECL(UChar, ubuffer, cnt); + const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)df->_format); + if (NULL == ustr) { + CFStringGetCharacters(df->_format, CFRangeMake(0, cnt), (UniChar *)ubuffer); + ustr = ubuffer; + } + __cficu_udat_applyPattern(icudf, false, ustr, cnt); + } + CFStringRef calident = (CFStringRef)CFLocaleGetValue(df->_locale, kCFLocaleCalendarIdentifierKey); if (calident && CFEqual(calident, kCFCalendarIdentifierGregorian)) { status = U_ZERO_ERROR; - udat_set2DigitYearStart(icudf, -631152000000.0, &status); // 1950-01-01 00:00:00 GMT + __cficu_udat_set2DigitYearStart(icudf, -631152000000.0, &status); // 1950-01-01 00:00:00 GMT } df->_df = icudf; + + __ReadCustomUDateFormatProperty(df); + + __SetCalendarProperties(df); + + if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != df->_dateStyle) { + __substituteFormatStringFromPrefsDFRelative(df); + } else { + __substituteFormatStringFromPrefsDF(df, false); + __substituteFormatStringFromPrefsDF(df, true); + } - __CFDateFormatterCustomize(df); + __ApplyUDateFormatSymbol(df); + if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != df->_dateStyle) { UChar dateBuffer[BUFFER_SIZE]; UChar timeBuffer[BUFFER_SIZE]; status = U_ZERO_ERROR; - CFIndex dateLen = udat_toPatternRelativeDate(icudf, dateBuffer, BUFFER_SIZE, &status); - CFIndex timeLen = (utstyle != UDAT_NONE) ? udat_toPatternRelativeTime(icudf, timeBuffer, BUFFER_SIZE, &status) : 0; + CFIndex dateLen = __cficu_udat_toPatternRelativeDate(icudf, dateBuffer, BUFFER_SIZE, &status); + CFIndex timeLen = (utstyle != UDAT_NONE) ? __cficu_udat_toPatternRelativeTime(icudf, timeBuffer, BUFFER_SIZE, &status) : 0; if (U_SUCCESS(status) && dateLen <= BUFFER_SIZE && timeLen <= BUFFER_SIZE) { // We assume that the 12/24-hour forcing preferences only affect the Time component CFStringRef newFormat = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)timeBuffer, timeLen); @@ -317,12 +659,12 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)timeBuffer); timeLen = cnt; status = U_ZERO_ERROR; - udat_applyPatternRelative(icudf, dateBuffer, dateLen, timeBuffer, timeLen, &status); + __cficu_udat_applyPatternRelative(icudf, dateBuffer, dateLen, timeBuffer, timeLen, &status); // ignore error and proceed anyway, what else can be done? UChar ubuffer[BUFFER_SIZE]; status = U_ZERO_ERROR; - int32_t ret = udat_toPattern(icudf, false, ubuffer, BUFFER_SIZE, &status); // read out current pattern + int32_t ret = __cficu_udat_toPattern(icudf, false, ubuffer, BUFFER_SIZE, &status); // read out current pattern if (U_SUCCESS(status) && ret <= BUFFER_SIZE) { if (df->_format) CFRelease(df->_format); df->_format = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, ret); @@ -334,7 +676,7 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF } else { UChar ubuffer[BUFFER_SIZE]; status = U_ZERO_ERROR; - int32_t ret = udat_toPattern(icudf, false, ubuffer, BUFFER_SIZE, &status); + int32_t ret = __cficu_udat_toPattern(icudf, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && ret <= BUFFER_SIZE) { CFStringRef newFormat = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, ret); CFStringRef formatString = __CFDateFormatterCreateForcedString(df, newFormat); @@ -348,8 +690,8 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF ustr = ubuffer; } UErrorCode status = U_ZERO_ERROR; -// udat_applyPattern(df->_df, false, ustr, cnt, &status); - udat_applyPattern(df->_df, false, ustr, cnt); +// __cficu_udat_applyPattern(df->_df, false, ustr, cnt, &status); + __cficu_udat_applyPattern(df->_df, false, ustr, cnt); if (U_SUCCESS(status)) { if (df->_format) CFRelease(df->_format); df->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(df), formatString); @@ -362,20 +704,6 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF if (df->_defformat) CFRelease(df->_defformat); df->_defformat = df->_format ? (CFStringRef)CFRetain(df->_format) : NULL; - CFStringRef calName = df->_property._CalendarName ? (df->_property._CalendarName) : NULL; - if (!calName) { - calName = (CFStringRef)CFLocaleGetValue(df->_locale, kCFLocaleCalendarIdentifierKey); - } - if (calName && CFEqual(calName, kCFCalendarIdentifierGregorian)) { - UCalendar *cal = (UCalendar *)udat_getCalendar(df->_df); - status = U_ZERO_ERROR; - UDate udate = ucal_getGregorianChange(cal, &status); - CFAbsoluteTime at = U_SUCCESS(status) ? (udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970) : -13197600000.0; // Oct 15, 1582 - udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0; - status = U_ZERO_ERROR; - ucal_setGregorianChange(cal, udate, &status); - } - RESET_PROPERTY(_IsLenient, kCFDateFormatterIsLenientKey); RESET_PROPERTY(_DoesRelativeDateFormatting, kCFDateFormatterDoesRelativeDateFormattingKey); RESET_PROPERTY(_Calendar, kCFDateFormatterCalendarKey); @@ -384,27 +712,8 @@ static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomF RESET_PROPERTY(_TwoDigitStartDate, kCFDateFormatterTwoDigitStartDateKey); RESET_PROPERTY(_DefaultDate, kCFDateFormatterDefaultDateKey); RESET_PROPERTY(_GregorianStartDate, kCFDateFormatterGregorianStartDateKey); - RESET_PROPERTY(_EraSymbols, kCFDateFormatterEraSymbolsKey); - RESET_PROPERTY(_LongEraSymbols, kCFDateFormatterLongEraSymbolsKey); - RESET_PROPERTY(_MonthSymbols, kCFDateFormatterMonthSymbolsKey); - RESET_PROPERTY(_ShortMonthSymbols, kCFDateFormatterShortMonthSymbolsKey); - RESET_PROPERTY(_VeryShortMonthSymbols, kCFDateFormatterVeryShortMonthSymbolsKey); - RESET_PROPERTY(_StandaloneMonthSymbols, kCFDateFormatterStandaloneMonthSymbolsKey); - RESET_PROPERTY(_ShortStandaloneMonthSymbols, kCFDateFormatterShortStandaloneMonthSymbolsKey); - RESET_PROPERTY(_VeryShortStandaloneMonthSymbols, kCFDateFormatterVeryShortStandaloneMonthSymbolsKey); - RESET_PROPERTY(_WeekdaySymbols, kCFDateFormatterWeekdaySymbolsKey); - RESET_PROPERTY(_ShortWeekdaySymbols, kCFDateFormatterShortWeekdaySymbolsKey); - RESET_PROPERTY(_VeryShortWeekdaySymbols, kCFDateFormatterVeryShortWeekdaySymbolsKey); - RESET_PROPERTY(_StandaloneWeekdaySymbols, kCFDateFormatterStandaloneWeekdaySymbolsKey); - RESET_PROPERTY(_ShortStandaloneWeekdaySymbols, kCFDateFormatterShortStandaloneWeekdaySymbolsKey); - RESET_PROPERTY(_VeryShortStandaloneWeekdaySymbols, kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey); - RESET_PROPERTY(_QuarterSymbols, kCFDateFormatterQuarterSymbolsKey); - RESET_PROPERTY(_ShortQuarterSymbols, kCFDateFormatterShortQuarterSymbolsKey); - RESET_PROPERTY(_StandaloneQuarterSymbols, kCFDateFormatterStandaloneQuarterSymbolsKey); - RESET_PROPERTY(_ShortStandaloneQuarterSymbols, kCFDateFormatterShortStandaloneQuarterSymbolsKey); - RESET_PROPERTY(_AMSymbol, kCFDateFormatterAMSymbolKey); - RESET_PROPERTY(_PMSymbol, kCFDateFormatterPMSymbolKey); RESET_PROPERTY(_AmbiguousYearStrategy, kCFDateFormatterAmbiguousYearStrategyKey); + RESET_PROPERTY(_UsesCharacterDirection, kCFDateFormatterUsesCharacterDirectionKey); } static CFTypeID __kCFDateFormatterTypeID = _kCFRuntimeNotATypeID; @@ -476,6 +785,33 @@ CFDateFormatterRef CFDateFormatterCreate(CFAllocatorRef allocator, CFLocaleRef l memory->_property._AMSymbol = NULL; memory->_property._PMSymbol = NULL; memory->_property._AmbiguousYearStrategy = NULL; + memory->_property._UsesCharacterDirection = NULL; + memory->_property._CustomEraSymbols = NULL; + memory->_property._CustomMonthSymbols = NULL; + memory->_property._CustomShortMonthSymbols = NULL; + memory->_property._CustomWeekdaySymbols = NULL; + memory->_property._CustomShortWeekdaySymbols = NULL; + memory->_property._CustomLongEraSymbols = NULL; + memory->_property._CustomVeryShortMonthSymbols = NULL; + memory->_property._CustomVeryShortWeekdaySymbols = NULL; + memory->_property._CustomStandaloneMonthSymbols = NULL; + memory->_property._CustomShortStandaloneMonthSymbols = NULL; + memory->_property._CustomVeryShortStandaloneMonthSymbols = NULL; + memory->_property._CustomStandaloneWeekdaySymbols = NULL; + memory->_property._CustomShortStandaloneWeekdaySymbols = NULL; + memory->_property._CustomVeryShortStandaloneWeekdaySymbols = NULL; + memory->_property._CustomQuarterSymbols = NULL; + memory->_property._CustomShortQuarterSymbols = NULL; + memory->_property._CustomStandaloneQuarterSymbols = NULL; + memory->_property._CustomShortStandaloneQuarterSymbols = NULL; + memory->_property._CustomDateFormat = NULL; + memory->_property._CustomTimeFormat = NULL; + memory->_property._Custom24Hour = NULL; + memory->_property._Custom12Hour = NULL; + memory->_property._CustomAMSymbol = NULL; + memory->_property._CustomPMSymbol = NULL; + memory->_property._CustomFirstWeekday = NULL; + memory->_property._CustomMinDaysInFirstWeek = NULL; switch (dateStyle) { case kCFDateFormatterNoStyle: @@ -502,6 +838,12 @@ CFDateFormatterRef CFDateFormatterCreate(CFAllocatorRef allocator, CFLocaleRef l memory->_locale = locale ? CFLocaleCreateCopy(allocator, locale) : (CFLocaleRef)CFRetain(CFLocaleGetSystem()); memory->_property._TimeZone = CFTimeZoneCopyDefault(); + + CFStringRef calident = (CFStringRef)CFLocaleGetValue(memory->_locale, kCFLocaleCalendarIdentifierKey); + if (calident && CFEqual(calident, kCFCalendarIdentifierGregorian)) { + memory->_property._TwoDigitStartDate = CFDateCreate(kCFAllocatorSystemDefault, -1609459200.0); // 1950-01-01 00:00:00 +0000 + } + __ResetUDateFormat(memory, false); if (!memory->_df) { CFRelease(memory); @@ -510,34 +852,19 @@ CFDateFormatterRef CFDateFormatterCreate(CFAllocatorRef allocator, CFLocaleRef l return (CFDateFormatterRef)memory; } -extern CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale); - static void __substituteFormatStringFromPrefsDFRelative(CFDateFormatterRef formatter) { - CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale); CFIndex dateLen = -1; UChar dateBuffer[BUFFER_SIZE]; if (kCFDateFormatterNoStyle != formatter->_dateStyle) { - CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUDateFormatStrings")) : NULL; - if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { - CFStringRef key; - switch (formatter->_dateStyle) { - case kCFDateFormatterShortStyle: key = CFSTR("1"); break; - case kCFDateFormatterMediumStyle: key = CFSTR("2"); break; - case kCFDateFormatterLongStyle: key = CFSTR("3"); break; - case kCFDateFormatterFullStyle: key = CFSTR("4"); break; - default: key = CFSTR("0"); break; - } - CFStringRef pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key); - if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) { - dateLen = __CFMin(CFStringGetLength(pref), BUFFER_SIZE); - CFStringGetCharacters(pref, CFRangeMake(0, dateLen), (UniChar *)dateBuffer); - } + if (formatter->_property._CustomDateFormat != NULL) { + dateLen = __CFMin(CFStringGetLength(formatter->_property._CustomDateFormat), BUFFER_SIZE); + CFStringGetCharacters(formatter->_property._CustomDateFormat, CFRangeMake(0, dateLen), (UniChar *)dateBuffer); } } if (-1 == dateLen) { UErrorCode status = U_ZERO_ERROR; - int32_t ret = udat_toPatternRelativeDate(formatter->_df, dateBuffer, BUFFER_SIZE, &status); + int32_t ret = __cficu_udat_toPatternRelativeDate(formatter->_df, dateBuffer, BUFFER_SIZE, &status); if (!U_FAILURE(status)) { dateLen = ret; } @@ -546,54 +873,28 @@ static void __substituteFormatStringFromPrefsDFRelative(CFDateFormatterRef forma CFIndex timeLen = -1; UChar timeBuffer[BUFFER_SIZE]; if (kCFDateFormatterNoStyle != formatter->_timeStyle) { - CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUTimeFormatStrings")) : NULL; - if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { - CFStringRef key; - switch (formatter->_timeStyle) { - case kCFDateFormatterShortStyle: key = CFSTR("1"); break; - case kCFDateFormatterMediumStyle: key = CFSTR("2"); break; - case kCFDateFormatterLongStyle: key = CFSTR("3"); break; - case kCFDateFormatterFullStyle: key = CFSTR("4"); break; - default: key = CFSTR("0"); break; - } - CFStringRef pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key); - if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) { - timeLen = __CFMin(CFStringGetLength(pref), BUFFER_SIZE); - CFStringGetCharacters(pref, CFRangeMake(0, timeLen), (UniChar *)timeBuffer); - } + if (formatter->_property._CustomTimeFormat != NULL) { + timeLen = __CFMin(CFStringGetLength(formatter->_property._CustomTimeFormat), BUFFER_SIZE); + CFStringGetCharacters(formatter->_property._CustomTimeFormat, CFRangeMake(0, timeLen), (UniChar *)timeBuffer); } } if (-1 == timeLen) { UErrorCode status = U_ZERO_ERROR; - int32_t ret = udat_toPatternRelativeTime(formatter->_df, timeBuffer, BUFFER_SIZE, &status); + int32_t ret = __cficu_udat_toPatternRelativeTime(formatter->_df, timeBuffer, BUFFER_SIZE, &status); if (!U_FAILURE(status)) { timeLen = ret; } } UErrorCode status = U_ZERO_ERROR; - udat_applyPatternRelative(formatter->_df, (0 <= dateLen) ? dateBuffer : NULL, (0 <= dateLen) ? dateLen : 0, (0 <= timeLen) ? timeBuffer : NULL, (0 <= timeLen) ? timeLen : 0, &status); + __cficu_udat_applyPatternRelative(formatter->_df, (0 <= dateLen) ? dateBuffer : NULL, (0 <= dateLen) ? dateLen : 0, (0 <= timeLen) ? timeBuffer : NULL, (0 <= timeLen) ? timeLen : 0, &status); } static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter, bool doTime) { CFIndex formatStyle = doTime ? formatter->_timeStyle : formatter->_dateStyle; - CFStringRef prefName = doTime ? CFSTR("AppleICUTimeFormatStrings") : CFSTR("AppleICUDateFormatStrings"); + CFStringRef pref = doTime ? formatter->_property._CustomTimeFormat : formatter->_property._CustomDateFormat; if (kCFDateFormatterNoStyle != formatStyle) { - CFStringRef pref = NULL; - CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale); - CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, prefName) : NULL; - if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { - CFStringRef key; - switch (formatStyle) { - case kCFDateFormatterShortStyle: key = CFSTR("1"); break; - case kCFDateFormatterMediumStyle: key = CFSTR("2"); break; - case kCFDateFormatterLongStyle: key = CFSTR("3"); break; - case kCFDateFormatterFullStyle: key = CFSTR("4"); break; - default: key = CFSTR("0"); break; - } - pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key); - } - if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) { + if (NULL != pref) { int32_t icustyle = UDAT_NONE; switch (formatStyle) { case kCFDateFormatterShortStyle: icustyle = UDAT_SHORT; break; @@ -608,15 +909,15 @@ static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter, bo if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer; } UErrorCode status = U_ZERO_ERROR; - UDateFormat *df = udat_open((UDateFormatStyle)(doTime ? icustyle : UDAT_NONE), (UDateFormatStyle)(doTime ? UDAT_NONE : icustyle), cstr, NULL, 0, NULL, 0, &status); + UDateFormat *df = __cficu_udat_open((UDateFormatStyle)(doTime ? icustyle : UDAT_NONE), (UDateFormatStyle)(doTime ? UDAT_NONE : icustyle), cstr, NULL, 0, NULL, 0, &status); if (NULL != df) { UChar ubuffer[BUFFER_SIZE]; status = U_ZERO_ERROR; - int32_t date_len = udat_toPattern(df, false, ubuffer, BUFFER_SIZE, &status); + int32_t date_len = __cficu_udat_toPattern(df, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && date_len <= BUFFER_SIZE) { CFStringRef dateString = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)ubuffer, date_len); status = U_ZERO_ERROR; - int32_t formatter_len = udat_toPattern(formatter->_df, false, ubuffer, BUFFER_SIZE, &status); + int32_t formatter_len = __cficu_udat_toPattern(formatter->_df, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && formatter_len <= BUFFER_SIZE) { CFMutableStringRef formatString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); CFStringAppendCharacters(formatString, (UniChar *)ubuffer, formatter_len); @@ -632,45 +933,102 @@ static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter, bo new_ustr = new_buffer; } status = U_ZERO_ERROR; -// udat_applyPattern(formatter->_df, false, new_ustr, new_len, &status); - udat_applyPattern(formatter->_df, false, new_ustr, new_len); +// __cficu_udat_applyPattern(formatter->_df, false, new_ustr, new_len, &status); + __cficu_udat_applyPattern(formatter->_df, false, new_ustr, new_len); } CFRelease(formatString); } CFRelease(dateString); } - udat_close(df); + __cficu_udat_close(df); } } } } -static void __CFDateFormatterApplySymbolPrefs(const void *key, const void *value, void *context) { +static void __CFDateFormatterStoreSymbolPrefs(const void *key, const void *value, void *context) { if (CFGetTypeID(key) == CFStringGetTypeID() && CFGetTypeID(value) == CFArrayGetTypeID()) { CFDateFormatterRef formatter = (CFDateFormatterRef)context; UDateFormatSymbolType sym = (UDateFormatSymbolType)CFStringGetIntValue((CFStringRef)key); CFArrayRef array = (CFArrayRef)value; CFIndex idx, cnt = CFArrayGetCount(array); - for (idx = 0; idx < cnt; idx++) { - CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(array, idx); - if (CFGetTypeID(item) != CFStringGetTypeID()) continue; - CFIndex item_cnt = CFStringGetLength(item); - STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt)); - UChar *item_ustr = (UChar *)CFStringGetCharactersPtr(item); - if (NULL == item_ustr) { - item_cnt = __CFMin(BUFFER_SIZE, item_cnt); - CFStringGetCharacters(item, CFRangeMake(0, item_cnt), (UniChar *)item_buffer); - item_ustr = item_buffer; - } - UErrorCode status = U_ZERO_ERROR; - udat_setSymbols(formatter->_df, sym, idx, item_ustr, item_cnt, &status); + switch (sym) { + case UDAT_ERAS: + formatter->_property._CustomEraSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_MONTHS: + formatter->_property._CustomMonthSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_SHORT_MONTHS: + formatter->_property._CustomShortMonthSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_WEEKDAYS: + formatter->_property._CustomWeekdaySymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_SHORT_WEEKDAYS: + formatter->_property._CustomShortWeekdaySymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_AM_PMS: + { + for (idx = 0; idx < cnt; idx++) { + CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(array, idx); + if (CFGetTypeID(item) != CFStringGetTypeID()) continue; + if (idx == 0) { + formatter->_property._CustomAMSymbol = (CFStringRef)CFRetain(item); + } else if (idx == 1) { + formatter->_property._CustomPMSymbol = (CFStringRef)CFRetain(item); + } + } + } + break; + case UDAT_ERA_NAMES: + formatter->_property._CustomLongEraSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_NARROW_MONTHS: + formatter->_property._CustomVeryShortMonthSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_NARROW_WEEKDAYS: + formatter->_property._CustomVeryShortWeekdaySymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_MONTHS: + formatter->_property._CustomStandaloneMonthSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_SHORT_MONTHS: + formatter->_property._CustomShortStandaloneMonthSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_NARROW_MONTHS: + formatter->_property._CustomVeryShortStandaloneMonthSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_WEEKDAYS: + formatter->_property._CustomStandaloneWeekdaySymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_SHORT_WEEKDAYS: + formatter->_property._CustomShortStandaloneWeekdaySymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_NARROW_WEEKDAYS: + formatter->_property._CustomVeryShortStandaloneWeekdaySymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_QUARTERS: + formatter->_property._CustomQuarterSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_SHORT_QUARTERS: + formatter->_property._CustomShortQuarterSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_QUARTERS: + formatter->_property._CustomStandaloneQuarterSymbols = (CFArrayRef)CFRetain(array); + break; + case UDAT_STANDALONE_SHORT_QUARTERS: + formatter->_property._CustomShortStandaloneQuarterSymbols = (CFArrayRef)CFRetain(array); + break; + default: + break; } } } static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFStringRef inString) { if (!inString) return NULL; - + Boolean doForce24 = false, doForce12 = false; CFDictionaryRef prefs = __CFLocaleGetPrefs(locale); CFPropertyListRef pref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce24HourTime")) : NULL; @@ -683,7 +1041,7 @@ static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFS } if (doForce24) doForce12 = false; // if both are set, Force24 wins, period if (!doForce24 && !doForce12) return (CFStringRef)CFRetain(inString); - + CFMutableStringRef outString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); CFIndex cnt = CFStringGetLength(inString); CFIndex lastSecond = -1, lastMinute = -1, firstHour = -1; @@ -692,39 +1050,115 @@ static CFStringRef __CFDateFormatterCreateForcedTemplate(CFLocaleRef locale, CFS Boolean emit = true; UniChar ch = CFStringGetCharacterAtIndex(inString, idx); switch (ch) { - case '\'': isInQuote = !isInQuote; break; - 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 - case 'H': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'h';} break; // switch 24-hour to 12-hour - 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; - break; + case '\'': isInQuote = !isInQuote; break; + 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 + case 'H': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'h';} break; // switch 24-hour to 12-hour + 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; + break; } if (emit) CFStringAppendCharacters(outString, &ch, 1); } - + 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; - CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale); - CFPropertyListRef pref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce24HourTime")) : NULL; - if (NULL != pref && CFGetTypeID(pref) == CFBooleanGetTypeID()) { - doForce24 = CFBooleanGetValue((CFBooleanRef)pref); + if (formatter->_property._Custom24Hour != NULL) { + doForce24 = CFBooleanGetValue((CFBooleanRef)formatter->_property._Custom24Hour); } - pref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce12HourTime")) : NULL; - if (NULL != pref && CFGetTypeID(pref) == CFBooleanGetTypeID()) { - doForce12 = CFBooleanGetValue((CFBooleanRef)pref); + if (formatter->_property._Custom12Hour != NULL) { + doForce12 = CFBooleanGetValue((CFBooleanRef)formatter->_property._Custom12Hour); } if (doForce24) doForce12 = false; // if both are set, Force24 wins, period + + static CFCharacterSetRef hourCharacters; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + hourCharacters = CFCharacterSetCreateWithCharactersInString(kCFAllocatorSystemDefault, CFSTR("hHkK")); + }); + + CFRange hourRange = CFRangeMake(kCFNotFound, 0); + if (!CFStringFindCharacterFromSet(inString, hourCharacters, CFRangeMake(0, CFStringGetLength(inString)), 0, &hourRange) || hourRange.location == kCFNotFound) { + doForce12 = false; + doForce24 = false; + } + 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; @@ -734,10 +1168,10 @@ static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef format UniChar ch = CFStringGetCharacterAtIndex(inString, idx); switch (ch) { case '\'': isInQuote = !isInQuote; 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 - case 'H': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'h';} break; // switch 24-hour to 12-hour - case 'k': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'K';} break; // switch 24-hour to 12-hour + 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; @@ -791,45 +1225,6 @@ static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef format return outString; } -static void __CFDateFormatterCustomize(CFDateFormatterRef formatter) { - Boolean wantRelative = (NULL != formatter->_property._DoesRelativeDateFormatting && formatter->_property._DoesRelativeDateFormatting == kCFBooleanTrue); - Boolean hasFormat = (NULL != formatter->_property._HasCustomFormat && formatter->_property._HasCustomFormat == kCFBooleanTrue); - if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != formatter->_dateStyle) { - __substituteFormatStringFromPrefsDFRelative(formatter); - } else { - __substituteFormatStringFromPrefsDF(formatter, false); - __substituteFormatStringFromPrefsDF(formatter, true); - } - CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale); - CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUDateTimeSymbols")) : NULL; - if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { - CFDictionaryApplyFunction((CFDictionaryRef)metapref, __CFDateFormatterApplySymbolPrefs, formatter); - } - metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleFirstWeekday")) : NULL; - CFStringRef calID = (CFStringRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendarIdentifierKey); - if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { - metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, calID); - } - if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) { - CFIndex wkdy; - if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &wkdy)) { - UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df); - if (cal) ucal_setAttribute(cal, UCAL_FIRST_DAY_OF_WEEK, wkdy); - } - } - metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleMinDaysInFirstWeek")) : NULL; - if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) { - metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, calID); - } - if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) { - CFIndex mwd; - if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &mwd)) { - UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df); - if (cal) ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, mwd); - } - } -} - CFLocaleRef CFDateFormatterGetLocale(CFDateFormatterRef formatter) { __CFGenericValidateType(formatter, CFDateFormatterGetTypeID()); return formatter->_locale; @@ -871,8 +1266,8 @@ void CFDateFormatterSetFormat(CFDateFormatterRef formatter, CFStringRef formatSt ustr = ubuffer; } UErrorCode status = U_ZERO_ERROR; -// udat_applyPattern(formatter->_df, false, ustr, cnt, &status); - udat_applyPattern(formatter->_df, false, ustr, cnt); +// __cficu_udat_applyPattern(formatter->_df, false, ustr, cnt, &status); + __cficu_udat_applyPattern(formatter->_df, false, ustr, cnt); if (U_SUCCESS(status)) { if (formatter->_format) CFRelease(formatter->_format); formatter->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(formatter), formatString); @@ -894,37 +1289,46 @@ CFStringRef CFDateFormatterCreateStringWithAbsoluteTime(CFAllocatorRef allocator if (allocator == NULL) allocator = __CFGetDefaultAllocator(); __CFGenericValidateType(allocator, CFAllocatorGetTypeID()); __CFGenericValidateType(formatter, CFDateFormatterGetTypeID()); - UChar *ustr = NULL, ubuffer[BUFFER_SIZE]; + UChar *ustr = NULL, ubuffer[BUFFER_SIZE + 1]; UErrorCode status = U_ZERO_ERROR; CFIndex used, cnt = BUFFER_SIZE; UDate ud = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0 + 0.5; - used = udat_format(formatter->_df, ud, ubuffer, cnt, NULL, &status); + used = __cficu_udat_format(formatter->_df, ud, ubuffer + 1, cnt, NULL, &status); if (status == U_BUFFER_OVERFLOW_ERROR || cnt < used) { - cnt = used + 1; + cnt = used + 1 + 1; // leave room for RTL marker if needed ustr = (UChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UChar) * cnt, 0); status = U_ZERO_ERROR; - used = udat_format(formatter->_df, ud, ustr, cnt, NULL, &status); + used = __cficu_udat_format(formatter->_df, ud, ustr + 1, cnt, NULL, &status); } CFStringRef string = NULL; if (U_SUCCESS(status)) { - string = CFStringCreateWithCharacters(allocator, (const UniChar *)(ustr ? ustr : ubuffer), used); + UniChar *bufferToUse = ustr ? (UniChar *)ustr : (UniChar *)ubuffer; + if (formatter->_property._UsesCharacterDirection == kCFBooleanTrue && CFLocaleGetLanguageCharacterDirection(CFLocaleGetIdentifier(formatter->_locale)) == kCFLocaleLanguageDirectionRightToLeft) { + // Insert Unicode RTL marker + bufferToUse[0] = 0x200F; + used++; + } else { + // Move past direction marker + bufferToUse++; + } + string = CFStringCreateWithCharacters(allocator, bufferToUse, used); } if (ustr) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ustr); return string; } static UDate __CFDateFormatterCorrectTimeWithTarget(UCalendar *calendar, UDate at, int32_t target, Boolean isEra, UErrorCode *status) { - ucal_setMillis(calendar, at, status); + __cficu_ucal_setMillis(calendar, at, status); UCalendarDateFields field = isEra ? UCAL_ERA : UCAL_YEAR; - ucal_set(calendar, field, target); - return ucal_getMillis(calendar, status); + __cficu_ucal_set(calendar, field, target); + return __cficu_ucal_getMillis(calendar, status); } static UDate __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(UCalendar *calendar, UDate at, CFIndex period, CFIndex pastYears, CFIndex futureYears, Boolean isEra, UErrorCode *status) { - ucal_setMillis(calendar, ucal_getNow(), status); - int32_t currYear = ucal_get(calendar, UCAL_YEAR, status); + __cficu_ucal_setMillis(calendar, __cficu_ucal_getNow(), status); + int32_t currYear = __cficu_ucal_get(calendar, UCAL_YEAR, status); UCalendarDateFields field = isEra ? UCAL_ERA : UCAL_YEAR; - int32_t currEraOrCentury = ucal_get(calendar, field, status); + int32_t currEraOrCentury = __cficu_ucal_get(calendar, field, status); if (!isEra) { currYear %= 100; currEraOrCentury = currEraOrCentury / 100 * 100; // get century @@ -968,8 +1372,8 @@ static UDate __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(UCalendar *ca } currRange.length = period - pastRange.length - futureRange.length; - ucal_setMillis(calendar, at, status); - int32_t atYear = ucal_get(calendar, UCAL_YEAR, status); + __cficu_ucal_setMillis(calendar, at, status); + int32_t atYear = __cficu_ucal_get(calendar, UCAL_YEAR, status); if (!isEra) { atYear %= 100; currEraOrCentury += atYear; @@ -985,15 +1389,17 @@ static UDate __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(UCalendar *ca return __CFDateFormatterCorrectTimeWithTarget(calendar, at, currEraOrCentury+offset, isEra, status); } +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS static int32_t __CFDateFormatterGetMaxYearGivenJapaneseEra(UCalendar *calendar, int32_t era, UErrorCode *status) { int32_t years = 0; - ucal_clear(calendar); - ucal_set(calendar, UCAL_ERA, era+1); - UDate target = ucal_getMillis(calendar, status); - ucal_set(calendar, UCAL_ERA, era); - years = ucal_getFieldDifference(calendar, target, UCAL_YEAR, status); + __cficu_ucal_clear(calendar); + __cficu_ucal_set(calendar, UCAL_ERA, era+1); + UDate target = __cficu_ucal_getMillis(calendar, status); + __cficu_ucal_set(calendar, UCAL_ERA, era); + years = __cficu_ucal_getFieldDifference(calendar, target, UCAL_YEAR, status); return years+1; } +#endif static Boolean __CFDateFormatterHandleAmbiguousYear(CFDateFormatterRef formatter, CFStringRef calendar_id, UDateFormat *df, UCalendar *cal, UDate *at, const UChar *ustr, CFIndex length, UErrorCode *status) { Boolean success = true; @@ -1004,14 +1410,14 @@ static Boolean __CFDateFormatterHandleAmbiguousYear(CFDateFormatterRef formatter if (calendar_id == kCFCalendarIdentifierChinese) { // we default to era 1 if era is missing, however, we cannot just test if the era is 1 becuase we may get era 2 or larger if the year in the string is greater than 60 // now I just assume that the year will not be greater than 600 in the string - if (ucal_get(cal, UCAL_ERA, status) < 10) { + if (__cficu_ucal_get(cal, UCAL_ERA, status) < 10) { switch (ambigStrat) { case kCFDateFormatterAmbiguousYearFailToParse: success = false; break; case kCFDateFormatterAmbiguousYearAssumeToCurrent: { - ucal_setMillis(cal, ucal_getNow(), status); - int32_t currEra = ucal_get(cal, UCAL_ERA, status); + __cficu_ucal_setMillis(cal, __cficu_ucal_getNow(), status); + int32_t currEra = __cficu_ucal_get(cal, UCAL_ERA, status); *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status); break; } @@ -1036,16 +1442,17 @@ static Boolean __CFDateFormatterHandleAmbiguousYear(CFDateFormatterRef formatter } } } else if (calendar_id == kCFCalendarIdentifierJapanese) { // ??? need more work - ucal_clear(cal); - ucal_set(cal, UCAL_ERA, 1); - udat_parseCalendar(df, cal, ustr, length, NULL, status); - UDate test = ucal_getMillis(cal, status); +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS + __cficu_ucal_clear(cal); + __cficu_ucal_set(cal, UCAL_ERA, 1); + __cficu_udat_parseCalendar(df, cal, ustr, length, NULL, status); + UDate test = __cficu_ucal_getMillis(cal, status); if (test != *at) { // missing era - ucal_setMillis(cal, *at, status); - int32_t givenYear = ucal_get(cal, UCAL_YEAR, status); - ucal_setMillis(cal, ucal_getNow(), status); - int32_t currYear = ucal_get(cal, UCAL_YEAR, status); - int32_t currEra = ucal_get(cal, UCAL_ERA, status); + __cficu_ucal_setMillis(cal, *at, status); + int32_t givenYear = __cficu_ucal_get(cal, UCAL_YEAR, status); + __cficu_ucal_setMillis(cal, __cficu_ucal_getNow(), status); + int32_t currYear = __cficu_ucal_get(cal, UCAL_YEAR, status); + int32_t currEra = __cficu_ucal_get(cal, UCAL_ERA, status); switch (ambigStrat) { case kCFDateFormatterAmbiguousYearFailToParse: success = false; @@ -1053,20 +1460,6 @@ static Boolean __CFDateFormatterHandleAmbiguousYear(CFDateFormatterRef formatter case kCFDateFormatterAmbiguousYearAssumeToCurrent: *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status); break; - case kCFDateFormatterAmbiguousYearAssumeToCenteredAroundCurrentDate: - // we allow the ball up to 30 years - // if the given year is larger than the current year + 30 years, we check the previous era - if (givenYear > currYear + 30) { - success = false; // if the previous era cannot have the given year, fail the parse - int32_t years = __CFDateFormatterGetMaxYearGivenJapaneseEra(cal, currEra-1, status); - if (givenYear <= years) { - success = true; - *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra-1, true, status); - } - } else { // current era - *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status); - } - break; case kCFDateFormatterAmbiguousYearAssumeToFuture: if (givenYear < currYear) { // we only consider current or the future success = false; @@ -1122,43 +1515,76 @@ static Boolean __CFDateFormatterHandleAmbiguousYear(CFDateFormatterRef formatter break; // do nothing } } +#else + success = false; +#endif } else { // calenders other than chinese and japanese - int32_t parsedYear = ucal_get(cal, UCAL_YEAR, status); - ucal_setMillis(cal, ucal_getNow(), status); - int32_t currYear = ucal_get(cal, UCAL_YEAR, status); - if (currYear + 1500 < parsedYear) { // most likely that the parsed string had a 2-digits year - switch (ambigStrat) { - case kCFDateFormatterAmbiguousYearFailToParse: - success = false; - break; - case kCFDateFormatterAmbiguousYearAssumeToCurrent: - *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, (currYear / 100 * 100) + parsedYear % 100, false, status); - break; - case kCFDateFormatterAmbiguousYearAssumeToCenteredAroundCurrentDate: - *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 50, 49, false, status); - break; - case kCFDateFormatterAmbiguousYearAssumeToFuture: - *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 0, 99, false, status); - break; - case kCFDateFormatterAmbiguousYearAssumeToPast: - *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 99, 0, false, status); - break; - case kCFDateFormatterAmbiguousYearAssumeToLikelyFuture: - *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 9, 90, false, status); - break; - case kCFDateFormatterAmbiguousYearAssumeToLikelyPast: - *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 90, 9, false, status); - break; - case kCFDateFormatterAmbiguousYearAssumeToNone: - default: - if (calendar_id == kCFCalendarIdentifierGregorian) { // historical default behavior of 1950 - 2049 - int32_t twoDigits = parsedYear % 100; - *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, ((twoDigits < 50) ? 2000 : 1900) + twoDigits, false, status); + int32_t parsedYear = __cficu_ucal_get(cal, UCAL_YEAR, status); + if (parsedYear >= 12000 && parsedYear <= 12099) { // most likely that the parsed string had a 2-digits year + if (formatter->_property._TwoDigitStartDate != NULL) { + UCalendar *tempCal = __cficu_ucal_clone(cal, status); + __cficu_ucal_clear(tempCal); + CFAbsoluteTime twoDigitAt = CFDateGetAbsoluteTime(formatter->_property._TwoDigitStartDate); + UDate targetUdate = (twoDigitAt + kCFAbsoluteTimeIntervalSince1970) * 1000.0; + __cficu_ucal_setMillis(tempCal, targetUdate, status); + int targetYear = __cficu_ucal_get(tempCal, UCAL_YEAR, status); + parsedYear -= 12000; + int targetYearM100 = targetYear % 100; + if (targetYearM100 < parsedYear) { + parsedYear = ((targetYear / 100) * 100) + parsedYear; + } else if (parsedYear < targetYearM100) { + parsedYear = ((targetYear / 100) * 100) + 100 + parsedYear; + } else { + __cficu_ucal_set(cal, UCAL_YEAR, targetYear); + UDate parseUdate = __cficu_ucal_getMillis(cal, status); + if (parseUdate >= targetUdate) { + parsedYear = targetYear; + } else { + parsedYear = targetYear + 100; + } + } + __cficu_ucal_close(tempCal); + __cficu_ucal_set(cal, UCAL_YEAR, parsedYear); + *at = __cficu_ucal_getMillis(cal, status); + } else { + switch (ambigStrat) { + case kCFDateFormatterAmbiguousYearFailToParse: + success = false; + break; + case kCFDateFormatterAmbiguousYearAssumeToCurrent: + { + // we can modify cal here because cal is just a temp cal from the caller + __cficu_ucal_setMillis(cal, __cficu_ucal_getNow(), status); + int32_t currYear = __cficu_ucal_get(cal, UCAL_YEAR, status); + *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, (currYear / 100 * 100) + parsedYear % 100, false, status); + } + break; + case kCFDateFormatterAmbiguousYearAssumeToCenteredAroundCurrentDate: + *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 50, 49, false, status); + break; + case kCFDateFormatterAmbiguousYearAssumeToFuture: + *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 0, 99, false, status); + break; + case kCFDateFormatterAmbiguousYearAssumeToPast: + *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 99, 0, false, status); + break; + case kCFDateFormatterAmbiguousYearAssumeToLikelyFuture: + *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 9, 90, false, status); + break; + case kCFDateFormatterAmbiguousYearAssumeToLikelyPast: + *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 100, 90, 9, false, status); + break; + case kCFDateFormatterAmbiguousYearAssumeToNone: + default: + if (calendar_id == kCFCalendarIdentifierGregorian) { // historical default behavior of 1950 - 2049 + int32_t twoDigits = parsedYear % 100; + *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, ((twoDigits < 50) ? 2000 : 1900) + twoDigits, false, status); + } + break; // do nothing } - break; // do nothing } - } + } } return success; } @@ -1196,53 +1622,43 @@ Boolean CFDateFormatterGetAbsoluteTimeFromString(CFDateFormatterRef formatter, C UDate udate; int32_t dpos = 0; UErrorCode status = U_ZERO_ERROR; - UDateFormat *df2 = udat_clone(formatter->_df, &status); - UCalendar *cal2 = (UCalendar *)udat_getCalendar(df2); + UDateFormat *df2 = __cficu_udat_clone(formatter->_df, &status); + const UCalendar *ucal2 = __cficu_udat_getCalendar(df2); + UCalendar *cal2 = __cficu_ucal_clone(ucal2, &status); CFStringRef calendar_id = (CFStringRef) CFDateFormatterCopyProperty(formatter, kCFDateFormatterCalendarIdentifierKey); - // we can do this direct comparison because locale in the formatter normalizes the identifier - if (formatter->_property._TwoDigitStartDate) { - // if set, don't use hint, leave it all to ICU, as historically - } else if (calendar_id != kCFCalendarIdentifierChinese && calendar_id != kCFCalendarIdentifierJapanese) { - ucal_setMillis(cal2, ucal_getNow(), &status); - int32_t newYear = ((ucal_get(cal2, UCAL_YEAR, &status) / 100) + 16) * 100; // move ahead 1501-1600 years, to the beginning of a century - ucal_set(cal2, UCAL_YEAR, newYear); - ucal_set(cal2, UCAL_MONTH, ucal_getLimit(cal2, UCAL_MONTH, UCAL_ACTUAL_MINIMUM, &status)); - ucal_set(cal2, UCAL_IS_LEAP_MONTH, 0); - ucal_set(cal2, UCAL_DAY_OF_MONTH, ucal_getLimit(cal2, UCAL_DAY_OF_MONTH, UCAL_ACTUAL_MINIMUM, &status)); - ucal_set(cal2, UCAL_HOUR_OF_DAY, ucal_getLimit(cal2, UCAL_HOUR_OF_DAY, UCAL_ACTUAL_MINIMUM, &status)); - ucal_set(cal2, UCAL_MINUTE, ucal_getLimit(cal2, UCAL_MINUTE, UCAL_ACTUAL_MINIMUM, &status)); - ucal_set(cal2, UCAL_SECOND, ucal_getLimit(cal2, UCAL_SECOND, UCAL_ACTUAL_MINIMUM, &status)); - ucal_set(cal2, UCAL_MILLISECOND, 0); - UDate future = ucal_getMillis(cal2, &status); - ucal_clear(cal2); - udat_set2DigitYearStart(df2, future, &status); + if (calendar_id != kCFCalendarIdentifierChinese && calendar_id != kCFCalendarIdentifierJapanese) { + __cficu_ucal_clear(cal2); + // set both year, and 2DigitYearStart to year 12000 + __cficu_ucal_set(cal2, UCAL_YEAR, 12000); + __cficu_udat_set2DigitYearStart(df2, 316516204800.0 * 1000.0, &status); } else if (calendar_id == kCFCalendarIdentifierChinese) { - ucal_clear(cal2); - ucal_set(cal2, UCAL_ERA, 1); // default to era 1 if no era info in the string for chinese + __cficu_ucal_clear(cal2); + __cficu_ucal_set(cal2, UCAL_ERA, 1); // default to era 1 if no era info in the string for chinese } else if (calendar_id == kCFCalendarIdentifierJapanese) { // default to the current era - ucal_setMillis(cal2, ucal_getNow(), &status); - int32_t currEra = ucal_get(cal2, UCAL_ERA, &status); - ucal_clear(cal2); - ucal_set(cal2, UCAL_ERA, currEra); + __cficu_ucal_setMillis(cal2, __cficu_ucal_getNow(), &status); + int32_t currEra = __cficu_ucal_get(cal2, UCAL_ERA, &status); + __cficu_ucal_clear(cal2); + __cficu_ucal_set(cal2, UCAL_ERA, currEra); } if (formatter->_property._DefaultDate) { CFAbsoluteTime at = CFDateGetAbsoluteTime(formatter->_property._DefaultDate); udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0; - ucal_setMillis(cal2, udate, &status); + __cficu_ucal_setMillis(cal2, udate, &status); } - udat_parseCalendar(df2, cal2, ustr, range.length, &dpos, &status); - udate = ucal_getMillis(cal2, &status); + __cficu_udat_parseCalendar(df2, cal2, ustr, range.length, &dpos, &status); + udate = __cficu_ucal_getMillis(cal2, &status); if (rangep) rangep->length = dpos; Boolean success = false; // first status check is for parsing and the second status check is for the work done inside __CFDateFormatterHandleAmbiguousYear() - if (!U_FAILURE(status) && (formatter->_property._TwoDigitStartDate || __CFDateFormatterHandleAmbiguousYear(formatter, calendar_id, df2, cal2, &udate, ustr, range.length, &status)) && !U_FAILURE(status)) { + if (!U_FAILURE(status) && (__CFDateFormatterHandleAmbiguousYear(formatter, calendar_id, df2, cal2, &udate, ustr, range.length, &status)) && !U_FAILURE(status)) { if (atp) { *atp = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970; } success = true; } CFRelease(calendar_id); - udat_close(df2); + __cficu_udat_close(df2); + __cficu_ucal_close(cal2); return success; } @@ -1263,13 +1679,13 @@ static void __CFDateFormatterSetSymbolsArray(UDateFormat *icudf, int32_t icucode item_ustr = item_buffer; } status = U_ZERO_ERROR; - udat_setSymbols(icudf, (UDateFormatSymbolType)icucode, idx + index_base, item_ustr, item_cnt, &status); + __cficu_udat_setSymbols(icudf, (UDateFormatSymbolType)icucode, idx + index_base, item_ustr, item_cnt, &status); } } static CFArrayRef __CFDateFormatterGetSymbolsArray(UDateFormat *icudf, int32_t icucode, int index_base) { UErrorCode status = U_ZERO_ERROR; - CFIndex idx, cnt = udat_countSymbols(icudf, (UDateFormatSymbolType)icucode); + CFIndex idx, cnt = __cficu_udat_countSymbols(icudf, (UDateFormatSymbolType)icucode); if (cnt <= index_base) return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks); cnt = cnt - index_base; STACK_BUFFER_DECL(CFStringRef, strings, cnt); @@ -1277,7 +1693,7 @@ static CFArrayRef __CFDateFormatterGetSymbolsArray(UDateFormat *icudf, int32_t i UChar ubuffer[BUFFER_SIZE]; CFStringRef str = NULL; status = U_ZERO_ERROR; - CFIndex ucnt = udat_getSymbols(icudf, (UDateFormatSymbolType)icucode, idx + index_base, ubuffer, BUFFER_SIZE, &status); + CFIndex ucnt = __cficu_udat_getSymbols(icudf, (UDateFormatSymbolType)icucode, idx + index_base, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { str = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, ucnt); } @@ -1305,7 +1721,6 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR __CFGenericValidateType(key, CFStringGetTypeID()); CFTypeRef oldProperty = NULL; UErrorCode status = U_ZERO_ERROR; - UChar ubuffer[BUFFER_SIZE]; if (kCFDateFormatterIsLenientKey == key) { if (!directToICU) { @@ -1313,12 +1728,10 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR formatter->_property. _IsLenient = NULL; } __CFGenericValidateType(value, CFBooleanGetTypeID()); - udat_setLenient(formatter->_df, (kCFBooleanTrue == value)); - UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df); - if (cal) ucal_setAttribute(cal, UCAL_LENIENT, (kCFBooleanTrue == value)); - if (!directToICU) { - formatter->_property. _IsLenient = (CFBooleanRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterIsLenientKey); - } + if (!directToICU) { + formatter->_property. _IsLenient = value ? (CFBooleanRef)CFRetain(value) : NULL; + __ResetUDateFormat(formatter, false); + } } else if (kCFDateFormatterDoesRelativeDateFormattingKey == key) { if (!directToICU) { oldProperty = formatter->_property. _DoesRelativeDateFormatting; @@ -1344,17 +1757,14 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR CFRelease(mcomponents); CFRelease(components); CFLocaleRef newLocale = CFLocaleCreate(CFGetAllocator(formatter->_locale), localeName); + // at this point, we should be setting the preferences if any into this new locale CFRelease(localeName); CFRelease(formatter->_locale); formatter->_locale = newLocale; - UCalendar *cal = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(formatter->_locale), formatter->_property._TimeZone); - if (cal) ucal_setAttribute(cal, UCAL_FIRST_DAY_OF_WEEK, CFCalendarGetFirstWeekday((CFCalendarRef)value)); - if (cal) ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, CFCalendarGetMinimumDaysInFirstWeek((CFCalendarRef)value)); - if (cal) udat_setCalendar(formatter->_df, cal); - if (cal) ucal_close(cal); - if (!directToICU) { + if (!directToICU) { formatter->_property. _Calendar = (CFCalendarRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterCalendarKey); - } + __ResetUDateFormat(formatter, false); + } } else if (kCFDateFormatterCalendarIdentifierKey == key) { if (!directToICU) { oldProperty = formatter->_property. _CalendarName; @@ -1369,15 +1779,14 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR CFRelease(mcomponents); CFRelease(components); CFLocaleRef newLocale = CFLocaleCreate(CFGetAllocator(formatter->_locale), localeName); + // at this point, we should be setting the preferences if any into this new locale CFRelease(localeName); CFRelease(formatter->_locale); formatter->_locale = newLocale; - UCalendar *cal = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(formatter->_locale), formatter->_property._TimeZone); - if (cal) udat_setCalendar(formatter->_df, cal); - if (cal) ucal_close(cal); - if (!directToICU) { + if (!directToICU) { formatter->_property. _CalendarName = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterCalendarIdentifierKey); - } + __ResetUDateFormat(formatter, false); + } } else if (kCFDateFormatterTimeZoneKey == key) { if (formatter->_property. _TimeZone != value) { if (!directToICU) { @@ -1388,17 +1797,12 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR CFTimeZoneRef old = formatter->_property._TimeZone; formatter->_property._TimeZone = value ? (CFTimeZoneRef)CFRetain(value) : CFTimeZoneCopyDefault(); if (old) CFRelease(old); - CFStringRef tznam = CFTimeZoneGetName(formatter->_property._TimeZone); - UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df); - CFIndex ucnt = CFStringGetLength(tznam); - if (BUFFER_SIZE < ucnt) ucnt = BUFFER_SIZE; - CFStringGetCharacters(tznam, CFRangeMake(0, ucnt), (UniChar *)ubuffer); - ucal_setTimeZone(cal, ubuffer, ucnt, &status); - if (!directToICU) { - old = formatter->_property._TimeZone; - formatter->_property. _TimeZone = (CFTimeZoneRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterTimeZoneKey); - if (old) CFRelease(old); - } + if (!directToICU) { + old = formatter->_property._TimeZone; + formatter->_property. _TimeZone = (CFTimeZoneRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterTimeZoneKey); + __ResetUDateFormat(formatter, false); + if (old) CFRelease(old); + } } } else if (kCFDateFormatterDefaultFormatKey == key) { // read-only attribute @@ -1408,11 +1812,8 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR formatter->_property. _TwoDigitStartDate = NULL; } __CFGenericValidateType(value, CFDateGetTypeID()); - CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)value); - UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0; - udat_set2DigitYearStart(formatter->_df, udate, &status); if (!directToICU) { - formatter->_property. _TwoDigitStartDate = (CFDateRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterTwoDigitStartDateKey); + formatter->_property. _TwoDigitStartDate = value ? (CFDateRef)CFRetain(value) : NULL; } } else if (kCFDateFormatterDefaultDateKey == key) { if (!directToICU) { @@ -1429,13 +1830,10 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR formatter->_property. _GregorianStartDate = NULL; } __CFGenericValidateType(value, CFDateGetTypeID()); - CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)value); - UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0; - UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df); - ucal_setGregorianChange(cal, udate, &status); - if (!directToICU) { - formatter->_property. _GregorianStartDate = (CFDateRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterGregorianStartDateKey); - } + if (!directToICU) { + formatter->_property. _GregorianStartDate = value ? (CFDateRef)CFRetain(value) : NULL; + __ResetUDateFormat(formatter, false); + } } else if (kCFDateFormatterEraSymbolsKey == key) { SET_SYMBOLS_ARRAY(UDAT_ERAS, 0, _EraSymbols) } else if (kCFDateFormatterLongEraSymbolsKey == key) { @@ -1486,9 +1884,9 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, item_cnt), (UniChar *)item_buffer); item_ustr = item_buffer; } - udat_setSymbols(formatter->_df, UDAT_AM_PMS, 0, item_ustr, item_cnt, &status); + __cficu_udat_setSymbols(formatter->_df, UDAT_AM_PMS, 0, item_ustr, item_cnt, &status); if (!directToICU) { - formatter->_property. _AMSymbol = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterAMSymbolKey); + formatter->_property. _AMSymbol = value ? (CFStringRef)CFStringCreateCopy(NULL, value) : NULL; } } else if (kCFDateFormatterPMSymbolKey == key) { if (!directToICU) { @@ -1504,15 +1902,19 @@ static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringR CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, item_cnt), (UniChar *)item_buffer); item_ustr = item_buffer; } - udat_setSymbols(formatter->_df, UDAT_AM_PMS, 1, item_ustr, item_cnt, &status); + __cficu_udat_setSymbols(formatter->_df, UDAT_AM_PMS, 1, item_ustr, item_cnt, &status); if (!directToICU) { - formatter->_property. _PMSymbol = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterPMSymbolKey); + formatter->_property. _PMSymbol = value ? (CFStringRef)CFStringCreateCopy(NULL, value) : NULL; } } else if (kCFDateFormatterAmbiguousYearStrategyKey == key) { oldProperty = formatter->_property._AmbiguousYearStrategy; formatter->_property._AmbiguousYearStrategy = NULL; __CFGenericValidateType(value, CFNumberGetTypeID()); formatter->_property._AmbiguousYearStrategy = (CFNumberRef)CFRetain(value); + } else if (kCFDateFormatterUsesCharacterDirectionKey == key) { + __CFGenericValidateType(value, CFBooleanGetTypeID()); + oldProperty = formatter->_property._UsesCharacterDirection; + formatter->_property._UsesCharacterDirection = (CFBooleanRef)CFRetain(value); } else { CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key); } @@ -1531,7 +1933,7 @@ CFTypeRef CFDateFormatterCopyProperty(CFDateFormatterRef formatter, CFStringRef if (kCFDateFormatterIsLenientKey == key) { if (formatter->_property._IsLenient) return CFRetain(formatter->_property._IsLenient); - return CFRetain(udat_isLenient(formatter->_df) ? kCFBooleanTrue : kCFBooleanFalse); + return CFRetain(__cficu_udat_isLenient(formatter->_df) ? kCFBooleanTrue : kCFBooleanFalse); } else if (kCFDateFormatterDoesRelativeDateFormattingKey == key) { if (formatter->_property._DoesRelativeDateFormatting) return CFRetain(formatter->_property._DoesRelativeDateFormatting); return CFRetain(kCFBooleanFalse); @@ -1544,23 +1946,17 @@ CFTypeRef CFDateFormatterCopyProperty(CFDateFormatterRef formatter, CFStringRef CFStringRef ident = (CFStringRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendarIdentifierKey); return ident ? CFRetain(ident) : NULL; } else if (kCFDateFormatterTimeZoneKey == key) { - if (formatter->_property._TwoDigitStartDate) return CFRetain(formatter->_property._TwoDigitStartDate); - return CFRetain(formatter->_property._TimeZone); + return formatter->_property._TimeZone ? CFRetain(formatter->_property._TimeZone) : NULL; } else if (kCFDateFormatterDefaultFormatKey == key) { return formatter->_defformat ? CFRetain(formatter->_defformat) : NULL; } else if (kCFDateFormatterTwoDigitStartDateKey == key) { - if (formatter->_property._TwoDigitStartDate) return CFRetain(formatter->_property._TwoDigitStartDate); - UDate udate = udat_get2DigitYearStart(formatter->_df, &status); - if (U_SUCCESS(status)) { - CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970; - return CFDateCreate(CFGetAllocator(formatter), at); - } + return formatter->_property._TwoDigitStartDate ? CFRetain(formatter->_property._TwoDigitStartDate) : NULL; } else if (kCFDateFormatterDefaultDateKey == key) { return formatter->_property._DefaultDate ? CFRetain(formatter->_property._DefaultDate) : NULL; } else if (kCFDateFormatterGregorianStartDateKey == key) { if (formatter->_property._GregorianStartDate) return CFRetain(formatter->_property._GregorianStartDate); - UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df); - UDate udate = ucal_getGregorianChange(cal, &status); + const UCalendar *cal = __cficu_udat_getCalendar(formatter->_df); + UDate udate = __cficu_ucal_getGregorianChange(cal, &status); if (U_SUCCESS(status)) { CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970; return CFDateCreate(CFGetAllocator(formatter), at); @@ -1621,24 +2017,26 @@ CFTypeRef CFDateFormatterCopyProperty(CFDateFormatterRef formatter, CFStringRef return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_SHORT_QUARTERS, 0); } else if (kCFDateFormatterAMSymbolKey == key) { if (formatter->_property._AMSymbol) return CFRetain(formatter->_property._AMSymbol); - CFIndex cnt = udat_countSymbols(formatter->_df, UDAT_AM_PMS); + CFIndex cnt = __cficu_udat_countSymbols(formatter->_df, UDAT_AM_PMS); if (2 <= cnt) { - CFIndex ucnt = udat_getSymbols(formatter->_df, UDAT_AM_PMS, 0, ubuffer, BUFFER_SIZE, &status); + CFIndex ucnt = __cficu_udat_getSymbols(formatter->_df, UDAT_AM_PMS, 0, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (UniChar *)ubuffer, ucnt); } } } else if (kCFDateFormatterPMSymbolKey == key) { if (formatter->_property._PMSymbol) return CFRetain(formatter->_property._PMSymbol); - CFIndex cnt = udat_countSymbols(formatter->_df, UDAT_AM_PMS); + CFIndex cnt = __cficu_udat_countSymbols(formatter->_df, UDAT_AM_PMS); if (2 <= cnt) { - CFIndex ucnt = udat_getSymbols(formatter->_df, UDAT_AM_PMS, 1, ubuffer, BUFFER_SIZE, &status); + CFIndex ucnt = __cficu_udat_getSymbols(formatter->_df, UDAT_AM_PMS, 1, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (UniChar *)ubuffer, ucnt); } } } else if (kCFDateFormatterAmbiguousYearStrategyKey == key) { if (formatter->_property._AmbiguousYearStrategy) return CFRetain(formatter->_property._AmbiguousYearStrategy); + } else if (kCFDateFormatterUsesCharacterDirectionKey == key) { + return formatter->_property._UsesCharacterDirection ? CFRetain(formatter->_property._UsesCharacterDirection) : CFRetain(kCFBooleanFalse); } else { CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key); } diff --git a/CFDateFormatter.h b/CFDateFormatter.h index 49ca968..d88a212 100644 --- a/CFDateFormatter.h +++ b/CFDateFormatter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFDateFormatter.h - Copyright (c) 2003-2012, Apple Inc. All rights reserved. + Copyright (c) 2003-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFDATEFORMATTER__) diff --git a/CFDictionary.c b/CFDictionary.c index 173c0ae..b689e99 100644 --- a/CFDictionary.c +++ b/CFDictionary.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFDictionary.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane Machine generated from Notes/HashingCode.template */ @@ -47,7 +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}; -__private_extern__ const CFDictionaryValueCallBacks kCFTypeDictionaryValueCompactableCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; static const CFDictionaryKeyCallBacks __kCFNullDictionaryKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; static const CFDictionaryValueCallBacks __kCFNullDictionaryValueCallBacks = {0, NULL, NULL, NULL, NULL}; @@ -133,328 +132,131 @@ CFTypeID CFDictionaryGetTypeID(void) { return __kCFDictionaryTypeID; } -#define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B) -#define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B) - -static uintptr_t __CFDictionaryStandardRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0100) return stack_value; - return (CFBasicHashHasStrongValues(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_value) : (uintptr_t)CFRetain((CFTypeRef)stack_value); -} - -static uintptr_t __CFDictionaryStandardRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0001) return stack_key; - return (CFBasicHashHasStrongKeys(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_key) : (uintptr_t)CFRetain((CFTypeRef)stack_key); -} - -static void __CFDictionaryStandardReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0200) return; - if (CFBasicHashHasStrongValues(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_value); else CFRelease((CFTypeRef)stack_value); -} - -static void __CFDictionaryStandardReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0002) return; - if (CFBasicHashHasStrongKeys(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_key); else CFRelease((CFTypeRef)stack_key); -} - -static Boolean __CFDictionaryStandardEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - if (CFBasicHashGetSpecialBits(ht) & 0x0400) return coll_value1 == stack_value2; - return CFEqual((CFTypeRef)coll_value1, (CFTypeRef)stack_value2); -} - -static Boolean __CFDictionaryStandardEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - if (CFBasicHashGetSpecialBits(ht) & 0x0004) return coll_key1 == stack_key2; - return CFEqual((CFTypeRef)coll_key1, (CFTypeRef)stack_key2); -} - -static uintptr_t __CFDictionaryStandardHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0008) return stack_key; - return (uintptr_t)CFHash((CFTypeRef)stack_key); -} - -static uintptr_t __CFDictionaryStandardGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFDictionaryStandardCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0800) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value); - return CFCopyDescription((CFTypeRef)stack_value); -} - -static CFStringRef __CFDictionaryStandardCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0010) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key); - return CFCopyDescription((CFTypeRef)stack_key); -} - -static CFBasicHashCallbacks *__CFDictionaryStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); -static void __CFDictionaryStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); - -static const CFBasicHashCallbacks CFDictionaryStandardCallbacks = { - __CFDictionaryStandardCopyCallbacks, - __CFDictionaryStandardFreeCallbacks, - __CFDictionaryStandardRetainValue, - __CFDictionaryStandardRetainKey, - __CFDictionaryStandardReleaseValue, - __CFDictionaryStandardReleaseKey, - __CFDictionaryStandardEquateValues, - __CFDictionaryStandardEquateKeys, - __CFDictionaryStandardHashKey, - __CFDictionaryStandardGetIndirectKey, - __CFDictionaryStandardCopyValueDescription, - __CFDictionaryStandardCopyKeyDescription -}; - -static CFBasicHashCallbacks *__CFDictionaryStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - return (CFBasicHashCallbacks *)&CFDictionaryStandardCallbacks; -} - -static void __CFDictionaryStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { -} - - -static CFBasicHashCallbacks *__CFDictionaryCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - CFBasicHashCallbacks *newcb = NULL; - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); - } else { - newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); - } - if (!newcb) return NULL; - memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *)); - return newcb; -} - -static void __CFDictionaryFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - } else { - CFAllocatorDeallocate(allocator, cb); - } -} - -static uintptr_t __CFDictionaryRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0]; - if (NULL == value_retain) return stack_value; - return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_value); -} - -static uintptr_t __CFDictionaryRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1]; - if (NULL == key_retain) return stack_key; - return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_key); -} - -static void __CFDictionaryReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2]; - if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t) stack_value); -} - -static void __CFDictionaryReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3]; - if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t) stack_key); -} - -static Boolean __CFDictionaryEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4]; - if (NULL == value_equal) return (coll_value1 == stack_value2); - return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t) coll_value1, (const_any_pointer_t) stack_value2) ? 1 : 0; -} - -static Boolean __CFDictionaryEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5]; - if (NULL == key_equal) return (coll_key1 == stack_key2); - return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t) coll_key1, (const_any_pointer_t) stack_key2) ? 1 : 0; -} - -static uintptr_t __CFDictionaryHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6]; - if (NULL == hash) return stack_key; - return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t) stack_key); -} - -static uintptr_t __CFDictionaryGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFDictionaryCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8]; - if (NULL == value_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_value); - return (CFStringRef)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t) stack_value); -} - -static CFStringRef __CFDictionaryCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[9]; - if (NULL == key_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_key); - return (CFStringRef)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t) stack_key); -} static CFBasicHashRef __CFDictionaryCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) { CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); - CFBasicHashCallbacks *cb = NULL; - Boolean std_cb = false; - uint16_t specialBits = 0; - const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; - void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL; - const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; - void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL; - - if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) { - Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain; - Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release; - Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal; - Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash; - Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription; - - Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull); - Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull); - Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull); - Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull); - - Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain; - Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release; - Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal; - Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash; - Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription; - - Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd); - Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd); - Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd); - Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd); - - if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) { - cb = (CFBasicHashCallbacks *)&CFDictionaryStandardCallbacks; - if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) { - std_cb = true; + if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { // all this crap is just for figuring out two flags for GC in the way done historically; it probably simplifies down to three lines, but we let the compiler worry about that + Boolean set_cb = false; + Boolean std_cb = false; + const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; + void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL; + const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; + void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL; + + if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) { + Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain; + Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release; + Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal; + Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash; + Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription; + + Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull); + Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull); + Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull); + Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull); + + Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain; + Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release; + Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal; + Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash; + Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription; + + Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd); + Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd); + Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd); + Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd); + + if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) { + set_cb = true; + if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) { + std_cb = true; + } else { + // just set these to tickle the GC Strong logic below in a way that mimics past practice + key_retain = keyCallBacks ? keyCallBacks->retain : NULL; + key_release = keyCallBacks ? keyCallBacks->release : NULL; + if (useValueCB) { + value_retain = valueCallBacks ? valueCallBacks->retain : NULL; + value_release = valueCallBacks ? valueCallBacks->release : NULL; + } else { + value_retain = key_retain; + value_release = key_release; + } + } + } + } + + if (!set_cb) { + key_retain = keyCallBacks ? keyCallBacks->retain : NULL; + key_release = keyCallBacks ? keyCallBacks->release : NULL; + if (useValueCB) { + value_retain = valueCallBacks ? valueCallBacks->retain : NULL; + value_release = valueCallBacks ? valueCallBacks->release : NULL; } else { - // just set these to tickle the GC Strong logic below in a way that mimics past practice - key_retain = keyCallBacks ? keyCallBacks->retain : NULL; - key_release = keyCallBacks ? keyCallBacks->release : NULL; - if (useValueCB) { - value_retain = valueCallBacks ? valueCallBacks->retain : NULL; - value_release = valueCallBacks ? valueCallBacks->release : NULL; - } else { - value_retain = key_retain; - value_release = key_release; - } + value_retain = key_retain; + value_release = key_release; } - if (keyRetainNull) specialBits |= 0x0001; - if (keyReleaseNull) specialBits |= 0x0002; - if (keyEquateNull) specialBits |= 0x0004; - if (keyHashNull) specialBits |= 0x0008; - if (keyDescribeNull) specialBits |= 0x0010; - if (valueRetainNull) specialBits |= 0x0100; - if (valueReleaseNull) specialBits |= 0x0200; - if (valueEquateNull) specialBits |= 0x0400; - if (valueDescribeNull) specialBits |= 0x0800; - } - } - - if (!cb) { - Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL; - Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL; - CFStringRef (*key_describe)(const_any_pointer_t) = NULL; - CFStringRef (*value_describe)(const_any_pointer_t) = NULL; - CFHashCode (*hash_key)(const_any_pointer_t) = NULL; - key_retain = keyCallBacks ? keyCallBacks->retain : NULL; - key_release = keyCallBacks ? keyCallBacks->release : NULL; - key_equal = keyCallBacks ? keyCallBacks->equal : NULL; - key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL; - if (useValueCB) { - value_retain = valueCallBacks ? valueCallBacks->retain : NULL; - value_release = valueCallBacks ? valueCallBacks->release : NULL; - value_equal = valueCallBacks ? valueCallBacks->equal : NULL; - value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL; - } else { - value_retain = key_retain; - value_release = key_release; - value_equal = key_equal; - value_describe = key_describe; - } - hash_key = keyCallBacks ? keyCallBacks->hash : NULL; - - CFBasicHashCallbacks *newcb = NULL; - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); - } else { - newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); } - if (!newcb) return NULL; - newcb->copyCallbacks = __CFDictionaryCopyCallbacks; - newcb->freeCallbacks = __CFDictionaryFreeCallbacks; - newcb->retainValue = __CFDictionaryRetainValue; - newcb->retainKey = __CFDictionaryRetainKey; - newcb->releaseValue = __CFDictionaryReleaseValue; - newcb->releaseKey = __CFDictionaryReleaseKey; - newcb->equateValues = __CFDictionaryEquateValues; - newcb->equateKeys = __CFDictionaryEquateKeys; - newcb->hashKey = __CFDictionaryHashKey; - newcb->getIndirectKey = __CFDictionaryGetIndirectKey; - newcb->copyValueDescription = __CFDictionaryCopyValueDescription; - newcb->copyKeyDescription = __CFDictionaryCopyKeyDescription; - newcb->context[0] = (uintptr_t)value_retain; - newcb->context[1] = (uintptr_t)key_retain; - newcb->context[2] = (uintptr_t)value_release; - newcb->context[3] = (uintptr_t)key_release; - newcb->context[4] = (uintptr_t)value_equal; - newcb->context[5] = (uintptr_t)key_equal; - newcb->context[6] = (uintptr_t)hash_key; - newcb->context[8] = (uintptr_t)value_describe; - newcb->context[9] = (uintptr_t)key_describe; - cb = newcb; - } - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { if (std_cb || value_retain != NULL || value_release != NULL) { flags |= kCFBasicHashStrongValues; } if (std_cb || key_retain != NULL || key_release != NULL) { flags |= kCFBasicHashStrongKeys; } -#if CFDictionary - if (valueCallBacks == &kCFTypeDictionaryValueCompactableCallBacks) { - // Foundation allocated collections will have compactable values - flags |= kCFBasicHashCompactableValues; - } -#endif } - CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); - if (ht) CFBasicHashSetSpecialBits(ht, specialBits); - if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb); + + CFBasicHashCallbacks callbacks; + callbacks.retainKey = keyCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))keyCallBacks->retain : NULL; + callbacks.releaseKey = keyCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))keyCallBacks->release : NULL; + callbacks.equateKeys = keyCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))keyCallBacks->equal : NULL; + callbacks.hashKey = keyCallBacks ? (CFHashCode (*)(uintptr_t))keyCallBacks->hash : NULL; + callbacks.getIndirectKey = NULL; + callbacks.copyKeyDescription = keyCallBacks ? (CFStringRef (*)(uintptr_t))keyCallBacks->copyDescription : NULL; + callbacks.retainValue = useValueCB ? (valueCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))valueCallBacks->retain : NULL) : (callbacks.retainKey); + callbacks.releaseValue = useValueCB ? (valueCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))valueCallBacks->release : NULL) : (callbacks.releaseKey); + callbacks.equateValues = useValueCB ? (valueCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))valueCallBacks->equal : NULL) : (callbacks.equateKeys); + callbacks.copyValueDescription = useValueCB ? (valueCallBacks ? (CFStringRef (*)(uintptr_t))valueCallBacks->copyDescription : NULL) : (callbacks.copyKeyDescription); + + CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); return ht; } #if CFDictionary -__private_extern__ CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { +CF_PRIVATE CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { #endif #if CFSet || CFBag -__private_extern__ CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { +CF_PRIVATE CFHashRef __CFDictionaryCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { const_any_pointer_t *vlist = klist; #endif CFTypeID typeID = CFDictionaryGetTypeID(); CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues); CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); - CFBasicHashCallbacks *cb = (CFBasicHashCallbacks *)&CFDictionaryStandardCallbacks; - CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); - CFBasicHashSetSpecialBits(ht, 0x0303); + + CFBasicHashCallbacks callbacks; + callbacks.retainKey = (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryKeyCallBacks.retain; + callbacks.releaseKey = (void (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryKeyCallBacks.release; + callbacks.equateKeys = (Boolean (*)(uintptr_t, uintptr_t))kCFTypeDictionaryKeyCallBacks.equal; + callbacks.hashKey = (CFHashCode (*)(uintptr_t))kCFTypeDictionaryKeyCallBacks.hash; + callbacks.getIndirectKey = NULL; + callbacks.copyKeyDescription = (CFStringRef (*)(uintptr_t))kCFTypeDictionaryKeyCallBacks.copyDescription; + callbacks.retainValue = CFDictionary ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryValueCallBacks.retain : callbacks.retainKey; + callbacks.releaseValue = CFDictionary ? (void (*)(CFAllocatorRef, uintptr_t))kCFTypeDictionaryValueCallBacks.release : callbacks.releaseKey; + callbacks.equateValues = CFDictionary ? (Boolean (*)(uintptr_t, uintptr_t))kCFTypeDictionaryValueCallBacks.equal : callbacks.equateKeys; + callbacks.copyValueDescription = CFDictionary ? (CFStringRef (*)(uintptr_t))kCFTypeDictionaryValueCallBacks.copyDescription : callbacks.copyKeyDescription; + + CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); + CFBasicHashSuppressRC(ht); if (0 < numValues) CFBasicHashSetCapacity(ht, numValues); for (CFIndex idx = 0; idx < numValues; idx++) { CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); } - CFBasicHashSetSpecialBits(ht, 0x0000); + CFBasicHashUnsuppressRC(ht); CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)"); return (CFHashRef)ht; } @@ -476,8 +278,7 @@ CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klis CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); } CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)"); return (CFHashRef)ht; } @@ -493,8 +294,7 @@ CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex cap CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); if (!ht) return NULL; - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)"); return (CFMutableHashRef)ht; } @@ -528,8 +328,7 @@ CFHashRef CFDictionaryCreateCopy(CFAllocatorRef allocator, CFHashRef other) { } if (!ht) return NULL; CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)"); return (CFHashRef)ht; } @@ -563,8 +362,7 @@ CFMutableHashRef CFDictionaryCreateMutableCopy(CFAllocatorRef allocator, CFIndex ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); } if (!ht) return NULL; - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)"); return (CFMutableHashRef)ht; } diff --git a/CFDictionary.h b/CFDictionary.h index 41c75d2..312f1d7 100644 --- a/CFDictionary.h +++ b/CFDictionary.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFDictionary.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /*! diff --git a/CFError.c b/CFError.c index d1cee84..00db595 100644 --- a/CFError.c +++ b/CFError.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFError.c - Copyright (c) 2006-2012, Apple Inc. All rights reserved. + Copyright (c) 2006-2013, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -160,7 +160,7 @@ static const CFRuntimeClass __CFErrorClass = { __CFErrorCopyDescription }; -__private_extern__ void __CFErrorInitialize(void) { +CF_PRIVATE void __CFErrorInitialize(void) { __kCFErrorTypeID = _CFRuntimeRegisterClass(&__CFErrorClass); } @@ -312,7 +312,7 @@ CFStringRef _CFErrorCreateDebugDescription(CFErrorRef err) { CFStringRef debugDesc = _CFErrorCopyUserInfoKey(err, kCFErrorDebugDescriptionKey); CFDictionaryRef userInfo = _CFErrorGetUserInfo(err); CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); - CFStringAppendFormat(result, NULL, CFSTR("Error Domain=%@ Code=%d"), CFErrorGetDomain(err), (long)CFErrorGetCode(err)); + CFStringAppendFormat(result, NULL, CFSTR("Error Domain=%@ Code=%ld"), CFErrorGetDomain(err), (long)CFErrorGetCode(err)); CFStringAppendFormat(result, NULL, CFSTR(" \"%@\""), desc); if (debugDesc && CFStringGetLength(debugDesc) > 0) CFStringAppendFormat(result, NULL, CFSTR(" (%@)"), debugDesc); if (userInfo && CFDictionaryGetCount(userInfo)) { diff --git a/CFError.h b/CFError.h index 61ee8a1..8602290 100644 --- a/CFError.h +++ b/CFError.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFError.h - Copyright (c) 2006-2012, Apple Inc. All rights reserved. + Copyright (c) 2006-2013, Apple Inc. All rights reserved. */ /*! diff --git a/CFError_Private.h b/CFError_Private.h index 6a9b6ef..f370523 100644 --- a/CFError_Private.h +++ b/CFError_Private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFError_Private.h - Copyright (c) 2006-2012, Apple Inc. All rights reserved. + Copyright (c) 2006-2013, Apple Inc. All rights reserved. This is Apple-internal SPI for CFError. */ diff --git a/CFFileUtilities.c b/CFFileUtilities.c index 4334b0e..9723263 100644 --- a/CFFileUtilities.c +++ b/CFFileUtilities.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFFileUtilities.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -74,33 +74,33 @@ CF_INLINE void closeAutoFSNoWait(int fd) { if (-1 != fd) close(fd); } -__private_extern__ CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstractType) { +CF_PRIVATE CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstractType) { return (abstractType ? (CFStringRef)CFRetain(abstractType) : NULL); } -__private_extern__ Boolean _CFCreateDirectory(const char *path) { +CF_PRIVATE Boolean _CFCreateDirectory(const char *path) { int no_hang_fd = openAutoFSNoWait(); int ret = ((mkdir(path, 0777) == 0) ? true : false); closeAutoFSNoWait(no_hang_fd); return ret; } -__private_extern__ Boolean _CFRemoveDirectory(const char *path) { +CF_PRIVATE Boolean _CFRemoveDirectory(const char *path) { int no_hang_fd = openAutoFSNoWait(); int ret = ((rmdir(path) == 0) ? true : false); closeAutoFSNoWait(no_hang_fd); return ret; } -__private_extern__ Boolean _CFDeleteFile(const char *path) { +CF_PRIVATE Boolean _CFDeleteFile(const char *path) { int no_hang_fd = openAutoFSNoWait(); int ret = unlink(path) == 0; closeAutoFSNoWait(no_hang_fd); return ret; } -__private_extern__ 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. +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. struct statinfo statBuf; *bytes = NULL; @@ -155,7 +155,7 @@ __private_extern__ Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, co return true; } -__private_extern__ Boolean _CFReadBytesFromPath(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags) { +CF_PRIVATE 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) { @@ -163,7 +163,7 @@ __private_extern__ Boolean _CFReadBytesFromPath(CFAllocatorRef alloc, const char } return result; } -__private_extern__ 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) { // maxLength is the number of bytes desired, or 0 if the whole file is desired regardless of length. char path[CFMaxPathSize]; @@ -173,7 +173,7 @@ __private_extern__ Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef u return _CFReadBytesFromPath(alloc, (const char *)path, bytes, length, maxLength, extraOpenFlags); } -__private_extern__ Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length) { +CF_PRIVATE Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length) { int fd = -1; int mode; struct statinfo statBuf; @@ -216,7 +216,7 @@ __private_extern__ Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, /* On Mac OS 8/9, one of dirSpec and dirURL must be non-NULL. On all other platforms, one of path and dirURL must be non-NULL If both are present, they are assumed to be in-synch; that is, they both refer to the same directory. */ /* Lately, dirSpec appears to be (rightfully) unused. */ -__private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType) { +CF_PRIVATE CFMutableArrayRef _CFCreateContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType) { CFMutableArrayRef files = NULL; Boolean releaseBase = false; CFIndex pathLength = dirPath ? strlen(dirPath) : 0; @@ -493,7 +493,7 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc #else -#error _CFContentsOfDirectory() unknown architecture, not implemented +#error _CFCreateContentsOfDirectory() unknown architecture, not implemented #endif @@ -506,7 +506,7 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc return files; } -__private_extern__ SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, Boolean *exists, SInt32 *posixMode, int64_t *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents) { +CF_PRIVATE SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, Boolean *exists, SInt32 *posixMode, int64_t *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents) { Boolean fileExists; Boolean isDirectory = false; @@ -580,7 +580,7 @@ __private_extern__ SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, if (dirContents != NULL) { if (fileExists && isDirectory) { - CFMutableArrayRef contents = _CFContentsOfDirectory(alloc, (char *)path, NULL, NULL, NULL); + CFMutableArrayRef contents = _CFCreateContentsOfDirectory(alloc, (char *)path, NULL, NULL, NULL); if (contents) { *dirContents = contents; @@ -594,7 +594,7 @@ __private_extern__ SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, return 0; } -__private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pathURL, Boolean *exists, SInt32 *posixMode, int64_t *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents) { +CF_PRIVATE SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pathURL, Boolean *exists, SInt32 *posixMode, int64_t *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents) { char path[CFMaxPathSize]; @@ -614,35 +614,57 @@ __private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pa #if defined(WINDOWS_PATH_SEMANTICS) #define CFPreferredSlash ((UniChar)'\\') + #define CFPreferredSlashStr CFSTR("\\") #elif defined(UNIX_PATH_SEMANTICS) #define CFPreferredSlash ((UniChar)'/') -#elif defined(HFS_PATH_SEMANTICS) - #define CFPreferredSlash ((UniChar)':') + #define CFPreferredSlashStr CFSTR("/") #else #error Cannot define NSPreferredSlash on this platform #endif -#if defined(HFS_PATH_SEMANTICS) -#define HAS_DRIVE(S) (false) -#define HAS_NET(S) (false) -#else +static Boolean _hasDrive(CFStringRef path) { + if (CFStringGetLength(path) >= 2) { + UniChar firstCharacters[2]; + firstCharacters[0] = CFStringGetCharacterAtIndex(path, 0); + firstCharacters[1] = CFStringGetCharacterAtIndex(path, 1); + if (firstCharacters[1] == ':' && + (('A' <= (firstCharacters)[0] && (firstCharacters)[0] <= 'Z') || + ('a' <= (firstCharacters)[0] && (firstCharacters)[0] <= 'z')) + ) { + return true; + } + } + return false; +} + +static Boolean _hasNet(CFStringRef path) { + if (CFStringGetLength(path) >= 2) { + UniChar firstCharacters[2]; + firstCharacters[0] = CFStringGetCharacterAtIndex(path, 0); + firstCharacters[1] = CFStringGetCharacterAtIndex(path, 1); + if (firstCharacters[0] == '\\' && firstCharacters[1] == '\\') return true; + } + return false; +} + #define HAS_DRIVE(S) ((S)[1] == ':' && (('A' <= (S)[0] && (S)[0] <= 'Z') || ('a' <= (S)[0] && (S)[0] <= 'z'))) #define HAS_NET(S) ((S)[0] == '\\' && (S)[1] == '\\') -#endif #if defined(WINDOWS_PATH_SEMANTICS) #define IS_SLASH(C) ((C) == '\\' || (C) == '/') #elif defined(UNIX_PATH_SEMANTICS) #define IS_SLASH(C) ((C) == '/') -#elif defined(HFS_PATH_SEMANTICS) - #define IS_SLASH(C) ((C) == ':') #endif -__private_extern__ UniChar _CFGetSlash(){ +CF_PRIVATE UniChar _CFGetSlash() { return CFPreferredSlash; } -__private_extern__ Boolean _CFIsAbsolutePath(UniChar *unichars, CFIndex length) { +CF_PRIVATE CFStringRef _CFGetSlashStr() { + return CFPreferredSlashStr; +} + +CF_PRIVATE Boolean _CFIsAbsolutePath(UniChar *unichars, CFIndex length) { if (length < 1) { return false; } @@ -662,8 +684,6 @@ __private_extern__ Boolean _CFIsAbsolutePath(UniChar *unichars, CFIndex length) if (IS_SLASH(unichars[2]) && HAS_DRIVE(unichars)) { return true; } -#elif defined(HFS_PATH_SEMANTICS) - return !IS_SLASH(unichars[0]); #else if (unichars[0] == '~') { return true; @@ -675,7 +695,7 @@ __private_extern__ Boolean _CFIsAbsolutePath(UniChar *unichars, CFIndex length) return false; } -__private_extern__ Boolean _CFStripTrailingPathSlashes(UniChar *unichars, CFIndex *length) { +CF_PRIVATE Boolean _CFStripTrailingPathSlashes(UniChar *unichars, CFIndex *length) { Boolean destHasDrive = (1 < *length) && HAS_DRIVE(unichars); CFIndex oldLength = *length; while (((destHasDrive && 3 < *length) || (!destHasDrive && 1 < *length)) && IS_SLASH(unichars[*length - 1])) { @@ -684,7 +704,7 @@ __private_extern__ Boolean _CFStripTrailingPathSlashes(UniChar *unichars, CFInde return (oldLength != *length); } -__private_extern__ Boolean _CFAppendTrailingPathSlash(UniChar *unichars, CFIndex *length, CFIndex maxLength) { +static Boolean _CFAppendTrailingPathSlash(UniChar *unichars, CFIndex *length, CFIndex maxLength) { if (maxLength < *length + 1) { return false; } @@ -708,7 +728,39 @@ __private_extern__ Boolean _CFAppendTrailingPathSlash(UniChar *unichars, CFIndex return true; } -__private_extern__ Boolean _CFAppendPathComponent(UniChar *unichars, CFIndex *length, CFIndex maxLength, UniChar *component, CFIndex componentLength) { +CF_PRIVATE void _CFAppendTrailingPathSlash2(CFMutableStringRef path) { + static const UniChar slash[1] = { CFPreferredSlash }; + CFIndex len = CFStringGetLength(path); + if (len == 0) { + // Do nothing for this case + } else if (len == 1) { + UniChar character = CFStringGetCharacterAtIndex((CFStringRef)path, 0); + if (!IS_SLASH(character)) { + CFStringAppendCharacters(path, slash, 1); + } + } else if (len == 2) { + if (!_hasDrive(path) && !_hasNet(path)) { + CFStringAppendCharacters(path, slash, 1); + } + } else { + CFStringAppendCharacters(path, slash, 1); + } +} + +CF_PRIVATE void _CFAppendConditionalTrailingPathSlash2(CFMutableStringRef path) { + static const UniChar slash[1] = { CFPreferredSlash }; + UniChar character = CFStringGetCharacterAtIndex((CFStringRef)path, CFStringGetLength(path) - 1); + if (!IS_SLASH(character)) { + CFStringAppendCharacters(path, slash, 1); + } +} + +CF_PRIVATE void _CFAppendPathComponent2(CFMutableStringRef path, CFStringRef component) { + _CFAppendTrailingPathSlash2(path); + CFStringAppend(path, component); +} + +CF_PRIVATE Boolean _CFAppendPathComponent(UniChar *unichars, CFIndex *length, CFIndex maxLength, UniChar *component, CFIndex componentLength) { if (0 == componentLength) { return true; } @@ -721,7 +773,61 @@ __private_extern__ Boolean _CFAppendPathComponent(UniChar *unichars, CFIndex *le return true; } -__private_extern__ Boolean _CFAppendPathExtension(UniChar *unichars, CFIndex *length, CFIndex maxLength, UniChar *extension, CFIndex extensionLength) { +CF_PRIVATE Boolean _CFAppendPathExtension2(CFMutableStringRef path, CFStringRef extension) { + if (!path) { + return false; + } + + if (0 < CFStringGetLength(extension) && IS_SLASH(CFStringGetCharacterAtIndex(extension, 0))) { + return false; + } + if (1 < CFStringGetLength(extension)) { + if (_hasDrive(extension)) return false; + } + + Boolean destHasDrive = (1 < CFStringGetLength(path)) && _hasDrive(path); + while (((destHasDrive && 3 < CFStringGetLength(path)) || (!destHasDrive && 1 < CFStringGetLength(path))) && IS_SLASH(CFStringGetCharacterAtIndex(path, CFStringGetLength(path) - 1))) { + CFStringDelete(path, CFRangeMake(CFStringGetLength(path) - 1, 1)); + } + + if (CFStringGetLength(path) == 0) { + return false; + } + + UniChar firstChar = CFStringGetCharacterAtIndex(path, 0); + CFIndex newLength = CFStringGetLength(path); + switch (newLength) { + case 0: + return false; + case 1: + if (IS_SLASH(firstChar) || firstChar == '~') { + return false; + } + break; + case 2: + if (_hasDrive(path) || _hasNet(path)) { + return false; + } + break; + case 3: + if (IS_SLASH(CFStringGetCharacterAtIndex(path, 2)) && _hasDrive(path)) { + return false; + } + break; + } + if (0 < newLength && firstChar == '~') { + // Make sure we have a slash in the string + if (!CFStringFindWithOptions(path, CFPreferredSlashStr, CFRangeMake(1, newLength - 1), 0, NULL)) { + return false; + } + } + static const UniChar dotChar = '.'; + CFStringAppendCharacters(path, &dotChar, 1); + CFStringAppend(path, extension); + return true; +} + +CF_PRIVATE Boolean _CFAppendPathExtension(UniChar *unichars, CFIndex *length, CFIndex maxLength, UniChar *extension, CFIndex extensionLength) { if (maxLength < *length + 1 + extensionLength) { return false; } @@ -767,7 +873,7 @@ __private_extern__ Boolean _CFAppendPathExtension(UniChar *unichars, CFIndex *le return true; } -__private_extern__ Boolean _CFTransmutePathSlashes(UniChar *unichars, CFIndex *length, UniChar replSlash) { +CF_PRIVATE Boolean _CFTransmutePathSlashes(UniChar *unichars, CFIndex *length, UniChar replSlash) { CFIndex didx, sidx, scnt = *length; sidx = (1 < *length && HAS_NET(unichars)) ? 2 : 0; didx = sidx; @@ -783,7 +889,34 @@ __private_extern__ Boolean _CFTransmutePathSlashes(UniChar *unichars, CFIndex *l return (scnt != didx); } -__private_extern__ CFIndex _CFStartOfLastPathComponent(UniChar *unichars, CFIndex length) { +CF_PRIVATE CFStringRef _CFCreateLastPathComponent(CFAllocatorRef alloc, CFStringRef path, CFIndex *slashIndex) { + CFIndex len = CFStringGetLength(path); + if (len < 2) { + // Can't be any path components in a string this short + if (slashIndex) *slashIndex = -1; + return (CFStringRef)CFRetain(path); + } + + // Find the last slash + for (CFIndex i = len - 1; i >= 0; i--) { + if (IS_SLASH(CFStringGetCharacterAtIndex(path, i))) { + if (slashIndex) *slashIndex = i; + return CFStringCreateWithSubstring(alloc, path, CFRangeMake(i + 1, len - i - 1)); + } + } + + // Strip any drive if we have one + if (len > 2 && _hasDrive(path)) { + if (slashIndex) *slashIndex = -1; + return CFStringCreateWithSubstring(alloc, path, CFRangeMake(2, len - 2)); + } + + // No slash, so just return the same string + if (slashIndex) *slashIndex = -1; + return (CFStringRef)CFRetain(path); +} + +CF_PRIVATE CFIndex _CFStartOfLastPathComponent(UniChar *unichars, CFIndex length) { CFIndex idx; if (length < 2) { return 0; @@ -799,7 +932,23 @@ __private_extern__ CFIndex _CFStartOfLastPathComponent(UniChar *unichars, CFInde return 0; } -__private_extern__ CFIndex _CFLengthAfterDeletingLastPathComponent(UniChar *unichars, CFIndex length) { +CF_PRIVATE CFIndex _CFStartOfLastPathComponent2(CFStringRef path) { + CFIndex length = CFStringGetLength(path); + if (length < 2) { + return 0; + } + for (CFIndex idx = length - 1; idx; idx--) { + if (IS_SLASH(CFStringGetCharacterAtIndex(path, idx - 1))) { + return idx; + } + } + if ((2 < length && _hasDrive(path))) { + return 2; + } + return 0; +} + +CF_PRIVATE CFIndex _CFLengthAfterDeletingLastPathComponent(UniChar *unichars, CFIndex length) { CFIndex idx; if (length < 2) { return 0; @@ -818,7 +967,28 @@ __private_extern__ CFIndex _CFLengthAfterDeletingLastPathComponent(UniChar *unic return 0; } -__private_extern__ CFIndex _CFStartOfPathExtension(UniChar *unichars, CFIndex length) { +CF_PRIVATE CFIndex _CFStartOfPathExtension2(CFStringRef path) { + if (CFStringGetLength(path) < 2) { + return 0; + } + Boolean hasDrive = _hasDrive(path); + for (CFIndex idx = CFStringGetLength(path) - 1; idx; idx--) { + UniChar thisCharacter = CFStringGetCharacterAtIndex(path, idx); + if (IS_SLASH(thisCharacter)) { + return 0; + } + if (thisCharacter != '.') { + continue; + } + if (idx == 2 && hasDrive) { + return 0; + } + return idx; + } + return 0; +} + +CF_PRIVATE CFIndex _CFStartOfPathExtension(UniChar *unichars, CFIndex length) { CFIndex idx; if (length < 2) { return 0; @@ -838,9 +1008,97 @@ __private_extern__ CFIndex _CFStartOfPathExtension(UniChar *unichars, CFIndex le return 0; } -__private_extern__ CFIndex _CFLengthAfterDeletingPathExtension(UniChar *unichars, CFIndex length) { +CF_PRIVATE CFIndex _CFLengthAfterDeletingPathExtension2(CFStringRef path) { + CFIndex start = _CFStartOfPathExtension2(path); + return ((0 < start) ? start : CFStringGetLength(path)); +} + +CF_PRIVATE CFIndex _CFLengthAfterDeletingPathExtension(UniChar *unichars, CFIndex length) { CFIndex start = _CFStartOfPathExtension(unichars, length); return ((0 < start) ? start : length); } +#if DEPLOYMENT_TARGET_WINDOWS +#define DT_DIR 4 +#define DT_REG 8 +#define DT_LNK 10 +#endif + +// NOTE: on Windows the filename is UTF16-encoded, the fileNameLen is result of wcslen. This function automatically skips '.' and '..', and '._' files +CF_PRIVATE void _CFIterateDirectory(CFStringRef directoryPath, Boolean (^fileHandler)(CFStringRef fileName, uint8_t fileType)) { + char directoryPathBuf[CFMaxPathSize]; + if (!CFStringGetFileSystemRepresentation(directoryPath, directoryPathBuf, CFMaxPathSize)) return; + +#if DEPLOYMENT_TARGET_WINDOWS + CFIndex cpathLen = strlen(directoryPathBuf); + // Make sure there is room for the additional space we need in the win32 api + if (cpathLen + 2 < CFMaxPathSize) { + WIN32_FIND_DATAW file; + HANDLE handle; + + directoryPathBuf[cpathLen++] = '\\'; + directoryPathBuf[cpathLen++] = '*'; + directoryPathBuf[cpathLen] = '\0'; + + // Convert UTF8 buffer to windows appropriate UTF-16LE + // Get the real length of the string in UTF16 characters + CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, directoryPathBuf, kCFStringEncodingUTF8); + cpathLen = CFStringGetLength(cfStr); + // Allocate a wide buffer to hold the converted string, including space for a NULL terminator + wchar_t *wideBuf = (wchar_t *)malloc((cpathLen + 1) * sizeof(wchar_t)); + // Copy the string into the buffer and terminate + CFStringGetCharacters(cfStr, CFRangeMake(0, cpathLen), (UniChar *)wideBuf); + wideBuf[cpathLen] = 0; + CFRelease(cfStr); + + handle = FindFirstFileW(wideBuf, (LPWIN32_FIND_DATAW)&file); + if (handle != INVALID_HANDLE_VALUE) { + do { + CFIndex nameLen = wcslen(file.cFileName); + if (file.cFileName[0] == '.' && (nameLen == 1 || (nameLen == 2 && file.cFileName[1] == '.'))) { + continue; + } + + CFStringRef fileName = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const uint8_t *)file.cFileName, nameLen * sizeof(wchar_t), kCFStringEncodingUTF16, NO); + if (!fileName) { + continue; + } + + Boolean isDirectory = file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + Boolean result = fileHandler(fileName, isDirectory ? DT_DIR : DT_REG); + CFRelease(fileName); + if (!result) break; + } while (FindNextFileW(handle, &file)); + + FindClose(handle); + } + free(wideBuf); + } +#else + DIR *dirp; + struct dirent *dent; + if ((dirp = opendir(directoryPathBuf))) { + while ((dent = readdir(dirp))) { +#if DEPLOYMENT_TARGET_LINUX + CFIndex nameLen = strlen(dent->d_name); +#else + CFIndex nameLen = dent->d_namlen; +#endif + if (0 == nameLen || 0 == dent->d_fileno || ('.' == dent->d_name[0] && (1 == nameLen || (2 == nameLen && '.' == dent->d_name[1]) || '_' == dent->d_name[1]))) { + continue; + } + + CFStringRef fileName = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dent->d_name); + if (!fileName) { + continue; + } + + Boolean result = fileHandler(fileName, dent->d_type); + CFRelease(fileName); + if (!result) break; + } + (void)closedir(dirp); + } +#endif +} diff --git a/CFICUConverters.c b/CFICUConverters.c index 3414ca3..931b11e 100644 --- a/CFICUConverters.c +++ b/CFICUConverters.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFICUConverters.c - Copyright (c) 2004-2012, Apple Inc. All rights reserved. + Copyright (c) 2004-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -74,7 +74,7 @@ CF_INLINE __CFICUThreadData *__CFStringEncodingICUGetThreadData() { return data; } -__private_extern__ const char *__CFStringEncodingGetICUName(CFStringEncoding encoding) { +CF_PRIVATE const char *__CFStringEncodingGetICUName(CFStringEncoding encoding) { #define STACK_BUFFER_SIZE (60) char buffer[STACK_BUFFER_SIZE]; const char *result = NULL; @@ -93,11 +93,12 @@ __private_extern__ const char *__CFStringEncodingGetICUName(CFStringEncoding enc #undef STACK_BUFFER_SIZE } -__private_extern__ CFStringEncoding __CFStringEncodingGetFromICUName(const char *icuName) { +CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromICUName(const char *icuName) { uint32_t codepage; + char *endPtr; UErrorCode errorCode = U_ZERO_ERROR; - if ((0 == strncasecmp_l(icuName, "windows-", strlen("windows-"), NULL)) && (0 != (codepage = strtol(icuName + strlen("windows-"), NULL, 10)))) return __CFStringEncodingGetFromWindowsCodePage(codepage); + if ((0 == strncasecmp_l(icuName, "windows-", strlen("windows-"), NULL)) && (0 != (codepage = strtol(icuName + strlen("windows-"), &endPtr, 10))) && (*endPtr == '\0')) return __CFStringEncodingGetFromWindowsCodePage(codepage); if (0 != ucnv_countAliases(icuName, &errorCode)) { CFStringEncoding encoding; @@ -107,7 +108,7 @@ __private_extern__ CFStringEncoding __CFStringEncodingGetFromICUName(const char name = ucnv_getStandardName(icuName, "WINDOWS", &errorCode); if (NULL != name) { - if ((0 == strncasecmp_l(name, "windows-", strlen("windows-"), NULL)) && (0 != (codepage = strtol(name + strlen("windows-"), NULL, 10)))) return __CFStringEncodingGetFromWindowsCodePage(codepage); + if ((0 == strncasecmp_l(name, "windows-", strlen("windows-"), NULL)) && (0 != (codepage = strtol(name + strlen("windows-"), &endPtr, 10))) && (*endPtr == '\0')) return __CFStringEncodingGetFromWindowsCodePage(codepage); if (strncasecmp_l(icuName, name, strlen(name), NULL) && (kCFStringEncodingInvalidId != (encoding = __CFStringEncodingGetFromCanonicalName(name)))) return encoding; } @@ -238,14 +239,17 @@ static CFIndex __CFStringEncodingConverterReleaseICUConverter(UConverter *conver #define MAX_BUFFER_SIZE (1000) #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED +#if 0 +// we're no longer doing this check. Revive when the status in the bug changed. #if (U_ICU_VERSION_MAJOR_NUM > 49) #warning Unknown ICU version. Check binary compatibility issues for rdar://problem/6024743 #endif #endif +#endif #define HAS_ICU_BUG_6024743 (1) #define HAS_ICU_BUG_6025527 (1) -__private_extern__ CFIndex __CFStringEncodingICUToBytes(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) { +CF_PRIVATE CFIndex __CFStringEncodingICUToBytes(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) { UConverter *converter; UErrorCode errorCode = U_ZERO_ERROR; const UTF16Char *source = characters; @@ -347,7 +351,7 @@ __private_extern__ CFIndex __CFStringEncodingICUToBytes(const char *icuName, uin return status; } -__private_extern__ CFIndex __CFStringEncodingICUToUnicode(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) { +CF_PRIVATE CFIndex __CFStringEncodingICUToUnicode(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) { UConverter *converter; UErrorCode errorCode = U_ZERO_ERROR; const char *source = (const char *)bytes; @@ -418,17 +422,17 @@ __private_extern__ CFIndex __CFStringEncodingICUToUnicode(const char *icuName, u return status; } -__private_extern__ CFIndex __CFStringEncodingICUCharLength(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) { +CF_PRIVATE CFIndex __CFStringEncodingICUCharLength(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) { CFIndex usedCharLen; return (__CFStringEncodingICUToUnicode(icuName, flags, bytes, numBytes, NULL, NULL, 0, &usedCharLen) == kCFStringEncodingConversionSuccess ? usedCharLen : 0); } -__private_extern__ CFIndex __CFStringEncodingICUByteLength(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars) { +CF_PRIVATE CFIndex __CFStringEncodingICUByteLength(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars) { CFIndex usedByteLen; return (__CFStringEncodingICUToBytes(icuName, flags, characters, numChars, NULL, NULL, 0, &usedByteLen) == kCFStringEncodingConversionSuccess ? usedByteLen : 0); } -__private_extern__ CFStringEncoding *__CFStringEncodingCreateICUEncodings(CFAllocatorRef allocator, CFIndex *numberOfIndex) { +CF_PRIVATE CFStringEncoding *__CFStringEncodingCreateICUEncodings(CFAllocatorRef allocator, CFIndex *numberOfIndex) { CFIndex count = ucnv_countAvailable(); CFIndex numEncodings = 0; CFStringEncoding *encodings; diff --git a/CFICUConverters.h b/CFICUConverters.h index cffc26c..9d1cfef 100644 --- a/CFICUConverters.h +++ b/CFICUConverters.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,23 +26,23 @@ * CoreFoundation * * Created by Aki Inoue on 07/12/04. - * Copyright (c) 2007-2012, Apple Inc. All rights reserved. + * Copyright (c) 2007-2013, Apple Inc. All rights reserved. * */ #include -__private_extern__ const char *__CFStringEncodingGetICUName(CFStringEncoding encoding); +CF_PRIVATE const char *__CFStringEncodingGetICUName(CFStringEncoding encoding); -__private_extern__ CFStringEncoding __CFStringEncodingGetFromICUName(const char *icuName); +CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromICUName(const char *icuName); -__private_extern__ CFIndex __CFStringEncodingICUToBytes(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen); -__private_extern__ CFIndex __CFStringEncodingICUToUnicode(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen); -__private_extern__ CFIndex __CFStringEncodingICUCharLength(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes); -__private_extern__ CFIndex __CFStringEncodingICUByteLength(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars); +CF_PRIVATE CFIndex __CFStringEncodingICUToBytes(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen); +CF_PRIVATE CFIndex __CFStringEncodingICUToUnicode(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen); +CF_PRIVATE CFIndex __CFStringEncodingICUCharLength(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes); +CF_PRIVATE CFIndex __CFStringEncodingICUByteLength(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars); // The caller is responsible for freeing the memory (use CFAllocatorDeallocate) -__private_extern__ CFStringEncoding *__CFStringEncodingCreateICUEncodings(CFAllocatorRef allocator, CFIndex *numberOfIndex); +CF_PRIVATE CFStringEncoding *__CFStringEncodingCreateICUEncodings(CFAllocatorRef allocator, CFIndex *numberOfIndex); diff --git a/CFICULogging.h b/CFICULogging.h new file mode 100644 index 0000000..8673e85 --- /dev/null +++ b/CFICULogging.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013 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@ + */ + +/* + CFICULogging.h + Copyright (c) 2008-2013, Apple Inc. All rights reserved. +*/ + +/* + This file is for the use of the CoreFoundation project only. +*/ + +#if !defined(__COREFOUNDATION_CFICULOGGING__) +#define __COREFOUNDATION_CFICULOGGING__ 1 + +#include +#include +#include +#include +#include +#include + +// ucal + + +#define __cficu_ucal_open ucal_open +#define __cficu_ucal_close ucal_close +#define __cficu_ucal_clone ucal_clone +#define __cficu_ucal_setAttribute ucal_setAttribute +#define __cficu_ucal_getAttribute ucal_getAttribute +#define __cficu_ucal_setGregorianChange ucal_setGregorianChange +#define __cficu_ucal_getGregorianChange ucal_getGregorianChange +#define __cficu_ucal_getMillis ucal_getMillis +#define __cficu_ucal_setMillis ucal_setMillis +#define __cficu_ucal_set ucal_set +#define __cficu_ucal_get ucal_get +#define __cficu_ucal_getDayOfWeekType ucal_getDayOfWeekType +#define __cficu_ucal_getWeekendTransition ucal_getWeekendTransition +#define __cficu_ucal_isWeekend ucal_isWeekend +#define __cficu_ucal_clear ucal_clear +#define __cficu_ucal_getLimit ucal_getLimit +#define __cficu_ucal_add ucal_add +#define __cficu_ucal_roll ucal_roll +#define __cficu_ucal_getFieldDifference ucal_getFieldDifference +#define __cficu_ucal_getNow ucal_getNow +#define __cficu_ucal_setTimeZone ucal_setTimeZone +// udatpg +#define __cficu_udatpg_open udatpg_open +#define __cficu_udatpg_close udatpg_close +#define __cficu_udatpg_getSkeleton udatpg_getSkeleton +#define __cficu_udatpg_getBestPattern udatpg_getBestPattern +// udat +#define __cficu_udat_applyPattern udat_applyPattern +#define __cficu_udat_applyPatternRelative udat_applyPatternRelative +#define __cficu_udat_clone udat_clone +#define __cficu_udat_close udat_close +#define __cficu_udat_countSymbols udat_countSymbols +#define __cficu_udat_format udat_format +#define __cficu_udat_get2DigitYearStart udat_get2DigitYearStart +#define __cficu_udat_getCalendar udat_getCalendar +#define __cficu_udat_getSymbols udat_getSymbols +#define __cficu_udat_isLenient udat_isLenient +#define __cficu_udat_open udat_open +#define __cficu_udat_parseCalendar udat_parseCalendar +#define __cficu_udat_set2DigitYearStart udat_set2DigitYearStart +#define __cficu_udat_setCalendar udat_setCalendar +#define __cficu_udat_setLenient udat_setLenient +#define __cficu_udat_setSymbols udat_setSymbols +#define __cficu_udat_toPattern udat_toPattern +#define __cficu_udat_toPatternRelativeDate udat_toPatternRelativeDate +#define __cficu_udat_toPatternRelativeTime udat_toPatternRelativeTime +#define __cficu_unum_applyPattern unum_applyPattern +#define __cficu_unum_close unum_close +#define __cficu_unum_formatDecimal unum_formatDecimal +#define __cficu_unum_formatDouble unum_formatDouble +#define __cficu_unum_getAttribute unum_getAttribute +#define __cficu_unum_getDoubleAttribute unum_getDoubleAttribute +#define __cficu_unum_getSymbol unum_getSymbol +#define __cficu_unum_getTextAttribute unum_getTextAttribute +#define __cficu_unum_open unum_open +#define __cficu_unum_parse unum_parse +#define __cficu_unum_parseDecimal unum_parseDecimal +#define __cficu_unum_setAttribute unum_setAttribute +#define __cficu_unum_setDoubleAttribute unum_setDoubleAttribute +#define __cficu_unum_setSymbol unum_setSymbol +#define __cficu_unum_setTextAttribute unum_setTextAttribute +#define __cficu_unum_toPattern unum_toPattern + +// ucurr + +#define __cficu_ucurr_getDefaultFractionDigits ucurr_getDefaultFractionDigits +#define __cficu_ucurr_getRoundingIncrement ucurr_getRoundingIncrement + + +#endif diff --git a/CFInternal.h b/CFInternal.h index dffc016..2204025 100644 --- a/CFInternal.h +++ b/CFInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFInternal.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /* @@ -36,6 +36,7 @@ #if !defined(__COREFOUNDATION_CFINTERNAL__) #define __COREFOUNDATION_CFINTERNAL__ 1 + #define __CF_COMPILE_YEAR__ (__DATE__[7] * 1000 + __DATE__[8] * 100 + __DATE__[9] * 10 + __DATE__[10] - 53328) #define __CF_COMPILE_MONTH__ ((__DATE__[1] + __DATE__[2] == 207) ? 1 : \ (__DATE__[1] + __DATE__[2] == 199) ? 2 : \ @@ -92,6 +93,7 @@ CF_EXTERN_C_BEGIN #include #include #include +#include #endif #include @@ -123,13 +125,26 @@ CF_EXPORT CFStringRef _CFStringCreateHostName(void); CF_EXPORT void _CFMachPortInstallNotifyPort(CFRunLoopRef rl, CFStringRef mode); #endif -__private_extern__ CFIndex __CFActiveProcessorCount(); + +CF_PRIVATE CFIndex __CFActiveProcessorCount(); + +#ifndef CLANG_ANALYZER_NORETURN +#if __has_feature(attribute_analyzer_noreturn) +#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) +#else +#define CLANG_ANALYZER_NORETURN +#endif +#endif + +#if DEPLOYMENT_TARGET_WINDOWS +#define __builtin_unreachable() do { } while (0) +#endif #if defined(__i386__) || defined(__x86_64__) #if defined(__GNUC__) - #define HALT do {asm __volatile__("int3"); kill(getpid(), 9); } while (0) + #define HALT do {asm __volatile__("int3"); kill(getpid(), 9); __builtin_unreachable(); } while (0) #elif defined(_MSC_VER) - #define HALT do { DebugBreak(); abort(); } while (0) + #define HALT do { DebugBreak(); abort(); __builtin_unreachable(); } while (0) #else #error Compiler not supported #endif @@ -163,7 +178,7 @@ __private_extern__ CFIndex __CFActiveProcessorCount(); #define __kCFLogAssertion 3 // 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 -__private_extern__ void _CFLogSimple(int32_t lev, char *format, ...); +CF_PRIVATE void _CFLogSimple(int32_t lev, char *format, ...); #if defined(DEBUG) extern void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, const char *func); @@ -200,6 +215,7 @@ enum { __CFTSDKeyCollatorUCollator = 9, __CFTSDKeyRunLoop = 10, __CFTSDKeyRunLoopCntr = 11, + __CFTSDKeyMachMessageBoost = 12, // valid only in the context of a CFMachPort callout // autorelease pool stuff must be higher than run loop constants __CFTSDKeyAutoreleaseData2 = 61, __CFTSDKeyAutoreleaseData1 = 62, @@ -270,16 +286,20 @@ CF_EXPORT void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr); CF_EXPORT CFAllocatorRef _CFTemporaryMemoryAllocator(void); -extern SInt64 __CFTimeIntervalToTSR(CFTimeInterval ti); -extern CFTimeInterval __CFTSRToTimeInterval(SInt64 tsr); +extern uint64_t __CFTimeIntervalToTSR(CFTimeInterval ti); +extern CFTimeInterval __CFTSRToTimeInterval(uint64_t tsr); +// use this instead of attempting to subtract mach_absolute_time() directly, because that can underflow and give an unexpected answer +CF_PRIVATE CFTimeInterval __CFTimeIntervalUntilTSR(uint64_t tsr); +CF_PRIVATE dispatch_time_t __CFTSRToDispatchTime(uint64_t tsr); +CF_PRIVATE uint64_t __CFTSRToNanoseconds(uint64_t tsr); extern CFStringRef __CFCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions); /* Enhanced string formatting support */ -__private_extern__ CFDictionaryRef _CFStringGetFormatSpecifierConfiguration(CFStringRef aFormatString); -__private_extern__ CFStringRef _CFStringCopyWithFomatStringConfiguration(CFStringRef aFormatString, CFDictionaryRef formatConfiguration); -__private_extern__ CFStringRef _CFCopyResolvedFormatStringWithConfiguration(CFTypeRef anObject, CFDictionaryRef aConfiguration, CFDictionaryRef formatOptions); +CF_PRIVATE CFDictionaryRef _CFStringGetFormatSpecifierConfiguration(CFStringRef aFormatString); +CF_PRIVATE CFStringRef _CFStringCopyWithFomatStringConfiguration(CFStringRef aFormatString, CFDictionaryRef formatConfiguration); +CF_PRIVATE CFStringRef _CFCopyResolvedFormatStringWithConfiguration(CFTypeRef anObject, CFDictionaryRef aConfiguration, CFDictionaryRef formatOptions); /* result is long long or int, depending on doLonglong */ @@ -289,6 +309,8 @@ extern Boolean __CFStringScanHex(CFStringInlineBuffer *buf, SInt32 *indexPtr, un extern const char *__CFgetenv(const char *n); +CF_PRIVATE Boolean __CFProcessIsRestricted(); + // This is really about the availability of C99. We don't have that on Windows, but we should everywhere else. #if DEPLOYMENT_TARGET_WINDOWS #define STACK_BUFFER_DECL(T, N, C) T *N = (T *)_alloca((C) * sizeof(T)) @@ -302,7 +324,7 @@ CF_EXPORT void * __CFConstantStringClassReferencePtr; #ifdef __CONSTANT_CFSTRINGS__ #define CONST_STRING_DECL(S, V) const CFStringRef S = (const CFStringRef)__builtin___CFStringMakeConstantString(V); -#define PE_CONST_STRING_DECL(S, V) __private_extern__ const CFStringRef S = (const CFStringRef)__builtin___CFStringMakeConstantString(V); +#define PE_CONST_STRING_DECL(S, V) CF_PRIVATE const CFStringRef S = (const CFStringRef)__builtin___CFStringMakeConstantString(V); #else @@ -323,7 +345,7 @@ static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringCl const CFStringRef S = (CFStringRef) & __ ## S ## __; #define PE_CONST_STRING_DECL(S, V) \ static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0x00, 0x00, 0x07, 0xc8}}, (uint8_t *)V, sizeof(V) - 1}; \ -__private_extern__ const CFStringRef S = (CFStringRef) & __ ## S ## __; +CF_PRIVATE const CFStringRef S = (CFStringRef) & __ ## S ## __; #elif __CF_LITTLE_ENDIAN__ @@ -332,7 +354,7 @@ static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringCl const CFStringRef S = (CFStringRef) & __ ## S ## __; #define PE_CONST_STRING_DECL(S, V) \ static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)(V), sizeof(V) - 1}; \ -__private_extern__ const CFStringRef S = (CFStringRef) & __ ## S ## __; +CF_PRIVATE const CFStringRef S = (CFStringRef) & __ ## S ## __; #endif @@ -350,7 +372,7 @@ CF_EXPORT CFHashCode CFHashBytes(UInt8 *bytes, CFIndex length); CF_EXPORT CFStringEncoding CFStringFileSystemEncoding(void); -__private_extern__ CFStringRef __CFStringCreateImmutableFunnel3(CFAllocatorRef alloc, const void *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean possiblyExternalFormat, Boolean tryToReduceUnicode, Boolean hasLengthByte, Boolean hasNullByte, Boolean noCopy, CFAllocatorRef contentsDeallocator, UInt32 converterFlags); +CF_PRIVATE CFStringRef __CFStringCreateImmutableFunnel3(CFAllocatorRef alloc, const void *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean possiblyExternalFormat, Boolean tryToReduceUnicode, Boolean hasLengthByte, Boolean hasNullByte, Boolean noCopy, CFAllocatorRef contentsDeallocator, UInt32 converterFlags); extern const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr); extern const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr); @@ -358,9 +380,9 @@ extern void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void *ptr) extern CFTypeRef CFMakeUncollectable(CFTypeRef cf); -__private_extern__ void _CFRaiseMemoryException(CFStringRef reason); +CF_PRIVATE void _CFRaiseMemoryException(CFStringRef reason); -__private_extern__ Boolean __CFProphylacticAutofsAccess; +CF_PRIVATE Boolean __CFProphylacticAutofsAccess; #if DEPLOYMENT_TARGET_MACOSX @@ -515,111 +537,63 @@ CF_EXPORT Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void CF_EXPORT Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length); -CF_EXPORT CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType); +CF_PRIVATE CFMutableArrayRef _CFCreateContentsOfDirectory(CFAllocatorRef alloc, char *dirPath, void *dirSpec, CFURLRef dirURL, CFStringRef matchingAbstractType); /* On Mac OS 8/9, one of dirSpec, dirPath and dirURL must be non-NULL */ /* On all other platforms, one of path and dirURL must be non-NULL */ /* If both are present, they are assumed to be in-synch; that is, they both refer to the same directory. */ /* alloc may be NULL */ /* return value is CFArray of CFURLs */ -CF_EXPORT SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, Boolean *exists, SInt32 *posixMode, SInt64 *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents); +CF_PRIVATE SInt32 _CFGetPathProperties(CFAllocatorRef alloc, char *path, Boolean *exists, SInt32 *posixMode, SInt64 *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents); /* alloc may be NULL */ /* any of exists, posixMode, size, modTime, and dirContents can be NULL. Usually it is not a good idea to pass NULL for exists, since interpretting the other values sometimes requires that you know whether the file existed or not. Except for dirContents, it is pretty cheap to compute any of these things as loing as one of them must be computed. */ -CF_EXPORT SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pathURL, Boolean *exists, SInt32 *posixMode, SInt64 *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents); +CF_PRIVATE SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pathURL, Boolean *exists, SInt32 *posixMode, SInt64 *size, CFDateRef *modTime, SInt32 *ownerID, CFArrayRef *dirContents); /* alloc may be NULL */ /* any of exists, posixMode, size, modTime, and dirContents can be NULL. Usually it is not a good idea to pass NULL for exists, since interpretting the other values sometimes requires that you know whether the file existed or not. Except for dirContents, it is pretty cheap to compute any of these things as loing as one of them must be computed. */ /* ==================== Simple path manipulation ==================== */ -/* These functions all act on a UniChar buffers. */ CF_EXPORT UniChar _CFGetSlash(); +CF_PRIVATE CFStringRef _CFGetSlashStr(); CF_EXPORT Boolean _CFIsAbsolutePath(UniChar *unichars, CFIndex length); -CF_EXPORT Boolean _CFStripTrailingPathSlashes(UniChar *unichars, CFIndex *length); -__private_extern__ Boolean _CFAppendTrailingPathSlash(UniChar *unichars, CFIndex *length, CFIndex maxLength); +CF_PRIVATE void _CFAppendTrailingPathSlash2(CFMutableStringRef path); +CF_PRIVATE void _CFAppendConditionalTrailingPathSlash2(CFMutableStringRef path); CF_EXPORT Boolean _CFAppendPathComponent(UniChar *unichars, CFIndex *length, CFIndex maxLength, UniChar *component, CFIndex componentLength); +CF_PRIVATE void _CFAppendPathComponent2(CFMutableStringRef path, CFStringRef component); +CF_PRIVATE Boolean _CFAppendPathExtension2(CFMutableStringRef path, CFStringRef extension); CF_EXPORT Boolean _CFAppendPathExtension(UniChar *unichars, CFIndex *length, CFIndex maxLength, UniChar *extension, CFIndex extensionLength); CF_EXPORT Boolean _CFTransmutePathSlashes(UniChar *unichars, CFIndex *length, UniChar replSlash); +CF_PRIVATE CFStringRef _CFCreateLastPathComponent(CFAllocatorRef alloc, CFStringRef path, CFIndex *slashIndex); CF_EXPORT CFIndex _CFStartOfLastPathComponent(UniChar *unichars, CFIndex length); +CF_PRIVATE CFIndex _CFStartOfLastPathComponent2(CFStringRef path); CF_EXPORT CFIndex _CFLengthAfterDeletingLastPathComponent(UniChar *unichars, CFIndex length); +CF_PRIVATE CFIndex _CFLengthAfterDeletingPathExtension2(CFStringRef path); CF_EXPORT CFIndex _CFStartOfPathExtension(UniChar *unichars, CFIndex length); +CF_PRIVATE CFIndex _CFStartOfPathExtension2(CFStringRef path); CF_EXPORT CFIndex _CFLengthAfterDeletingPathExtension(UniChar *unichars, CFIndex length); -#define __CFMaxRuntimeTypes 65535 - -// Tagged pointer support -// Low-bit set means tagged object, next 3 bits (currently) -// define the tagged object class, next 4 bits are for type -// information for the specific tagged object class. Thus, -// the low byte is for type info, and the rest of a pointer -// (32 or 64-bit) is for payload, whatever the tagged class. -// -// Note that the specific integers used to identify the -// specific tagged classes can and will change from release -// to release (that's why this stuff is in CF*Internal*.h), -// as can the definition of type info vs payload above. -// -#if __LP64__ -#define CF_IS_TAGGED_OBJ(PTR) ((uintptr_t)(PTR) & 0x1) -#define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF) -#else -#define CF_IS_TAGGED_OBJ(PTR) 0 -#define CF_TAGGED_OBJ_TYPE(PTR) 0 +#if __BLOCKS__ +#if DEPLOYMENT_TARGET_WINDOWS +#define DT_DIR 4 +#define DT_REG 8 +#define DT_LNK 10 #endif - -enum { - kCFTaggedObjectID_Invalid = 0, - kCFTaggedObjectID_Atom = (0 << 1) + 1, - kCFTaggedObjectID_Undefined3 = (1 << 1) + 1, - kCFTaggedObjectID_Undefined2 = (2 << 1) + 1, - kCFTaggedObjectID_Integer = (3 << 1) + 1, - kCFTaggedObjectID_DateTS = (4 << 1) + 1, - kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data - kCFTaggedObjectID_Date = (6 << 1) + 1, - kCFTaggedObjectID_Undefined7 = (7 << 1) + 1, -}; +// This function automatically skips '.' and '..', and '._' files +CF_PRIVATE void _CFIterateDirectory(CFStringRef directoryPath, Boolean (^fileHandler)(CFStringRef fileName, uint8_t fileType)); +#endif +#define __CFMaxRuntimeTypes 65535 #define __CFRuntimeClassTableSize 1024 -extern uintptr_t __CFRuntimeObjCClassTable[]; -CF_INLINE uintptr_t __CFISAForTypeID(CFTypeID typeID) { - return (typeID < __CFRuntimeClassTableSize) ? __CFRuntimeObjCClassTable[typeID] : 0; -} - -CF_INLINE Boolean CF_IS_OBJC(CFTypeID typeID, const void *obj) { -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS - if (CF_IS_TAGGED_OBJ(obj)) return true; - uintptr_t cfisa = ((CFRuntimeBase *)obj)->_cfisa; - if (cfisa == 0) return false; -#if 0 - // Temporarily disabled -#if __LP64__ - if (cfisa < 0x10000000UL) { - CFLog(kCFLogLevelWarning, CFSTR("*** Warning: CF tested pointer %p for objectness and found its isa pointer to be bogus (%p)"), obj, cfisa); - return false; - } -#else - if (cfisa < 0x1000UL) { - CFLog(kCFLogLevelWarning, CFSTR("*** Warning: CF tested pointer %p for objectness and found its isa pointer to be bogus (%p)"), obj, cfisa); - return false; - } -#endif -#endif - if (cfisa == (uintptr_t)__CFConstantStringClassReferencePtr) return false; - uintptr_t type_isa = (uintptr_t)(typeID < __CFRuntimeClassTableSize ? __CFRuntimeObjCClassTable[typeID] : 0); - if (cfisa == type_isa) return false; - return true; -#else - return false; -#endif -} - +extern void _CFRuntimeSetInstanceTypeIDAndIsa(CFTypeRef cf, CFTypeID newTypeID); #define CF_OBJC_FUNCDISPATCHV(typeID, obj, ...) do { } while (0) #define CF_OBJC_CALLV(obj, ...) (0) - +#define CF_IS_OBJC(typeID, obj) (0) +#define __CFISAForTypeID(t) (0) /* See comments in CFBase.c */ @@ -703,19 +677,21 @@ extern void *__CFLookupCoreServicesInternalFunction(const char *name); #define DEFINE_WEAK_CORESERVICESINTERNAL_FUNC(R, N, P, A, ...) #endif -__private_extern__ CFComparisonResult _CFCompareStringsWithLocale(CFStringInlineBuffer *str1, CFRange str1Range, CFStringInlineBuffer *str2, CFRange str2Range, CFOptionFlags options, const void *compareLocale); +CF_PRIVATE CFComparisonResult _CFCompareStringsWithLocale(CFStringInlineBuffer *str1, CFRange str1Range, CFStringInlineBuffer *str2, CFRange str2Range, CFOptionFlags options, const void *compareLocale); -__private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops); +CF_PRIVATE CFArrayRef _CFBundleCopyUserLanguages(); // This should only be used in CF types, not toll-free bridged objects! // It should not be used with CFAllocator arguments! // Use CFGetAllocator() in the general case, and this inline function in a few limited (but often called) situations. CF_INLINE CFAllocatorRef __CFGetAllocator(CFTypeRef cf) { // !!! Use with CF types only, and NOT WITH CFAllocator! - if (CF_IS_TAGGED_OBJ(cf)) { +#if OBJC_HAVE_TAGGED_POINTERS + if (_objc_isTaggedPointer(cf)) { return kCFAllocatorSystemDefault; } +#endif if (__builtin_expect(__CFBitfieldGetValue(((const CFRuntimeBase *)cf)->_cfinfo[CF_INFO_BITS], 7, 7), 1)) { return kCFAllocatorSystemDefault; } @@ -730,8 +706,10 @@ struct __objcFastEnumerationStateEquivalent { unsigned long extra[5]; }; +#if 0 #pragma mark - #pragma mark Windows Compatability +#endif // Need to use the _O_BINARY flag on Windows to get the correct behavior #if DEPLOYMENT_TARGET_WINDOWS @@ -764,7 +742,7 @@ CF_EXPORT void _NS_pthread_setname_np(const char *name); #endif #if DEPLOYMENT_TARGET_WINDOWS -__private_extern__ const wchar_t *_CFDLLPath(void); +CF_PRIVATE const wchar_t *_CFDLLPath(void); #endif /* Buffer size for file pathname */ @@ -781,6 +759,24 @@ __private_extern__ const wchar_t *_CFDLLPath(void); #define PATH_SEP_STR CFSTR("/") #endif +CF_INLINE const char *CFPathRelativeToAppleFrameworksRoot(const char *path, Boolean *allocated) { + if (path) { + const char *platformRoot = __CFgetenv("APPLE_FRAMEWORKS_ROOT"); + if (platformRoot) { + char *newPath = NULL; + asprintf(&newPath, "%s%s", platformRoot, path); + if (allocated && newPath) { + *allocated = true; + } + return newPath; + } + } + if (allocated) { + *allocated = false; + } + return path; +} + CF_EXTERN_C_END #endif /* ! __COREFOUNDATION_CFINTERNAL__ */ diff --git a/CFLocale.c b/CFLocale.c index d6eb54d..b9a840c 100644 --- a/CFLocale.c +++ b/CFLocale.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFLocale.c - Copyright (c) 2002-2012, Apple Inc. All rights reserved. + Copyright (c) 2002-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -154,11 +154,11 @@ struct __CFLocale { Boolean _nullLocale; }; -__private_extern__ Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale) { +CF_PRIVATE Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale) { return locale->_nullLocale; } -__private_extern__ void __CFLocaleSetNullLocale(struct __CFLocale *locale) { +CF_PRIVATE void __CFLocaleSetNullLocale(struct __CFLocale *locale) { locale->_nullLocale = true; } @@ -299,72 +299,97 @@ static CFLocaleRef __CFLocaleCurrent = NULL; #define FALLBACK_LOCALE_NAME CFSTR("en_US") #endif -CFLocaleRef CFLocaleCopyCurrent(void) { - - CFStringRef name = NULL, ident = NULL; +static CFLocaleRef _CFLocaleCopyCurrentGuts(CFStringRef name, Boolean useCache, CFDictionaryRef overridePrefs) { + + CFStringRef ident = NULL; // We cannot be helpful here, because it causes performance problems, // even though the preference lookup is relatively quick, as there are // things which call this function thousands or millions of times in // a short period. + if (!name) { #if 0 // DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX - name = (CFStringRef)CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication); + name = (CFStringRef)CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication); #endif + } else { + CFRetain(name); + } if (name && (CFStringGetTypeID() == CFGetTypeID(name))) { ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, name); } if (name) CFRelease(name); - CFLocaleRef oldLocale = NULL; - __CFLocaleLockGlobal(); - if (__CFLocaleCurrent) { - if (ident && !CFEqual(__CFLocaleCurrent->_identifier, ident)) { - oldLocale = __CFLocaleCurrent; - __CFLocaleCurrent = NULL; - } else { - CFLocaleRef res = __CFLocaleCurrent; - CFRetain(res); - __CFLocaleUnlockGlobal(); - if (ident) CFRelease(ident); - return res; - } + + if (useCache) { + CFLocaleRef oldLocale = NULL; + __CFLocaleLockGlobal(); + if (__CFLocaleCurrent) { + if (ident && !CFEqual(__CFLocaleCurrent->_identifier, ident)) { + oldLocale = __CFLocaleCurrent; + __CFLocaleCurrent = NULL; + } else { + CFLocaleRef res = __CFLocaleCurrent; + CFRetain(res); + __CFLocaleUnlockGlobal(); + if (ident) CFRelease(ident); + return res; + } + } + __CFLocaleUnlockGlobal(); + if (oldLocale) CFRelease(oldLocale); } - __CFLocaleUnlockGlobal(); - if (oldLocale) CFRelease(oldLocale); - if (ident) CFRelease(ident); - // We could *probably* re-use ident down below, but that would't - // get us out of querying CFPrefs for the current application state. - + CFDictionaryRef prefs = NULL; - CFStringRef identifier = NULL; struct __CFLocale *locale; uint32_t size = sizeof(struct __CFLocale) - sizeof(CFRuntimeBase); locale = (struct __CFLocale *)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, CFLocaleGetTypeID(), size, NULL); if (NULL == locale) { if (prefs) CFRelease(prefs); - if (identifier) CFRelease(identifier); + if (ident) CFRelease(ident); return NULL; } __CFLocaleSetType(locale, __kCFLocaleUser); - if (NULL == identifier) identifier = (CFStringRef)CFRetain(FALLBACK_LOCALE_NAME); - locale->_identifier = identifier; + if (NULL == ident) ident = (CFStringRef)CFRetain(FALLBACK_LOCALE_NAME); + locale->_identifier = ident; locale->_cache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); locale->_overrides = NULL; locale->_prefs = prefs; locale->_lock = CFSpinLockInit; locale->_nullLocale = false; - - __CFLocaleLockGlobal(); - if (NULL == __CFLocaleCurrent) { - __CFLocaleCurrent = locale; - } else { - CFRelease(locale); + + if (useCache) { + __CFLocaleLockGlobal(); + if (NULL == __CFLocaleCurrent) { + __CFLocaleCurrent = locale; + } else { + CFRelease(locale); + } + locale = (struct __CFLocale *)CFRetain(__CFLocaleCurrent); + __CFLocaleUnlockGlobal(); } - locale = (struct __CFLocale *)CFRetain(__CFLocaleCurrent); - __CFLocaleUnlockGlobal(); return locale; } -__private_extern__ CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale) { +/* + NSDateFormatter: Cannot specify force12HourTime/force24HourTime + This returns an instance of CFLocale that's set up exactly like it would be if the user changed the current locale to that identifier, then called CFLocaleCopyCurrent() + */ +CFLocaleRef _CFLocaleCopyAsIfCurrent(CFStringRef name) { + return _CFLocaleCopyCurrentGuts(name, false, NULL); +} + +/* + Need the ability to initialize a CFLocaleRef from a preferences dictionary + This returns an instance of CFLocale that's set up exactly like it would be if the user changed the current locale to that identifier, set the preferences keys in the overrides dictionary, then called CFLocaleCopyCurrent() + */ +CFLocaleRef _CFLocaleCopyAsIfCurrentWithOverrides(CFStringRef name, CFDictionaryRef overrides) { + return _CFLocaleCopyCurrentGuts(name, false, overrides); +} + +CFLocaleRef CFLocaleCopyCurrent(void) { + return _CFLocaleCopyCurrentGuts(NULL, true, NULL); +} + +CF_PRIVATE CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale) { CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFDictionaryRef, (NSLocale *)locale, _prefs); return locale->_prefs; } diff --git a/CFLocale.h b/CFLocale.h index 3f575fc..b8d3383 100644 --- a/CFLocale.h +++ b/CFLocale.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFLocale.h - Copyright (c) 2002-2012, Apple Inc. All rights reserved. + Copyright (c) 2002-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFLOCALE__) diff --git a/CFLocaleIdentifier.c b/CFLocaleIdentifier.c index 48bc702..496c907 100644 --- a/CFLocaleIdentifier.c +++ b/CFLocaleIdentifier.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /* CFLocaleIdentifier.c - Copyright (c) 2002-2012, Apple Inc. All rights reserved. + Copyright (c) 2002-2013, Apple Inc. All rights reserved. Responsibility: David Smith CFLocaleIdentifier.c defines diff --git a/CFLocaleInternal.h b/CFLocaleInternal.h index c1b5b98..7b0134a 100644 --- a/CFLocaleInternal.h +++ b/CFLocaleInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /* CFLocaleInternal.h - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. */ /* @@ -83,6 +83,7 @@ CF_EXPORT CFStringRef const kCFDateFormatterVeryShortStandaloneMonthSymbolsKey; CF_EXPORT CFStringRef const kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey; CF_EXPORT CFStringRef const kCFDateFormatterVeryShortWeekdaySymbolsKey; CF_EXPORT CFStringRef const kCFDateFormatterWeekdaySymbolsKey; +CF_EXPORT CFStringRef const kCFDateFormatterUsesCharacterDirectionKey; CF_EXPORT CFStringRef const kCFNumberFormatterAlwaysShowDecimalSeparatorKey; CF_EXPORT CFStringRef const kCFNumberFormatterCurrencyCodeKey; @@ -122,6 +123,7 @@ CF_EXPORT CFStringRef const kCFNumberFormatterSecondaryGroupingSizeKey; CF_EXPORT CFStringRef const kCFNumberFormatterUseGroupingSeparatorKey; CF_EXPORT CFStringRef const kCFNumberFormatterUseSignificantDigitsKey; CF_EXPORT CFStringRef const kCFNumberFormatterZeroSymbolKey; +CF_EXPORT CFStringRef const kCFNumberFormatterUsesCharacterDirectionKey; CF_EXPORT CFStringRef const kCFCalendarIdentifierGregorian; CF_EXPORT CFStringRef const kCFCalendarIdentifierBuddhist; diff --git a/CFLocaleKeys.c b/CFLocaleKeys.c index 425c9af..6d79c89 100644 --- a/CFLocaleKeys.c +++ b/CFLocaleKeys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFLocaleKeys.c - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -80,6 +80,7 @@ CONST_STRING_DECL(kCFDateFormatterVeryShortStandaloneMonthSymbolsKey, "kCFDateFo CONST_STRING_DECL(kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey, "kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey"); CONST_STRING_DECL(kCFDateFormatterVeryShortWeekdaySymbolsKey, "kCFDateFormatterVeryShortWeekdaySymbolsKey"); CONST_STRING_DECL(kCFDateFormatterWeekdaySymbolsKey, "kCFDateFormatterWeekdaySymbolsKey"); +CONST_STRING_DECL(kCFDateFormatterUsesCharacterDirectionKey, "kCFDateFormatterUsesCharacterDirectionKey"); CONST_STRING_DECL(kCFNumberFormatterAlwaysShowDecimalSeparatorKey, "kCFNumberFormatterAlwaysShowDecimalSeparatorKey"); CONST_STRING_DECL(kCFNumberFormatterCurrencyCodeKey, "kCFNumberFormatterCurrencyCodeKey"); @@ -119,6 +120,7 @@ CONST_STRING_DECL(kCFNumberFormatterSecondaryGroupingSizeKey, "kCFNumberFormatte CONST_STRING_DECL(kCFNumberFormatterUseGroupingSeparatorKey, "kCFNumberFormatterUseGroupingSeparatorKey"); CONST_STRING_DECL(kCFNumberFormatterUseSignificantDigitsKey, "kCFNumberFormatterUseSignificantDigitsKey"); CONST_STRING_DECL(kCFNumberFormatterZeroSymbolKey, "kCFNumberFormatterZeroSymbolKey"); +CONST_STRING_DECL(kCFNumberFormatterUsesCharacterDirectionKey, "kCFNumberFormatterUsesCharacterDirectionKey"); CONST_STRING_DECL(kCFCalendarIdentifierGregorian, "gregorian"); CONST_STRING_DECL(kCFCalendarIdentifierBuddhist, "buddhist"); @@ -233,6 +235,8 @@ CF_EXPORT CFStringRef const kCFNumberFormatterSecondaryGroupingSize __attribute_ CF_EXPORT CFStringRef const kCFNumberFormatterUseGroupingSeparator __attribute__((alias ("kCFNumberFormatterUseGroupingSeparatorKey"))); CF_EXPORT CFStringRef const kCFNumberFormatterUseSignificantDigits __attribute__((alias ("kCFNumberFormatterUseSignificantDigitsKey"))); CF_EXPORT CFStringRef const kCFNumberFormatterZeroSymbol __attribute__((alias ("kCFNumberFormatterZeroSymbolKey"))); +CF_EXPORT CFStringRef const kCFNumberFormatterUsesCharacterDirection __attribute__((alias ("kCFNumberFormatterUsesCharacterDirectionKey"))); +CF_EXPORT CFStringRef const kCFDateFormatterUsesCharacterDirection __attribute__((alias ("kCFDateFormatterUsesCharacterDirectionKey"))); CF_EXPORT CFStringRef const kCFDateFormatterCalendarName __attribute__((alias ("kCFDateFormatterCalendarIdentifierKey"))); #endif diff --git a/CFLogUtilities.h b/CFLogUtilities.h index b4b0623..896f4b2 100644 --- a/CFLogUtilities.h +++ b/CFLogUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFLogUtilities.h - Copyright (c) 2004-2012, Apple Inc. All rights reserved. + Copyright (c) 2004-2013, Apple Inc. All rights reserved. */ /* diff --git a/CFMachPort.c b/CFMachPort.c index d5df91e..a8479e1 100644 --- a/CFMachPort.c +++ b/CFMachPort.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFMachPort.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -33,6 +33,7 @@ #include #include #include +#include #include "CFInternal.h" @@ -62,14 +63,14 @@ struct __CFMachPort { int32_t _state; mach_port_t _port; /* immutable */ dispatch_source_t _dsrc; /* protected by _lock */ - dispatch_source_t _dsrc2; /* protected by _lock */ dispatch_semaphore_t _dsrc_sem; /* protected by _lock */ - dispatch_semaphore_t _dsrc2_sem; /* protected by _lock */ CFMachPortInvalidationCallBack _icallout; /* protected by _lock */ CFRunLoopSourceRef _source; /* immutable, once created */ CFMachPortCallBack _callout; /* immutable */ CFMachPortContext _context; /* immutable */ CFSpinLock_t _lock; + const void *(*retain)(const void *info); // use these to store the real callbacks + void (*release)(const void *info); }; /* Bit 1 in the base reserved bits is used for has-receive-ref state */ @@ -131,7 +132,7 @@ static CFStringRef __CFMachPortCopyDescription(CFTypeRef cf) { Dl_info info; void *addr = mp->_callout; const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???"; - CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{valid = %s, port = %p, source = %p, callout = %s (%p), context = %@}"), cf, CFGetAllocator(mp), (__CFMachPortIsValid(mp) ? "Yes" : "No"), mp->_port, mp->_source, name, addr, contextDesc); + CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{valid = %s, port = %x, source = %p, callout = %s (%p), context = %@}"), cf, CFGetAllocator(mp), (__CFMachPortIsValid(mp) ? "Yes" : "No"), mp->_port, mp->_source, name, addr, contextDesc); if (NULL != contextDesc) { CFRelease(contextDesc); } @@ -153,10 +154,11 @@ CF_INLINE void __CFMachPortInvalidateLocked(CFRunLoopSourceRef source, CFMachPor __CFSpinLock(&mp->_lock); } void *info = mp->_context.info; + void (*release)(const void *info) = mp->release; mp->_context.info = NULL; - if (mp->_context.release) { + if (release) { __CFSpinUnlock(&mp->_lock); - mp->_context.release(info); + release(info); __CFSpinLock(&mp->_lock); } mp->_state = kCFMachPortStateInvalid; @@ -178,10 +180,6 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { dispatch_source_cancel(mp->_dsrc); mp->_dsrc = NULL; } - if (mp->_dsrc2) { - dispatch_source_cancel(mp->_dsrc2); - mp->_dsrc2 = NULL; - } source = mp->_source; mp->_source = NULL; } @@ -193,7 +191,6 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { // hand ownership of the port and semaphores to the block below mach_port_t port = mp->_port; dispatch_semaphore_t sem1 = mp->_dsrc_sem; - dispatch_semaphore_t sem2 = mp->_dsrc2_sem; Boolean doSend2 = __CFMachPortHasSend2(mp), doSend = __CFMachPortHasSend(mp), doReceive = __CFMachPortHasReceive(mp); __CFSpinUnlock(&mp->_lock); @@ -204,11 +201,6 @@ static void __CFMachPortDeallocate(CFTypeRef cf) { // immediate release is only safe if dispatch_semaphore_signal() does not touch the semaphore after doing the signal bit dispatch_release(sem1); } - if (sem2) { - dispatch_semaphore_wait(sem2, DISPATCH_TIME_FOREVER); - // immediate release is only safe if dispatch_semaphore_signal() does not touch the semaphore after doing the signal bit - dispatch_release(sem2); - } // MUST deallocate the send right FIRST if necessary, // then the receive right if necessary. Don't ask me why; @@ -234,6 +226,7 @@ static CFMutableArrayRef __CFAllMachPorts = NULL; static __CFPointerArray *__CFAllMachPorts = nil; #endif +static Boolean __CFMachPortCheck(mach_port_t) __attribute__((noinline)); static Boolean __CFMachPortCheck(mach_port_t port) { mach_port_type_t type = 0; kern_return_t ret = mach_port_type(mach_task_self(), port, &type); @@ -262,10 +255,6 @@ static void __CFMachPortChecker(Boolean fromTimer) { dispatch_source_cancel(mp->_dsrc); mp->_dsrc = NULL; } - if (mp->_dsrc2) { - dispatch_source_cancel(mp->_dsrc2); - mp->_dsrc2 = NULL; - } source = mp->_source; mp->_source = NULL; CFRetain(mp); @@ -309,7 +298,7 @@ static const CFRuntimeClass __CFMachPortClass = { __CFMachPortCopyDescription }; -__private_extern__ void __CFMachPortInitialize(void) { +CF_PRIVATE void __CFMachPortInitialize(void) { __kCFMachPortTypeID = _CFRuntimeRegisterClass(&__CFMachPortClass); } @@ -337,10 +326,7 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p static dispatch_source_t timerSource = NULL; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - uint64_t nanos = 63 * 1000 * 1000 * 1000ULL; - uint64_t leeway = 9 * 1000ULL; - timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _CFMachPortQueue()); - dispatch_source_set_timer(timerSource, dispatch_time(DISPATCH_TIME_NOW, nanos), nanos, leeway); + timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_INTERVAL, 60 * 1000 /* milliseconds */, 0, _CFMachPortQueue()); dispatch_source_set_event_handler(timerSource, ^{ __CFMachPortChecker(true); }); @@ -378,20 +364,24 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p } memory->_port = port; memory->_dsrc = NULL; - memory->_dsrc2 = NULL; memory->_dsrc_sem = NULL; - memory->_dsrc2_sem = NULL; memory->_icallout = NULL; memory->_source = NULL; memory->_context.info = NULL; memory->_context.retain = NULL; memory->_context.release = NULL; memory->_context.copyDescription = NULL; + memory->retain = NULL; + memory->release = NULL; memory->_callout = callout; memory->_lock = CFSpinLockInit; if (NULL != context) { objc_memmove_collectable(&memory->_context, context, sizeof(CFMachPortContext)); memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info; + memory->retain = context->retain; + memory->release = context->release; + memory->_context.retain = (void *)0xAAAAAAAAAACCCAAA; + memory->_context.release = (void *)0xAAAAAAAAAABBBAAA; } memory->_state = kCFMachPortStateReady; __CFSpinLock(&__CFAllMachPortsLock); @@ -408,26 +398,14 @@ CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t p if (type & MACH_PORT_TYPE_SEND_RIGHTS) { dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, port, DISPATCH_MACH_SEND_DEAD, _CFMachPortQueue()); - dispatch_source_set_cancel_handler(theSource, ^{ - dispatch_release(theSource); - }); - dispatch_source_set_event_handler(theSource, ^{ - __CFMachPortChecker(false); - }); - memory->_dsrc = theSource; - dispatch_resume(theSource); - } - if (memory->_dsrc) { - dispatch_source_t source = memory->_dsrc; // put these in locals so they are fully copied into the block - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - memory->_dsrc_sem = sem; - dispatch_source_set_cancel_handler(memory->_dsrc, ^{ dispatch_semaphore_signal(sem); dispatch_release(source); }); - } - if (memory->_dsrc2) { - dispatch_source_t source = memory->_dsrc2; - dispatch_semaphore_t sem = dispatch_semaphore_create(0); - memory->_dsrc2_sem = sem; - dispatch_source_set_cancel_handler(memory->_dsrc2, ^{ dispatch_semaphore_signal(sem); dispatch_release(source); }); + if (theSource) { + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + dispatch_source_set_cancel_handler(theSource, ^{ dispatch_semaphore_signal(sem); dispatch_release(theSource); }); + dispatch_source_set_event_handler(theSource, ^{ __CFMachPortChecker(false); }); + memory->_dsrc_sem = sem; + memory->_dsrc = theSource; + dispatch_resume(theSource); + } } } @@ -498,10 +476,6 @@ void CFMachPortInvalidate(CFMachPortRef mp) { dispatch_source_cancel(mp->_dsrc); mp->_dsrc = NULL; } - if (mp->_dsrc2) { - dispatch_source_cancel(mp->_dsrc2); - mp->_dsrc2 = NULL; - } source = mp->_source; mp->_source = NULL; } @@ -553,6 +527,13 @@ CFMachPortInvalidationCallBack CFMachPortGetInvalidationCallBack(CFMachPortRef m void CFMachPortSetInvalidationCallBack(CFMachPortRef mp, CFMachPortInvalidationCallBack callout) { CHECK_FOR_FORK_RET(); __CFGenericValidateType(mp, CFMachPortGetTypeID()); + if (callout) { + mach_port_type_t type = 0; + kern_return_t ret = mach_port_type(mach_task_self(), mp->_port, &type); + if (KERN_SUCCESS != ret || 0 == (type & MACH_PORT_TYPE_SEND_RIGHTS)) { + 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); if (__CFMachPortIsValid(mp) || !callout) { mp->_icallout = callout; @@ -581,7 +562,7 @@ static mach_port_t __CFMachPortGetPort(void *info) { return mp->_port; } -static void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef allocator, 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); @@ -589,25 +570,27 @@ static void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef allocat void *context_info = NULL; void (*context_release)(const void *) = NULL; if (isValid) { - if (mp->_context.retain) { - context_info = (void *)mp->_context.retain(mp->_context.info); - context_release = mp->_context.release; + if (mp->retain) { + context_info = (void *)mp->retain(mp->_context.info); + context_release = mp->release; } else { context_info = mp->_context.info; } } __CFSpinUnlock(&mp->_lock); - if (!isValid) return NULL; - - mp->_callout(mp, msg, size, context_info); + if (isValid) { + mp->_callout(mp, msg, size, context_info); - if (context_release) { - context_release(context_info); + if (context_release) { + context_release(context_info); + } + CHECK_FOR_FORK_RET(NULL); } - CHECK_FOR_FORK_RET(NULL); return NULL; } + + CFRunLoopSourceRef CFMachPortCreateRunLoopSource(CFAllocatorRef allocator, CFMachPortRef mp, CFIndex order) { CHECK_FOR_FORK_RET(NULL); __CFGenericValidateType(mp, CFMachPortGetTypeID()); diff --git a/CFMachPort.h b/CFMachPort.h index de87262..605c92e 100644 --- a/CFMachPort.h +++ b/CFMachPort.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFMachPort.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFMACHPORT__) diff --git a/CFMessagePort.c b/CFMessagePort.c index f28a81f..385a7bc 100644 --- a/CFMessagePort.c +++ b/CFMessagePort.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFMessagePort.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -301,7 +301,7 @@ static const CFRuntimeClass __CFMessagePortClass = { __CFMessagePortCopyDescription }; -__private_extern__ void __CFMessagePortInitialize(void) { +CF_PRIVATE void __CFMessagePortInitialize(void) { __kCFMessagePortTypeID = _CFRuntimeRegisterClass(&__CFMessagePortClass); } @@ -879,7 +879,7 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef CFRunLoopRef currentRL = CFRunLoopGetCurrent(); CFRunLoopSourceRef source = NULL; CFDataRef reply = NULL; - int64_t termTSR; + uint64_t termTSR; uint32_t sendOpts = 0, sendTimeOut = 0; int32_t desiredReply; Boolean didRegister = false; @@ -953,10 +953,10 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef _CFMachPortInstallNotifyPort(currentRL, replyMode); termTSR = mach_absolute_time() + __CFTimeIntervalToTSR(rcvTimeout); for (;;) { - CFRunLoopRunInMode(replyMode, __CFTSRToTimeInterval(termTSR - mach_absolute_time()), true); + CFRunLoopRunInMode(replyMode, __CFTimeIntervalUntilTSR(termTSR), true); // warning: what, if anything, should be done if remote is now invalid? reply = CFDictionaryGetValue(remote->_replies, (void *)(uintptr_t)desiredReply); - if (NULL != reply || termTSR < (int64_t)mach_absolute_time()) { + if (NULL != reply || termTSR < mach_absolute_time()) { break; } if (!CFMessagePortIsValid(remote)) { @@ -990,6 +990,7 @@ static mach_port_t __CFMessagePortGetPort(void *info) { return ms->_port ? CFMachPortGetPort(ms->_port) : MACH_PORT_NULL; } + static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allocator, void *info) { CFMessagePortRef ms = info; mach_msg_base_t *msgp = msg; @@ -1015,6 +1016,7 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo } __CFMessagePortUnlock(ms); + int32_t byteslen = 0; Boolean invalidMagic = (MSGP_GET(msgp, magic) != MAGIC) && (CFSwapInt32(MSGP_GET(msgp, magic)) != MAGIC); diff --git a/CFMessagePort.h b/CFMessagePort.h index 4d8f9b7..6112e49 100644 --- a/CFMessagePort.h +++ b/CFMessagePort.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFMessagePort.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFMESSAGEPORT__) diff --git a/CFNumber.c b/CFNumber.c index 4ddbcc0..f945444 100644 --- a/CFNumber.c +++ b/CFNumber.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFNumber.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -60,7 +60,7 @@ static CFStringRef __CFBooleanCopyDescription(CFTypeRef cf) { return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{value = %s}"), cf, CFGetAllocator(cf), (boolean == kCFBooleanTrue) ? "true" : "false"); } -__private_extern__ CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { +CF_PRIVATE CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { CFBooleanRef boolean = (CFBooleanRef)cf; return (CFStringRef)CFRetain((boolean == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false")); } @@ -88,12 +88,10 @@ static const CFRuntimeClass __CFBooleanClass = { __CFBooleanCopyDescription }; -__private_extern__ void __CFBooleanInitialize(void) { +CF_PRIVATE void __CFBooleanInitialize(void) { __kCFBooleanTypeID = _CFRuntimeRegisterClass(&__CFBooleanClass); - _CFRuntimeSetInstanceTypeID(&__kCFBooleanTrue, __kCFBooleanTypeID); - __kCFBooleanTrue._base._cfisa = __CFISAForTypeID(__kCFBooleanTypeID); - _CFRuntimeSetInstanceTypeID(&__kCFBooleanFalse, __kCFBooleanTypeID); - __kCFBooleanFalse._base._cfisa = __CFISAForTypeID(__kCFBooleanTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanTrue, __kCFBooleanTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFBooleanFalse, __kCFBooleanTypeID); } CFTypeID CFBooleanGetTypeID(void) { @@ -129,7 +127,7 @@ struct __CFNumber_old { /* Only as many bytes as necessary are alloc static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2); static CFHashCode __CFNumberHash_old(CFTypeRef cf); static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf); -__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf); +CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf); static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions); static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr); static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number); @@ -425,14 +423,7 @@ static const struct { /* kCFNumberSInt128Type */ {kCFNumberSInt128Type, 0, 1, 4, 0}, }; -#define CF_IS_TAGGED_INT(OBJ) (CF_TAGGED_OBJ_TYPE(OBJ) == kCFTaggedObjectID_Integer) - CF_INLINE CFNumberType __CFNumberGetType(CFNumberRef num) { - if (CF_IS_TAGGED_INT(num)) { - uintptr_t type_bits = ((uintptr_t)num >> 6) & 0x3; // top 2 bits of low byte - const CFNumberType canonical_types[4] = {kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt64Type}; - return canonical_types[type_bits]; - } return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0); } @@ -464,12 +455,6 @@ static Boolean __CFNumberGetValue(CFNumberRef number, CFNumberType type, void *v type = __CFNumberTypeTable[type].canonicalType; CFNumberType ntype = __CFNumberGetType(number); const void *data = &(number->_pad); - intptr_t taggedInteger; - if (CF_IS_TAGGED_INT(number)) { - taggedInteger = (intptr_t)number; - taggedInteger = taggedInteger >> 8; - data = &taggedInteger; - } switch (type) { case kCFNumberSInt8Type: if (__CFNumberTypeTable[ntype].floatBit) { @@ -660,12 +645,6 @@ static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, v type = __CFNumberTypeTable[type].canonicalType; CFNumberType ntype = __CFNumberGetType(number); const void *data = &(number->_pad); - intptr_t taggedInteger; - if (CF_IS_TAGGED_INT(number)) { - taggedInteger = (intptr_t)number; - taggedInteger = taggedInteger >> 8; - data = &taggedInteger; - } switch (type) { case kCFNumberSInt8Type: if (__CFNumberTypeTable[ntype].floatBit) { @@ -897,7 +876,7 @@ static CFStringRef __CFNumberCreateFormattingDescriptionAsFloat64(CFAllocatorRef return CFStringCreateWithFormat(allocator, NULL, CFSTR("%.*g"), DBL_DIG + 2, d); } -__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) { +CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) { CFStringRef result = __CFNumberCreateFormattingDescriptionAsFloat64(kCFAllocatorSystemDefault, cf); #if OLD_CRAP_TOO CFNumberRef number = (CFNumberRef)cf; @@ -913,7 +892,7 @@ CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescri return result; } -__private_extern__ CFStringRef __CFNumberCreateFormattingDescription(CFAllocatorRef allocator, CFTypeRef cf, CFDictionaryRef formatOptions) { +CF_PRIVATE CFStringRef __CFNumberCreateFormattingDescription(CFAllocatorRef allocator, CFTypeRef cf, CFDictionaryRef formatOptions) { CFNumberRef number = (CFNumberRef)cf; CFNumberType type = __CFNumberGetType(number); if (__CFNumberTypeTable[type].floatBit) { @@ -939,7 +918,7 @@ static CFStringRef __CFNumberCopyFormattingDescription_new(CFTypeRef cf, CFDicti return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%s"), buffer); } -__private_extern__ CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { +CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { CFStringRef result = __CFNumberCopyFormattingDescription_new(cf, formatOptions); #if OLD_CRAP_TOO CFNumberRef number = (CFNumberRef)cf; @@ -1007,7 +986,6 @@ CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h } static CFTypeID __kCFNumberTypeID = _kCFRuntimeNotATypeID; -static void *__CFTaggedNumberClass = 0; enum { kCFNumberCachingEnabled = 0, @@ -1029,21 +1007,18 @@ static const CFRuntimeClass __CFNumberClass = { }; -__private_extern__ void __CFNumberInitialize(void) { +CF_PRIVATE void __CFNumberInitialize(void) { __kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass); - _CFRuntimeSetInstanceTypeID(&__kCFNumberNaN, __kCFNumberTypeID); - __kCFNumberNaN._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(&__kCFNumberNaN, __kCFNumberTypeID); __CFBitfieldSetValue(__kCFNumberNaN._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); __kCFNumberNaN._pad = BITSFORDOUBLENAN; - _CFRuntimeSetInstanceTypeID(& __kCFNumberNegativeInfinity, __kCFNumberTypeID); - __kCFNumberNegativeInfinity._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberNegativeInfinity, __kCFNumberTypeID); __CFBitfieldSetValue(__kCFNumberNegativeInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); __kCFNumberNegativeInfinity._pad = BITSFORDOUBLENEGINF; - _CFRuntimeSetInstanceTypeID(& __kCFNumberPositiveInfinity, __kCFNumberTypeID); - __kCFNumberPositiveInfinity._base._cfisa = __CFISAForTypeID(__kCFNumberTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberPositiveInfinity, __kCFNumberTypeID); __CFBitfieldSetValue(__kCFNumberPositiveInfinity._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type); __kCFNumberPositiveInfinity._pad = BITSFORDOUBLEPOSINF; @@ -1067,45 +1042,6 @@ CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType type, const vo if (!allocator) allocator = __CFGetDefaultAllocator(); - if (__CFTaggedNumberClass && _CFAllocatorIsSystemDefault(allocator) && (__CFNumberCaching != kCFNumberCachingFullyDisabled)) { - switch (__CFNumberTypeTable[type].canonicalType) { // canonicalized client-desired type - case kCFNumberSInt8Type: { - int8_t value = *(int8_t *)valuePtr; - return (CFNumberRef)((uintptr_t)((intptr_t)value << 8) | (0 << 6) | kCFTaggedObjectID_Integer); - } - case kCFNumberSInt16Type: { - int16_t value = *(int16_t *)valuePtr; - return (CFNumberRef)((uintptr_t)((intptr_t)value << 8) | (1 << 6) | kCFTaggedObjectID_Integer); - } - case kCFNumberSInt32Type: { - int32_t value = *(int32_t *)valuePtr; -#if !__LP64__ - // We don't bother allowing the min 24-bit integer -2^23 to also be fast-pathed; - // tell anybody that complains about that to go ... hang. - int32_t limit = (1L << 23); - if (value <= -limit || limit <= value) break; -#endif - uintptr_t ptr_val = ((uintptr_t)((intptr_t)value << 8) | (2 << 6) | kCFTaggedObjectID_Integer); - return (CFNumberRef)ptr_val; - } - case kCFNumberSInt64Type: { - int64_t value = *(int64_t *)valuePtr; -#if __LP64__ - // We don't bother allowing the min 56-bit integer -2^55 to also be fast-pathed; - // tell anybody that complains about that to go ... hang. - int64_t limit = (1L << 55); - if (value <= -limit || limit <= value) break; -#else - // We don't bother allowing the min 24-bit integer -2^23 to also be fast-pathed; - // tell anybody that complains about that to go ... hang. - int64_t limit = (1L << 23); - if (value <= -limit || limit <= value) break; -#endif - uintptr_t ptr_val = ((uintptr_t)((intptr_t)value << 8) | (3 << 6) | kCFTaggedObjectID_Integer); - return (CFNumberRef)ptr_val; - } - } - } // Look for cases where we can return a cached instance. // We only use cached objects if the allocator is the system @@ -1194,9 +1130,6 @@ CFLog(kCFLogLevelWarning, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDes CFNumberType CFNumberGetType(CFNumberRef number) { //printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number); - if (CF_IS_TAGGED_INT(number)) { - return __CFNumberGetType(number); - } CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType); __CFAssertIsNumber(number); CFNumberType type = __CFNumberGetType(number); @@ -1216,6 +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); __CFAssertIsNumber(number); return __CFNumberGetType(number); } @@ -1258,51 +1192,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); - if (CF_IS_TAGGED_INT(number)) { - __CFAssertIsValidNumberType(type); - uint8_t localMemory[128]; - if (!valuePtr) valuePtr = localMemory; - intptr_t taggedInteger = (intptr_t)number; - taggedInteger = taggedInteger >> 8; - switch (__CFNumberTypeTable[type].canonicalType) { // canonicalized client-desired type - case kCFNumberSInt8Type: -#if 0 - if (taggedInteger < INT8_MIN) { - *(int8_t *)valuePtr = INT8_MIN; - return false; - } - if (INT8_MAX < taggedInteger) { - *(int8_t *)valuePtr = INT8_MAX; - return false; - } -#endif - *(int8_t *)valuePtr = (int8_t)taggedInteger; - return true; - case kCFNumberSInt16Type: -#if 0 - if (taggedInteger < INT16_MIN) { - *(int16_t *)valuePtr = INT16_MIN; - return false; - } - if (INT16_MAX < taggedInteger) { - *(int16_t *)valuePtr = INT16_MAX; - return false; - } -#endif - *(int16_t *)valuePtr = (int16_t)taggedInteger; - return true; - case kCFNumberSInt32Type: - *(int32_t *)valuePtr = (int32_t)taggedInteger; - return true; -#if __LP64__ - case kCFNumberSInt64Type: - *(int64_t *)valuePtr = (int64_t)taggedInteger; - return true; -#endif - } - Boolean r = __CFNumberGetValueCompat(number, type, valuePtr); - return r; - } + CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, Boolean, (NSNumber *)number, _getValue:(void *)valuePtr forType:(CFNumberType)__CFNumberTypeTable[type].canonicalType); __CFAssertIsNumber(number); __CFAssertIsValidNumberType(type); @@ -1631,7 +1521,7 @@ static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf) { // This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well. -__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf) { +CF_PRIVATE CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf) { double d; CFNumberGetValue_old((struct __CFNumber_old *)cf, kCFNumberFloat64Type, &d); if (isnan(d)) { diff --git a/CFNumber.h b/CFNumber.h index 5cddcbb..2792e27 100644 --- a/CFNumber.h +++ b/CFNumber.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFNumber.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFNUMBER__) diff --git a/CFNumberFormatter.c b/CFNumberFormatter.c index 2a3fc8c..dbb63df 100644 --- a/CFNumberFormatter.c +++ b/CFNumberFormatter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFNumberFormatter.c - Copyright (c) 2002-2012, Apple Inc. All rights reserved. + Copyright (c) 2002-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -31,8 +31,7 @@ #include #include "CFInternal.h" #include "CFLocaleInternal.h" -#include -#include +#include "CFICULogging.h" #include #include @@ -55,6 +54,7 @@ struct __CFNumberFormatter { CFStringRef _zeroSym; Boolean _isLenient; Boolean _userSetMultiplier; + Boolean _usesCharacterDirection; }; static CFStringRef __CFNumberFormatterCopyDescription(CFTypeRef cf) { @@ -64,7 +64,7 @@ static CFStringRef __CFNumberFormatterCopyDescription(CFTypeRef cf) { static void __CFNumberFormatterDeallocate(CFTypeRef cf) { CFNumberFormatterRef formatter = (CFNumberFormatterRef)cf; - if (formatter->_nf) unum_close(formatter->_nf); + if (formatter->_nf) __cficu_unum_close(formatter->_nf); if (formatter->_locale) CFRelease(formatter->_locale); if (formatter->_format) CFRelease(formatter->_format); if (formatter->_defformat) CFRelease(formatter->_defformat); @@ -115,6 +115,7 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR memory->_zeroSym = NULL; memory->_isLenient = false; memory->_userSetMultiplier = false; + memory->_usesCharacterDirection = false; if (NULL == locale) locale = CFLocaleGetSystem(); memory->_style = style; uint32_t ustyle; @@ -144,7 +145,7 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR return NULL; } UErrorCode status = U_ZERO_ERROR; - memory->_nf = unum_open((UNumberFormatStyle)ustyle, NULL, 0, cstr, NULL, &status); + memory->_nf = __cficu_unum_open((UNumberFormatStyle)ustyle, NULL, 0, cstr, NULL, &status); CFAssert2(memory->_nf, __kCFLogAssertion, "%s(): error (%d) creating number formatter", __PRETTY_FUNCTION__, status); if (NULL == memory->_nf) { CFRelease(memory); @@ -154,16 +155,16 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR if (kCFNumberFormatterNoStyle == style) { status = U_ZERO_ERROR; ubuff[0] = '#'; ubuff[1] = ';'; ubuff[2] = '#'; - unum_applyPattern(memory->_nf, false, ubuff, 3, NULL, &status); - unum_setAttribute(memory->_nf, UNUM_MAX_INTEGER_DIGITS, 42); - unum_setAttribute(memory->_nf, UNUM_MAX_FRACTION_DIGITS, 0); + __cficu_unum_applyPattern(memory->_nf, false, ubuff, 3, NULL, &status); + __cficu_unum_setAttribute(memory->_nf, UNUM_MAX_INTEGER_DIGITS, 42); + __cficu_unum_setAttribute(memory->_nf, UNUM_MAX_FRACTION_DIGITS, 0); } memory->_locale = locale ? CFLocaleCreateCopy(allocator, locale) : CFLocaleGetSystem(); __CFNumberFormatterCustomize(memory); if (kCFNumberFormatterSpellOutStyle != memory->_style && kCFNumberFormatterOrdinalStyle != memory->_style && kCFNumberFormatterDurationStyle != memory->_style) { UChar ubuffer[BUFFER_SIZE]; status = U_ZERO_ERROR; - int32_t ret = unum_toPattern(memory->_nf, false, ubuffer, BUFFER_SIZE, &status); + int32_t ret = __cficu_unum_toPattern(memory->_nf, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && ret <= BUFFER_SIZE) { memory->_format = CFStringCreateWithCharacters(allocator, (const UniChar *)ubuffer, ret); } @@ -171,13 +172,13 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR memory->_defformat = memory->_format ? (CFStringRef)CFRetain(memory->_format) : NULL; memory->_compformat = memory->_format ? __CFNumberFormatterCreateCompressedString(memory->_format, true, NULL) : NULL; if (kCFNumberFormatterSpellOutStyle != memory->_style && kCFNumberFormatterOrdinalStyle != memory->_style && kCFNumberFormatterDurationStyle != memory->_style) { - int32_t n = unum_getAttribute(memory->_nf, UNUM_MULTIPLIER); + int32_t n = __cficu_unum_getAttribute(memory->_nf, UNUM_MULTIPLIER); if (1 != n) { memory->_multiplier = CFNumberCreate(allocator, kCFNumberSInt32Type, &n); - unum_setAttribute(memory->_nf, UNUM_MULTIPLIER, 1); + __cficu_unum_setAttribute(memory->_nf, UNUM_MULTIPLIER, 1); } } - unum_setAttribute(memory->_nf, UNUM_LENIENT_PARSE, 0); + __cficu_unum_setAttribute(memory->_nf, UNUM_LENIENT_PARSE, 0); return (CFNumberFormatterRef)memory; } @@ -225,15 +226,15 @@ static void __substituteFormatStringFromPrefsNF(CFNumberFormatterRef formatter) if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer; } UErrorCode status = U_ZERO_ERROR; - UNumberFormat *nf = unum_open((UNumberFormatStyle)icustyle, NULL, 0, cstr, NULL, &status); + UNumberFormat *nf = __cficu_unum_open((UNumberFormatStyle)icustyle, NULL, 0, cstr, NULL, &status); if (NULL != nf) { UChar ubuffer[BUFFER_SIZE]; status = U_ZERO_ERROR; - int32_t number_len = unum_toPattern(nf, false, ubuffer, BUFFER_SIZE, &status); + int32_t number_len = __cficu_unum_toPattern(nf, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && number_len <= BUFFER_SIZE) { CFStringRef numberString = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, number_len); status = U_ZERO_ERROR; - int32_t formatter_len = unum_toPattern(formatter->_nf, false, ubuffer, BUFFER_SIZE, &status); + int32_t formatter_len = __cficu_unum_toPattern(formatter->_nf, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && formatter_len <= BUFFER_SIZE) { CFMutableStringRef formatString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); CFStringAppendCharacters(formatString, (const UniChar *)ubuffer, formatter_len); @@ -247,7 +248,7 @@ static void __substituteFormatStringFromPrefsNF(CFNumberFormatterRef formatter) } CFRelease(numberString); } - unum_close(nf); + __cficu_unum_close(nf); } } } @@ -301,7 +302,7 @@ static void __CFNumberFormatterApplySymbolPrefs(const void *key, const void *val item_ustr = item_buffer; } UErrorCode status = U_ZERO_ERROR; - unum_setSymbol(formatter->_nf, sym, item_ustr, item_cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, sym, item_ustr, item_cnt, &status); } } @@ -318,21 +319,21 @@ static UErrorCode __CFNumberFormatterApplyPattern(CFNumberFormatterRef formatter ustr = ubuffer; } UErrorCode status = U_ZERO_ERROR; - unum_applyPattern(formatter->_nf, false, ustr, cnt, NULL, &status); + __cficu_unum_applyPattern(formatter->_nf, false, ustr, cnt, NULL, &status); - // unum_applyPattern() may have magically changed other attributes based on + // __cficu_unum_applyPattern() may have magically changed other attributes based on // the contents of the format string; we simply expose that ICU behavior, except // for UNUM_MULTIPLIER, which we re-read and reset, like we did at initialization // time though any user-set multiplier state takes precedence. if (formatter->_userSetMultiplier) { - unum_setAttribute(formatter->_nf, UNUM_MULTIPLIER, 1); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MULTIPLIER, 1); } else { if (formatter->_multiplier) CFRelease(formatter->_multiplier); formatter->_multiplier = NULL; - int32_t n = unum_getAttribute(formatter->_nf, UNUM_MULTIPLIER); + int32_t n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MULTIPLIER); if (1 != n) { formatter->_multiplier = CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MULTIPLIER, 1); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MULTIPLIER, 1); } } return status; @@ -365,7 +366,7 @@ CFStringRef CFNumberFormatterGetFormat(CFNumberFormatterRef formatter) { UChar ubuffer[BUFFER_SIZE]; CFStringRef newString = NULL; UErrorCode status = U_ZERO_ERROR; - int32_t ret = unum_toPattern(formatter->_nf, false, ubuffer, BUFFER_SIZE, &status); + int32_t ret = __cficu_unum_toPattern(formatter->_nf, false, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && ret <= BUFFER_SIZE) { newString = CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, ret); } @@ -397,7 +398,7 @@ void CFNumberFormatterSetFormat(CFNumberFormatterRef formatter, CFStringRef form if (U_SUCCESS(status)) { UChar ubuffer2[BUFFER_SIZE]; status = U_ZERO_ERROR; - int32_t ret = unum_toPattern(formatter->_nf, false, ubuffer2, BUFFER_SIZE, &status); + int32_t ret = __cficu_unum_toPattern(formatter->_nf, false, ubuffer2, BUFFER_SIZE, &status); if (U_SUCCESS(status) && ret <= BUFFER_SIZE) { if (formatter->_format) CFRelease(formatter->_format); formatter->_format = CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer2, ret); @@ -425,6 +426,7 @@ CFStringRef CFNumberFormatterCreateStringWithNumber(CFAllocatorRef allocator, CF __CFGenericValidateType(allocator, CFAllocatorGetTypeID()); __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID()); __CFGenericValidateType(number, CFNumberGetTypeID()); + // The values of CFNumbers with large unsigned 64-bit ints don't survive well through this CFNumberType type = CFNumberGetType(number); char buffer[64]; CFNumberGetValue(number, type, buffer); @@ -438,12 +440,12 @@ CFStringRef CFNumberFormatterCreateStringWithNumber(CFAllocatorRef allocator, CF value = (T)(value * multiplier); \ } \ status = U_ZERO_ERROR; \ - used = FUNC(formatter->_nf, value, ubuffer, cnt, NULL, &status); \ + used = FUNC(formatter->_nf, value, ubuffer + 1, cnt, NULL, &status); \ if (status == U_BUFFER_OVERFLOW_ERROR || cnt < used) { \ - cnt = used + 1; \ + cnt = used + 1 + 1; \ ustr = (UChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UChar) * cnt, 0); \ status = U_ZERO_ERROR; \ - used = FUNC(formatter->_nf, value, ustr, cnt, NULL, &status); \ + used = FUNC(formatter->_nf, value, ustr + 1, cnt, NULL, &status); \ } #define FORMAT_INT(T, FUN) \ @@ -454,15 +456,15 @@ CFStringRef CFNumberFormatterCreateStringWithNumber(CFAllocatorRef allocator, CF } \ _CFBigNum bignum; \ FUN(&bignum, value); \ - char buffer[BUFFER_SIZE]; \ + char buffer[BUFFER_SIZE + 1]; \ _CFBigNumToCString(&bignum, false, true, buffer, BUFFER_SIZE); \ status = U_ZERO_ERROR; \ - used = unum_formatDecimal(formatter->_nf, buffer, strlen(buffer), ubuffer, BUFFER_SIZE, NULL, &status); \ + used = __cficu_unum_formatDecimal(formatter->_nf, buffer, strlen(buffer), ubuffer + 1, BUFFER_SIZE, NULL, &status); \ if (status == U_BUFFER_OVERFLOW_ERROR || cnt < used) { \ - cnt = used + 1; \ + cnt = used + 1 + 1; \ ustr = (UChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UChar) * cnt, 0); \ status = U_ZERO_ERROR; \ - used = unum_formatDecimal(formatter->_nf, buffer, strlen(buffer), ustr, cnt, NULL, &status); \ + used = __cficu_unum_formatDecimal(formatter->_nf, buffer, strlen(buffer), ustr + 1, cnt, NULL, &status); \ } \ CFStringRef CFNumberFormatterCreateStringWithValue(CFAllocatorRef allocator, CFNumberFormatterRef formatter, CFNumberType numberType, const void *valuePtr) { @@ -470,13 +472,13 @@ CFStringRef CFNumberFormatterCreateStringWithValue(CFAllocatorRef allocator, CFN __CFGenericValidateType(allocator, CFAllocatorGetTypeID()); __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID()); GET_MULTIPLIER; - UChar *ustr = NULL, ubuffer[BUFFER_SIZE]; + UChar *ustr = NULL, ubuffer[BUFFER_SIZE + 1]; UErrorCode status = U_ZERO_ERROR; CFIndex used, cnt = BUFFER_SIZE; if (numberType == kCFNumberFloat64Type || numberType == kCFNumberDoubleType) { - FORMAT_FLT(double, unum_formatDouble) + FORMAT_FLT(double, __cficu_unum_formatDouble) } else if (numberType == kCFNumberFloat32Type || numberType == kCFNumberFloatType) { - FORMAT_FLT(float, unum_formatDouble) + FORMAT_FLT(float, __cficu_unum_formatDouble) } else if (numberType == kCFNumberSInt64Type || numberType == kCFNumberLongLongType) { FORMAT_INT(int64_t, _CFBigNumInitWithInt64) } else if (numberType == kCFNumberLongType || numberType == kCFNumberCFIndexType) { @@ -497,7 +499,16 @@ CFStringRef CFNumberFormatterCreateStringWithValue(CFAllocatorRef allocator, CFN } CFStringRef string = NULL; if (U_SUCCESS(status)) { - string = CFStringCreateWithCharacters(allocator, ustr ? (const UniChar *)ustr : (const UniChar *)ubuffer, used); + UniChar *bufferToUse = ustr ? (UniChar *)ustr : (UniChar *)ubuffer; + if (formatter->_usesCharacterDirection && CFLocaleGetLanguageCharacterDirection(CFLocaleGetIdentifier(formatter->_locale)) == kCFLocaleLanguageDirectionRightToLeft) { + // Insert Unicode RTL marker + bufferToUse[0] = 0x200F; + used++; + } else { + // Move past direction marker + bufferToUse++; + } + string = CFStringCreateWithCharacters(allocator, bufferToUse, used); } if (ustr) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ustr); return string; @@ -606,7 +617,7 @@ Boolean CFNumberFormatterGetValueFromString(CFNumberFormatterRef formatter, CFSt } else { range.length = CFStringGetLength(stringToParse); } - // unum_parse chokes on leading whitespace + // __cficu_unum_parse chokes on leading whitespace CFCharacterSetRef whitespace = CFCharacterSetGetPredefined(kCFCharacterSetWhitespace); while(range.length > 0 && CFCharacterSetIsCharacterMember(whitespace, CFStringGetCharacterAtIndex(stringToParse, range.location))) { range.location++; @@ -644,10 +655,10 @@ Boolean CFNumberFormatterGetValueFromString(CFNumberFormatterRef formatter, CFSt case kCFNumberSInt32Type: case kCFNumberIntType: case kCFNumberLongType: case kCFNumberCFIndexType: case kCFNumberSInt64Type: case kCFNumberLongLongType: - unum_setAttribute(formatter->_nf, UNUM_PARSE_INT_ONLY, 1); // ignored by ICU for rule-based formatters + __cficu_unum_setAttribute(formatter->_nf, UNUM_PARSE_INT_ONLY, 1); // ignored by ICU for rule-based formatters break; default: - unum_setAttribute(formatter->_nf, UNUM_PARSE_INT_ONLY, 0); // ignored by ICU for rule-based formatters + __cficu_unum_setAttribute(formatter->_nf, UNUM_PARSE_INT_ONLY, 0); // ignored by ICU for rule-based formatters integerOnly = 0; break; } @@ -660,7 +671,7 @@ Boolean CFNumberFormatterGetValueFromString(CFNumberFormatterRef formatter, CFSt } else { char buffer[1024]; memset(buffer, 0, sizeof(buffer)); - int32_t len = unum_parseDecimal(formatter->_nf, ustr, range.length, &dpos, buffer, sizeof(buffer), &status); + int32_t len = __cficu_unum_parseDecimal(formatter->_nf, ustr, range.length, &dpos, buffer, sizeof(buffer), &status); if (!U_FAILURE(status) && 0 < len && integerOnly) { char *endptr = NULL; errno = 0; @@ -766,37 +777,37 @@ void CFNumberFormatterSetProperty(CFNumberFormatterRef formatter, CFStringRef ke cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setTextAttribute(formatter->_nf, UNUM_CURRENCY_CODE, ubuffer, cnt, &status); + __cficu_unum_setTextAttribute(formatter->_nf, UNUM_CURRENCY_CODE, ubuffer, cnt, &status); } else if (kCFNumberFormatterDecimalSeparatorKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_DECIMAL_SEPARATOR_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_DECIMAL_SEPARATOR_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterCurrencyDecimalSeparatorKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_MONETARY_SEPARATOR_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_MONETARY_SEPARATOR_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterAlwaysShowDecimalSeparatorKey == key) { __CFGenericValidateType(value, CFBooleanGetTypeID()); - unum_setAttribute(formatter->_nf, UNUM_DECIMAL_ALWAYS_SHOWN, (kCFBooleanTrue == value)); + __cficu_unum_setAttribute(formatter->_nf, UNUM_DECIMAL_ALWAYS_SHOWN, (kCFBooleanTrue == value)); } else if (kCFNumberFormatterGroupingSeparatorKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_GROUPING_SEPARATOR_SYMBOL, (const UChar *)ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_GROUPING_SEPARATOR_SYMBOL, (const UChar *)ubuffer, cnt, &status); } else if (kCFNumberFormatterUseGroupingSeparatorKey == key) { __CFGenericValidateType(value, CFBooleanGetTypeID()); - unum_setAttribute(formatter->_nf, UNUM_GROUPING_USED, (kCFBooleanTrue == value)); + __cficu_unum_setAttribute(formatter->_nf, UNUM_GROUPING_USED, (kCFBooleanTrue == value)); } else if (kCFNumberFormatterPercentSymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_PERCENT_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_PERCENT_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterZeroSymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); CFStringRef old = formatter->_zeroSym; @@ -807,83 +818,83 @@ void CFNumberFormatterSetProperty(CFNumberFormatterRef formatter, CFStringRef ke cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_NAN_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_NAN_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterInfinitySymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_INFINITY_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_INFINITY_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterMinusSignKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_MINUS_SIGN_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_MINUS_SIGN_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterPlusSignKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_PLUS_SIGN_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_PLUS_SIGN_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterCurrencySymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_CURRENCY_SYMBOL, (const UChar *)ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_CURRENCY_SYMBOL, (const UChar *)ubuffer, cnt, &status); } else if (kCFNumberFormatterExponentSymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_EXPONENTIAL_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_EXPONENTIAL_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterMinIntegerDigitsKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MIN_INTEGER_DIGITS, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MIN_INTEGER_DIGITS, n); } else if (kCFNumberFormatterMaxIntegerDigitsKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MAX_INTEGER_DIGITS, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MAX_INTEGER_DIGITS, n); } else if (kCFNumberFormatterMinFractionDigitsKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MIN_FRACTION_DIGITS, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MIN_FRACTION_DIGITS, n); } else if (kCFNumberFormatterMaxFractionDigitsKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MAX_FRACTION_DIGITS, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MAX_FRACTION_DIGITS, n); } else if (kCFNumberFormatterGroupingSizeKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_GROUPING_SIZE, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_GROUPING_SIZE, n); } else if (kCFNumberFormatterSecondaryGroupingSizeKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_SECONDARY_GROUPING_SIZE, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_SECONDARY_GROUPING_SIZE, n); } else if (kCFNumberFormatterRoundingModeKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_ROUNDING_MODE, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_ROUNDING_MODE, n); } else if (kCFNumberFormatterRoundingIncrementKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberDoubleType, &d); - unum_setDoubleAttribute(formatter->_nf, UNUM_ROUNDING_INCREMENT, d); + __cficu_unum_setDoubleAttribute(formatter->_nf, UNUM_ROUNDING_INCREMENT, d); } else if (kCFNumberFormatterFormatWidthKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_FORMAT_WIDTH, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_FORMAT_WIDTH, n); } else if (kCFNumberFormatterPaddingPositionKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_PADDING_POSITION, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_PADDING_POSITION, n); } else if (kCFNumberFormatterPaddingCharacterKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setTextAttribute(formatter->_nf, UNUM_PADDING_CHARACTER, ubuffer, cnt, &status); + __cficu_unum_setTextAttribute(formatter->_nf, UNUM_PADDING_CHARACTER, ubuffer, cnt, &status); } else if (kCFNumberFormatterDefaultFormatKey == key) { // read-only attribute } else if (kCFNumberFormatterMultiplierKey == key) { @@ -897,65 +908,68 @@ void CFNumberFormatterSetProperty(CFNumberFormatterRef formatter, CFStringRef ke cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setTextAttribute(formatter->_nf, UNUM_POSITIVE_PREFIX, ubuffer, cnt, &status); + __cficu_unum_setTextAttribute(formatter->_nf, UNUM_POSITIVE_PREFIX, ubuffer, cnt, &status); } else if (kCFNumberFormatterPositiveSuffixKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setTextAttribute(formatter->_nf, UNUM_POSITIVE_SUFFIX, (const UChar *)ubuffer, cnt, &status); + __cficu_unum_setTextAttribute(formatter->_nf, UNUM_POSITIVE_SUFFIX, (const UChar *)ubuffer, cnt, &status); } else if (kCFNumberFormatterNegativePrefixKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setTextAttribute(formatter->_nf, UNUM_NEGATIVE_PREFIX, ubuffer, cnt, &status); + __cficu_unum_setTextAttribute(formatter->_nf, UNUM_NEGATIVE_PREFIX, ubuffer, cnt, &status); } else if (kCFNumberFormatterNegativeSuffixKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setTextAttribute(formatter->_nf, UNUM_NEGATIVE_SUFFIX, (const UChar *)ubuffer, cnt, &status); + __cficu_unum_setTextAttribute(formatter->_nf, UNUM_NEGATIVE_SUFFIX, (const UChar *)ubuffer, cnt, &status); } else if (kCFNumberFormatterPerMillSymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_PERMILL_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_PERMILL_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterInternationalCurrencySymbolKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_INTL_CURRENCY_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_INTL_CURRENCY_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterCurrencyGroupingSeparatorKey == key) { __CFGenericValidateType(value, CFStringGetTypeID()); cnt = CFStringGetLength((CFStringRef)value); if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE; CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer); - unum_setSymbol(formatter->_nf, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, ubuffer, cnt, &status); + __cficu_unum_setSymbol(formatter->_nf, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, ubuffer, cnt, &status); } else if (kCFNumberFormatterIsLenientKey == key) { __CFGenericValidateType(value, CFBooleanGetTypeID()); formatter->_isLenient = (kCFBooleanTrue == value); - unum_setAttribute(formatter->_nf, UNUM_LENIENT_PARSE, (kCFBooleanTrue == value)); + __cficu_unum_setAttribute(formatter->_nf, UNUM_LENIENT_PARSE, (kCFBooleanTrue == value)); } else if (kCFNumberFormatterUseSignificantDigitsKey == key) { __CFGenericValidateType(value, CFBooleanGetTypeID()); - unum_setAttribute(formatter->_nf, UNUM_SIGNIFICANT_DIGITS_USED, (kCFBooleanTrue == value)); + __cficu_unum_setAttribute(formatter->_nf, UNUM_SIGNIFICANT_DIGITS_USED, (kCFBooleanTrue == value)); } else if (kCFNumberFormatterMinSignificantDigitsKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MIN_SIGNIFICANT_DIGITS, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MIN_SIGNIFICANT_DIGITS, n); } else if (kCFNumberFormatterMaxSignificantDigitsKey == key) { __CFGenericValidateType(value, CFNumberGetTypeID()); CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n); - unum_setAttribute(formatter->_nf, UNUM_MAX_SIGNIFICANT_DIGITS, n); + __cficu_unum_setAttribute(formatter->_nf, UNUM_MAX_SIGNIFICANT_DIGITS, n); + } else if (kCFNumberFormatterUsesCharacterDirectionKey == key) { + __CFGenericValidateType(value, CFBooleanGetTypeID()); + formatter->_usesCharacterDirection = value == kCFBooleanTrue; } else { CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key); } if (_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard)) { // do a dummy call to CFNumberFormatterGetFormat() after changing an attribute because // ICU sometimes changes the pattern due to a property change, and we need to poke - // unum_toPattern() and also update our own variables + // __cficu_unum_toPattern() and also update our own variables CFNumberFormatterGetFormat(formatter); } } @@ -973,7 +987,7 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString if (kCFNumberFormatterOrdinalStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return NULL; if (kCFNumberFormatterDurationStyle == formatter->_style && kCFNumberFormatterIsLenientKey != key) return NULL; if (kCFNumberFormatterCurrencyCodeKey == key) { - cnt = unum_getTextAttribute(formatter->_nf, UNUM_CURRENCY_CODE, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getTextAttribute(formatter->_nf, UNUM_CURRENCY_CODE, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt == 0) { CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale); char buffer[BUFFER_SIZE]; @@ -985,129 +999,129 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString return NULL; } UErrorCode status = U_ZERO_ERROR; - UNumberFormat *nf = unum_open(UNUM_CURRENCY, NULL, 0, cstr, NULL, &status); + UNumberFormat *nf = __cficu_unum_open(UNUM_CURRENCY, NULL, 0, cstr, NULL, &status); if (NULL != nf) { - cnt = unum_getTextAttribute(nf, UNUM_CURRENCY_CODE, ubuffer, BUFFER_SIZE, &status); - unum_close(nf); + cnt = __cficu_unum_getTextAttribute(nf, UNUM_CURRENCY_CODE, ubuffer, BUFFER_SIZE, &status); + __cficu_unum_close(nf); } } if (U_SUCCESS(status) && 0 < cnt && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterDecimalSeparatorKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_DECIMAL_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_DECIMAL_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterCurrencyDecimalSeparatorKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_MONETARY_SEPARATOR_SYMBOL, (UChar *)ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_MONETARY_SEPARATOR_SYMBOL, (UChar *)ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterAlwaysShowDecimalSeparatorKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_DECIMAL_ALWAYS_SHOWN); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_DECIMAL_ALWAYS_SHOWN); if (1) { return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse); } } else if (kCFNumberFormatterGroupingSeparatorKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_GROUPING_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_GROUPING_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterUseGroupingSeparatorKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_GROUPING_USED); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_GROUPING_USED); if (1) { return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse); } } else if (kCFNumberFormatterPercentSymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_PERCENT_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_PERCENT_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterZeroSymbolKey == key) { return formatter->_zeroSym ? CFRetain(formatter->_zeroSym) : NULL; } else if (kCFNumberFormatterNaNSymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_NAN_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_NAN_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterInfinitySymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_INFINITY_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_INFINITY_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterMinusSignKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_MINUS_SIGN_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_MINUS_SIGN_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterPlusSignKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_PLUS_SIGN_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_PLUS_SIGN_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterCurrencySymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_CURRENCY_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_CURRENCY_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterExponentSymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_EXPONENTIAL_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_EXPONENTIAL_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterMinIntegerDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_MIN_INTEGER_DIGITS); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MIN_INTEGER_DIGITS); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterMaxIntegerDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_MAX_INTEGER_DIGITS); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MAX_INTEGER_DIGITS); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterMinFractionDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_MIN_FRACTION_DIGITS); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MIN_FRACTION_DIGITS); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterMaxFractionDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_MAX_FRACTION_DIGITS); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MAX_FRACTION_DIGITS); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterGroupingSizeKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_GROUPING_SIZE); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_GROUPING_SIZE); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterSecondaryGroupingSizeKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_SECONDARY_GROUPING_SIZE); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_SECONDARY_GROUPING_SIZE); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterRoundingModeKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_ROUNDING_MODE); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_ROUNDING_MODE); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterRoundingIncrementKey == key) { - d = unum_getDoubleAttribute(formatter->_nf, UNUM_ROUNDING_INCREMENT); + d = __cficu_unum_getDoubleAttribute(formatter->_nf, UNUM_ROUNDING_INCREMENT); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberDoubleType, &d); } } else if (kCFNumberFormatterFormatWidthKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_FORMAT_WIDTH); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_FORMAT_WIDTH); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterPaddingPositionKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_PADDING_POSITION); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_PADDING_POSITION); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterPaddingCharacterKey == key) { - cnt = unum_getTextAttribute(formatter->_nf, UNUM_PADDING_CHARACTER, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getTextAttribute(formatter->_nf, UNUM_PADDING_CHARACTER, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } @@ -1116,55 +1130,55 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString } else if (kCFNumberFormatterMultiplierKey == key) { return formatter->_multiplier ? CFRetain(formatter->_multiplier) : NULL; } else if (kCFNumberFormatterPositivePrefixKey == key) { - cnt = unum_getTextAttribute(formatter->_nf, UNUM_POSITIVE_PREFIX, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getTextAttribute(formatter->_nf, UNUM_POSITIVE_PREFIX, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterPositiveSuffixKey == key) { - cnt = unum_getTextAttribute(formatter->_nf, UNUM_POSITIVE_SUFFIX, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getTextAttribute(formatter->_nf, UNUM_POSITIVE_SUFFIX, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterNegativePrefixKey == key) { - cnt = unum_getTextAttribute(formatter->_nf, UNUM_NEGATIVE_PREFIX, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getTextAttribute(formatter->_nf, UNUM_NEGATIVE_PREFIX, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterNegativeSuffixKey == key) { - cnt = unum_getTextAttribute(formatter->_nf, UNUM_NEGATIVE_SUFFIX, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getTextAttribute(formatter->_nf, UNUM_NEGATIVE_SUFFIX, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterPerMillSymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_PERMILL_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_PERMILL_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterInternationalCurrencySymbolKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_INTL_CURRENCY_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_INTL_CURRENCY_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterCurrencyGroupingSeparatorKey == key) { - cnt = unum_getSymbol(formatter->_nf, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status); + cnt = __cficu_unum_getSymbol(formatter->_nf, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status); if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt); } } else if (kCFNumberFormatterIsLenientKey == key) { - // unum_getAttribute(, UNUM_LENIENT_PARSE) is undefined. + // __cficu_unum_getAttribute(, UNUM_LENIENT_PARSE) is undefined. return CFRetain(formatter->_isLenient ? kCFBooleanTrue : kCFBooleanFalse); } else if (kCFNumberFormatterUseSignificantDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_SIGNIFICANT_DIGITS_USED); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_SIGNIFICANT_DIGITS_USED); if (1) { return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse); } } else if (kCFNumberFormatterMinSignificantDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_MIN_SIGNIFICANT_DIGITS); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MIN_SIGNIFICANT_DIGITS); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } } else if (kCFNumberFormatterMaxSignificantDigitsKey == key) { - n = unum_getAttribute(formatter->_nf, UNUM_MAX_SIGNIFICANT_DIGITS); + n = __cficu_unum_getAttribute(formatter->_nf, UNUM_MAX_SIGNIFICANT_DIGITS); if (1) { return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n); } @@ -1182,8 +1196,8 @@ Boolean CFNumberFormatterGetDecimalInfoForCurrencyCode(CFStringRef currencyCode, CFStringGetCharacters(currencyCode, CFRangeMake(0, 3), (UniChar *)ubuffer); ubuffer[3] = 0; UErrorCode icuStatus = U_ZERO_ERROR; - if (defaultFractionDigits) *defaultFractionDigits = ucurr_getDefaultFractionDigits(ubuffer, &icuStatus); - if (roundingIncrement) *roundingIncrement = ucurr_getRoundingIncrement(ubuffer, &icuStatus); + if (defaultFractionDigits) *defaultFractionDigits = __cficu_ucurr_getDefaultFractionDigits(ubuffer, &icuStatus); + if (roundingIncrement) *roundingIncrement = __cficu_ucurr_getRoundingIncrement(ubuffer, &icuStatus); if (U_FAILURE(icuStatus)) return false; return (!defaultFractionDigits || 0 <= *defaultFractionDigits) && (!roundingIncrement || 0.0 <= *roundingIncrement); diff --git a/CFNumberFormatter.h b/CFNumberFormatter.h index 9c17102..f9eded1 100644 --- a/CFNumberFormatter.h +++ b/CFNumberFormatter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFNumberFormatter.h - Copyright (c) 2003-2012, Apple Inc. All rights reserved. + Copyright (c) 2003-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFNUMBERFORMATTER__) diff --git a/CFOldStylePList.c b/CFOldStylePList.c index 3881788..1882efa 100644 --- a/CFOldStylePList.c +++ b/CFOldStylePList.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFOldStylePList.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -42,10 +42,10 @@ // CF_INLINE void __CFPListRelease(CFTypeRef cf, CFAllocatorRef allocator) { - if (cf && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(cf); + if (cf && !(0)) CFRelease(cf); } -__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...); +CF_PRIVATE CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...); typedef struct { const UniChar *begin; @@ -171,7 +171,7 @@ static UniChar getSlashedChar(_CFStringsFileParseInfo *pInfo) { } static CFStringRef _uniqueStringForCharacters(_CFStringsFileParseInfo *pInfo, const UniChar *base, CFIndex length) { - if (0 == length) return !_CFAllocatorIsGCRefZero(pInfo->allocator) ? (CFStringRef)CFRetain(CFSTR("")) : CFSTR(""); + if (0 == length) return !(0) ? (CFStringRef)CFRetain(CFSTR("")) : CFSTR(""); // This is to avoid having to promote the buffers of all the strings compared against // during the set probe; if a Unicode string is passed in, that's what happens. CFStringRef stringToUnique = NULL; @@ -198,7 +198,7 @@ static CFStringRef _uniqueStringForCharacters(_CFStringsFileParseInfo *pInfo, co uniqued = stringToUnique; } __CFPListRelease(stringToUnique, pInfo->allocator); - if (uniqued && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(uniqued); + if (uniqued && !(0)) CFRetain(uniqued); return uniqued; } @@ -209,7 +209,7 @@ static CFStringRef _uniqueStringForString(_CFStringsFileParseInfo *pInfo, CFStri CFSetAddValue(pInfo->stringSet, uniqued); __CFTypeCollectionRelease(pInfo->allocator, uniqued); } - if (uniqued && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(uniqued); + if (uniqued && !(0)) CFRetain(uniqued); return uniqued; } @@ -532,7 +532,7 @@ static CFTypeRef parsePlistObject(_CFStringsFileParseInfo *pInfo, bool requireOb // CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError, Boolean allowNewTypes, CFPropertyListFormat *format, CFSetRef keyPaths -__private_extern__ CFTypeRef __CFParseOldStylePropertyListOrStringsFile(CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError,CFPropertyListFormat *format) { +CF_PRIVATE CFTypeRef __CFCreateOldStylePropertyListOrStringsFile(CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError,CFPropertyListFormat *format) { // Convert the string to UTF16 for parsing old-style if (originalString) { @@ -622,8 +622,8 @@ __private_extern__ CFTypeRef __CFParseOldStylePropertyListOrStringsFile(CFAlloca if (result && format) *format = kCFPropertyListOpenStepFormat; - if (createdBuffer && !_CFAllocatorIsGCRefZero(allocator)) CFAllocatorDeallocate(allocator, buf); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(stringsPInfo.stringSet); + if (createdBuffer && !(0)) CFAllocatorDeallocate(allocator, buf); + CFRelease(stringsPInfo.stringSet); CFRelease(originalString); return result; } diff --git a/CFPlatform.c b/CFPlatform.c index 7d51cfa..aca99b2 100644 --- a/CFPlatform.c +++ b/CFPlatform.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlatform.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -37,6 +37,7 @@ #include #include #include + #include #endif #if DEPLOYMENT_TARGET_WINDOWS @@ -63,14 +64,14 @@ int _CFArgc(void) { return *_NSGetArgc(); } #endif -__private_extern__ Boolean _CFGetCurrentDirectory(char *path, int maxlen) { +CF_PRIVATE Boolean _CFGetCurrentDirectory(char *path, int maxlen) { return getcwd(path, maxlen) != NULL; } #if DEPLOYMENT_TARGET_WINDOWS // Returns the path to the CF DLL, which we can then use to find resources like char sets bool bDllPathCached = false; -__private_extern__ const wchar_t *_CFDLLPath(void) { +CF_PRIVATE const wchar_t *_CFDLLPath(void) { static wchar_t cachedPath[MAX_PATH+1]; if (!bDllPathCached) { @@ -190,7 +191,7 @@ const char *_CFProcessPath(void) { } #endif -__private_extern__ CFStringRef _CFProcessNameString(void) { +CF_PRIVATE CFStringRef _CFProcessNameString(void) { static CFStringRef __CFProcessNameString = NULL; if (!__CFProcessNameString) { const char *processName = *_CFGetProgname(); @@ -231,7 +232,7 @@ static CFURLRef _CFCopyHomeDirURLForUser(struct passwd *upwd, bool fallBackToHom #define CFMaxHostNameLength 256 #define CFMaxHostNameSize (CFMaxHostNameLength+1) -__private_extern__ CFStringRef _CFStringCreateHostName(void) { +CF_PRIVATE CFStringRef _CFStringCreateHostName(void) { char myName[CFMaxHostNameSize]; // return @"" instead of nil a la CFUserName() and Ali Ozer @@ -510,7 +511,7 @@ CF_EXPORT int _NS_pthread_main_np() { #define CF_TSD_MAX_SLOTS 70 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -#define CF_TSD_KEY 55 +static const unsigned long CF_TSD_KEY = __PTK_FRAMEWORK_COREFOUNDATION_KEY5; #endif // Windows and Linux, not sure how many times the destructor could get called; CF_TSD_MAX_DESTRUCTOR_CALLS could be 1 @@ -533,17 +534,17 @@ static void __CFTSDFinalize(void *arg); static DWORD __CFTSDIndexKey = 0xFFFFFFFF; // Called from CFRuntime's startup code, on Windows only -__private_extern__ void __CFTSDWindowsInitialize() { +CF_PRIVATE void __CFTSDWindowsInitialize() { __CFTSDIndexKey = TlsAlloc(); } // Called from CFRuntime's cleanup code, on Windows only -__private_extern__ void __CFTSDWindowsCleanup() { +CF_PRIVATE void __CFTSDWindowsCleanup() { TlsFree(__CFTSDIndexKey); } // Called for each thread as it exits, on Windows only -__private_extern__ void __CFFinalizeWindowsThreadData() { +CF_PRIVATE void __CFFinalizeWindowsThreadData() { // Normally, this should call the finalizer several times to emulate the behavior of pthreads on Windows. However, a few bugs keep us from doing this: // REGRESSION(CF-610-CF-611): Crash closing Safari in BonjourDB destructor (Windows) // SyncUIHandler crashes after conflict is resolved and we do SyncNow @@ -559,7 +560,7 @@ __private_extern__ void __CFFinalizeWindowsThreadData() { static pthread_key_t __CFTSDIndexKey; // Called from CFRuntime's startup code, on Linux only -__private_extern__ void __CFTSDLinuxInitialize() { +CF_PRIVATE void __CFTSDLinuxInitialize() { (void)pthread_key_create(&__CFTSDIndexKey, __CFTSDFinalize); } @@ -567,7 +568,7 @@ __private_extern__ void __CFTSDLinuxInitialize() { static void __CFTSDSetSpecific(void *arg) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - pthread_setspecific(CF_TSD_KEY, arg); + _pthread_setspecific_direct(CF_TSD_KEY, arg); #elif DEPLOYMENT_TARGET_LINUX pthread_setspecific(__CFTSDIndexKey, arg); #elif DEPLOYMENT_TARGET_WINDOWS @@ -577,7 +578,7 @@ static void __CFTSDSetSpecific(void *arg) { static void *__CFTSDGetSpecific() { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - return pthread_getspecific(CF_TSD_KEY); + return _pthread_getspecific_direct(CF_TSD_KEY); #elif DEPLOYMENT_TARGET_LINUX return pthread_getspecific(__CFTSDIndexKey); #elif DEPLOYMENT_TARGET_WINDOWS @@ -1023,7 +1024,7 @@ struct timezone { int tz_dsttime; /* type of dst correction */ }; -__private_extern__ int _NS_gettimeofday(struct timeval *tv, struct timezone *tz) { +CF_PRIVATE int _NS_gettimeofday(struct timeval *tv, struct timezone *tz) { if (tv) { FILETIME ft; GetSystemTimeAsFileTime(&ft); @@ -1077,6 +1078,10 @@ bool OSAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatil return __sync_bool_compare_and_swap(theValue, oldValue, newValue); } +bool OSAtomicCompareAndSwap64Barrier(int64_t oldValue, int64_t newValue, volatile int64_t *theValue) { + return __sync_bool_compare_and_swap(theValue, oldValue, newValue); +} + int32_t OSAtomicDecrement32Barrier(volatile int32_t *dst) { return OSAtomicAdd32Barrier(-1, dst); @@ -1103,6 +1108,13 @@ void OSMemoryBarrier() { __sync_synchronize(); } +#include + +void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) { + struct Block_layout *layout = (struct Block_layout *)block; + pthread_once(predicate, (void (*)(void))layout->invoke); +} + #endif // DEPLOYMENT_TARGET_LINUX #pragma mark - @@ -1112,7 +1124,7 @@ void OSMemoryBarrier() { #include -__private_extern__ int asprintf(char **ret, const char *format, ...) { +CF_PRIVATE int asprintf(char **ret, const char *format, ...) { va_list args; size_t sz = 1024; *ret = (char *) malloc(sz * sizeof(char)); diff --git a/CFPlatformConverters.c b/CFPlatformConverters.c index b4b8d09..fc264d5 100644 --- a/CFPlatformConverters.c +++ b/CFPlatformConverters.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlatformConverters.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -59,7 +59,7 @@ static const CFStringEncodingConverter __CFPlatformBootstrap = { NULL /* toUnicodeFallback */, NULL /* toBytesPrecompose */, NULL, /* isValidCombiningChar */ }; -__private_extern__ const CFStringEncodingConverter *__CFStringEncodingGetExternalConverter(uint32_t encoding) { +CF_PRIVATE const CFStringEncodingConverter *__CFStringEncodingGetExternalConverter(uint32_t encoding) { // we prefer Text Encoding Converter ICU since it's more reliable if (__CFIsPlatformConverterAvailable(encoding)) { @@ -75,7 +75,7 @@ __private_extern__ const CFStringEncodingConverter *__CFStringEncodingGetExterna } #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -__private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { +CF_PRIVATE CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { return NULL; } @@ -101,7 +101,7 @@ static char CALLBACK __CFWin32EnumCodePageProc(LPTSTR string) { return true; } -__private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { +CF_PRIVATE CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { CFStringEncoding *encodings; EnumSystemCodePages((CODEPAGE_ENUMPROC)&__CFWin32EnumCodePageProc, CP_INSTALLED); @@ -117,10 +117,10 @@ __private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlat return encodings; } #else -__private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { return NULL; } +CF_PRIVATE CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { return NULL; } #endif -__private_extern__ CFIndex __CFStringEncodingPlatformUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) { +CF_PRIVATE CFIndex __CFStringEncodingPlatformUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) { #if DEPLOYMENT_TARGET_WINDOWS WORD dwFlags = 0; @@ -171,7 +171,7 @@ __private_extern__ CFIndex __CFStringEncodingPlatformUnicodeToBytes(uint32_t enc return kCFStringEncodingConverterUnavailable; } -__private_extern__ CFIndex __CFStringEncodingPlatformBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) { +CF_PRIVATE CFIndex __CFStringEncodingPlatformBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) { #if DEPLOYMENT_TARGET_WINDOWS WORD dwFlags = 0; @@ -216,12 +216,12 @@ __private_extern__ CFIndex __CFStringEncodingPlatformBytesToUnicode(uint32_t enc return kCFStringEncodingConverterUnavailable; } -__private_extern__ CFIndex __CFStringEncodingPlatformCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) { +CF_PRIVATE CFIndex __CFStringEncodingPlatformCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) { CFIndex usedCharLen; return (__CFStringEncodingPlatformBytesToUnicode(encoding, flags, bytes, numBytes, NULL, NULL, 0, &usedCharLen) == kCFStringEncodingConversionSuccess ? usedCharLen : 0); } -__private_extern__ CFIndex __CFStringEncodingPlatformByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars) { +CF_PRIVATE CFIndex __CFStringEncodingPlatformByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars) { CFIndex usedByteLen; return (__CFStringEncodingPlatformUnicodeToBytes(encoding, flags, characters, numChars, NULL, NULL, 0, &usedByteLen) == kCFStringEncodingConversionSuccess ? usedByteLen : 0); } diff --git a/CFPlugIn.c b/CFPlugIn.c index 1a28795..c1e7b85 100644 --- a/CFPlugIn.c +++ b/CFPlugIn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugIn.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -35,7 +35,7 @@ CONST_STRING_DECL(kCFPlugInUnloadFunctionKey, "CFPlugInUnloadFunction") CONST_STRING_DECL(kCFPlugInFactoriesKey, "CFPlugInFactories") CONST_STRING_DECL(kCFPlugInTypesKey, "CFPlugInTypes") -__private_extern__ void __CFPlugInInitialize(void) { +CF_PRIVATE void __CFPlugInInitialize(void) { } /* ===================== Finding factories and creating instances ===================== */ diff --git a/CFPlugIn.h b/CFPlugIn.h index d51e0be..c440e00 100644 --- a/CFPlugIn.h +++ b/CFPlugIn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugIn.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPLUGIN__) @@ -43,16 +43,11 @@ CF_EXTERN_C_BEGIN /* ================ Standard Info.plist keys for plugIns ================ */ -CF_EXPORT -const CFStringRef kCFPlugInDynamicRegistrationKey; -CF_EXPORT -const CFStringRef kCFPlugInDynamicRegisterFunctionKey; -CF_EXPORT -const CFStringRef kCFPlugInUnloadFunctionKey; -CF_EXPORT -const CFStringRef kCFPlugInFactoriesKey; -CF_EXPORT -const CFStringRef kCFPlugInTypesKey; +CF_EXPORT const CFStringRef kCFPlugInDynamicRegistrationKey; +CF_EXPORT const CFStringRef kCFPlugInDynamicRegisterFunctionKey; +CF_EXPORT const CFStringRef kCFPlugInUnloadFunctionKey; +CF_EXPORT const CFStringRef kCFPlugInFactoriesKey; +CF_EXPORT const CFStringRef kCFPlugInTypesKey; /* ================= Function prototypes for various callbacks ================= */ /* Function types that plugIn authors can implement for various purposes. */ @@ -63,15 +58,12 @@ typedef void *(*CFPlugInFactoryFunction)(CFAllocatorRef allocator, CFUUIDRef typ /* ================= Creating PlugIns ================= */ -CF_EXPORT -CFTypeID CFPlugInGetTypeID(void); +CF_EXPORT CFTypeID CFPlugInGetTypeID(void); -CF_EXPORT -CFPlugInRef CFPlugInCreate(CFAllocatorRef allocator, CFURLRef plugInURL); +CF_EXPORT CFPlugInRef CFPlugInCreate(CFAllocatorRef allocator, CFURLRef plugInURL); /* Might return an existing instance with the ref-count bumped. */ -CF_EXPORT -CFBundleRef CFPlugInGetBundle(CFPlugInRef plugIn); +CF_EXPORT CFBundleRef CFPlugInGetBundle(CFPlugInRef plugIn); /* ================= Controlling load on demand ================= */ /* For plugIns. */ @@ -79,56 +71,45 @@ CFBundleRef CFPlugInGetBundle(CFPlugInRef plugIn); /* PlugIns that do dynamic registration are not load on demand by default. */ /* A dynamic registration function can call CFPlugInSetLoadOnDemand(). */ -CF_EXPORT -void CFPlugInSetLoadOnDemand(CFPlugInRef plugIn, Boolean flag); +CF_EXPORT void CFPlugInSetLoadOnDemand(CFPlugInRef plugIn, Boolean flag); -CF_EXPORT -Boolean CFPlugInIsLoadOnDemand(CFPlugInRef plugIn); +CF_EXPORT Boolean CFPlugInIsLoadOnDemand(CFPlugInRef plugIn); /* ================= Finding factories and creating instances ================= */ /* For plugIn hosts. */ /* Functions for finding factories to create specific types and actually creating instances of a type. */ -CF_EXPORT -CFArrayRef CFPlugInFindFactoriesForPlugInType(CFUUIDRef typeUUID); - /* This function finds all the factories from any plugin for the given type. Returns an array that the caller must release. */ - -CF_EXPORT -CFArrayRef CFPlugInFindFactoriesForPlugInTypeInPlugIn(CFUUIDRef typeUUID, CFPlugInRef plugIn); - /* This function restricts the result to factories from the given plug-in that can create the given type. Returns an array that the caller must release. */ +/* This function finds all the factories from any plugin for the given type. Returns an array that the caller must release. */ +CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInType(CFUUIDRef typeUUID) CF_RETURNS_RETAINED; -CF_EXPORT -void *CFPlugInInstanceCreate(CFAllocatorRef allocator, CFUUIDRef factoryUUID, CFUUIDRef typeUUID); - /* This function returns the IUnknown interface for the new instance. */ + +/* This function restricts the result to factories from the given plug-in that can create the given type. Returns an array that the caller must release. */ +CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInTypeInPlugIn(CFUUIDRef typeUUID, CFPlugInRef plugIn) CF_RETURNS_RETAINED; + +/* This function returns the IUnknown interface for the new instance. */ +CF_EXPORT void *CFPlugInInstanceCreate(CFAllocatorRef allocator, CFUUIDRef factoryUUID, CFUUIDRef typeUUID); /* ================= Registering factories and types ================= */ /* For plugIn writers who must dynamically register things. */ /* Functions to register factory functions and to associate factories with types. */ -CF_EXPORT -Boolean CFPlugInRegisterFactoryFunction(CFUUIDRef factoryUUID, CFPlugInFactoryFunction func); +CF_EXPORT Boolean CFPlugInRegisterFactoryFunction(CFUUIDRef factoryUUID, CFPlugInFactoryFunction func); -CF_EXPORT -Boolean CFPlugInRegisterFactoryFunctionByName(CFUUIDRef factoryUUID, CFPlugInRef plugIn, CFStringRef functionName); +CF_EXPORT Boolean CFPlugInRegisterFactoryFunctionByName(CFUUIDRef factoryUUID, CFPlugInRef plugIn, CFStringRef functionName); -CF_EXPORT -Boolean CFPlugInUnregisterFactory(CFUUIDRef factoryUUID); +CF_EXPORT Boolean CFPlugInUnregisterFactory(CFUUIDRef factoryUUID); -CF_EXPORT -Boolean CFPlugInRegisterPlugInType(CFUUIDRef factoryUUID, CFUUIDRef typeUUID); +CF_EXPORT Boolean CFPlugInRegisterPlugInType(CFUUIDRef factoryUUID, CFUUIDRef typeUUID); -CF_EXPORT -Boolean CFPlugInUnregisterPlugInType(CFUUIDRef factoryUUID, CFUUIDRef typeUUID); +CF_EXPORT Boolean CFPlugInUnregisterPlugInType(CFUUIDRef factoryUUID, CFUUIDRef typeUUID); /* ================= Registering instances ================= */ /* When a new instance of a type is created, the instance is responsible for registering itself with the factory that created it and unregistering when it deallocates. */ /* This means that an instance must keep track of the CFUUIDRef of the factory that created it so it can unregister when it goes away. */ -CF_EXPORT -void CFPlugInAddInstanceForFactory(CFUUIDRef factoryID); +CF_EXPORT void CFPlugInAddInstanceForFactory(CFUUIDRef factoryID); -CF_EXPORT -void CFPlugInRemoveInstanceForFactory(CFUUIDRef factoryID); +CF_EXPORT void CFPlugInRemoveInstanceForFactory(CFUUIDRef factoryID); /* Obsolete API */ @@ -138,16 +119,16 @@ typedef struct __CFPlugInInstance *CFPlugInInstanceRef; typedef Boolean (*CFPlugInInstanceGetInterfaceFunction)(CFPlugInInstanceRef instance, CFStringRef interfaceName, void **ftbl); typedef void (*CFPlugInInstanceDeallocateInstanceDataFunction)(void *instanceData); -CF_EXPORT -Boolean CFPlugInInstanceGetInterfaceFunctionTable(CFPlugInInstanceRef instance, CFStringRef interfaceName, void **ftbl); -CF_EXPORT -CFStringRef CFPlugInInstanceGetFactoryName(CFPlugInInstanceRef instance); -CF_EXPORT -void *CFPlugInInstanceGetInstanceData(CFPlugInInstanceRef instance); -CF_EXPORT -CFTypeID CFPlugInInstanceGetTypeID(void); -CF_EXPORT -CFPlugInInstanceRef CFPlugInInstanceCreateWithInstanceDataSize(CFAllocatorRef allocator, CFIndex instanceDataSize, CFPlugInInstanceDeallocateInstanceDataFunction deallocateInstanceFunction, CFStringRef factoryName, CFPlugInInstanceGetInterfaceFunction getInterfaceFunction); +CF_EXPORT Boolean CFPlugInInstanceGetInterfaceFunctionTable(CFPlugInInstanceRef instance, CFStringRef interfaceName, void **ftbl); + +/* This function returns a retained object on 10.8 or later. */ +CF_EXPORT CFStringRef CFPlugInInstanceGetFactoryName(CFPlugInInstanceRef instance) CF_RETURNS_RETAINED; + +CF_EXPORT void *CFPlugInInstanceGetInstanceData(CFPlugInInstanceRef instance); + +CF_EXPORT CFTypeID CFPlugInInstanceGetTypeID(void); + +CF_EXPORT CFPlugInInstanceRef CFPlugInInstanceCreateWithInstanceDataSize(CFAllocatorRef allocator, CFIndex instanceDataSize, CFPlugInInstanceDeallocateInstanceDataFunction deallocateInstanceFunction, CFStringRef factoryName, CFPlugInInstanceGetInterfaceFunction getInterfaceFunction); CF_EXTERN_C_END diff --git a/CFPlugInCOM.h b/CFPlugInCOM.h index cc41e52..b06469e 100644 --- a/CFPlugInCOM.h +++ b/CFPlugInCOM.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugInCOM.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPLUGINCOM__) diff --git a/CFPlugIn_Factory.c b/CFPlugIn_Factory.c index b65a86a..82e59b4 100644 --- a/CFPlugIn_Factory.c +++ b/CFPlugIn_Factory.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugIn_Factory.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -61,7 +61,7 @@ static const CFRuntimeClass __CFPFactoryClass = { NULL, // debug desc }; -__private_extern__ void __CFPFactoryInitialize(void) { +CF_PRIVATE void __CFPFactoryInitialize(void) { __kCFPFactoryTypeID = _CFRuntimeRegisterClass(&__CFPFactoryClass); } @@ -104,7 +104,7 @@ static void _CFPFactoryRemoveFromTable(_CFPFactoryRef factory) { if (uuid) CFRelease(uuid); } -__private_extern__ _CFPFactoryRef _CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) { +CF_PRIVATE _CFPFactoryRef _CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) { _CFPFactoryRef result = NULL; __CFSpinLock(&CFPlugInGlobalDataLock); @@ -153,7 +153,7 @@ static _CFPFactoryRef _CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRe return factory; } -__private_extern__ _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) { +CF_PRIVATE _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) { _CFPFactoryRef factory = _CFPFactoryCommonCreate(allocator, factoryID); __CFSpinLock(&factory->_lock); @@ -165,7 +165,7 @@ __private_extern__ _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CF return factory; } -__private_extern__ _CFPFactoryRef _CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) { +CF_PRIVATE _CFPFactoryRef _CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) { _CFPFactoryRef factory = _CFPFactoryCommonCreate(allocator, factoryID); __CFSpinLock(&factory->_lock); @@ -178,7 +178,7 @@ __private_extern__ _CFPFactoryRef _CFPFactoryCreateByName(CFAllocatorRef allocat return factory; } -__private_extern__ CFUUIDRef _CFPFactoryCopyFactoryID(_CFPFactoryRef factory) { +CF_PRIVATE CFUUIDRef _CFPFactoryCopyFactoryID(_CFPFactoryRef factory) { __CFSpinLock(&factory->_lock); CFUUIDRef uuid = factory->_uuid; if (uuid) CFRetain(uuid); @@ -186,7 +186,7 @@ __private_extern__ CFUUIDRef _CFPFactoryCopyFactoryID(_CFPFactoryRef factory) { return uuid; } -__private_extern__ CFPlugInRef _CFPFactoryCopyPlugIn(_CFPFactoryRef factory) { +CF_PRIVATE CFPlugInRef _CFPFactoryCopyPlugIn(_CFPFactoryRef factory) { __CFSpinLock(&factory->_lock); CFPlugInRef result = factory->_plugIn; if (result) CFRetain(result); @@ -194,7 +194,7 @@ __private_extern__ CFPlugInRef _CFPFactoryCopyPlugIn(_CFPFactoryRef factory) { return result; } -__private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactoryRef factory, CFUUIDRef typeID) { +CF_PRIVATE void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactoryRef factory, CFUUIDRef typeID) { void *result = NULL; __CFSpinLock(&factory->_lock); @@ -219,14 +219,14 @@ __private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CF return result; } -__private_extern__ void _CFPFactoryDisable(_CFPFactoryRef factory) { +CF_PRIVATE void _CFPFactoryDisable(_CFPFactoryRef factory) { __CFSpinLock(&factory->_lock); factory->_enabled = false; __CFSpinUnlock(&factory->_lock); CFRelease(factory); } -__private_extern__ void _CFPFactoryFlushFunctionCache(_CFPFactoryRef 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); @@ -234,7 +234,7 @@ __private_extern__ void _CFPFactoryFlushFunctionCache(_CFPFactoryRef factory) { __CFSpinUnlock(&factory->_lock); } -__private_extern__ void _CFPFactoryAddType(_CFPFactoryRef factory, CFUUIDRef typeID) { +CF_PRIVATE void _CFPFactoryAddType(_CFPFactoryRef factory, CFUUIDRef typeID) { /* Add the factory to the type's array of factories */ __CFSpinLock(&factory->_lock); /* Add the type to the factory's type list */ @@ -255,7 +255,7 @@ __private_extern__ void _CFPFactoryAddType(_CFPFactoryRef factory, CFUUIDRef typ __CFSpinUnlock(&CFPlugInGlobalDataLock); } -__private_extern__ void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef typeID) { +CF_PRIVATE void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef typeID) { /* Remove it from the factory's type list */ SInt32 idx; @@ -279,7 +279,7 @@ __private_extern__ void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef __CFSpinUnlock(&CFPlugInGlobalDataLock); } -__private_extern__ Boolean _CFPFactorySupportsType(_CFPFactoryRef factory, CFUUIDRef typeID) { +CF_PRIVATE Boolean _CFPFactorySupportsType(_CFPFactoryRef factory, CFUUIDRef typeID) { SInt32 idx; __CFSpinLock(&factory->_lock); @@ -289,7 +289,7 @@ __private_extern__ Boolean _CFPFactorySupportsType(_CFPFactoryRef factory, CFUUI return (idx >= 0 ? true : false); } -__private_extern__ CFArrayRef _CFPFactoryFindCopyForType(CFUUIDRef typeID) { +CF_PRIVATE CFArrayRef _CFPFactoryFindCopyForType(CFUUIDRef typeID) { CFArrayRef result = NULL; __CFSpinLock(&CFPlugInGlobalDataLock); if (_factoriesByTypeID) { @@ -302,7 +302,7 @@ __private_extern__ CFArrayRef _CFPFactoryFindCopyForType(CFUUIDRef typeID) { } /* These methods are called by CFPlugInInstance when an instance is created or destroyed. If a factory's instance count goes to 0 and the factory has been disabled, the factory is destroyed. */ -__private_extern__ void _CFPFactoryAddInstance(_CFPFactoryRef factory) { +CF_PRIVATE void _CFPFactoryAddInstance(_CFPFactoryRef factory) { /* MF:!!! Assert that factory is enabled. */ CFRetain(factory); __CFSpinLock(&factory->_lock); @@ -315,7 +315,7 @@ __private_extern__ void _CFPFactoryAddInstance(_CFPFactoryRef factory) { } } -__private_extern__ void _CFPFactoryRemoveInstance(_CFPFactoryRef factory) { +CF_PRIVATE void _CFPFactoryRemoveInstance(_CFPFactoryRef factory) { __CFSpinLock(&factory->_lock); CFPlugInRef plugin = factory->_plugIn; if (plugin) CFRetain(plugin); diff --git a/CFPlugIn_Factory.h b/CFPlugIn_Factory.h index 2b4320a..8f94abf 100644 --- a/CFPlugIn_Factory.h +++ b/CFPlugIn_Factory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugIn_Factory.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPLUGIN_FACTORY__) diff --git a/CFPlugIn_Instance.c b/CFPlugIn_Instance.c index afc17eb..252b45a 100644 --- a/CFPlugIn_Instance.c +++ b/CFPlugIn_Instance.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugIn_Instance.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -79,7 +79,7 @@ static const CFRuntimeClass __CFPlugInInstanceClass = { __CFPlugInInstanceCopyDescription }; -__private_extern__ void __CFPlugInInstanceInitialize(void) { +CF_PRIVATE void __CFPlugInInstanceInitialize(void) { __kCFPlugInInstanceTypeID = _CFRuntimeRegisterClass(&__CFPlugInInstanceClass); } @@ -115,7 +115,8 @@ CF_EXPORT Boolean CFPlugInInstanceGetInterfaceFunctionTable(CFPlugInInstanceRef } CF_EXPORT CFStringRef CFPlugInInstanceGetFactoryName(CFPlugInInstanceRef instance) { - // This function leaks, but it's the only safe way to access the factory name + // This function leaks, but it's the only safe way to access the factory name (on 10.8 or later). + // On 10.9 we added the CF_RETURNS_RETAINED annotation to the header. CFUUIDRef factoryId = _CFPFactoryCopyFactoryID(instance->factory); return (CFStringRef)factoryId; } diff --git a/CFPlugIn_PlugIn.c b/CFPlugIn_PlugIn.c index c922f8c..6ba9a07 100644 --- a/CFPlugIn_PlugIn.c +++ b/CFPlugIn_PlugIn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPlugIn_PlugIn.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -66,7 +66,7 @@ static void _registerType(const void *key, const void *val, void *context) { if (typeID) CFRelease(typeID); } -__private_extern__ Boolean _CFBundleNeedsInitPlugIn(CFBundleRef bundle) { +CF_PRIVATE Boolean _CFBundleNeedsInitPlugIn(CFBundleRef bundle) { Boolean result = false; CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle), factoryDict; CFStringRef tempStr; @@ -79,7 +79,7 @@ __private_extern__ Boolean _CFBundleNeedsInitPlugIn(CFBundleRef bundle) { return result; } -__private_extern__ void _CFBundleInitPlugIn(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleInitPlugIn(CFBundleRef bundle) { CFArrayCallBacks _pluginFactoryArrayCallbacks = {0, NULL, NULL, NULL, NULL}; Boolean doDynamicReg = false; CFDictionaryRef infoDict; @@ -119,7 +119,7 @@ __private_extern__ void _CFBundleInitPlugIn(CFBundleRef bundle) { } } -__private_extern__ void _CFBundlePlugInLoaded(CFBundleRef bundle) { +CF_PRIVATE void _CFBundlePlugInLoaded(CFBundleRef bundle) { CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle); CFStringRef tempStr; CFPlugInDynamicRegisterFunction func = NULL; @@ -148,7 +148,7 @@ __private_extern__ void _CFBundlePlugInLoaded(CFBundleRef bundle) { } } -__private_extern__ void _CFBundleDeallocatePlugIn(CFBundleRef bundle) { +CF_PRIVATE void _CFBundleDeallocatePlugIn(CFBundleRef bundle) { if (__CFBundleGetPlugInData(bundle)->_isPlugIn) { SInt32 c; @@ -196,7 +196,7 @@ Boolean CFPlugInIsLoadOnDemand(CFPlugInRef plugIn) { } } -__private_extern__ void _CFPlugInWillUnload(CFPlugInRef plugIn) { +CF_PRIVATE void _CFPlugInWillUnload(CFPlugInRef plugIn) { if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) { SInt32 c = CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories); /* First, flush all the function pointers that may be cached by our factories. */ @@ -204,7 +204,7 @@ __private_extern__ void _CFPlugInWillUnload(CFPlugInRef plugIn) { } } -__private_extern__ void _CFPlugInAddPlugInInstance(CFPlugInRef plugIn) { +CF_PRIVATE void _CFPlugInAddPlugInInstance(CFPlugInRef plugIn) { if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) { if (__CFBundleGetPlugInData(plugIn)->_instanceCount == 0 && __CFBundleGetPlugInData(plugIn)->_loadOnDemand) _CFBundleUnscheduleForUnloading(CFPlugInGetBundle(plugIn)); // Make sure we are not scheduled for unloading __CFBundleGetPlugInData(plugIn)->_instanceCount++; @@ -213,7 +213,7 @@ __private_extern__ void _CFPlugInAddPlugInInstance(CFPlugInRef plugIn) { } } -__private_extern__ void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn) { +CF_PRIVATE void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn) { if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) { /* MF:!!! Assert that instanceCount > 0. */ __CFBundleGetPlugInData(plugIn)->_instanceCount--; @@ -228,11 +228,11 @@ __private_extern__ void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn) { } } -__private_extern__ void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) { +CF_PRIVATE void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) { if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) CFArrayAppendValue(__CFBundleGetPlugInData(plugIn)->_factories, factory); } -__private_extern__ void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) { +CF_PRIVATE void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) { if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) { SInt32 idx = CFArrayGetFirstIndexOfValue(__CFBundleGetPlugInData(plugIn)->_factories, CFRangeMake(0, CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories)), factory); if (idx >= 0) CFArrayRemoveValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, idx); diff --git a/CFPreferences.c b/CFPreferences.c index 5364c34..50637c4 100644 --- a/CFPreferences.c +++ b/CFPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPreferences.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -67,7 +67,7 @@ CONST_STRING_DECL(kCFPreferencesCurrentUser, "kCFPreferencesCurrentUser") static CFAllocatorRef _preferencesAllocator = NULL; -__private_extern__ CFAllocatorRef __CFPreferencesAllocator(void) { +CF_PRIVATE CFAllocatorRef __CFPreferencesAllocator(void) { if (!_preferencesAllocator) { #if DEBUG_PREFERENCES_MEMORY _preferencesAllocator = CFCountingAllocatorCreate(NULL); @@ -103,7 +103,7 @@ CF_EXPORT void CFPreferencesDumpMem(void) { // If this becomes available in a header (), I need to pull this out int gethostuuid(unsigned char *uuid_buf, const struct timespec *timeoutp); -__private_extern__ CFStringRef _CFGetHostUUIDString(void) { +CF_PRIVATE CFStringRef _CFGetHostUUIDString(void) { static CFStringRef __hostUUIDString = NULL; if (!__hostUUIDString) { @@ -131,7 +131,7 @@ __private_extern__ CFStringRef _CFGetHostUUIDString(void) { return __hostUUIDString; } -__private_extern__ CFStringRef _CFPreferencesGetByHostIdentifierString(void) { +CF_PRIVATE CFStringRef _CFPreferencesGetByHostIdentifierString(void) { static CFStringRef __byHostIdentifierString = NULL; if (!__byHostIdentifierString) { @@ -164,7 +164,7 @@ __private_extern__ CFStringRef _CFPreferencesGetByHostIdentifierString(void) { #else -__private_extern__ CFStringRef _CFPreferencesGetByHostIdentifierString(void) { +CF_PRIVATE CFStringRef _CFPreferencesGetByHostIdentifierString(void) { return CFSTR(""); } @@ -425,7 +425,7 @@ static const CFRuntimeClass __CFPreferencesDomainClass = { }; /* This is called once at CFInitialize() time. */ -__private_extern__ void __CFPreferencesDomainInitialize(void) { +CF_PRIVATE void __CFPreferencesDomainInitialize(void) { __kCFPreferencesDomainTypeID = _CFRuntimeRegisterClass(&__CFPreferencesDomainClass); } @@ -571,7 +571,7 @@ static void __CFPreferencesPerformSynchronize(const void *key, const void *value if (!_CFPreferencesDomainSynchronize(domain)) *cumulativeResult = false; } -__private_extern__ Boolean _CFSynchronizeDomainCache(void) { +CF_PRIVATE Boolean _CFSynchronizeDomainCache(void) { Boolean result = true; __CFSpinLock(&domainCacheLock); if (domainCache) { @@ -581,7 +581,7 @@ __private_extern__ Boolean _CFSynchronizeDomainCache(void) { return result; } -__private_extern__ void _CFPreferencesPurgeDomainCache(void) { +CF_PRIVATE void _CFPreferencesPurgeDomainCache(void) { _CFSynchronizeDomainCache(); __CFSpinLock(&domainCacheLock); if (domainCache) { @@ -591,7 +591,7 @@ __private_extern__ void _CFPreferencesPurgeDomainCache(void) { __CFSpinUnlock(&domainCacheLock); } -__private_extern__ CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { +CF_PRIVATE CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); CFArrayRef domains; CFMutableArrayRef marray; @@ -715,17 +715,17 @@ void _CFPreferencesDomainSet(CFPreferencesDomainRef domain, CFStringRef key, CF domain->_callBacks->writeValue(domain->_context, domain->_domain, key, value); } -__private_extern__ Boolean _CFPreferencesDomainSynchronize(CFPreferencesDomainRef domain) { +CF_PRIVATE Boolean _CFPreferencesDomainSynchronize(CFPreferencesDomainRef domain) { return domain->_callBacks->synchronize(domain->_context, domain->_domain); } -__private_extern__ void _CFPreferencesDomainSetIsWorldReadable(CFPreferencesDomainRef domain, Boolean isWorldReadable) { +CF_PRIVATE void _CFPreferencesDomainSetIsWorldReadable(CFPreferencesDomainRef domain, Boolean isWorldReadable) { if (domain->_callBacks->setIsWorldReadable) { domain->_callBacks->setIsWorldReadable(domain->_context, domain->_domain, isWorldReadable); } } -__private_extern__ void *_CFPreferencesDomainCopyDictFunc(CFPreferencesDomainRef domain) { +CF_PRIVATE void *_CFPreferencesDomainCopyDictFunc(CFPreferencesDomainRef domain) { return domain->_callBacks->copyDomainDictionary; } diff --git a/CFPreferences.h b/CFPreferences.h index 9a59a26..aa2c154 100644 --- a/CFPreferences.h +++ b/CFPreferences.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPreferences.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPREFERENCES__) @@ -129,7 +129,7 @@ which have preferences in the scope of the given user and host. The returned value must be released by the caller; neither argument may be NULL. */ CF_EXPORT -CFArrayRef CFPreferencesCopyApplicationList(CFStringRef userName, CFStringRef hostName); +CFArrayRef CFPreferencesCopyApplicationList(CFStringRef userName, CFStringRef hostName) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); /* Constructs and returns the list of all keys set in the given location. The returned value must be released by the caller; diff --git a/CFPriv.h b/CFPriv.h index 3ce6702..6957d7a 100644 --- a/CFPriv.h +++ b/CFPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPriv.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /* @@ -46,6 +46,7 @@ #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_LINUX)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) #include +#include #endif #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || TARGET_OS_WIN32 @@ -85,6 +86,8 @@ CF_EXPORT CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef all CF_EXPORT void CFPreferencesFlushCaches(void); + + #if TARGET_OS_WIN32 CF_EXPORT Boolean _CFURLGetWideFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, wchar_t *buffer, CFIndex bufferLength); #endif @@ -222,6 +225,7 @@ typedef CF_OPTIONS(CFOptionFlags, CFSearchPathDomainMask) { CF_EXPORT CFArrayRef CFCopySearchPathForDirectoriesInDomains(CFSearchPathDirectory directory, CFSearchPathDomainMask domainMask, Boolean expandTilde); + /* Obsolete keys */ CF_EXPORT const CFStringRef kCFFileURLExists; CF_EXPORT const CFStringRef kCFFileURLPOSIXMode; @@ -304,8 +308,8 @@ extern UniChar __CFCharToUniCharTable[256]; CF_INLINE const UniChar *CFStringGetCharactersPtrFromInlineBuffer(CFStringInlineBuffer *buf, CFRange desiredRange) { if ((desiredRange.location < 0) || ((desiredRange.location + desiredRange.length) > buf->rangeToBuffer.length)) return NULL; - if (buf->directBuffer) { - return buf->directBuffer + buf->rangeToBuffer.location + desiredRange.location; + if (buf->directUniCharBuffer) { + return buf->directUniCharBuffer + buf->rangeToBuffer.location + desiredRange.location; } else { if (desiredRange.length > __kCFStringInlineBufferLength) return NULL; @@ -313,7 +317,14 @@ CF_INLINE const UniChar *CFStringGetCharactersPtrFromInlineBuffer(CFStringInline buf->bufferedRangeStart = desiredRange.location; buf->bufferedRangeEnd = buf->bufferedRangeStart + __kCFStringInlineBufferLength; if (buf->bufferedRangeEnd > buf->rangeToBuffer.length) buf->bufferedRangeEnd = buf->rangeToBuffer.length; - CFStringGetCharacters(buf->theString, CFRangeMake(buf->rangeToBuffer.location + buf->bufferedRangeStart, buf->bufferedRangeEnd - buf->bufferedRangeStart), buf->buffer); + CFIndex location = buf->rangeToBuffer.location + buf->bufferedRangeStart; + CFIndex length = buf->bufferedRangeEnd - buf->bufferedRangeStart; + if (buf->directCStringBuffer) { + UniChar *bufPtr = buf->buffer; + while (length--) *bufPtr++ = (UniChar)buf->directCStringBuffer[location++]; + } else { + CFStringGetCharacters(buf->theString, CFRangeMake(location, length), buf->buffer); + } } return buf->buffer + (desiredRange.location - buf->bufferedRangeStart); @@ -321,8 +332,8 @@ CF_INLINE const UniChar *CFStringGetCharactersPtrFromInlineBuffer(CFStringInline } CF_INLINE void CFStringGetCharactersFromInlineBuffer(CFStringInlineBuffer *buf, CFRange desiredRange, UniChar *outBuf) { - if (buf->directBuffer) { - memmove(outBuf, buf->directBuffer + buf->rangeToBuffer.location + desiredRange.location, desiredRange.length * sizeof(UniChar)); + if (buf->directUniCharBuffer) { + memmove(outBuf, buf->directUniCharBuffer + buf->rangeToBuffer.location + desiredRange.location, desiredRange.length * sizeof(UniChar)); } else { if ((desiredRange.location >= buf->bufferedRangeStart) && (desiredRange.location < buf->bufferedRangeEnd)) { CFIndex bufLen = desiredRange.length; @@ -340,19 +351,103 @@ CF_INLINE void CFStringGetCharactersFromInlineBuffer(CFStringInlineBuffer *buf, } } - if (desiredRange.length > 0) CFStringGetCharacters(buf->theString, CFRangeMake(buf->rangeToBuffer.location + desiredRange.location, desiredRange.length), outBuf); + if (desiredRange.length > 0) { + CFIndex location = buf->rangeToBuffer.location + desiredRange.location; + CFIndex length = desiredRange.length; + if (buf->directCStringBuffer) { + UniChar *bufPtr = outBuf; + while (length--) *bufPtr++ = (UniChar)buf->directCStringBuffer[location++]; + } else { + CFStringGetCharacters(buf->theString, CFRangeMake(location, length), outBuf); + } + } } } #else -#define CFStringGetCharactersPtrFromInlineBuffer(buf, desiredRange) ((buf)->directBuffer ? (buf)->directBuffer + (buf)->rangeToBuffer.location + desiredRange.location : NULL) +#define CFStringGetCharactersPtrFromInlineBuffer(buf, desiredRange) ((buf)->directUniCharBuffer ? (buf)->directUniCharBuffer + (buf)->rangeToBuffer.location + desiredRange.location : NULL) #define CFStringGetCharactersFromInlineBuffer(buf, desiredRange, outBuf) \ - if (buf->directBuffer) memmove(outBuf, (buf)->directBuffer + (buf)->rangeToBuffer.location + desiredRange.location, desiredRange.length * sizeof(UniChar)); \ + if (buf->directUniCharBuffer) memmove(outBuf, (buf)->directUniCharBuffer + (buf)->rangeToBuffer.location + desiredRange.location, desiredRange.length * sizeof(UniChar)); \ else CFStringGetCharacters((buf)->theString, CFRangeMake((buf)->rangeToBuffer.location + desiredRange.location, desiredRange.length), outBuf); #endif /* CF_INLINE */ + +#if defined(CF_INLINE) + +#ifndef __kCFStringAppendBufferLength + #define __kCFStringAppendBufferLength 1024 +#endif +typedef struct { + UniChar buffer[__kCFStringAppendBufferLength]; + CFIndex bufferIndex; + CFMutableStringRef theString; +} CFStringAppendBuffer; + + +// Initializes CFStringAppendBuffer with new mutable string. +CF_INLINE void CFStringInitAppendBuffer(CFAllocatorRef alloc, CFStringAppendBuffer *buf) +{ + buf->bufferIndex = 0; + buf->theString = CFStringCreateMutable(alloc, 0); +} + +// Appends the characters of a string to the CFStringAppendBuffer. +CF_INLINE void CFStringAppendStringToAppendBuffer(CFStringAppendBuffer *buf, CFStringRef appendedString) +{ + CFIndex numChars = CFStringGetLength(appendedString); + if ( numChars > __kCFStringAppendBufferLength ) { + if ( buf->bufferIndex ) { + CFStringAppendCharacters(buf->theString, buf->buffer, buf->bufferIndex); + buf->bufferIndex = 0; + } + CFStringAppend(buf->theString, appendedString); + } + else { + if ( (buf->bufferIndex + numChars) > __kCFStringAppendBufferLength ) { + CFStringAppendCharacters(buf->theString, buf->buffer, buf->bufferIndex); + buf->bufferIndex = 0; + } + CFStringGetCharacters(appendedString, CFRangeMake(0, numChars), &buf->buffer[buf->bufferIndex]); + buf->bufferIndex += numChars; + } +} + +// Appends a buffer of Unicode characters to the CFStringAppendBuffer. +CF_INLINE void CFStringAppendCharactersToAppendBuffer(CFStringAppendBuffer *buf, const UniChar *chars, CFIndex numChars) +{ + if ( numChars > __kCFStringAppendBufferLength ) { + if ( buf->bufferIndex ) { + CFStringAppendCharacters(buf->theString, buf->buffer, buf->bufferIndex); + buf->bufferIndex = 0; + } + CFStringAppendCharacters(buf->theString, chars, numChars); + } + else { + if ( (buf->bufferIndex + numChars) > __kCFStringAppendBufferLength ) { + CFStringAppendCharacters(buf->theString, buf->buffer, buf->bufferIndex); + buf->bufferIndex = 0; + } + memcpy(&buf->buffer[buf->bufferIndex], chars, numChars * sizeof(UniChar)); + buf->bufferIndex += numChars; + } +} + +// Returns a mutable string from the CFStringAppendBuffer. +CF_INLINE CFMutableStringRef CFStringCreateMutableWithAppendBuffer(CFStringAppendBuffer *buf) +{ + if ( buf->bufferIndex ) { + CFStringAppendCharacters(buf->theString, buf->buffer, buf->bufferIndex); + buf->bufferIndex = 0; + } + CFMutableStringRef result = buf->theString; + buf->theString = NULL; + return ( result ); +} + +#endif /* CF_INLINE */ + /* CFCharacterSetInlineBuffer related declarations */ @@ -513,6 +608,8 @@ CF_EXPORT bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFData // Returns a subset of the 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. CF_EXPORT bool _CFPropertyListCreateFiltered(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFSetRef keyPaths, CFPropertyListRef *value, CFErrorRef *error) CF_AVAILABLE(10_8, 6_0); +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || TARGET_OS_WIN32 + // Returns a subset of a bundle's Info.plist. The keyPaths follow the same rules as above CFPropertyList function. This function takes platform and product keys into account. typedef CF_OPTIONS(CFOptionFlags, _CFBundleFilteredPlistOptions) { _CFBundleFilteredPlistMemoryMapped = 1 @@ -520,6 +617,7 @@ typedef CF_OPTIONS(CFOptionFlags, _CFBundleFilteredPlistOptions) { CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) CF_AVAILABLE(10_8, 6_0); CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredLocalizedInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, CFStringRef localizationName, _CFBundleFilteredPlistOptions options) CF_AVAILABLE(10_8, 6_0); +#endif #if TARGET_OS_WIN32 #include @@ -552,6 +650,9 @@ CF_EXPORT CFArrayRef CFDateFormatterCreateDateFormatsFromTemplates(CFAllocatorRe CF_EXPORT CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void); #endif +CF_EXPORT const CFStringRef kCFNumberFormatterUsesCharacterDirection CF_AVAILABLE(10_9, 6_0); // CFBoolean +CF_EXPORT const CFStringRef kCFDateFormatterUsesCharacterDirection CF_AVAILABLE(10_9, 6_0); // CFBoolean + CF_EXTERN_C_END diff --git a/CFPropertyList.c b/CFPropertyList.c index b22218c..0ff03e4 100644 --- a/CFPropertyList.c +++ b/CFPropertyList.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPropertyList.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -49,6 +49,9 @@ #include #include + +CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number); + #define PLIST_IX 0 #define ARRAY_IX 1 #define DICT_IX 2 @@ -88,7 +91,7 @@ if (N ## _count__ == 0) N ## _count__ = 1; \ STACK_BUFFER_DECL(CFTypeRef, N ## _buffer__, N ## _is_stack__ ? N ## _count__ : 1); \ if (N ## _is_stack__) memset(N ## _buffer__, 0, N ## _count__ * sizeof(CFTypeRef)); \ - CFTypeRef * N = N ## _is_stack__ ? N ## _buffer__ : (CFTypeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, (N ## _count__) * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); \ + CFTypeRef * N = N ## _is_stack__ ? N ## _buffer__ : (CFTypeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, (N ## _count__) * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory); \ if (! N) { \ CRSetCrashLogMessage("CFPropertyList ran out of memory while attempting to allocate temporary storage."); \ HALT; \ @@ -99,7 +102,7 @@ #if !defined(free_cftype_array) #define free_cftype_array(N) \ if (! N ## _is_stack__) { \ - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFAllocatorDeallocate(kCFAllocatorSystemDefault, N); \ + CFAllocatorDeallocate(kCFAllocatorSystemDefault, N); \ } \ do {} while (0) #endif @@ -125,7 +128,7 @@ static void initStatics() { }); } -__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...) { +CF_PRIVATE CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...) { va_list argList; CFErrorRef error = NULL; @@ -153,8 +156,13 @@ static CFStringRef __copyErrorDebugDescription(CFErrorRef error) { CFStringRef result = NULL; if (error) { CFDictionaryRef userInfo = CFErrorCopyUserInfo(error); - result = CFStringCreateCopy(kCFAllocatorSystemDefault, (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey)); - CFRelease(userInfo); + if (userInfo != NULL) { + CFStringRef desc = (CFStringRef) CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey); + if (desc != NULL) { + result = CFStringCreateCopy(kCFAllocatorSystemDefault, desc); + } + CFRelease(userInfo); + } } return result; } @@ -243,9 +251,9 @@ static bool __CFPropertyListIsValidAux(CFPropertyListRef plist, bool recursive, static Boolean _CFPropertyListIsValidWithErrorString(CFPropertyListRef plist, CFPropertyListFormat format, CFStringRef *error) { initStatics(); CFAssert1(plist != NULL, __kCFLogAssertion, "%s(): NULL is not a property list", __PRETTY_FUNCTION__); - CFMutableSetRef set = CFSetCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, NULL); + CFMutableSetRef set = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL); bool result = __CFPropertyListIsValidAux(plist, true, set, format, error); - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(set); + CFRelease(set); return result; } @@ -298,10 +306,10 @@ typedef struct { Boolean skip; // if true, do not create any objects. } _CFXMLPlistParseInfo; -__private_extern__ CFTypeRef __CFParseOldStylePropertyListOrStringsFile(CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError,CFPropertyListFormat *format); +CF_PRIVATE CFTypeRef __CFCreateOldStylePropertyListOrStringsFile(CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError,CFPropertyListFormat *format); CF_INLINE void __CFPListRelease(CFTypeRef cf, CFAllocatorRef allocator) { - if (cf && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(cf); + if (cf && !(0)) CFRelease(cf); } @@ -690,7 +698,7 @@ CF_EXPORT CFDataRef _CFPropertyListCreateXMLDataWithExtras(CFAllocatorRef alloca Boolean CFPropertyListIsValid(CFPropertyListRef plist, CFPropertyListFormat format) { initStatics(); CFAssert1(plist != NULL, __kCFLogAssertion, "%s(): NULL is not a property list", __PRETTY_FUNCTION__); - CFMutableSetRef set = CFSetCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, NULL); + CFMutableSetRef set = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL); CFStringRef error = NULL; bool result = __CFPropertyListIsValidAux(plist, true, set, format, &error); if (error) { @@ -699,7 +707,7 @@ Boolean CFPropertyListIsValid(CFPropertyListRef plist, CFPropertyListFormat form #endif CFRelease(error); } - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(set); + CFRelease(set); return result; } @@ -1071,8 +1079,6 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableDataRe CFDataAppendBytes(stringData, (const UInt8 *)&ch, 1); } -extern void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len); - static void _createStringMap(_CFXMLPlistParseInfo *pInfo) { pInfo->stringTrie = CFBurstTrieCreate(); pInfo->stringCache = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks); @@ -1080,24 +1086,31 @@ static void _createStringMap(_CFXMLPlistParseInfo *pInfo) { static void _cleanupStringMap(_CFXMLPlistParseInfo *pInfo) { CFBurstTrieRelease(pInfo->stringTrie); - if (!_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRelease(pInfo->stringCache); + CFRelease(pInfo->stringCache); + pInfo->stringTrie = NULL; + pInfo->stringCache = NULL; } -static CFStringRef _uniqueStringForUTF8Bytes(_CFXMLPlistParseInfo *pInfo, const char *base, CFIndex length) { - if (length == 0) return !_CFAllocatorIsGCRefZero(pInfo->allocator) ? (CFStringRef)CFRetain(CFSTR("")) : CFSTR(""); +static CFStringRef _createUniqueStringWithUTF8Bytes(_CFXMLPlistParseInfo *pInfo, const char *base, CFIndex length) { + if (length == 0) return !(0) ? (CFStringRef)CFRetain(CFSTR("")) : CFSTR(""); CFStringRef result = NULL; uint32_t payload = 0; Boolean uniqued = CFBurstTrieContainsUTF8String(pInfo->stringTrie, (UInt8 *)base, length, &payload); - if (uniqued) { - result = (CFStringRef)CFArrayGetValueAtIndex(pInfo->stringCache, (CFIndex)payload); - if (!_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(result); + if (uniqued && payload > 0) { + // The index is at payload - 1 (see below). + result = (CFStringRef)CFArrayGetValueAtIndex(pInfo->stringCache, (CFIndex)payload - 1); + CFRetain(result); } else { result = CFStringCreateWithBytes(pInfo->allocator, (const UInt8 *)base, length, kCFStringEncodingUTF8, NO); if (!result) return NULL; - payload = CFArrayGetCount(pInfo->stringCache); - CFArrayAppendValue(pInfo->stringCache, result); - CFBurstTrieAddUTF8String(pInfo->stringTrie, (UInt8 *)base, length, payload); + // Payload must be >0, so the actual index of the value is at payload - 1 + // We also get add to the array after we make sure that CFBurstTrieAddUTF8String succeeds (it can fail, if the string is too large, for example) + payload = CFArrayGetCount(pInfo->stringCache) + 1; + Boolean didAddToBurstTrie = CFBurstTrieAddUTF8String(pInfo->stringTrie, (UInt8 *)base, length, payload); + if (didAddToBurstTrie) { + CFArrayAppendValue(pInfo->stringCache, result); + } } return result; } @@ -1136,7 +1149,7 @@ static Boolean parseStringTag(_CFXMLPlistParseInfo *pInfo, CFStringRef *out) { *out = NULL; } else { if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) { - CFStringRef s = _uniqueStringForUTF8Bytes(pInfo, mark, pInfo->curr - mark); + CFStringRef s = _createUniqueStringWithUTF8Bytes(pInfo, mark, pInfo->curr - mark); if (!s) { pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unable to convert string to correct encoding")); return false; @@ -1159,7 +1172,7 @@ static Boolean parseStringTag(_CFXMLPlistParseInfo *pInfo, CFStringRef *out) { } else { CFDataAppendBytes(stringData, (const UInt8 *)mark, pInfo->curr - mark); if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) { - CFStringRef s = _uniqueStringForUTF8Bytes(pInfo, (const char *)CFDataGetBytePtr(stringData), CFDataGetLength(stringData)); + CFStringRef s = _createUniqueStringWithUTF8Bytes(pInfo, (const char *)CFDataGetBytePtr(stringData), CFDataGetLength(stringData)); if (!s) { pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unable to convert string to correct encoding")); return false; @@ -1275,7 +1288,7 @@ static CFSetRef createTopLevelKeypaths(CFAllocatorRef allocator, CFSetRef keyPat } // This splits up the keypaths into the ones relevant for this level (of array or dictionary), and the ones for the next level (of array or dictionary) -__private_extern__ void __CFPropertyListCreateSplitKeypaths(CFAllocatorRef allocator, CFSetRef currentKeys, CFSetRef *theseKeys, CFSetRef *nextKeys) { +CF_PRIVATE void __CFPropertyListCreateSplitKeypaths(CFAllocatorRef allocator, CFSetRef currentKeys, CFSetRef *theseKeys, CFSetRef *nextKeys) { if (!currentKeys) { *theseKeys = NULL; *nextKeys = NULL; return; } CFIndex count = CFSetGetCount(currentKeys); @@ -1529,6 +1542,7 @@ static Boolean parseDictTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) { return true; } + if (dict) __CFPListRelease(dict, pInfo->allocator); return false; } @@ -1622,11 +1636,15 @@ static Boolean parseDataTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) { CF_INLINE Boolean read2DigitNumber(_CFXMLPlistParseInfo *pInfo, int32_t *result) { char ch1, ch2; - if (pInfo->curr + 2 >= pInfo->end) return false; + if (pInfo->curr + 2 >= pInfo->end) { + return false; + } ch1 = *pInfo->curr; ch2 = *(pInfo->curr + 1); pInfo->curr += 2; - if (!isdigit(ch1) || !isdigit(ch2)) return false; + if (!isdigit(ch1) || !isdigit(ch2)) { + return false; + } *result = (ch1 - '0')*10 + (ch2 - '0'); return true; } @@ -1794,12 +1812,12 @@ CF_INLINE bool isWhitespace(const char *utf8bytes, const char *end) { 3000 -> */ // Except we consider some additional values from 0x0 to 0x21 and 0x7E to 0xA1 as whitespace, for compatability - char byte1 = *utf8bytes; + unsigned char byte1 = *utf8bytes; if (byte1 < 0x21 || (byte1 > 0x7E && byte1 < 0xA1)) return true; if ((byte1 == 0xe2 || byte1 == 0xe3) && (end - utf8bytes >= 3)) { // Check other possibilities in the 3-bytes range - char byte2 = *(utf8bytes + 1); - char byte3 = *(utf8bytes + 2); + unsigned char byte2 = *(utf8bytes + 1); + unsigned char byte3 = *(utf8bytes + 2); if (byte1 == 0xe2 && byte2 == 0x80) { return ((byte3 >= 80 && byte3 <= 0x8b) || byte3 == 0xaf); } else if (byte1 == 0xe2 && byte2 == 0x81) { @@ -1942,7 +1960,9 @@ static Boolean parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey, CFTy } pInfo->curr ++; } - if (pInfo->curr >= pInfo->end) return false; + if (pInfo->curr >= pInfo->end) { + return false; + } isEmpty = (*(pInfo->curr-1) == '/'); if (markerLength == -1) markerLength = pInfo->curr - (isEmpty ? 1 : 0) - marker; @@ -2338,7 +2358,7 @@ static Boolean _CFPropertyListCreateFromUTF8Data(CFAllocatorRef allocator, CFDat if (success && result && format) *format = kCFPropertyListXMLFormat_v1_0; _cleanupStringMap(pInfo); - if (pInfo->keyPaths && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(pInfo->keyPaths); + if (pInfo->keyPaths && !(0)) CFRelease(pInfo->keyPaths); CFRelease(xmlData); if (success) { @@ -2348,7 +2368,7 @@ static Boolean _CFPropertyListCreateFromUTF8Data(CFAllocatorRef allocator, CFDat // Try again, old-style CFErrorRef oldStyleError = NULL; - result = __CFParseOldStylePropertyListOrStringsFile(allocator, xmlData, originalString, guessedEncoding, option, outError ? &oldStyleError : NULL, format); + result = __CFCreateOldStylePropertyListOrStringsFile(allocator, xmlData, originalString, guessedEncoding, option, outError ? &oldStyleError : NULL, format); if (result) { // Release old error, return if (pInfo->error) CFRelease(pInfo->error); @@ -2453,12 +2473,17 @@ static Boolean _CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef // Convert to UTF8 first CFStringRef xmlString = CFStringCreateWithBytes(allocator, CFDataGetBytePtr(data) + skip, CFDataGetLength(data) - skip, encoding, false); + if (!xmlString) { + if (outError) *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Could not determine the encoding of the XML data (string creation failed)")); + return false; + } + CFDataRef utf8Data = _createUTF8DataFromString(allocator, xmlString); Boolean result = _CFPropertyListCreateFromUTF8Data(allocator, utf8Data, 0, xmlString, 0, option, outError, allowNewTypes, format, topLevelKeys, out); - if (xmlString && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(xmlString); - if (utf8Data && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(utf8Data); + if (xmlString && !(0)) CFRelease(xmlString); + if (utf8Data && !(0)) CFRelease(utf8Data); return result; } @@ -2473,7 +2498,7 @@ CFTypeRef _CFPropertyListCreateFromXMLStringError(CFAllocatorRef allocator, CFSt CFDataRef utf8Data = _createUTF8DataFromString(allocator, xmlString); CFTypeRef result = NULL; _CFPropertyListCreateFromUTF8Data(allocator, utf8Data, 0, xmlString, 0, option, error, allowNewTypes, format, NULL, &result); - if (utf8Data && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(utf8Data); + if (utf8Data && !(0)) CFRelease(utf8Data); return result; } @@ -2506,8 +2531,8 @@ CFTypeRef _CFPropertyListCreateFromXMLString(CFAllocatorRef allocator, CFStringR CFRelease(oldStyleParserUserInfo); } else { - debugString = (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey); - CFRetain(debugString); + debugString = (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey); + if (debugString) CFRetain(debugString); } // Give the debugString to the caller, who is responsible for releasing it @@ -2522,7 +2547,7 @@ CFTypeRef _CFPropertyListCreateFromXMLString(CFAllocatorRef allocator, CFStringR return result; } -__private_extern__ bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist); +CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist); // Returns a subset of the property list, only including the key paths in the CFSet. bool _CFPropertyListCreateFiltered(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFSetRef keyPaths, CFPropertyListRef *value, CFErrorRef *error) { @@ -2552,8 +2577,8 @@ bool _CFPropertyListCreateFiltered(CFAllocatorRef allocator, CFDataRef data, CFO CFMutableDictionaryRef objects = CFDictionaryCreateMutable(allocator, 0, NULL, &kCFTypeDictionaryValueCallBacks); success = __CFBinaryPlistCreateObjectFiltered(databytes, datalen, valueOffset, &trailer, allocator, option, objects, NULL, 0, splitKeyPaths, &out); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(splitKeyPaths); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(objects); + CFRelease(splitKeyPaths); + CFRelease(objects); } else { // Try an XML property list success = _CFPropertyListCreateWithData(allocator, data, option, error, true, NULL, keyPaths, &out); @@ -2594,11 +2619,11 @@ bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFDataRef data, // First check to see if it is a binary property list if (8 <= datalen && __CFBinaryPlistGetTopLevelInfo(databytes, datalen, &marker, &offset, &trailer)) { // Split up the key path - CFArrayRef keyPathArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorSystemDefaultGCRefZero, keyPath, CFSTR(":")); + CFArrayRef keyPathArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorSystemDefault, keyPath, CFSTR(":")); uint64_t keyOffset, valueOffset = offset; // Create a dictionary to cache objects in - CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, NULL, &kCFTypeDictionaryValueCallBacks); + CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); CFIndex keyPathCount = CFArrayGetCount(keyPathArray); _CFDictionarySetCapacity(objects, keyPathCount + 1); @@ -2628,16 +2653,16 @@ bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFDataRef data, } } - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(keyPathArray); - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(objects); + CFRelease(keyPathArray); + CFRelease(objects); } else { // Try an XML property list // Note: This is currently not any more efficient than grabbing the whole thing. This could be improved in the future. CFPropertyListRef plist = CFPropertyListCreateWithData(allocator, data, option, NULL, error); - CFPropertyListRef nextObject = plist; - success = true; - if (!(*error) && plist) { - CFArrayRef keyPathArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorSystemDefaultGCRefZero, keyPath, CFSTR(":")); + if (plist) { + CFPropertyListRef nextObject = plist; + success = true; + CFArrayRef keyPathArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorSystemDefault, keyPath, CFSTR(":")); for (CFIndex i = 0; i < CFArrayGetCount(keyPathArray); i++) { CFStringRef oneKey = (CFStringRef)CFArrayGetValueAtIndex(keyPathArray, i); SInt32 intValue = CFStringGetIntValue(oneKey); @@ -2661,9 +2686,9 @@ bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFDataRef data, success = false; } - if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(keyPathArray); - } - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(plist); + CFRelease(keyPathArray); + CFRelease(plist); + } } return success; @@ -2773,6 +2798,10 @@ CFIndex CFPropertyListWrite(CFPropertyListRef propertyList, CFWriteStreamRef str } if (format == kCFPropertyListXMLFormat_v1_0) { CFDataRef data = _CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, propertyList, true); + if (!data) { + CFLog(kCFLogLevelError, CFSTR("Property list format kCFPropertyListXMLFormat_v1_0 specified but was not a valid property list type")); + return 0; + } CFIndex len = CFDataGetLength(data); const uint8_t *ptr = CFDataGetBytePtr(data); while (0 < len) { @@ -2842,7 +2871,7 @@ CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStrea return result; } -static void __convertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint8_t **buffer, CFIndex *length, CFErrorRef *error) { +static bool __convertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint8_t **buffer, CFIndex *length, CFErrorRef *error) { int32_t buflen = 0, bufsize = 0, retlen; uint8_t *buf = NULL, sbuf[8192]; for (;;) { @@ -2854,9 +2883,10 @@ static void __convertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint if (retlen < 0 && error) { // Copy the error out *error = CFReadStreamCopyError(stream); + return false; } - return; + return true; } if (bufsize < buflen + retlen) { if (bufsize < 256 * 1024) { @@ -2878,9 +2908,10 @@ static void __convertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint if (max <= 0) { *buffer = buf; *length = buflen; - return; + return true; } } + return true; } CFPropertyListRef CFPropertyListCreateWithStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFErrorRef *error) { @@ -2895,17 +2926,20 @@ CFPropertyListRef CFPropertyListCreateWithStream(CFAllocatorRef allocator, CFRea CFErrorRef underlyingError = NULL; CFIndex buflen = 0; uint8_t *buffer = NULL; - __convertReadStreamToBytes(stream, streamLength, &buffer, &buflen, &underlyingError); - if (underlyingError) { + if (!__convertReadStreamToBytes(stream, streamLength, &buffer, &buflen, &underlyingError)) { if (error) { // Wrap the error from CFReadStream in a new error in the cocoa domain CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(userInfo, kCFErrorDebugDescriptionKey, CFSTR("Property list reading could not be completed because the stream had an unknown error.")); - CFDictionarySetValue(userInfo, kCFErrorUnderlyingErrorKey, underlyingError); + CFDictionarySetValue(userInfo, kCFErrorDebugDescriptionKey, CFSTR("Property list reading could not be completed because the stream had an unknown error. Did you forget to open the stream?")); + if (underlyingError) { + CFDictionarySetValue(userInfo, kCFErrorUnderlyingErrorKey, underlyingError); + } *error = CFErrorCreate(kCFAllocatorSystemDefault, kCFErrorDomainCocoa, kCFPropertyListReadStreamError, userInfo); CFRelease(userInfo); } - CFRelease(underlyingError); + if (underlyingError) { + CFRelease(underlyingError); + } return NULL; } @@ -2957,9 +2991,7 @@ static CFArrayRef _arrayDeepImmutableCopy(CFAllocatorRef allocator, CFArrayRef a } result = (i == c) ? CFArrayCreate(allocator, values, c, &kCFTypeArrayCallBacks) : NULL; c = i; - if (!_CFAllocatorIsGCRefZero(allocator)) { - for (i = 0; i < c; i ++) CFRelease(values[i]); - } + for (i = 0; i < c; i ++) CFRelease(values[i]); free_cftype_array(values); } return result; @@ -2973,10 +3005,10 @@ static CFMutableArrayRef _arrayDeepMutableCopy(CFAllocatorRef allocator, CFArray CFTypeRef newValue = CFPropertyListCreateDeepCopy(allocator, CFArrayGetValueAtIndex(array, i), mutabilityOption); if (!newValue) break; CFArrayAppendValue(result, newValue); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(newValue); + CFRelease(newValue); } if (i != c) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(result); + CFRelease(result); result = NULL; } } @@ -3012,7 +3044,7 @@ CFPropertyListRef CFPropertyListCreateDeepCopy(CFAllocatorRef allocator, CFPrope __CFAssignWithWriteBarrier((void **)keys + i, (void *)newKey); CFTypeRef newValue = CFPropertyListCreateDeepCopy(allocator, values[i], mutabilityOption); if (newValue == NULL) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(keys[i]); + CFRelease(keys[i]); break; } __CFAssignWithWriteBarrier((void **)values + i, (void *)newValue); @@ -3023,15 +3055,15 @@ CFPropertyListRef CFPropertyListCreateDeepCopy(CFAllocatorRef allocator, CFPrope if (isMutable) { CFDictionarySetValue((CFMutableDictionaryRef)result, keys[i], values[i]); } - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(keys[i]); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(values[i]); + CFRelease(keys[i]); + CFRelease(values[i]); } } else { result = NULL; count = i; for (i = 0; i < count; i ++) { - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(keys[i]); - if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(values[i]); + CFRelease(keys[i]); + CFRelease(values[i]); } } free_cftype_array(keys); @@ -3049,9 +3081,9 @@ CFPropertyListRef CFPropertyListCreateDeepCopy(CFAllocatorRef allocator, CFPrope result = CFDataCreateCopy(allocator, (CFDataRef)propertyList); } } else if (typeID == numbertype) { - // Warning - this will break if byteSize is ever greater than 32 - uint8_t bytes[32]; - CFNumberType numType = CFNumberGetType((CFNumberRef)propertyList); + // Warning - this will break if byteSize is ever greater than 128 + uint8_t bytes[128]; + CFNumberType numType = _CFNumberGetType2((CFNumberRef)propertyList); CFNumberGetValue((CFNumberRef)propertyList, numType, (void *)bytes); result = CFNumberCreate(allocator, numType, (void *)bytes); } else if (typeID == booltype) { diff --git a/CFPropertyList.h b/CFPropertyList.h index 35ba94a..99ba0a7 100644 --- a/CFPropertyList.h +++ b/CFPropertyList.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFPropertyList.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFPROPERTYLIST__) diff --git a/CFRunLoop.c b/CFRunLoop.c index 8a151fc..1566156 100644 --- a/CFRunLoop.c +++ b/CFRunLoop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,20 +22,30 @@ */ /* CFRunLoop.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ #include #include #include +#include +#include #include "CFInternal.h" #include #include #include #include #include + + +#if DEPLOYMENT_TARGET_WINDOWS +#include +#endif +#include + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#include #include #include #include @@ -43,6 +53,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 @@ -52,16 +63,33 @@ DISPATCH_EXPORT void _dispatch_main_queue_callback_4CF(void); #define MACH_PORT_NULL 0 #define mach_port_name_t HANDLE +#define mach_port_t HANDLE #define _dispatch_get_main_queue_port_4CF _dispatch_get_main_queue_handle_4CF #define _dispatch_main_queue_callback_4CF(x) _dispatch_main_queue_callback_4CF() #define AbsoluteTime LARGE_INTEGER #endif + +#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR +CF_EXPORT pthread_t _CF_pthread_main_thread_np(void); +#define pthread_main_thread_np() _CF_pthread_main_thread_np() +#endif + #include +#include + +#if DEPLOYMENT_TARGET_MACOSX +#define USE_DISPATCH_SOURCE_FOR_TIMERS 1 +#define USE_MK_TIMER_TOO 1 +#else +#define USE_DISPATCH_SOURCE_FOR_TIMERS 0 +#define USE_MK_TIMER_TOO 1 +#endif static int _LogCFRunLoop = 0; +static void _runLoopTimerWithBlockContext(CFRunLoopTimerRef timer, void *opaqueBlock); // for conservative arithmetic safety, such that (TIMER_DATE_LIMIT + TIMER_INTERVAL_LIMIT + kCFAbsoluteTimeIntervalSince1970) * 10^9 < 2^63 #define TIMER_DATE_LIMIT 4039289856.0 @@ -69,6 +97,8 @@ static int _LogCFRunLoop = 0; #define HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY 0 +#define CRASH(string, errcode) do { char msg[256]; snprintf(msg, 256, string, errcode); CRSetCrashLogMessage(msg); HALT; } while (0) + #if DEPLOYMENT_TARGET_WINDOWS static pthread_t kNilPthreadT = { nil, nil }; @@ -83,14 +113,48 @@ static pthread_t kNilPthreadT = (pthread_t)0; #define lockCount(a) a #endif +#pragma mark - + +#define CF_RUN_LOOP_PROBES 0 -CF_EXPORT bool CFDictionaryGetKeyIfPresent(CFDictionaryRef dict, const void *key, const void **actualkey); +#if CF_RUN_LOOP_PROBES +#include "CFRunLoopProbes.h" +#else +#define CFRUNLOOP_NEXT_TIMER_ARMED(arg0) do { } while (0) +#define CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED() (0) +#define CFRUNLOOP_POLL() do { } while (0) +#define CFRUNLOOP_POLL_ENABLED() (0) +#define CFRUNLOOP_SLEEP() do { } while (0) +#define CFRUNLOOP_SLEEP_ENABLED() (0) +#define CFRUNLOOP_SOURCE_FIRED(arg0, arg1, arg2) do { } while (0) +#define CFRUNLOOP_SOURCE_FIRED_ENABLED() (0) +#define CFRUNLOOP_TIMER_CREATED(arg0, arg1, arg2, arg3, arg4, arg5, arg6) do { } while (0) +#define CFRUNLOOP_TIMER_CREATED_ENABLED() (0) +#define CFRUNLOOP_TIMER_FIRED(arg0, arg1, arg2, arg3, arg4) do { } while (0) +#define CFRUNLOOP_TIMER_FIRED_ENABLED() (0) +#define CFRUNLOOP_TIMER_RESCHEDULED(arg0, arg1, arg2, arg3, arg4, arg5) do { } while (0) +#define CFRUNLOOP_TIMER_RESCHEDULED_ENABLED() (0) +#define CFRUNLOOP_WAKEUP(arg0) do { } while (0) +#define CFRUNLOOP_WAKEUP_ENABLED() (0) +#define CFRUNLOOP_WAKEUP_FOR_DISPATCH() do { } while (0) +#define CFRUNLOOP_WAKEUP_FOR_DISPATCH_ENABLED() (0) +#define CFRUNLOOP_WAKEUP_FOR_NOTHING() do { } while (0) +#define CFRUNLOOP_WAKEUP_FOR_NOTHING_ENABLED() (0) +#define CFRUNLOOP_WAKEUP_FOR_SOURCE() do { } while (0) +#define CFRUNLOOP_WAKEUP_FOR_SOURCE_ENABLED() (0) +#define CFRUNLOOP_WAKEUP_FOR_TIMEOUT() do { } while (0) +#define CFRUNLOOP_WAKEUP_FOR_TIMEOUT_ENABLED() (0) +#define CFRUNLOOP_WAKEUP_FOR_TIMER() do { } while (0) +#define CFRUNLOOP_WAKEUP_FOR_TIMER_ENABLED() (0) +#define CFRUNLOOP_WAKEUP_FOR_WAKEUP() do { } while (0) +#define CFRUNLOOP_WAKEUP_FOR_WAKEUP_ENABLED() (0) +#endif // In order to reuse most of the code across Mach and Windows v1 RunLoopSources, we define a // simple abstraction layer spanning Mach ports and Windows HANDLES #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -__private_extern__ uint32_t __CFGetProcessPortCount(void) { +CF_PRIVATE uint32_t __CFGetProcessPortCount(void) { ipc_info_space_t info; ipc_info_name_array_t table = 0; mach_msg_type_number_t tableCount = 0; @@ -110,7 +174,7 @@ __private_extern__ uint32_t __CFGetProcessPortCount(void) { return (uint32_t)tableCount; } -__private_extern__ CFArrayRef __CFStopAllThreads(void) { +CF_PRIVATE CFArrayRef __CFStopAllThreads(void) { CFMutableArrayRef suspended_list = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL); mach_port_t my_task = mach_task_self(); mach_port_t my_thread = mach_thread_self(); @@ -137,16 +201,11 @@ __private_extern__ CFArrayRef __CFStopAllThreads(void) { return suspended_list; } -__private_extern__ void __CFRestartAllThreads(CFArrayRef threads) { +CF_PRIVATE void __CFRestartAllThreads(CFArrayRef threads) { for (CFIndex idx = 0; idx < CFArrayGetCount(threads); idx++) { thread_act_t thread = (thread_act_t)(uintptr_t)CFArrayGetValueAtIndex(threads, idx); kern_return_t ret = thread_resume(thread); - if (ret != KERN_SUCCESS) { - char msg[256]; - snprintf(msg, 256, "*** Failure from thread_resume (%d) ***", ret); - CRSetCrashLogMessage(msg); - HALT; - } + if (ret != KERN_SUCCESS) CRASH("*** Failure from thread_resume (%d) ***", ret); mach_port_deallocate(mach_task_self(), thread); } } @@ -192,32 +251,22 @@ static void __THE_SYSTEM_HAS_NO_PORTS_AVAILABLE__(kern_return_t ret) { HALT; }; static __CFPort __CFPortAllocate(void) { __CFPort result = CFPORT_NULL; kern_return_t ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &result); - if (KERN_SUCCESS != ret) { + if (KERN_SUCCESS != ret) { char msg[256]; snprintf(msg, 256, "*** The system has no mach ports available. You may be able to diagnose which application(s) are using ports by using 'top' or Activity Monitor. (%d) ***", ret); CRSetCrashLogMessage(msg); __THE_SYSTEM_HAS_NO_PORTS_AVAILABLE__(ret); - return CFPORT_NULL; + return CFPORT_NULL; } ret = mach_port_insert_right(mach_task_self(), result, result, MACH_MSG_TYPE_MAKE_SEND); - if (KERN_SUCCESS != ret) { - char msg[256]; - snprintf(msg, 256, "*** Unable to set send right on mach port. (%d) ***", ret); - CRSetCrashLogMessage(msg); - HALT; - } + if (KERN_SUCCESS != ret) CRASH("*** Unable to set send right on mach port. (%d) ***", ret); + mach_port_limits_t limits; limits.mpl_qlimit = 1; ret = mach_port_set_attributes(mach_task_self(), result, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&limits, MACH_PORT_LIMITS_INFO_COUNT); - if (KERN_SUCCESS != ret) { - char msg[256]; - snprintf(msg, 256, "*** Unable to set attributes on mach port. (%d) ***", ret); - CRSetCrashLogMessage(msg); - mach_port_destroy(mach_task_self(), result); - HALT; - } + if (KERN_SUCCESS != ret) CRASH("*** Unable to set attributes on mach port. (%d) ***", ret); return result; } @@ -374,17 +423,22 @@ typedef UnsignedWide AbsoluteTime; #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI + +#if USE_DISPATCH_SOURCE_FOR_TIMERS +#endif +#if USE_MK_TIMER_TOO extern mach_port_name_t mk_timer_create(void); extern kern_return_t mk_timer_destroy(mach_port_name_t name); extern kern_return_t mk_timer_arm(mach_port_name_t name, AbsoluteTime expire_time); extern kern_return_t mk_timer_cancel(mach_port_name_t name, AbsoluteTime *result_time); -CF_INLINE AbsoluteTime __CFUInt64ToAbsoluteTime(int64_t x) { +CF_INLINE AbsoluteTime __CFUInt64ToAbsoluteTime(uint64_t x) { AbsoluteTime a; a.hi = x >> 32; - a.lo = x & (int64_t)0xFFFFFFFF; + a.lo = x & (uint64_t)0xFFFFFFFF; return a; } +#endif static uint32_t __CFSendTrivialMachMessage(mach_port_t port, uint32_t msg_id, CFOptionFlags options, uint32_t timeout) { kern_return_t result; @@ -432,13 +486,14 @@ static kern_return_t mk_timer_cancel(HANDLE name, LARGE_INTEGER *result_time) { } // The name of this function is a lie on Windows. The return value matches the argument of the fake mk_timer functions above. Note that the Windows timers expect to be given "system time". We have to do some calculations to get the right value, which is a FILETIME-like value. -CF_INLINE LARGE_INTEGER __CFUInt64ToAbsoluteTime(int64_t desiredFireTime) { +CF_INLINE LARGE_INTEGER __CFUInt64ToAbsoluteTime(uint64_t desiredFireTime) { LARGE_INTEGER result; - // There is a race we know about here, (timer fire time calculated -> thread suspended -> timer armed == late timer fire), but we don't have a way to avoid it at this time, since the only way to specify an absolute value to the timer is to calculate the relative time first. Fixing that would probably require not using the TSR for timers on Windows. - int64_t timeDiff = desiredFireTime - (int64_t)mach_absolute_time(); - if (timeDiff < 0) { + // There is a race we know about here, (timer fire time calculated -> thread suspended -> timer armed == late timer fire), but we don't have a way to avoid it at this time, since the only way to specify an absolute value to the timer is to calculate the relative time first. Fixing that would probably require not using the TSR for timers on Windows. + uint64_t now = mach_absolute_time(); + if (now > desiredFireTime) { result.QuadPart = 0; } else { + uint64_t timeDiff = desiredFireTime - now; CFTimeInterval amountOfTimeToWait = __CFTSRToTimeInterval(timeDiff); // Result is in 100 ns (10**-7 sec) units to be consistent with a FILETIME. // CFTimeInterval is in seconds. @@ -449,6 +504,9 @@ CF_INLINE LARGE_INTEGER __CFUInt64ToAbsoluteTime(int64_t desiredFireTime) { #endif +#pragma mark - +#pragma mark Modes + /* unlock a run loop and modes before doing callouts/sleeping */ /* never try to take the run loop lock with a mode locked */ /* be very careful of common subexpression elimination and compacting code, particular across locks and unlocks! */ @@ -475,23 +533,31 @@ struct __CFRunLoopMode { CFMutableDictionaryRef _portToV1SourceMap; __CFPortSet _portSet; CFIndex _observerMask; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#if USE_DISPATCH_SOURCE_FOR_TIMERS + dispatch_source_t _timerSource; + dispatch_queue_t _queue; + Boolean _timerFired; // set to true by the source when a timer has fired + Boolean _dispatchTimerArmed; +#endif +#if USE_MK_TIMER_TOO mach_port_t _timerPort; + Boolean _mkTimerArmed; #endif #if DEPLOYMENT_TARGET_WINDOWS - HANDLE _timerPort; DWORD _msgQMask; void (*_msgPump)(void); #endif + uint64_t _timerSoftDeadline; /* TSR */ + uint64_t _timerHardDeadline; /* TSR */ }; CF_INLINE void __CFRunLoopModeLock(CFRunLoopModeRef rlm) { pthread_mutex_lock(&(rlm->_lock)); -// CFLog(6, CFSTR("__CFRunLoopModeLock locked %p"), rlm); + //CFLog(6, CFSTR("__CFRunLoopModeLock locked %p"), rlm); } CF_INLINE void __CFRunLoopModeUnlock(CFRunLoopModeRef rlm) { -// CFLog(6, CFSTR("__CFRunLoopModeLock unlocking %p"), rlm); + //CFLog(6, CFSTR("__CFRunLoopModeLock unlocking %p"), rlm); pthread_mutex_unlock(&(rlm->_lock)); } @@ -511,12 +577,18 @@ static CFStringRef __CFRunLoopModeCopyDescription(CFTypeRef cf) { CFMutableStringRef result; result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0); CFStringAppendFormat(result, NULL, CFSTR("{name = %@, "), rlm, CFGetAllocator(rlm), rlm->_name); - CFStringAppendFormat(result, NULL, CFSTR("port set = %p, "), rlm->_portSet); - CFStringAppendFormat(result, NULL, CFSTR("timer port = %p, "), rlm->_timerPort); + CFStringAppendFormat(result, NULL, CFSTR("port set = 0x%x, "), rlm->_portSet); +#if USE_DISPATCH_SOURCE_FOR_TIMERS + CFStringAppendFormat(result, NULL, CFSTR("queue = %p, "), rlm->_queue); + CFStringAppendFormat(result, NULL, CFSTR("source = %p (%s), "), rlm->_timerSource, rlm->_timerFired ? "fired" : "not fired"); +#endif +#if USE_MK_TIMER_TOO + CFStringAppendFormat(result, NULL, CFSTR("timer port = 0x%x, "), rlm->_timerPort); +#endif #if DEPLOYMENT_TARGET_WINDOWS CFStringAppendFormat(result, NULL, CFSTR("MSGQ mask = %p, "), rlm->_msgQMask); #endif - CFStringAppendFormat(result, NULL, CFSTR("\n\tsources0 = %@,\n\tsources1 = %@,\n\tobservers = %@,\n\ttimers = %@\n},\n"), rlm->_sources0, rlm->_sources1, rlm->_observers, rlm->_timers); + CFStringAppendFormat(result, NULL, CFSTR("\n\tsources0 = %@,\n\tsources1 = %@,\n\tobservers = %@,\n\ttimers = %@,\n\tcurrently %0.09g (%lld) / soft deadline in: %0.09g sec (@ %lld) / hard deadline in: %0.09g sec (@ %lld)\n},\n"), rlm->_sources0, rlm->_sources1, rlm->_observers, rlm->_timers, CFAbsoluteTimeGetCurrent(), mach_absolute_time(), __CFTSRToTimeInterval(rlm->_timerSoftDeadline - mach_absolute_time()), rlm->_timerSoftDeadline, __CFTSRToTimeInterval(rlm->_timerHardDeadline - mach_absolute_time()), rlm->_timerHardDeadline); return result; } @@ -529,11 +601,25 @@ static void __CFRunLoopModeDeallocate(CFTypeRef cf) { if (NULL != rlm->_portToV1SourceMap) CFRelease(rlm->_portToV1SourceMap); CFRelease(rlm->_name); __CFPortSetFree(rlm->_portSet); +#if USE_DISPATCH_SOURCE_FOR_TIMERS + if (rlm->_timerSource) { + dispatch_source_cancel(rlm->_timerSource); + dispatch_release(rlm->_timerSource); + } + if (rlm->_queue) { + dispatch_release(rlm->_queue); + } +#endif +#if USE_MK_TIMER_TOO if (MACH_PORT_NULL != rlm->_timerPort) mk_timer_destroy(rlm->_timerPort); +#endif pthread_mutex_destroy(&rlm->_lock); memset((char *)cf + sizeof(CFRuntimeBase), 0x7C, sizeof(struct __CFRunLoopMode) - sizeof(CFRuntimeBase)); } +#pragma mark - +#pragma mark Run Loops + struct _block_item { struct _block_item *_next; CFTypeRef _mode; // CFString or CFSet @@ -629,11 +715,11 @@ CF_INLINE void __CFRunLoopSetDeallocating(CFRunLoopRef rl) { CF_INLINE void __CFRunLoopLock(CFRunLoopRef rl) { pthread_mutex_lock(&(((CFRunLoopRef)rl)->_lock)); -// CFLog(6, CFSTR("__CFRunLoopLock locked %p"), rl); + // CFLog(6, CFSTR("__CFRunLoopLock locked %p"), rl); } CF_INLINE void __CFRunLoopUnlock(CFRunLoopRef rl) { -// CFLog(6, CFSTR("__CFRunLoopLock unlocking %p"), rl); + // CFLog(6, CFSTR("__CFRunLoopLock unlocking %p"), rl); pthread_mutex_unlock(&(((CFRunLoopRef)rl)->_lock)); } @@ -650,7 +736,7 @@ static CFStringRef __CFRunLoopCopyDescription(CFTypeRef cf) { return result; } -__private_extern__ void __CFRunLoopDump() { // __private_extern__ to keep the compiler from discarding it +CF_PRIVATE void __CFRunLoopDump() { // __private_extern__ to keep the compiler from discarding it CFShow(CFCopyDescription(CFRunLoopGetCurrent())); } @@ -664,14 +750,13 @@ CF_INLINE void __CFRunLoopLockInit(pthread_mutex_t *lock) { } } -/* call with rl locked */ +/* call with rl locked, returns mode locked */ static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef modeName, Boolean create) { CHECK_FOR_FORK(); CFRunLoopModeRef rlm; struct __CFRunLoopMode srlm; memset(&srlm, 0, sizeof(srlm)); - srlm._base._cfisa = __CFISAForTypeID(__kCFRunLoopModeTypeID); - _CFRuntimeSetInstanceTypeID(&srlm, __kCFRunLoopModeTypeID); + _CFRuntimeSetInstanceTypeIDAndIsa(&srlm, __kCFRunLoopModeTypeID); srlm._name = modeName; rlm = (CFRunLoopModeRef)CFSetGetValue(rl->_modes, &srlm); if (NULL != rlm) { @@ -695,22 +780,40 @@ static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef modeNam rlm->_timers = NULL; rlm->_observerMask = 0; rlm->_portSet = __CFPortSetAllocate(); + rlm->_timerSoftDeadline = UINT64_MAX; + rlm->_timerHardDeadline = UINT64_MAX; + + kern_return_t ret = KERN_SUCCESS; +#if USE_DISPATCH_SOURCE_FOR_TIMERS + rlm->_timerFired = false; + rlm->_queue = _dispatch_runloop_root_queue_create_4CF("Run Loop Mode Queue", 0); + mach_port_t queuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->_queue); + if (queuePort == MACH_PORT_NULL) CRASH("*** Unable to create run loop mode queue port. (%d) ***", -1); + rlm->_timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, rlm->_queue); + + __block Boolean *timerFiredPointer = &(rlm->_timerFired); + dispatch_source_set_event_handler(rlm->_timerSource, ^{ + *timerFiredPointer = true; + }); + + // Set timer to far out there. The unique leeway makes this timer easy to spot in debug output. + _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 321); + dispatch_resume(rlm->_timerSource); + + ret = __CFPortSetInsert(queuePort, rlm->_portSet); + if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port set. (%d) ***", ret); + +#endif +#if USE_MK_TIMER_TOO rlm->_timerPort = mk_timer_create(); - kern_return_t ret = __CFPortSetInsert(rlm->_timerPort, rlm->_portSet); - if (KERN_SUCCESS != ret) { - char msg[256]; - snprintf(msg, 256, "*** Unable to insert timer port into port set. (%d) ***", ret); - CRSetCrashLogMessage(msg); - HALT; - } + ret = __CFPortSetInsert(rlm->_timerPort, rlm->_portSet); + if (KERN_SUCCESS != ret) CRASH("*** Unable to insert timer port into port set. (%d) ***", ret); +#endif + ret = __CFPortSetInsert(rl->_wakeUpPort, rlm->_portSet); - if (KERN_SUCCESS != ret) { - char msg[256]; - snprintf(msg, 256, "*** Unable to insert wake up port into port set. (%d) ***", ret); - CRSetCrashLogMessage(msg); - HALT; - } -#if DEPLOYMENT_TARGET_WINDOWS + if (KERN_SUCCESS != ret) CRASH("*** Unable to insert wake up port into port set. (%d) ***", ret); + +#if DEPLOYMENT_TARGET_WINDOWS rlm->_msgQMask = 0; rlm->_msgPump = NULL; #endif @@ -820,6 +923,9 @@ void _CFRunLoopSetWindowsMessageQueueHandler(CFRunLoopRef rl, CFStringRef modeNa #endif +#pragma mark - +#pragma mark Sources + /* Bit 3 in the base reserved bits is used for invalid state in run loop objects */ CF_INLINE Boolean __CFIsValid(const void *cf) { @@ -870,6 +976,7 @@ CF_INLINE void __CFRunLoopSourceUnlock(CFRunLoopSourceRef rls) { pthread_mutex_unlock(&(rls->_lock)); } +#pragma mark Observers struct __CFRunLoopObserver { CFRuntimeBase _base; @@ -937,6 +1044,8 @@ static void __CFRunLoopObserverCancel(CFRunLoopObserverRef rlo, CFRunLoopRef rl, __CFRunLoopObserverUnlock(rlo); } +#pragma mark Timers + struct __CFRunLoopTimer { CFRuntimeBase _base; uint16_t _bits; @@ -945,7 +1054,8 @@ struct __CFRunLoopTimer { CFMutableSetRef _rlModes; CFAbsoluteTime _nextFireDate; CFTimeInterval _interval; /* immutable */ - int64_t _fireTSR; /* TSR units */ + CFTimeInterval _tolerance; /* mutable */ + uint64_t _fireTSR; /* TSR units */ CFIndex _order; /* immutable */ CFRunLoopTimerCallBack _callout; /* immutable */ CFRunLoopTimerContext _context; /* immutable, except invalidation */ @@ -953,6 +1063,7 @@ struct __CFRunLoopTimer { /* Bit 0 of the base reserved bits is used for firing state */ /* Bit 1 of the base reserved bits is used for fired-during-callout state */ +/* Bit 2 of the base reserved bits is used for waking state */ CF_INLINE Boolean __CFRunLoopTimerIsFiring(CFRunLoopTimerRef rlt) { return (Boolean)__CFBitfieldGetValue(rlt->_bits, 0, 0); @@ -994,40 +1105,7 @@ CF_INLINE void __CFRunLoopTimerFireTSRUnlock(void) { __CFSpinUnlock(&__CFRLTFireTSRLock); } -#if DEPLOYMENT_TARGET_WINDOWS - -struct _collectTimersContext { - CFMutableArrayRef results; - int64_t cutoffTSR; -}; - -static void __CFRunLoopCollectTimers(const void *value, void *ctx) { - CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)value; - struct _collectTimersContext *context = (struct _collectTimersContext *)ctx; - if (rlt->_fireTSR <= context->cutoffTSR) { - if (NULL == context->results) - context->results = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(context->results, rlt); - } -} - -// RunLoop and RunLoopMode must be locked -static void __CFRunLoopTimersToFireRecursive(CFRunLoopRef rl, CFRunLoopModeRef rlm, struct _collectTimersContext *ctxt) { - __CFRunLoopTimerFireTSRLock(); - if (NULL != rlm->_timers && 0 < CFArrayGetCount(rlm->_timers)) { - CFArrayApplyFunction(rlm->_timers, CFRangeMake(0, CFArrayGetCount(rlm->_timers)), __CFRunLoopCollectTimers, ctxt); - } - __CFRunLoopTimerFireTSRUnlock(); -} - -// RunLoop and RunLoopMode must be locked -static CFArrayRef __CFRunLoopTimersToFire(CFRunLoopRef rl, CFRunLoopModeRef rlm) { - struct _collectTimersContext ctxt = {NULL, mach_absolute_time()}; - __CFRunLoopTimersToFireRecursive(rl, rlm, &ctxt); - return ctxt.results; -} - -#endif +#pragma mark - /* CFRunLoop */ @@ -1129,37 +1207,40 @@ static void __CFRunLoopDeallocateObservers(const void *value, void *context) { static void __CFRunLoopDeallocateTimers(const void *value, void *context) { CFRunLoopModeRef rlm = (CFRunLoopModeRef)value; - CFIndex idx, cnt; - const void **list, *buffer[256]; if (NULL == rlm->_timers) return; - cnt = CFArrayGetCount(rlm->_timers); - list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0)); - CFArrayGetValues(rlm->_timers, CFRangeMake(0, CFArrayGetCount(rlm->_timers)), list); - for (idx = 0; idx < cnt; idx++) { - CFRetain(list[idx]); - } - CFArrayRemoveAllValues(rlm->_timers); - for (idx = 0; idx < cnt; idx++) { - CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)list[idx]; - __CFRunLoopTimerLock(rlt); - // if the run loop is deallocating, and since a timer can only be in one - // run loop, we're going to be removing the timer from all modes, so be - // a little heavy-handed and direct - CFSetRemoveAllValues(rlt->_rlModes); - rlt->_runLoop = NULL; - __CFRunLoopTimerUnlock(rlt); - CFRelease(list[idx]); - } - if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); + void (^deallocateTimers)(CFMutableArrayRef timers) = ^(CFMutableArrayRef timers) { + CFIndex idx, cnt; + const void **list, *buffer[256]; + cnt = CFArrayGetCount(timers); + list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0)); + CFArrayGetValues(timers, CFRangeMake(0, CFArrayGetCount(timers)), list); + for (idx = 0; idx < cnt; idx++) { + CFRetain(list[idx]); + } + CFArrayRemoveAllValues(timers); + for (idx = 0; idx < cnt; idx++) { + CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)list[idx]; + __CFRunLoopTimerLock(rlt); + // if the run loop is deallocating, and since a timer can only be in one + // run loop, we're going to be removing the timer from all modes, so be + // a little heavy-handed and direct + CFSetRemoveAllValues(rlt->_rlModes); + rlt->_runLoop = NULL; + __CFRunLoopTimerUnlock(rlt); + CFRelease(list[idx]); + } + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); + }; + + if (rlm->_timers && CFArrayGetCount(rlm->_timers)) deallocateTimers(rlm->_timers); } -CF_EXPORT pthread_t _CFMainPThread; CF_EXPORT CFRunLoopRef _CFRunLoopGet0b(pthread_t t); static void __CFRunLoopDeallocate(CFTypeRef cf) { CFRunLoopRef rl = (CFRunLoopRef)cf; - if (_CFRunLoopGet0b(_CFMainPThread) == cf) HALT; + if (_CFRunLoopGet0b(pthread_main_thread_np()) == cf) HALT; /* We try to keep the run loop in a valid state as long as possible, since sources may have non-retained references to the run loop. @@ -1226,12 +1307,9 @@ static const CFRuntimeClass __CFRunLoopClass = { __CFRunLoopCopyDescription }; -__private_extern__ void __CFFinalizeRunLoop(uintptr_t data); - -static int64_t tenus = 0LL; +CF_PRIVATE void __CFFinalizeRunLoop(uintptr_t data); -__private_extern__ void __CFRunLoopInitialize(void) { - tenus = __CFTimeIntervalToTSR(0.000010000); +CF_PRIVATE void __CFRunLoopInitialize(void) { __kCFRunLoopTypeID = _CFRuntimeRegisterClass(&__CFRunLoopClass); __kCFRunLoopModeTypeID = _CFRuntimeRegisterClass(&__CFRunLoopModeClass); } @@ -1279,14 +1357,14 @@ static CFSpinLock_t loopsLock = CFSpinLockInit; // t==0 is a synonym for "main thread" that always works CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) { if (pthread_equal(t, kNilPthreadT)) { - t = _CFMainPThread; + t = pthread_main_thread_np(); } __CFSpinLock(&loopsLock); if (!__CFRunLoops) { __CFSpinUnlock(&loopsLock); CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); - CFRunLoopRef mainLoop = __CFRunLoopCreate(_CFMainPThread); - CFDictionarySetValue(dict, pthreadPointer(_CFMainPThread), mainLoop); + CFRunLoopRef mainLoop = __CFRunLoopCreate(pthread_main_thread_np()); + CFDictionarySetValue(dict, pthreadPointer(pthread_main_thread_np()), mainLoop); if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) { CFRelease(dict); } @@ -1319,7 +1397,7 @@ CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) { // should only be called by Foundation CFRunLoopRef _CFRunLoopGet0b(pthread_t t) { if (pthread_equal(t, kNilPthreadT)) { - t = _CFMainPThread; + t = pthread_main_thread_np(); } __CFSpinLock(&loopsLock); CFRunLoopRef loop = NULL; @@ -1333,7 +1411,7 @@ CFRunLoopRef _CFRunLoopGet0b(pthread_t t) { static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName); // Called for each thread as it exits -__private_extern__ void __CFFinalizeRunLoop(uintptr_t data) { +CF_PRIVATE void __CFFinalizeRunLoop(uintptr_t data) { CFRunLoopRef rl = NULL; if (data <= 1) { __CFSpinLock(&loopsLock); @@ -1404,7 +1482,7 @@ void _CFRunLoopSetCurrent(CFRunLoopRef rl) { CFRunLoopRef CFRunLoopGetMain(void) { CHECK_FOR_FORK(); static CFRunLoopRef __main = NULL; // no retain needed - if (!__main) __main = _CFRunLoopGet0(_CFMainPThread); // no CAS needed + if (!__main) __main = _CFRunLoopGet0(pthread_main_thread_np()); // no CAS needed return __main; } @@ -1507,6 +1585,12 @@ 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 +} + static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() __attribute__((noinline)); static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(CFRunLoopObserverCallBack func, CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { if (func) { @@ -1737,6 +1821,9 @@ static Boolean __CFRunLoopDoSources0(CFRunLoopRef rl, CFRunLoopModeRef rlm, Bool return sourceHandled; } +CF_INLINE void __CFRunLoopDebugInfoForRunLoopSource(CFRunLoopSourceRef rls) { +} + // msg, size and reply are unused on Windows static Boolean __CFRunLoopDoSource1() __attribute__((noinline)); static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopSourceRef rls @@ -1755,6 +1842,7 @@ static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRun if (__CFIsValid(rls)) { __CFRunLoopSourceUnsetSignaled(rls); __CFRunLoopSourceUnlock(rls); + __CFRunLoopDebugInfoForRunLoopSource(rls); __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__(rls->_context.version1.perform, #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI msg, size, reply, @@ -1808,52 +1896,140 @@ static CFIndex __CFRunLoopInsertionIndexInTimerArray(CFArrayRef array, CFRunLoop return lastTestLEQ ? idx + 1 : idx; } -static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm) { - CFRunLoopTimerRef nextTimer = NULL; - for (CFIndex idx = 0, cnt = CFArrayGetCount(rlm->_timers); idx < cnt; idx++) { - CFRunLoopTimerRef t = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm->_timers, idx); - if (!__CFRunLoopTimerIsFiring(t)) { - nextTimer = t; - break; +static void __CFArmNextTimerInMode(CFRunLoopModeRef rlm, CFRunLoopRef rl) { + uint64_t nextHardDeadline = UINT64_MAX; + uint64_t nextSoftDeadline = UINT64_MAX; + + if (rlm->_timers) { + // Look at the list of timers. We will calculate two TSR values; the next soft and next hard deadline. + // The next soft deadline is the first time we can fire any timer. This is the fire date of the first timer in our sorted list of timers. + // The next hard deadline is the last time at which we can fire the timer before we've moved out of the allowable tolerance of the timers in our list. + for (CFIndex idx = 0, cnt = CFArrayGetCount(rlm->_timers); idx < cnt; idx++) { + CFRunLoopTimerRef t = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm->_timers , idx); + // discount timers currently firing + if (__CFRunLoopTimerIsFiring(t)) continue; + + int32_t err = CHECKINT_NO_ERROR; + uint64_t oneTimerSoftDeadline = t->_fireTSR; + uint64_t oneTimerHardDeadline = check_uint64_add(t->_fireTSR, __CFTimeIntervalToTSR(t->_tolerance), &err); + if (err != CHECKINT_NO_ERROR) oneTimerHardDeadline = UINT64_MAX; + + // We can stop searching if the soft deadline for this timer exceeds the current hard deadline. Otherwise, later timers with lower tolerance could still have earlier hard deadlines. + if (oneTimerSoftDeadline > nextHardDeadline) { + break; + } + + if (oneTimerSoftDeadline < nextSoftDeadline) { + nextSoftDeadline = oneTimerSoftDeadline; + } + + if (oneTimerHardDeadline < nextHardDeadline) { + nextHardDeadline = oneTimerHardDeadline; + } + } + + if (nextSoftDeadline < UINT64_MAX && (nextHardDeadline != rlm->_timerHardDeadline || nextSoftDeadline != rlm->_timerSoftDeadline)) { + if (CFRUNLOOP_NEXT_TIMER_ARMED_ENABLED()) { + CFRUNLOOP_NEXT_TIMER_ARMED((unsigned long)(nextSoftDeadline - mach_absolute_time())); + } +#if USE_DISPATCH_SOURCE_FOR_TIMERS + // We're going to hand off the range of allowable timer fire date to dispatch and let it fire when appropriate for the system. + uint64_t leeway = __CFTSRToNanoseconds(nextHardDeadline - nextSoftDeadline); + dispatch_time_t deadline = __CFTSRToDispatchTime(nextSoftDeadline); +#if USE_MK_TIMER_TOO + if (leeway > 0) { + // Only use the dispatch timer if we have any leeway + // + + // Cancel the mk timer + if (rlm->_mkTimerArmed && rlm->_timerPort) { + AbsoluteTime dummy; + mk_timer_cancel(rlm->_timerPort, &dummy); + rlm->_mkTimerArmed = false; + } + + // Arm the dispatch timer + _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, deadline, DISPATCH_TIME_FOREVER, leeway); + rlm->_dispatchTimerArmed = true; + } else { + // Cancel the dispatch timer + if (rlm->_dispatchTimerArmed) { + // Cancel the dispatch timer + _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 888); + rlm->_dispatchTimerArmed = false; + } + + // Arm the mk timer + if (rlm->_timerPort) { + mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(nextSoftDeadline)); + rlm->_mkTimerArmed = true; + } + } +#else + _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, deadline, DISPATCH_TIME_FOREVER, leeway); +#endif +#else + if (rlm->_timerPort) { + mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(nextSoftDeadline)); + } +#endif + } else if (nextSoftDeadline == UINT64_MAX) { + // Disarm the timers - there is no timer scheduled + + if (rlm->_mkTimerArmed && rlm->_timerPort) { + AbsoluteTime dummy; + mk_timer_cancel(rlm->_timerPort, &dummy); + rlm->_mkTimerArmed = false; + } + +#if USE_DISPATCH_SOURCE_FOR_TIMERS + if (rlm->_dispatchTimerArmed) { + _dispatch_source_set_runloop_timer_4CF(rlm->_timerSource, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, 333); + rlm->_dispatchTimerArmed = false; + } +#endif } } - if (nextTimer) { - int64_t fireTSR = nextTimer->_fireTSR; - fireTSR = (fireTSR / tenus + 1) * tenus; - mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(fireTSR)); - } + rlm->_timerHardDeadline = nextHardDeadline; + rlm->_timerSoftDeadline = nextSoftDeadline; } // call with rlm and its run loop locked, and the TSRLock locked; rlt not locked; returns with same state static void __CFRepositionTimerInMode(CFRunLoopModeRef rlm, CFRunLoopTimerRef rlt, Boolean isInArray) __attribute__((noinline)); static void __CFRepositionTimerInMode(CFRunLoopModeRef rlm, CFRunLoopTimerRef rlt, Boolean isInArray) { - if (!rlt || !rlm->_timers) return; + if (!rlt) return; + + CFMutableArrayRef timerArray = rlm->_timers; + if (!timerArray) return; Boolean found = false; + + // If we know in advance that the timer is not in the array (just being added now) then we can skip this search if (isInArray) { - CFIndex idx = CFArrayGetFirstIndexOfValue(rlm->_timers, CFRangeMake(0, CFArrayGetCount(rlm->_timers)), rlt); - if (kCFNotFound != idx) { - CFRetain(rlt); - CFArrayRemoveValueAtIndex(rlm->_timers, idx); - found = true; - } + CFIndex idx = CFArrayGetFirstIndexOfValue(timerArray, CFRangeMake(0, CFArrayGetCount(timerArray)), rlt); + if (kCFNotFound != idx) { + CFRetain(rlt); + CFArrayRemoveValueAtIndex(timerArray, idx); + found = true; + } } if (!found && isInArray) return; - CFIndex newIdx = __CFRunLoopInsertionIndexInTimerArray(rlm->_timers, rlt); - CFArrayInsertValueAtIndex(rlm->_timers, newIdx, rlt); - __CFArmNextTimerInMode(rlm); + CFIndex newIdx = __CFRunLoopInsertionIndexInTimerArray(timerArray, rlt); + CFArrayInsertValueAtIndex(timerArray, newIdx, rlt); + __CFArmNextTimerInMode(rlm, rlt->_runLoop); if (isInArray) CFRelease(rlt); } + // mode and rl are locked on entry and exit static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopTimerRef rlt) { /* DOES CALLOUT */ Boolean timerHandled = false; - int64_t oldFireTSR = 0; + uint64_t oldFireTSR = 0; /* Fire a timer */ CFRetain(rlt); __CFRunLoopTimerLock(rlt); - if (__CFIsValid(rlt) && rlt->_fireTSR <= (int64_t)mach_absolute_time() && !__CFRunLoopTimerIsFiring(rlt) && rlt->_runLoop == rl) { + if (__CFIsValid(rlt) && rlt->_fireTSR <= mach_absolute_time() && !__CFRunLoopTimerIsFiring(rlt) && rlt->_runLoop == rl) { void *context_info = NULL; void (*context_release)(const void *) = NULL; if (rlt->_context.retain) { @@ -1864,12 +2040,15 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo } Boolean doInvalidate = (0.0 == rlt->_interval); __CFRunLoopTimerSetFiring(rlt); + // Just in case the next timer has exactly the same deadlines as this one, we reset these values so that the arm next timer code can correctly find the next timer in the list and arm the underlying timer. + rlm->_timerSoftDeadline = UINT64_MAX; + rlm->_timerHardDeadline = UINT64_MAX; __CFRunLoopTimerUnlock(rlt); __CFRunLoopTimerFireTSRLock(); oldFireTSR = rlt->_fireTSR; __CFRunLoopTimerFireTSRUnlock(); - __CFArmNextTimerInMode(rlm); + __CFArmNextTimerInMode(rlm, rl); __CFRunLoopModeUnlock(rlm); __CFRunLoopUnlock(rl); @@ -1901,10 +2080,10 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo // skipped because it was firing. Need to redo the // min timer calculation in case rlt should now be that // timer instead of whatever was chosen. - __CFArmNextTimerInMode(rlm); + __CFArmNextTimerInMode(rlm, rl); } else { - int64_t nextFireTSR = 0LL; - int64_t intervalTSR = 0LL; + uint64_t nextFireTSR = 0LL; + uint64_t intervalTSR = 0LL; if (rlt->_interval <= 0.0) { } else if (TIMER_INTERVAL_LIMIT < rlt->_interval) { intervalTSR = __CFTimeIntervalToTSR(TIMER_INTERVAL_LIMIT); @@ -1914,7 +2093,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo if (LLONG_MAX - intervalTSR <= oldFireTSR) { nextFireTSR = LLONG_MAX; } else { - int64_t currentTSR = (int64_t)mach_absolute_time(); + uint64_t currentTSR = mach_absolute_time(); nextFireTSR = oldFireTSR; while (nextFireTSR <= currentTSR) { nextFireTSR += intervalTSR; @@ -1941,11 +2120,11 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo } __CFRunLoopTimerFireTSRLock(); rlt->_fireTSR = nextFireTSR; - rlt->_nextFireDate = CFAbsoluteTimeGetCurrent() + __CFTSRToTimeInterval(nextFireTSR - (int64_t)mach_absolute_time()); + rlt->_nextFireDate = CFAbsoluteTimeGetCurrent() + __CFTimeIntervalUntilTSR(nextFireTSR); for (CFIndex idx = 0; idx < cnt; idx++) { CFRunLoopModeRef rlm = (CFRunLoopModeRef)modes[idx]; if (rlm) { - __CFRepositionTimerInMode(rlm, rlt, true); + __CFRepositionTimerInMode(rlm, rlt, true); } } __CFRunLoopTimerFireTSRUnlock(); @@ -1957,7 +2136,7 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo __CFRunLoopTimerUnlock(rlt); __CFRunLoopTimerFireTSRLock(); rlt->_fireTSR = nextFireTSR; - rlt->_nextFireDate = CFAbsoluteTimeGetCurrent() + __CFTSRToTimeInterval(nextFireTSR - (int64_t)mach_absolute_time()); + rlt->_nextFireDate = CFAbsoluteTimeGetCurrent() + __CFTimeIntervalUntilTSR(nextFireTSR); __CFRunLoopTimerFireTSRUnlock(); } } @@ -1968,17 +2147,22 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo return timerHandled; } + // rl and rlm are locked on entry and exit -static Boolean __CFRunLoopDoTimers(CFRunLoopRef rl, CFRunLoopModeRef rlm, int64_t limitTSR) { /* DOES CALLOUT */ +static Boolean __CFRunLoopDoTimers(CFRunLoopRef rl, CFRunLoopModeRef rlm, uint64_t limitTSR) { /* DOES CALLOUT */ Boolean timerHandled = false; CFMutableArrayRef timers = NULL; for (CFIndex idx = 0, cnt = rlm->_timers ? CFArrayGetCount(rlm->_timers) : 0; idx < cnt; idx++) { CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm->_timers, idx); - if (__CFIsValid(rlt) && rlt->_fireTSR <= limitTSR && !__CFRunLoopTimerIsFiring(rlt)) { - if (!timers) timers = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(timers, rlt); + + if (__CFIsValid(rlt) && !__CFRunLoopTimerIsFiring(rlt)) { + if (rlt->_fireTSR <= limitTSR) { + if (!timers) timers = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(timers, rlt); + } } } + for (CFIndex idx = 0, cnt = timers ? CFArrayGetCount(timers) : 0; idx < cnt; idx++) { CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)CFArrayGetValueAtIndex(timers, idx); Boolean did = __CFRunLoopDoTimer(rl, rlm, rlt); @@ -2009,8 +2193,9 @@ 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_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) { Boolean originalBuffer = true; + kern_return_t ret = KERN_SUCCESS; for (;;) { /* In that sleep of death what nightmares may come ... */ mach_msg_header_t *msg = (mach_msg_header_t *)*buffer; msg->msgh_bits = 0; @@ -2018,11 +2203,17 @@ static Boolean __CFRunLoopServiceMachPort(mach_port_name_t port, mach_msg_header msg->msgh_remote_port = MACH_PORT_NULL; msg->msgh_size = buffer_size; msg->msgh_id = 0; - kern_return_t 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); - if (MACH_MSG_SUCCESS == ret) return true; + 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); + CFRUNLOOP_WAKEUP(ret); + if (MACH_MSG_SUCCESS == ret) { + *livePort = msg ? msg->msgh_local_port : MACH_PORT_NULL; + return true; + } if (MACH_RCV_TIMED_OUT == ret) { if (!originalBuffer) free(msg); *buffer = NULL; + *livePort = MACH_PORT_NULL; return false; } if (MACH_RCV_TOO_LARGE != ret) break; @@ -2095,7 +2286,7 @@ static Boolean __CFRunLoopWaitForMultipleObjects(__CFPortSet portSet, HANDLE *on struct __timeout_context { dispatch_source_t ds; CFRunLoopRef rl; - int64_t termTSR; + uint64_t termTSR; }; static void __CFRunLoopTimeoutCancel(void *arg) { @@ -2107,14 +2298,15 @@ static void __CFRunLoopTimeoutCancel(void *arg) { static void __CFRunLoopTimeout(void *arg) { struct __timeout_context *context = (struct __timeout_context *)arg; - context->termTSR = 0LL; + context->termTSR = 0ULL; + CFRUNLOOP_WAKEUP_FOR_TIMEOUT(); CFRunLoopWakeUp(context->rl); // The interval is DISPATCH_TIME_FOREVER, so this won't fire again } /* rl, rlm are locked on entrance and exit */ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) { - int64_t startTSR = (int64_t)mach_absolute_time(); + uint64_t startTSR = mach_absolute_time(); if (__CFRunLoopIsStopped(rl)) { __CFRunLoopUnsetStopped(rl); @@ -2127,12 +2319,22 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter mach_port_name_t dispatchPort = MACH_PORT_NULL; Boolean libdispatchQSafe = pthread_main_np() && ((HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == _CFGetTSD(__CFTSDKeyIsInGCDMainQ))); if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl->_commonModes, rlm->_name)) dispatchPort = _dispatch_get_main_queue_port_4CF(); - + +#if USE_DISPATCH_SOURCE_FOR_TIMERS + mach_port_name_t modeQueuePort = MACH_PORT_NULL; + if (rlm->_queue) { + modeQueuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->_queue); + if (!modeQueuePort) { + CRASH("Unable to get port for run loop mode queue (%d)", -1); + } + } +#endif + dispatch_source_t timeout_timer = NULL; struct __timeout_context *timeout_context = (struct __timeout_context *)malloc(sizeof(*timeout_context)); if (seconds <= 0.0) { // instant timeout seconds = 0.0; - timeout_context->termTSR = 0LL; + 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); timeout_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); @@ -2143,12 +2345,12 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter dispatch_set_context(timeout_timer, timeout_context); // source gets ownership of context dispatch_source_set_event_handler_f(timeout_timer, __CFRunLoopTimeout); dispatch_source_set_cancel_handler_f(timeout_timer, __CFRunLoopTimeoutCancel); - uint64_t nanos = (uint64_t)(seconds * 1000 * 1000 + 1) * 1000; - dispatch_source_set_timer(timeout_timer, dispatch_time(DISPATCH_TIME_NOW, nanos), DISPATCH_TIME_FOREVER, 0); - dispatch_resume(timeout_timer); + uint64_t ns_at = (uint64_t)((__CFTSRToTimeInterval(startTSR) + seconds) * 1000000000ULL); + dispatch_source_set_timer(timeout_timer, dispatch_time(1, ns_at), DISPATCH_TIME_FOREVER, 1000ULL); + dispatch_resume(timeout_timer); } else { // infinite timeout seconds = 9999999999.0; - timeout_context->termTSR = INT64_MAX; + timeout_context->termTSR = UINT64_MAX; } Boolean didDispatchPortLastTime = true; @@ -2157,6 +2359,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter uint8_t msg_buffer[3 * 1024]; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI mach_msg_header_t *msg = NULL; + mach_port_t livePort = MACH_PORT_NULL; #elif DEPLOYMENT_TARGET_WINDOWS HANDLE livePort = NULL; Boolean windowsMessageReceived = false; @@ -2175,12 +2378,12 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter __CFRunLoopDoBlocks(rl, rlm); } - Boolean poll = sourceHandledThisLoop || (0LL == timeout_context->termTSR); + Boolean poll = sourceHandledThisLoop || (0ULL == timeout_context->termTSR); 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), 0)) { + if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0)) { goto handle_msg; } #elif DEPLOYMENT_TARGET_WINDOWS @@ -2201,17 +2404,45 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter // want these ports to get serviced. __CFPortSetInsert(dispatchPort, waitSet); - + __CFRunLoopModeUnlock(rlm); __CFRunLoopUnlock(rl); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#if USE_DISPATCH_SOURCE_FOR_TIMERS + do { + if (kCFUseCollectableAllocator) { + 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); + + 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. + while (_dispatch_runloop_root_queue_perform_4CF(rlm->_queue)); + if (rlm->_timerFired) { + // Leave livePort as the queue port, and service timers below + rlm->_timerFired = false; + break; + } else { + if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg); + } + } else { + // Go ahead and leave the inner loop. + break; + } + } while (1); +#else if (kCFUseCollectableAllocator) { objc_clear_stack(0); memset(msg_buffer, 0, sizeof(msg_buffer)); } msg = (mach_msg_header_t *)msg_buffer; - __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), poll ? 0 : TIMEOUT_INFINITY); + __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY); +#endif + + #elif DEPLOYMENT_TARGET_WINDOWS // Here, use the app-supplied message queue mask. They will set this if they are interested in having this run loop receive windows messages. __CFRunLoopWaitForMultipleObjects(waitSet, NULL, poll ? 0 : TIMEOUT_INFINITY, rlm->_msgQMask, &livePort, &windowsMessageReceived); @@ -2236,9 +2467,6 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter handle_msg:; __CFRunLoopSetIgnoreWakeUps(rl); -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - mach_port_t livePort = msg ? msg->msgh_local_port : MACH_PORT_NULL; -#endif #if DEPLOYMENT_TARGET_WINDOWS if (windowsMessageReceived) { // These Win32 APIs cause a callout, so make sure we're unlocked first and relocked after @@ -2277,35 +2505,52 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter #endif if (MACH_PORT_NULL == livePort) { + CFRUNLOOP_WAKEUP_FOR_NOTHING(); // handle nothing } else if (livePort == rl->_wakeUpPort) { + CFRUNLOOP_WAKEUP_FOR_WAKEUP(); // do nothing on Mac OS #if DEPLOYMENT_TARGET_WINDOWS // Always reset the wake up port, or risk spinning forever ResetEvent(rl->_wakeUpPort); #endif - } else if (livePort == rlm->_timerPort) { -#if DEPLOYMENT_TARGET_WINDOWS - // On Windows, we have observed an issue where the timer port is set before the time which we requested it to be set. For example, we set the fire time to be TSR 167646765860, but it is actually observed firing at TSR 167646764145, which is 1715 ticks early. On the hardware where this was observed, multiplying by the TSR to seconds conversion rate shows that this was 0.000478~ seconds early, but the tenus used when setting fire dates is 0.00001 seconds. The result is that, when __CFRunLoopDoTimers checks to see if any of the run loop timers should be firing, it appears to be 'too early' for the next timer, and no timers are handled. + } +#if USE_DISPATCH_SOURCE_FOR_TIMERS + else if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) { + CFRUNLOOP_WAKEUP_FOR_TIMER(); + if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) { + // Re-arm the next timer, because we apparently fired early + __CFArmNextTimerInMode(rlm, rl); + } + } +#endif +#if USE_MK_TIMER_TOO + else if (rlm->_timerPort != MACH_PORT_NULL && livePort == rlm->_timerPort) { + CFRUNLOOP_WAKEUP_FOR_TIMER(); + // On Windows, we have observed an issue where the timer port is set before the time which we requested it to be set. For example, we set the fire time to be TSR 167646765860, but it is actually observed firing at TSR 167646764145, which is 1715 ticks early. The result is that, when __CFRunLoopDoTimers checks to see if any of the run loop timers should be firing, it appears to be 'too early' for the next timer, and no timers are handled. // In this case, the timer port has been automatically reset (since it was returned from MsgWaitForMultipleObjectsEx), and if we do not re-arm it, then no timers will ever be serviced again unless something adjusts the timer list (e.g. adding or removing timers). The fix for the issue is to reset the timer here if CFRunLoopDoTimers did not handle a timer itself. 9308754 if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) { // Re-arm the next timer - __CFArmNextTimerInMode(rlm); + __CFArmNextTimerInMode(rlm, rl); } -#else - __CFRunLoopDoTimers(rl, rlm, mach_absolute_time()); + } #endif - } else if (livePort == dispatchPort) { - __CFRunLoopModeUnlock(rlm); - __CFRunLoopUnlock(rl); + else if (livePort == dispatchPort) { + CFRUNLOOP_WAKEUP_FOR_DISPATCH(); + __CFRunLoopModeUnlock(rlm); + __CFRunLoopUnlock(rl); _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL); - _dispatch_main_queue_callback_4CF(msg); +#if DEPLOYMENT_TARGET_WINDOWS + void *msg = 0; +#endif + __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg); _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL); __CFRunLoopLock(rl); __CFRunLoopModeLock(rlm); sourceHandledThisLoop = true; didDispatchPortLastTime = true; } else { + CFRUNLOOP_WAKEUP_FOR_SOURCE(); // Despite the name, this works for windows handles as well CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, livePort); if (rls) { @@ -2326,10 +2571,11 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter #endif __CFRunLoopDoBlocks(rl, rlm); + if (sourceHandledThisLoop && stopAfterHandle) { retVal = kCFRunLoopRunHandledSource; - } else if (timeout_context->termTSR < (int64_t)mach_absolute_time()) { + } else if (timeout_context->termTSR < mach_absolute_time()) { retVal = kCFRunLoopRunTimedOut; } else if (__CFRunLoopIsStopped(rl)) { __CFRunLoopUnsetStopped(rl); @@ -2366,10 +2612,12 @@ SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterva volatile _per_run_data *previousPerRun = __CFRunLoopPushPerRunData(rl); CFRunLoopModeRef previousMode = rl->_currentMode; rl->_currentMode = currentMode; - int32_t result; + int32_t result = kCFRunLoopRunFinished; + if (currentMode->_observerMask & kCFRunLoopEntry ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry); result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode); if (currentMode->_observerMask & kCFRunLoopExit ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit); + __CFRunLoopModeUnlock(currentMode); __CFRunLoopPopPerRunData(rl, previousPerRun); rl->_currentMode = previousMode; @@ -2395,8 +2643,10 @@ CFAbsoluteTime CFRunLoopGetNextTimerFireDate(CFRunLoopRef rl, CFStringRef modeNa __CFRunLoopLock(rl); CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, false); CFAbsoluteTime at = 0.0; - CFRunLoopTimerRef timer = (rlm && rlm->_timers && 0 < CFArrayGetCount(rlm->_timers)) ? (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm->_timers, 0) : NULL; - if (timer) at = CFRunLoopTimerGetNextFireDate(timer); + CFRunLoopTimerRef nextTimer = (rlm && rlm->_timers && 0 < CFArrayGetCount(rlm->_timers)) ? (CFRunLoopTimerRef)CFArrayGetValueAtIndex(rlm->_timers, 0) : NULL; + if (nextTimer) { + at = CFRunLoopTimerGetNextFireDate(nextTimer); + } if (rlm) __CFRunLoopModeUnlock(rlm); __CFRunLoopUnlock(rl); return at; @@ -2421,12 +2671,7 @@ void CFRunLoopWakeUp(CFRunLoopRef rl) { * to lose a wakeup, but the send may fail if there is already a * wakeup pending, since the queue length is 1. */ ret = __CFSendTrivialMachMessage(rl->_wakeUpPort, 0, MACH_SEND_TIMEOUT, 0); - if (ret != MACH_MSG_SUCCESS && ret != MACH_SEND_TIMED_OUT) { - char msg[256]; - snprintf(msg, 256, "*** Unable to send message to wake up port. (%d) ***", ret); - CRSetCrashLogMessage(msg); - HALT; - } + if (ret != MACH_MSG_SUCCESS && ret != MACH_SEND_TIMED_OUT) CRASH("*** Unable to send message to wake up port. (%d) ***", ret); #elif DEPLOYMENT_TARGET_WINDOWS SetEvent(rl->_wakeUpPort); #endif @@ -2640,7 +2885,7 @@ void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef rls, CFStringRef } __CFRunLoopSourceUnlock(rls); if (0 == rls->_context.version0.version) { - if (NULL != rls->_context.version0.schedule) { + if (NULL != rls->_context.version0.cancel) { doVer0Callout = true; } } @@ -2821,11 +3066,11 @@ Boolean CFRunLoopContainsTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringR } } else { CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, false); - if (NULL != rlm && NULL != rlm->_timers) { - CFIndex idx = CFArrayGetFirstIndexOfValue(rlm->_timers, CFRangeMake(0, CFArrayGetCount(rlm->_timers)), rlt); - hasValue = (kCFNotFound != idx); - } - if (NULL != rlm) { + if (NULL != rlm) { + if (NULL != rlm->_timers) { + CFIndex idx = CFArrayGetFirstIndexOfValue(rlm->_timers, CFRangeMake(0, CFArrayGetCount(rlm->_timers)), rlt); + hasValue = (kCFNotFound != idx); + } __CFRunLoopModeUnlock(rlm); } } @@ -2852,10 +3097,12 @@ void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeN } } else { CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, true); - if (NULL != rlm && NULL == rlm->_timers) { - CFArrayCallBacks cb = kCFTypeArrayCallBacks; - cb.equal = NULL; - rlm->_timers = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &cb); + if (NULL != rlm) { + if (NULL == rlm->_timers) { + CFArrayCallBacks cb = kCFTypeArrayCallBacks; + cb.equal = NULL; + rlm->_timers = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &cb); + } } if (NULL != rlm && !CFSetContainsValue(rlt->_rlModes, rlm->_name)) { __CFRunLoopTimerLock(rlt); @@ -2870,7 +3117,7 @@ void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeN CFSetAddValue(rlt->_rlModes, rlm->_name); __CFRunLoopTimerUnlock(rlt); __CFRunLoopTimerFireTSRLock(); - __CFRepositionTimerInMode(rlm, rlt, false); + __CFRepositionTimerInMode(rlm, rlt, false); __CFRunLoopTimerFireTSRUnlock(); if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLion)) { // Normally we don't do this on behalf of clients, but for @@ -2903,8 +3150,12 @@ void CFRunLoopRemoveTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef mo } else { CFRunLoopModeRef rlm = __CFRunLoopFindMode(rl, modeName, false); CFIndex idx = kCFNotFound; - if (NULL != rlm && NULL != rlm->_timers) { - idx = CFArrayGetFirstIndexOfValue(rlm->_timers, CFRangeMake(0, CFArrayGetCount(rlm->_timers)), rlt); + CFMutableArrayRef timerList = NULL; + if (NULL != rlm) { + timerList = rlm->_timers; + if (NULL != timerList) { + idx = CFArrayGetFirstIndexOfValue(timerList, CFRangeMake(0, CFArrayGetCount(timerList)), rlt); + } } if (kCFNotFound != idx) { __CFRunLoopTimerLock(rlt); @@ -2913,14 +3164,9 @@ void CFRunLoopRemoveTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef mo rlt->_runLoop = NULL; } __CFRunLoopTimerUnlock(rlt); - CFArrayRemoveValueAtIndex(rlm->_timers, idx); - if (0 == CFArrayGetCount(rlm->_timers)) { - AbsoluteTime dummy; - mk_timer_cancel(rlm->_timerPort, &dummy); - } else if (0 == idx) { - __CFArmNextTimerInMode(rlm); - } - } + CFArrayRemoveValueAtIndex(timerList, idx); + __CFArmNextTimerInMode(rlm, rl); + } if (NULL != rlm) { __CFRunLoopModeUnlock(rlm); } @@ -2973,7 +3219,7 @@ static CFStringRef __CFRunLoopSourceCopyDescription(CFTypeRef cf) { /* DOES CALL #if DEPLOYMENT_TARGET_WINDOWS result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{signalled = %s, valid = %s, order = %d, context = %@}"), cf, CFGetAllocator(rls), __CFRunLoopSourceIsSignaled(rls) ? "Yes" : "No", __CFIsValid(rls) ? "Yes" : "No", rls->_order, contextDesc); #else - result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{signalled = %s, valid = %s, order = %d, context = %@}"), cf, CFGetAllocator(rls), __CFRunLoopSourceIsSignaled(rls) ? "Yes" : "No", __CFIsValid(rls) ? "Yes" : "No", rls->_order, contextDesc); + result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{signalled = %s, valid = %s, order = %ld, context = %@}"), cf, CFGetAllocator(rls), __CFRunLoopSourceIsSignaled(rls) ? "Yes" : "No", __CFIsValid(rls) ? "Yes" : "No", (unsigned long)rls->_order, contextDesc); #endif CFRelease(contextDesc); return result; @@ -3001,7 +3247,7 @@ static const CFRuntimeClass __CFRunLoopSourceClass = { __CFRunLoopSourceCopyDescription }; -__private_extern__ void __CFRunLoopSourceInitialize(void) { +CF_PRIVATE void __CFRunLoopSourceInitialize(void) { __kCFRunLoopSourceTypeID = _CFRuntimeRegisterClass(&__CFRunLoopSourceClass); } @@ -3013,10 +3259,8 @@ CFRunLoopSourceRef CFRunLoopSourceCreate(CFAllocatorRef allocator, CFIndex order CHECK_FOR_FORK(); CFRunLoopSourceRef memory; uint32_t size; - if (NULL == context) { - CRSetCrashLogMessage("*** NULL context value passed to CFRunLoopSourceCreate(). ***"); - HALT; - } + 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); if (NULL == memory) { @@ -3142,7 +3386,7 @@ Boolean CFRunLoopSourceIsSignalled(CFRunLoopSourceRef rls) { return ret; } -__private_extern__ void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls) { +CF_PRIVATE void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls) { CFBagRef loops = NULL; __CFRunLoopSourceLock(rls); if (__CFIsValid(rls) && NULL != rls->_runLoops) { @@ -3173,7 +3417,7 @@ static CFStringRef __CFRunLoopObserverCopyDescription(CFTypeRef cf) { /* DOES CA void *addr = rlo->_callout; Dl_info info; const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???"; - result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlo), __CFIsValid(rlo) ? "Yes" : "No", rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", rlo->_order, name, addr, contextDesc); + result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{valid = %s, activities = 0x%lx, repeats = %s, order = %ld, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlo), __CFIsValid(rlo) ? "Yes" : "No", (long)rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", (long)rlo->_order, name, addr, contextDesc); #endif CFRelease(contextDesc); return result; @@ -3197,7 +3441,7 @@ static const CFRuntimeClass __CFRunLoopObserverClass = { __CFRunLoopObserverCopyDescription }; -__private_extern__ void __CFRunLoopObserverInitialize(void) { +CF_PRIVATE void __CFRunLoopObserverInitialize(void) { __kCFRunLoopObserverTypeID = _CFRuntimeRegisterClass(&__CFRunLoopObserverClass); } @@ -3332,7 +3576,8 @@ void CFRunLoopObserverGetContext(CFRunLoopObserverRef rlo, CFRunLoopObserverCont *context = rlo->_context; } -/* CFRunLoopTimer */ +#pragma mark - +#pragma mark CFRunLoopTimer static CFStringRef __CFRunLoopTimerCopyDescription(CFTypeRef cf) { /* DOES CALLOUT */ CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)cf; @@ -3344,12 +3589,27 @@ static CFStringRef __CFRunLoopTimerCopyDescription(CFTypeRef cf) { /* DOES CALLO contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR(""), rlt->_context.info); } void *addr = (void *)rlt->_callout; - const char *name = "???"; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - Dl_info info; - name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???"; -#endif - CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{valid = %s, firing = %s, interval = %0.09g, next fire date = %0.09g, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlt), __CFIsValid(rlt) ? "Yes" : "No", __CFRunLoopTimerIsFiring(rlt) ? "Yes" : "No", rlt->_interval, rlt->_nextFireDate, name, addr, contextDesc); + char libraryName[2048]; + char functionName[2048]; + void *functionPtr = NULL; + libraryName[0] = '?'; libraryName[1] = '\0'; + functionName[0] = '?'; functionName[1] = '\0'; + CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, + CFSTR("{valid = %s, firing = %s, interval = %0.09g, tolerance = %0.09g, next fire date = %0.09g (%0.09g @ %lld), callout = %s (%p / %p) (%s), context = %@}"), + cf, + CFGetAllocator(rlt), + __CFIsValid(rlt) ? "Yes" : "No", + __CFRunLoopTimerIsFiring(rlt) ? "Yes" : "No", + rlt->_interval, + rlt->_tolerance, + rlt->_nextFireDate, + rlt->_nextFireDate - CFAbsoluteTimeGetCurrent(), + rlt->_fireTSR, + functionName, + addr, + functionPtr, + libraryName, + contextDesc); CFRelease(contextDesc); return result; } @@ -3376,7 +3636,7 @@ static const CFRuntimeClass __CFRunLoopTimerClass = { __CFRunLoopTimerCopyDescription }; -__private_extern__ void __CFRunLoopTimerInitialize(void) { +CF_PRIVATE void __CFRunLoopTimerInitialize(void) { __kCFRunLoopTimerTypeID = _CFRuntimeRegisterClass(&__CFRunLoopTimerClass); } @@ -3401,10 +3661,11 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime memory->_order = order; if (interval < 0.0) interval = 0.0; memory->_interval = interval; + memory->_tolerance = 0.0; if (TIMER_DATE_LIMIT < fireDate) fireDate = TIMER_DATE_LIMIT; memory->_nextFireDate = fireDate; - memory->_fireTSR = 0LL; - int64_t now2 = (int64_t)mach_absolute_time(); + memory->_fireTSR = 0ULL; + uint64_t now2 = mach_absolute_time(); CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent(); if (fireDate < now1) { memory->_fireTSR = now2; @@ -3469,8 +3730,8 @@ void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDat CHECK_FOR_FORK(); if (!__CFIsValid(rlt)) return; if (TIMER_DATE_LIMIT < fireDate) fireDate = TIMER_DATE_LIMIT; - int64_t nextFireTSR = 0LL; - int64_t now2 = (int64_t)mach_absolute_time(); + uint64_t nextFireTSR = 0ULL; + uint64_t now2 = mach_absolute_time(); CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent(); if (fireDate < now1) { nextFireTSR = now2; @@ -3613,3 +3874,36 @@ void CFRunLoopTimerGetContext(CFRunLoopTimerRef rlt, CFRunLoopTimerContext *cont *context = rlt->_context; } +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); + return rlt->_tolerance; +#else + return 0.0; +#endif +} + +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); + /* + * dispatch rules: + * + * For the initial timer fire at 'start', the upper limit to the allowable + * delay is set to 'leeway' nanoseconds. For the subsequent timer fires at + * 'start' + N * 'interval', the upper limit is MIN('leeway','interval'/2). + */ + if (rlt->_interval > 0) { + rlt->_tolerance = MIN(tolerance, rlt->_interval / 2); + } else { + // Tolerance must be a positive value or zero + if (tolerance < 0) tolerance = 0.0; + rlt->_tolerance = tolerance; + } +#endif +} + diff --git a/CFRunLoop.h b/CFRunLoop.h index e2eb7f3..2744ea1 100644 --- a/CFRunLoop.h +++ b/CFRunLoop.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFRunLoop.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFRUNLOOP__) @@ -193,6 +193,11 @@ CF_EXPORT void CFRunLoopTimerInvalidate(CFRunLoopTimerRef timer); CF_EXPORT Boolean CFRunLoopTimerIsValid(CFRunLoopTimerRef timer); CF_EXPORT void CFRunLoopTimerGetContext(CFRunLoopTimerRef timer, CFRunLoopTimerContext *context); +// Setting a tolerance for a timer allows it to fire later than the scheduled fire date, improving the ability of the system to optimize for increased power savings and responsiveness. The timer may fire at any time between its scheduled fire date and the scheduled fire date plus the tolerance. The timer will not fire before the scheduled fire date. For repeating timers, the next fire date is calculated from the original fire date regardless of tolerance applied at individual fire times, to avoid drift. The default value is zero, which means no additional tolerance is applied. The system reserves the right to apply a small amount of tolerance to certain timers regardless of the value of this property. +// As the user of the timer, you will have the best idea of what an appropriate tolerance for a timer may be. A general rule of thumb, though, is to set the tolerance to at least 10% of the interval, for a repeating timer. Even a small amount of tolerance will have a significant positive impact on the power usage of your application. The system may put a maximum value of the tolerance. +CF_EXPORT CFTimeInterval CFRunLoopTimerGetTolerance(CFRunLoopTimerRef timer) CF_AVAILABLE(10_9, 7_0); +CF_EXPORT void CFRunLoopTimerSetTolerance(CFRunLoopTimerRef timer, CFTimeInterval tolerance) CF_AVAILABLE(10_9, 7_0); + CF_EXTERN_C_END #endif /* ! __COREFOUNDATION_CFRUNLOOP__ */ diff --git a/CFRuntime.c b/CFRuntime.c index 6a5ee6d..cb2d3fb 100644 --- a/CFRuntime.c +++ b/CFRuntime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFRuntime.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -70,7 +70,7 @@ __kCFReleaseEvent = 29 #define FAKE_INSTRUMENTS 0 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -__private_extern__ void __CFOAInitializeNSObject(void); // from NSObject.m +CF_PRIVATE void __CFOAInitializeNSObject(void); // from NSObject.m bool __CFOASafe = false; @@ -199,10 +199,10 @@ static const CFRuntimeClass __CFTypeClass = { // 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; -__private_extern__ CFRuntimeClass * __CFRuntimeClassTable[__CFRuntimeClassTableSize] = {0}; -__private_extern__ int32_t __CFRuntimeClassTableCount = 0; +CF_PRIVATE CFRuntimeClass * __CFRuntimeClassTable[__CFRuntimeClassTableSize] = {0}; +CF_PRIVATE int32_t __CFRuntimeClassTableCount = 0; -__private_extern__ uintptr_t __CFRuntimeObjCClassTable[__CFRuntimeClassTableSize] = {0}; +CF_PRIVATE uintptr_t __CFRuntimeObjCClassTable[__CFRuntimeClassTableSize] = {0}; #if !defined(__CFObjCIsCollectable) bool (*__CFObjCIsCollectable)(void *) = NULL; @@ -266,8 +266,8 @@ void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID) { #if defined(DEBUG) || defined(ENABLE_ZOMBIES) -__private_extern__ uint8_t __CFZombieEnabled = 0; -__private_extern__ uint8_t __CFDeallocateZombies = 0; +CF_PRIVATE uint8_t __CFZombieEnabled = 0; +CF_PRIVATE uint8_t __CFDeallocateZombies = 0; extern void __CFZombifyNSObject(void); // from NSObject.m @@ -299,11 +299,11 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF CFLog(kCFLogLevelWarning, CFSTR("*** _CFRuntimeCreateInstance() found inconsistent class '%s'."), cls->className); return NULL; } - if (customRC && kCFUseCollectableAllocator && (kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator)) { + 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 = _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); + CFAllocatorRef realAllocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator; if (kCFAllocatorNull == realAllocator) { return NULL; } @@ -330,10 +330,9 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF *(CFAllocatorRef *)((char *)memory) = (CFAllocatorRef)CFRetain(realAllocator); memory = (CFRuntimeBase *)((char *)memory + sizeof(CFAllocatorRef)); } - memory->_cfisa = __CFISAForTypeID(typeID); uint32_t rc = 0; #if __LP64__ - if (!kCFUseCollectableAllocator || (kCFAllocatorSystemDefaultGCRefZero != allocator && kCFAllocatorDefaultGCRefZero != allocator)) { + if (!kCFUseCollectableAllocator || (1 && 1)) { memory->_rc = 1; } if (customRC) { @@ -341,7 +340,7 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF rc = 0xFF; } #else - if (!kCFUseCollectableAllocator || (kCFAllocatorSystemDefaultGCRefZero != allocator && kCFAllocatorDefaultGCRefZero != allocator)) { + if (!kCFUseCollectableAllocator || (1 && 1)) { rc = 1; } if (customRC) { @@ -350,6 +349,7 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF #endif uint32_t *cfinfop = (uint32_t *)&(memory->_cfinfo); *cfinfop = (uint32_t)((rc << 24) | (customRC ? 0x800000 : 0x0) | ((uint32_t)typeID << 8) | (usesSystemDefaultAllocator ? 0x80 : 0x00)); + memory->_cfisa = 0; if (NULL != cls->init) { (cls->init)(memory); } @@ -366,12 +366,12 @@ void _CFRuntimeInitStaticInstance(void *ptr, CFTypeID typeID) { return; } CFRuntimeBase *memory = (CFRuntimeBase *)ptr; - memory->_cfisa = __CFISAForTypeID(typeID); uint32_t *cfinfop = (uint32_t *)&(memory->_cfinfo); *cfinfop = (uint32_t)(((customRC ? 0xFF : 0) << 24) | (customRC ? 0x800000 : 0x0) | ((uint32_t)typeID << 8) | 0x80); #if __LP64__ memory->_rc = customRC ? 0xFFFFFFFFU : 0x0; #endif + memory->_cfisa = 0; if (NULL != cfClass->init) { (cfClass->init)(memory); } @@ -397,6 +397,10 @@ void _CFRuntimeSetInstanceTypeID(CFTypeRef cf, CFTypeID newTypeID) { *cfinfop = (*cfinfop & 0xFFF000FFU) | ((uint32_t)newTypeID << 8); } +CF_PRIVATE void _CFRuntimeSetInstanceTypeIDAndIsa(CFTypeRef cf, CFTypeID newTypeID) { + _CFRuntimeSetInstanceTypeID(cf, newTypeID); +} + enum { __kCFObjectRetainedEvent = 12, @@ -453,68 +457,6 @@ CF_EXPORT uintptr_t __CFDoExternRefOperation(uintptr_t op, id obj) { return 0; } -static void __CFExternRefNullFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { -} - -static uintptr_t __CFExternRefNullRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - return stack_value; -} - -static uintptr_t __CFExternRefNullRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - return stack_key; -} - -static void __CFExternRefNullReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { -} - -static void __CFExternRefNullReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { -} - -static Boolean __CFExternRefNullEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - return coll_value1 == stack_value2; -} - -static Boolean __CFExternRefNullEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - return coll_key1 == stack_key2; -} - -static uintptr_t __CFExternRefNullHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - return stack_key; -} - -static uintptr_t __CFExternRefNullGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFExternRefNullCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value); -} - -static CFStringRef __CFExternRefNullCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key); -} - -static CFBasicHashCallbacks *__CFExternRefNullCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); - -static const CFBasicHashCallbacks CFExternRefCallbacks = { - __CFExternRefNullCopyCallbacks, - __CFExternRefNullFreeCallbacks, - __CFExternRefNullRetainValue, - __CFExternRefNullRetainKey, - __CFExternRefNullReleaseValue, - __CFExternRefNullReleaseKey, - __CFExternRefNullEquateValues, - __CFExternRefNullEquateKeys, - __CFExternRefNullHashKey, - __CFExternRefNullGetIndirectKey, - __CFExternRefNullCopyValueDescription, - __CFExternRefNullCopyKeyDescription -}; - -static CFBasicHashCallbacks *__CFExternRefNullCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - return (CFBasicHashCallbacks *)&CFExternRefCallbacks; -} - CF_EXPORT CFTypeID CFNumberGetTypeID(void); CF_INLINE CFTypeID __CFGenericTypeID_inline(const void *cf) { @@ -532,7 +474,7 @@ CFTypeID CFTypeGetTypeID(void) { return __kCFTypeTypeID; } -__private_extern__ void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, const char *func) { +CF_PRIVATE void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, const char *func) { if (cf && CF_IS_OBJC(type, cf)) return; CFAssert2((cf != NULL) && (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]) && (__kCFNotATypeTypeID != __CFGenericTypeID_inline(cf)) && (__kCFTypeTypeID != __CFGenericTypeID_inline(cf)), __kCFLogAssertion, "%s(): pointer %p is not a CF object", func, cf); \ CFAssert3(__CFGenericTypeID_inline(cf) == type, __kCFLogAssertion, "%s(): pointer %p is not a %s", func, cf, __CFRuntimeClassTable[type]->className); \ @@ -571,6 +513,11 @@ CFTypeRef CFRetain(CFTypeRef cf) { return _CFRetain(cf, false); } +CFTypeRef CFAutorelease(CFTypeRef __attribute__((cf_consumed)) cf) { + if (NULL == cf) { CRSetCrashLogMessage("*** CFAutorelease() called with NULL ***"); HALT; } + return cf; +} + static void _CFRelease(CFTypeRef cf); void CFRelease(CFTypeRef cf) { @@ -591,18 +538,21 @@ void CFRelease(CFTypeRef cf) { } -__private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf); +CF_PRIVATE void __CFAllocatorDeallocate(CFTypeRef cf); -__private_extern__ const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr) { +CF_PRIVATE const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr) { if (NULL == ptr) { CRSetCrashLogMessage("*** __CFStringCollectionCopy() called with NULL ***"); HALT; } CFStringRef theString = (CFStringRef)ptr; - CFStringRef result = CFStringCreateCopy(_CFConvertAllocatorToGCRefZeroEquivalent(allocator), theString); + CFStringRef result = CFStringCreateCopy((allocator), theString); + if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { + result = (CFStringRef)CFMakeCollectable(result); + } return (const void *)result; } extern void CFCollection_non_gc_storage_error(void); -__private_extern__ const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr) { +CF_PRIVATE const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr) { if (NULL == ptr) { CRSetCrashLogMessage("*** __CFTypeCollectionRetain() called with NULL; likely a collection has been corrupted ***"); HALT; } CFTypeRef cf = (CFTypeRef)ptr; // only collections allocated in the GC zone can opt-out of reference counting. @@ -637,7 +587,7 @@ __private_extern__ const void *__CFTypeCollectionRetain(CFAllocatorRef allocator } -__private_extern__ void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void *ptr) { +CF_PRIVATE void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void *ptr) { if (NULL == ptr) { CRSetCrashLogMessage("*** __CFTypeCollectionRelease() called with NULL; likely a collection has been corrupted ***"); HALT; } CFTypeRef cf = (CFTypeRef)ptr; // only collections allocated in the GC zone can opt-out of reference counting. @@ -775,7 +725,7 @@ CFStringRef CFCopyDescription(CFTypeRef cf) { } // Definition: if type produces a formatting description, return that string, otherwise NULL -__private_extern__ CFStringRef __CFCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { +CF_PRIVATE CFStringRef __CFCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { if (NULL == cf) return NULL; __CFGenericAssertIsCF(cf); if (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->copyFormattingDesc) { @@ -821,14 +771,15 @@ 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 -__private_extern__ void __CFTSDLinuxInitialize(); +CF_PRIVATE void __CFTSDLinuxInitialize(); #endif #if DEPLOYMENT_TARGET_WINDOWS // From CFPlatform.c -__private_extern__ void __CFTSDWindowsInitialize(void); -__private_extern__ void __CFTSDWindowsCleanup(void); -__private_extern__ void __CFFinalizeWindowsThreadData(); +CF_PRIVATE void __CFTSDWindowsInitialize(void); +CF_PRIVATE void __CFTSDWindowsCleanup(void); +CF_PRIVATE void __CFFinalizeWindowsThreadData(); #endif extern void __CFStreamInitialize(void); extern void __CFCalendarInitialize(); @@ -842,10 +793,10 @@ extern void __CFXPreferencesInitialize(void); #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -__private_extern__ uint8_t __CF120290 = false; -__private_extern__ uint8_t __CF120291 = false; -__private_extern__ uint8_t __CF120293 = false; -__private_extern__ char * __crashreporter_info__ = NULL; // Keep this symbol, since it was exported and other things may be linking against it, like GraphicsServices.framework on iOS +CF_PRIVATE uint8_t __CF120290 = false; +CF_PRIVATE uint8_t __CF120291 = false; +CF_PRIVATE uint8_t __CF120293 = false; +CF_PRIVATE char * __crashreporter_info__ = NULL; // Keep this symbol, since it was exported and other things may be linking against it, like GraphicsServices.framework on iOS asm(".desc ___crashreporter_info__, 0x10"); static void __01121__(void) { @@ -872,7 +823,7 @@ static void __01123__(void) { #define EXEC_WARNING_STRING_1 "The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().\n" #define EXEC_WARNING_STRING_2 "Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.\n" -__private_extern__ void __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__(void) { +CF_PRIVATE void __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__(void) { write(2, EXEC_WARNING_STRING_1, sizeof(EXEC_WARNING_STRING_1) - 1); write(2, EXEC_WARNING_STRING_2, sizeof(EXEC_WARNING_STRING_2) - 1); // HALT; @@ -882,7 +833,7 @@ __private_extern__ void __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOU CF_EXPORT const void *__CFArgStuff; const void *__CFArgStuff = NULL; -__private_extern__ void *__CFAppleLanguages = NULL; +CF_PRIVATE void *__CFAppleLanguages = NULL; // do not cache CFFIXED_USER_HOME or HOME, there are situations where they can change @@ -915,16 +866,21 @@ static struct { {"__CFPREFERENCES_LOG_FAILURES", NULL}, {"CFNumberDisableCache", NULL}, {"__CFPREFERENCES_AVOID_DAEMON", NULL}, + {"APPLE_FRAMEWORKS_ROOT", NULL}, {NULL, NULL}, // the last one is for optional "COMMAND_MODE" "legacy", do not use this slot, insert before }; -__private_extern__ const char *__CFgetenv(const char *n) { +CF_PRIVATE const char *__CFgetenv(const char *n) { for (CFIndex idx = 0; idx < sizeof(__CFEnv) / sizeof(__CFEnv[0]); idx++) { if (__CFEnv[idx].name && 0 == strcmp(n, __CFEnv[idx].name)) return __CFEnv[idx].value; } return getenv(n); } +CF_PRIVATE Boolean __CFProcessIsRestricted() { + return issetugid(); +} + #if DEPLOYMENT_TARGET_WINDOWS #define kNilPthreadT { nil, nil } #else @@ -932,16 +888,26 @@ __private_extern__ const char *__CFgetenv(const char *n) { #endif -CF_EXPORT pthread_t _CFMainPThread; -pthread_t _CFMainPThread = kNilPthreadT; - #undef kCFUseCollectableAllocator CF_EXPORT bool kCFUseCollectableAllocator; bool kCFUseCollectableAllocator = false; -__private_extern__ Boolean __CFProphylacticAutofsAccess = false; -__private_extern__ Boolean __CFInitializing = 0; -__private_extern__ Boolean __CFInitialized = 0; +CF_PRIVATE Boolean __CFProphylacticAutofsAccess = false; +CF_PRIVATE Boolean __CFInitializing = 0; +CF_PRIVATE Boolean __CFInitialized = 0; + +// move the next 2 lines down into the #if below, and make it static, after Foundation gets off this symbol on other platforms +CF_EXPORT pthread_t _CFMainPThread; +pthread_t _CFMainPThread = kNilPthreadT; +#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR + +CF_EXPORT pthread_t _CF_pthread_main_thread_np(void); +pthread_t _CF_pthread_main_thread_np(void) { + return _CFMainPThread; +} +#define pthread_main_thread_np() _CF_pthread_main_thread_np() + +#endif #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD static void __CFInitialize(void) __attribute__ ((constructor)); @@ -955,11 +921,11 @@ void __CFInitialize(void) { if (!__CFInitialized && !__CFInitializing) { __CFInitializing = 1; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS - if (!pthread_main_np()) HALT; // CoreFoundation must be initialized on the main thread +#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR + if (!pthread_main_np()) HALT; // CoreFoundation must be initialized on the main thread #endif - - _CFMainPThread = pthread_self(); + // move this next line up into the #if above after Foundation gets off this symbol + _CFMainPThread = pthread_self(); #if DEPLOYMENT_TARGET_WINDOWS // Must not call any CF functions @@ -1022,7 +988,8 @@ void __CFInitialize(void) { CFBagGetTypeID(); for (CFIndex idx = 0; idx < NUM_EXTERN_TABLES; idx++) { - __NSRetainCounters[idx].table = CFBasicHashCreate(kCFAllocatorSystemDefault, kCFBasicHashHasCounts | kCFBasicHashLinearHashing | kCFBasicHashAggressiveGrowth, &CFExternRefCallbacks); + 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; } @@ -1070,6 +1037,9 @@ void __CFInitialize(void) { #if DEPLOYMENT_TARGET_WINDOWS __CFWindowsNamedPipeInitialize(); #endif + + __CFDateInitialize(); + #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS __CFRunLoopInitialize(); __CFRunLoopObserverInitialize(); @@ -1086,8 +1056,8 @@ void __CFInitialize(void) { #endif { - CFIndex idx, cnt; - char **args; + CFIndex idx, cnt = 0; + char **args = NULL; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI args = *_NSGetArgv(); cnt = *_NSGetArgc(); @@ -1152,10 +1122,10 @@ void __CFInitialize(void) { #if DEPLOYMENT_TARGET_WINDOWS -__private_extern__ void __CFStringCleanup(void); -__private_extern__ void __CFSocketCleanup(void); -__private_extern__ void __CFUniCharCleanup(void); -__private_extern__ void __CFStreamCleanup(void); +CF_PRIVATE void __CFStringCleanup(void); +CF_PRIVATE void __CFSocketCleanup(void); +CF_PRIVATE void __CFUniCharCleanup(void); +CF_PRIVATE void __CFStreamCleanup(void); static CFBundleRef RegisterCoreFoundationBundle(void) { #ifdef _DEBUG @@ -1345,13 +1315,17 @@ static CFTypeRef _CFRetain(CFTypeRef cf, Boolean tryR) { // Never called under GC, only called via ARR weak subsystem; a return of NULL is failure CFTypeRef _CFTryRetain(CFTypeRef cf) { if (NULL == cf) return NULL; - if (CF_IS_TAGGED_OBJ(cf)) return cf; // success +#if OBJC_HAVE_TAGGED_POINTERS + if (_objc_isTaggedPointer(cf)) return cf; // success +#endif return _CFRetain(cf, true); } Boolean _CFIsDeallocating(CFTypeRef cf) { if (NULL == cf) return false; - if (CF_IS_TAGGED_OBJ(cf)) return false; +#if OBJC_HAVE_TAGGED_POINTERS + if (_objc_isTaggedPointer(cf)) return false; +#endif uint32_t cfinfo = *(uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo); if (cfinfo & 0x800000) { // custom ref counting for object return true; // lie for now; this weak references to these objects cannot be formed diff --git a/CFRuntime.h b/CFRuntime.h index 4ee6137..3e23515 100644 --- a/CFRuntime.h +++ b/CFRuntime.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFRuntime.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFRUNTIME__) @@ -40,54 +40,18 @@ CF_EXTERN_C_BEGIN CF_EXPORT bool kCFUseCollectableAllocator; CF_EXPORT bool (*__CFObjCIsCollectable)(void *); -// Only CoreFoundation and Foundation should use these *GCRefZero constants; -// do not listen to anyone who tells you otherwise. - -CF_EXPORT -const CFAllocatorRef kCFAllocatorSystemDefaultGCRefZero; // DO NOT USE THIS -CF_EXPORT -const CFAllocatorRef kCFAllocatorDefaultGCRefZero; // DO NOT USE THIS - -CF_INLINE CFAllocatorRef _CFConvertAllocatorToNonGCRefZeroEquivalent(CFAllocatorRef allocator) { - if (kCFAllocatorSystemDefaultGCRefZero == allocator) { - allocator = kCFAllocatorSystemDefault; - } else if (kCFAllocatorDefaultGCRefZero == allocator || NULL == allocator || kCFAllocatorDefault == allocator) { - allocator = CFAllocatorGetDefault(); - } - return allocator; -} - -CF_INLINE CFAllocatorRef _CFConvertAllocatorToGCRefZeroEquivalent(CFAllocatorRef allocator) { // DO NOT USE THIS - if (!kCFUseCollectableAllocator) return allocator; - if (kCFAllocatorDefault == allocator || NULL == allocator) { - allocator = CFAllocatorGetDefault(); - } - if (kCFAllocatorSystemDefault == allocator) { - allocator = kCFAllocatorSystemDefaultGCRefZero; - } else if (CFAllocatorGetDefault() == allocator) { - allocator = kCFAllocatorDefaultGCRefZero; - } - return allocator; -} - CF_INLINE Boolean _CFAllocatorIsSystemDefault(CFAllocatorRef allocator) { - if (allocator == kCFAllocatorSystemDefaultGCRefZero || allocator == kCFAllocatorSystemDefault) return true; - if (kCFAllocatorDefaultGCRefZero == allocator || NULL == allocator || kCFAllocatorDefault == allocator) { + if (allocator == kCFAllocatorSystemDefault) return true; + if (NULL == allocator || kCFAllocatorDefault == allocator) { return (kCFAllocatorSystemDefault == CFAllocatorGetDefault()); } return false; } -CF_INLINE Boolean _CFAllocatorIsGCRefZero(CFAllocatorRef allocator) { - // not intended as a literal test, but as a behavioral test - if (!kCFUseCollectableAllocator) return false; - return (kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator); -} - // is GC on? #define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator) // is GC on and is this the GC allocator? -#define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (kCFUseCollectableAllocator && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator) || _CFAllocatorIsGCRefZero(allocator))) +#define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (kCFUseCollectableAllocator && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator) || 0)) // is this allocated by the collector? #define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false) @@ -95,11 +59,6 @@ CF_INLINE Boolean _CFAllocatorIsGCRefZero(CFAllocatorRef allocator) { #define kCFUseCollectableAllocator 0 #define __CFObjCIsCollectable 0 -#define kCFAllocatorSystemDefaultGCRefZero kCFAllocatorSystemDefault -#define kCFAllocatorDefaultGCRefZero kCFAllocatorDefault - -#define _CFConvertAllocatorToNonGCRefZeroEquivalent(A) (A) -#define _CFConvertAllocatorToGCRefZeroEquivalent(A) (A) CF_INLINE Boolean _CFAllocatorIsSystemDefault(CFAllocatorRef allocator) { if (allocator == kCFAllocatorSystemDefault) return true; @@ -109,7 +68,6 @@ CF_INLINE Boolean _CFAllocatorIsSystemDefault(CFAllocatorRef allocator) { return false; } -#define _CFAllocatorIsGCRefZero(A) (0) #define CF_USING_COLLECTABLE_MEMORY 0 #define CF_IS_COLLECTABLE_ALLOCATOR(allocator) 0 #define CF_IS_COLLECTABLE(obj) 0 diff --git a/CFSet.c b/CFSet.c index 775b4e8..fff082a 100644 --- a/CFSet.c +++ b/CFSet.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSet.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane Machine generated from Notes/HashingCode.template */ @@ -47,7 +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}; -__private_extern__ const CFSetValueCallBacks kCFTypeSetValueCompactableCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual}; static const CFSetKeyCallBacks __kCFNullSetKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL}; static const CFSetValueCallBacks __kCFNullSetValueCallBacks = {0, NULL, NULL, NULL, NULL}; @@ -133,328 +132,131 @@ CFTypeID CFSetGetTypeID(void) { return __kCFSetTypeID; } -#define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B) -#define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B) - -static uintptr_t __CFSetStandardRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0100) return stack_value; - return (CFBasicHashHasStrongValues(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_value) : (uintptr_t)CFRetain((CFTypeRef)stack_value); -} - -static uintptr_t __CFSetStandardRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0001) return stack_key; - return (CFBasicHashHasStrongKeys(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_key) : (uintptr_t)CFRetain((CFTypeRef)stack_key); -} - -static void __CFSetStandardReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0200) return; - if (CFBasicHashHasStrongValues(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_value); else CFRelease((CFTypeRef)stack_value); -} - -static void __CFSetStandardReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0002) return; - if (CFBasicHashHasStrongKeys(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_key); else CFRelease((CFTypeRef)stack_key); -} - -static Boolean __CFSetStandardEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - if (CFBasicHashGetSpecialBits(ht) & 0x0400) return coll_value1 == stack_value2; - return CFEqual((CFTypeRef)coll_value1, (CFTypeRef)stack_value2); -} - -static Boolean __CFSetStandardEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - if (CFBasicHashGetSpecialBits(ht) & 0x0004) return coll_key1 == stack_key2; - return CFEqual((CFTypeRef)coll_key1, (CFTypeRef)stack_key2); -} - -static uintptr_t __CFSetStandardHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0008) return stack_key; - return (uintptr_t)CFHash((CFTypeRef)stack_key); -} - -static uintptr_t __CFSetStandardGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFSetStandardCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - if (CFBasicHashGetSpecialBits(ht) & 0x0800) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value); - return CFCopyDescription((CFTypeRef)stack_value); -} - -static CFStringRef __CFSetStandardCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - if (CFBasicHashGetSpecialBits(ht) & 0x0010) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key); - return CFCopyDescription((CFTypeRef)stack_key); -} - -static CFBasicHashCallbacks *__CFSetStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); -static void __CFSetStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb); - -static const CFBasicHashCallbacks CFSetStandardCallbacks = { - __CFSetStandardCopyCallbacks, - __CFSetStandardFreeCallbacks, - __CFSetStandardRetainValue, - __CFSetStandardRetainKey, - __CFSetStandardReleaseValue, - __CFSetStandardReleaseKey, - __CFSetStandardEquateValues, - __CFSetStandardEquateKeys, - __CFSetStandardHashKey, - __CFSetStandardGetIndirectKey, - __CFSetStandardCopyValueDescription, - __CFSetStandardCopyKeyDescription -}; - -static CFBasicHashCallbacks *__CFSetStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - return (CFBasicHashCallbacks *)&CFSetStandardCallbacks; -} - -static void __CFSetStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { -} - - -static CFBasicHashCallbacks *__CFSetCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - CFBasicHashCallbacks *newcb = NULL; - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); - } else { - newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); - } - if (!newcb) return NULL; - memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *)); - return newcb; -} - -static void __CFSetFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) { - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - } else { - CFAllocatorDeallocate(allocator, cb); - } -} - -static uintptr_t __CFSetRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0]; - if (NULL == value_retain) return stack_value; - return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_value); -} - -static uintptr_t __CFSetRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1]; - if (NULL == key_retain) return stack_key; - return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_key); -} - -static void __CFSetReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2]; - if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t) stack_value); -} - -static void __CFSetReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3]; - if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t) stack_key); -} - -static Boolean __CFSetEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4]; - if (NULL == value_equal) return (coll_value1 == stack_value2); - return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t) coll_value1, (const_any_pointer_t) stack_value2) ? 1 : 0; -} - -static Boolean __CFSetEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5]; - if (NULL == key_equal) return (coll_key1 == stack_key2); - return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t) coll_key1, (const_any_pointer_t) stack_key2) ? 1 : 0; -} - -static uintptr_t __CFSetHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6]; - if (NULL == hash) return stack_key; - return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t) stack_key); -} - -static uintptr_t __CFSetGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) { - return 0; -} - -static CFStringRef __CFSetCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8]; - if (NULL == value_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_value); - return (CFStringRef)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t) stack_value); -} - -static CFStringRef __CFSetCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) { - const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht); - CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[9]; - if (NULL == key_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_key); - return (CFStringRef)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t) stack_key); -} static CFBasicHashRef __CFSetCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) { CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); - CFBasicHashCallbacks *cb = NULL; - Boolean std_cb = false; - uint16_t specialBits = 0; - const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; - void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL; - const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; - void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL; - - if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) { - Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain; - Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release; - Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal; - Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash; - Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription; - - Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull); - Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull); - Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull); - Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull); - - Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain; - Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release; - Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal; - Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash; - Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription; - - Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd); - Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd); - Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd); - Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd); - - if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) { - cb = (CFBasicHashCallbacks *)&CFSetStandardCallbacks; - if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) { - std_cb = true; + if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { // all this crap is just for figuring out two flags for GC in the way done historically; it probably simplifies down to three lines, but we let the compiler worry about that + Boolean set_cb = false; + Boolean std_cb = false; + const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; + void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL; + const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL; + void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL; + + if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) { + Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain; + Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release; + Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal; + Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash; + Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription; + + Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull); + Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull); + Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull); + Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull); + + Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain; + Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release; + Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal; + Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash; + Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription; + + Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd); + Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd); + Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd); + Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd); + + if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) { + set_cb = true; + if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) { + std_cb = true; + } else { + // just set these to tickle the GC Strong logic below in a way that mimics past practice + key_retain = keyCallBacks ? keyCallBacks->retain : NULL; + key_release = keyCallBacks ? keyCallBacks->release : NULL; + if (useValueCB) { + value_retain = valueCallBacks ? valueCallBacks->retain : NULL; + value_release = valueCallBacks ? valueCallBacks->release : NULL; + } else { + value_retain = key_retain; + value_release = key_release; + } + } + } + } + + if (!set_cb) { + key_retain = keyCallBacks ? keyCallBacks->retain : NULL; + key_release = keyCallBacks ? keyCallBacks->release : NULL; + if (useValueCB) { + value_retain = valueCallBacks ? valueCallBacks->retain : NULL; + value_release = valueCallBacks ? valueCallBacks->release : NULL; } else { - // just set these to tickle the GC Strong logic below in a way that mimics past practice - key_retain = keyCallBacks ? keyCallBacks->retain : NULL; - key_release = keyCallBacks ? keyCallBacks->release : NULL; - if (useValueCB) { - value_retain = valueCallBacks ? valueCallBacks->retain : NULL; - value_release = valueCallBacks ? valueCallBacks->release : NULL; - } else { - value_retain = key_retain; - value_release = key_release; - } + value_retain = key_retain; + value_release = key_release; } - if (keyRetainNull) specialBits |= 0x0001; - if (keyReleaseNull) specialBits |= 0x0002; - if (keyEquateNull) specialBits |= 0x0004; - if (keyHashNull) specialBits |= 0x0008; - if (keyDescribeNull) specialBits |= 0x0010; - if (valueRetainNull) specialBits |= 0x0100; - if (valueReleaseNull) specialBits |= 0x0200; - if (valueEquateNull) specialBits |= 0x0400; - if (valueDescribeNull) specialBits |= 0x0800; - } - } - - if (!cb) { - Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL; - Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL; - CFStringRef (*key_describe)(const_any_pointer_t) = NULL; - CFStringRef (*value_describe)(const_any_pointer_t) = NULL; - CFHashCode (*hash_key)(const_any_pointer_t) = NULL; - key_retain = keyCallBacks ? keyCallBacks->retain : NULL; - key_release = keyCallBacks ? keyCallBacks->release : NULL; - key_equal = keyCallBacks ? keyCallBacks->equal : NULL; - key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL; - if (useValueCB) { - value_retain = valueCallBacks ? valueCallBacks->retain : NULL; - value_release = valueCallBacks ? valueCallBacks->release : NULL; - value_equal = valueCallBacks ? valueCallBacks->equal : NULL; - value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL; - } else { - value_retain = key_retain; - value_release = key_release; - value_equal = key_equal; - value_describe = key_describe; - } - hash_key = keyCallBacks ? keyCallBacks->hash : NULL; - - CFBasicHashCallbacks *newcb = NULL; - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { - newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false); - } else { - newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0); } - if (!newcb) return NULL; - newcb->copyCallbacks = __CFSetCopyCallbacks; - newcb->freeCallbacks = __CFSetFreeCallbacks; - newcb->retainValue = __CFSetRetainValue; - newcb->retainKey = __CFSetRetainKey; - newcb->releaseValue = __CFSetReleaseValue; - newcb->releaseKey = __CFSetReleaseKey; - newcb->equateValues = __CFSetEquateValues; - newcb->equateKeys = __CFSetEquateKeys; - newcb->hashKey = __CFSetHashKey; - newcb->getIndirectKey = __CFSetGetIndirectKey; - newcb->copyValueDescription = __CFSetCopyValueDescription; - newcb->copyKeyDescription = __CFSetCopyKeyDescription; - newcb->context[0] = (uintptr_t)value_retain; - newcb->context[1] = (uintptr_t)key_retain; - newcb->context[2] = (uintptr_t)value_release; - newcb->context[3] = (uintptr_t)key_release; - newcb->context[4] = (uintptr_t)value_equal; - newcb->context[5] = (uintptr_t)key_equal; - newcb->context[6] = (uintptr_t)hash_key; - newcb->context[8] = (uintptr_t)value_describe; - newcb->context[9] = (uintptr_t)key_describe; - cb = newcb; - } - if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) { if (std_cb || value_retain != NULL || value_release != NULL) { flags |= kCFBasicHashStrongValues; } if (std_cb || key_retain != NULL || key_release != NULL) { flags |= kCFBasicHashStrongKeys; } -#if CFDictionary - if (valueCallBacks == &kCFTypeDictionaryValueCompactableCallBacks) { - // Foundation allocated collections will have compactable values - flags |= kCFBasicHashCompactableValues; - } -#endif } - CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); - if (ht) CFBasicHashSetSpecialBits(ht, specialBits); - if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb); + + CFBasicHashCallbacks callbacks; + callbacks.retainKey = keyCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))keyCallBacks->retain : NULL; + callbacks.releaseKey = keyCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))keyCallBacks->release : NULL; + callbacks.equateKeys = keyCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))keyCallBacks->equal : NULL; + callbacks.hashKey = keyCallBacks ? (CFHashCode (*)(uintptr_t))keyCallBacks->hash : NULL; + callbacks.getIndirectKey = NULL; + callbacks.copyKeyDescription = keyCallBacks ? (CFStringRef (*)(uintptr_t))keyCallBacks->copyDescription : NULL; + callbacks.retainValue = useValueCB ? (valueCallBacks ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))valueCallBacks->retain : NULL) : (callbacks.retainKey); + callbacks.releaseValue = useValueCB ? (valueCallBacks ? (void (*)(CFAllocatorRef, uintptr_t))valueCallBacks->release : NULL) : (callbacks.releaseKey); + callbacks.equateValues = useValueCB ? (valueCallBacks ? (Boolean (*)(uintptr_t, uintptr_t))valueCallBacks->equal : NULL) : (callbacks.equateKeys); + callbacks.copyValueDescription = useValueCB ? (valueCallBacks ? (CFStringRef (*)(uintptr_t))valueCallBacks->copyDescription : NULL) : (callbacks.copyKeyDescription); + + CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); return ht; } #if CFDictionary -__private_extern__ CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { +CF_PRIVATE CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) { #endif #if CFSet || CFBag -__private_extern__ CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { +CF_PRIVATE CFHashRef __CFSetCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) { const_any_pointer_t *vlist = klist; #endif CFTypeID typeID = CFSetGetTypeID(); CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues); CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0); - CFBasicHashCallbacks *cb = (CFBasicHashCallbacks *)&CFSetStandardCallbacks; - CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb); - CFBasicHashSetSpecialBits(ht, 0x0303); + + CFBasicHashCallbacks callbacks; + callbacks.retainKey = (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeSetKeyCallBacks.retain; + callbacks.releaseKey = (void (*)(CFAllocatorRef, uintptr_t))kCFTypeSetKeyCallBacks.release; + callbacks.equateKeys = (Boolean (*)(uintptr_t, uintptr_t))kCFTypeSetKeyCallBacks.equal; + callbacks.hashKey = (CFHashCode (*)(uintptr_t))kCFTypeSetKeyCallBacks.hash; + callbacks.getIndirectKey = NULL; + callbacks.copyKeyDescription = (CFStringRef (*)(uintptr_t))kCFTypeSetKeyCallBacks.copyDescription; + callbacks.retainValue = CFDictionary ? (uintptr_t (*)(CFAllocatorRef, uintptr_t))kCFTypeSetValueCallBacks.retain : callbacks.retainKey; + callbacks.releaseValue = CFDictionary ? (void (*)(CFAllocatorRef, uintptr_t))kCFTypeSetValueCallBacks.release : callbacks.releaseKey; + callbacks.equateValues = CFDictionary ? (Boolean (*)(uintptr_t, uintptr_t))kCFTypeSetValueCallBacks.equal : callbacks.equateKeys; + callbacks.copyValueDescription = CFDictionary ? (CFStringRef (*)(uintptr_t))kCFTypeSetValueCallBacks.copyDescription : callbacks.copyKeyDescription; + + CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, &callbacks); + CFBasicHashSuppressRC(ht); if (0 < numValues) CFBasicHashSetCapacity(ht, numValues); for (CFIndex idx = 0; idx < numValues; idx++) { CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); } - CFBasicHashSetSpecialBits(ht, 0x0000); + CFBasicHashUnsuppressRC(ht); CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)"); return (CFHashRef)ht; } @@ -476,8 +278,7 @@ CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIn CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]); } CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)"); return (CFHashRef)ht; } @@ -493,8 +294,7 @@ CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity); CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary); if (!ht) return NULL; - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)"); return (CFMutableHashRef)ht; } @@ -528,8 +328,7 @@ CFHashRef CFSetCreateCopy(CFAllocatorRef allocator, CFHashRef other) { } if (!ht) return NULL; CFBasicHashMakeImmutable(ht); - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)"); return (CFHashRef)ht; } @@ -563,8 +362,7 @@ CFMutableHashRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capaci ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other); } if (!ht) return NULL; - *(uintptr_t *)ht = __CFISAForTypeID(typeID); - _CFRuntimeSetInstanceTypeID(ht, typeID); + _CFRuntimeSetInstanceTypeIDAndIsa(ht, typeID); if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)"); return (CFMutableHashRef)ht; } @@ -781,7 +579,7 @@ 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, (NSSet *)hc, replaceObject:(id)key); + if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key); __CFGenericValidateType(hc, __kCFSetTypeID); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) { @@ -799,7 +597,7 @@ 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 (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); CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc); diff --git a/CFSet.h b/CFSet.h index 0ee1ce8..538d9dc 100644 --- a/CFSet.h +++ b/CFSet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSet.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /*! @header CFSet diff --git a/CFSocket.c b/CFSocket.c index f07069a..3bce445 100644 --- a/CFSocket.c +++ b/CFSocket.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSocket.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -983,7 +983,7 @@ typedef int32_t fd_mask; typedef int socklen_t; #define gettimeofday _NS_gettimeofday -__private_extern__ int _NS_gettimeofday(struct timeval *tv, struct timezone *tz); +CF_PRIVATE int _NS_gettimeofday(struct timeval *tv, struct timezone *tz); // although this is only used for debug info, we define it for compatibility #define timersub(tvp, uvp, vvp) \ @@ -1330,7 +1330,7 @@ CF_EXPORT void __CFSocketInitializeWinSock(void) { __CFSpinUnlock(&__CFActiveSocketsLock); } -__private_extern__ void __CFSocketCleanup(void) { +CF_PRIVATE void __CFSocketCleanup(void) { if (INVALID_SOCKET != __CFWakeupSocketPair[0]) { closesocket(__CFWakeupSocketPair[0]); __CFWakeupSocketPair[0] = INVALID_SOCKET; @@ -1583,8 +1583,8 @@ static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout) #if defined(LOG_CFSOCKET) fprintf(stdout, "TIMEOUT RECEIVED - WILL SIGNAL IMMEDIATELY TO FLUSH (%ld buffered)\n", s->_bytesToBufferPos); #endif - /* we've got a timeout, but no bytes read. Ignore the timeout. */ - if (s->_bytesToBufferPos == 0) { + /* we've got a timeout, but no bytes read, and we don't have any bytes to send. Ignore the timeout. */ + if (s->_bytesToBufferPos == 0 && s->_leftoverBytes == NULL) { #if defined(LOG_CFSOCKET) fprintf(stdout, "TIMEOUT - but no bytes, restoring to active set\n"); fflush(stdout); @@ -1913,6 +1913,81 @@ static void __CFSocketWriteSocketList(CFArrayRef sockets, CFDataRef fdSet, Boole } #endif +static void +clearInvalidFileDescriptors(CFMutableDataRef d) +{ + if (d) { + SInt32 count = __CFSocketFdGetSize(d); + fd_set* s = (fd_set*) CFDataGetMutableBytePtr(d); + for (SInt32 idx = 0; idx < count; idx++) { + if (FD_ISSET(idx, s)) + if (! __CFNativeSocketIsValid(idx)) { + FD_CLR(idx, s); + } + } + } +} + +static void +manageSelectError() +{ + SInt32 selectError = __CFSocketLastError(); +#if defined(LOG_CFSOCKET) + fprintf(stdout, "socket manager received error %ld from select\n", (long)selectError); +#endif + if (EBADF == selectError) { + CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); + + __CFSpinLock(&__CFActiveSocketsLock); + CFIndex cnt = CFArrayGetCount(__CFWriteSockets); + CFIndex idx; + for (idx = 0; idx < cnt; idx++) { + CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx); + if (!__CFNativeSocketIsValid(s->_socket)) { +#if defined(LOG_CFSOCKET) + fprintf(stdout, "socket manager found write socket %d invalid\n", s->_socket); +#endif + CFArrayAppendValue(invalidSockets, s); + } + } + cnt = CFArrayGetCount(__CFReadSockets); + for (idx = 0; idx < cnt; idx++) { + CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx); + if (!__CFNativeSocketIsValid(s->_socket)) { +#if defined(LOG_CFSOCKET) + fprintf(stdout, "socket manager found read socket %d invalid\n", s->_socket); +#endif + CFArrayAppendValue(invalidSockets, s); + } + } + + + cnt = CFArrayGetCount(invalidSockets); + + /* Note that we're doing this only when we got EBADF but otherwise + * don't have an explicit bad descriptor. Note that the lock is held now. + * Finally, note that cnt == 0 doesn't necessarily mean + * that this loop will do anything, since fd's may have been invalidated + * while we were in select. + */ + if (cnt == 0) { +#if defined(LOG_CFSOCKET) + fprintf(stdout, "socket manager received EBADF(1): No sockets were marked as invalid, cleaning out fdsets\n"); +#endif + + clearInvalidFileDescriptors(__CFReadSocketsFds); + clearInvalidFileDescriptors(__CFWriteSocketsFds); + } + + __CFSpinUnlock(&__CFActiveSocketsLock); + + for (idx = 0; idx < cnt; idx++) { + CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx))); + } + CFRelease(invalidSockets); + } +} + #ifdef __GNUC__ __attribute__ ((noreturn)) // mostly interesting for shutting up a warning #endif /* __GNUC__ */ @@ -2047,42 +2122,8 @@ static void __CFSocketManager(void * arg) /* and below, we dispatch through the normal read dispatch mechanism */ } - if (0 > nrfds) { - SInt32 selectError = __CFSocketLastError(); -#if defined(LOG_CFSOCKET) - fprintf(stdout, "socket manager received error %ld from select\n", (long)selectError); -#endif - if (EBADF == selectError) { - CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks); - __CFSpinLock(&__CFActiveSocketsLock); - cnt = CFArrayGetCount(__CFWriteSockets); - for (idx = 0; idx < cnt; idx++) { - CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx); - if (!__CFNativeSocketIsValid(s->_socket)) { -#if defined(LOG_CFSOCKET) - fprintf(stdout, "socket manager found write socket %d invalid\n", s->_socket); -#endif - CFArrayAppendValue(invalidSockets, s); - } - } - cnt = CFArrayGetCount(__CFReadSockets); - for (idx = 0; idx < cnt; idx++) { - CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx); - if (!__CFNativeSocketIsValid(s->_socket)) { -#if defined(LOG_CFSOCKET) - fprintf(stdout, "socket manager found read socket %d invalid\n", s->_socket); -#endif - CFArrayAppendValue(invalidSockets, s); - } - } - __CFSpinUnlock(&__CFActiveSocketsLock); - - cnt = CFArrayGetCount(invalidSockets); - for (idx = 0; idx < cnt; idx++) { - CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx))); - } - CFRelease(invalidSockets); - } + if (0 > nrfds) { + manageSelectError(); continue; } if (FD_ISSET(__CFWakeupSocketPair[1], readfds)) { @@ -2171,7 +2212,7 @@ static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) { // don't bother trying to figure out callout names const char *name = ""; #endif - CFStringAppendFormat(result, NULL, CFSTR("{valid = %s, type = %d, socket = %d, socket set count = %ld,\n callback types = 0x%x, callout = %s (%p), source = %p,\n run loops = %@,\n context = "), cf, CFGetAllocator(s), (__CFSocketIsValid(s) ? "Yes" : "No"), s->_socketType, s->_socket, s->_socketSetCount, __CFSocketCallBackTypes(s), name, addr, s->_source0, s->_runLoops); + CFStringAppendFormat(result, NULL, CFSTR("{valid = %s, type = %d, socket = %d, socket set count = %ld,\n callback types = 0x%x, callout = %s (%p), source = %p,\n run loops = %@,\n context = "), cf, CFGetAllocator(s), (__CFSocketIsValid(s) ? "Yes" : "No"), (int)(s->_socketType), s->_socket, (long)s->_socketSetCount, __CFSocketCallBackTypes(s), name, addr, s->_source0, s->_runLoops); contextInfo = s->_context.info; contextCopyDescription = s->_context.copyDescription; __CFSocketUnlock(s); @@ -3018,7 +3059,7 @@ CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeI #endif } #if defined(LOG_CFSOCKET) - fprintf(stdout, "connection attempt returns %d error %d on socket %d (flags 0x%x blocking %d)\n", result, connect_err, sock, flags, wasBlocking); + fprintf(stdout, "connection attempt returns %d error %d on socket %d (flags 0x%x blocking %d)\n", (int) result, (int) connect_err, sock, (int) flags, wasBlocking); #endif if (EINPROGRESS == connect_err && timeout >= 0.0) { /* select on socket */ @@ -3041,7 +3082,7 @@ CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeI } CFRelease(fds); #if defined(LOG_CFSOCKET) - fprintf(stdout, "timed connection attempt %s on socket %d, result %d, select returns %d error %d\n", (result == 0) ? "succeeds" : "fails", sock, result, nrfds, select_err); + fprintf(stdout, "timed connection attempt %s on socket %d, result %d, select returns %d error %d\n", (result == 0) ? "succeeds" : "fails", sock, (int) result, (int) nrfds, (int) select_err); #endif } if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, (u_long *)&no); diff --git a/CFSocket.h b/CFSocket.h index 80ddad9..b8d0803 100644 --- a/CFSocket.h +++ b/CFSocket.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSocket.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSOCKET__) diff --git a/CFSocketStream.c b/CFSocketStream.c index bb9ca57..662858e 100644 --- a/CFSocketStream.c +++ b/CFSocketStream.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSocketStream.c - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. Responsibility: Jeremy Wyld */ // Original Author: Becky Willrich @@ -203,7 +203,7 @@ CF_EXPORT void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc, c createPair(alloc, NULL, 0, 0, sig, readStream, writeStream); } -__private_extern__ CFStreamError _CFStreamErrorFromError(CFErrorRef error) { +CF_PRIVATE CFStreamError _CFStreamErrorFromError(CFErrorRef error) { CFStreamError result; Boolean canUpCall; @@ -230,7 +230,7 @@ __private_extern__ CFStreamError _CFStreamErrorFromError(CFErrorRef error) { return result; } -__private_extern__ CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *streamError) { +CF_PRIVATE CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *streamError) { CFErrorRef result; Boolean canUpCall; diff --git a/CFSortFunctions.c b/CFSortFunctions.c index 40cdc94..5e5e74f 100644 --- a/CFSortFunctions.c +++ b/CFSortFunctions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSortFunctions.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ diff --git a/CFStorage.c b/CFStorage.c index 22652dd..7f6ceaa 100644 --- a/CFStorage.c +++ b/CFStorage.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStorage.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -976,7 +976,7 @@ static CFStringRef __CFStorageCopyDescription(CFTypeRef cf) { CFMutableStringRef result; CFAllocatorRef allocator = CFGetAllocator(storage); result = CFStringCreateMutable(allocator, 0); - CFStringAppendFormat(result, NULL, CFSTR("[count = %u, capacity = %u]\n"), storage, allocator, __CFStorageGetCount(storage), __CFStorageGetCapacity(storage)); + CFStringAppendFormat(result, NULL, CFSTR("[count = %lu, capacity = %lu]\n"), storage, allocator, (unsigned long)__CFStorageGetCount(storage), (unsigned long)__CFStorageGetCapacity(storage)); __CFStorageDescribeNode(&storage->rootNode, result, 0); return result; } @@ -1105,7 +1105,7 @@ static const CFRuntimeClass __CFStorageClass = { __CFStorageCopyDescription }; -__private_extern__ void __CFStorageInitialize(void) { +CF_PRIVATE void __CFStorageInitialize(void) { __kCFStorageTypeID = _CFRuntimeRegisterClass(&__CFStorageClass); } @@ -1471,7 +1471,7 @@ static void __CFStorageNodeSetUnscanned(CFStorageNode *node, auto_zone_t *zone) } } -__private_extern__ void _CFStorageSetWeak(CFStorageRef storage) { +CF_PRIVATE void _CFStorageSetWeak(CFStorageRef storage) { storage->nodeHint = 0; __CFStorageNodeSetUnscanned(&storage->rootNode, (auto_zone_t *)objc_collectableZone()); } diff --git a/CFStorage.h b/CFStorage.h index 7431f0b..eb455ba 100644 --- a/CFStorage.h +++ b/CFStorage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStorage.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ /*! @header CFStorage diff --git a/CFStream.c b/CFStream.c index b4c52fd..60f3242 100644 --- a/CFStream.c +++ b/CFStream.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStream.c - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. Responsibility: John Iarocci */ @@ -37,12 +37,23 @@ #include #endif - -struct CFStreamAux { - CFSpinLock_t streamLock; +struct _CFStream { + CFRuntimeBase _cfBase; + CFOptionFlags flags; + CFErrorRef error; // if callBacks->version < 2, this is actually a pointer to a CFStreamError + struct _CFStreamClient *client; + /* NOTE: CFNetwork is still using _CFStreamGetInfoPointer, and so this slot needs to stay in this position (as the fifth field in the structure) */ + /* NOTE: This can be taken out once CFNetwork rebuilds */ + /* NOTE: Remove comment once CFNetwork has been rebuilt */ + 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; CFArrayRef previousRunloopsAndModes; + dispatch_queue_t queue; }; + enum { MIN_STATUS_CODE_BIT = 0, // ..status bits... @@ -78,7 +89,7 @@ static CFTypeID __kCFWriteStreamTypeID = _kCFRuntimeNotATypeID; // Just reads the bits, for those cases where we don't want to go through any callback checking #define __CFStreamGetStatus(x) __CFBitfieldGetValue((x)->flags, MAX_STATUS_CODE_BIT, MIN_STATUS_CODE_BIT) -__private_extern__ CFStreamStatus _CFStreamGetStatus(struct _CFStream *stream); +CF_PRIVATE CFStreamStatus _CFStreamGetStatus(struct _CFStream *stream); static Boolean _CFStreamRemoveRunLoopAndModeFromArray(CFMutableArrayRef runLoopsAndModes, CFRunLoopRef rl, CFStringRef mode); static void _wakeUpRunLoop(struct _CFStream *stream); @@ -89,50 +100,30 @@ CF_INLINE void checkRLMArray(CFArrayRef arr) #endif } -CF_INLINE void* _CFStreamCreateReserved(CFAllocatorRef alloc) { - struct CFStreamAux* aux = (struct CFStreamAux*) CFAllocatorAllocate(alloc, sizeof(struct CFStreamAux), 0); - if (aux) { - aux->streamLock = CFSpinLockInit; - aux->previousRunloopsAndModes = NULL; - } - return aux; -} - -CF_INLINE void _CFStreamDestroyReserved(CFAllocatorRef alloc, void* aux) { - struct CFStreamAux* paux = (struct CFStreamAux*) aux; - if (paux->previousRunloopsAndModes) - CFRelease(paux->previousRunloopsAndModes); - CFAllocatorDeallocate(alloc, aux); -} - -CF_INLINE struct CFStreamAux* _CFStreamGetAuxRecord(struct _CFStream* stream) { - return (struct CFStreamAux*) stream->_reserved1; -} - CF_INLINE void _CFStreamLock(struct _CFStream* stream) { - __CFSpinLock(&_CFStreamGetAuxRecord(stream)->streamLock); + __CFSpinLock(&stream->streamLock); } CF_INLINE void _CFStreamUnlock(struct _CFStream* stream) { - __CFSpinUnlock(&_CFStreamGetAuxRecord(stream)->streamLock); + __CFSpinUnlock(&stream->streamLock); } CF_INLINE CFRunLoopSourceRef _CFStreamCopySource(struct _CFStream* stream) { - CFRunLoopSourceRef source = NULL; - - if (stream) { - _CFStreamLock(stream); - - if (stream->client) - source = stream->client->rlSource; + CFRunLoopSourceRef source = NULL; - if (source) - CFRetain(source); - - _CFStreamUnlock(stream); - } - - return source; + if (stream) { + _CFStreamLock(stream); + + if (stream->client) + source = stream->client->rlSource; + + if (source) + CFRetain(source); + + _CFStreamUnlock(stream); + } + + return source; } CF_INLINE void _CFStreamSetSource(struct _CFStream* stream, CFRunLoopSourceRef source, Boolean invalidateOldSource) { @@ -266,23 +257,25 @@ static void _CFStreamDetachSource(struct _CFStream* stream) { } } -__private_extern__ void _CFStreamClose(struct _CFStream *stream) { +CF_PRIVATE void _CFStreamClose(struct _CFStream *stream) { CFStreamStatus status = _CFStreamGetStatus(stream); const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream); if (status == kCFStreamStatusNotOpen || status == kCFStreamStatusClosed || (status == kCFStreamStatusError && __CFBitIsSet(stream->flags, HAVE_CLOSED))) { // Stream is not open from the client's perspective; do not callout and do not update our status to "closed" return; } - __CFBitSet(stream->flags, HAVE_CLOSED); - __CFBitSet(stream->flags, CALLING_CLIENT); - if (cb->close) { - cb->close(stream, _CFStreamGetInfoPointer(stream)); - } - if (stream->client) { - _CFStreamDetachSource(stream); + if (! __CFBitIsSet(stream->flags, HAVE_CLOSED)) { + __CFBitSet(stream->flags, HAVE_CLOSED); + __CFBitSet(stream->flags, CALLING_CLIENT); + if (cb->close) { + cb->close(stream, _CFStreamGetInfoPointer(stream)); + } + if (stream->client) { + _CFStreamDetachSource(stream); + } + _CFStreamSetStatusCode(stream, kCFStreamStatusClosed); + __CFBitClear(stream->flags, CALLING_CLIENT); } - _CFStreamSetStatusCode(stream, kCFStreamStatusClosed); - __CFBitClear(stream->flags, CALLING_CLIENT); } //static int numStreamInstances = 0; @@ -302,7 +295,7 @@ static void __CFStreamDeallocate(CFTypeRef cf) { if (cbContext->info && cbContext->release) { cbContext->release(cbContext->info); } - _CFStreamDetachSource(stream); + if (stream->client->runLoopsAndModes) { CFRelease(stream->client->runLoopsAndModes); } @@ -327,8 +320,14 @@ static void __CFStreamDeallocate(CFTypeRef cf) { if (!__CFBitIsSet(stream->flags, CONSTANT_CALLBACKS)) { CFAllocatorDeallocate(alloc, (void *)stream->callBacks); } - if (stream->_reserved1) - _CFStreamDestroyReserved(alloc, stream->_reserved1); + if (stream->previousRunloopsAndModes) { + CFRelease(stream->previousRunloopsAndModes); + stream->previousRunloopsAndModes = NULL; + } + if (stream->queue) { + dispatch_release(stream->queue); + stream->queue = NULL; + } } static const CFRuntimeClass __CFReadStreamClass = { @@ -361,7 +360,7 @@ CONST_STRING_DECL(kCFStreamPropertySocketRemotePortNumber, "kCFStreamPropertySoc CONST_STRING_DECL(kCFStreamPropertyDataWritten, "kCFStreamPropertyDataWritten") CONST_STRING_DECL(kCFStreamPropertyAppendToFile, "kCFStreamPropertyAppendToFile") -__private_extern__ void __CFStreamInitialize(void) { +CF_PRIVATE void __CFStreamInitialize(void) { __kCFReadStreamTypeID = _CFRuntimeRegisterClass(&__CFReadStreamClass); __kCFWriteStreamTypeID = _CFRuntimeRegisterClass(&__CFWriteStreamClass); } @@ -386,12 +385,18 @@ static struct _CFStream *_CFStreamCreate(CFAllocatorRef allocator, Boolean isRea newStream->info = NULL; newStream->callBacks = NULL; - newStream->_reserved1 = _CFStreamCreateReserved(allocator); + newStream->streamLock = CFSpinLockInit; + newStream->previousRunloopsAndModes = NULL; + newStream->queue = NULL; } return newStream; } -__private_extern__ struct _CFStream *_CFStreamCreateWithConstantCallbacks(CFAllocatorRef alloc, void *info, const struct _CFStreamCallBacks *cb, Boolean isReading) { +CF_EXPORT void* _CFStreamGetInfoPointer(struct _CFStream* stream) { + return stream == NULL? NULL : stream->info; +} + +CF_PRIVATE struct _CFStream *_CFStreamCreateWithConstantCallbacks(CFAllocatorRef alloc, void *info, const struct _CFStreamCallBacks *cb, Boolean isReading) { struct _CFStream *newStream; if (cb->version != 1) return NULL; newStream = _CFStreamCreate(alloc, isReading); @@ -577,50 +582,80 @@ static void _signalEventSync(struct _CFStream* stream, CFOptionFlags whatToSigna __CFBitSet(stream->flags, CALLING_CLIENT); - void* info = NULL; - void (*release) (void*) = NULL; + _CFStreamLock(stream); - if (stream->client->cbContext.retain == NULL) - info = stream->client->cbContext.info; - else { - info = stream->client->cbContext.retain(stream->client->cbContext.info); - release = stream->client->cbContext.release; - } + struct _CFStreamClient* client = stream->client; + if (client == NULL) { + _CFStreamUnlock(stream); + } else { + void* info = NULL; + void (*release) (void*) = NULL; + void (*cb)(struct _CFStream *, CFStreamEventType, void *) = client == NULL? NULL : client->cb; - for (eventMask = 1; eventMask <= whatToSignal; eventMask = eventMask << 1) { - if ((eventMask & whatToSignal) && (stream->client->when & eventMask)) { - stream->client->cb(stream, eventMask, info); - - /* What happens if the callback sets the client to NULL? We're in a loop here... Hmm. */ - /* After writing that comment, I see: CFReadStreamSetClient(..., NULL) unsafely releases info pointer immediately */ - /* Of note, when the stream callbacks are set to to NULL, we're re-initalized so as not to receive more events, so we - * should break pout of this loop */ - } - } + if (stream->client->cbContext.retain == NULL) + info = stream->client->cbContext.info; + else { + info = stream->client->cbContext.retain(stream->client->cbContext.info); + release = stream->client->cbContext.release; + } + _CFStreamUnlock(stream); - if (release) - (*release) (info); + for (eventMask = 1; eventMask <= whatToSignal; eventMask = eventMask << 1) { + _CFStreamLock(stream); + Boolean shouldSignal = ((eventMask & whatToSignal) && stream->client && (stream->client->when & eventMask)); + _CFStreamUnlock(stream); + if (shouldSignal && client) { + cb(stream, eventMask, info); + + /* What happens if the callback sets the client to NULL? We're in a loop here... Hmm. */ + /* After writing that comment, I see: CFReadStreamSetClient(..., NULL) unsafely releases info pointer immediately */ + /* Of note, when the stream callbacks are set to to NULL, we're re-initalized so as not to receive more events, so we + * should break pout of this loop */ + } + } + + if (release) + (*release) (info); + } __CFBitClear(stream->flags, CALLING_CLIENT); } +static void _signalEventQueue(dispatch_queue_t q, struct _CFStream* stream, CFOptionFlags whatToSignal) +{ + CFRetain(stream); + dispatch_async(q, ^{ + _signalEventSync(stream, whatToSignal); + CFRelease(stream); + }); +} + static void _cfstream_solo_signalEventSync(void* info) { CFTypeID typeID = CFGetTypeID((CFTypeRef) info); if (typeID != CFReadStreamGetTypeID() && typeID != CFWriteStreamGetTypeID()) { - CFLog(__kCFLogAssertion, CFSTR("Expected an read or write stream for %p"), info); + CFLog(__kCFLogAssertion, CFSTR("Expected a read or write stream for %p"), info); #if defined(DEBUG) abort(); #endif } else { struct _CFStream* stream = (struct _CFStream*) info; + _CFStreamLock(stream); CFOptionFlags whatToSignal = stream->client->whatToSignal; stream->client->whatToSignal = 0; - + dispatch_queue_t queue = stream->queue; + if (queue) dispatch_retain(queue); + CFRetain(stream); + _CFStreamUnlock(stream); + /* Since the array version holds a retain, we do it here as well, as opposed to taking a second retain in the client callback */ - CFRetain(stream); - _signalEventSync(stream, whatToSignal); + if (queue == 0) + _signalEventSync(stream, whatToSignal); + else { + _signalEventQueue(queue, stream, whatToSignal); + dispatch_release(queue); + } CFRelease(stream); } } @@ -638,44 +673,52 @@ static void _cfstream_shared_signalEventSync(void* info) CFMutableArrayRef list = (CFMutableArrayRef) info; CFIndex c, i; CFOptionFlags whatToSignal = 0; + dispatch_queue_t queue = 0; struct _CFStream* stream = NULL; - + __CFSpinLock(&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... */ c = CFArrayGetCount(list); for (i = 0; i < c; i++) { struct _CFStream* s = (struct _CFStream*)CFArrayGetValueAtIndex(list, i); - + if (s->client->whatToSignal) { stream = s; CFRetain(stream); whatToSignal = stream->client->whatToSignal; s->client->whatToSignal = 0; + queue = stream->queue; + if (queue) dispatch_retain(queue); break; } } - + /* And then we also signal any other streams in this array so that we get them next go? */ for (; i < c; i++) { struct _CFStream* s = (struct _CFStream*)CFArrayGetValueAtIndex(list, i); if (s->client->whatToSignal) { - CFRunLoopSourceRef source = _CFStreamCopySource(s); - if (source) { - CFRunLoopSourceSignal(source); - CFRelease(source); - } - break; + CFRunLoopSourceRef source = _CFStreamCopySource(s); + if (source) { + CFRunLoopSourceSignal(source); + CFRelease(source); + } + break; } } - + __CFSpinUnlock(&sSourceLock); - + /* We're sitting here now, possibly with a stream that needs to be processed by the common routine */ if (stream) { - _signalEventSync(stream, whatToSignal); - + if (queue == 0) + _signalEventSync(stream, whatToSignal); + else { + _signalEventQueue(queue, stream, whatToSignal); + dispatch_release(queue); + } + /* Lose our extra retain */ CFRelease(stream); } @@ -688,15 +731,14 @@ static CFArrayRef _CFStreamGetRunLoopsAndModes(struct _CFStream *stream) CFArrayRef result = NULL; if (stream && stream->client) { _CFStreamLock(stream); - struct CFStreamAux* aux = _CFStreamGetAuxRecord(stream); - if (aux->previousRunloopsAndModes) { - CFRelease(aux->previousRunloopsAndModes); - aux->previousRunloopsAndModes = NULL; + if (stream->previousRunloopsAndModes) { + CFRelease(stream->previousRunloopsAndModes); + stream->previousRunloopsAndModes = NULL; } if (stream->client->runLoopsAndModes) { - aux->previousRunloopsAndModes = CFArrayCreateCopy(CFGetAllocator(stream), stream->client->runLoopsAndModes); + stream->previousRunloopsAndModes = CFArrayCreateCopy(CFGetAllocator(stream), stream->client->runLoopsAndModes); } - result = aux->previousRunloopsAndModes; + result = stream->previousRunloopsAndModes; checkRLMArray(result); _CFStreamUnlock(stream); } @@ -754,7 +796,7 @@ static void _wakeUpRunLoop(struct _CFStream *stream) { } } -__private_extern__ void _CFStreamSignalEvent(struct _CFStream *stream, CFStreamEventType event, CFErrorRef error, Boolean synchronousAllowed) { +CF_PRIVATE void _CFStreamSignalEvent(struct _CFStream *stream, CFStreamEventType event, CFErrorRef error, Boolean synchronousAllowed) { // Update our internal status; we must use the primitive __CFStreamGetStatus(), because CFStreamGetStatus() calls us, and we can end up in an infinite loop. CFStreamStatus status = __CFStreamGetStatus(stream); @@ -826,12 +868,12 @@ __private_extern__ void _CFStreamSignalEvent(struct _CFStream *stream, CFStreamE _wakeUpRunLoop(stream); } - CFRelease(source); + CFRelease(source); } } } -__private_extern__ CFStreamStatus _CFStreamGetStatus(struct _CFStream *stream) { +CF_PRIVATE CFStreamStatus _CFStreamGetStatus(struct _CFStream *stream) { CFStreamStatus status = __CFStreamGetStatus(stream); // Status code just represents the value when last we checked; if we were in the middle of doing work at that time, we need to find out if the work has completed, now. If we find out about a status change, we need to inform the client as well, so we call _CFStreamSignalEvent. This will take care of updating our internal status correctly, too. __CFBitSet(stream->flags, CALLING_CLIENT); @@ -921,7 +963,7 @@ CF_EXPORT CFErrorRef CFWriteStreamCopyError(CFWriteStreamRef stream) { CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, CFErrorRef, (NSOutputStream *)stream, streamError); } -__private_extern__ Boolean _CFStreamOpen(struct _CFStream *stream) { +CF_PRIVATE Boolean _CFStreamOpen(struct _CFStream *stream) { const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream); Boolean success, openComplete; if (_CFStreamGetStatus(stream) != kCFStreamStatusNotOpen) { @@ -1190,7 +1232,7 @@ CF_EXPORT CFIndex CFWriteStreamWrite(CFWriteStreamRef writeStream, const UInt8 * } } -__private_extern__ CFTypeRef _CFStreamCopyProperty(struct _CFStream *stream, CFStringRef propertyName) { +CF_PRIVATE CFTypeRef _CFStreamCopyProperty(struct _CFStream *stream, CFStringRef propertyName) { const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream); if (cb->copyProperty == NULL) { return NULL; @@ -1213,7 +1255,7 @@ CF_EXPORT CFTypeRef CFWriteStreamCopyProperty(CFWriteStreamRef stream, CFStringR return _CFStreamCopyProperty((struct _CFStream *)stream, propertyName); } -__private_extern__ Boolean _CFStreamSetProperty(struct _CFStream *stream, CFStringRef prop, CFTypeRef val) { +CF_PRIVATE Boolean _CFStreamSetProperty(struct _CFStream *stream, CFStringRef prop, CFTypeRef val) { const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream); if (cb->setProperty == NULL) { return FALSE; @@ -1246,7 +1288,7 @@ static void _initializeClient(struct _CFStream *stream) { } /* If we add a setClient callback to the concrete stream callbacks, we must set/clear CALLING_CLIENT around it */ -__private_extern__ Boolean _CFStreamSetClient(struct _CFStream *stream, CFOptionFlags streamEvents, void (*clientCB)(struct _CFStream *, CFStreamEventType, void *), CFStreamClientContext *clientCallBackContext) { +CF_PRIVATE Boolean _CFStreamSetClient(struct _CFStream *stream, CFOptionFlags streamEvents, void (*clientCB)(struct _CFStream *, CFStreamEventType, void *), CFStreamClientContext *clientCallBackContext) { Boolean removingClient = (streamEvents == kCFStreamEventNone || clientCB == NULL || clientCallBackContext == NULL); @@ -1293,13 +1335,47 @@ __private_extern__ Boolean _CFStreamSetClient(struct _CFStream *stream, CFOption } CF_EXPORT Boolean CFReadStreamSetClient(CFReadStreamRef readStream, CFOptionFlags streamEvents, CFReadStreamClientCallBack clientCB, CFStreamClientContext *clientContext) { - CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, Boolean, (NSInputStream *)readStream, _setCFClientFlags:streamEvents callback:clientCB context:clientContext); +#if defined(CFSTREAM_SUPPORTS_BRIDGING) + if (CF_IS_OBJC(__kCFReadStreamTypeID, (const void *)(NSInputStream *)readStream)) { + NSInputStream* is = (NSInputStream*) readStream; + + if ([is respondsToSelector:@selector(_setCFClientFlags:callback:context:)]) + return [is _setCFClientFlags:streamEvents callback:clientCB context:clientContext]; + else { + if (clientCB == NULL) + [is setDelegate:nil]; + else { + _CFStreamDelegate* d = [[_CFStreamDelegate alloc] initWithStreamEvents:streamEvents callback:(void*) clientCB context:clientContext]; + [is setDelegate:d]; + } + return true; + } + } +#endif + streamEvents &= ~kCFStreamEventCanAcceptBytes; return _CFStreamSetClient((struct _CFStream *)readStream, streamEvents, (void (*)(struct _CFStream *, CFStreamEventType, void *))clientCB, clientContext); } CF_EXPORT Boolean CFWriteStreamSetClient(CFWriteStreamRef writeStream, CFOptionFlags streamEvents, CFWriteStreamClientCallBack clientCB, CFStreamClientContext *clientContext) { - CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, Boolean, (NSOutputStream *)writeStream, _setCFClientFlags:streamEvents callback:clientCB context:clientContext); +#if defined(CFSTREAM_SUPPORTS_BRIDGING) + if (CF_IS_OBJC(__kCFWriteStreamTypeID, (const void *)(NSInputStream *)writeStream)) { + NSOutputStream* os = (NSOutputStream*) writeStream; + + if ([os respondsToSelector:@selector(_setCFClientFlags:callback:context:)]) + return [os _setCFClientFlags:streamEvents callback:clientCB context:clientContext]; + else { + if (clientCB == NULL) + [os setDelegate:nil]; + else { + _CFStreamDelegate* d = [[_CFStreamDelegate alloc] initWithStreamEvents:streamEvents callback:(void*) clientCB context:clientContext]; + [os setDelegate:d]; + } + return true; + } + } +#endif + streamEvents &= ~kCFStreamEventHasBytesAvailable; return _CFStreamSetClient((struct _CFStream *)writeStream, streamEvents, (void (*)(struct _CFStream *, CFStreamEventType, void *))clientCB, clientContext); } @@ -1318,7 +1394,7 @@ CF_EXPORT void *_CFWriteStreamGetClient(CFWriteStreamRef writeStream) { } -__private_extern__ void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { +CF_PRIVATE void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream); if (! stream->client) { @@ -1478,17 +1554,37 @@ __private_extern__ void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, C } CF_EXPORT void CFReadStreamScheduleWithRunLoop(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { - CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, void, (NSInputStream *)stream, _scheduleInCFRunLoop:runLoop forMode:runLoopMode); +#if defined(CFSTREAM_SUPPORTS_BRIDGING) + if (CF_IS_OBJC(__kCFReadStreamTypeID, (const void *)(NSInputStream *)stream)) { + NSInputStream* is = (NSInputStream*) stream; + if ([is respondsToSelector:@selector(_scheduleInCFRunLoop:forMode:)]) + [is _scheduleInCFRunLoop:runLoop forMode:runLoopMode]; + else + [is scheduleInRunLoop:cfToNSRL(runLoop) forMode:(id) runLoopMode]; + return; + } +#endif + _CFStreamScheduleWithRunLoop((struct _CFStream *)stream, runLoop, runLoopMode); } CF_EXPORT void CFWriteStreamScheduleWithRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { - CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, void, (NSOutputStream *)stream, _scheduleInCFRunLoop:runLoop forMode:runLoopMode); +#if defined(CFSTREAM_SUPPORTS_BRIDGING) + if (CF_IS_OBJC(__kCFWriteStreamTypeID, (const void *)(NSOutputStream *)stream)) { + NSOutputStream* os = (NSOutputStream*) stream; + if ([os respondsToSelector:@selector(_scheduleInCFRunLoop:forMode:)]) + [os _scheduleInCFRunLoop:runLoop forMode:runLoopMode]; + else + [os scheduleInRunLoop:cfToNSRL(runLoop) forMode:(id) runLoopMode]; + return; + } +#endif + _CFStreamScheduleWithRunLoop((struct _CFStream *)stream, runLoop, runLoopMode); } -__private_extern__ void _CFStreamUnscheduleFromRunLoop(struct _CFStream *stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { +CF_PRIVATE void _CFStreamUnscheduleFromRunLoop(struct _CFStream *stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream); if (!stream->client) return; if (!stream->client->rlSource) return; @@ -1545,15 +1641,196 @@ __private_extern__ void _CFStreamUnscheduleFromRunLoop(struct _CFStream *stream, } CF_EXPORT void CFReadStreamUnscheduleFromRunLoop(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { - CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, void, (NSInputStream *)stream, _unscheduleFromCFRunLoop:runLoop forMode:runLoopMode); +#if defined(CFSTREAM_SUPPORTS_BRIDGING) + if (CF_IS_OBJC(__kCFReadStreamTypeID, (const void *)(NSInputStream *)stream)) { + NSInputStream* is = (NSInputStream*) stream; + if ([is respondsToSelector:@selector(_unscheduleFromCFRunLoop:forMode:)]) + [is _unscheduleFromCFRunLoop:runLoop forMode:runLoopMode]; + else + [is removeFromRunLoop:cfToNSRL(runLoop) forMode:(id) runLoopMode]; + return; + } +#endif + _CFStreamUnscheduleFromRunLoop((struct _CFStream *)stream, runLoop, runLoopMode); } void CFWriteStreamUnscheduleFromRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) { - CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, void, (NSOutputStream *)stream, _unscheduleFromCFRunLoop:runLoop forMode:runLoopMode); +#if defined(CFSTREAM_SUPPORTS_BRIDGING) + if (CF_IS_OBJC(__kCFWriteStreamTypeID, (const void *)(NSOutputStream *)stream)) { + NSOutputStream* os = (NSOutputStream*) stream; + if ([os respondsToSelector:@selector(_unscheduleFromCFRunLoop:forMode:)]) + [os _unscheduleFromCFRunLoop:runLoop forMode:runLoopMode]; + else + [os removeFromRunLoop:cfToNSRL(runLoop) forMode:(id) runLoopMode]; + return; + } +#endif + _CFStreamUnscheduleFromRunLoop((struct _CFStream *)stream, runLoop, runLoopMode); } +static CFRunLoopRef sLegacyRL = NULL; + +static void _perform(void* info) +{ +} + +static void* _legacyStreamRunLoop_workThread(void* arg) +{ + sLegacyRL = CFRunLoopGetCurrent(); + +#if defined(LOG_STREAM) + fprintf(stderr, "Creating Schedulingset emulation thread. Runloop: %p\n", sLegacyRL); +#endif + + CFStringRef s = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<< CFStreamLegacySource for Runloop %p >>"), sLegacyRL); + + CFRunLoopSourceContext ctxt = { + 0, + (void*) s, + CFRetain, + CFRelease, + CFCopyDescription, + CFEqual, + CFHash, + NULL, + NULL, + _perform + }; + + CFRunLoopSourceRef rls = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &ctxt); + CFRelease(s); + + CFRunLoopAddSource(sLegacyRL, rls, kCFRunLoopDefaultMode); + CFRelease(rls); + + dispatch_semaphore_signal(*(dispatch_semaphore_t*) arg); + arg = NULL; + + while (true) { + SInt32 why = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1E30, true); + + (void) why; +#if defined(LOG_STREAM) + switch (why) { + case kCFRunLoopRunFinished: + fprintf(stderr, "WOKE: kCFRunLoopRunFinished\n"); + break; + case kCFRunLoopRunStopped: + fprintf(stderr, "WOKE: kCFRunLoopRunStopped\n"); + break; + case kCFRunLoopRunTimedOut: + fprintf(stderr, "WOKE: kCFRunLoopRunTimedOut\n"); + break; + case kCFRunLoopRunHandledSource: + fprintf(stderr, "WOKE: kCFRunLoopRunHandledSource\n"); + break; + } +#endif + } + + return NULL; +} +static CFRunLoopRef _legacyStreamRunLoop() +{ + static dispatch_once_t sOnce = 0; + + dispatch_once(&sOnce, ^{ + + if (sLegacyRL == NULL) { + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_t workThread; + (void) pthread_create(&workThread, &attr, _legacyStreamRunLoop_workThread, &sem); + pthread_attr_destroy(&attr); + + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + dispatch_release(sem); + } + }); + + return sLegacyRL; +} + +static dispatch_queue_t _CFStreamCopyDispatchQueue(struct _CFStream* stream) +{ + dispatch_queue_t result = NULL; + + _CFStreamLock(stream); + if (stream->client) { + result = stream->queue; + if (result) + dispatch_retain(result); + } + _CFStreamUnlock(stream); + + return result; +} + +static void _CFStreamSetDispatchQueue(struct _CFStream* stream, dispatch_queue_t q) +{ + CFArrayRef rlm = _CFStreamCopyRunLoopsAndModes(stream); + if (rlm) { + CFIndex count = CFArrayGetCount(rlm); + for (CFIndex i = 0; i < count; i += 2) { + CFRunLoopRef rl = (CFRunLoopRef) CFArrayGetValueAtIndex(rlm, i); + CFStringRef mode = (CFStringRef) CFArrayGetValueAtIndex(rlm, i + 1); + _CFStreamUnscheduleFromRunLoop(stream, rl, mode); + } + CFRelease(rlm); + } + + if (q == NULL) { + _CFStreamLock(stream); + if (stream->client) { + if (stream->queue) + dispatch_release(stream->queue); + stream->queue = NULL; + } + _CFStreamUnlock(stream); + } else { + _CFStreamScheduleWithRunLoop(stream, _legacyStreamRunLoop(), kCFRunLoopDefaultMode); + + _CFStreamLock(stream); + if (stream->client) { + if (stream->queue != q) { + if (stream->queue) + dispatch_release(stream->queue); + stream->queue = q; + if (stream->queue) + dispatch_retain(stream->queue); + } + } + + _CFStreamUnlock(stream); + } +} + +void CFReadStreamSetDispatchQueue(CFReadStreamRef stream, dispatch_queue_t q) +{ + _CFStreamSetDispatchQueue((struct _CFStream*) stream, q); +} + +void CFWriteStreamSetDispatchQueue(CFWriteStreamRef stream, dispatch_queue_t q) +{ + _CFStreamSetDispatchQueue((struct _CFStream*) stream, q); +} + +dispatch_queue_t CFReadStreamCopyDispatchQueue(CFReadStreamRef stream) +{ + return _CFStreamCopyDispatchQueue((struct _CFStream*) stream); +} + +dispatch_queue_t CFWriteStreamCopyDispatchQueue(CFWriteStreamRef stream) +{ + return _CFStreamCopyDispatchQueue((struct _CFStream*) stream); +} + + static void waitForOpen(struct _CFStream *stream) { CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFStringRef privateMode = CFSTR("_kCFStreamBlockingOpenMode"); diff --git a/CFStream.h b/CFStream.h index 0bd5dff..4db4edf 100644 --- a/CFStream.h +++ b/CFStream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStream.h - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAM__) @@ -35,6 +35,7 @@ #include #include #include +#include CF_IMPLICIT_BRIDGING_ENABLED CF_EXTERN_C_BEGIN @@ -185,12 +186,12 @@ CF_EXPORT CFIndex CFReadStreamRead(CFReadStreamRef stream, UInt8 *buffer, CFIndex bufferLength); /* Returns a pointer to an internal buffer if possible (setting *numBytesRead - to the length of the returned buffer), otherwise returns NULL; guaranteed - to return in O(1). Bytes returned in the buffer are considered read from + to the length of the returned buffer), otherwise returns NULL; guaranteed + to return in O(1). Bytes returned in the buffer are considered read from the stream; if maxBytesToRead is greater than 0, not more than maxBytesToRead will be returned. If maxBytesToRead is less than or equal to zero, as many bytes - as are readily available will be returned. The returned buffer is good only - until the next stream operation called on the stream. Caller should neither + as are readily available will be returned. The returned buffer is good only + until the next stream operation called on the stream. Caller should neither change the contents of the returned buffer nor attempt to deallocate the buffer; it is still owned by the stream. */ CF_EXPORT @@ -232,12 +233,11 @@ Boolean CFWriteStreamSetProperty(CFWriteStreamRef stream, CFStringRef propertyNa /* Asynchronous processing - If you wish to neither poll nor block, you may register a client to hear about interesting events that occur on a stream. Only one client per stream is allowed; registering a new client replaces the previous one. - - Once you have set a client, you need to schedule a run loop on which that client - can be notified. You may schedule multiple run loops (for instance, if you are - using a thread pool). The client callback will be triggered via one of the scheduled - run loops; It is the caller's responsibility to ensure that at least one of the - scheduled run loops is being run. + + Once you have set a client, the stream must be scheduled to provide the context in + which the client will be called. Streams may be scheduled on a single dispatch queue + or on one or more run loops. If scheduled on a run loop, it is the caller's responsibility + to ensure that at least one of the scheduled run loops is being run. NOTE: Unlike other CoreFoundation APIs, pasing a NULL clientContext here will remove the client. If you do not care about the client context (i.e. your only concern @@ -261,6 +261,29 @@ void CFReadStreamUnscheduleFromRunLoop(CFReadStreamRef stream, CFRunLoopRef runL CF_EXPORT void CFWriteStreamUnscheduleFromRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode); +/* + * Specify the dispatch queue upon which the client callbacks will be invoked. + * Passing NULL for the queue will prevent future callbacks from being invoked. + * Specifying a dispatch queue using this API will unschedule the stream from + * any run loops it had previously been scheduled upon - similarly, scheduling + * with a runloop will disassociate the stream from any existing dispatch queue. + */ +CF_EXPORT +void CFReadStreamSetDispatchQueue(CFReadStreamRef stream, dispatch_queue_t q) CF_AVAILABLE(10_9, 7_0); + +CF_EXPORT +void CFWriteStreamSetDispatchQueue(CFWriteStreamRef stream, dispatch_queue_t q) CF_AVAILABLE(10_9, 7_0); + +/* + * Returns the previously set dispatch queue with an incremented retain count. + * Note that the stream's queue may have been set to NULL if the stream was + * scheduled on a runloop subsequent to it having had a dispatch queue set. + */ +CF_EXPORT +dispatch_queue_t CFReadStreamCopyDispatchQueue(CFReadStreamRef stream) CF_AVAILABLE(10_9, 7_0); + +CF_EXPORT +dispatch_queue_t CFWriteStreamCopyDispatchQueue(CFWriteStreamRef stream) CF_AVAILABLE(10_9, 7_0); /* The following API is deprecated starting in 10.5; please use CFRead/WriteStreamCopyError(), above, instead */ typedef CF_ENUM(CFIndex, CFStreamErrorDomain) { diff --git a/CFStreamAbstract.h b/CFStreamAbstract.h index ab4d070..f126887 100644 --- a/CFStreamAbstract.h +++ b/CFStreamAbstract.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStreamAbstract.h - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAMABSTRACT__) diff --git a/CFStreamInternal.h b/CFStreamInternal.h index 7d7f4ea..72cbe9d 100644 --- a/CFStreamInternal.h +++ b/CFStreamInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -64,8 +64,8 @@ struct _CFStreamCallBacksV1 { }; // These two are defined in CFSocketStream.c because that's where the glue for CFNetwork is. -__private_extern__ CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *err); -__private_extern__ CFStreamError _CFStreamErrorFromError(CFErrorRef error); +CF_PRIVATE CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *err); +CF_PRIVATE CFStreamError _CFStreamErrorFromError(CFErrorRef error); CF_EXTERN_C_END diff --git a/CFStreamPriv.h b/CFStreamPriv.h index 37ee6f0..15f9bec 100644 --- a/CFStreamPriv.h +++ b/CFStreamPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStreamPriv.h - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTREAMPRIV__) @@ -69,21 +69,9 @@ struct _CFStreamCallBacks { void (*unschedule)(struct _CFStream *stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void *info); }; -struct _CFStream { - CFRuntimeBase _cfBase; - CFOptionFlags flags; - CFErrorRef error; // if callBacks->version < 2, this is actually a pointer to a CFStreamError - struct _CFStreamClient *client; - void *info; - const struct _CFStreamCallBacks *callBacks; // This will not exist (will not be allocated) if the callbacks are from our known, "blessed" set. - void *_reserved1; -}; - - -CF_INLINE void *_CFStreamGetInfoPointer(struct _CFStream *stream) { - return stream->info; -} +struct _CFStream; +CF_EXPORT void* _CFStreamGetInfoPointer(struct _CFStream* stream); // cb version must be > 0 CF_EXPORT struct _CFStream *_CFStreamCreateWithConstantCallbacks(CFAllocatorRef alloc, void *info, const struct _CFStreamCallBacks *cb, Boolean isReading); diff --git a/CFString.c b/CFString.c index e59d7d7..a852643 100644 --- a/CFString.c +++ b/CFString.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFString.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, 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. @@ -64,7 +64,7 @@ #define INSTRUMENT_SHARED_STRINGS 0 #endif -__private_extern__ const CFStringRef __kCFLocaleCollatorID; +CF_PRIVATE const CFStringRef __kCFLocaleCollatorID; #if INSTRUMENT_SHARED_STRINGS #include /* for umask() */ @@ -112,7 +112,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, CFStringRef formatString, CFIndex initialArgPosition, const void *origValues, CFIndex originalValuesSize, va_list 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); #if defined(DEBUG) @@ -284,8 +284,7 @@ CF_INLINE CFAllocatorRef __CFStrContentsDeallocator(CFStringRef str) { // Assumption: Called with immutable strings only, and on strings that are known to have a contentsDeallocator CF_INLINE void __CFStrSetContentsDeallocator(CFStringRef str, CFAllocatorRef allocator) { - allocator = kCFUseCollectableAllocator ? allocator : _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); - if (!(kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator)) CFRetain(allocator); + if (!(0 || 0)) CFRetain(allocator); *__CFStrContentsDeallocatorPtr(str) = allocator; } @@ -302,8 +301,7 @@ CF_INLINE CFAllocatorRef __CFStrContentsAllocator(CFMutableStringRef str) { // Assumption: Called with strings that have a contents allocator; also, contents allocator follows custom CF_INLINE void __CFStrSetContentsAllocator(CFMutableStringRef str, CFAllocatorRef allocator) { - allocator = kCFUseCollectableAllocator ? allocator : _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator); - if (!(kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator)) CFRetain(allocator); + if (!(0 || 0)) CFRetain(allocator); *(__CFStrContentsAllocatorPtr(str)) = allocator; } @@ -392,7 +390,7 @@ static void *__CFStrAllocateMutableContents(CFMutableStringRef str, CFIndex size static void __CFStrDeallocateMutableContents(CFMutableStringRef str, void *buffer) { CFAllocatorRef alloc = (__CFStrHasContentsAllocator(str)) ? __CFStrContentsAllocator(str) : __CFGetAllocator(str); - if (__CFStrIsMutable(str) && __CFStrHasContentsAllocator(str) && _CFAllocatorIsGCRefZero(alloc)) { + if (__CFStrIsMutable(str) && __CFStrHasContentsAllocator(str) && (0)) { // do nothing } else if (CF_IS_COLLECTABLE_ALLOCATOR(alloc)) { // GC: for finalization safety, let collector reclaim the buffer in the next GC cycle. @@ -512,20 +510,30 @@ CF_INLINE Boolean __CFStrEncodingCanBeStoredInEightBit(CFStringEncoding encoding } /* Returns the encoding used in eight bit CFStrings (can't be any encoding which isn't 1-to-1 with Unicode) - ??? Perhaps only ASCII fits the bill due to Unicode decomposition. + For 10.9-linked apps, we've set this encoding to ASCII for all cases; see */ CFStringEncoding __CFStringComputeEightBitStringEncoding(void) { - if (__CFDefaultEightBitStringEncoding == kCFStringEncodingInvalidId) { - CFStringEncoding systemEncoding = CFStringGetSystemEncoding(); - if (systemEncoding == kCFStringEncodingInvalidId) { // We're right in the middle of querying system encoding from default database. Delaying to set until system encoding is determined. - return kCFStringEncodingASCII; - } else if (__CFStrEncodingCanBeStoredInEightBit(systemEncoding)) { - __CFDefaultEightBitStringEncoding = systemEncoding; - } else { - __CFDefaultEightBitStringEncoding = kCFStringEncodingASCII; + // This flag prevents recursive entry into __CFStringComputeEightBitStringEncoding + static Boolean __CFStringIsBeingInitialized2 = false; + if (__CFStringIsBeingInitialized2) return kCFStringEncodingASCII; + __CFStringIsBeingInitialized2 = true; + + Boolean useAscii = true; + __CFStringIsBeingInitialized2 = false; + if (useAscii) { + __CFDefaultEightBitStringEncoding = kCFStringEncodingASCII; + } else { + if (__CFDefaultEightBitStringEncoding == kCFStringEncodingInvalidId) { + CFStringEncoding systemEncoding = CFStringGetSystemEncoding(); + if (systemEncoding == kCFStringEncodingInvalidId) { // We're right in the middle of querying system encoding from default database. Delaying to set until system encoding is determined. + return kCFStringEncodingASCII; + } else if (__CFStrEncodingCanBeStoredInEightBit(systemEncoding)) { + __CFDefaultEightBitStringEncoding = systemEncoding; + } else { + __CFDefaultEightBitStringEncoding = kCFStringEncodingASCII; + } } } - return __CFDefaultEightBitStringEncoding; } @@ -950,7 +958,7 @@ static void __CFStringDeallocate(CFTypeRef cf) { if (__CFStrHasContentsDeallocator(str)) { CFAllocatorRef allocator = __CFStrContentsDeallocator(str); CFAllocatorDeallocate(allocator, contents); - if (!(kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator)) CFRelease(allocator); + if (!(0 || 0 )) CFRelease(allocator); } else { CFAllocatorRef alloc = __CFGetAllocator(str); CFAllocatorDeallocate(alloc, contents); @@ -959,7 +967,7 @@ static void __CFStringDeallocate(CFTypeRef cf) { } if (isMutable && __CFStrHasContentsAllocator(str)) { CFAllocatorRef allocator = __CFStrContentsAllocator((CFMutableStringRef)str); - if (!(kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator)) CFRelease(allocator); + if (!(0 || 0)) CFRelease(allocator); } } } @@ -1194,7 +1202,7 @@ static const CFRuntimeClass __CFStringClass = { __CFStringCopyDescription }; -__private_extern__ void __CFStringInitialize(void) { +CF_PRIVATE void __CFStringInitialize(void) { __kCFStringTypeID = _CFRuntimeRegisterClass(&__CFStringClass); } @@ -1226,7 +1234,7 @@ static Boolean CFStrIsUnicode(CFStringRef str) { bytes should not contain BOM characters !!! Various flags should be combined to reduce number of arguments, if possible */ -__private_extern__ CFStringRef __CFStringCreateImmutableFunnel3( +CF_PRIVATE CFStringRef __CFStringCreateImmutableFunnel3( CFAllocatorRef alloc, const void *bytes, CFIndex numBytes, CFStringEncoding encoding, Boolean possiblyExternalFormat, Boolean tryToReduceUnicode, Boolean hasLengthByte, Boolean hasNullByte, Boolean noCopy, CFAllocatorRef contentsDeallocator, UInt32 converterFlags) { @@ -1398,9 +1406,9 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3( } #endif +#if USE_STRING_ROM CFStringRef romResult = NULL; -#if USE_STRING_ROM if (stringSupportsROM) { // Disable the string ROM if necessary @@ -1422,16 +1430,17 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3( /* 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; } -#endif if (! romResult) { +#else + if (1) { +#endif // Now determine the necessary size if (noCopy) { size = sizeof(void *); // Pointer to the buffer - // special GCRefZero allocator usage always needs saving - if (_CFAllocatorIsGCRefZero(contentsDeallocator) || (contentsDeallocator != alloc && contentsDeallocator != kCFAllocatorNull)) { + if ((0) || (contentsDeallocator != alloc && contentsDeallocator != kCFAllocatorNull)) { size += sizeof(void *); // The contentsDeallocator } if (!hasLengthByte) size += sizeof(CFIndex); // Explicit length @@ -1473,7 +1482,7 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3( if (str) { if (__CFOASafe) __CFSetLastAllocationEventName(str, "CFString (immutable)"); - CFOptionFlags allocBits = _CFAllocatorIsGCRefZero(contentsDeallocator) ? __kCFHasContentsDeallocator : (contentsDeallocator == alloc ? __kCFNotInlineContentsDefaultFree : (contentsDeallocator == kCFAllocatorNull ? __kCFNotInlineContentsNoFree : __kCFNotInlineContentsCustomFree)); + CFOptionFlags allocBits = (0) ? __kCFHasContentsDeallocator : (contentsDeallocator == alloc ? __kCFNotInlineContentsDefaultFree : (contentsDeallocator == kCFAllocatorNull ? __kCFNotInlineContentsNoFree : __kCFNotInlineContentsCustomFree)); __CFStrSetInfoBits(str, (useInlineData ? __kCFHasInlineContents : allocBits) | ((encoding == kCFStringEncodingUnicode) ? __kCFIsUnicode : 0) | @@ -1503,6 +1512,19 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3( } if (vBuf.shouldFreeChars) CFAllocatorDeallocate(vBuf.allocator, (void *)bytes); +#if 0 +#warning Debug code + const uint8_t *contents = (uint8_t *)__CFStrContents(str); + CFIndex len = __CFStrLength2(str, contents); + + if (__CFStrIsEightBit(str)) { + contents += __CFStrSkipAnyLengthByte(str); + if (!__CFBytesInASCII(contents, len)) { + printf("CFString with 8 bit backing store not ASCII: %p, \"%.*s\"\n", str, (int)len, contents); + } + } +#endif + return str; } @@ -1570,7 +1592,7 @@ CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFSt 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, format, 0, NULL, 0, arguments); + __CFStringAppendFormatCore(outputString, copyDescFunc, 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); @@ -1611,9 +1633,9 @@ CFStringRef CFStringCreateCopy(CFAllocatorRef alloc, CFStringRef str) { __CFAssertIsString(str); if (!__CFStrIsMutable((CFStringRef)str) && // If the string is not mutable - ((alloc ? _CFConvertAllocatorToNonGCRefZeroEquivalent(alloc) : __CFGetDefaultAllocator()) == __CFGetAllocator(str)) && // and it has the same allocator as the one we're using + ((alloc ? alloc : __CFGetDefaultAllocator()) == __CFGetAllocator(str)) && // and it has the same allocator as the one we're using (__CFStrIsInline((CFStringRef)str) || __CFStrFreeContentsWhenDone((CFStringRef)str) || __CFStrIsConstant((CFStringRef)str))) { // and the characters are inline, or are owned by the string, or the string is constant - if (!(kCFUseCollectableAllocator && _CFAllocatorIsGCRefZero(alloc))) CFRetain(str); // Then just retain instead of making a true copy + if (!(kCFUseCollectableAllocator && (0))) CFRetain(str); // Then just retain instead of making a true copy return str; } if (__CFStrIsEightBit((CFStringRef)str)) { @@ -1838,7 +1860,7 @@ CF_INLINE void __CFStringReplace(CFMutableStringRef str, CFRange range, CFString CF_INLINE CFMutableStringRef __CFStringCreateMutableFunnel(CFAllocatorRef alloc, CFIndex maxLength, UInt32 additionalInfoBits) { CFMutableStringRef str; - if (_CFAllocatorIsGCRefZero(alloc)) additionalInfoBits |= __kCFHasContentsAllocator; + if ((0)) additionalInfoBits |= __kCFHasContentsAllocator; Boolean hasExternalContentsAllocator = (additionalInfoBits & __kCFHasContentsAllocator) ? true : false; if (alloc == NULL) alloc = __CFGetDefaultAllocator(); @@ -1870,7 +1892,7 @@ CFMutableStringRef CFStringCreateMutableWithExternalCharactersNoCopy(CFAllocator __CFStrSetIsExternalMutable(string); if (__CFStrHasContentsAllocator(string)) { CFAllocatorRef allocator = __CFStrContentsAllocator((CFMutableStringRef)string); - if (!(kCFAllocatorSystemDefaultGCRefZero == allocator || kCFAllocatorDefaultGCRefZero == allocator)) CFRelease(allocator); + if (!(0 || 0)) CFRelease(allocator); __CFStrSetContentsAllocator(string, externalCharactersAllocator); } CFStringSetExternalCharactersNoCopy(string, chars, numChars, capacity); @@ -1896,7 +1918,7 @@ CFMutableStringRef CFStringCreateMutableCopy(CFAllocatorRef alloc, CFIndex maxL } -__private_extern__ void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len) { +CF_PRIVATE void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len) { __CFAssertIsStringAndMutable(str); __CFStrSetDesiredCapacity(str, len); } @@ -2033,6 +2055,8 @@ const char * CFStringGetCStringPtr(CFStringRef str, CFStringEncoding encoding) { if (encoding != __CFStringGetEightBitStringEncoding() && (kCFStringEncodingASCII != __CFStringGetEightBitStringEncoding() || !__CFStringEncodingIsSupersetOfASCII(encoding))) return NULL; // ??? Also check for encoding = SystemEncoding and perhaps bytes are all ASCII? + if (str == NULL) return NULL; // Should really just crash, but for compatibility... see + CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, const char *, (NSString *)str, _fastCStringContents:true); __CFAssertIsString(str); @@ -2153,8 +2177,8 @@ Boolean CFStringGetCString(CFStringRef str, char *buffer, CFIndex bufferSize, CF extern Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale); extern void __CFLocaleSetNullLocale(struct __CFLocale *locale); -static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) { - CFStringRef collatorID; +static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale, bool collatorOnly) { + CFStringRef localeID; const char *langID = NULL; static const void *lastLocale = NULL; static const char *lastLangID = NULL; @@ -2169,16 +2193,22 @@ static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) { } __CFSpinUnlock(&lock); - collatorID = (CFStringRef)CFLocaleGetValue(locale, __kCFLocaleCollatorID); + localeID = (CFStringRef)CFLocaleGetValue(locale, __kCFLocaleCollatorID); + + if (!collatorOnly) { + CFIndex length = __CFStrLength(localeID); + + if ((length < 2) || ((4 == length) && CFEqual(localeID, CFSTR("root")))) localeID = (CFStringRef)CFLocaleGetIdentifier(locale); + } // This is somewhat depending on CFLocale implementation always creating CFString for locale identifer ??? - if (__CFStrLength(collatorID) > 1) { - const void *contents = __CFStrContents(collatorID); + if (__CFStrLength(localeID) > 1) { + const void *contents = __CFStrContents(localeID); const char *string; char buffer[2]; - if (__CFStrIsEightBit(collatorID)) { - string = ((const char *)contents) + __CFStrSkipAnyLengthByte(collatorID); + if (__CFStrIsEightBit(localeID)) { + string = ((const char *)contents) + __CFStrSkipAnyLengthByte(localeID); } else { const UTF16Char *characters = (const UTF16Char *)contents; @@ -2200,7 +2230,6 @@ static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) { } } - if (langID == NULL) __CFLocaleSetNullLocale((struct __CFLocale *)locale); __CFSpinLock(&lock); @@ -2493,7 +2522,7 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr freeLocale = true; } - langCode = ((NULL == locale) ? NULL : (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(locale)); + langCode = ((NULL == locale) ? NULL : (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(locale, true)); if (__CFStringFillCharacterSetInlineBuffer(&csetBuffer, compareOptions)) { ignoredChars = &csetBuffer; @@ -2854,11 +2883,11 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT if (NULL == locale) { if (compareOptions & kCFCompareLocalized) { CFLocaleRef currentLocale = CFLocaleCopyCurrent(); - langCode = (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(currentLocale); + langCode = (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(currentLocale, true); CFRelease(currentLocale); } } else { - langCode = (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(locale); + langCode = (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(locale, true); } CFStringInitInlineBuffer(string, &inlineBuf1, CFRangeMake(0, rangeToSearch.location + rangeToSearch.length)); @@ -3242,7 +3271,7 @@ static void __rangeRelease(CFAllocatorRef allocator, const void *ptr) { static CFStringRef __rangeCopyDescription(const void *ptr) { CFRange range = *(CFRange *)ptr; - return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{%d, %d}"), range.location, range.length); + return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("{%ld, %ld}"), (long)range.location, (long)range.length); } static Boolean __rangeEqual(const void *ptr1, const void *ptr2) { @@ -3274,8 +3303,7 @@ CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef // If necessary, grow the data and squirrel away the found range if (foundCount >= capacity) { - // Note that rangeStorage is not allowed to be allocated from one of the GCRefZero allocators - if (rangeStorage == NULL) rangeStorage = CFDataCreateMutable(_CFConvertAllocatorToNonGCRefZeroEquivalent(alloc), 0); + if (rangeStorage == NULL) rangeStorage = CFDataCreateMutable(alloc, 0); capacity = (capacity + 4) * 2; CFDataSetLength(rangeStorage, capacity * (sizeof(CFRange) + sizeof(CFDataRef))); rangeStorageBytes = (uint8_t *)CFDataGetMutableBytePtr(rangeStorage) + foundCount * (sizeof(CFRange) + sizeof(CFDataRef)); @@ -3925,14 +3953,14 @@ CFArrayRef CFStringCreateArrayBySeparatingStrings(CFAllocatorRef alloc, CFString numChars = currentRange->location - startIndex; substring = CFStringCreateWithSubstring(alloc, string, CFRangeMake(startIndex, numChars)); CFArrayAppendValue(array, substring); - if (!_CFAllocatorIsGCRefZero(alloc)) CFRelease(substring); + CFRelease(substring); startIndex = currentRange->location + currentRange->length; } substring = CFStringCreateWithSubstring(alloc, string, CFRangeMake(startIndex, length - startIndex)); CFArrayAppendValue(array, substring); - if (!_CFAllocatorIsGCRefZero(alloc)) CFRelease(substring); + CFRelease(substring); - if (!_CFAllocatorIsGCRefZero(alloc)) CFRelease(separatorRanges); + CFRelease(separatorRanges); return array; } @@ -4426,7 +4454,7 @@ void CFStringLowercase(CFMutableStringRef string, CFLocaleRef locale) { length = __CFStrLength(string); - langCode = (const uint8_t *)(_CFCanUseLocale(locale) ? _CFStrGetLanguageIdentifierForLocale(locale) : NULL); + langCode = (const uint8_t *)(_CFCanUseLocale(locale) ? _CFStrGetLanguageIdentifierForLocale(locale, false) : NULL); if (!langCode && isEightBit) { uint8_t *contents = (uint8_t *)__CFStrContents(string) + __CFStrSkipAnyLengthByte(string); @@ -4517,7 +4545,7 @@ void CFStringUppercase(CFMutableStringRef string, CFLocaleRef locale) { length = __CFStrLength(string); - langCode = (const uint8_t *)(_CFCanUseLocale(locale) ? _CFStrGetLanguageIdentifierForLocale(locale) : NULL); + langCode = (const uint8_t *)(_CFCanUseLocale(locale) ? _CFStrGetLanguageIdentifierForLocale(locale, false) : NULL); if (!langCode && isEightBit) { uint8_t *contents = (uint8_t *)__CFStrContents(string) + __CFStrSkipAnyLengthByte(string); @@ -4613,7 +4641,7 @@ void CFStringCapitalize(CFMutableStringRef string, CFLocaleRef locale) { caseIgnorableForBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharCaseIgnorableCharacterSet, 0); - langCode = (const uint8_t *)(_CFCanUseLocale(locale) ? _CFStrGetLanguageIdentifierForLocale(locale) : NULL); + langCode = (const uint8_t *)(_CFCanUseLocale(locale) ? _CFStrGetLanguageIdentifierForLocale(locale, false) : NULL); if (!langCode && isEightBit) { uint8_t *contents = (uint8_t *)__CFStrContents(string) + __CFStrSkipAnyLengthByte(string); @@ -5043,7 +5071,7 @@ void CFStringNormalize(CFMutableStringRef string, CFStringNormalizationForm theF } } -void CFStringFold(CFMutableStringRef theString, CFOptionFlags theFlags, CFLocaleRef locale) { +void CFStringFold(CFMutableStringRef theString, CFStringCompareFlags theFlags, CFLocaleRef locale) { CFStringInlineBuffer stringBuffer; CFIndex length = CFStringGetLength(theString); CFIndex currentIndex = 0; @@ -5064,7 +5092,7 @@ void CFStringFold(CFMutableStringRef theString, CFOptionFlags theFlags, CFLocale if ((0 == theFlags) || (0 == length)) goto bail; // nothing to do - langCode = ((NULL == theLocale) ? NULL : (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(theLocale)); + langCode = ((NULL == theLocale) ? NULL : (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(theLocale, true)); eightBitEncoding = __CFStringGetEightBitStringEncoding(); cString = (const uint8_t *)CFStringGetCStringPtr(theString, eightBitEncoding); @@ -5337,7 +5365,7 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca // use significant digits pattern CFStringAppendCString(pattern, "@", kCFStringEncodingASCII); CFStringPad(pattern, CFSTR("#"), prec, 0); - double targetValue = values[spec->mainArgNum].value.doubleValue;; + double targetValue = values[spec->mainArgNum].value.doubleValue; #if LONG_DOUBLE_SUPPORT if (CFFormatSize16 == values[spec->mainArgNum].size) { targetValue = values[spec->mainArgNum].value.longDoubleValue; // losing precision @@ -5355,19 +5383,20 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca CFRelease(pattern); } - CFNumberRef tmp; + // clear the padding, we will add it later if we need it + const SInt32 z = 0; + CFNumberRef zero = CFNumberCreate(NULL, kCFNumberSInt32Type, &z); + CFNumberFormatterSetProperty(formatter, kCFNumberFormatterFormatWidthKey, zero); - tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &prec); + CFNumberRef tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &prec); CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigitsKey, tmp); if (spec->type == CFFormatDoubleType) { CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMinFractionDigitsKey, tmp); } else { - CFRelease(tmp); - SInt32 zero = 0; - tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &zero); - CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMinFractionDigitsKey, tmp); + CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMinFractionDigitsKey, zero); } CFRelease(tmp); + CFRelease(zero); // ??? use the right zero here for Arabic @@ -5389,8 +5418,22 @@ static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLoca CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingPositionKey, tmp); CFRelease(tmp); + Boolean isNegative = false; + switch (values[spec->mainArgNum].type) { + case CFFormatLongType: + if (values[spec->mainArgNum].value.int64Value < 0) isNegative = true; + break; + case CFFormatDoubleType: +#if LONG_DOUBLE_SUPPORT + if ((CFFormatSize16 == values[spec->mainArgNum].size) && (values[spec->mainArgNum].value.longDoubleValue < 0)) isNegative = true; + else +#endif + if (values[spec->mainArgNum].value.doubleValue < 0) isNegative = true; + break; + } + CFStringRef pattern = CFNumberFormatterGetFormat(formatter); - if (spec->flags & kCFStringFormatPlusFlag) { + if ((spec->flags & kCFStringFormatPlusFlag) && !isNegative) { if (CFStringGetCharacterAtIndex(pattern, 0) != '+') { CFMutableStringRef newPattern = CFStringCreateMutableCopy(NULL, 0, CFSTR("+")); CFStringAppend(newPattern, pattern); @@ -5664,7 +5707,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, formatString, 0, NULL, 0, args); + __CFStringAppendFormatCore(outputString, NULL, formatOptions, NULL, formatString, 0, NULL, 0, args); } // Length of the buffer to call sprintf() with @@ -5704,9 +5747,9 @@ 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, formatString, 0, NULL, 0, args); } +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, CFStringRef formatString, CFIndex initialArgPosition, const void *origValues, CFIndex originalValuesSize, va_list 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) { SInt32 numSpecs, sizeSpecs, sizeArgNum, formatIdx, curSpec, argNum; CFIndex formatLen; #define FORMAT_BUFFER_LEN 400 diff --git a/CFString.h b/CFString.h index 3ce34cb..8fe267d 100644 --- a/CFString.h +++ b/CFString.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFString.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRING__) @@ -704,7 +704,7 @@ CF_EXPORT void CFStringNormalize(CFMutableStringRef theString, CFStringNormaliza */ CF_EXPORT -void CFStringFold(CFMutableStringRef theString, CFOptionFlags theFlags, CFLocaleRef theLocale) CF_AVAILABLE(10_5, 2_0); +void CFStringFold(CFMutableStringRef theString, CFStringCompareFlags theFlags, CFLocaleRef theLocale) CF_AVAILABLE(10_5, 2_0); /* Perform string transliteration. The transformation represented by transform is applied to the given range of string, modifying it in place. Only the specified range will be modified, but the transform may look at portions of the string outside that range for context. NULL range pointer causes the whole string to be transformed. On return, range is modified to reflect the new range corresponding to the original range. reverse indicates that the inverse transform should be used instead, if it exists. If the transform is successful, true is returned; if unsuccessful, false. Reasons for the transform being unsuccessful include an invalid transform identifier, or attempting to reverse an irreversible transform. @@ -796,7 +796,8 @@ CFStringEncoding CFStringGetMostCompatibleMacStringEncoding(CFStringEncoding enc typedef struct { UniChar buffer[__kCFStringInlineBufferLength]; CFStringRef theString; - const UniChar *directBuffer; + const UniChar *directUniCharBuffer; + const char *directCStringBuffer; CFRange rangeToBuffer; /* Range in string to buffer */ CFIndex bufferedRangeStart; /* Start of range currently buffered (relative to rangeToBuffer.location) */ CFIndex bufferedRangeEnd; /* bufferedRangeStart + number of chars actually buffered */ @@ -806,17 +807,15 @@ typedef struct { CF_INLINE void CFStringInitInlineBuffer(CFStringRef str, CFStringInlineBuffer *buf, CFRange range) { buf->theString = str; buf->rangeToBuffer = range; - buf->directBuffer = CFStringGetCharactersPtr(str); + buf->directCStringBuffer = (buf->directUniCharBuffer = CFStringGetCharactersPtr(str)) ? NULL : CFStringGetCStringPtr(str, kCFStringEncodingASCII); buf->bufferedRangeStart = buf->bufferedRangeEnd = 0; } CF_INLINE UniChar CFStringGetCharacterFromInlineBuffer(CFStringInlineBuffer *buf, CFIndex idx) { - if (buf->directBuffer) { - if (idx < 0 || idx >= buf->rangeToBuffer.length) return 0; - return buf->directBuffer[idx + buf->rangeToBuffer.location]; - } + if (idx < 0 || idx >= buf->rangeToBuffer.length) return 0; + if (buf->directUniCharBuffer) return buf->directUniCharBuffer[idx + buf->rangeToBuffer.location]; + if (buf->directCStringBuffer) return (UniChar)(buf->directCStringBuffer[idx + buf->rangeToBuffer.location]); if (idx >= buf->bufferedRangeEnd || idx < buf->bufferedRangeStart) { - if (idx < 0 || idx >= buf->rangeToBuffer.length) return 0; if ((buf->bufferedRangeStart = idx - 4) < 0) buf->bufferedRangeStart = 0; buf->bufferedRangeEnd = buf->bufferedRangeStart + __kCFStringInlineBufferLength; if (buf->bufferedRangeEnd > buf->rangeToBuffer.length) buf->bufferedRangeEnd = buf->rangeToBuffer.length; @@ -829,10 +828,10 @@ CF_INLINE UniChar CFStringGetCharacterFromInlineBuffer(CFStringInlineBuffer *buf /* If INLINE functions are not available, we do somewhat less powerful macros that work similarly (except be aware that the buf argument is evaluated multiple times). */ #define CFStringInitInlineBuffer(str, buf, range) \ - do {(buf)->theString = str; (buf)->rangeToBuffer = range; (buf)->directBuffer = CFStringGetCharactersPtr(str);} while (0) + do {(buf)->theString = str; (buf)->rangeToBuffer = range; (buf)->directCStringBuffer = ((buf)->directUniCharBuffer = CFStringGetCharactersPtr(str)) ? NULL : CFStringGetCStringPtr(str, kCFStringEncodingASCII);} while (0) #define CFStringGetCharacterFromInlineBuffer(buf, idx) \ - (((idx) < 0 || (idx) >= (buf)->rangeToBuffer.length) ? 0 : ((buf)->directBuffer ? (buf)->directBuffer[(idx) + (buf)->rangeToBuffer.location] : CFStringGetCharacterAtIndex((buf)->theString, (idx) + (buf)->rangeToBuffer.location))) + (((idx) < 0 || (idx) >= (buf)->rangeToBuffer.length) ? 0 : ((buf)->directUniCharBuffer ? (buf)->directUniCharBuffer[(idx) + (buf)->rangeToBuffer.location] : ((buf)->directCStringBuffer ? (UniChar)((buf)->directCStringBuffer[(idx) + (buf)->rangeToBuffer.location]) : CFStringGetCharacterAtIndex((buf)->theString, (idx) + (buf)->rangeToBuffer.location)))) #endif /* CF_INLINE */ @@ -881,7 +880,7 @@ void CFShowStr(CFStringRef str); /* This function is private and should not be used directly */ CF_EXPORT -CFStringRef __CFStringMakeConstantString(const char *cStr); /* Private; do not use */ +CFStringRef __CFStringMakeConstantString(const char *cStr) CF_FORMAT_ARGUMENT(1); /* Private; do not use */ CF_EXTERN_C_END CF_IMPLICIT_BRIDGING_DISABLED diff --git a/CFStringDefaultEncoding.h b/CFStringDefaultEncoding.h index f209328..e7c21eb 100644 --- a/CFStringDefaultEncoding.h +++ b/CFStringDefaultEncoding.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringDefaultEncoding.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGDEFAULTENCODING__) diff --git a/CFStringEncodingConverter.c b/CFStringEncodingConverter.c index 5ce9c40..62a116c 100644 --- a/CFStringEncodingConverter.c +++ b/CFStringEncodingConverter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodingConverter.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -853,11 +853,11 @@ uint32_t CFStringEncodingBytesToUnicode(uint32_t encoding, uint32_t flags, const return theResult; } -__private_extern__ bool CFStringEncodingIsValidEncoding(uint32_t encoding) { +CF_PRIVATE bool CFStringEncodingIsValidEncoding(uint32_t encoding) { return (CFStringEncodingGetConverter(encoding) ? true : false); } -__private_extern__ CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) { +CF_PRIVATE CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) { const _CFEncodingConverter *converter = __CFGetConverter(encoding); if (converter) { @@ -901,7 +901,7 @@ __private_extern__ CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, return 0; } -__private_extern__ CFIndex CFStringEncodingByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars) { +CF_PRIVATE CFIndex CFStringEncodingByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars) { const _CFEncodingConverter *converter = __CFGetConverter(encoding); if (converter) { @@ -925,7 +925,7 @@ __private_extern__ CFIndex CFStringEncodingByteLengthForCharacters(uint32_t enco return 0; } -__private_extern__ void CFStringEncodingRegisterFallbackProcedures(uint32_t encoding, CFStringEncodingToBytesFallbackProc toBytes, CFStringEncodingToUnicodeFallbackProc toUnicode) { +void CFStringEncodingRegisterFallbackProcedures(uint32_t encoding, CFStringEncodingToBytesFallbackProc toBytes, CFStringEncodingToUnicodeFallbackProc toUnicode) { _CFEncodingConverter *converter = (_CFEncodingConverter *)__CFGetConverter(encoding); if (NULL != converter) { @@ -936,7 +936,7 @@ __private_extern__ void CFStringEncodingRegisterFallbackProcedures(uint32_t enco } } -__private_extern__ const CFStringEncodingConverter *CFStringEncodingGetConverter(uint32_t encoding) { +CF_PRIVATE const CFStringEncodingConverter *CFStringEncodingGetConverter(uint32_t encoding) { const _CFEncodingConverter *converter = __CFGetConverter(encoding); return ((NULL == converter) ? NULL : converter->definition); @@ -984,7 +984,7 @@ static void __CFStringEncodingFliterDupes(CFStringEncoding *encodings, CFIndex n } } -__private_extern__ const CFStringEncoding *CFStringEncodingListOfAvailableEncodings(void) { +CF_PRIVATE const CFStringEncoding *CFStringEncodingListOfAvailableEncodings(void) { static const CFStringEncoding *encodings = NULL; if (NULL == encodings) { diff --git a/CFStringEncodingConverter.h b/CFStringEncodingConverter.h index ea1f9ec..2357ac2 100644 --- a/CFStringEncodingConverter.h +++ b/CFStringEncodingConverter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodingConverter.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTER__) diff --git a/CFStringEncodingConverterExt.h b/CFStringEncodingConverterExt.h index 9c1328f..2415c6a 100644 --- a/CFStringEncodingConverterExt.h +++ b/CFStringEncodingConverterExt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodingConverterExt.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERETEREXT__) diff --git a/CFStringEncodingConverterPriv.h b/CFStringEncodingConverterPriv.h index 91a5ed1..faab37c 100644 --- a/CFStringEncodingConverterPriv.h +++ b/CFStringEncodingConverterPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodingConverterPriv.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTERPRIV__) diff --git a/CFStringEncodingDatabase.c b/CFStringEncodingDatabase.c index 50116da..2e1845b 100644 --- a/CFStringEncodingDatabase.c +++ b/CFStringEncodingDatabase.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodingDatabase.c - Copyright (c) 2005-2012, Apple Inc. All rights reserved. + Copyright (c) 2005-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -393,7 +393,7 @@ static inline CFIndex __CFGetEncodingIndex(CFStringEncoding encoding) { return kCFNotFound; } -__private_extern__ uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncoding encoding) { +CF_PRIVATE uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncoding encoding) { CFStringEncoding encodingBase = encoding & 0x0F00; if (0x0100 == encodingBase) { // UTF @@ -416,7 +416,7 @@ __private_extern__ uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncodin return 0; } -__private_extern__ CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t codepage) { +CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t codepage) { switch (codepage) { case 65001: return kCFStringEncodingUTF8; case 1200: return kCFStringEncodingUTF16; @@ -453,7 +453,7 @@ __private_extern__ CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uin return kCFStringEncodingInvalidId; } -__private_extern__ bool __CFStringEncodingGetCanonicalName(CFStringEncoding encoding, char *buffer, CFIndex bufferSize) { +CF_PRIVATE bool __CFStringEncodingGetCanonicalName(CFStringEncoding encoding, char *buffer, CFIndex bufferSize) { const char *format = "%s"; const char *name = NULL; uint32_t value = 0; @@ -523,7 +523,7 @@ static CFHashCode __CFCanonicalNameHash(const void *value) { return code * (name - (const char *)value); } -__private_extern__ CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *canonicalName) { +CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *canonicalName) { CFStringEncoding encoding; CFIndex prefixLength; static CFMutableDictionaryRef mappingTable = NULL; @@ -797,7 +797,7 @@ static const char *__CFOtherNameList[] = { }; #endif /* DEPLOYMENT_TARGET_MACOSX */ -__private_extern__ CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript(CFStringEncoding encoding) { +CF_PRIVATE CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript(CFStringEncoding encoding) { #if DEPLOYMENT_TARGET_MACOSX switch (encoding & 0x0F00) { case 0: return encoding & 0xFF; break; // Mac scripts @@ -822,7 +822,7 @@ __private_extern__ CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript return kCFStringEncodingInvalidId; } -__private_extern__ const char *__CFStringEncodingGetName(CFStringEncoding encoding) { +CF_PRIVATE const char *__CFStringEncodingGetName(CFStringEncoding encoding) { switch (encoding) { case kCFStringEncodingUTF8: return "Unicode (UTF-8)"; break; case kCFStringEncodingUTF16: return "Unicode (UTF-16)"; break; diff --git a/CFStringEncodingDatabase.h b/CFStringEncodingDatabase.h index c8f334e..f908e14 100644 --- a/CFStringEncodingDatabase.h +++ b/CFStringEncodingDatabase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,18 +26,18 @@ * CoreFoundation * * Created by Aki Inoue on 07/12/05. - * Copyright (c) 2007-2012, Apple Inc. All rights reserved. + * Copyright (c) 2007-2013, Apple Inc. All rights reserved. * */ #include -__private_extern__ uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncoding encoding); -__private_extern__ CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t codepage); +CF_PRIVATE uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncoding encoding); +CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t codepage); -__private_extern__ bool __CFStringEncodingGetCanonicalName(CFStringEncoding encoding, char *buffer, CFIndex bufferSize); -__private_extern__ CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *canonicalName); +CF_PRIVATE bool __CFStringEncodingGetCanonicalName(CFStringEncoding encoding, char *buffer, CFIndex bufferSize); +CF_PRIVATE CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *canonicalName); -__private_extern__ CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript(CFStringEncoding encoding); +CF_PRIVATE CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript(CFStringEncoding encoding); -__private_extern__ const char *__CFStringEncodingGetName(CFStringEncoding encoding); // Returns simple non-localizd name +CF_PRIVATE const char *__CFStringEncodingGetName(CFStringEncoding encoding); // Returns simple non-localizd name diff --git a/CFStringEncodingExt.h b/CFStringEncodingExt.h index 77fd916..8dc4164 100644 --- a/CFStringEncodingExt.h +++ b/CFStringEncodingExt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodingExt.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFSTRINGENCODINGEXT__) diff --git a/CFStringEncodings.c b/CFStringEncodings.c index f0f9db0..2dc9e94 100644 --- a/CFStringEncodings.c +++ b/CFStringEncodings.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringEncodings.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -57,7 +57,7 @@ Boolean (*__CFCharToUniCharFunc)(UInt32 flags, uint8_t ch, UniChar *unicodeChar) // To avoid early initialization issues, we just initialize this here // This should not be const as it is changed -__private_extern__ UniChar __CFCharToUniCharTable[256] = { +CF_PRIVATE UniChar __CFCharToUniCharTable[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -76,7 +76,7 @@ __private_extern__ UniChar __CFCharToUniCharTable[256] = { 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; -__private_extern__ void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, UInt8 ch, UniChar *unicodeChar)) { +CF_PRIVATE void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, UInt8 ch, UniChar *unicodeChar)) { if (__CFCharToUniCharFunc != func) { int ch; __CFCharToUniCharFunc = func; @@ -91,7 +91,7 @@ __private_extern__ void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, U } } -__private_extern__ void __CFStrConvertBytesToUnicode(const uint8_t *bytes, UniChar *buffer, CFIndex numChars) { +CF_PRIVATE void __CFStrConvertBytesToUnicode(const uint8_t *bytes, UniChar *buffer, CFIndex numChars) { CFIndex idx; for (idx = 0; idx < numChars; idx++) buffer[idx] = __CFCharToUniCharTable[bytes[idx]]; } diff --git a/CFStringScanner.c b/CFStringScanner.c index a5f1627..980e142 100644 --- a/CFStringScanner.c +++ b/CFStringScanner.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringScanner.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Ali Ozer */ @@ -63,7 +63,7 @@ CF_INLINE UniChar __CFStringGetFirstNonSpaceCharacterFromInlineBuffer(CFStringIn /* result is int64_t or int, depending on doLonglong */ -__private_extern__ Boolean __CFStringScanInteger(CFStringInlineBuffer *buf, CFTypeRef locale, SInt32 *indexPtr, Boolean doLonglong, void *result) { +CF_PRIVATE Boolean __CFStringScanInteger(CFStringInlineBuffer *buf, CFTypeRef locale, SInt32 *indexPtr, Boolean doLonglong, void *result) { Boolean doingLonglong = false; /* Set to true if doLonglong, and we overflow an int... */ Boolean neg = false; int intResult = 0; @@ -121,7 +121,7 @@ __private_extern__ Boolean __CFStringScanInteger(CFStringInlineBuffer *buf, CFTy return true; } -__private_extern__ Boolean __CFStringScanHex(CFStringInlineBuffer *buf, SInt32 *indexPtr, unsigned *result) { +CF_PRIVATE Boolean __CFStringScanHex(CFStringInlineBuffer *buf, SInt32 *indexPtr, unsigned *result) { UInt32 value = 0; SInt32 curDigit; UniChar ch; @@ -175,7 +175,7 @@ static const unsigned char __CFNumberSet[16] = { 0X00, // 0, 0, 0, 0, 0, 0, 0, 0 // x y z { | } ~ del }; -__private_extern__ Boolean __CFStringScanDouble(CFStringInlineBuffer *buf, CFTypeRef locale, SInt32 *indexPtr, double *resultPtr) { +CF_PRIVATE Boolean __CFStringScanDouble(CFStringInlineBuffer *buf, CFTypeRef locale, SInt32 *indexPtr, double *resultPtr) { #define STACK_BUFFER_SIZE 256 #define ALLOC_CHUNK_SIZE 256 // first and subsequent malloc size. Should be greater than STACK_BUFFER_SIZE char localCharBuffer[STACK_BUFFER_SIZE]; diff --git a/CFStringUtilities.c b/CFStringUtilities.c index 637326a..507b37d 100644 --- a/CFStringUtilities.c +++ b/CFStringUtilities.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFStringUtilities.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -111,6 +111,11 @@ CFStringEncoding CFStringConvertIANACharSetNameToEncoding(CFStringRef charsetNam #endif + // handling Java name variant for MS codepages + if ((kCFStringEncodingInvalidId == encoding) && !strncasecmp(name, "ms950", strlen("ms950"))) { // “MS950” is not recognized + encoding = __CFStringEncodingGetFromCanonicalName("cp950"); + } + return encoding; } @@ -556,7 +561,7 @@ static inline CFIndex __extendLocationForward(CFIndex location, CFStringInlineBu return location; } -__private_extern__ CFComparisonResult _CFCompareStringsWithLocale(CFStringInlineBuffer *str1, CFRange str1Range, CFStringInlineBuffer *str2, CFRange str2Range, CFOptionFlags options, const void *compareLocale) { +CF_PRIVATE CFComparisonResult _CFCompareStringsWithLocale(CFStringInlineBuffer *str1, CFRange str1Range, CFStringInlineBuffer *str2, CFRange str2Range, CFOptionFlags options, const void *compareLocale) { const UniChar *characters1; const UniChar *characters2; CFComparisonResult compResult = kCFCompareEqualTo; diff --git a/CFSystemDirectories.c b/CFSystemDirectories.c index 6efe1a2..51a2da7 100644 --- a/CFSystemDirectories.c +++ b/CFSystemDirectories.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFSystemDirectories.c - Copyright (c) 1997-2012, Apple Inc. All rights reserved. + Copyright (c) 1997-2013, Apple Inc. All rights reserved. Responsibility: Kevin Perry */ @@ -43,6 +43,7 @@ #include #include #include +#include #include CFSearchPathEnumerationState __CFStartSearchPathEnumeration(CFSearchPathDirectory dir, CFSearchPathDomainMask domainMask) { @@ -104,6 +105,7 @@ CFArrayRef CFCopySearchPathForDirectoriesInDomains(CFSearchPathDirectory directo #endif + #undef numDirs #undef numApplicationDirs #undef numLibraryDirs diff --git a/CFTimeZone.c b/CFTimeZone.c index 5e40803..62460e2 100644 --- a/CFTimeZone.c +++ b/CFTimeZone.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFTimeZone.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -479,7 +479,7 @@ static const CFRuntimeClass __CFTimeZoneClass = { __CFTimeZoneCopyDescription }; -__private_extern__ void __CFTimeZoneInitialize(void) { +CF_PRIVATE void __CFTimeZoneInitialize(void) { __kCFTimeZoneTypeID = _CFRuntimeRegisterClass(&__CFTimeZoneClass); } diff --git a/CFTimeZone.h b/CFTimeZone.h index c30f7c7..4272729 100644 --- a/CFTimeZone.h +++ b/CFTimeZone.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFTimeZone.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFTIMEZONE__) diff --git a/CFTree.c b/CFTree.c index dd08b99..1fe4f0e 100644 --- a/CFTree.c +++ b/CFTree.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFTree.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Christopher Kane */ @@ -97,7 +97,7 @@ static CFStringRef __CFTreeCopyDescription(CFTypeRef cf) { if (NULL == contextDesc) { contextDesc = CFStringCreateWithFormat(allocator, NULL, CFSTR(""), tree->_info); } - CFStringAppendFormat(result, NULL, CFSTR("{children = %u, context = %@}"), cf, allocator, CFTreeGetChildCount(tree), contextDesc); + CFStringAppendFormat(result, NULL, CFSTR("{children = %lu, context = %@}"), cf, allocator, (unsigned long)CFTreeGetChildCount(tree), contextDesc); if (contextDesc) CFRelease(contextDesc); return result; } @@ -136,7 +136,7 @@ static const CFRuntimeClass __CFTreeClass = { __CFTreeCopyDescription }; -__private_extern__ void __CFTreeInitialize(void) { +CF_PRIVATE void __CFTreeInitialize(void) { __kCFTreeTypeID = _CFRuntimeRegisterClass(&__CFTreeClass); } diff --git a/CFTree.h b/CFTree.h index 277eb1f..41a21a6 100644 --- a/CFTree.h +++ b/CFTree.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFTree.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ /*! @header CFTree diff --git a/CFURL.c b/CFURL.c index b15658c..4407e3b 100644 --- a/CFURL.c +++ b/CFURL.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFURL.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: John Iarocci */ @@ -43,17 +43,29 @@ #include #include #include +#include #include #endif +#ifndef DEBUG_URL_MEMORY_USAGE +// enables various statistical counters which can be displayed with __CFURLDumpMemRecord(). +#define DEBUG_URL_MEMORY_USAGE 0 +#endif + +#ifndef DEBUG_URL_INITIALIZER_LOGGING +// enables logging in URL initializer. You get to see the inputs and output for each URL created. +#define DEBUG_URL_INITIALIZER_LOGGING 0 +#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); +static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute); #endif -static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir); -static CFStringRef WindowsPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir); -static CFStringRef POSIXPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDirectory); +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); +static CFStringRef CreateStringFromFileSystemRepresentationByAddingPercentEscapes(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex numBytes, Boolean isDirectory, Boolean isAbsolute, Boolean windowsPath, Boolean *addedPercentEncoding); CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLRef anURL, CFURLPathStyle fsType, Boolean resolveAgainstBase); CF_EXPORT CFURLRef _CFURLCreateCurrentDirectoryURL(CFAllocatorRef allocator); #if DEPLOYMENT_TARGET_MACOSX @@ -62,18 +74,31 @@ static Boolean _CFURLHasFileURLScheme(CFURLRef url, Boolean *hasScheme); - -#ifndef DEBUG_URL_MEMORY_USAGE -#define DEBUG_URL_MEMORY_USAGE 0 +// When __CONSTANT_CFSTRINGS__ is not defined, we have separate macros for static and exported constant strings, but +// when it is defined, we must prefix with static to prevent the string from being exported +#ifdef __CONSTANT_CFSTRINGS__ +static CONST_STRING_DECL(kCFURLHTTPScheme, "http") +static CONST_STRING_DECL(kCFURLHTTPSScheme, "https") +static CONST_STRING_DECL(kCFURLFileScheme, "file") +static CONST_STRING_DECL(kCFURLDataScheme, "data") +static CONST_STRING_DECL(kCFURLFTPScheme, "ftp") +static CONST_STRING_DECL(kCFURLLocalhost, "localhost") +#else +CONST_STRING_DECL(kCFURLHTTPScheme, "http") +CONST_STRING_DECL(kCFURLHTTPSScheme, "https") +CONST_STRING_DECL(kCFURLFileScheme, "file") +CONST_STRING_DECL(kCFURLDataScheme, "data") +CONST_STRING_DECL(kCFURLFTPScheme, "ftp") +CONST_STRING_DECL(kCFURLLocalhost, "localhost") #endif #if DEBUG_URL_MEMORY_USAGE -static UInt32 numURLs = 0; -static UInt32 numDealloced = 0; -static UInt32 numFileURLsCreated = 0; -static UInt32 numExtraDataAllocated = 0; -static UInt32 numURLsWithBaseURL = 0; -static UInt32 numNonUTF8EncodedURLs = 0; +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 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 #endif /* The bit flags in myURL->_flags */ @@ -90,13 +115,11 @@ static UInt32 numNonUTF8EncodedURLs = 0; // various boolean flags #define IS_IPV6_ENCODED (0x00000400) #define IS_DIRECTORY (0x00000800) -#define IS_CANONICAL_FILE_URL (0x00001000) +#define IS_CANONICAL_FILE_URL (0x00001000) // if set, the URL is a file URL in the form "file://" (it was created from a file system path or representation) #define PATH_HAS_FILE_ID (0x00002000) -#define IS_ABSOLUTE (0x00004000) -#define IS_DECOMPOSABLE (0x00008000) -#define POSIX_AND_URL_PATHS_MATCH (0x00010000) // POSIX_AND_URL_PATHS_MATCH will only be true if the URL path and the POSIX path are identical, character for character, except for the presence/absence of a trailing slash on directories -#define ORIGINAL_AND_URL_STRINGS_MATCH (0x00020000) -#define USES_EIGHTBITSTRINGENCODING (0x00040000) +#define IS_DECOMPOSABLE (0x00004000) +#define POSIX_AND_URL_PATHS_MATCH (0x00008000) // POSIX_AND_URL_PATHS_MATCH will only be true if the URL path and the POSIX path are identical, character for character, except for the presence/absence of a trailing slash on directories +#define ORIGINAL_AND_URL_STRINGS_MATCH (0x00010000) // scheme bits and amount to shift it to translate to the kXXXXScheme enums #define SCHEME_TYPE_MASK (0xE0000000) #define SCHEME_SHIFT 29 @@ -117,10 +140,10 @@ CF_INLINE void _setSchemeTypeInFlags(UInt32 *flags, UInt32 schemeType); #define NET_LOCATION_MASK (HAS_HOST | HAS_USER | HAS_PASSWORD | HAS_PORT) #define RESOURCE_SPECIFIER_MASK (HAS_PARAMETERS | HAS_QUERY | HAS_FRAGMENT) // These flags can be compared for equality since these are all set once when the CFURL is created. -// IS_CANONICAL_FILE_URL cannot be compared since we don't create the URL string. +// IS_CANONICAL_FILE_URL cannot be compared since we don't always create the URL string. // POSIX_AND_URL_PATHS_MATCH cannot be compared because it may not be set // ORIGINAL_AND_URL_STRINGS_MATCH cannot be compared because it gets set on demand later. -#define EQUAL_FLAGS_MASK (HAS_SCHEME | HAS_USER | HAS_PASSWORD | HAS_HOST | HAS_PORT | HAS_PATH | HAS_PARAMETERS | HAS_QUERY | HAS_FRAGMENT | IS_IPV6_ENCODED | IS_DIRECTORY | PATH_HAS_FILE_ID | IS_ABSOLUTE | IS_DECOMPOSABLE | SCHEME_TYPE_MASK ) +#define EQUAL_FLAGS_MASK (HAS_SCHEME | HAS_USER | HAS_PASSWORD | HAS_HOST | HAS_PORT | HAS_PATH | HAS_PARAMETERS | HAS_QUERY | HAS_FRAGMENT | IS_IPV6_ENCODED | IS_DIRECTORY | PATH_HAS_FILE_ID | IS_DECOMPOSABLE | SCHEME_TYPE_MASK ) // The value of FULL_URL_REPRESENTATION must not be in the CFURLPathStyle enums. Also, its value is exposed via _CFURLCopyPropertyListRepresentation to the Finder so don't change it. #define FULL_URL_REPRESENTATION (0xF) @@ -143,9 +166,18 @@ CF_INLINE void _setSchemeTypeInFlags(UInt32 *flags, UInt32 schemeType); #define FILE_ID_PREAMBLE_LENGTH 10 #define FILE_PREFIX "file://" +static const UInt8 fileURLPrefix[] = FILE_PREFIX; + +// FILE_PREFIX_WITH_AUTHORITY and fileURLPrefixWithAuthority are only needed because some code incorrectly expects file URLs to have a host of "localhost", so if the application is linked on or before OS X 10.9 or iOS 7.0, we add "localhost" to file path URLs we create. #define FILE_PREFIX_WITH_AUTHORITY "file://localhost" static const UInt8 fileURLPrefixWithAuthority[] = FILE_PREFIX_WITH_AUTHORITY; +static Boolean AddAuthorityToFileURL(void) +{ + static Boolean result = false; + return ( result ); +} + // In order to reduce the sizeof ( __CFURL ), move these items into a seperate structure which is // only allocated when necessary. In my tests, it's almost never needed -- very rarely does a CFURL have // either a sanitized string or a reserved pointer for URLHandle. @@ -163,7 +195,7 @@ struct __CFURL { CFURLRef _base; CFRange *_ranges; struct _CFURLAdditionalData* _extra; - void *_resourceInfo; // For use by CarbonCore to cache property values. Retained and released by CFURL. + void *_resourceInfo; // For use by CoreServicesInternal to cache property values. Retained and released by CFURL. }; @@ -291,61 +323,7 @@ CF_INLINE void _setSchemeTypeInFlags(UInt32 *flags, UInt32 schemeType) *flags = (*flags & ~SCHEME_TYPE_MASK) + (schemeType << SCHEME_SHIFT); } -/* Returns whether the provided bytes can be stored in ASCII - */ -static Boolean __CFBytesInASCII(const uint8_t *bytes, CFIndex len) { -#if __LP64__ - /* A bit of unrolling; go by 32s, 16s, and 8s first */ - while (len >= 32) { - uint64_t val = *(const uint64_t *)bytes; - uint64_t hiBits = (val & 0x8080808080808080ULL); // More efficient to collect this rather than do a conditional at every step - bytes += 8; - val = *(const uint64_t *)bytes; - hiBits |= (val & 0x8080808080808080ULL); - bytes += 8; - val = *(const uint64_t *)bytes; - hiBits |= (val & 0x8080808080808080ULL); - bytes += 8; - val = *(const uint64_t *)bytes; - if (hiBits | (val & 0x8080808080808080ULL)) return false; - bytes += 8; - len -= 32; - } - - while (len >= 16) { - uint64_t val = *(const uint64_t *)bytes; - uint64_t hiBits = (val & 0x8080808080808080ULL); - bytes += 8; - val = *(const uint64_t *)bytes; - if (hiBits | (val & 0x8080808080808080ULL)) return false; - bytes += 8; - len -= 16; - } - - while (len >= 8) { - uint64_t val = *(const uint64_t *)bytes; - if (val & 0x8080808080808080ULL) return false; - bytes += 8; - len -= 8; - } -#endif - /* Go by 4s */ - while (len >= 4) { - uint32_t val = *(const uint32_t *)bytes; - if (val & 0x80808080U) return false; - bytes += 4; - len -= 4; - } - /* Handle the rest one byte at a time */ - while (len--) { - if (*bytes++ & 0x80) return false; - } - - return true; -} - static Boolean _pathHasFileIDPrefix(CFStringRef path); -static void _convertToURLRepresentation(struct __CFURL *url, UInt32 fsType); 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); @@ -363,7 +341,7 @@ CF_INLINE void _parseComponentsOfURL(CFURLRef url) { enum { VALID = 1, - UNRESERVED = 2, + ALPHA = 2, PATHVALID = 4, SCHEME = 8, HEXDIGIT = 16 @@ -403,31 +381,31 @@ static const unsigned char sURLValidCharacters[128] = { /* rs 30 */ 0, /* us 31 */ 0, /* sp 32 */ 0, - /* '!' 33 */ VALID | UNRESERVED | PATHVALID , + /* '!' 33 */ VALID | PATHVALID , /* '"' 34 */ 0, /* '#' 35 */ 0, /* '$' 36 */ VALID | PATHVALID , /* '%' 37 */ 0, /* '&' 38 */ VALID | PATHVALID , - /* ''' 39 */ VALID | UNRESERVED | PATHVALID , - /* '(' 40 */ VALID | UNRESERVED | PATHVALID , - /* ')' 41 */ VALID | UNRESERVED | PATHVALID , - /* '*' 42 */ VALID | UNRESERVED | PATHVALID , + /* ''' 39 */ VALID | PATHVALID , + /* '(' 40 */ VALID | PATHVALID , + /* ')' 41 */ VALID | PATHVALID , + /* '*' 42 */ VALID | PATHVALID , /* '+' 43 */ VALID | SCHEME | PATHVALID , /* ',' 44 */ VALID | PATHVALID , - /* '-' 45 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* '.' 46 */ VALID | UNRESERVED | SCHEME | PATHVALID , + /* '-' 45 */ VALID | SCHEME | PATHVALID , + /* '.' 46 */ VALID | SCHEME | PATHVALID , /* '/' 47 */ VALID | PATHVALID , - /* '0' 48 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '1' 49 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '2' 50 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '3' 51 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '4' 52 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '5' 53 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '6' 54 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '7' 55 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '8' 56 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* '9' 57 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , + /* '0' 48 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '1' 49 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '2' 50 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '3' 51 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '4' 52 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '5' 53 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '6' 54 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '7' 55 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '8' 56 */ VALID | SCHEME | PATHVALID | HEXDIGIT , + /* '9' 57 */ VALID | SCHEME | PATHVALID | HEXDIGIT , /* ':' 58 */ VALID , /* ';' 59 */ VALID , /* '<' 60 */ 0, @@ -435,90 +413,89 @@ static const unsigned char sURLValidCharacters[128] = { /* '>' 62 */ 0, /* '?' 63 */ VALID , /* '@' 64 */ VALID , - /* 'A' 65 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'B' 66 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'C' 67 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'D' 68 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'E' 69 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'F' 70 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'G' 71 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'H' 72 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'I' 73 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'J' 74 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'K' 75 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'L' 76 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'M' 77 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'N' 78 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'O' 79 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'P' 80 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'Q' 81 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'R' 82 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'S' 83 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'T' 84 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'U' 85 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'V' 86 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'W' 87 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'X' 88 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'Y' 89 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'Z' 90 */ VALID | UNRESERVED | SCHEME | PATHVALID , + /* 'A' 65 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'B' 66 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'C' 67 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'D' 68 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'E' 69 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'F' 70 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'G' 71 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'H' 72 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'I' 73 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'J' 74 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'K' 75 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'L' 76 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'M' 77 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'N' 78 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'O' 79 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'P' 80 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'Q' 81 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'R' 82 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'S' 83 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'T' 84 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'U' 85 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'V' 86 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'W' 87 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'X' 88 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'Y' 89 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'Z' 90 */ VALID | ALPHA | SCHEME | PATHVALID , /* '[' 91 */ 0, /* '\' 92 */ 0, /* ']' 93 */ 0, /* '^' 94 */ 0, - /* '_' 95 */ VALID | UNRESERVED | PATHVALID , + /* '_' 95 */ VALID | PATHVALID , /* '`' 96 */ 0, - /* 'a' 97 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'b' 98 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'c' 99 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'd' 100 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'e' 101 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'f' 102 */ VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT , - /* 'g' 103 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'h' 104 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'i' 105 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'j' 106 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'k' 107 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'l' 108 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'm' 109 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'n' 110 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'o' 111 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'p' 112 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'q' 113 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'r' 114 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 's' 115 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 't' 116 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'u' 117 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'v' 118 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'w' 119 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'x' 120 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'y' 121 */ VALID | UNRESERVED | SCHEME | PATHVALID , - /* 'z' 122 */ VALID | UNRESERVED | SCHEME | PATHVALID , + /* 'a' 97 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'b' 98 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'c' 99 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'd' 100 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'e' 101 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'f' 102 */ VALID | ALPHA | SCHEME | PATHVALID | HEXDIGIT , + /* 'g' 103 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'h' 104 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'i' 105 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'j' 106 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'k' 107 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'l' 108 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'm' 109 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'n' 110 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'o' 111 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'p' 112 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'q' 113 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'r' 114 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 's' 115 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 't' 116 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'u' 117 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'v' 118 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'w' 119 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'x' 120 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'y' 121 */ VALID | ALPHA | SCHEME | PATHVALID , + /* 'z' 122 */ VALID | ALPHA | SCHEME | PATHVALID , /* '{' 123 */ 0, /* '|' 124 */ 0, /* '}' 125 */ 0, - /* '~' 126 */ VALID | UNRESERVED | PATHVALID , + /* '~' 126 */ VALID | PATHVALID , /* del 127 */ 0, }; CF_INLINE Boolean isURLLegalCharacter(UniChar ch) { - return (ch <= 127) ? (sURLValidCharacters[ch] & VALID) : false; + return (ch <= 127) ? ((sURLValidCharacters[ch] & VALID) != 0) : false; } CF_INLINE Boolean scheme_valid(UniChar ch) { - return (ch <= 127) ? (sURLValidCharacters[ch] & SCHEME) : false; + return (ch <= 127) ? ((sURLValidCharacters[ch] & SCHEME) != 0) : false; } -// "Unreserved" as defined by RFC 2396 -CF_INLINE Boolean isUnreservedCharacter(UniChar ch) { - return (ch <= 127) ? (sURLValidCharacters[ch] & UNRESERVED) : false; +CF_INLINE Boolean isALPHA(UniChar ch) { + return (ch <= 127) ? ((sURLValidCharacters[ch] & ALPHA) != 0) : false; } CF_INLINE Boolean isPathLegalCharacter(UniChar ch) { - return (ch <= 127) ? (sURLValidCharacters[ch] & PATHVALID) : false; + return (ch <= 127) ? ((sURLValidCharacters[ch] & PATHVALID) != 0) : false; } CF_INLINE Boolean isHexDigit(UniChar ch) { - return (ch <= 127) ? (sURLValidCharacters[ch] & HEXDIGIT) : false; + return (ch <= 127) ? ((sURLValidCharacters[ch] & HEXDIGIT) != 0) : false; } // Returns false if ch1 or ch2 isn't properly formatted @@ -542,9 +519,278 @@ CF_INLINE Boolean _haveTestedOriginalString(CFURLRef url) { return ((url->_flags & ORIGINAL_AND_URL_STRINGS_MATCH) != 0) || (_getSanitizedString(url) != NULL); } +enum { + IS_PCHAR = 0x01, +}; + +static const unsigned char sURLValidBytes[256] = { + /* nul 0 */ 0, + /* soh 1 */ 0, + /* stx 2 */ 0, + /* etx 3 */ 0, + /* eot 4 */ 0, + /* enq 5 */ 0, + /* ack 6 */ 0, + /* bel 7 */ 0, + /* bs 8 */ 0, + /* ht 9 */ 0, + /* nl 10 */ 0, + /* vt 11 */ 0, + /* np 12 */ 0, + /* cr 13 */ 0, + /* so 14 */ 0, + /* si 15 */ 0, + /* dle 16 */ 0, + /* dc1 17 */ 0, + /* dc2 18 */ 0, + /* dc3 19 */ 0, + /* dc4 20 */ 0, + /* nak 21 */ 0, + /* syn 22 */ 0, + /* etb 23 */ 0, + /* can 24 */ 0, + /* em 25 */ 0, + /* sub 26 */ 0, + /* esc 27 */ 0, + /* fs 28 */ 0, + /* gs 29 */ 0, + /* rs 30 */ 0, + /* us 31 */ 0, + /* sp 32 */ 0, + /* '!' 33 */ IS_PCHAR, + /* '"' 34 */ 0, + /* '#' 35 */ 0, + /* '$' 36 */ IS_PCHAR, + /* '%' 37 */ 0, + /* '&' 38 */ IS_PCHAR, + /* ''' 39 */ IS_PCHAR, + /* '(' 40 */ IS_PCHAR, + /* ')' 41 */ IS_PCHAR, + /* '*' 42 */ IS_PCHAR, + /* '+' 43 */ IS_PCHAR, + /* ',' 44 */ IS_PCHAR, + /* '-' 45 */ IS_PCHAR, + /* '.' 46 */ IS_PCHAR, + /* '/' 47 */ IS_PCHAR, // not really a pchar -- it's the segment delimiter + /* '0' 48 */ IS_PCHAR, + /* '1' 49 */ IS_PCHAR, + /* '2' 50 */ IS_PCHAR, + /* '3' 51 */ IS_PCHAR, + /* '4' 52 */ IS_PCHAR, + /* '5' 53 */ IS_PCHAR, + /* '6' 54 */ IS_PCHAR, + /* '7' 55 */ IS_PCHAR, + /* '8' 56 */ IS_PCHAR, + /* '9' 57 */ IS_PCHAR, + /* ':' 58 */ IS_PCHAR, + /* ';' 59 */ 0, // we need to percent-escape ';' in file system paths so it won't be mistaken for the start of the obsolete param rule (rfc2396) that CFURL still supports + /* '<' 60 */ 0, + /* '=' 61 */ IS_PCHAR, + /* '>' 62 */ 0, + /* '?' 63 */ 0, + /* '@' 64 */ IS_PCHAR, + /* 'A' 65 */ IS_PCHAR, + /* 'B' 66 */ IS_PCHAR, + /* 'C' 67 */ IS_PCHAR, + /* 'D' 68 */ IS_PCHAR, + /* 'E' 69 */ IS_PCHAR, + /* 'F' 70 */ IS_PCHAR, + /* 'G' 71 */ IS_PCHAR, + /* 'H' 72 */ IS_PCHAR, + /* 'I' 73 */ IS_PCHAR, + /* 'J' 74 */ IS_PCHAR, + /* 'K' 75 */ IS_PCHAR, + /* 'L' 76 */ IS_PCHAR, + /* 'M' 77 */ IS_PCHAR, + /* 'N' 78 */ IS_PCHAR, + /* 'O' 79 */ IS_PCHAR, + /* 'P' 80 */ IS_PCHAR, + /* 'Q' 81 */ IS_PCHAR, + /* 'R' 82 */ IS_PCHAR, + /* 'S' 83 */ IS_PCHAR, + /* 'T' 84 */ IS_PCHAR, + /* 'U' 85 */ IS_PCHAR, + /* 'V' 86 */ IS_PCHAR, + /* 'W' 87 */ IS_PCHAR, + /* 'X' 88 */ IS_PCHAR, + /* 'Y' 89 */ IS_PCHAR, + /* 'Z' 90 */ IS_PCHAR, + /* '[' 91 */ 0, + /* '\' 92 */ 0, + /* ']' 93 */ 0, + /* '^' 94 */ 0, + /* '_' 95 */ IS_PCHAR, + /* '`' 96 */ 0, + /* 'a' 97 */ IS_PCHAR, + /* 'b' 98 */ IS_PCHAR, + /* 'c' 99 */ IS_PCHAR, + /* 'd' 100 */ IS_PCHAR, + /* 'e' 101 */ IS_PCHAR, + /* 'f' 102 */ IS_PCHAR, + /* 'g' 103 */ IS_PCHAR, + /* 'h' 104 */ IS_PCHAR, + /* 'i' 105 */ IS_PCHAR, + /* 'j' 106 */ IS_PCHAR, + /* 'k' 107 */ IS_PCHAR, + /* 'l' 108 */ IS_PCHAR, + /* 'm' 109 */ IS_PCHAR, + /* 'n' 110 */ IS_PCHAR, + /* 'o' 111 */ IS_PCHAR, + /* 'p' 112 */ IS_PCHAR, + /* 'q' 113 */ IS_PCHAR, + /* 'r' 114 */ IS_PCHAR, + /* 's' 115 */ IS_PCHAR, + /* 't' 116 */ IS_PCHAR, + /* 'u' 117 */ IS_PCHAR, + /* 'v' 118 */ IS_PCHAR, + /* 'w' 119 */ IS_PCHAR, + /* 'x' 120 */ IS_PCHAR, + /* 'y' 121 */ IS_PCHAR, + /* 'z' 122 */ IS_PCHAR, + /* '{' 123 */ 0, + /* '|' 124 */ 0, + /* '}' 125 */ 0, + /* '~' 126 */ IS_PCHAR, + /* del 127 */ 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, + 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, +}; + +CF_INLINE Boolean is_pchar(unsigned char ch) { + return ( (sURLValidBytes[ch] & IS_PCHAR) != 0 ); +} + + /* CreateStringFromFileSystemRepresentationByAddingPercentEscapes creates a CFString for the path-absolute form of a URI path component from the native file system representation. + Note: this code uses '/' path separators The rules for path-absolute from rfc3986 are: path-absolute = "/" [ segment-nz *( "/" segment ) ] @@ -555,85 +801,105 @@ CF_INLINE Boolean _haveTestedOriginalString(CFURLRef url) { unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" */ -static CFStringRef CreateStringFromFileSystemRepresentationByAddingPercentEscapes(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex numBytes, Boolean windowsPath) +static CFStringRef CreateStringFromFileSystemRepresentationByAddingPercentEscapes(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex numBytes, Boolean isDirectory, Boolean isAbsolute, Boolean windowsPath, Boolean *addedPercentEncoding) { static const UInt8 hexchars[] = "0123456789ABCDEF"; - STACK_BUFFER_DECL(UInt8, stackBuf, PATH_MAX * 3); // worst case is every byte needs to be percent-escaped + const UInt8 *fileURLPrefixPtr; + size_t fileURLPrefixLength; + if ( AddAuthorityToFileURL() ) { + fileURLPrefixPtr = fileURLPrefixWithAuthority; + fileURLPrefixLength = sizeof(fileURLPrefixWithAuthority); + } + else { + fileURLPrefixPtr = fileURLPrefix; + fileURLPrefixLength = sizeof(fileURLPrefix); + } + STACK_BUFFER_DECL(UInt8, stackBuf, (PATH_MAX * 3) + (isAbsolute ? fileURLPrefixLength : 0) + (isDirectory ? 1 : 0)); // worst case is every byte needs to be percent-escaped UInt8 *bufStartPtr; UInt8 *bufBytePtr; const UInt8 *bytePtr = bytes; CFIndex idx; CFStringRef result; + Boolean addedPercent = FALSE; // choose a buffer to percent-escape into. if ( numBytes <= PATH_MAX ) { bufStartPtr = &stackBuf[0]; } else { - // worst case is every byte needs to be percent-escaped (numBytes * 3) - bufStartPtr = (UInt8 *)malloc(numBytes * 3); + // worst case is every byte needs to be percent-escaped + bufStartPtr = (UInt8 *)malloc((numBytes * 3) + (isAbsolute ? fileURLPrefixLength : 0) + (isDirectory ? 1 : 0)); } if ( bufStartPtr != NULL ) { - bufBytePtr = bufStartPtr; - for ( idx = 0; (idx < numBytes) && (*bytePtr != 0); ++idx ) { - switch ( *bytePtr ) { - // these are the visible 7-bit ascii characters that are not legal pchar octets - case '"': - case '#': - case '%': - case ';': // we need to percent-escape ';' in file system paths so it won't be mistaken for the start of the obsolete param rule (rfc2396) that CFURL still supports - case '<': - case '>': - case '?': // we need to percent-escape '?' in file system paths so it won't be mistaken for the start of a query - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': - // percent-escape non-pchar octets spread throughout the visible 7-bit ascii range + if ( isAbsolute ) { + // start with the fileURLPrefix + strcpy((char *)bufStartPtr, (char *)fileURLPrefixPtr); + bufBytePtr = bufStartPtr + fileURLPrefixLength - 1; + } + else { + bufBytePtr = bufStartPtr; + } + + if ( !windowsPath ) { + for ( idx = 0; (idx < numBytes) && (*bytePtr != 0); ++idx ) { + if ( is_pchar(*bytePtr) ) { + *bufBytePtr++ = *bytePtr; + } + else { *bufBytePtr++ = '%'; *bufBytePtr++ = hexchars[*bytePtr >> 4]; *bufBytePtr++ = hexchars[*bytePtr & 0x0f]; - break; - default: - if ( (*bytePtr <= ' ') || // percent-escape non-pchar octets that are space or less (control characters) - (*bytePtr >= 0x7f) || // percent-escape non-pchar octets that del and 8-bit ascii with the high bit set - (windowsPath && (*bytePtr == '/')) ) { // percent-escape the forward slash if this is a windowsPath - *bufBytePtr++ = '%'; - *bufBytePtr++ = hexchars[*bytePtr >> 4]; - *bufBytePtr++ = hexchars[*bytePtr & 0x0f]; - } - else { - // copy everything else - *bufBytePtr++ = *bytePtr; - } - break; + addedPercent = TRUE; + } + ++bytePtr; + } + } + else { + for ( idx = 0; (idx < numBytes) && (*bytePtr != 0); ++idx ) { + if ( is_pchar(*bytePtr) && (*bytePtr != '/') ) { // percent-escape the forward slash if this is a windowsPath + *bufBytePtr++ = *bytePtr; + } + else { + *bufBytePtr++ = '%'; + *bufBytePtr++ = hexchars[*bytePtr >> 4]; + *bufBytePtr++ = hexchars[*bytePtr & 0x0f]; + addedPercent = TRUE; + } + ++bytePtr; } - ++bytePtr; } // did we convert numBytes? - if ( idx == numBytes ) { - // create the result - result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), kCFStringEncodingUTF8, FALSE); - } - else { + if ( idx != numBytes ) { // no, but it's OK if the remaining bytes are all nul (embedded nul bytes are not allowed) - for ( /* start where we left off */; (idx < numBytes) && (bufStartPtr[idx] == 0); ++idx ) { + const UInt8 *nullBytePtr = bytePtr; + for ( /* start where we left off */; (idx < numBytes) && (*nullBytePtr == '\0'); ++idx, ++nullBytePtr ) { // do nothing } - if ( idx == numBytes ) { - // create the result - result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), kCFStringEncodingUTF8, FALSE); + } + + if ( idx == numBytes ) { + if ( isDirectory ) { + // if it is a directory and it doesn't end with PATH_SEP, append a PATH_SEP. + if ( bytes[numBytes-1] != '/' ) { + *bufBytePtr++ = '/'; + } } else { - // the remaining bytes were not all nul - result = NULL; + // it is not a directory: remove any pathDelim characters at end (leaving at least one character) + while ( (numBytes > 1) && (bytes[numBytes-1] == '/') ) { + --bufBytePtr; + --numBytes; + } } + + // create the result + result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), kCFStringEncodingUTF8, FALSE); + } + else { + // the remaining bytes were not all nul + result = NULL; } // free the buffer if we malloc'd it @@ -644,6 +910,11 @@ static CFStringRef CreateStringFromFileSystemRepresentationByAddingPercentEscape else { result = NULL; } + + if ( addedPercentEncoding ) { + *addedPercentEncoding = addedPercent; + } + return ( result ); } @@ -652,34 +923,11 @@ CF_INLINE CFStringRef _replacePathIllegalCharacters(CFStringRef str, CFAllocator CFStringRef result = NULL; STACK_BUFFER_DECL(char, buffer, PATH_MAX); if ( CFStringGetCString(str, buffer, PATH_MAX, kCFStringEncodingUTF8) ) { - result = CreateStringFromFileSystemRepresentationByAddingPercentEscapes(kCFAllocatorDefault, (const UInt8 *)buffer, strlen(buffer), !preserveSlashes); + result = CreateStringFromFileSystemRepresentationByAddingPercentEscapes(kCFAllocatorDefault, (const UInt8 *)buffer, strlen(buffer), FALSE, FALSE, !preserveSlashes, NULL); } return result; } -// We have 2 UniChars of a surrogate; we must convert to the correct percent-encoded UTF8 string and append to str. Added so that file system URLs can always be converted from POSIX to full URL representation. -- REW, 8/20/2001 -static Boolean _hackToConvertSurrogates(UniChar highChar, UniChar lowChar, CFMutableStringRef str) { - UniChar surrogate[2]; - uint8_t bytes[6]; // Aki sez it should never take more than 6 bytes - CFIndex len; - uint8_t *currByte; - surrogate[0] = highChar; - surrogate[1] = lowChar; - if (CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8, 0, surrogate, 2, NULL, bytes, 6, &len) != kCFStringEncodingConversionSuccess) { - return false; - } - for (currByte = bytes; currByte < bytes + len; currByte ++) { - UniChar escapeSequence[3] = {'%', '\0', '\0'}; - unsigned char high, low; - high = ((*currByte) & 0xf0) >> 4; - low = (*currByte) & 0x0f; - escapeSequence[1] = (high < 10) ? '0' + high : 'A' + high - 10; - escapeSequence[2] = (low < 10) ? '0' + low : 'A' + low - 10; - CFStringAppendCharacters(str, escapeSequence, 3); - } - return true; -} - static Boolean _appendPercentEscapesForCharacter(UniChar ch, CFStringEncoding encoding, CFMutableStringRef str) { uint8_t bytes[6]; // 6 bytes is the maximum a single character could require in UTF8 (most common case); other encodings could require more uint8_t *bytePtr = bytes, *currByte; @@ -713,6 +961,116 @@ static Boolean _appendPercentEscapesForCharacter(UniChar ch, CFStringEncoding en return true; } +static CFStringRef UnescapeAllWithUTF8(CFAllocatorRef alloc, CFStringRef originalString) +{ + CFStringRef result = NULL; + CFIndex strLength = CFStringGetLength(originalString); + CFIndex maxBufferSize = CFStringGetMaximumSizeForEncoding(strLength, kCFStringEncodingUTF8); + CFIndex stackBufferSize = 2096; + STACK_BUFFER_DECL(UInt8, escapedStackBuf, stackBufferSize *2); + UInt8 *escapedBuf; + UInt8 *unescapedBuf; + // choose a buffer to percent-escape into. + if ( maxBufferSize <= stackBufferSize ) { + escapedBuf = &escapedStackBuf[0]; + } + else { + escapedBuf = (UInt8 *)malloc(maxBufferSize * 2); + } + if ( escapedBuf ) { + CFIndex charsConverted; + CFIndex usedBufLen; + unescapedBuf = &escapedBuf[maxBufferSize]; + charsConverted = CFStringGetBytes(originalString, CFRangeMake(0, strLength), kCFStringEncodingUTF8, 0, false, escapedBuf, maxBufferSize, &usedBufLen); + if ( charsConverted ) { + // 0x80 marks invalid hex digits so this table can validate the digits while getting the values + static const UInt8 hexvalues[] = { + /* 00 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 08 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 10 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 18 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 20 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 28 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 30 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* 38 */ 0x08, 0x09, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 40 */ 0x80, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80, + /* 48 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 50 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 58 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 60 */ 0x80, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x80, + /* 68 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 70 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 78 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + + /* 80 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 88 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 90 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* 98 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* A0 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* A8 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* B0 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* B8 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* C0 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* C8 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* D0 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* D8 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* E0 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* E8 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* F0 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + /* F8 */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + }; + UInt8 *bufStartPtr; + UInt8 *bufPtr; + const UInt8 *bytePtr = escapedBuf; + CFIndex idx; + + bufPtr = bufStartPtr = unescapedBuf; + Boolean conversionOK = TRUE; + + for ( idx = 0; (idx < usedBufLen) && conversionOK; ++idx ) { + switch ( *bytePtr ) { + case '%': + idx += 2; + if ( idx < usedBufLen ) { + UInt8 hex1, hex2; + // skip over % + bytePtr++; + // get the hex digits + hex1 = hexvalues[*bytePtr++]; + hex2 = hexvalues[*bytePtr++]; + // validate them + if ( ((hex1 | hex2) & 0x80) == 0 ) { + // convert hex digits + *bufPtr = (hex1 << 4) + hex2; + } + else { + conversionOK = FALSE; + } + } + else { + conversionOK = FALSE; + } + break; + default: + // copy everything else + *bufPtr = *bytePtr++; + break; + } + ++bufPtr; + } + if ( conversionOK ) { + result = CFStringCreateWithBytes(alloc, unescapedBuf, bufPtr - bufStartPtr, kCFStringEncodingUTF8, false); + } + } + + // free the buffer if we malloc'd it + if ( escapedBuf != &escapedStackBuf[0] ) { + free(escapedBuf); + } + } + return ( result ); +} + // Uses UTF-8 to translate all percent escape sequences; returns NULL if it encounters a format failure. May return the original string. CFStringRef CFURLCreateStringByReplacingPercentEscapes(CFAllocatorRef alloc, CFStringRef originalString, CFStringRef charactersToLeaveEscaped) { CFMutableStringRef newStr = NULL; @@ -726,12 +1084,17 @@ CFStringRef CFURLCreateStringByReplacingPercentEscapes(CFAllocatorRef alloc, CF Boolean failed = false; if (!originalString) return NULL; - - if (charactersToLeaveEscaped == NULL) { + + length = CFStringGetLength(originalString); + + if ((length == 0) || (charactersToLeaveEscaped == NULL)) { return (CFStringRef)CFStringCreateCopy(alloc, originalString); } - - length = CFStringGetLength(originalString); + + if ( escapeAll ) { + return ( UnescapeAllWithUTF8(alloc, originalString) ); + } + searchRange = CFRangeMake(0, length); while (!failed && CFStringFindWithOptions(originalString, CFSTR("%"), searchRange, 0, &percentRange)) { @@ -775,6 +1138,7 @@ CFStringRef CFURLCreateStringByReplacingPercentEscapes(CFAllocatorRef alloc, CF if (!_translateBytes(ch1, ch2, bytes+j)) { failed = true; break; } } + // FIXME: This uses about 1/3 of the time spent in CFURLCreateStringByReplacingPercentEscapes // !!! We should do the low-level bit-twiddling ourselves; this is expensive! REW, 6/10/99 escapedStr = CFStringCreateWithBytes(alloc, bytes, numBytesExpected, kCFStringEncodingUTF8, false); if (!escapedStr) { @@ -809,7 +1173,7 @@ CFStringRef CFURLCreateStringByReplacingPercentEscapes(CFAllocatorRef alloc, CF newStr = CFStringCreateMutable(alloc, length); } if (percentRange.location - mark > 0) { - // The creation of this temporary string is unfortunate. + // FIXME: The creation of this temporary string is unfortunate. CFStringRef substring = CFStringCreateWithSubstring(alloc, originalString, CFRangeMake(mark, percentRange.location - mark)); CFStringAppend(newStr, substring); CFRelease(substring); @@ -910,7 +1274,7 @@ CFStringRef CFURLCreateStringByReplacingPercentEscapesUsingEncoding(CFAllocatorR newStr = CFStringCreateMutable(alloc, length); } if (percentRange.location - mark > 0) { - // The creation of this temporary string is unfortunate. + // FIXME: The creation of this temporary string is unfortunate. CFStringRef substring = CFStringCreateWithSubstring(alloc, originalString, CFRangeMake(mark, percentRange.location - mark)); CFStringAppend(newStr, substring); CFRelease(substring); @@ -956,11 +1320,24 @@ CFStringRef CFURLCreateStringByReplacingPercentEscapesUsingEncoding(CFAllocatorR } } +static Boolean _stringContainsCharacter(CFStringRef string, UniChar ch) { + CFIndex i, c = CFStringGetLength(string); + CFStringInlineBuffer buf; + CFStringInitInlineBuffer(string, &buf, CFRangeMake(0, c)); + for (i = 0; i < c; i ++) if (__CFStringGetCharacterFromInlineBufferQuick(&buf, i) == ch) return true; + return false; +} -static CFStringRef _addPercentEscapesToString(CFAllocatorRef allocator, CFStringRef originalString, Boolean (*shouldReplaceChar)(UniChar, void*), CFIndex (*handlePercentChar)(CFIndex, CFStringRef, CFStringRef *, void *), CFStringEncoding encoding, void *context) { +// Note: charactersToLeaveUnescaped and legalURLCharactersToBeEscaped only work for characters which can be represented as a single UTF16 codepoint. +CF_EXPORT CFStringRef CFURLCreateStringByAddingPercentEscapes(CFAllocatorRef allocator, CFStringRef originalString, CFStringRef charactersToLeaveUnescaped, CFStringRef legalURLCharactersToBeEscaped, CFStringEncoding encoding) { CFMutableStringRef newString = NULL; CFIndex idx, length; CFStringInlineBuffer buf; + enum { + kCharBufferMax = 4096, + }; + STACK_BUFFER_DECL(UniChar, charBuffer, kCharBufferMax); + CFIndex charBufferIndex = 0; if (!originalString) return NULL; length = CFStringGetLength(originalString); @@ -968,99 +1345,100 @@ static CFStringRef _addPercentEscapesToString(CFAllocatorRef allocator, CFString CFStringInitInlineBuffer(originalString, &buf, CFRangeMake(0, length)); for (idx = 0; idx < length; idx ++) { - UniChar ch = CFStringGetCharacterFromInlineBuffer(&buf, idx); - Boolean shouldReplace = shouldReplaceChar(ch, context); + UniChar ch = __CFStringGetCharacterFromInlineBufferQuick(&buf, idx); + Boolean shouldReplace = (isURLLegalCharacter(ch) == false); + if (shouldReplace) { + if (charactersToLeaveUnescaped && _stringContainsCharacter(charactersToLeaveUnescaped, ch)) { + shouldReplace = false; + } + } else if (legalURLCharactersToBeEscaped && _stringContainsCharacter(legalURLCharactersToBeEscaped, ch)) { + shouldReplace = true; + } + if (shouldReplace) { + enum { + kMaxBytesPerUniChar = 8, // 8 bytes is the maximum a single UniChar can require in any current encodings; future encodings could require more + kMaxPercentEncodedUniChars = kMaxBytesPerUniChar * 3 + }; + + static const UInt8 hexchars[] = "0123456789ABCDEF"; + uint8_t bytes[kMaxBytesPerUniChar]; + uint8_t *bytePtr = bytes; + uint8_t *currByte; + uint8_t *endPtr; + CFIndex byteLength; + // Perform the replacement - if (!newString) { + if ( !newString ) { newString = CFStringCreateMutableCopy(CFGetAllocator(originalString), 0, originalString); CFStringDelete(newString, CFRangeMake(idx, length-idx)); } - if (!_appendPercentEscapesForCharacter(ch, encoding, newString)) { -//#warning FIXME - once CFString supports finding glyph boundaries walk by glyph boundaries instead of by unichars - if (encoding == kCFStringEncodingUTF8 && CFCharacterSetIsSurrogateHighCharacter(ch) && idx + 1 < length && CFCharacterSetIsSurrogateLowCharacter(CFStringGetCharacterFromInlineBuffer(&buf, idx+1))) { - // Hack to guarantee we always safely convert file URLs between POSIX & full URL representation - if (_hackToConvertSurrogates(ch, CFStringGetCharacterFromInlineBuffer(&buf, idx+1), newString)) { - idx ++; // We consumed 2 characters, not 1 - } else { + // make sure charBuffer has enough room + if ( charBufferIndex >= (kCharBufferMax - kMaxPercentEncodedUniChars) ) { + // make room + CFStringAppendCharacters(newString, charBuffer, charBufferIndex); + charBufferIndex = 0; + } + + // convert the UniChar to bytes + if ( CFStringEncodingUnicodeToBytes(encoding, 0, &ch, 1, NULL, bytePtr, 8, &byteLength) == kCFStringEncodingConversionSuccess ) { + // percent-encode the bytes + endPtr = bytePtr + byteLength; + for ( currByte = bytePtr; currByte < endPtr; currByte++ ) { + charBuffer[charBufferIndex++] = '%'; + charBuffer[charBufferIndex++] = hexchars[*currByte >> 4]; + charBuffer[charBufferIndex++] = hexchars[*currByte & 0x0f]; + } + } + else { + // FIXME: once CFString supports finding glyph boundaries walk by glyph boundaries instead of by unichars + if ( encoding == kCFStringEncodingUTF8 && CFCharacterSetIsSurrogateHighCharacter(ch) && idx + 1 < length && CFCharacterSetIsSurrogateLowCharacter(__CFStringGetCharacterFromInlineBufferQuick(&buf, idx+1)) ) { + UniChar surrogate[2]; + uint8_t *currByte; + + surrogate[0] = ch; + surrogate[1] = __CFStringGetCharacterFromInlineBufferQuick(&buf, idx+1); + // Aki sez it should never take more than 6 bytes + if (CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8, 0, surrogate, 2, NULL, bytes, 6, &byteLength) == kCFStringEncodingConversionSuccess) { + endPtr = bytePtr + byteLength; + for ( currByte = bytes; currByte < endPtr; currByte++ ) { + charBuffer[charBufferIndex++] = '%'; + charBuffer[charBufferIndex++] = hexchars[*currByte >> 4]; + charBuffer[charBufferIndex++] = hexchars[*currByte & 0x0f]; + } + idx++; // We consumed 2 characters, not 1 + } + else { + // surrogate pair conversion failed break; } } else { + // not a surrogate pair break; } } - } else if (ch == '%' && handlePercentChar) { - CFStringRef replacementString = NULL; - CFIndex newIndex = handlePercentChar(idx, originalString, &replacementString, context); - if (newIndex < 0) { - break; - } else if (replacementString) { - if (!newString) { - newString = CFStringCreateMutableCopy(CFGetAllocator(originalString), 0, originalString); - CFStringDelete(newString, CFRangeMake(idx, length-idx)); - } - CFStringAppend(newString, replacementString); - CFRelease(replacementString); - } - if (newIndex == idx) { - if (newString) { - CFStringAppendCharacters(newString, &ch, 1); - } - } else { - if (!replacementString && newString) { - CFIndex tmpIndex; - for (tmpIndex = idx; tmpIndex < newIndex; tmpIndex ++) { - ch = CFStringGetCharacterAtIndex(originalString, idx); - CFStringAppendCharacters(newString, &ch, 1); - } - } - idx = newIndex - 1; - } } else if (newString) { - CFStringAppendCharacters(newString, &ch, 1); + charBuffer[charBufferIndex++] = ch; + if ( charBufferIndex == kCharBufferMax ) { + CFStringAppendCharacters(newString, charBuffer, charBufferIndex); + charBufferIndex = 0; + } } } if (idx < length) { - // Ran in to an encoding failure + // Ran into an encoding failure if (newString) CFRelease(newString); return NULL; } else if (newString) { + if ( charBufferIndex != 0 ) { + CFStringAppendCharacters(newString, charBuffer, charBufferIndex); + } return newString; } else { return (CFStringRef)CFStringCreateCopy(CFGetAllocator(originalString), originalString); } } - -static Boolean _stringContainsCharacter(CFStringRef string, UniChar ch) { - CFIndex i, c = CFStringGetLength(string); - CFStringInlineBuffer buf; - CFStringInitInlineBuffer(string, &buf, CFRangeMake(0, c)); - for (i = 0; i < c; i ++) if (__CFStringGetCharacterFromInlineBufferQuick(&buf, i) == ch) return true; - return false; -} - -static Boolean _shouldPercentReplaceChar(UniChar ch, void *context) { - CFStringRef unescape = ((CFStringRef *)context)[0]; - CFStringRef escape = ((CFStringRef *)context)[1]; - Boolean shouldReplace = (isURLLegalCharacter(ch) == false); - if (shouldReplace) { - if (unescape && _stringContainsCharacter(unescape, ch)) { - shouldReplace = false; - } - } else if (escape && _stringContainsCharacter(escape, ch)) { - shouldReplace = true; - } - return shouldReplace; -} - -CF_EXPORT CFStringRef CFURLCreateStringByAddingPercentEscapes(CFAllocatorRef allocator, CFStringRef originalString, CFStringRef charactersToLeaveUnescaped, CFStringRef legalURLCharactersToBeEscaped, CFStringEncoding encoding) { - CFStringRef strings[2]; - strings[0] = charactersToLeaveUnescaped; - strings[1] = legalURLCharactersToBeEscaped; - return _addPercentEscapesToString(allocator, originalString, _shouldPercentReplaceChar, NULL, encoding, strings); -} - static Boolean __CFURLEqual(CFTypeRef cf1, CFTypeRef cf2) { Boolean result; CFURLRef url1 = (CFURLRef)cf1; @@ -1108,39 +1486,111 @@ static CFHashCode __CFURLHash(CFTypeRef cf) return ( result ); } -static CFStringRef __CFURLCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { - CFURLRef url = (CFURLRef)cf; - __CFGenericValidateType(cf, CFURLGetTypeID()); - if (! url->_base) { - CFRetain(url->_string); - return url->_string; - } else { - // Do not dereference url->_base; it may be an ObjC object - return CFStringCreateWithFormat(CFGetAllocator(url), NULL, CFSTR("%@ -- %@"), url->_string, url->_base); +static CFStringRef CreateTruncatedURLString(CFAllocatorRef alloc, CFStringRef urlString, CFIndex maxLength, CFIndex suffixLength) +{ + CFStringRef result; + + CFIndex len = CFStringGetLength(urlString); + if ( len <= maxLength ) { + // return the retained urlString + result = CFStringCreateCopy(alloc, urlString); } -} - + else { + CFStringRef start = CFStringCreateWithSubstring(alloc, urlString, CFRangeMake(0, maxLength - suffixLength)); + CFStringRef end = CFStringCreateWithSubstring(alloc, urlString, CFRangeMake(len - suffixLength, suffixLength)); + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@ ... %@"), start, end); + if ( start ) { + CFRelease(start); + } + if ( (end) ) { + CFRelease(end); + } + } + return ( result ); +} + +static CFStringRef __CFURLCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { + CFStringRef result; + CFURLRef url = (CFURLRef)cf; + __CFGenericValidateType(cf, CFURLGetTypeID()); + CFAllocatorRef alloc = CFGetAllocator(url); + + Boolean isDataURL = false; + CFStringRef scheme = CFURLCopyScheme(url); + if ( scheme ) { + isDataURL = CFStringCompare(scheme, kCFURLDataScheme, kCFCompareCaseInsensitive) == kCFCompareEqualTo; + CFRelease(scheme); + } + + if ( !isDataURL ) { + if (!url->_base) { + { + result = CFStringCreateCopy(alloc, url->_string); + } + } else { + // Do not dereference url->_base; it may be an ObjC object + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@ -- %@"), url->_string, url->_base); + } + } + else { + if ( !url->_base ) { + result = CreateTruncatedURLString(alloc, url->_string, 128, 8); + } + else { + CFStringRef urlString = CreateTruncatedURLString(alloc, url->_string, 128, 8); + CFStringRef baseString = CreateTruncatedURLString(alloc, CFURLGetString(url->_base), 128, 8); + // Do not dereference url->_base; it may be an ObjC object + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@ -- %@"), urlString, baseString); + if ( urlString ) { + CFRelease(urlString); + } + if ( baseString ) { + CFRelease(baseString); + } + } + } + return ( result ); +} + static CFStringRef __CFURLCopyDescription(CFTypeRef cf) { CFURLRef url = (CFURLRef)cf; CFStringRef result; CFAllocatorRef alloc = CFGetAllocator(url); - if ( url->_base) { - CFStringRef baseString = CFCopyDescription(url->_base); - result = CFStringCreateWithFormat(alloc, NULL, CFSTR("{string = %@, encoding = %d\n\tbase = %@}"), cf, alloc, url->_string, url->_encoding, baseString); - CFRelease(baseString); - } else { - result = CFStringCreateWithFormat(alloc, NULL, CFSTR("{string = %@, encoding = %d, base = (null)}"), cf, alloc, url->_string, url->_encoding); + Boolean isDataURL = false; + CFStringRef scheme = CFURLCopyScheme(url); + + if ( scheme ) { + isDataURL = CFStringCompare(scheme, kCFURLDataScheme, kCFCompareCaseInsensitive) == kCFCompareEqualTo; + CFRelease(scheme); + } + + if ( !isDataURL ) { + if ( url->_base) { + CFStringRef baseString = CFCopyDescription(url->_base); + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("{string = %@, encoding = %u\n\tbase = %@}"), cf, alloc, url->_string, (unsigned int)(url->_encoding), baseString); + CFRelease(baseString); + } else { + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("{string = %@, encoding = %u, base = (null)}"), cf, alloc, url->_string, (unsigned int)(url->_encoding)); + } + } + else { + CFStringRef urlString = CreateTruncatedURLString(alloc, url->_string, 128, 8); + if ( url->_base) { + CFStringRef baseString = CFCopyDescription(url->_base); + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("{string = %@, encoding = %u\n\tbase = %@}"), cf, alloc, urlString, (unsigned int)(url->_encoding), baseString); + CFRelease(baseString); + } else { + result = CFStringCreateWithFormat(alloc, NULL, CFSTR("{string = %@, encoding = %u, base = (null)}"), cf, alloc, urlString, (unsigned int)(url->_encoding)); + } + CFRelease(urlString); } return result; } #if DEBUG_URL_MEMORY_USAGE - extern __attribute((used)) void __CFURLDumpMemRecord(void) { - CFStringRef str = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%d URLs created; %d destroyed\n%d file URLs created; %d urls had 'extra' data allocated, %d had base urls, %d were not UTF8 encoded\n"), numURLs, numDealloced, numFileURLsCreated, numExtraDataAllocated, numURLsWithBaseURL, numNonUTF8EncodedURLs ); - CFShow(str); - CFRelease(str); + 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); } #endif @@ -1177,24 +1627,7 @@ static const CFRuntimeClass __CFURLClass = { NULL, // refcount }; -// When __CONSTANT_CFSTRINGS__ is not defined, we have separate macros for static and exported constant strings, but -// when it is defined, we must prefix with static to prevent the string from being exported -#ifdef __CONSTANT_CFSTRINGS__ -static CONST_STRING_DECL(kCFURLHTTPScheme, "http") -static CONST_STRING_DECL(kCFURLHTTPSScheme, "https") -static CONST_STRING_DECL(kCFURLFileScheme, "file") -static CONST_STRING_DECL(kCFURLDataScheme, "data") -static CONST_STRING_DECL(kCFURLFTPScheme, "ftp") -static CONST_STRING_DECL(kCFURLLocalhost, "localhost") -#else -CONST_STRING_DECL(kCFURLHTTPScheme, "http") -CONST_STRING_DECL(kCFURLHTTPSScheme, "https") -CONST_STRING_DECL(kCFURLFileScheme, "file") -CONST_STRING_DECL(kCFURLDataScheme, "data") -CONST_STRING_DECL(kCFURLFTPScheme, "ftp") -CONST_STRING_DECL(kCFURLLocalhost, "localhost") -#endif -__private_extern__ void __CFURLInitialize(void) { +CF_PRIVATE void __CFURLInitialize(void) { __kCFURLTypeID = _CFRuntimeRegisterClass(&__CFURLClass); } @@ -1208,7 +1641,7 @@ CFTypeID CFURLGetTypeID(void) { return __kCFURLTypeID; } -__private_extern__ void CFShowURL(CFURLRef url) { +CF_PRIVATE void CFShowURL(CFURLRef url) { if (!url) { fprintf(stdout, "(null)\n"); return; @@ -1234,12 +1667,12 @@ __private_extern__ void CFShowURL(CFURLRef url) { /***************************************************/ /* URL creation and String/Data creation from URLS */ /***************************************************/ -static void constructBuffers(CFAllocatorRef alloc, CFStringRef string, Boolean useEightBitStringEncoding, UInt8 *inBuffer, CFIndex inBufferSize, const char **cstring, const UniChar **ustring, Boolean *useCString, Boolean *freeCharacters) { +static void constructBuffers(CFAllocatorRef alloc, CFStringRef string, UInt8 *inBuffer, CFIndex inBufferSize, const char **cstring, const UniChar **ustring, Boolean *useCString, Boolean *freeCharacters) { CFIndex neededLength; CFIndex length; CFRange rg; - *cstring = CFStringGetCStringPtr(string, (useEightBitStringEncoding ? __CFStringGetEightBitStringEncoding() : kCFStringEncodingISOLatin1)); + *cstring = CFStringGetCStringPtr(string, kCFStringEncodingISOLatin1); if (*cstring) { *ustring = NULL; *useCString = true; @@ -1286,315 +1719,56 @@ static void constructBuffers(CFAllocatorRef alloc, CFStringRef string, Boolean u } } -#define STRING_CHAR(x) (useCString ? cstring[(x)] : ustring[(x)]) +static void _parseComponentsCString(CFAllocatorRef alloc, CFURLRef baseURL, UInt32 *theFlags, CFRange **range, CFIndex cfStringLength, const char *characterArray) +#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) +#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) { - 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. */ - - CFIndex idx, base_idx = 0; - CFIndex string_length; - UInt32 flags = *theFlags; - Boolean useEightBitStringEncoding = (flags & USES_EIGHTBITSTRINGENCODING) != 0; - Boolean useCString, freeCharacters, isCompliant; - uint8_t numRanges = 0; + CFIndex cfStringLength = CFStringGetLength(string); + Boolean useCString, freeCharacters; const char *cstring = NULL; const UniChar *ustring = NULL; CFIndex stackBufferSize = 4096; STACK_BUFFER_DECL(UInt8, stackBuffer, stackBufferSize); - string_length = CFStringGetLength(string); - constructBuffers(alloc, string, useEightBitStringEncoding, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); + constructBuffers(alloc, string, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); - // Algorithm is as described in RFC 1808 - // 1: parse the fragment; remainder after left-most "#" is fragment - for (idx = base_idx; idx < string_length; idx++) { - if ('#' == STRING_CHAR(idx)) { - flags |= HAS_FRAGMENT; - ranges[8].location = idx + 1; - ranges[8].length = string_length - (idx + 1); - numRanges ++; - string_length = idx; // remove fragment from parse string - break; - } + if (useCString) { + _parseComponentsCString(alloc, baseURL, theFlags, range, cfStringLength, cstring); } - // 2: parse the scheme - for (idx = base_idx; idx < string_length; idx++) { - UniChar ch = STRING_CHAR(idx); - if (':' == ch) { - flags |= HAS_SCHEME; - flags |= IS_ABSOLUTE; - ranges[0].location = base_idx; - ranges[0].length = idx; - numRanges ++; - base_idx = idx + 1; - // optimization for ftp urls - if (idx == 3 && STRING_CHAR(0) == 'f' && STRING_CHAR(1) == 't' && STRING_CHAR(2) == 'p') { - _setSchemeTypeInFlags(&flags, kHasFtpScheme); - } - else if (idx == 4) { - // optimization for http urls - if (STRING_CHAR(0) == 'h' && STRING_CHAR(1) == 't' && STRING_CHAR(2) == 't' && STRING_CHAR(3) == 'p') { - _setSchemeTypeInFlags(&flags, kHasHttpScheme); - } - // optimization for file urls - if (STRING_CHAR(0) == 'f' && STRING_CHAR(1) == 'i' && STRING_CHAR(2) == 'l' && STRING_CHAR(3) == 'e') { - _setSchemeTypeInFlags(&flags, kHasFileScheme); - } - // optimization for data urls - if (STRING_CHAR(0) == 'd' && STRING_CHAR(1) == 'a' && STRING_CHAR(2) == 't' && STRING_CHAR(3) == 'a') { - _setSchemeTypeInFlags(&flags, kHasDataScheme); - } - } - // optimization for https urls - else if (idx == 5 && STRING_CHAR(0) == 'h' && STRING_CHAR(1) == 't' && STRING_CHAR(2) == 't' && STRING_CHAR(3) == 'p' && STRING_CHAR(3) == 's') { - _setSchemeTypeInFlags(&flags, kHasHttpsScheme); - } - break; - } else if (!scheme_valid(ch)) { - break; // invalid scheme character -- no scheme - } - } - - // Make sure we have an RFC-1808 compliant URL - that's either something without a scheme, or scheme:/(stuff) or scheme://(stuff) - // Strictly speaking, RFC 1808 & 2396 bar "scheme:" (with nothing following the colon); however, common usage - // expects this to be treated identically to "scheme://" - REW, 12/08/03 - if (!(flags & HAS_SCHEME)) { - isCompliant = true; - } else if (base_idx == string_length) { - isCompliant = false; - } else if (STRING_CHAR(base_idx) != '/') { - isCompliant = false; - } else { - isCompliant = true; - } - - if (!isCompliant) { - // Clear the fragment flag if it's been set - if (flags & HAS_FRAGMENT) { - flags &= (~HAS_FRAGMENT); - string_length = CFStringGetLength(string); - } - (*theFlags) = flags; - (*range) = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0); - (*range)->location = ranges[0].location; - (*range)->length = ranges[0].length; - - if (freeCharacters) { - CFAllocatorDeallocate(alloc, useCString ? (void *)cstring : (void *)ustring); - } - return; + else { + _parseComponentsUString(alloc, baseURL, theFlags, range, cfStringLength, ustring); } - // URL is 1808-compliant - flags |= IS_DECOMPOSABLE; - // 3: parse the network location and login - if (2 <= (string_length - base_idx) && '/' == STRING_CHAR(base_idx) && '/' == STRING_CHAR(base_idx+1)) { - CFIndex base = 2 + base_idx, extent; - for (idx = base; idx < string_length; idx++) { - if ('/' == STRING_CHAR(idx) || '?' == STRING_CHAR(idx)) break; - } - extent = idx; - - // 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 ('@' == STRING_CHAR(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 (':' == STRING_CHAR(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; - break; - } - } - flags |= HAS_HOST; - numRanges ++; - ranges[3].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 ('[' == STRING_CHAR(idx)) { // starting IPV6 explicit address - // Find the ']' terminator of the IPv6 address, leave idx pointing to ']' or end - for ( ; idx < extent; ++ idx ) { - if ( ']' == STRING_CHAR(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 ( ':' == STRING_CHAR(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; - } - } - if (!(flags & HAS_PORT)) { - ranges[3].length = extent - base; // host extent - } - } - base_idx = extent; - } - - // 4: parse the query; remainder after left-most "?" is query - for (idx = base_idx; idx < string_length; idx++) { - if ('?' == STRING_CHAR(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; - } - } - - // 5: parse the parameters; remainder after left-most ";" is parameters - for (idx = base_idx; idx < string_length; idx++) { - if (';' == STRING_CHAR(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; - } - } - - // 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 ('%' == STRING_CHAR(idx)) { - sawPercent = TRUE; - break; - } - } -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI - if (pathRg.length > 6 && STRING_CHAR(pathRg.location) == '/' && STRING_CHAR(pathRg.location + 1) == '.' && STRING_CHAR(pathRg.location + 2) == 'f' && STRING_CHAR(pathRg.location + 3) == 'i' && STRING_CHAR(pathRg.location + 4) == 'l' && STRING_CHAR(pathRg.location + 5) == 'e' && STRING_CHAR(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; - } -#endif - - ch = STRING_CHAR(pathRg.location + pathRg.length - 1); - if (ch == '/') { - isDir = true; - } else if (ch == '.') { - if (pathRg.length == 1) { - isDir = true; - } else { - ch = STRING_CHAR(pathRg.location + pathRg.length - 2); - if (ch == '/') { - isDir = true; - } else if (ch != '.') { - isDir = false; - } else if (pathRg.length == 2) { - isDir = true; - } else { - isDir = (STRING_CHAR(pathRg.location + pathRg.length - 3) == '/'); - } - } - } else { - isDir = false; - } - } else { - isDir = (baseURL != NULL) ? CFURLHasDirectoryPath(baseURL) : false; - } - if (isDir) { - flags |= IS_DIRECTORY; - } - } - if (freeCharacters) { CFAllocatorDeallocate(alloc, useCString ? (void *)cstring : (void *)ustring); } - (*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 ++; - } - } } +static Boolean scanCharactersCString(CFAllocatorRef alloc, CFMutableStringRef *escapedString, UInt32 *flags, const char *characterArray, Boolean useCString, CFIndex base, CFIndex end, CFIndex *mark, UInt32 componentFlag, CFStringEncoding encoding) +#define CFURL_INCLUDE_SCAN_CHARACTERS +#include "CFURL.inc.h" +#undef CFURL_INCLUDE_SCAN_CHARACTERS + +static Boolean scanCharactersUString(CFAllocatorRef alloc, CFMutableStringRef *escapedString, UInt32 *flags, const UniChar *characterArray, Boolean useCString, CFIndex base, CFIndex end, CFIndex *mark, UInt32 componentFlag, CFStringEncoding encoding) +#define CFURL_INCLUDE_SCAN_CHARACTERS +#include "CFURL.inc.h" +#undef CFURL_INCLUDE_SCAN_CHARACTERS + static Boolean scanCharacters(CFAllocatorRef alloc, CFMutableStringRef *escapedString, UInt32 *flags, const char *cstring, const UniChar *ustring, Boolean useCString, CFIndex base, CFIndex end, CFIndex *mark, UInt32 componentFlag, CFStringEncoding encoding) { - CFIndex idx; - Boolean sawIllegalChar = false; - for (idx = base; idx < end; idx ++) { - Boolean shouldEscape; - UniChar ch = STRING_CHAR(idx); - if (isURLLegalCharacter(ch)) { - if ((componentFlag == HAS_USER || componentFlag == HAS_PASSWORD) && (ch == '/' || ch == '?' || ch == '@')) { - shouldEscape = true; - } else { - shouldEscape = false; - } - } else if (ch == '%' && idx + 2 < end && isHexDigit(STRING_CHAR(idx + 1)) && isHexDigit(STRING_CHAR(idx+2))) { - shouldEscape = false; - } else if (componentFlag == HAS_HOST && ((idx == base && ch == '[') || (idx == end-1 && ch == ']'))) { - shouldEscape = false; - } else { - shouldEscape = true; - } - if (shouldEscape) { - sawIllegalChar = true; - if (componentFlag && flags) { - *flags |= componentFlag; - } - if (!*escapedString) { - *escapedString = CFStringCreateMutable(alloc, 0); - } - if (useCString) { - CFStringRef tempString = CFStringCreateWithBytes(alloc, (uint8_t *)&(cstring[*mark]), idx - *mark, kCFStringEncodingISOLatin1, false); - CFStringAppend(*escapedString, tempString); - CFRelease(tempString); - } else { - CFStringAppendCharacters(*escapedString, &(ustring[*mark]), idx - *mark); - } - *mark = idx + 1; - _appendPercentEscapesForCharacter(ch, encoding, *escapedString); // This can never fail because anURL->_string was constructed from the encoding passed in - } + if ( useCString ) { + return ( scanCharactersCString(alloc, escapedString, flags, cstring, useCString, base, end, mark, componentFlag, encoding)); + } + else { + return ( scanCharactersUString(alloc, escapedString, flags, ustring, useCString, base, end, mark, componentFlag, encoding)); } - return sawIllegalChar; -} +} static void computeSanitizedString(CFURLRef url) { CFAllocatorRef alloc = CFGetAllocator(url); @@ -1608,9 +1782,8 @@ static void computeSanitizedString(CFURLRef url) { STACK_BUFFER_DECL(UInt8, stackBuffer, stackBufferSize); CFMutableStringRef sanitizedString = NULL; UInt32 additionalDataFlags = 0; - Boolean useEightBitStringEncoding = (url->_flags & USES_EIGHTBITSTRINGENCODING) != 0; - constructBuffers(alloc, url->_string, useEightBitStringEncoding, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); + constructBuffers(alloc, url->_string, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); if (!(url->_flags & IS_DECOMPOSABLE)) { // Impossible to have a problem character in the scheme base = _rangeForComponent(url->_flags, url->_ranges, HAS_SCHEME).length + 1; @@ -1628,7 +1801,7 @@ static void computeSanitizedString(CFURLRef url) { while (currentComponent < (HAS_FRAGMENT << 1)) { CFRange componentRange = _rangeForComponent(url->_flags, url->_ranges, currentComponent); if (componentRange.location != kCFNotFound) { - scanCharacters(alloc, & sanitizedString, &additionalDataFlags, cstring, ustring, useCString, componentRange.location, componentRange.location + componentRange.length, &mark, currentComponent, url->_encoding); + scanCharacters(alloc, &sanitizedString, &additionalDataFlags, cstring, ustring, useCString, componentRange.location, componentRange.location + componentRange.length, &mark, currentComponent, url->_encoding); } currentComponent = currentComponent << 1; } @@ -1640,9 +1813,7 @@ static void computeSanitizedString(CFURLRef url) { } if (sanitizedString && mark != string_length) { if (useCString) { - CFStringRef tempString = CFStringCreateWithBytes(alloc, (uint8_t *)&(cstring[mark]), string_length - mark, kCFStringEncodingISOLatin1, false); - CFStringAppend(sanitizedString, tempString); - CFRelease(tempString); + __CFStringAppendBytes(sanitizedString, (char *)&(cstring[mark]), string_length - mark, kCFStringEncodingISOLatin1); } else { CFStringAppendCharacters(sanitizedString, &(ustring[mark]), string_length - mark); } @@ -1668,14 +1839,12 @@ static CFStringRef correctedComponent(CFStringRef comp, UInt32 compFlag, CFStrin CFIndex stackBufferSize = 1024; STACK_BUFFER_DECL(UInt8, stackBuffer, stackBufferSize); - constructBuffers(alloc, comp, false, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); + constructBuffers(alloc, comp, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters); scanCharacters(alloc, &result, NULL, cstring, ustring, useCString, 0, string_length, &mark, compFlag, enc); if (result) { if (mark < string_length) { if (useCString) { - CFStringRef tempString = CFStringCreateWithBytes(alloc, (uint8_t *)&(cstring[mark]), string_length - mark, kCFStringEncodingISOLatin1, false); - CFStringAppend(result, tempString); - CFRelease(tempString); + __CFStringAppendBytes(result, (char *)&(cstring[mark]), string_length - mark, kCFStringEncodingISOLatin1); } else { CFStringAppendCharacters(result, &(ustring[mark]), string_length - mark); } @@ -1691,11 +1860,14 @@ static CFStringRef correctedComponent(CFStringRef comp, UInt32 compFlag, CFStrin return result; } -#undef STRING_CHAR + CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator) { struct __CFURL *url; #if DEBUG_URL_MEMORY_USAGE numURLs ++; +// if ( numURLs % 1000 == 0 ) { +// __CFURLDumpMemRecord(); +// } #endif url = (struct __CFURL *)_CFRuntimeCreateInstance(allocator, __kCFURLTypeID, sizeof(struct __CFURL) - sizeof(CFRuntimeBase), NULL); if (url) { @@ -1710,196 +1882,433 @@ CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator) { 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. This ALSO means it's the caller's responsibility to set the IS_ABSOLUTE bit, since we may have a degenerate URL whose string is relative, but lacks a base. -static void _CFURLInit(struct __CFURL *url, CFStringRef URLString, UInt32 fsType, CFURLRef base) { - CFAssert2((fsType == FULL_URL_REPRESENTATION) || (fsType == kCFURLPOSIXPathStyle) || (fsType == kCFURLWindowsPathStyle) || (fsType == kCFURLHFSPathStyle), __kCFLogAssertion, "%s(): Received bad fsType %d", __PRETTY_FUNCTION__, fsType); +// 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->_string = CFStringCreateCopy(CFGetAllocator(url), URLString); url->_base = base ? CFURLCopyAbsoluteURL(base) : NULL; #if DEBUG_URL_MEMORY_USAGE - if ( (fsType == kCFURLPOSIXPathStyle) || (fsType == kCFURLHFSPathStyle) || (fsType == kCFURLWindowsPathStyle) ) { - numFileURLsCreated ++; - } if ( url->_base ) { numURLsWithBaseURL ++; } #endif - if (fsType != FULL_URL_REPRESENTATION) { - // _convertToURLRepresentation parses the URL - _convertToURLRepresentation((struct __CFURL *)url, fsType); - } - else { + if ( parseURL ) { +#if DEBUG_URL_MEMORY_USAGE + numFileURLsParsed++; +#endif _parseComponentsOfURL(url); } } -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX -CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path) { - CFIndex len = CFStringGetLength(path); - if (len && CFStringGetCharacterAtIndex(path, 0) == '/') { - _CFURLInit((struct __CFURL *)url, path, kCFURLPOSIXPathStyle, NULL); - ((struct __CFURL *)url)->_flags |= IS_ABSOLUTE; - } else { - CFURLRef cwdURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(url)); - _CFURLInit((struct __CFURL *)url, path, kCFURLPOSIXPathStyle, cwdURL); - if ( cwdURL ) - CFRelease(cwdURL); +static Boolean _CFStringIsLegalURLString(CFStringRef string) { + Boolean result = true; + if ( string ) { + CFStringInlineBuffer stringBuffer; + Boolean sawHash = false; + CFIndex idx = 0; + CFIndex checkHexDigit = 0; + CFIndex length; + + length = CFStringGetLength(string); + { + CFStringInitInlineBuffer(string, &stringBuffer, CFRangeMake(0, length)); + + while ( idx < length ) { + CFIndex rangeLength; + const UniChar *chPtr; + + rangeLength = (idx + __kCFStringInlineBufferLength <= length) ? __kCFStringInlineBufferLength : length - idx; + chPtr = CFStringGetCharactersPtrFromInlineBuffer(&stringBuffer, CFRangeMake(idx, rangeLength)); + for ( CFIndex rangeIdx = 0; rangeIdx < rangeLength; ++rangeIdx, ++chPtr ) { + if ( !checkHexDigit ) { + if ( *chPtr == '%' ) { + // percent encoded? make sure there at least 2 characters left to check + if ( (idx + rangeIdx + 2) < length ) { + // the next 2 characters must be HEXDIG + checkHexDigit = 2; + continue; + } + else { + result = false; + break; + } + } + if ( *chPtr == '[' || *chPtr == ']' ) { + continue; // IPV6 support (RFC 2732) DCJ June/10/2002 + } + if ( *chPtr == '#' ) { + // only allow one # character + if ( !sawHash ) { + sawHash = true; + continue; + } + else { + result = false; + break; + } + } +#if DEPLOYMENT_TARGET_WINDOWS + // CF on Windows: CFURLCreateWithString should work with | in path on Windows + if ( isURLLegalCharacter(*chPtr) || *chPtr == '|' ) { + continue; + } +#else + if ( isURLLegalCharacter(*chPtr) ) { + continue; + } +#endif + else { + result = false; + break; + } + } + else { + if ( isHexDigit(*chPtr) ) { + --checkHexDigit; + continue; + } + else { + result = false; + break; + } + } + } + + if ( !result ) { + break; // out of main while loop + } + + idx += rangeLength; + } + } } - if (!len || '/' == CFStringGetCharacterAtIndex(path, len - 1)) - ((struct __CFURL *)url)->_flags |= IS_DIRECTORY; -} -#elif DEPLOYMENT_TARGET_WINDOWS -CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path) { - CFIndex len = CFStringGetLength(path); - // be sure to use the windows path separator when checking the path to see if it's a directory here - if (!len || '\\' == CFStringGetCharacterAtIndex(path, len - 1)) - ((struct __CFURL *)url)->_flags |= IS_DIRECTORY; - UniChar firstChar = 0 < len ? CFStringGetCharacterAtIndex(path, 0) : 0; - UniChar secondChar = 1 < len ? CFStringGetCharacterAtIndex(path, 1) : 0; - Boolean isDrive = ('A' <= firstChar && firstChar <= 'Z') || ('a' <= firstChar && firstChar <= 'z'); - if (!len || '/' == CFStringGetCharacterAtIndex(path, len - 1)) - ((struct __CFURL *)url)->_flags |= IS_DIRECTORY; - isDrive = isDrive && (secondChar == ':' || secondChar == '|'); - if (isDrive || (firstChar == '\\' && secondChar == '\\')) { - _CFURLInit((struct __CFURL *)url, path, kCFURLWindowsPathStyle, NULL); - ((struct __CFURL *)url)->_flags |= IS_ABSOLUTE; - } else if (firstChar == '/') { - if (!len || '/' == CFStringGetCharacterAtIndex(path, len - 1)) - ((struct __CFURL *)url)->_flags |= IS_DIRECTORY; - _CFURLInit((struct __CFURL *)url, path, kCFURLPOSIXPathStyle, NULL); - ((struct __CFURL *)url)->_flags |= IS_ABSOLUTE; - } else { - CFURLRef cwdURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(url)); - _CFURLInit((struct __CFURL *)url, path, kCFURLPOSIXPathStyle, cwdURL); - if ( cwdURL ) - CFRelease(cwdURL); + else { + CFAssert(false, __kCFLogAssertion, "Cannot create an CFURL from a NULL string"); + result = false; } + + return ( result ); } -#endif -// Exported for Foundation's use -CF_EXPORT Boolean _CFStringIsLegalURLString(CFStringRef string) { - // Check each character to make sure it is a legal URL char. The valid characters are 'A'-'Z', 'a' - 'z', '0' - '9', plus the characters in "-_.!~*'()", and the set of reserved characters (these characters have special meanings in the URL syntax), which are ";/?:@&=+$,". In addition, percent escape sequences '%' hex-digit hex-digit are permitted. - // Plus the hash character '#' which denotes the beginning of a fragment, and can appear exactly once in the entire URL string. -- REW, 12/13/2000 - CFStringInlineBuffer stringBuffer; - CFIndex idx = 0, length; - Boolean sawHash = false; - if (!string) { - CFAssert(false, __kCFLogAssertion, "Cannot create an CFURL from a NULL string"); - return false; +/* initializes a URL object with a URL string */ +CF_EXPORT Boolean _CFURLInitWithURLString(CFURLRef uninitializedURL, CFStringRef string, Boolean checkForLegalCharacters, CFURLRef baseURL) +{ +#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 ) { + // determine if URL is absolute (i.e. it has a scheme and the scheme characters are valid + CFStringInlineBuffer stringBuffer; + CFIndex length = CFStringGetLength(string); + CFIndex idx = 0; + Boolean isAbsolute = false; + Boolean schemeCharsValid = true; + + CFStringInitInlineBuffer(string, &stringBuffer, CFRangeMake(0, length)); + // the first character of the scheme must be ALPHA + if ( (length > 0) && isALPHA(__CFStringGetCharacterFromInlineBufferQuick(&stringBuffer, 0)) ) { + // stop looking if we hit the end of the string, find a colon (isAbsolute), or find a non-scheme character (schemeCharsValid) + while (idx < length && schemeCharsValid && !isAbsolute) { + CFIndex rangeLength = (idx + __kCFStringInlineBufferLength <= length) ? __kCFStringInlineBufferLength : length - idx; + const UniChar *chPtr = CFStringGetCharactersPtrFromInlineBuffer(&stringBuffer, CFRangeMake(idx, rangeLength)); + for (CFIndex i = 0; i < rangeLength; ++i, ++chPtr) { + if ( *chPtr == ':' ) { + isAbsolute = true; + break; + } + if ( !scheme_valid(*chPtr) ) { + schemeCharsValid = false; + break; + } + } + if ( isAbsolute ) { + break; + } + idx += rangeLength; + } + } + + _CFURLInit((struct __CFURL *)uninitializedURL, string, isAbsolute ? NULL : baseURL, TRUE); } - length = CFStringGetLength(string); - CFStringInitInlineBuffer(string, &stringBuffer, CFRangeMake(0, length)); - while (idx < length) { - UniChar ch = CFStringGetCharacterFromInlineBuffer(&stringBuffer, idx); - idx ++; - - // Make sure that two valid hex digits follow a '%' character - if ( ch == '%' ) { - if ( idx + 2 > length ) - { - //CFAssert1(false, __kCFLogAssertion, "Detected illegal percent escape sequence at character %d when trying to create a CFURL", idx-1); - idx = -1; // To guarantee index < length, and our failure case is triggered - break; - } - - ch = CFStringGetCharacterFromInlineBuffer(&stringBuffer, idx); - idx ++; - if (! isHexDigit(ch) ) { - //CFAssert1(false, __kCFLogAssertion, "Detected illegal percent escape sequence at character %d when trying to create a CFURL", idx-2); - idx = -1; - break; - } - ch = CFStringGetCharacterFromInlineBuffer(&stringBuffer, idx); - idx ++; - if (! isHexDigit(ch) ) { - //CFAssert1(false, __kCFLogAssertion, "Detected illegal percent escape sequence at character %d when trying to create a CFURL", idx-3); - idx = -1; - break; - } +#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); + if ( input_string ) { + CFRelease(input_string); + } + if ( input_baseURL ) { + CFRelease(input_baseURL); + } +#endif + return ( result ); +} - continue; +/* initializes a URL object with a file system path */ +CF_EXPORT Boolean _CFURLInitWithFileSystemPath(CFURLRef uninitializedURL, CFStringRef fileSystemPath, CFURLPathStyle pathStyle, Boolean isDirectory, CFURLRef baseURL) +{ +#if DEBUG_URL_INITIALIZER_LOGGING + CFStringRef input_fileSystemPath = fileSystemPath ? CFRetain(fileSystemPath) : NULL; + CFURLPathStyle input_pathStyle = pathStyle; + 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); + 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 + switch (pathStyle) { + case kCFURLPOSIXPathStyle: + pathDelim = '/'; + isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(fileSystemPath, 0) == pathDelim); + break; + + + case kCFURLWindowsPathStyle: + { + // this is what _CFURLInitFSPath() did (with a small change to handle absolute paths that begin with a single backslash) + UniChar firstChar = 0 < len ? CFStringGetCharacterAtIndex(fileSystemPath, 0) : 0; + UniChar secondChar = 1 < len ? CFStringGetCharacterAtIndex(fileSystemPath, 1) : 0; + Boolean isDrive = isALPHA(firstChar) && (secondChar == ':' || secondChar == '|'); + + if ( isDrive) { + // A disk designator + pathDelim = '\\'; + isAbsolute = true; + } + 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; + } + else if (firstChar == '/') { + // We switch to kCFURLPOSIXPathStyle here because there's probably code that passes POSIX paths in but wrongly specifies kCFURLWindowsPathStyle. + pathStyle = kCFURLPOSIXPathStyle; + pathDelim = '/'; + isAbsolute = true; + } + 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; + } + } + break; } - if (ch == '[' || ch == ']') continue; // IPV6 support (RFC 2732) DCJ June/10/2002 - if (ch == '#') { - if (sawHash) break; - sawHash = true; - continue; + + // 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 ) { + if ( isAbsolute ) { + // if fileSystemPath is an absolute path, ignore baseURL (if provided) + baseURL = NULL; + } + else if ( baseURL == NULL ) { + // if fileSystemPath is a relative path and no baseURL is provided, use the current working directory + baseURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(uninitializedURL)); + releaseBaseURL = true; + } + + // override isDirectory if the path is to root + if ( !isDirectory && (len == 1) && (CFStringGetCharacterAtIndex(urlString, 0) == pathDelim) ) { + // 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); + } + 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); + } + } 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 ) { + CFRelease(baseURL); + } + + CFRelease(urlString); + result = true; } -#if DEPLOYMENT_TARGET_WINDOWS - // CF on Windows: CFURLCreateWithString should work with | in path on Windows - if (isURLLegalCharacter(ch) || ch == '|') -#else - if ( isURLLegalCharacter( ch ) ) -#endif - continue; - break; } - if (idx < length) { - return false; +#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); +#pragma GCC diagnostic pop + if ( input_fileSystemPath ) { + CFRelease(input_fileSystemPath); } - return true; + if ( input_baseURL ) { + CFRelease(input_baseURL); + } +#endif + return ( result ); } -CF_EXPORT void _CFURLInitWithString(CFURLRef myURL, CFStringRef string, CFURLRef baseURL) { - struct __CFURL *url = (struct __CFURL *)myURL; // Supress annoying compile warnings - Boolean isAbsolute = false; - CFRange colon = CFStringFind(string, CFSTR(":"), 0); - if (colon.location != kCFNotFound) { - isAbsolute = true; - CFIndex i; - for (i = 0; i < colon.location; i++) { - char ch = (char)CFStringGetCharacterAtIndex(string, i); - if (!scheme_valid(ch)) { - isAbsolute = false; - break; +/* initializes a URL object with the file system representation */ +CF_EXPORT Boolean _CFURLInitWithFileSystemRepresentation(CFURLRef uninitializedURL, const UInt8 *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL) +{ +#if DEBUG_URL_INITIALIZER_LOGGING + STACK_BUFFER_DECL(UInt8, input_buffer, bufLen); + CFIndex input_bufLen = bufLen; + Boolean input_isDirectory = isDirectory; + CFURLRef input_baseURL = baseURL ? CFRetain(baseURL) : NULL; + memcpy(input_buffer, buffer, bufLen); +#endif + Boolean result = false; + CFAllocatorRef alloc = CFGetAllocator(uninitializedURL); +#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; + + if ( isAbsolute ) { + // if buffer contains an absolute path, ignore baseURL (if provided) + baseURL = NULL; + } + else if ( baseURL == NULL ) { + // if buffer contains a relative path and no baseURL is provided, use the current working directory + baseURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(uninitializedURL)); + releaseBaseURL = true; + } + CFStringRef urlString = CreateStringFromFileSystemRepresentationByAddingPercentEscapes(alloc, 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); + } + 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); } + } 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; } - _CFURLInit(url, string, FULL_URL_REPRESENTATION, isAbsolute ? NULL : baseURL); - if (isAbsolute) { - url->_flags |= IS_ABSOLUTE; +#elif DEPLOYMENT_TARGET_WINDOWS + CFStringRef filePath = CFStringCreateWithBytes(alloc, buffer, bufLen, CFStringFileSystemEncoding(), false); + if ( filePath ) { + result = _CFURLInitWithFileSystemPath(uninitializedURL, filePath, kCFURLWindowsPathStyle, isDirectory, baseURL); + CFRelease(filePath); } +#endif +#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); + if ( input_baseURL ) { + CFRelease(input_baseURL); + } +#endif + return ( result ); } -struct __CFURLEncodingTranslationParameters { - CFStringEncoding fromEnc; - CFStringEncoding toEnc; - const UniChar *addlChars; - int count; - Boolean escapeHighBit; - Boolean escapePercents; - Boolean agreesOverASCII; - Boolean encodingsMatch; -} ; - // encoding will be used both to interpret the bytes of URLBytes, and to interpret any percent-escapes within the bytes. CFURLRef CFURLCreateWithBytes(CFAllocatorRef allocator, const uint8_t *URLBytes, CFIndex length, CFStringEncoding encoding, CFURLRef baseURL) { - CFStringRef urlString; - Boolean useEightBitStringEncoding = ( __CFStringEncodingIsSupersetOfASCII(encoding) && __CFBytesInASCII(URLBytes, length) ); - urlString = CFStringCreateWithBytes(allocator, URLBytes, length, useEightBitStringEncoding ? __CFStringGetEightBitStringEncoding() : encoding, false); - CFURLRef result; - if (!urlString || CFStringGetLength(urlString) == 0) { - if (urlString) CFRelease(urlString); - return NULL; - } - result = _CFURLAlloc(allocator); - if (result) { - if ( useEightBitStringEncoding ) { - ((struct __CFURL *)result)->_flags |= USES_EIGHTBITSTRINGENCODING; - } - _CFURLInitWithString(result, urlString, baseURL); - if (encoding != kCFStringEncodingUTF8) { - ((struct __CFURL *)result)->_encoding = encoding; + 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; #if DEBUG_URL_MEMORY_USAGE - numNonUTF8EncodedURLs++; + numNonUTF8EncodedURLs++; #endif + } + } + } } + CFRelease(urlString); // it's retained by result, now. } - CFRelease(urlString); // it's retained by result, now. - return result; + return ( result ); } CFDataRef CFURLCreateData(CFAllocatorRef allocator, CFURLRef url, CFStringEncoding encoding, Boolean escapeWhitespace) { @@ -1915,29 +2324,50 @@ 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; - if (!URLString || CFStringGetLength(URLString) == 0) return NULL; - if (!_CFStringIsLegalURLString(URLString)) return NULL; - url = _CFURLAlloc(allocator); - if (url) { - _CFURLInitWithString(url, URLString, 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; + } + } } - return url; + return ( url ); } -static CFURLRef _CFURLCreateWithArbitraryString(CFAllocatorRef allocator, CFStringRef URLString, CFURLRef baseURL) { - CFURLRef url; - if (!URLString || CFStringGetLength(URLString) == 0) return NULL; - url = _CFURLAlloc(allocator); - if (url) { - _CFURLInitWithString(url, URLString, baseURL); +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; + } + } } - return url; + return ( url ); } CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *relativeURLBytes, CFIndex length, CFStringEncoding encoding, CFURLRef baseURL, Boolean useCompatibilityMode) { CFURLRef result = NULL; + /* + CFURLCreateAbsoluteURLWithBytes() and useCompatibilityMode is for: + Problem with '|' in url and calling CFURLCreateWithString() + CFURL resolves "../" URLs at top level in a way that is not the same as web browsers + CFURL API should be more helpful for accepting URLs with technically-bad characters + Safari needs CFURL to deal with google.com URLs that end in "%" + Safari needs CFURL to not remove path when relative URL is just a query string + Safari needs CFURL to support "compatibility" resolution of partial URLs with schemes + + If useCompatibilityMode is true, the rules historically used on the web are used to resolve relativeString against baseURL - these rules are generally listed in the RFC as optional or alternate interpretations. Otherwise, the strict rules from the RFC are used. + + The major differences are that in compatibility mode, we are lenient of the scheme appearing in relative portion, leading "../" components are removed from the final URL's path, and if the relative portion contains only resource specifier pieces (query, parameters, and fragment), then the last path component of the base URL will not be deleted + */ + // if not useCompatibilityMode, use CFURLCreateWithBytes and then CFURLCopyAbsoluteURL if there's a baseURL if ( !useCompatibilityMode ) { CFURLRef url = CFURLCreateWithBytes(alloc, relativeURLBytes, length, encoding, baseURL); @@ -1956,18 +2386,16 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela Boolean absStringIsMutable = false; CFURLRef absURL; CFStringRef relativeString; - Boolean useEightBitStringEncoding; - useEightBitStringEncoding = ( __CFStringEncodingIsSupersetOfASCII(encoding) && __CFBytesInASCII(relativeURLBytes, length) ); - relativeString = CFStringCreateWithBytes(alloc, relativeURLBytes, length, useEightBitStringEncoding ? __CFStringGetEightBitStringEncoding() : encoding, false); + relativeString = CFStringCreateWithBytes(alloc, relativeURLBytes, length, encoding, false); if ( relativeString != NULL ) { if (!baseURL) { - if ( useEightBitStringEncoding ) { - absFlags |= USES_EIGHTBITSTRINGENCODING; - } absString = relativeString; } else { - UniChar ch = CFStringGetCharacterAtIndex(relativeString, 0); + UniChar ch = 0; + if ( CFStringGetLength(relativeString) > 0 ) { + ch = CFStringGetCharacterAtIndex(relativeString, 0); + } if (ch == '?' || ch == ';' || ch == '#') { // Nothing but parameter + query + fragment; append to the baseURL string CFStringRef baseString; @@ -1995,9 +2423,6 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela _parseComponents(alloc, relString, baseURL, &relFlags, &relRanges); } else { // Discard the base string; the relative string is absolute and we're not in the funky edge case where the schemes match - if ( useEightBitStringEncoding ) { - absFlags |= USES_EIGHTBITSTRINGENCODING; - } CFRetain(relativeString); absString = relativeString; } @@ -2112,7 +2537,7 @@ static CFStringRef _resolvedPath(UniChar *pathStr, UniChar *end, UniChar pathDel pathStr[0] = '.'; pathStr[1] = '/'; pathStr[2] = '\0'; - end = & pathStr[3]; + end = &pathStr[3]; break; } } @@ -2135,32 +2560,37 @@ static CFStringRef _resolvedPath(UniChar *pathStr, UniChar *end, UniChar pathDel if (stripTrailingDelimiter && end > pathStr && end-1 != pathStr && *(end-1) == pathDelimiter) { end --; } - return CFStringCreateWithCharactersNoCopy(alloc, pathStr, end - pathStr, alloc); + // return an zero-length string if end < pathStr + return CFStringCreateWithCharactersNoCopy(alloc, pathStr, end >= pathStr ? end - pathStr : 0, alloc); } -static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, CFRange *baseRanges) { - CFMutableStringRef newString = CFStringCreateMutable(alloc, 0); - CFIndex bufLen = CFStringGetLength(baseString) + CFStringGetLength(relString); // Overkill, but guarantees we never allocate again - UniChar *buf = (UniChar *)CFAllocatorAllocate(alloc, bufLen * sizeof(UniChar), 0); +static CFMutableStringRef resolveAbsoluteURLStringBuffer(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, CFRange *baseRanges, UniChar *buf) +{ + CFStringAppendBuffer appendBuffer; + UniChar chars[2]; + CFStringInitAppendBuffer(alloc, &appendBuffer); CFRange rg; rg = _rangeForComponent(baseFlags, baseRanges, HAS_SCHEME); if (rg.location != kCFNotFound) { CFStringGetCharacters(baseString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); - CFStringAppendCString(newString, ":", kCFStringEncodingASCII); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); + chars[0] = ':'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 1); } - + if (relFlags & NET_LOCATION_MASK) { - CFStringAppend(newString, relString); + CFStringAppendStringToAppendBuffer(&appendBuffer, relString); } else { - CFStringAppendCString(newString, "//", kCFStringEncodingASCII); + chars[0] = '/'; + chars[1] = '/'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 2); rg = _netLocationRange(baseFlags, baseRanges); if (rg.location != kCFNotFound) { CFStringGetCharacters(baseString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } - + if (relFlags & HAS_PATH) { CFRange relPathRg = _rangeForComponent(relFlags, relRanges, HAS_PATH); CFRange basePathRg = _rangeForComponent(baseFlags, baseRanges, HAS_PATH); @@ -2181,7 +2611,7 @@ static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStrin } else if (useBasePath) { newPath = CFStringCreateWithSubstring(alloc, baseString, basePathRg); } else { - // #warning FIXME - Get rid of this allocation + // FIXME: Get rid of this allocation UniChar *newPathBuf = (UniChar *)CFAllocatorAllocate(alloc, sizeof(UniChar) * (relPathRg.length + basePathRg.length + 1), 0); UniChar *idx, *end; CFStringGetCharacters(baseString, basePathRg, newPathBuf); @@ -2197,33 +2627,34 @@ static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStrin * so we have to add one '/' to the newString * (Sergey Zubarev) */ - // No - the input strings here are URL path strings, not Win32 paths. - // Absolute paths should have had a '/' prepended before this point. - // I have removed Sergey Zubarev's change and left his comment (and - // this one) as a record. - REW, 1/5/2004 + // No - the input strings here are URL path strings, not Win32 paths. + // Absolute paths should have had a '/' prepended before this point. + // I have removed Sergey Zubarev's change and left his comment (and + // this one) as a record. - REW, 1/5/2004 // if the relative URL does not begin with a slash and // the base does not end with a slash, add a slash if ((basePathRg.location == kCFNotFound || basePathRg.length == 0) && CFStringGetCharacterAtIndex(newPath, 0) != '/') { - CFStringAppendCString(newString, "/", kCFStringEncodingASCII); + chars[0] = '/'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 1); } - CFStringAppend(newString, newPath); + CFStringAppendStringToAppendBuffer(&appendBuffer, newPath); CFRelease(newPath); rg.location = relPathRg.location + relPathRg.length; rg.length = CFStringGetLength(relString); if (rg.length > rg.location) { - rg.length -= rg.location; + rg.length -= rg.location; CFStringGetCharacters(relString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } } else { rg = _rangeForComponent(baseFlags, baseRanges, HAS_PATH); if (rg.location != kCFNotFound) { CFStringGetCharacters(baseString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } - + if (!(relFlags & RESOURCE_SPECIFIER_MASK)) { // ??? Can this ever happen? UInt32 rsrcFlag = _firstResourceSpecifierFlag(baseFlags); @@ -2233,47 +2664,66 @@ static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStrin rg.location --; // To pick up the separator rg.length ++; CFStringGetCharacters(baseString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } } else if (relFlags & HAS_PARAMETERS) { rg = _rangeForComponent(relFlags, relRanges, HAS_PARAMETERS); rg.location --; // To get the semicolon that starts the parameters rg.length = CFStringGetLength(relString) - rg.location; CFStringGetCharacters(relString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } else { // Sigh; we have to resolve these against one another rg = _rangeForComponent(baseFlags, baseRanges, HAS_PARAMETERS); if (rg.location != kCFNotFound) { - CFStringAppendCString(newString, ";", kCFStringEncodingASCII); + chars[0] = ';'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 1); CFStringGetCharacters(baseString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } rg = _rangeForComponent(relFlags, relRanges, HAS_QUERY); if (rg.location != kCFNotFound) { - CFStringAppendCString(newString, "?", kCFStringEncodingASCII); + chars[0] = '?'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 1); CFStringGetCharacters(relString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } else { rg = _rangeForComponent(baseFlags, baseRanges, HAS_QUERY); if (rg.location != kCFNotFound) { - CFStringAppendCString(newString, "?", kCFStringEncodingASCII); + chars[0] = '?'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 1); CFStringGetCharacters(baseString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } } // Only the relative portion of the URL can supply the fragment; otherwise, what would be in the relativeURL? rg = _rangeForComponent(relFlags, relRanges, HAS_FRAGMENT); if (rg.location != kCFNotFound) { - CFStringAppendCString(newString, "#", kCFStringEncodingASCII); + chars[0] = '#'; + CFStringAppendCharactersToAppendBuffer(&appendBuffer, chars, 1); CFStringGetCharacters(relString, rg, buf); - CFStringAppendCharacters(newString, buf, rg.length); + CFStringAppendCharactersToAppendBuffer(&appendBuffer, buf, rg.length); } } } } - CFAllocatorDeallocate(alloc, buf); - return newString; + return CFStringCreateMutableWithAppendBuffer(&appendBuffer); +} + +static CFMutableStringRef resolveAbsoluteURLString(CFAllocatorRef alloc, CFStringRef relString, UInt32 relFlags, CFRange *relRanges, CFStringRef baseString, UInt32 baseFlags, CFRange *baseRanges) { + CFMutableStringRef result; + CFIndex bufLen = CFStringGetLength(baseString) + CFStringGetLength(relString); // Overkill, but guarantees we never allocate again + if ( bufLen <= 1024 ) { + STACK_BUFFER_DECL(UniChar, buf, bufLen); + result = resolveAbsoluteURLStringBuffer(alloc, relString, relFlags, relRanges, baseString, baseFlags, baseRanges, buf); + return ( result ); + } + else { + UniChar *buf = (UniChar *)CFAllocatorAllocate(alloc, bufLen * sizeof(UniChar), 0); + result = resolveAbsoluteURLStringBuffer(alloc, relString, relFlags, relRanges, baseString, baseFlags, baseRanges, buf); + CFAllocatorDeallocate(alloc, buf); + return ( result ); + } } CFURLRef CFURLCopyAbsoluteURL(CFURLRef relativeURL) { @@ -2432,7 +2882,7 @@ static CFStringRef _retainedComponentString(CFURLRef url, UInt32 compFlag, Boole comp = CFStringCreateWithSubstring(alloc, url->_string, rg); } - if (!fromOriginalString) { + if (comp && !fromOriginalString) { if (!_haveTestedOriginalString(url)) { computeSanitizedString(url); } @@ -2442,7 +2892,7 @@ static CFStringRef _retainedComponentString(CFURLRef url, UInt32 compFlag, Boole comp = newComp; } } - if (removePercentEscapes) { + if (comp && removePercentEscapes) { CFStringRef tmp; if (url->_encoding == kCFStringEncodingUTF8) { tmp = CFURLCreateStringByReplacingPercentEscapes(alloc, comp, CFSTR("")); @@ -3174,7 +3624,7 @@ static CFURLRef composeFromRFC1808(CFAllocatorRef alloc, const CFURLComponentsRF hadPrePathComponent = true; } if (comp->port != kCFNotFound) { - CFStringAppendFormat(urlString, NULL, CFSTR(":%d"), comp->port); + CFStringAppendFormat(urlString, NULL, CFSTR(":%ld"), (long)comp->port); hadPrePathComponent = true; } @@ -3260,7 +3710,7 @@ static CFURLRef composeFromRFC2396(CFAllocatorRef alloc, const CFURLComponentsRF if (comp->host) { CFStringAppend(urlString, comp->host); if (comp->port != kCFNotFound) { - CFStringAppendFormat(urlString, NULL, CFSTR(":%d"), comp->port); + CFStringAppendFormat(urlString, NULL, CFSTR(":%ld"), (long)comp->port); } hadPrePathComponent = true; } @@ -3336,7 +3786,7 @@ CF_EXPORT void __CFURLSetResourceInfoPtr(CFURLRef url, void *ptr) { /* File system stuff */ /* HFSPath<->URLPath functions at the bottom of the file */ -static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) { +static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute) { CFArrayRef tmp; CFMutableArrayRef urlComponents = NULL; CFIndex i=0; @@ -3346,9 +3796,8 @@ static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef al CFRelease(tmp); CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(urlComponents, 0); - if (CFStringGetLength(str) == 2 && CFStringGetCharacterAtIndex(str, 1) == ':') { - CFArrayInsertValueAtIndex(urlComponents, 0, CFSTR("")); // So we get a leading '/' below - i = 2; // Skip over the drive letter and the empty string we just inserted + if (isAbsolute && CFStringGetLength(str) == 2 && CFStringGetCharacterAtIndex(str, 1) == ':') { + i = 1; // Skip over the drive letter } CFIndex c; for (c = CFArrayGetCount(urlComponents); i < c; i ++) { @@ -3369,15 +3818,23 @@ static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef al if (CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(urlComponents, CFArrayGetCount(urlComponents) - 1)) != 0) CFArrayAppendValue(urlComponents, CFSTR("")); } + if (isAbsolute) { + if ( AddAuthorityToFileURL() ) { + CFArrayInsertValueAtIndex(urlComponents, 0, CFSTR(FILE_PREFIX_WITH_AUTHORITY)); + } + else { + CFArrayInsertValueAtIndex(urlComponents, 0, CFSTR(FILE_PREFIX)); + } + } return urlComponents; } -static CFStringRef WindowsPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) { +static CFStringRef WindowsPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir, Boolean isAbsolute) { CFArrayRef urlComponents; CFStringRef str; if (CFStringGetLength(path) == 0) return CFStringCreateWithCString(alloc, "", kCFStringEncodingASCII); - urlComponents = WindowsPathToURLComponents(path, alloc, isDir); + urlComponents = WindowsPathToURLComponents(path, alloc, isDir, isAbsolute); if (!urlComponents) return CFStringCreateWithCString(alloc, "", kCFStringEncodingASCII); // WindowsPathToURLComponents already added percent escapes for us; no need to add them again here. @@ -3386,12 +3843,16 @@ static CFStringRef WindowsPathToURLPath(CFStringRef path, CFAllocatorRef alloc, return str; } -static CFStringRef POSIXPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDirectory) { - CFStringRef pathString = _replacePathIllegalCharacters(path, alloc, true); - if (isDirectory && CFStringGetCharacterAtIndex(path, CFStringGetLength(path)-1) != '/') { - CFStringRef tmp = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@/"), pathString); - CFRelease(pathString); - pathString = tmp; +static CFStringRef POSIXPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDirectory, Boolean isAbsolute, Boolean *posixAndUrlPathsMatch) { + Boolean addedPercentEncoding; + CFStringRef pathString = NULL; + STACK_BUFFER_DECL(char, buffer, PATH_MAX); + if ( CFStringGetFileSystemRepresentation(path, buffer, PATH_MAX) ) { + pathString = CreateStringFromFileSystemRepresentationByAddingPercentEscapes(kCFAllocatorDefault, (const UInt8 *)buffer, strlen(buffer), isDirectory, isAbsolute, false /* windowsPath */, &addedPercentEncoding); + } + + if ( posixAndUrlPathsMatch ) { + *posixAndUrlPathsMatch = !addedPercentEncoding; } return pathString; } @@ -3406,18 +3867,25 @@ static CFStringRef URLPathToPOSIXPath(CFStringRef path, CFAllocatorRef allocator CFRelease(result); result = tmp; } - } + } return result; - } +} -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX -static Boolean CanonicalFileURLStringToFileSystemRepresentation(CFStringRef str, CFAllocatorRef alloc, UInt8 *inBuffer, CFIndex inBufferLen) +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX +static Boolean CanonicalFileURLStringToFileSystemRepresentation(CFStringRef str, UInt8 *inBuffer, CFIndex inBufferLen) { + size_t fileURLPrefixLength; + if ( AddAuthorityToFileURL() ) { + fileURLPrefixLength = sizeof(fileURLPrefixWithAuthority); + } + else { + fileURLPrefixLength = sizeof(fileURLPrefix); + } Boolean result; if ( inBuffer && inBufferLen ) { STACK_BUFFER_DECL(UInt8, stackEscapedBuf, PATH_MAX * 3); // worst case size is every unicode code point could be a 3-byte UTF8 sequence UInt8 *escapedBuf; - CFIndex strLength = CFStringGetLength(str) - (sizeof(fileURLPrefixWithAuthority) - 1); + CFIndex strLength = CFStringGetLength(str) - (fileURLPrefixLength - 1); if ( strLength != 0 ) { CFIndex maxBufLength = strLength * 3; CFIndex usedBufLen; @@ -3430,7 +3898,7 @@ static Boolean CanonicalFileURLStringToFileSystemRepresentation(CFStringRef str, escapedBuf = (UInt8 *)malloc(maxBufLength); } if ( escapedBuf != NULL ) { - charsConverted = CFStringGetBytes(str, CFRangeMake(sizeof(fileURLPrefixWithAuthority) - 1, strLength), kCFStringEncodingUTF8, 0, false, escapedBuf, maxBufLength, &usedBufLen); + charsConverted = CFStringGetBytes(str, CFRangeMake(fileURLPrefixLength - 1, strLength), kCFStringEncodingUTF8, 0, false, escapedBuf, maxBufLength, &usedBufLen); if ( charsConverted ) { static const UInt8 hexvalues[] = { /* 00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -3621,61 +4089,6 @@ static CFStringRef URLPathToWindowsPath(CFStringRef path, CFAllocatorRef allocat -// converts url from a file system path representation to a standard representation -static void _convertToURLRepresentation(struct __CFURL *url, UInt32 fsType) { - CFStringRef path = NULL; - Boolean isDir = ((url->_flags & IS_DIRECTORY) != 0); - Boolean isFileReferencePath = false; - CFAllocatorRef alloc = CFGetAllocator(url); - - switch (fsType) { - case kCFURLPOSIXPathStyle: - isFileReferencePath = _pathHasFileIDPrefix(url->_string); - if (url->_flags & POSIX_AND_URL_PATHS_MATCH) { - path = (CFStringRef)CFRetain(url->_string); - } else { - path = POSIXPathToURLPath(url->_string, alloc, isDir); - } - break; - case kCFURLWindowsPathStyle: - path = WindowsPathToURLPath(url->_string, alloc, isDir); - break; - } - CFAssert2(path != NULL, __kCFLogAssertion, "%s(): Encountered malformed file system URL %@", __PRETTY_FUNCTION__, url); - if ( path ) - { - if (!url->_base) { - CFMutableStringRef str = CFStringCreateMutable(alloc, 0); - CFStringAppend(str, isFileReferencePath ? CFSTR(FILE_PREFIX) : CFSTR(FILE_PREFIX_WITH_AUTHORITY)); - CFStringAppend(str, path); - url->_flags = (url->_flags & (IS_DIRECTORY)) | IS_DECOMPOSABLE | IS_ABSOLUTE | HAS_SCHEME | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | ( isFileReferencePath ? PATH_HAS_FILE_ID : HAS_HOST ); - _setSchemeTypeInFlags(&url->_flags, kHasFileScheme); - CFRelease(url->_string); - url->_string = CFStringCreateCopy(alloc, str); - CFRelease(str); - if (isFileReferencePath) { - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 2, 0); - url->_ranges[0] = CFRangeMake(0, 4); // scheme "file" - url->_ranges[1] = CFRangeMake(7, CFStringGetLength(path)); // path - } - else { - 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(path)); // path - } - CFRelease(path); - } else { - CFRelease(url->_string); - url->_flags = (url->_flags & (IS_DIRECTORY)) | IS_DECOMPOSABLE | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH; - url->_string = CFStringCreateCopy(alloc, path); - CFRelease(path); - url->_ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0); - *(url->_ranges) = CFRangeMake(0, CFStringGetLength(url->_string)); - } - } -} - // Caller must release the returned string static CFStringRef _resolveFileSystemPaths(CFStringRef relativePath, CFStringRef basePath, Boolean baseIsDir, CFURLPathStyle fsType, CFAllocatorRef alloc) { CFIndex baseLen = CFStringGetLength(basePath); @@ -3695,7 +4108,10 @@ static CFStringRef _resolveFileSystemPaths(CFStringRef relativePath, CFStringRef } baseLen = ptr - buf + 1; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" if (fsType == kCFURLHFSPathStyle) { +#pragma GCC diagnostic pop // HFS relative paths will begin with a colon, so we must remove the trailing colon from the base path first. baseLen --; } @@ -3714,185 +4130,31 @@ CFURLRef _CFURLCreateCurrentDirectoryURL(CFAllocatorRef allocator) { } CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle fsType, Boolean isDirectory) { - Boolean isAbsolute = true; - CFIndex len; - CFURLRef baseURL, result; - - CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType); + CFURLRef result; - CFAssert1(filePath != NULL, __kCFLogAssertion, "%s(): NULL filePath argument not permitted", __PRETTY_FUNCTION__); - - len = CFStringGetLength(filePath); - - switch(fsType) { - case kCFURLPOSIXPathStyle: - isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(filePath, 0) == '/'); - break; - case kCFURLWindowsPathStyle: - isAbsolute = (len >= 3 && CFStringGetCharacterAtIndex(filePath, 1) == ':' && CFStringGetCharacterAtIndex(filePath, 2) == '\\'); - /* Absolute path under Win32 can begin with "\\" - * (Sergey Zubarev) - */ - if (!isAbsolute) isAbsolute = (len > 2 && CFStringGetCharacterAtIndex(filePath, 0) == '\\' && CFStringGetCharacterAtIndex(filePath, 1) == '\\'); - break; - case kCFURLHFSPathStyle: - isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(filePath, 0) != ':'); - break; - } - if (isAbsolute) { - baseURL = NULL; - } else { - baseURL = _CFURLCreateCurrentDirectoryURL(allocator); + result = _CFURLAlloc(allocator); + if ( result ) { + if ( !_CFURLInitWithFileSystemPath(result, filePath, fsType, isDirectory, NULL) ) { + CFRelease(result); + result = NULL; + } } - result = CFURLCreateWithFileSystemPathRelativeToBase(allocator, filePath, fsType, isDirectory, baseURL); - if (baseURL) CFRelease(baseURL); - return result; + + return ( result ); } CF_EXPORT CFURLRef CFURLCreateWithFileSystemPathRelativeToBase(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle fsType, Boolean isDirectory, CFURLRef baseURL) { - CFURLRef url; - Boolean isAbsolute = true, releaseFilePath = false, releaseBaseURL = false; - UniChar pathDelim = '\0'; - CFIndex len; - - CFAssert1(filePath != NULL, __kCFLogAssertion, "%s(): NULL path string not permitted", __PRETTY_FUNCTION__); - CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType); + CFURLRef result; - len = CFStringGetLength(filePath); - - switch(fsType) { - case kCFURLPOSIXPathStyle: - isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(filePath, 0) == '/'); - - pathDelim = '/'; - break; - case kCFURLWindowsPathStyle: - isAbsolute = (len >= 3 && CFStringGetCharacterAtIndex(filePath, 1) == ':' && CFStringGetCharacterAtIndex(filePath, 2) == '\\'); - /* Absolute path under Win32 can begin with "\\" - * (Sergey Zubarev) - */ - if (!isAbsolute) - isAbsolute = (len > 2 && CFStringGetCharacterAtIndex(filePath, 0) == '\\' && CFStringGetCharacterAtIndex(filePath, 1) == '\\'); - pathDelim = '\\'; - break; - case kCFURLHFSPathStyle: - { CFRange fullStrRange = CFRangeMake( 0, CFStringGetLength( filePath ) ); - - isAbsolute = (len > 0 && CFStringGetCharacterAtIndex(filePath, 0) != ':'); - pathDelim = ':'; - - if ( filePath && CFStringFindWithOptions( filePath, CFSTR("::"), fullStrRange, 0, NULL ) ) { - UniChar * chars = (UniChar *) malloc( fullStrRange.length * sizeof( UniChar ) ); - CFIndex index, writeIndex, firstColonOffset = -1; - - CFStringGetCharacters( filePath, fullStrRange, chars ); - - for ( index = 0, writeIndex = 0 ; index < fullStrRange.length; index ++ ) { - if ( chars[ index ] == ':' ) { - if ( index + 1 < fullStrRange.length && chars[ index + 1 ] == ':' ) { - - // Don't let :: go off the 'top' of the path -- which means that there always has to be at - // least one ':' to the left of the current write position to go back to. - if ( writeIndex > 0 && firstColonOffset >= 0 ) - { - writeIndex --; - while ( writeIndex > 0 && writeIndex >= firstColonOffset && chars[ writeIndex ] != ':' ) - writeIndex --; - } - index ++; // skip over the first ':', so we replace the ':' which is there with a new one - } - - if ( firstColonOffset == -1 ) - firstColonOffset = writeIndex; - } - - chars[ writeIndex ++ ] = chars[ index ]; - } - - if ( releaseFilePath && filePath ) - CFRelease( filePath ); - - filePath = CFStringCreateWithCharacters( allocator, chars, writeIndex ); - // reset len because a canonical HFS path can be a different length than the original CFString - len = CFStringGetLength(filePath); - releaseFilePath = true; - - free( chars ); - } - - break; - } - } - if (isAbsolute) { - baseURL = NULL; - } - else if ( baseURL == NULL ) { - baseURL = _CFURLCreateCurrentDirectoryURL(allocator); - releaseBaseURL = true; - } - - - if (isDirectory && len > 0 && CFStringGetCharacterAtIndex(filePath, len-1) != pathDelim) { - CFMutableStringRef tempRef = CFStringCreateMutable(allocator, 0); - CFStringAppend(tempRef, filePath); - CFStringAppendCharacters(tempRef, &pathDelim, 1); - if ( releaseFilePath && filePath ) CFRelease( filePath ); - filePath = tempRef; - releaseFilePath = true; - } else if (!isDirectory && len > 0 && CFStringGetCharacterAtIndex(filePath, len-1) == pathDelim) { - if (len == 1 || CFStringGetCharacterAtIndex(filePath, len-2) == pathDelim) { - // Override isDirectory - isDirectory = true; - } else { - CFStringRef tempRef = CFStringCreateWithSubstring(allocator, filePath, CFRangeMake(0, len-1)); - if ( releaseFilePath && filePath ) - CFRelease( filePath ); - filePath = tempRef; - releaseFilePath = true; - } - } - if (!filePath || CFStringGetLength(filePath) == 0) { - if (releaseFilePath && filePath) CFRelease(filePath); - if (releaseBaseURL && baseURL) CFRelease(baseURL); - return NULL; - } - url = _CFURLAlloc(allocator); - _CFURLInit((struct __CFURL *)url, filePath, fsType, baseURL); - if (releaseFilePath) CFRelease(filePath); - if (releaseBaseURL && baseURL) CFRelease(baseURL); - if (isDirectory) ((struct __CFURL *)url)->_flags |= IS_DIRECTORY; - if (fsType == kCFURLPOSIXPathStyle) { - // Check if relative path is equivalent to URL representation; this will be true if url->_string contains only characters from the unreserved character set, plus '/' to delimit the path, plus ';', '@', '&', '=', '+', '$', ',' (according to RFC 2396) -- REW, 12/1/2000 - // Per Section 5 of RFC 2396, there's a special problem if a colon apears in the first path segment - in this position, it can be mistaken for the scheme name. Otherwise, it's o.k., and can be safely identified as part of the path. In this one case, we need to prepend "./" to make it clear what's going on.... -- REW, 8/24/2001 - CFStringInlineBuffer buf; - Boolean sawSlash = FALSE; - Boolean mustPrependDotSlash = FALSE; - CFIndex idx, length = CFStringGetLength(url->_string); - CFStringInitInlineBuffer(url->_string, &buf, CFRangeMake(0, length)); - for (idx = 0; idx < length; idx ++) { - UniChar ch = CFStringGetCharacterFromInlineBuffer(&buf, idx); - if (!isPathLegalCharacter(ch)) break; - if (!sawSlash) { - if (ch == '/') { - sawSlash = TRUE; - } else if (ch == ':') { - mustPrependDotSlash = TRUE; - } - } - } - if (idx == length) { - ((struct __CFURL *)url)->_flags |= POSIX_AND_URL_PATHS_MATCH; - } - if (mustPrependDotSlash) { - CFMutableStringRef newString = CFStringCreateMutable(allocator, 0); - CFStringAppend(newString, CFSTR("./")); - CFStringAppend(newString, url->_string); - CFRelease(url->_string); - ((struct __CFURL *)url)->_string = CFStringCreateCopy(allocator, newString); - CFRelease(newString); + result = _CFURLAlloc(allocator); + if ( result ) { + if ( !_CFURLInitWithFileSystemPath(result, filePath, fsType, isDirectory, baseURL) ) { + CFRelease(result); + result = NULL; } } - return url; + + return ( result ); } static Boolean _pathHasFileIDPrefix( CFStringRef path ) @@ -3915,11 +4177,36 @@ static Boolean _pathHasFileIDOnly( CFStringRef path ) #endif CF_EXPORT CFStringRef CFURLCopyFileSystemPath(CFURLRef anURL, CFURLPathStyle pathStyle) { +#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 - CFStringRef result; + CFStringRef result = NULL; + CFAllocatorRef alloc = CFGetAllocator(anURL); +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX + Boolean isCanonicalFileURL = false; + + if ( (pathStyle == kCFURLPOSIXPathStyle) && (CFURLGetBaseURL(anURL) == NULL) ) { + if ( !CF_IS_OBJC(__kCFURLTypeID, anURL) ) { + // We can grope the ivars + isCanonicalFileURL = ((anURL->_flags & IS_CANONICAL_FILE_URL) != 0); + if ( isCanonicalFileURL ) { + STACK_BUFFER_DECL(UInt8, buffer, PATH_MAX + 1); + if ( CanonicalFileURLStringToFileSystemRepresentation(anURL->_string, buffer, PATH_MAX + 1) ) { + result = CFStringCreateWithBytes(alloc, buffer, strlen((char *)buffer), kCFStringEncodingUTF8, false); + } + } + } + } + if ( ! result ) { + // fall back to slower way. + result = CFURLCreateStringWithFileSystemPath(alloc, anURL, pathStyle, false); + } +#else // !DEPLOYMENT_TARGET_MACOSX + result = CFURLCreateStringWithFileSystemPath(alloc, anURL, pathStyle, false); +#endif // !DEPLOYMENT_TARGET_MACOSX - result = CFURLCreateStringWithFileSystemPath(CFGetAllocator(anURL), anURL, pathStyle, false); return ( result ); } @@ -3947,7 +4234,10 @@ CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLR case kCFURLPOSIXPathStyle: relPath = URLPathToPOSIXPath(urlPath, allocator, enc); break; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" case kCFURLHFSPathStyle: +#pragma GCC diagnostic pop relPath = NULL; break; case kCFURLWindowsPathStyle: @@ -3971,15 +4261,18 @@ CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLR } if ( relPath ) { - if ( basePath ) { - // we have both basePath and relPath -- resolve them + if ( basePath && (CFStringGetCharacterAtIndex(relPath, 0) != '/') ) { + // we have both basePath and relPath, and relPath is not absolute -- resolve them CFStringRef result = _resolveFileSystemPaths(relPath, basePath, CFURLHasDirectoryPath(base), fsType, allocator); CFRelease(basePath); CFRelease(relPath); return result; } else { - // we only have the relPath -- return it + // we only have the relPath or relpath is absolute -- return it + if ( basePath ) { + CFRelease(basePath); + } return relPath; } } @@ -3994,18 +4287,18 @@ CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLR } Boolean CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, uint8_t *buffer, CFIndex bufLen) { -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS CFAllocatorRef alloc = CFGetAllocator(url); CFStringRef path; if (!url) return false; #endif -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX +#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)) { // We can grope the ivars if ( url->_flags & IS_CANONICAL_FILE_URL ) { - return CanonicalFileURLStringToFileSystemRepresentation(url->_string, alloc, buffer, bufLen); + return CanonicalFileURLStringToFileSystemRepresentation(url->_string, buffer, bufLen); } } } @@ -4055,209 +4348,32 @@ CF_EXPORT Boolean _CFURLGetWideFileSystemRepresentation(CFURLRef url, Boolean re } #endif -static CFStringRef _createPathFromFileSystemRepresentation(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory) { - char pathDelim = PATH_SEP; - CFStringRef path; - if ( isDirectory ) { - // it is a directory: if it doesn't end with pathDelim, append a pathDelim. Limit stack buffer to PATH_MAX+1 in case a large bogus value is passed. - if ( (bufLen > 0) && (bufLen <= PATH_MAX) && (buffer[bufLen-1] != pathDelim) ) { - STACK_BUFFER_DECL(uint8_t, tempBuf, bufLen + 1); - memcpy(tempBuf, buffer, bufLen); - tempBuf[bufLen] = pathDelim; - path = CFStringCreateWithBytes(allocator, tempBuf, bufLen + 1, CFStringFileSystemEncoding(), false); - } - else { - // already had pathDelim at end of buffer or bufLen is really large - path = CFStringCreateWithBytes(allocator, buffer, bufLen, CFStringFileSystemEncoding(), false); - } - } - else { - // it is not a directory: remove any pathDelim characters at end (leaving at least one character) - while ( (bufLen > 1) && (buffer[bufLen-1] == pathDelim) ) { - --bufLen; - } - path = CFStringCreateWithBytes(allocator, buffer, bufLen, CFStringFileSystemEncoding(), false); - } - return path; -} - -/* - CreatePOSIXFileURLStringFromPOSIXAbsolutePath creates file URL string from the native file system representation. - - The rules for path-absolute from rfc3986 are: - path-absolute = "/" [ segment-nz *( "/" segment ) ] - segment = *pchar - segment-nz = 1*pchar - pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pct-encoded = "%" HEXDIG HEXDIG - unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - */ -static CFStringRef CreatePOSIXFileURLStringFromPOSIXAbsolutePath(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex numBytes, Boolean isDirectory, Boolean *addedPercentEncoding) -{ - static const UInt8 hexchars[] = "0123456789ABCDEF"; - STACK_BUFFER_DECL(UInt8, stackBuf, (PATH_MAX * 3) + sizeof(fileURLPrefixWithAuthority)); // worst case is every byte needs to be percent-escaped - UInt8 *bufStartPtr; - UInt8 *bufBytePtr; - const UInt8 *bytePtr = bytes; - CFIndex idx; - CFStringRef result; - Boolean addedPercent = FALSE; - - // choose a buffer to percent-escape into. - if ( numBytes <= PATH_MAX ) { - bufStartPtr = &stackBuf[0]; - } - else { - // worst case is every byte needs to be percent-escaped (numBytes * 3) - bufStartPtr = (UInt8 *)malloc((numBytes * 3) + sizeof(fileURLPrefixWithAuthority)); - } +CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory) { + CFURLRef result; - if ( bufStartPtr != NULL ) { - // start with the fileURLPrefixWithAuthority - strcpy((char *)bufStartPtr, (char *)fileURLPrefixWithAuthority); - bufBytePtr = bufStartPtr + sizeof(fileURLPrefixWithAuthority) - 1; - // append the percent-escaped path - for ( idx = 0; (idx < numBytes) && (*bytePtr != 0); ++idx ) { - switch ( *bytePtr ) { - // these are the visible 7-bit ascii characters that are not legal pchar octets - case '"': - case '#': - case '%': - case ';': // we need to percent-escape ';' in file system paths so it won't be mistaken for the start of the obsolete param rule (rfc2396) that CFURL still supports - case '<': - case '>': - case '?': // we need to percent-escape '?' in file system paths so it won't be mistaken for the start of a query - case '[': - case '\\': - case ']': - case '^': - case '`': - case '{': - case '|': - case '}': - // percent-escape non-pchar octets spread throughout the visible 7-bit ascii range - *bufBytePtr++ = '%'; - *bufBytePtr++ = hexchars[*bytePtr >> 4]; - *bufBytePtr++ = hexchars[*bytePtr & 0x0f]; - addedPercent = TRUE; - break; - default: - if ( (*bytePtr <= ' ') || // percent-escape non-pchar octets that are space or less (control characters) - (*bytePtr >= 0x7f) ) { // percent-escape non-pchar octets that del and 8-bit ascii with the high bit set - *bufBytePtr++ = '%'; - *bufBytePtr++ = hexchars[*bytePtr >> 4]; - *bufBytePtr++ = hexchars[*bytePtr & 0x0f]; - addedPercent = TRUE; - } - else { - // copy everything else - *bufBytePtr++ = *bytePtr; - } - break; - } - ++bytePtr; - } - - // did we convert numBytes? - if ( idx == numBytes ) { - // if it is a directory and it doesn't end with PATH_SEP, append a PATH_SEP. - if ( isDirectory && bytes[numBytes-1] != PATH_SEP) { - *bufBytePtr++ = PATH_SEP; - } - - // create the result - result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), __CFStringGetEightBitStringEncoding(), FALSE); - } - else { - // no, but it's OK if the remaining bytes are all nul (embedded nul bytes are not allowed) - const UInt8 *nullBytePtr = bytePtr; - for ( /* start where we left off */; (idx < numBytes) && (*nullBytePtr == '\0'); ++idx, ++nullBytePtr ) { - // do nothing - } - if ( idx == numBytes ) { - // create the result - result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), __CFStringGetEightBitStringEncoding(), FALSE); - } - else { - // the remaining bytes were not all nul - result = NULL; - } - } - // free the buffer if we malloc'd it - if ( bufStartPtr != &stackBuf[0] ) { - free(bufStartPtr); + result = _CFURLAlloc(allocator); + if ( result ) { + if ( !_CFURLInitWithFileSystemRepresentation(result, buffer, bufLen, isDirectory, NULL) ) { + CFRelease(result); + result = NULL; } } - else { - result = NULL; - } - - if ( addedPercentEncoding ) { - *addedPercentEncoding = addedPercent; - } return ( result ); } -CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory) { - CFURLRef newURL = NULL; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX - if ( bufLen && (*buffer == '/') ) { - Boolean addedPercentEncoding; - - CFStringRef urlStr = CreatePOSIXFileURLStringFromPOSIXAbsolutePath(allocator, buffer, bufLen, isDirectory, &addedPercentEncoding); - if ( urlStr ) { - newURL = _CFURLAlloc(allocator); - if ( newURL ) { - ((struct __CFURL *)newURL)->_flags |= USES_EIGHTBITSTRINGENCODING; - // we know urlStr has a scheme and is absolute - _CFURLInit((struct __CFURL *)newURL, urlStr, FULL_URL_REPRESENTATION, NULL); - ((struct __CFURL *)newURL)->_flags |= (IS_ABSOLUTE | IS_CANONICAL_FILE_URL); - if ( !addedPercentEncoding ) { - ((struct __CFURL *)newURL)->_flags |= POSIX_AND_URL_PATHS_MATCH; - } - } - CFRelease(urlStr); - } - else { - newURL = NULL; - } - } - else { - CFStringRef path = _createPathFromFileSystemRepresentation(allocator, buffer, bufLen, isDirectory); - if ( path ) { - newURL = CFURLCreateWithFileSystemPath(allocator, path, kCFURLPOSIXPathStyle, isDirectory); - CFRelease(path); - } - else { - newURL = NULL; +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; } } -#elif DEPLOYMENT_TARGET_WINDOWS - CFStringRef path = _createPathFromFileSystemRepresentation(allocator, buffer, bufLen, isDirectory); - if ( path ) { - newURL = CFURLCreateWithFileSystemPath(allocator, path, kCFURLWindowsPathStyle, isDirectory); - CFRelease(path); - } - else { - newURL = NULL; - } -#endif - return newURL; -} - -CF_EXPORT CFURLRef CFURLCreateFromFileSystemRepresentationRelativeToBase(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory, CFURLRef baseURL) { - CFStringRef path = _createPathFromFileSystemRepresentation(allocator, buffer, bufLen, isDirectory); - CFURLRef newURL = NULL; - if (!path) return NULL; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX - newURL = CFURLCreateWithFileSystemPathRelativeToBase(allocator, path, kCFURLPOSIXPathStyle, isDirectory, baseURL); -#elif DEPLOYMENT_TARGET_WINDOWS - newURL = CFURLCreateWithFileSystemPathRelativeToBase(allocator, path, kCFURLWindowsPathStyle, isDirectory, baseURL); -#endif - CFRelease(path); - return newURL; + + return ( result ); } @@ -4324,7 +4440,7 @@ CFStringRef CFURLCopyLastPathComponent(CFURLRef url) { } else { Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - if ( _CFURLIsFileReferenceURL(url) ) { + if ( CFURLIsFileReferenceURL(url) ) { // use a file path URL or fail CFURLRef filePathURL = CFURLCreateFilePathURL(CFGetAllocator(url), url, NULL); if ( filePathURL ) { @@ -4397,7 +4513,7 @@ CFURLRef CFURLCreateCopyAppendingPathComponent(CFAllocatorRef allocator, CFURLRe Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - if ( _CFURLIsFileReferenceURL(url) ) { + if ( CFURLIsFileReferenceURL(url) ) { // use a file path URL if possible (only because this is appending a path component) CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL); if ( filePathURL ) { @@ -4447,7 +4563,7 @@ CFURLRef CFURLCreateCopyDeletingLastPathComponent(CFAllocatorRef allocator, CFUR Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - if ( _CFURLIsFileReferenceURL(url) ) { + if ( CFURLIsFileReferenceURL(url) ) { // use a file path URL or fail CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL); if ( filePathURL ) { @@ -4524,7 +4640,7 @@ CFURLRef CFURLCreateCopyAppendingPathExtension(CFAllocatorRef allocator, CFURLRe Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - if ( _CFURLIsFileReferenceURL(url) ) { + if ( CFURLIsFileReferenceURL(url) ) { // use a file path URL or fail CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL); if ( filePathURL ) { @@ -4568,7 +4684,7 @@ CFURLRef CFURLCreateCopyDeletingPathExtension(CFAllocatorRef allocator, CFURLRef Boolean filePathURLCreated = false; #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED - if ( _CFURLIsFileReferenceURL(url) ) { + if ( CFURLIsFileReferenceURL(url) ) { // use a file path URL or fail CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL); if ( filePathURL ) { @@ -4694,7 +4810,7 @@ static CFStringRef escapePathComponent(CFAllocatorRef alloc, CFStringRef origCom return CFURLCreateStringByAddingPercentEscapes(alloc, origComponent, NULL, CFSTR(";?/"), kCFStringEncodingUTF8); } -static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) { +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; @@ -4708,6 +4824,16 @@ static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Bool } 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; } @@ -4802,7 +4928,10 @@ CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef alloc, CFProp return NULL; } urlTypeNum = (CFNumberRef)CFDictionaryGetValue(dict, CFSTR("_CFURLStringType")); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" if (!urlTypeNum || CFGetTypeID(urlTypeNum) != CFNumberGetTypeID() || !CFNumberGetValue(urlTypeNum, kCFNumberSInt32Type, &urlType) || (urlType != FULL_URL_REPRESENTATION && urlType != kCFURLPOSIXPathStyle && urlType != kCFURLHFSPathStyle && urlType != kCFURLWindowsPathStyle)) { +#pragma GCC diagnostic pop return NULL; } baseString = (CFStringRef)CFDictionaryGetValue(dict, CFSTR("_CFURLBaseURLString")); @@ -4811,8 +4940,11 @@ CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef alloc, CFProp return NULL; } baseTypeNum = (CFNumberRef)CFDictionaryGetValue(dict, CFSTR("_CFURLBaseStringType")); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" if (!baseTypeNum || CFGetTypeID(baseTypeNum) != CFNumberGetTypeID() || !CFNumberGetValue(baseTypeNum, kCFNumberSInt32Type, &baseType) || (baseType != FULL_URL_REPRESENTATION && baseType != kCFURLPOSIXPathStyle && baseType != kCFURLHFSPathStyle && baseType != kCFURLWindowsPathStyle)) { +#pragma GCC diagnostic pop return NULL; } if (baseType == FULL_URL_REPRESENTATION) { @@ -4832,19 +4964,24 @@ CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef alloc, CFProp #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED Boolean _CFURLIsFileReferenceURL(CFURLRef url) +{ + return ( CFURLIsFileReferenceURL(url) ); +} + +Boolean CFURLIsFileReferenceURL(CFURLRef url) { // returns TRUE if url is is a file URL whose path starts with a file ID reference Boolean result = false; CFURLRef baseURL = CFURLGetBaseURL(url); if ( baseURL ) { - result = _CFURLIsFileReferenceURL(baseURL); + result = CFURLIsFileReferenceURL(baseURL); } else { if ( CF_IS_OBJC(__kCFURLTypeID, url) ) { result = (Boolean) CF_OBJC_CALLV((NSURL *)url, isFileReferenceURL); } else { - result = ((_getSchemeTypeFromFlags(url->_flags) == kHasFileScheme) && (url->_flags & PATH_HAS_FILE_ID)); + result = ((_getSchemeTypeFromFlags(url->_flags) == kHasFileScheme) && ((url->_flags & PATH_HAS_FILE_ID) != 0)); } } return ( result ); @@ -4928,7 +5065,7 @@ CFURLRef CFURLCreateFilePathURL(CFAllocatorRef alloc, CFURLRef url, CFErrorRef * } if ( fsPath ) { CFStringRef urlPath = _replacePathIllegalCharacters( fsPath, alloc, true ); - newURLString = CFStringCreateWithFormat( alloc, NULL, CFSTR("file://%@%@%@%@"), (netLoc ? netLoc : CFSTR("")), urlPath, ((CFStringCompare(urlPath, CFSTR("/"), 0) != kCFCompareEqualTo) ? (CFURLHasDirectoryPath( url ) ? CFSTR("/") : CFSTR("")) : CFSTR("")), (rSpec ? rSpec : CFSTR(""))); + newURLString = CFStringCreateWithFormat( alloc, NULL, CFSTR(FILE_PREFIX "%@%@%@%@"), (netLoc ? netLoc : CFSTR("")), urlPath, ((CFStringCompare(urlPath, CFSTR("/"), 0) != kCFCompareEqualTo) ? (CFURLHasDirectoryPath( url ) ? CFSTR("/") : CFSTR("")) : CFSTR("")), (rSpec ? rSpec : CFSTR(""))); result = CFURLCreateWithString( alloc, newURLString, NULL ); CFRelease( newURLString ); CFRelease( urlPath ); diff --git a/CFURL.h b/CFURL.h index 8eeb525..406ce5c 100644 --- a/CFURL.h +++ b/CFURL.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFURL.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFURL__) @@ -38,7 +38,7 @@ CF_EXTERN_C_BEGIN typedef CF_ENUM(CFIndex, CFURLPathStyle) { kCFURLPOSIXPathStyle = 0, - kCFURLHFSPathStyle, /* The use of kCFURLHFSPathStyle is deprecated. The Carbon File Manager, which uses HFS style paths, is deprecated. HFS style paths are unreliable because they can arbitrarily refer to multiple volumes if those volumes have identical volume names. You should instead use kCFURLPOSIXPathStyle wherever possible. */ + kCFURLHFSPathStyle CF_ENUM_DEPRECATED(10_0, 10_9, 2_0, 7_0), /* The use of kCFURLHFSPathStyle is deprecated. The Carbon File Manager, which uses HFS style paths, is deprecated. HFS style paths are unreliable because they can arbitrarily refer to multiple volumes if those volumes have identical volume names. You should instead use kCFURLPOSIXPathStyle wherever possible. */ kCFURLWindowsPathStyle }; @@ -63,6 +63,11 @@ CFTypeID CFURLGetTypeID(void); /* encoding will be used both to interpret the bytes of URLBytes, and to */ /* interpret any percent-escapes within the bytes. */ +/* Using a string encoding which isn't a superset of ASCII encoding is not */ +/* supported because CFURLGetBytes and CFURLGetByteRangeForComponent require */ +/* 7-bit ASCII characters to be stored in a single 8-bit byte. */ +/* CFStringEncodings which are a superset of ASCII encoding include MacRoman, */ +/* WindowsLatin1, ISOLatin1, NextStepLatin, ASCII, and UTF8. */ CF_EXPORT CFURLRef CFURLCreateWithBytes(CFAllocatorRef allocator, const UInt8 *URLBytes, CFIndex length, CFStringEncoding encoding, CFURLRef baseURL); @@ -87,7 +92,12 @@ CFURLRef CFURLCreateWithString(CFAllocatorRef allocator, CFStringRef URLString, /* in relative portion, leading "../" components are removed from the */ /* final URL's path, and if the relative portion contains only */ /* resource specifier pieces (query, parameters, and fragment), then */ -/* the last path component of the base URL will not be deleted */ +/* the last path component of the base URL will not be deleted. */ +/* Using a string encoding which isn't a superset of ASCII encoding is not */ +/* supported because CFURLGetBytes and CFURLGetByteRangeForComponent require */ +/* 7-bit ASCII characters to be stored in a single 8-bit byte. */ +/* CFStringEncodings which are a superset of ASCII encoding include MacRoman, */ +/* WindowsLatin1, ISOLatin1, NextStepLatin, ASCII, and UTF8. */ CF_EXPORT CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *relativeURLBytes, CFIndex length, CFStringEncoding encoding, CFURLRef baseURL, Boolean useCompatibilityMode); @@ -412,6 +422,18 @@ CFStringRef CFURLCreateStringByAddingPercentEscapes(CFAllocatorRef allocator, CF #if (TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || CF_BUILDING_CF || NSBUILDINGFOUNDATION CF_IMPLICIT_BRIDGING_DISABLED +/* + CFURLIsFileReferenceURL + + Returns whether the URL is a file reference URL. + + Parameters + url + The URL specifying the resource. + */ +CF_EXPORT +Boolean CFURLIsFileReferenceURL(CFURLRef url) CF_AVAILABLE(10_9, 7_0); + /* CFURLCreateFileReferenceURL @@ -797,6 +819,10 @@ CF_EXPORT const CFStringRef kCFURLIsExcludedFromBackupKey CF_AVAILABLE(10_8, 5_1); /* true if resource should be excluded from backups, false otherwise (Read-write, value type CFBoolean). This property is only useful for excluding cache and other application support files which are not needed in a backup. Some operations commonly made to user documents will cause this property to be reset to false and so this property should not be used on user documents. */ +CF_EXPORT +const CFStringRef kCFURLTagNamesKey CF_AVAILABLE(10_9, NA); + /* The array of Tag names (Read-write, value type CFArray of CFString) */ + CF_EXPORT const CFStringRef kCFURLPathKey CF_AVAILABLE(10_8, 6_0); /* the URL's path as a file system path (Read-only, value type CFString) */ @@ -989,8 +1015,8 @@ const CFStringRef kCFURLUbiquitousItemHasUnresolvedConflictsKey CF_AVAILABLE(10_ /* true if this item has conflicts outstanding. (Read-only, value type CFBoolean) */ CF_EXPORT -const CFStringRef kCFURLUbiquitousItemIsDownloadedKey CF_AVAILABLE(10_7, 5_0); - /* true if there is local data present for this item. (Read-only, value type CFBoolean) */ +const CFStringRef kCFURLUbiquitousItemIsDownloadedKey CF_DEPRECATED(10_7, 10_9, 5_0, 7_0, "Use kCFURLUbiquitousItemDownloadingStatusKey instead"); + /* Equivalent to NSURLUbiquitousItemDownloadingStatusKey == NSURLUbiquitousItemDownloadingStatusCurrent. Has never behaved as documented in earlier releases, hence deprecated. (Read-only, value type CFBoolean) */ CF_EXPORT const CFStringRef kCFURLUbiquitousItemIsDownloadingKey CF_AVAILABLE(10_7, 5_0); @@ -1005,15 +1031,42 @@ const CFStringRef kCFURLUbiquitousItemIsUploadingKey CF_AVAILABLE(10_7, 5_0); /* true if data is being uploaded for this item. (Read-only, value type CFBoolean) */ CF_EXPORT -const CFStringRef kCFURLUbiquitousItemPercentDownloadedKey CF_DEPRECATED(10_7, 10_8, 5_0, 6_0); +const CFStringRef kCFURLUbiquitousItemPercentDownloadedKey CF_DEPRECATED(10_7, 10_8, 5_0, 6_0, "Use NSMetadataQuery and NSMetadataUbiquitousItemPercentDownloadedKey on NSMetadataItem instead"); /* Use NSMetadataQuery and NSMetadataUbiquitousItemPercentDownloadedKey on NSMetadataItem instead */ CF_EXPORT -const CFStringRef kCFURLUbiquitousItemPercentUploadedKey CF_DEPRECATED(10_7, 10_8, 5_0, 6_0); +const CFStringRef kCFURLUbiquitousItemPercentUploadedKey CF_DEPRECATED(10_7, 10_8, 5_0, 6_0, "Use NSMetadataQuery and NSMetadataUbiquitousItemPercentUploadedKey on NSMetadataItem instead"); /* Use NSMetadataQuery and NSMetadataUbiquitousItemPercentUploadedKey on NSMetadataItem instead */ +CF_EXPORT +const CFStringRef kCFURLUbiquitousItemDownloadingStatusKey CF_AVAILABLE(10_9, 7_0); + /* Returns the download status of this item. (Read-only, value type CFString). Possible values below. */ + +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. */ + +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. */ + +/* The values returned for kCFURLUbiquitousItemDownloadingStatusKey + */ +CF_EXPORT +const CFStringRef kCFURLUbiquitousItemDownloadingStatusNotDownloaded CF_AVAILABLE(10_9, 7_0); + /* this item has not been downloaded yet. Use NSFileManager's startDownloadingUbiquitousItemAtURL:error: to download it */ + +CF_EXPORT +const CFStringRef kCFURLUbiquitousItemDownloadingStatusDownloaded CF_AVAILABLE(10_9, 7_0); + /* there is a local version of this item available. The most current version will get downloaded as soon as possible. */ + +CF_EXPORT +const CFStringRef kCFURLUbiquitousItemDownloadingStatusCurrent CF_AVAILABLE(10_9, 7_0); + /* there is a local version of this item and it is the most up-to-date version known to this device. */ + + typedef CF_OPTIONS(CFOptionFlags, CFURLBookmarkCreationOptions) { - kCFURLBookmarkCreationPreferFileIDResolutionMask = ( 1UL << 8 ), // At resolution time, this alias will prefer resolving by the embedded fileID to the path + 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 @@ -1075,8 +1128,8 @@ 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 ( all properties if propertiesToReturn == NULL ). - This returns only the properties stored within the bookmark and will not attempt to resolve the bookmark or do i/o. + @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. diff --git a/CFURL.inc.h b/CFURL.inc.h new file mode 100644 index 0000000..a41c7f1 --- /dev/null +++ b/CFURL.inc.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2013 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@ + */ + +/* CFURL.inc.h + Copyright (c) 2012-2013, Apple Inc. All rights reserved. + Responsibility: Jim Luther +*/ + + +/* + + What's this file for? + + CFURL's URL string parser needs to be able to parse either an array of char or an array of UniChar. + + The code in CFURL.c used to use this macro "#define STRING_CHAR(x) (useCString ? cstring[(x)] : ustring[(x)])" to determine which array to get a character from for every character looked at in the URL string. That macro added one or more compare and branch instructins to the parser's execution for *every* character in the URL string. Those extra compares and branches added up to 10% of the time (for long URL strings) it takes to create a URL object. + + To ensure the exact same parser code is run over a char or a UniChar string, the source code was move to this .h file and is included multiple times by CFURL.c as needed. "STRING_CHAR(x)" was replaced by "characterArray[x]", and characterArray is defined as either an "const char *" or a "const UniChar *" for the two sets of function headers that are either parsing an array of char or an array of UniChar. + + Any changes made to the parser are made in this file so that both char and the UniChar strings are parsed exactly the same way. + + */ + +/* + 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) + */ +#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. */ + + CFIndex idx, base_idx = 0; + CFIndex string_length; + UInt32 flags = *theFlags; + Boolean isCompliant; + uint8_t numRanges = 0; + + string_length = cfStringLength; + + // Algorithm is as described in RFC 1808 + // 1: parse the fragment; remainder after left-most "#" is fragment + 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); + numRanges ++; + string_length = idx; // remove fragment from parse string + break; + } + } + // 2: parse the scheme + for (idx = base_idx; idx < string_length; idx++) { + UniChar ch = characterArray[idx]; + if (':' == ch) { + flags |= HAS_SCHEME; + ranges[0].location = base_idx; + ranges[0].length = idx; + numRanges ++; + base_idx = idx + 1; + // optimization for ftp urls + if (idx == 3 && characterArray[0] == 'f' && characterArray[1] == 't' && characterArray[2] == 'p') { + _setSchemeTypeInFlags(&flags, kHasFtpScheme); + } + else if (idx == 4) { + // optimization for http urls + if (characterArray[0] == 'h' && characterArray[1] == 't' && characterArray[2] == 't' && characterArray[3] == 'p') { + _setSchemeTypeInFlags(&flags, kHasHttpScheme); + } + // optimization for file urls + if (characterArray[0] == 'f' && characterArray[1] == 'i' && characterArray[2] == 'l' && characterArray[3] == 'e') { + _setSchemeTypeInFlags(&flags, kHasFileScheme); + } + // optimization for data urls + if (characterArray[0] == 'd' && characterArray[1] == 'a' && characterArray[2] == 't' && characterArray[3] == 'a') { + _setSchemeTypeInFlags(&flags, kHasDataScheme); + } + } + // optimization for https urls + else if (idx == 5 && characterArray[0] == 'h' && characterArray[1] == 't' && characterArray[2] == 't' && characterArray[3] == 'p' && characterArray[3] == 's') { + _setSchemeTypeInFlags(&flags, kHasHttpsScheme); + } + break; + } else if (!scheme_valid(ch)) { + break; // invalid scheme character -- no scheme + } + } + + // Make sure we have an RFC-1808 compliant URL - that's either something without a scheme, or scheme:/(stuff) or scheme://(stuff) + // Strictly speaking, RFC 1808 & 2396 bar "scheme:" (with nothing following the colon); however, common usage + // expects this to be treated identically to "scheme://" - REW, 12/08/03 + if (!(flags & HAS_SCHEME)) { + isCompliant = true; + } else if (base_idx == string_length) { + isCompliant = false; + } else if (characterArray[base_idx] != '/') { + isCompliant = false; + } else { + isCompliant = true; + } + + if (!isCompliant) { + // Clear the fragment flag if it's been set + if (flags & HAS_FRAGMENT) { + flags &= (~HAS_FRAGMENT); + string_length = cfStringLength; + } + (*theFlags) = flags; + (*range) = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0); + (*range)->location = ranges[0].location; + (*range)->length = ranges[0].length; + + return; + } + // 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; + + // 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; + break; + } + } + flags |= HAS_HOST; + numRanges ++; + ranges[3].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 ++; + ranges[4].location = idx+1; // base of port + ranges[4].length = extent - (idx+1); // port extent + ranges[3].length = idx - base; // host extent + break; + } + } + if (!(flags & HAS_PORT)) { + ranges[3].length = extent - base; // host 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; + } + } + + // 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; + } + } + + // 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; + } + } +#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; + } +#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS + 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) { + isDir = true; + } else { + 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 = (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 ++; + } + } +} +#endif // CFURL_INCLUDE_PARSE_COMPONENTS + +/* + static Boolean scanCharactersCString(CFAllocatorRef alloc, CFMutableStringRef *escapedString, UInt32 *flags, const char *characterArray, Boolean useCString, CFIndex base, CFIndex end, CFIndex *mark, UInt32 componentFlag, CFStringEncoding encoding) + static Boolean scanCharactersUString(CFAllocatorRef alloc, CFMutableStringRef *escapedString, UInt32 *flags, const UniChar *characterArray, Boolean useCString, CFIndex base, CFIndex end, CFIndex *mark, UInt32 componentFlag, CFStringEncoding encoding) + */ +#ifdef CFURL_INCLUDE_SCAN_CHARACTERS // defined when we want this block of code included +{ + CFIndex idx; + Boolean sawIllegalChar = false; + for (idx = base; idx < end; idx ++) { + Boolean shouldEscape; + UniChar ch = characterArray[idx]; + if (isURLLegalCharacter(ch)) { + if ((componentFlag == HAS_USER || componentFlag == HAS_PASSWORD) && (ch == '/' || ch == '?' || ch == '@')) { + shouldEscape = true; + } else { + shouldEscape = false; + } + } else if (ch == '%' && idx + 2 < end && isHexDigit(characterArray[idx + 1]) && isHexDigit(characterArray[idx+2])) { + shouldEscape = false; + } else if (componentFlag == HAS_HOST && ((idx == base && ch == '[') || (idx == end-1 && ch == ']'))) { + shouldEscape = false; + } else { + shouldEscape = true; + } + if (shouldEscape) { + sawIllegalChar = true; + if (componentFlag && flags) { + *flags |= componentFlag; + } + if (!*escapedString) { + *escapedString = CFStringCreateMutable(alloc, 0); + } + if (useCString) { + CFStringRef tempString = CFStringCreateWithBytes(alloc, (uint8_t *)&(characterArray[*mark]), idx - *mark, kCFStringEncodingISOLatin1, false); + CFStringAppend(*escapedString, tempString); + CFRelease(tempString); + } else { + CFStringAppendCharacters(*escapedString, (const UniChar *)&(characterArray[*mark]), idx - *mark); + } + *mark = idx + 1; + _appendPercentEscapesForCharacter(ch, encoding, *escapedString); // This can never fail because anURL->_string was constructed from the encoding passed in + } + } + return sawIllegalChar; +} +#endif // CFURL_INCLUDE_SCAN_CHARACTERS diff --git a/CFURLAccess.c b/CFURLAccess.c index d0b0a4d..2da209b 100644 --- a/CFURLAccess.c +++ b/CFURLAccess.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFURLAccess.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Chris Linn */ @@ -30,6 +30,9 @@ CFData read/write routines -------*/ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" + #include "CFInternal.h" #include #include @@ -852,5 +855,6 @@ Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode) { #endif } } +#pragma GCC diagnostic pop diff --git a/CFURLAccess.h b/CFURLAccess.h index af279ea..da2af3f 100644 --- a/CFURLAccess.h +++ b/CFURLAccess.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,9 @@ */ /* CFURLAccess.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, 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. */ #if !defined(__COREFOUNDATION_CFURLACCESS__) @@ -62,8 +64,9 @@ resource (file). Please use CFStream or other techniques if you are downloading 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_AVAILABLE(10_0, 2_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); /* Attempts to write the given data and properties to the given URL. If dataToWrite is NULL, only properties are written out (use @@ -73,18 +76,23 @@ is NULL or empty, the URL's properties are not changed at all. Returns success or failure; errorCode is set as for 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_AVAILABLE(10_0, 2_0); +Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef dataToWrite, CFDictionaryRef propertiesToWrite, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); -/* Destroys the resource indicated by url. */ -/* Returns success or failure; errorCode set as above. */ +/* 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_AVAILABLE(10_0, 2_0); +Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); -/* Convenience method which calls through to CFURLCreateDataAndPropertiesFromResource(). */ -/* Returns NULL on error and sets errorCode accordingly. */ +/* 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_AVAILABLE(10_0, 2_0); +CFTypeRef CFURLCreatePropertyFromResource(CFAllocatorRef alloc, CFURLRef url, CFStringRef property, SInt32 *errorCode) CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); /* Common error codes (returned only by the older APIs that predate CFError) */ @@ -98,26 +106,26 @@ typedef CF_ENUM(CFIndex, CFURLError) { kCFURLUnknownPropertyKeyError = -16L, kCFURLPropertyKeyUnavailableError = -17L, kCFURLTimeoutError = -18L -}; +} CF_ENUM_DEPRECATED(10_0, 10_9, 2_0, 7_0); /* Older property keys */ CF_EXPORT -const CFStringRef kCFURLFileExists CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLFileExists CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLFileDirectoryContents CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLFileDirectoryContents CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLFileLength CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLFileLength CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLFileLastModificationTime CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLFileLastModificationTime CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLFilePOSIXMode CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLFilePOSIXMode CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLFileOwnerID CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLFileOwnerID CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLHTTPStatusCode CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLHTTPStatusCode CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); CF_EXPORT -const CFStringRef kCFURLHTTPStatusLine CF_AVAILABLE(10_0, 2_0); +const CFStringRef kCFURLHTTPStatusLine CF_DEPRECATED(10_0, 10_9, 2_0, 7_0); /* 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 */ diff --git a/CFURLPriv.h b/CFURLPriv.h index 9066c97..17d94e2 100644 --- a/CFURLPriv.h +++ b/CFURLPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFURLPriv.h - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFURLPRIV__) @@ -69,18 +69,11 @@ enum { } CF_ENUM_AVAILABLE(10_5, 2_0); -/* - Error user dictionary keys -*/ -CF_EXPORT -const CFStringRef kCFURLKeyArrayErrorKey CF_AVAILABLE(10_6, 4_0); - - /* Private File System Property Keys */ -CF_EXPORT const CFStringRef _kCFURLPathKey CF_AVAILABLE(10_6, 4_0); - /* File system path (CFString) */ +CF_EXPORT const CFStringRef _kCFURLPathKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLPathKey or NSURLPathKey public property keys */ CF_EXPORT const CFStringRef _kCFURLVolumeIDKey CF_AVAILABLE(10_6, 4_0); /* Volume ID (CFNumber) */ @@ -95,10 +88,10 @@ CF_EXPORT const CFStringRef _kCFURLParentDirectoryIDKey CF_AVAILABLE(10_6, 4_0); /* 64-bit file ID (for tracking a parent directory by ID. This may or may not be the inode number) (CFNumber) */ CF_EXPORT const CFStringRef _kCFURLDistinctLocalizedNameKey CF_AVAILABLE(10_6, 4_0); - /* The localized name, if it is disnct from the real name. Otherwise, NULL (CFString) */ + /* The localized name, if it is distinct from the real name. Otherwise, NULL (CFString) */ CF_EXPORT const CFStringRef _kCFURLNameExtensionKey CF_AVAILABLE(10_6, 4_0); - /* The name extenison (CFString) */ + /* The name extension (CFString) */ CF_EXPORT const CFStringRef _kCFURLFinderInfoKey CF_AVAILABLE(10_6, 4_0); /* A 16-byte Finder Info structure immediately followed by a 16-byte Extended Finder Info structure (CFData) */ @@ -112,23 +105,23 @@ CF_EXPORT const CFStringRef _kCFURLIsApplicationKey CF_AVAILABLE(10_6, 4_0); CF_EXPORT const CFStringRef _kCFURLCanSetHiddenExtensionKey CF_AVAILABLE(10_6, 4_0); /* True if the filename extension can be hidden or unhidden (CFBoolean) */ -CF_EXPORT const CFStringRef _kCFURLIsReadableKey CF_AVAILABLE(10_6, 4_0); -/* OBSOLETE */CF_EXPORT const CFStringRef _kCFURLUserCanReadKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0); - /* True if current user can read the resource (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLIsReadableKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLIsReadableKey or NSURLIsReadableKey public property keys */ +/* never implemented and scheduled for removal in 10.10/8.0 */CF_EXPORT const CFStringRef _kCFURLUserCanReadKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0); -CF_EXPORT const CFStringRef _kCFURLIsWriteableKey CF_AVAILABLE(10_6, 4_0); -/* OBSOLETE */CF_EXPORT const CFStringRef _kCFURLUserCanWriteKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0); - /* True if current user can write to the resource (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLIsWriteableKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLIsWritableKey or NSURLIsWritableKey public property keys */ +/* never implemented and scheduled for removal in 10.10/8.0 */CF_EXPORT const CFStringRef _kCFURLUserCanWriteKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0); -CF_EXPORT const CFStringRef _kCFURLIsExecutableKey CF_AVAILABLE(10_6, 4_0); -/* OBSOLETE */CF_EXPORT const CFStringRef _kCFURLUserCanExecuteKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0); - /* True if current user can execute a file resource or search a directory resource (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLIsExecutableKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLIsExecutableKey or NSURLIsExecutableKey public property keys */ +/* never implemented and scheduled for removal in 10.10/8.0 */CF_EXPORT const CFStringRef _kCFURLUserCanExecuteKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0); CF_EXPORT const CFStringRef _kCFURLParentDirectoryIsVolumeRootKey CF_AVAILABLE(10_6, 4_0); /* True if the parent directory is the root of a volume (CFBoolean) */ -CF_EXPORT const CFStringRef _kCFURLFileSecurityKey CF_AVAILABLE(10_6, 4_0); - /* The file's security settings (FSFileSecurity, CarbonCore/Files.h) */ +CF_EXPORT const CFStringRef _kCFURLFileSecurityKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLFileSecurityKey or NSURLFileSecurityKey public property keys */ CF_EXPORT const CFStringRef _kCFURLFileSizeOfResourceForkKey CF_AVAILABLE(10_6, 4_0); /* Size in bytes of the resource fork (CFNumber) */ @@ -154,14 +147,14 @@ CF_EXPORT const CFStringRef _kCFURLVersionKey CF_AVAILABLE(10_6, 4_0); CF_EXPORT const CFStringRef _kCFURLShortVersionStringKey CF_AVAILABLE(10_6, 4_0); /* If resource is a bundle, the bundle short version (CFBundleShortVersionString) as a string (CFString) */ -CF_EXPORT const CFStringRef _kCFURLOwnerIDKey CF_AVAILABLE(10_6, 4_0); - /* 32-bit owner ID (uid_t) (CFNumber) */ +CF_EXPORT const CFStringRef _kCFURLOwnerIDKey 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 - Use the kCFURLFileSecurityKey or NSURLFileSecurityKey public property keys and CFFileSecurityGetOwner() */ -CF_EXPORT const CFStringRef _kCFURLGroupIDKey CF_AVAILABLE(10_6, 4_0); - /* 32-bit group ID (gid_t) (CFNumber) */ +CF_EXPORT const CFStringRef _kCFURLGroupIDKey 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 - Use the kCFURLFileSecurityKey or NSURLFileSecurityKey public property keys and CFFileSecurityGetGroup() */ -CF_EXPORT const CFStringRef _kCFURLStatModeKey CF_AVAILABLE(10_6, 4_0); - /* 32-bit group ID (mode_t) (CFNumber) */ +CF_EXPORT const CFStringRef _kCFURLStatModeKey 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 - Use the kCFURLFileSecurityKey or NSURLFileSecurityKey public property keys and CFFileSecurityGetMode() */ CF_EXPORT const CFStringRef _kCFURLLocalizedNameDictionaryKey CF_AVAILABLE(10_7, NA); /* For items with localized display names, the dictionary of all available localizations. The keys are the cannonical locale strings for the available localizations. (CFDictionary) */ @@ -181,43 +174,49 @@ CF_EXPORT const CFStringRef _kCFURLCanSetApplicationHighResolutionModeIsMagnifie CF_EXPORT const CFStringRef _kCFURLWriterBundleIdentifierKey CF_AVAILABLE(10_8, NA); /* The bundle identifier of the process writing to this object (Read-write, value type CFString) */ +CF_EXPORT const CFStringRef _kCFURLApplicationNapIsDisabledKey CF_AVAILABLE(10_9, NA); + /* True if app nap is disabled (Applications only, Per-user, CFBoolean) */ + +CF_EXPORT const CFStringRef _kCFURLCanSetApplicationNapIsDisabledKey CF_AVAILABLE(10_9, NA); + /* True if the ApplicationNapIsDisabled property value can be changed (Applications only, Read only, CFBoolean) */ + /* Additional volume properties */ CF_EXPORT const CFStringRef _kCFURLVolumeRefNumKey CF_AVAILABLE(10_6, 4_0); /* The Carbon File Manager's FSVolumeRefNum for the resource volume (CFNumber) */ -CF_EXPORT const CFStringRef _kCFURLVolumeUUIDStringKey CF_AVAILABLE(10_6, 4_0); - /* The volume's persistent unique ID as a string, or NULL if not available (CFString) */ +CF_EXPORT const CFStringRef _kCFURLVolumeUUIDStringKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeUUIDStringKey or NSURLVolumeUUIDStringKey public property keys */ -CF_EXPORT const CFStringRef _kCFURLVolumeCreationDateKey CF_AVAILABLE(10_6, 4_0); - /* Value type CFDate */ +CF_EXPORT const CFStringRef _kCFURLVolumeCreationDateKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeCreationDateKey or NSURLVolumeCreationDateKey public property keys */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsLocalKey CF_AVAILABLE(10_6, 4_0); - /* Volume is on a locally connected device -- not a network volume (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsLocalKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsLocalKey or NSURLVolumeIsLocalKey public property keys */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsAutomountKey CF_AVAILABLE(10_6, 4_0); - /* Volume was mounted by the automounter (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsAutomountKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsAutomountedKey or NSURLVolumeIsAutomountedKey public property keys */ -CF_EXPORT const CFStringRef _kCFURLVolumeDontBrowseKey CF_AVAILABLE(10_6, 4_0); - /* Don't browse: generally, not shown to users (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeDontBrowseKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsBrowsableKey or NSURLVolumeIsBrowsableKey public property keys (Note: value is inverse of _kCFURLVolumeDontBrowseKey) */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsReadOnlyKey CF_AVAILABLE(10_6, 4_0); - /* Mounted read-only (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsReadOnlyKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsReadOnlyKey or NSURLVolumeIsReadOnlyKey public property keys */ CF_EXPORT const CFStringRef _kCFURLVolumeIsQuarantinedKey CF_AVAILABLE(10_6, 4_0); /* Mounted quarantined (CFBoolean) */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsEjectableKey CF_AVAILABLE(10_6, 4_0); - /* Volume is ejectable media (CD, DVD, etc) (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsEjectableKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsEjectableKey or NSURLVolumeIsEjectableKey public property keys */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsRemovableKey CF_AVAILABLE(10_6, 4_0); - /* Volume can be disconnected (USB, FireWire) (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsRemovableKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsRemovableKey or NSURLVolumeIsRemovableKey public property keys */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsInternalKey CF_AVAILABLE(10_6, 4_0); - /* Device is on an internal bus/channel (Note: this has different behavior than the public VolumeIsInternal key) (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsInternalKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsInternalKey or NSURLVolumeIsInternalKey public property keys (Note: this has slightly different behavior than the public VolumeIsInternal key) */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsExternalKey CF_AVAILABLE(10_6, 4_0); - /* Device is on an external bus/channel (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsExternalKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - Use the kCFURLVolumeIsInternalKey or NSURLVolumeIsInternalKey public property keys (Note: this has slightly different behavior than the public VolumeIsInternal key) */ CF_EXPORT const CFStringRef _kCFURLVolumeIsDiskImageKey CF_AVAILABLE(10_6, 4_0); /* Volume is a mounted disk image (CFBoolean) */ @@ -228,14 +227,14 @@ CF_EXPORT const CFStringRef _kCFURLDiskImageBackingURLKey CF_AVAILABLE(10_6, 4_0 CF_EXPORT const CFStringRef _kCFURLVolumeIsFileVaultKey CF_AVAILABLE(10_6, 4_0); /* Volume uses File Vault encryption (CFBoolean) */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsiDiskKey CF_AVAILABLE(10_6, 4_0); - /* Volume is an iDisk (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsiDiskKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - there are no more iDisks */ -CF_EXPORT const CFStringRef _kCFURLVolumeiDiskUserNameKey CF_AVAILABLE(10_6, 4_0); - /* If volume is an iDisk, the base member name of the iDisk owner (CFString) */ +CF_EXPORT const CFStringRef _kCFURLVolumeiDiskUserNameKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - there are no more iDisks */ -CF_EXPORT const CFStringRef _kCFURLVolumeIsLocaliDiskMirrorKey CF_AVAILABLE(10_6, 4_0); - /* Volume is a local mirror of an iDisk (CFBoolean) */ +CF_EXPORT const CFStringRef _kCFURLVolumeIsLocaliDiskMirrorKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* Deprecated and scheduled for removal in 10.10/8.0 - there are no more iDisks */ CF_EXPORT const CFStringRef _kCFURLVolumeIsiPodKey CF_AVAILABLE(10_6, 4_0); /* Volume is on an iPod (CFBoolean) */ @@ -252,25 +251,23 @@ CF_EXPORT const CFStringRef _kCFURLVolumeIsDeviceFileSystemKey CF_AVAILABLE(10_7 CF_EXPORT const CFStringRef _kCFURLVolumeIsHFSStandardKey CF_AVAILABLE(10_6, 4_0); /* Volume is HFS standard (which includes AFP volumes). Directory IDs, but not file IDs, can be looked up. (CFBoolean) */ -/* Keys specific to bookmarks at this time */ -CF_EXPORT const CFStringRef _kCFURLPropertyKeyFullPathString CF_AVAILABLE(10_6, 4_0); - /* the full filesystem path of the item the bookmark was create against */ - -CF_EXPORT const CFStringRef _kCFURLURLString CF_AVAILABLE(10_6, 4_0); - /* the url string ( possibly relative to a base url ) of the url this bookmark was created against. */ +CF_EXPORT const CFStringRef _kCFURLVolumeIOMediaIconFamilyNameKey CF_AVAILABLE(10_9, NA); + /* Volume's IOMediaIconFamilyName. (CFStringRef) */ -CF_EXPORT const CFStringRef _kCFURLFileIDData CF_AVAILABLE(10_6, 4_0); - /* the url string ( possibly relative to a base url ) of the url this bookmark was created against. */ +CF_EXPORT const CFStringRef _kCFURLVolumeIOMediaIconBundleIdentifierKey CF_AVAILABLE(10_9, NA); + /* Volume's IOMediaIconBundleIdentifier. (CFStringRef) */ -CF_EXPORT const CFStringRef _kCFURLResolvedFromBookmarkDataKey CF_AVAILABLE(10_6, 4_0); - /* the bookmark data that was resolved to produce the URL, if any (CFData) */ +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 (*/ -CF_EXPORT const CFStringRef _kCFURLVolumeMountPointStringKey CF_AVAILABLE(10_6, 4_0); +CF_EXPORT const CFStringRef _kCFURLVolumeMountPointStringKey CF_AVAILABLE(10_6, 4_0); /* the volume mountpoint string (Read-only, value type CFString) */ -CF_EXPORT const CFStringRef _kCFURLCompleteMountURLKey CF_AVAILABLE(10_6, 4_0); - /* the URL to mount the volume on which the resource is stored, if any (Read-only, value type CFURL) */ +CF_EXPORT const CFStringRef _kCFURLCompleteMountURLKey CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); + /* 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) */ /* @@ -290,7 +287,8 @@ enum { kCFURLResourceHasHiddenExtension = 0x00000100, kCFURLResourceIsApplication = 0x00000200, kCFURLResourceIsCompressed = 0x00000400, - /* OBSOLETE */ kCFURLResourceIsSystemCompressed = 0x00000400, /* -> kCFURLResourceIsCompressed */ + kCFURLResourceIsSystemCompressed CF_ENUM_DEPRECATED(10_6, 10_9, 4_0, 7_0) + = 0x00000400, /* Deprecated and scheduled for removal in 10.10/8.0 - Use kCFURLResourceIsCompressed */ kCFURLCanSetHiddenExtension = 0x00000800, kCFURLResourceIsReadable = 0x00001000, kCFURLResourceIsWriteable = 0x00002000, @@ -377,12 +375,33 @@ typedef CF_OPTIONS(unsigned long long, CFURLVolumePropertyFlags) { kCFURLVolumeIsExternal = 0x100LL, kCFURLVolumeIsDiskImage = 0x200LL, kCFURLVolumeIsFileVault = 0x400LL, - kCFURLVolumeIsLocaliDiskMirror = 0x800LL, + kCFURLVolumeIsLocaliDiskMirror CF_ENUM_DEPRECATED(10_6, 10_9, 4_0, 7_0) + = 0x800LL, // Deprecated and scheduled for removal in 10.10/8.0 - there are no more iDisks kCFURLVolumeIsiPod = 0x1000LL, - kCFURLVolumeIsiDisk = 0x2000LL, + kCFURLVolumeIsiDisk CF_ENUM_DEPRECATED(10_6, 10_9, 4_0, 7_0) + = 0x2000LL, // Deprecated and scheduled for removal in 10.10/8.0 - there are no more iDisks kCFURLVolumeIsCD = 0x4000LL, kCFURLVolumeIsDVD = 0x8000LL, kCFURLVolumeIsDeviceFileSystem = 0x10000LL, + kCFURLVolumeIsTimeMachine CF_ENUM_AVAILABLE_MAC(10_9) + = 0x20000LL, + kCFURLVolumeIsAirport CF_ENUM_AVAILABLE_MAC(10_9) + = 0x40000LL, + kCFURLVolumeIsVideoDisk CF_ENUM_AVAILABLE_MAC(10_9) + = 0x80000LL, + kCFURLVolumeIsDVDVideo CF_ENUM_AVAILABLE_MAC(10_9) + = 0x100000LL, + kCFURLVolumeIsBDVideo CF_ENUM_AVAILABLE_MAC(10_9) + = 0x200000LL, + kCFURLVolumeIsMobileTimeMachine CF_ENUM_AVAILABLE_MAC(10_9) + = 0x400000LL, + kCFURLVolumeIsNetworkOptical CF_ENUM_AVAILABLE_MAC(10_9) + = 0x800000LL, + kCFURLVolumeIsBeingRepaired CF_ENUM_AVAILABLE_MAC(10_9) + = 0x1000000LL, + kCFURLVolumeIsBeingUnmounted CF_ENUM_AVAILABLE_MAC(10_9) + = 0x2000000LL, + // IMPORTANT: The values of the following flags must stay in sync with the // VolumeCapabilities flags in CarbonCore (FileIDTreeStorage.h) kCFURLVolumeSupportsPersistentIDs = 0x100000000LL, @@ -428,6 +447,53 @@ typedef CF_OPTIONS(unsigned long long, CFURLVolumePropertyFlags) { CF_EXPORT Boolean _CFURLGetVolumePropertyFlags(CFURLRef url, CFURLVolumePropertyFlags mask, CFURLVolumePropertyFlags *flags, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0); + +/* _CFURLCopyResourcePropertyForKeyFromCache works like CFURLCopyResourcePropertyForKey + only it never causes I/O. If the property value requested is cached (or known + to be not available) for the resource, return TRUE and the property value. The + property value returned could be NULL meaning that property is not available + for the resource. If the property value requested is not cached or the resource, + FALSE is returned. + + Only for use by DesktopServices! + */ +CF_EXPORT +Boolean _CFURLCopyResourcePropertyForKeyFromCache(CFURLRef url, CFStringRef key, void *cfTypeRefValue) CF_AVAILABLE(10_8, NA); + +/* _CFURLCopyResourcePropertiesForKeysFromCache works like CFURLCopyResourcePropertiesForKeys + only it never causes I/O. If the property values requested are cached (or known + to be not available) for the resource, return a CFDictionary. Property values + not available for the resource are not included in the CFDictionary. + If the values requested are not cached, return NULL. + + Only for use by DesktopServices! + */ +CF_EXPORT +CFDictionaryRef _CFURLCopyResourcePropertiesForKeysFromCache(CFURLRef url, CFArrayRef keys) CF_AVAILABLE(10_8, NA); + +/* _CFURLCacheResourcePropertyForKey works like CFURLCopyResourcePropertyForKey + only it does not return the property value -- it just ensures the value is cached. + If no errors occur, TRUE is returned. If an error occurs, FALSE is returned + and the optional output error is set to a valid CFErrorRef (which must be + released by the caller. + + Only for use by DesktopServices! + */ +CF_EXPORT +Boolean _CFURLCacheResourcePropertyForKey(CFURLRef url, CFStringRef key, CFErrorRef *error) CF_AVAILABLE(10_8, NA); + +/* _CFURLCacheResourcePropertiesForKeys works like CFURLCopyResourcePropertiesForKeys + only it does not return the property values -- it just ensures the values is cached. + If no errors occur, TRUE is returned. If an error occurs, FALSE is returned + and the optional output error is set to a valid CFErrorRef (which must be + released by the caller. + + Only for use by DesktopServices! + */ +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) @@ -477,9 +543,9 @@ CFArrayRef _CFURLCreateDisplayPathComponentsArray(CFURLRef url, CFErrorRef *erro CF_EXPORT Boolean _CFURLIsFileURL(CFURLRef url) CF_AVAILABLE(10_6, 4_0); -/* Returns true for file URLs that use the file reference form */ +/* Deprecated and scheduled for removal in 10.10/8.0 - Use the public API CFURLIsFileReferenceURL() */ CF_EXPORT -Boolean _CFURLIsFileReferenceURL(CFURLRef url) CF_AVAILABLE(10_6, 4_0); +Boolean _CFURLIsFileReferenceURL(CFURLRef url) CF_DEPRECATED(10_6, 10_9, 4_0, 7_0); /* For use by Core Services */ CF_EXPORT @@ -488,27 +554,6 @@ void *__CFURLResourceInfoPtr(CFURLRef url) CF_AVAILABLE(10_6, 4_0); CF_EXPORT void __CFURLSetResourceInfoPtr(CFURLRef url, void *ptr) CF_AVAILABLE(10_6, 4_0); -#if TARGET_OS_MAC - -CF_EXPORT -CFURLRef _CFURLCreateFileReferenceURLFromIDs( CFAllocatorRef allocator, fsid_t fsid, UInt64 inodeNumber ) CF_AVAILABLE(10_7, NA); - -/* _CFURLVolumeIdentifierGetVolumeRefNum is used by LaunchServices */ -CF_EXPORT -SInt16 _CFURLVolumeIdentifierGetVolumeRefNum(UInt64 volumeIdentifier) CF_AVAILABLE(10_7, NA); - -CF_EXPORT -CFURLRef _CFURLCreateFileReferenceURLFromFSRef(CFAllocatorRef allocator, const struct FSRef *ref) CF_AVAILABLE(10_7, NA); - -/* _CFURLGetFSRef is a very lightweight version of CFURLGetFSRef that assumes the CFURL is a file URL and the properties needed to create a FSRef are available in the file URL's cache. This is for use only by CarbonCore's FileOperations SPI and API. */ -CF_EXPORT -Boolean _CFURLGetFSRef(CFURLRef url, struct FSRef *fsRef) CF_AVAILABLE(10_7, NA); - -/* _CFURLGetObjectInformationNoIO is used by LaunchServices */ -CF_EXPORT -Boolean _CFURLGetObjectInformationNoIO(CFURLRef url, UInt64 * volumeIdentifier, UInt64 * objectIdentifier, UInt32 * statMode) CF_AVAILABLE(10_7, NA); - -#endif struct FSCatalogInfo; struct HFSUniStr255; @@ -561,15 +606,9 @@ typedef CF_ENUM(CFIndex, CFURLBookmarkMatchResult) { kCFURLBookmarkComparisonExactMatch = 0x0000f000 /* the two bookmarks are identical */ }; -/* Keys specific to bookmarks at this time */ -CF_EXPORT const CFStringRef _kCFURLPropertyKeyFullPathString; // the full filesystem path of the item the bookmark was create against -CF_EXPORT const CFStringRef _kCFURLURLString; // the url string ( possibly relative to a base url ) of the url this bookmark was created against. -CF_EXPORT const CFStringRef _kCFURLFileIDData; // the url string ( possibly relative to a base url ) of the url this bookmark was created against. - -CFURLBookmarkMatchResult _CFURLCompareBookmarkData( CFDataRef bookmark1Ref, CFDataRef bookmark2Ref, CFURLRef relativeToURL, CFArrayRef* matchingPropertyKeys ) CF_AVAILABLE(10_7, NA); - +/* The relativeToURL and matchingPropertyKeys parameters are not used and are ignored */ CF_EXPORT -CFURLBookmarkMatchResult _CFURLBookmarkDataCompare(CFDataRef bookmark1Ref, CFDataRef bookmark2Ref, CFURLRef relativeToURL, CFArrayRef* matchingPropertyKeys) CF_AVAILABLE(10_7, NA); // Use _CFURLCompareBookmarkData() instead +CFURLBookmarkMatchResult _CFURLBookmarkDataCompare(CFDataRef bookmark1Ref, CFDataRef bookmark2Ref, CFURLRef relativeToURL, CFArrayRef* matchingPropertyKeys) CF_AVAILABLE(10_7, NA); CF_EXPORT OSStatus _CFURLBookmarkDataToAliasHandle(CFDataRef bookmarkRef, void* aliasHandleP) CF_AVAILABLE(10_7, NA); diff --git a/CFUUID.c b/CFUUID.c index e820e8c..03c815d 100644 --- a/CFUUID.c +++ b/CFUUID.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUUID.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -232,7 +232,7 @@ static const CFRuntimeClass __CFUUIDClass = { __CFUUIDCopyDescription }; -__private_extern__ void __CFUUIDInitialize(void) { +CF_PRIVATE void __CFUUIDInitialize(void) { __kCFUUIDTypeID = _CFRuntimeRegisterClass(&__CFUUIDClass); } diff --git a/CFUUID.h b/CFUUID.h index 04b5e1d..b1f95f9 100644 --- a/CFUUID.h +++ b/CFUUID.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUUID.h - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUUID__) diff --git a/CFUniChar.c b/CFUniChar.c index ec63504..56445c7 100644 --- a/CFUniChar.c +++ b/CFUniChar.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUniChar.c - Copyright (c) 2001-2012, Apple Inc. All rights reserved. + Copyright (c) 2001-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -76,7 +76,30 @@ CF_INLINE uint32_t __CFUniCharMapCompatibilitySetID(uint32_t cset) { return ((cs #include #include +extern const void* unicode_csbitmaps_section_start __asm("section$start$__UNICODE$__csbitmaps"); +extern const void* unicode_csbitmaps_section_end __asm("section$end$__UNICODE$__csbitmaps"); +extern const void* unicode_properties_section_start __asm("section$start$__UNICODE$__properties"); +extern const void* unicode_properties_section_end __asm("section$end$__UNICODE$__properties"); +extern const void* unicode_data_section_start __asm("section$start$__UNICODE$__data"); +extern const void* unicode_data_section_end __asm("section$end$__UNICODE$__data"); + static const void *__CFGetSectDataPtr(const char *segname, const char *sectname, uint64_t *sizep) { + // special case three common sections to have fast access + if ( strcmp(segname, "__UNICODE") == 0 ) { + if ( strcmp(sectname, "__csbitmaps") == 0) { + if (sizep) *sizep = &unicode_csbitmaps_section_end - &unicode_csbitmaps_section_start; + return &unicode_csbitmaps_section_start; + } + else if ( strcmp(sectname, "__properties") == 0 ) { + if (sizep) *sizep = &unicode_properties_section_end - &unicode_properties_section_start; + return &unicode_properties_section_start; + } + else if ( strcmp(sectname, "__data") == 0 ) { + if (sizep) *sizep = &unicode_data_section_end - &unicode_data_section_start; + return &unicode_data_section_start; + } + } + uint32_t idx, cnt = _dyld_image_count(); for (idx = 0; idx < cnt; idx++) { void *mh = (void *)_dyld_get_image_header(idx); @@ -247,7 +270,11 @@ static bool __CFUniCharLoadFile(const wchar_t *bitmapName, const void **bytes, i char cpath[MAXPATHLEN]; __CFUniCharCharacterSetPath(cpath); strlcat(cpath, bitmapName, MAXPATHLEN); - return __CFUniCharLoadBytesFromFile(cpath, bytes, fileSize); + Boolean needToFree = false; + const char *possiblyFrameworkRootedCPath = CFPathRelativeToAppleFrameworksRoot(cpath, &needToFree); + bool result = __CFUniCharLoadBytesFromFile(possiblyFrameworkRootedCPath, bytes, fileSize); + if (needToFree) free((void *)possiblyFrameworkRootedCPath); + return result; #elif DEPLOYMENT_TARGET_WINDOWS wchar_t wpath[MAXPATHLEN]; __CFUniCharCharacterSetPath(wpath); @@ -403,7 +430,7 @@ static bool __CFUniCharLoadBitmapData(void) { return true; } -__private_extern__ const char *__CFUniCharGetUnicodeVersionString(void) { +CF_PRIVATE const char *__CFUniCharGetUnicodeVersionString(void) { if (NULL == __CFUniCharBitmapDataArray) __CFUniCharLoadBitmapData(); return __CFUniCharUnicodeVersionString; } @@ -473,7 +500,7 @@ const uint8_t *CFUniCharGetBitmapPtrForPlane(uint32_t charset, uint32_t plane) { return NULL; } -__private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t plane, void *bitmap, bool isInverted) { +CF_PRIVATE uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t plane, void *bitmap, bool isInverted) { const uint8_t *src = CFUniCharGetBitmapPtrForPlane(charset, plane); int numBytes = (8 * 1024); @@ -601,7 +628,7 @@ __private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t return (isInverted ? kCFUniCharBitmapAll : kCFUniCharBitmapEmpty); } -__private_extern__ uint32_t CFUniCharGetNumberOfPlanes(uint32_t charset) { +CF_PRIVATE uint32_t CFUniCharGetNumberOfPlanes(uint32_t charset) { if ((charset == kCFUniCharControlCharacterSet) || (charset == kCFUniCharControlAndFormatterCharacterSet)) { return 15; // 0 to 14 } else if (charset < kCFUniCharDecimalDigitCharacterSet) { @@ -656,7 +683,7 @@ static CFSpinLock_t __CFUniCharMappingTableLock = CFSpinLockInit; #error Unknown or unspecified DEPLOYMENT_TARGET #endif -__private_extern__ const void *CFUniCharGetMappingData(uint32_t type) { +CF_PRIVATE const void *CFUniCharGetMappingData(uint32_t type) { __CFSpinLock(&__CFUniCharMappingTableLock); @@ -1070,7 +1097,7 @@ CF_INLINE bool __CFUniCharIsAfter_i(UTF16Char *buffer, CFIndex length) { return true; } -__private_extern__ uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char theChar, UTF16Char *buffer, CFIndex currentIndex, CFIndex length, uint32_t type, const uint8_t *langCode, uint32_t lastFlags) { +CF_PRIVATE uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char theChar, UTF16Char *buffer, CFIndex currentIndex, CFIndex length, uint32_t type, const uint8_t *langCode, uint32_t lastFlags) { if (theChar == 0x03A3) { // GREEK CAPITAL LETTER SIGMA if ((type == kCFUniCharToLowercase) && (currentIndex > 0)) { UTF16Char *start = buffer; @@ -1110,10 +1137,12 @@ __private_extern__ uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char th return (__CFUniCharIsAfter_i(buffer, currentIndex) ? kCFUniCharCaseMapAfter_i : 0); } else if (type == kCFUniCharToLowercase) { if ((theChar == 0x0049) || (theChar == 0x004A) || (theChar == 0x012E)) { - return (__CFUniCharIsMoreAbove(buffer + (++currentIndex), length - currentIndex) ? kCFUniCharCaseMapMoreAbove : 0); + ++currentIndex; + return (__CFUniCharIsMoreAbove(buffer + currentIndex, length - currentIndex) ? kCFUniCharCaseMapMoreAbove : 0); } } else if ((theChar == 'i') || (theChar == 'j')) { - return (__CFUniCharIsMoreAbove(buffer + (++currentIndex), length - currentIndex) ? (kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove) : 0); + ++currentIndex; + return (__CFUniCharIsMoreAbove(buffer + currentIndex, length - currentIndex) ? (kCFUniCharCaseMapAfter_i|kCFUniCharCaseMapMoreAbove) : 0); } } else if ((*((const uint16_t *)langCode) == TURKISH_LANG_CODE) || (*((const uint16_t *)langCode) == AZERI_LANG_CODE)) { if (type == kCFUniCharToLowercase) { @@ -1139,7 +1168,7 @@ __private_extern__ uint32_t CFUniCharGetConditionalCaseMappingFlags(UTF32Char th } } if (((theChar >= 0x0370) && (theChar < 0x0400)) || ((theChar >= 0x1F00) && (theChar < 0x2000))) { // Greek/Coptic & Greek extended ranges - if (((type == kCFUniCharToUppercase) || (type == kCFUniCharToTitlecase))&& (CFUniCharIsMemberOf(theChar, kCFUniCharLetterCharacterSet))) return kCFUniCharCaseMapGreekTonos; + if ((type == kCFUniCharToUppercase) && (CFUniCharIsMemberOf(theChar, kCFUniCharLetterCharacterSet))) return kCFUniCharCaseMapGreekTonos; } } return 0; @@ -1238,12 +1267,12 @@ const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint3 return (plane < __CFUniCharUnicodePropertyTable[propertyType]._numPlanes ? __CFUniCharUnicodePropertyTable[propertyType]._planes[plane] : NULL); } -__private_extern__ uint32_t CFUniCharGetNumberOfPlanesForUnicodePropertyData(uint32_t propertyType) { +CF_PRIVATE uint32_t CFUniCharGetNumberOfPlanesForUnicodePropertyData(uint32_t propertyType) { (void)CFUniCharGetUnicodePropertyDataForPlane(propertyType, 0); return __CFUniCharUnicodePropertyTable[propertyType]._numPlanes; } -__private_extern__ uint32_t CFUniCharGetUnicodeProperty(UTF32Char character, uint32_t propertyType) { +CF_PRIVATE uint32_t CFUniCharGetUnicodeProperty(UTF32Char character, uint32_t propertyType) { if (propertyType == kCFUniCharCombiningProperty) { return CFUniCharGetCombiningPropertyForCharacter(character, (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(propertyType, (character >> 16) & 0xFF)); } else if (propertyType == kCFUniCharBidiProperty) { diff --git a/CFUniChar.h b/CFUniChar.h index b886945..2dc365f 100644 --- a/CFUniChar.h +++ b/CFUniChar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUniChar.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUNICHAR__) @@ -227,7 +227,7 @@ CF_INLINE bool CFUniCharFromUTF32(const UTF32Char *src, CFIndex length, UTF16Cha while (src < limit) { character = (isBigEndien ? CFSwapInt32BigToHost(*(src++)) : CFSwapInt32LittleToHost(*(src++))); - if (character < 0xFFFF) { // BMP + if (character < 0x10000) { // BMP if (allowLossy) { if (CFUniCharIsSurrogateHighCharacter(character)) { UTF32Char otherCharacter = 0xFFFD; // replacement character diff --git a/CFUniCharPriv.h b/CFUniCharPriv.h index de85604..205fa52 100644 --- a/CFUniCharPriv.h +++ b/CFUniCharPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUniCharPriv.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUNICHARPRIV__) diff --git a/CFUnicodeDecomposition.c b/CFUnicodeDecomposition.c index 4026b4f..f760704 100644 --- a/CFUnicodeDecomposition.c +++ b/CFUnicodeDecomposition.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUnicodeDecomposition.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -357,7 +357,7 @@ CF_INLINE void __CFUniCharMoveBufferFromEnd1(UTF32Char *convertedChars, CFIndex while (convertedChars > limit) *(--dstP) = *(--convertedChars); } -__private_extern__ CFIndex CFUniCharCompatibilityDecompose(UTF32Char *convertedChars, CFIndex length, CFIndex maxBufferLength) { +CF_PRIVATE CFIndex CFUniCharCompatibilityDecompose(UTF32Char *convertedChars, CFIndex length, CFIndex maxBufferLength) { UTF32Char currentChar; UTF32Char buffer[MAX_COMP_DECOMP_LEN]; const UTF32Char *bufferP; diff --git a/CFUnicodeDecomposition.h b/CFUnicodeDecomposition.h index 35e82b4..36a8add 100644 --- a/CFUnicodeDecomposition.h +++ b/CFUnicodeDecomposition.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,7 +26,7 @@ * CoreFoundation * * Created by aki on Wed Oct 03 2001. - * Copyright (c) 2001-2012, Apple Inc. All rights reserved. + * Copyright (c) 2001-2013, Apple Inc. All rights reserved. * */ diff --git a/CFUnicodePrecomposition.c b/CFUnicodePrecomposition.c index 915bf86..b66532e 100644 --- a/CFUnicodePrecomposition.c +++ b/CFUnicodePrecomposition.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUnicodePrecomposition.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: Aki Inoue */ @@ -121,7 +121,7 @@ static uint32_t __CFUniCharGetMappedValue_P(const __CFUniCharPrecomposeMappings return 0; } -__private_extern__ +CF_PRIVATE UTF32Char CFUniCharPrecomposeCharacter(UTF32Char base, UTF32Char combining) { uint32_t value; diff --git a/CFUnicodePrecomposition.h b/CFUnicodePrecomposition.h index 97ce588..5f01591 100644 --- a/CFUnicodePrecomposition.h +++ b/CFUnicodePrecomposition.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,7 +26,7 @@ * CoreFoundation * * Created by aki on Wed Oct 03 2001. - * Copyright (c) 2001-2012, Apple Inc. All rights reserved. + * Copyright (c) 2001-2013, Apple Inc. All rights reserved. * */ diff --git a/CFUserNotification.c b/CFUserNotification.c index bc848fe..805bcb8 100644 --- a/CFUserNotification.c +++ b/CFUserNotification.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUserNotification.c - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. Original Author: Doug Davidson Responsibility: Kevin Perry */ @@ -128,7 +128,7 @@ static const CFRuntimeClass __CFUserNotificationClass = { __CFUserNotificationCopyDescription }; -__private_extern__ void __CFUserNotificationInitialize(void) { +CF_PRIVATE void __CFUserNotificationInitialize(void) { __kCFUserNotificationTypeID = _CFRuntimeRegisterClass(&__CFUserNotificationClass); } @@ -257,12 +257,17 @@ static SInt32 _CFUserNotificationSendRequest(CFAllocatorRef allocator, CFStringR return retval; } +static SInt32 _getNextToken() { + static uint16_t tokenCounter = 0; + SInt32 token = ((getpid() << 16) | (tokenCounter++)); + return token; +} + CFUserNotificationRef CFUserNotificationCreate(CFAllocatorRef allocator, CFTimeInterval timeout, CFOptionFlags flags, SInt32 *error, CFDictionaryRef dictionary) { CHECK_FOR_FORK(); CFUserNotificationRef userNotification = NULL; SInt32 retval = ERR_SUCCESS; - static uint16_t tokenCounter = 0; - SInt32 token = ((getpid() << 16) | (tokenCounter++)); + SInt32 token = _getNextToken(); CFStringRef sessionID = (dictionary ? CFDictionaryGetValue(dictionary, kCFUserNotificationSessionIDKey) : NULL); mach_port_t replyPort = MACH_PORT_NULL; @@ -412,7 +417,6 @@ CFRunLoopSourceRef CFUserNotificationCreateRunLoopSource(CFAllocatorRef allocato SInt32 CFUserNotificationDisplayNotice(CFTimeInterval timeout, CFOptionFlags flags, CFURLRef iconURL, CFURLRef soundURL, CFURLRef localizationURL, CFStringRef alertHeader, CFStringRef alertMessage, CFStringRef defaultButtonTitle) { CHECK_FOR_FORK(); - CFUserNotificationRef userNotification; SInt32 retval = ERR_SUCCESS; CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (iconURL) CFDictionaryAddValue(dict, kCFUserNotificationIconURLKey, iconURL); @@ -421,8 +425,10 @@ SInt32 CFUserNotificationDisplayNotice(CFTimeInterval timeout, CFOptionFlags fla if (alertHeader) CFDictionaryAddValue(dict, kCFUserNotificationAlertHeaderKey, alertHeader); if (alertMessage) CFDictionaryAddValue(dict, kCFUserNotificationAlertMessageKey, alertMessage); if (defaultButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationDefaultButtonTitleKey, defaultButtonTitle); - userNotification = CFUserNotificationCreate(kCFAllocatorSystemDefault, timeout, flags, &retval, dict); - if (userNotification) CFRelease(userNotification); + retval = _CFUserNotificationSendRequest(__CFGetDefaultAllocator(), NULL, MACH_PORT_NULL, _getNextToken(), timeout, flags, dict); + if (ERR_SUCCESS != retval) { + CFUserNotificationLog(alertHeader, alertMessage); + } CFRelease(dict); return retval; } diff --git a/CFUserNotification.h b/CFUserNotification.h index a3e4406..6699c3a 100644 --- a/CFUserNotification.h +++ b/CFUserNotification.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUserNotification.h - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFUSERNOTIFICATION__) diff --git a/CFUtilities.c b/CFUtilities.c index b14becc..d3877b3 100644 --- a/CFUtilities.c +++ b/CFUtilities.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFUtilities.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ @@ -75,6 +75,7 @@ #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD #include #include +#include #endif /* Comparator is passed the address of the values. */ @@ -104,7 +105,7 @@ } */ -__private_extern__ CFIndex CFBSearch(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { +CF_PRIVATE CFIndex CFBSearch(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { const char *ptr = (const char *)list; while (0 < count) { CFIndex half = count / 2; @@ -144,7 +145,7 @@ CFHashCode CFHashBytes(uint8_t *bytes, CFIndex length) { #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI -__private_extern__ uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start) { +CF_PRIVATE uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start) { vm_map_t task = mach_task_self(); mach_vm_address_t address = start; for (;;) { @@ -170,7 +171,7 @@ __private_extern__ uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start) { return 0; } -__private_extern__ void __CFDumpAllPointerLocations(uintptr_t ptr) { +CF_PRIVATE void __CFDumpAllPointerLocations(uintptr_t ptr) { uintptr_t addr = 0; do { addr = __CFFindPointer(ptr, sizeof(void *) + addr); @@ -195,7 +196,7 @@ static unsigned __stdcall __CFWinThreadFunc(void *arg) { } #endif -__private_extern__ void *__CFStartSimpleThread(void *func, void *arg) { +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; @@ -249,24 +250,34 @@ static CFStringRef _CFCopyLocalizedVersionKey(CFBundleRef *bundlePtr, CFStringRe static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) { CFPropertyListRef plist = NULL; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI CFDataRef data; CFURLRef url; url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, path, kCFURLPOSIXPathStyle, false); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" if (url && CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, url, &data, NULL, NULL, NULL)) { +#pragma GCC diagnostic pop plist = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListMutableContainers, NULL); CFRelease(data); } if (url) CFRelease(url); if (plist) { +#if DEPLOYMENT_TARGET_EMBEDDED_MINI + CFStringRef fullVersion, vers, versExtra, build; + CFStringRef versionString = CFRetain(_kCFSystemVersionProductVersionStringKey); + CFStringRef buildString = CFRetain(_kCFSystemVersionBuildStringKey); + CFStringRef fullVersionString = CFRetain(CFSTR("FullVersionString")); +#else CFBundleRef locBundle = NULL; CFStringRef fullVersion, vers, versExtra, build; CFStringRef versionString = _CFCopyLocalizedVersionKey(&locBundle, _kCFSystemVersionProductVersionStringKey); CFStringRef buildString = _CFCopyLocalizedVersionKey(&locBundle, _kCFSystemVersionBuildStringKey); CFStringRef fullVersionString = _CFCopyLocalizedVersionKey(&locBundle, CFSTR("FullVersionString")); if (locBundle) CFRelease(locBundle); +#endif // Now build the full version string if (CFEqual(fullVersionString, CFSTR("FullVersionString"))) { @@ -287,7 +298,7 @@ static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) { CFRelease(buildString); CFRelease(fullVersionString); CFRelease(fullVersion); - } + } #elif DEPLOYMENT_TARGET_WINDOWS OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); @@ -360,7 +371,7 @@ CF_EXPORT Boolean _CFExecutableLinkedOnOrAfter(CFSystemVersion version) { #if DEPLOYMENT_TARGET_MACOSX -__private_extern__ void *__CFLookupCarbonCoreFunction(const char *name) { +CF_PRIVATE void *__CFLookupCarbonCoreFunction(const char *name) { static void *image = NULL; if (NULL == image) { image = dlopen("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", RTLD_LAZY | RTLD_LOCAL); @@ -374,7 +385,7 @@ __private_extern__ void *__CFLookupCarbonCoreFunction(const char *name) { #endif #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED -__private_extern__ void *__CFLookupCoreServicesInternalFunction(const char *name) { +CF_PRIVATE void *__CFLookupCoreServicesInternalFunction(const char *name) { static void *image = NULL; if (NULL == image) { image = dlopen("/System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal", RTLD_LAZY | RTLD_LOCAL); @@ -386,11 +397,11 @@ __private_extern__ void *__CFLookupCoreServicesInternalFunction(const char *name return dyfunc; } -__private_extern__ void *__CFLookupCFNetworkFunction(const char *name) { +CF_PRIVATE void *__CFLookupCFNetworkFunction(const char *name) { static void *image = NULL; if (NULL == image) { const char *path = NULL; - if (!issetugid()) { + if (!__CFProcessIsRestricted()) { path = __CFgetenv("CFNETWORK_LIBRARY_PATH"); } if (!path) { @@ -409,13 +420,13 @@ __private_extern__ void *__CFLookupCFNetworkFunction(const char *name) { #ifndef __CFGetSessionID_defined -__private_extern__ uint32_t __CFGetSessionID(void) { +CF_PRIVATE uint32_t __CFGetSessionID(void) { return 0; } #endif -__private_extern__ CFIndex __CFActiveProcessorCount() { +CF_PRIVATE CFIndex __CFActiveProcessorCount() { int32_t pcnt; #if DEPLOYMENT_TARGET_WINDOWS SYSTEM_INFO sysInfo; @@ -441,7 +452,7 @@ __private_extern__ CFIndex __CFActiveProcessorCount() { return pcnt; } -__private_extern__ void __CFGetUGIDs(uid_t *euid, gid_t *egid) { +CF_PRIVATE void __CFGetUGIDs(uid_t *euid, gid_t *egid) { #if 1 && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI) uid_t uid; gid_t gid; @@ -569,11 +580,13 @@ static Boolean also_do_stderr() { mode_t m = sb.st_mode & S_IFMT; if (S_IFREG == m || S_IFSOCK == m) return true; if (!(S_IFIFO == m || S_IFCHR == m)) return false; // disallow any whacky stuff +#if 0 // launchd no longer repeats everything it hears // if it could be a pipe back to launchd, fail int64_t val = 0; // assumes val is not written to on error vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &val); if (val) return false; +#endif #endif return true; } @@ -585,9 +598,8 @@ static void __CFLogCString(int32_t lev, const char *message, size_t length, char char *time = NULL; char *thread = NULL; char *uid = NULL; -#if DEPLOYMENT_TARGET_WINDOWS - int bannerLen = 0; -#endif + int bannerLen; + bannerLen = 0; #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) { @@ -615,7 +627,7 @@ static void __CFLogCString(int32_t lev, const char *message, size_t length, char asprintf(&thread, "%x", GetCurrentThreadId()); #else bannerLen = asprintf(&banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), (unsigned int)pthread_self()); - asprintf(&thread, "%x", pthread_self()); + asprintf(&thread, "%lx", pthread_self()); #endif asprintf(&time, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, minute, second, ms); @@ -719,7 +731,7 @@ CF_EXPORT void _CFLogvEx(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, co } // 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 -__private_extern__ void _CFLogSimple(int32_t lev, char *format, ...) { +CF_PRIVATE void _CFLogSimple(int32_t lev, char *format, ...) { va_list args; va_start(args, format); char formattedMessage[1024]; @@ -866,7 +878,7 @@ static int32_t __CFProcessExitStatus = 0; static int __CFProcessIsKillableNotifyToken; static Boolean __CFProcessIsKillableNotifyTokenIsFigured = false; -__private_extern__ void _CFSetSuddenTerminationEnabled(Boolean isEnabled) { +CF_PRIVATE void _CFSetSuddenTerminationEnabled(Boolean isEnabled) { if (!__CFProcessIsKillableNotifyTokenIsFigured) { char *notificationName = NULL; asprintf(¬ificationName, "com.apple.isKillable.%i", getpid()); @@ -938,7 +950,7 @@ size_t _CFSuddenTerminationDisablingCount(void) { typedef void (^ThrottleTypeA)(void); // allows calls per nanoseconds typedef void (^ThrottleTypeB)(uint64_t amt); // allows amount per nanoseconds -__private_extern__ ThrottleTypeA __CFCreateThrottleTypeA(uint16_t calls, uint64_t nanoseconds) { +CF_PRIVATE ThrottleTypeA __CFCreateThrottleTypeA(uint16_t calls, uint64_t nanoseconds) { struct mach_timebase_info info; mach_timebase_info(&info); uint64_t period = nanoseconds / info.numer * info.denom; @@ -964,7 +976,7 @@ __private_extern__ ThrottleTypeA __CFCreateThrottleTypeA(uint16_t calls, uint64_ }); } -__private_extern__ ThrottleTypeB __CFCreateThrottleTypeB(uint64_t amount, uint64_t nanoseconds) { +CF_PRIVATE ThrottleTypeB __CFCreateThrottleTypeB(uint64_t amount, uint64_t nanoseconds) { struct mach_timebase_info info; mach_timebase_info(&info); uint64_t period = nanoseconds / info.numer * info.denom; @@ -1018,7 +1030,7 @@ static CFErrorRef _CFErrorWithFilePathCodeDomain(CFStringRef domain, CFIndex cod } // Caller is responsible for freeing memory. munmap() if map == true, else malloc(). -__private_extern__ Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, Boolean uncached, void **outBytes, CFIndex *outLength, CFErrorRef *errorPtr) { +CF_PRIVATE Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, Boolean uncached, void **outBytes, CFIndex *outLength, CFErrorRef *errorPtr) { void *bytes = NULL; unsigned long length; char cpath[CFMaxPathSize]; @@ -1067,7 +1079,7 @@ __private_extern__ Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, if (0LL == statBuf.st_size) { bytes = malloc(8); // don't return constant string -- it's freed! length = 0; -#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI +#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX } else if (map) { if((void *)-1 == (bytes = mmap(0, (size_t)statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0))) { int32_t savederrno = errno; @@ -1107,7 +1119,7 @@ __private_extern__ Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, } length = (unsigned long)statBuf.st_size - numBytesRemaining; } -#else +#elif DEPLOYMENT_TARGET_WINDOWS } else { bytes = malloc(statBuf.st_size); DWORD numBytesRead; diff --git a/CFUtilities.h b/CFUtilities.h new file mode 100644 index 0000000..e2080fd --- /dev/null +++ b/CFUtilities.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 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@ + */ + +/* CFUtilities.h + Copyright (c) 2005-2013, Apple Inc. All rights reserved. +*/ + +#if !defined(__COREFOUNDATION_CFUTILITIES__) +#define __COREFOUNDATION_CFUTILITIES__ 1 + +#include +#include +#include + +CF_IMPLICIT_BRIDGING_ENABLED +CF_EXTERN_C_BEGIN + +CF_EXPORT +CFURLRef CFCopyHomeDirectoryURL(void) CF_AVAILABLE_IOS(5_0); + +CF_EXTERN_C_END +CF_IMPLICIT_BRIDGING_DISABLED + +#endif /* ! __COREFOUNDATION_CFUTILITIES__ */ + diff --git a/CFVersion.c b/CFVersion.c index 8be1dbe..7b72dbc 100644 --- a/CFVersion.c +++ b/CFVersion.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,5 +25,5 @@ Copyright 2009-2011, Apple Inc. All rights reserved. Responsibility: CFLite Team */ -const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-744.12 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n"; -double kCFCoreFoundationVersionNumber = (double)744.12; +const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-855.11 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n"; +double kCFCoreFoundationVersionNumber = (double)855.11; diff --git a/CFWindowsUtilities.c b/CFWindowsUtilities.c index af1bb39..6fcd046 100644 --- a/CFWindowsUtilities.c +++ b/CFWindowsUtilities.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,7 +23,7 @@ /* CFWindowsUtilities.c - Copyright (c) 2008-2012, Apple Inc. All rights reserved. + Copyright (c) 2008-2013, Apple Inc. All rights reserved. Responsibility: Tony Parker */ diff --git a/CFXMLInputStream.c b/CFXMLInputStream.c index b3d7352..52cc6c5 100644 --- a/CFXMLInputStream.c +++ b/CFXMLInputStream.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLInputStream.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -145,7 +145,7 @@ CF_INLINE void _fillStringWithCharacters(CFMutableStringRef string, UniChar *cha } } -__private_extern__ Boolean _openInputStream(_CFXMLInputStream *stream) { +CF_PRIVATE Boolean _openInputStream(_CFXMLInputStream *stream) { if (NULL == stream->data) { return false; } else { @@ -159,7 +159,7 @@ __private_extern__ Boolean _openInputStream(_CFXMLInputStream *stream) { } } -__private_extern__ void _initializeInputStream(_CFXMLInputStream *stream, CFAllocatorRef alloc, CFURLRef dataSource, CFDataRef xmlData) { +CF_PRIVATE void _initializeInputStream(_CFXMLInputStream *stream, CFAllocatorRef alloc, CFURLRef dataSource, CFDataRef xmlData) { stream->data = xmlData ? (CFDataRef)CFRetain(xmlData) : NULL; stream->url = dataSource ? (CFURLRef)CFRetain(dataSource) : NULL; stream->encoding = kCFStringEncodingInvalidId; @@ -182,7 +182,7 @@ __private_extern__ void _initializeInputStream(_CFXMLInputStream *stream, CFAllo } -__private_extern__ void _freeInputStream(_CFXMLInputStream *stream) { +CF_PRIVATE void _freeInputStream(_CFXMLInputStream *stream) { if (stream->data) CFRelease(stream->data); if (stream->url) CFRelease(stream->url); if (stream->charBuffer) CFAllocatorDeallocate(stream->allocator, stream->charBuffer); @@ -191,26 +191,26 @@ __private_extern__ void _freeInputStream(_CFXMLInputStream *stream) { CFRelease(stream->allocator); } -__private_extern__ CFStringEncoding _inputStreamGetEncoding(_CFXMLInputStream *stream) { +CF_PRIVATE CFStringEncoding _inputStreamGetEncoding(_CFXMLInputStream *stream) { return stream->encoding; } -__private_extern__ CFIndex _inputStreamCurrentLocation(_CFXMLInputStream *stream) { +CF_PRIVATE CFIndex _inputStreamCurrentLocation(_CFXMLInputStream *stream) { return stream->charIndex; } -__private_extern__ CFIndex _inputStreamCurrentLine(_CFXMLInputStream *stream) { +CF_PRIVATE CFIndex _inputStreamCurrentLine(_CFXMLInputStream *stream) { return stream->lineNum; } -__private_extern__ Boolean _inputStreamAtEOF(_CFXMLInputStream *stream) { +CF_PRIVATE Boolean _inputStreamAtEOF(_CFXMLInputStream *stream) { if (!(stream->flags & STREAM_OPEN)) return false; if (stream->currentChar) return false; if (stream->currentByte - CFDataGetBytePtr(stream->data) < CFDataGetLength(stream->data)) return false; return true; } -__private_extern__ Boolean _inputStreamComposingErrorOccurred(_CFXMLInputStream *stream) { +CF_PRIVATE Boolean _inputStreamComposingErrorOccurred(_CFXMLInputStream *stream) { return stream->flags & ENCODING_COMPOSITION_ERROR; } @@ -428,15 +428,15 @@ CF_INLINE Boolean getCharacter(_CFXMLInputStream *stream, UniChar *ch, Boolean a return true; } -__private_extern__ Boolean _inputStreamPeekCharacter(_CFXMLInputStream *stream, UniChar *ch) { +CF_PRIVATE Boolean _inputStreamPeekCharacter(_CFXMLInputStream *stream, UniChar *ch) { return getCharacter(stream, ch, false); } -__private_extern__ Boolean _inputStreamGetCharacter(_CFXMLInputStream *stream, UniChar *ch) { +CF_PRIVATE Boolean _inputStreamGetCharacter(_CFXMLInputStream *stream, UniChar *ch) { return getCharacter(stream, ch, true); } -__private_extern__ Boolean _inputStreamReturnCharacter(_CFXMLInputStream *stream, UniChar ch) { +CF_PRIVATE Boolean _inputStreamReturnCharacter(_CFXMLInputStream *stream, UniChar ch) { Boolean decrementLineNum = false; if (ch == '\n') { decrementLineNum = true; @@ -514,17 +514,17 @@ static UniChar *dropMark(_CFXMLInputStream *stream) { } -__private_extern__ void _inputStreamSetMark(_CFXMLInputStream *stream) { +CF_PRIVATE void _inputStreamSetMark(_CFXMLInputStream *stream) { CFAssert(stream->mark == NULL, __kCFLogAssertion, "CF internal error: parser input stream malformed"); stream->mark = dropMark(stream); } -__private_extern__ void _inputStreamClearMark(_CFXMLInputStream *stream) { +CF_PRIVATE void _inputStreamClearMark(_CFXMLInputStream *stream) { CFAssert(stream->mark != NULL, __kCFLogAssertion, "CF internal error: parser input stream malformed"); stream->mark = NULL; } -__private_extern__ void _inputStreamGetCharactersFromMark(_CFXMLInputStream *stream, CFMutableStringRef string) { +CF_PRIVATE void _inputStreamGetCharactersFromMark(_CFXMLInputStream *stream, CFMutableStringRef string) { UniChar *end = stream->currentChar ? stream->currentChar : stream->charBuffer + stream->bufferLength; CFIndex numChars = end - stream->mark; CFAssert(stream->mark, __kCFLogAssertion, "CF internal error: malformed XML input stream"); @@ -559,7 +559,7 @@ static void restoreToMark(_CFXMLInputStream *stream, UniChar *mark) { } } -__private_extern__ void _inputStreamBackUpToMark(_CFXMLInputStream *stream) { +CF_PRIVATE void _inputStreamBackUpToMark(_CFXMLInputStream *stream) { CFAssert(stream->mark != NULL || stream->charBuffer == NULL, __kCFLogAssertion, "CF internal error: malformed XML input stream"); restoreToMark(stream, stream->mark); } @@ -568,7 +568,7 @@ CF_INLINE Boolean isWhitespaceChar(UniChar ch) { return (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t'); } -__private_extern__ CFIndex _inputStreamSkipWhitespace(_CFXMLInputStream *stream, CFMutableStringRef str) { +CF_PRIVATE CFIndex _inputStreamSkipWhitespace(_CFXMLInputStream *stream, CFMutableStringRef str) { UniChar ch; CFIndex len = 0; if (str) { @@ -588,7 +588,7 @@ __private_extern__ CFIndex _inputStreamSkipWhitespace(_CFXMLInputStream *stream, } // false return means EOF was encountered without finding scanChars -__private_extern__ Boolean _inputStreamScanToCharacters(_CFXMLInputStream *stream, const UniChar *scanChars, CFIndex numChars, CFMutableStringRef str) { +CF_PRIVATE Boolean _inputStreamScanToCharacters(_CFXMLInputStream *stream, const UniChar *scanChars, CFIndex numChars, CFMutableStringRef str) { Boolean done = false; CFIndex firstRepeatIndex = -1; CFIndex len = 0; @@ -636,7 +636,7 @@ __private_extern__ Boolean _inputStreamScanToCharacters(_CFXMLInputStream *strea return true; } -__private_extern__ Boolean _inputStreamMatchString(_CFXMLInputStream *stream, const UniChar *stringToMatch, CFIndex length) { +CF_PRIVATE Boolean _inputStreamMatchString(_CFXMLInputStream *stream, const UniChar *stringToMatch, CFIndex length) { const UniChar *end = stringToMatch+length; const UniChar *sPtr=stringToMatch; stream->parserMark = dropMark(stream); @@ -656,7 +656,7 @@ __private_extern__ Boolean _inputStreamMatchString(_CFXMLInputStream *stream, co } } -__private_extern__ Boolean _inputStreamScanQuotedString(_CFXMLInputStream *stream, CFMutableStringRef str) { +CF_PRIVATE Boolean _inputStreamScanQuotedString(_CFXMLInputStream *stream, CFMutableStringRef str) { UniChar ch; if (!_inputStreamPeekCharacter(stream, &ch)) return false; if (ch != '\'' && ch != '\"') return false; @@ -685,7 +685,7 @@ __private_extern__ Boolean _inputStreamScanQuotedString(_CFXMLInputStream *strea CombiningChar == kCFUniCharNonBaseCharacterSet Extender - complex, and not represented by a uniform character set. */ -__private_extern__ Boolean _inputStreamScanXMLName(_CFXMLInputStream *stream, Boolean isNMToken, CFStringRef *str) { +CF_PRIVATE Boolean _inputStreamScanXMLName(_CFXMLInputStream *stream, Boolean isNMToken, CFStringRef *str) { UniChar ch; Boolean success = true; stream->parserMark = dropMark(stream); diff --git a/CFXMLInputStream.h b/CFXMLInputStream.h index 0eadcee..9fb4532 100644 --- a/CFXMLInputStream.h +++ b/CFXMLInputStream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLInputStream.h - Copyright (c) 2000-2012, Apple Inc. All rights reserved. + Copyright (c) 2000-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_CFXMLINPUTSTREAM__) diff --git a/CFXMLNode.c b/CFXMLNode.c index 10700d5..84653d2 100644 --- a/CFXMLNode.c +++ b/CFXMLNode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLNode.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -139,7 +139,7 @@ static CFHashCode __CFXMLNodeHash(CFTypeRef cf) { static CFStringRef __CFXMLNodeCopyDescription(CFTypeRef cf) { struct __CFXMLNode *node = (struct __CFXMLNode *)cf; - return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFXMLNode %p>{typeID = %d, string = %@}"), cf, node->dataTypeID, node->dataString); + return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFXMLNode %p>{typeID = %ld, string = %@}"), cf, (unsigned long)node->dataTypeID, node->dataString); } static void __CFXMLNodeDeallocate(CFTypeRef cf) { diff --git a/CFXMLNode.h b/CFXMLNode.h index 8be66f4..1717172 100644 --- a/CFXMLNode.h +++ b/CFXMLNode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLNode.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, 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. */ diff --git a/CFXMLParser.c b/CFXMLParser.c index 16dda04..108f59e 100644 --- a/CFXMLParser.c +++ b/CFXMLParser.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLParser.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ diff --git a/CFXMLParser.h b/CFXMLParser.h index aa5b54d..f151434 100644 --- a/CFXMLParser.h +++ b/CFXMLParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLParser.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, 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. */ diff --git a/CFXMLPreferencesDomain.c b/CFXMLPreferencesDomain.c index 03a9b0d..a87cbbe 100644 --- a/CFXMLPreferencesDomain.c +++ b/CFXMLPreferencesDomain.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLPreferencesDomain.c - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -62,7 +62,7 @@ static void getXMLKeysAndValues(CFAllocatorRef alloc, CFTypeRef context, void *x static CFDictionaryRef copyXMLDomainDictionary(CFTypeRef context, void *domain); static void setXMLDomainIsWorldReadable(CFTypeRef context, void *domain, Boolean isWorldReadable); -__private_extern__ const _CFPreferencesDomainCallBacks __kCFXMLPropertyListDomainCallBacks = {createXMLDomain, freeXMLDomain, fetchXMLValue, writeXMLValue, synchronizeXMLDomain, getXMLKeysAndValues, copyXMLDomainDictionary, setXMLDomainIsWorldReadable}; +CF_PRIVATE const _CFPreferencesDomainCallBacks __kCFXMLPropertyListDomainCallBacks = {createXMLDomain, freeXMLDomain, fetchXMLValue, writeXMLValue, synchronizeXMLDomain, getXMLKeysAndValues, copyXMLDomainDictionary, setXMLDomainIsWorldReadable}; // Directly ripped from Foundation.... static void __CFMilliSleep(uint32_t msecs) { diff --git a/CFXMLTree.c b/CFXMLTree.c index 0c704a3..9af9cc9 100644 --- a/CFXMLTree.c +++ b/CFXMLTree.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CFXMLTree.c - Copyright (c) 1999-2012, Apple Inc. All rights reserved. + Copyright (c) 1999-2013, Apple Inc. All rights reserved. Responsibility: David Smith */ @@ -55,7 +55,7 @@ CFXMLNodeRef CFXMLTreeGetNode(CFXMLTreeRef xmlNode) { } // We will probably ultimately want to export this under some public API name -__private_extern__ Boolean CFXMLTreeEqual(CFXMLTreeRef xmlTree1, CFXMLTreeRef xmlTree2) { +CF_PRIVATE Boolean CFXMLTreeEqual(CFXMLTreeRef xmlTree1, CFXMLTreeRef xmlTree2) { CFXMLNodeRef node1, node2; CFXMLTreeRef child1, child2; if (CFTreeGetChildCount(xmlTree1) != CFTreeGetChildCount(xmlTree2)) return false; @@ -101,7 +101,7 @@ static void _CFAppendXML(CFMutableStringRef str, CFXMLTreeRef tree) { _CFAppendXMLEpilog(str, tree); } -__private_extern__ void appendQuotedString(CFMutableStringRef str, CFStringRef strToQuote) { +CF_PRIVATE void appendQuotedString(CFMutableStringRef str, CFStringRef strToQuote) { char quoteChar = CFStringFindWithOptions(strToQuote, CFSTR("\""), CFRangeMake(0, CFStringGetLength(strToQuote)), 0, NULL) ? '\'' : '\"'; CFStringAppendFormat(str, NULL, CFSTR("%c%@%c"), quoteChar, strToQuote, quoteChar); } @@ -158,7 +158,7 @@ static void _CFAppendXMLProlog(CFMutableStringRef str, const CFXMLTreeRef tree) if (data->dataString) { CFStringAppendFormat(str, NULL, CFSTR(""), CFXMLNodeGetString(CFXMLTreeGetNode(tree)), data->dataString); } else { - CFStringAppendFormat(str, NULL, CFSTR("")); + CFStringAppendFormat(str, NULL, CFSTR(""), CFXMLNodeGetString(CFXMLTreeGetNode(tree))); } break; } diff --git a/CoreFoundation.h b/CoreFoundation.h index 100e4e5..ead85b0 100644 --- a/CoreFoundation.h +++ b/CoreFoundation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CoreFoundation.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !defined(__COREFOUNDATION_COREFOUNDATION__) diff --git a/CoreFoundation_Prefix.h b/CoreFoundation_Prefix.h index f353a9a..e40a7f3 100644 --- a/CoreFoundation_Prefix.h +++ b/CoreFoundation_Prefix.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* CoreFoundation_Prefix.h - Copyright (c) 2005-2012, Apple Inc. All rights reserved. + Copyright (c) 2005-2013, Apple Inc. All rights reserved. */ @@ -61,8 +61,7 @@ typedef char * Class; #import #endif -/* This macro creates 3 helper functions which are useful in dealing with libdispatch: - * __ PREFIX SyncDispatchIsSafe -- returns bool indicating whether calling dispatch_sync() would be safe from self-deadlock +/* This macro creates some helper functions which are useful in dealing with libdispatch: * __ PREFIX Queue -- manages and returns a singleton serial queue * * Use the macro like this: @@ -70,11 +69,6 @@ typedef char * Class; */ #define DISPATCH_HELPER_FUNCTIONS(PREFIX, QNAME) \ -static Boolean __ ## PREFIX ## SyncDispatchIsSafe(dispatch_queue_t Q) { \ - dispatch_queue_t C = dispatch_get_current_queue(); \ - return (!C || Q != C) ? true : false; \ -} \ - \ static dispatch_queue_t __ ## PREFIX ## Queue(void) { \ static volatile dispatch_queue_t __ ## PREFIX ## dq = NULL; \ if (!__ ## PREFIX ## dq) { \ @@ -112,7 +106,7 @@ typedef int boolean_t; #if DEPLOYMENT_TARGET_LINUX -#define __private_extern__ +#define CF_PRIVATE #define __strong #define __weak @@ -123,9 +117,34 @@ typedef int boolean_t; #define strncasecmp_l(a, b, c, d) strncasecmp(a, b, c) #define fprintf_l(a,locale,b,...) fprintf(a, b, __VA_ARGS__) - -#define strlcat(a,b,c) strncat(a,b,c) -#define strlcpy(a,b,c) strncpy(a,b,c) + +#include + +CF_INLINE size_t +strlcpy(char * dst, const char * src, size_t maxlen) { + const size_t srclen = strlen(src); + if (srclen < maxlen) { + memcpy(dst, src, srclen+1); + } else if (maxlen != 0) { + memcpy(dst, src, maxlen-1); + dst[maxlen-1] = '\0'; + } + return srclen; +} + +CF_INLINE size_t +strlcat(char * dst, const char * src, size_t maxlen) { + const size_t srclen = strlen(src); + const size_t dstlen = strnlen(dst, maxlen); + if (dstlen == maxlen) return maxlen+srclen; + if (srclen < maxlen-dstlen) { + memcpy(dst+dstlen, src, srclen+1); + } else { + memcpy(dst+dstlen, src, maxlen-dstlen-1); + dst[maxlen-1] = '\0'; + } + return dstlen + srclen; +} #define issetugid() 0 @@ -133,7 +152,8 @@ typedef int boolean_t; bool OSAtomicCompareAndSwapPtr(void *oldp, void *newp, void *volatile *dst); bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst); bool OSAtomicCompareAndSwapPtrBarrier(void *oldp, void *newp, void *volatile *dst); - +bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ); + int32_t OSAtomicDecrement32Barrier(volatile int32_t *dst); int32_t OSAtomicIncrement32Barrier(volatile int32_t *dst); int32_t OSAtomicIncrement32(volatile int32_t *theValue); @@ -149,6 +169,11 @@ void OSMemoryBarrier(); CF_INLINE size_t malloc_size(void *memblock) { return malloc_usable_size(memblock); } + +// substitute for dispatch_once +typedef pthread_once_t dispatch_once_t; +typedef void (^dispatch_block_t)(void); +void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block); #endif @@ -178,7 +203,7 @@ CF_INLINE size_t malloc_size(void *memblock) { #define mode_t uint16_t // This works because things aren't actually exported from the DLL unless they have a __declspec(dllexport) on them... so extern by itself is closest to __private_extern__ on Mac OS -#define __private_extern__ extern +#define CF_PRIVATE extern #define __builtin_expect(P1,P2) P1 @@ -239,6 +264,8 @@ typedef int gid_t; #define getuid() 0 #define getegid() 0 +#define scalbn(A, B) _scalb(A, B) + #define fsync(a) _commit(a) #define malloc_create_zone(a,b) 123 #define malloc_set_zone_name(zone,name) @@ -278,14 +305,38 @@ CF_INLINE long long llabs(long long v) { #define strtoul_l(a,b,c,locale) strtoul(a,b,c) #define strtol_l(a,b,c,locale) strtol(a,b,c) #define strtoll_l(a,b,c,locale) _strtoi64(a,b,c) +#define strncasecmp(a, b, c) _strnicmp(a, b, c) #define strncasecmp_l(a, b, c, d) _strnicmp(a, b, c) #define snprintf _snprintf #define fprintf_l(a,locale,b,...) fprintf(a, b, __VA_ARGS__) -#define strlcat(a,b,c) strncat(a,b,c) -#define strlcpy(a,b,c) strncpy(a,b,c) - +CF_INLINE size_t +strlcpy(char * dst, const char * src, size_t maxlen) { + const size_t srclen = strlen(src); + if (srclen < maxlen) { + memcpy(dst, src, srclen+1); + } else if (maxlen != 0) { + memcpy(dst, src, maxlen-1); + dst[maxlen-1] = '\0'; + } + return srclen; +} + +CF_INLINE size_t +strlcat(char * dst, const char * src, size_t maxlen) { + const size_t srclen = strlen(src); + const size_t dstlen = strnlen(dst, maxlen); + if (dstlen == maxlen) return maxlen+srclen; + if (srclen < maxlen-dstlen) { + memcpy(dst+dstlen, src, srclen+1); + } else { + memcpy(dst+dstlen, src, maxlen-dstlen-1); + dst[maxlen-1] = '\0'; + } + return dstlen + srclen; +} + #define sleep(x) Sleep(1000*x) #define issetugid() 0 @@ -322,6 +373,10 @@ CF_EXPORT int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *_ #endif +#if !defined(CF_PRIVATE) +#define CF_PRIVATE __attribute__((__visibility__("hidden"))) +#endif + #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_WINDOWS #include @@ -341,7 +396,7 @@ CF_INLINE int popcountll(long long x) { return count; } -__private_extern__ int asprintf(char **ret, const char *format, ...); +CF_PRIVATE int asprintf(char **ret, const char *format, ...); #endif diff --git a/ForFoundationOnly.h b/ForFoundationOnly.h index 2a304ea..14711b0 100644 --- a/ForFoundationOnly.h +++ b/ForFoundationOnly.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,7 +22,7 @@ */ /* ForFoundationOnly.h - Copyright (c) 1998-2012, Apple Inc. All rights reserved. + Copyright (c) 1998-2013, Apple Inc. All rights reserved. */ #if !CF_BUILDING_CF && !NSBUILDINGFOUNDATION @@ -77,14 +77,9 @@ CF_EXPORT const CFStringRef _kCFBundleResolvedPathKey; CF_EXPORT const CFStringRef _kCFBundlePrincipalClassKey; #if __BLOCKS__ -CF_EXPORT CFArrayRef _CFFindBundleResources(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef subDirName, CFArrayRef searchLanguages, CFStringRef resName, CFArrayRef resTypes, CFIndex limit, Boolean (^predicate)(CFStringRef filename, Boolean *stop), UInt8 version); -// new look up algorithm is in place (look for CFBUNDLE_NEWLOOKUP) 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)); #endif -CF_EXPORT UInt8 _CFBundleLayoutVersion(CFBundleRef bundle); - -CF_EXPORT CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt8 *version); CF_EXPORT CFArrayRef _CFBundleGetLanguageSearchList(CFBundleRef bundle); CF_EXPORT Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error); @@ -177,6 +172,38 @@ CF_EXTERN_C_END #include +#define NSSTRING_BOUNDSERROR \ + [NSException raise:NSRangeException format:@"%@: Range or index out of bounds", __CFExceptionProem((id)self, _cmd)] + +#define NSSTRING_RANGEERROR(range, len) \ + [NSException raise:NSRangeException format:@"%@: Range {%lu, %lu} out of bounds; string length %lu", __CFExceptionProem((id)self, _cmd), (unsigned long)range.location, (unsigned long)range.length, (unsigned long)len] + +#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 +#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); \ + } \ +} + +#define NSSTRING_ILLEGALREQUESTERROR \ + [NSException raise:NSInvalidArgumentException format:@"Can't call %s in %@", sel_getName(_cmd), object_getClass((id)self)] + +#define NSSTRING_INVALIDMUTATIONERROR \ + [NSException raise:NSInvalidArgumentException format:@"Attempt to mutate immutable object with %s", sel_getName(_cmd)] + +#define NSSTRING_NULLCSTRINGERROR \ + [NSException raise:NSInvalidArgumentException format:@"%@: NULL cString", __CFExceptionProem((id)self, _cmd)] + +#define NSSTRING_NILSTRINGERROR \ + [NSException raise:NSInvalidArgumentException format:@"%@: nil argument", __CFExceptionProem((id)self, _cmd)] + + CF_EXTERN_C_BEGIN /* Create a byte stream from a CFString backing. Can convert a string piece at a @@ -285,12 +312,10 @@ CF_INLINE Boolean __CFIsWhitespace(UniChar theChar) { /* Same as CFStringGetCharacterFromInlineBuffer() but returns 0xFFFF on out of bounds access */ CF_INLINE UniChar __CFStringGetCharacterFromInlineBufferAux(CFStringInlineBuffer *buf, CFIndex idx) { - if (buf->directBuffer) { - if (idx < 0 || idx >= buf->rangeToBuffer.length) return 0xFFFF; - return buf->directBuffer[idx + buf->rangeToBuffer.location]; - } + if (idx < 0 || idx >= buf->rangeToBuffer.length) return 0xFFFF; + if (buf->directUniCharBuffer) return buf->directUniCharBuffer[idx + buf->rangeToBuffer.location]; + if (buf->directCStringBuffer) return (UniChar)(buf->directCStringBuffer[idx + buf->rangeToBuffer.location]); if (idx >= buf->bufferedRangeEnd || idx < buf->bufferedRangeStart) { - if (idx < 0 || idx >= buf->rangeToBuffer.length) return 0xFFFF; if ((buf->bufferedRangeStart = idx - 4) < 0) buf->bufferedRangeStart = 0; buf->bufferedRangeEnd = buf->bufferedRangeStart + __kCFStringInlineBufferLength; if (buf->bufferedRangeEnd > buf->rangeToBuffer.length) buf->bufferedRangeEnd = buf->rangeToBuffer.length; @@ -302,7 +327,8 @@ CF_INLINE UniChar __CFStringGetCharacterFromInlineBufferAux(CFStringInlineBuffer /* Same as CFStringGetCharacterFromInlineBuffer(), but without the bounds checking (will return garbage or crash) */ CF_INLINE UniChar __CFStringGetCharacterFromInlineBufferQuick(CFStringInlineBuffer *buf, CFIndex idx) { - if (buf->directBuffer) return buf->directBuffer[idx + buf->rangeToBuffer.location]; + if (buf->directUniCharBuffer) return buf->directUniCharBuffer[idx + buf->rangeToBuffer.location]; + if (buf->directCStringBuffer) return (UniChar)(buf->directCStringBuffer[idx + buf->rangeToBuffer.location]); if (idx >= buf->bufferedRangeEnd || idx < buf->bufferedRangeStart) { if ((buf->bufferedRangeStart = idx - 4) < 0) buf->bufferedRangeStart = 0; buf->bufferedRangeEnd = buf->bufferedRangeStart + __kCFStringInlineBufferLength; @@ -499,9 +525,9 @@ CF_EXPORT CFStringRef _CFErrorCreateLocalizedRecoverySuggestion(CFErrorRef err); CF_EXPORT CFStringRef _CFErrorCreateDebugDescription(CFErrorRef err); CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator); -CF_EXPORT void _CFURLInitWithString(CFURLRef url, CFStringRef string, CFURLRef baseURL); -CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path); -CF_EXPORT Boolean _CFStringIsLegalURLString(CFStringRef string); +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); diff --git a/Info.plist b/Info.plist index 944c11f..6cca5eb 100644 --- a/Info.plist +++ b/Info.plist @@ -15,18 +15,10 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 6.8 + 6.9 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) - CarbonLazyValues - - CodeFragmentManager - - CoreFoundation - CFMPriv_CoreFoundation - - diff --git a/Makefile b/Makefile index 7093efa..1052254 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,17 @@ include MakefileVersion -MIN_MACOSX_VERSION=10.8 -MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_8 +MIN_MACOSX_VERSION=10.9 +MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_9 OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c)) OBJECTS += CFBasicHash.o HFILES = $(wildcard *.h) INTERMEDIATE_HFILES = $(addprefix $(OBJBASE)/CoreFoundation/,$(HFILES)) -PUBLIC_HEADERS=CFArray.h CFBag.h CFBase.h CFBinaryHeap.h CFBitVector.h CFBundle.h CFByteOrder.h CFCalendar.h CFCharacterSet.h CFData.h CFDate.h CFDateFormatter.h CFDictionary.h CFError.h CFLocale.h CFMessagePort.h CFNumber.h CFNumberFormatter.h CFPlugIn.h CFPlugInCOM.h CFPreferences.h CFPropertyList.h CFRunLoop.h CFSet.h CFSocket.h CFStream.h CFString.h CFStringEncodingExt.h CFTimeZone.h CFTree.h CFURL.h CFURLAccess.h CFUUID.h CFUserNotification.h CFXMLNode.h CFXMLParser.h CoreFoundation.h +PUBLIC_HEADERS=CFArray.h CFBag.h CFBase.h CFBinaryHeap.h CFBitVector.h CFBundle.h CFByteOrder.h CFCalendar.h CFCharacterSet.h CFData.h CFDate.h CFDateFormatter.h CFDictionary.h CFError.h CFLocale.h CFMessagePort.h CFNumber.h CFNumberFormatter.h CFPlugIn.h CFPlugInCOM.h CFPreferences.h CFPropertyList.h CFRunLoop.h CFSet.h CFSocket.h CFStream.h CFString.h CFStringEncodingExt.h CFTimeZone.h CFTree.h CFURL.h CFURLAccess.h CFUUID.h CFUserNotification.h CFXMLNode.h CFXMLParser.h CFAvailability.h CFUtilities.h CoreFoundation.h -PRIVATE_HEADERS=CFBundlePriv.h CFCharacterSetPriv.h CFError_Private.h CFLogUtilities.h CFPriv.h CFRuntime.h CFStorage.h CFStreamAbstract.h CFStreamPriv.h CFStreamInternal.h CFStringDefaultEncoding.h CFStringEncodingConverter.h CFStringEncodingConverterExt.h CFUniChar.h CFUnicodeDecomposition.h CFUnicodePrecomposition.h ForFoundationOnly.h CFBurstTrie.h +PRIVATE_HEADERS=CFBundlePriv.h CFCharacterSetPriv.h CFError_Private.h CFLogUtilities.h CFPriv.h CFRuntime.h CFStorage.h CFStreamAbstract.h CFStreamPriv.h CFStreamInternal.h CFStringDefaultEncoding.h CFStringEncodingConverter.h CFStringEncodingConverterExt.h CFUniChar.h CFUnicodeDecomposition.h CFUnicodePrecomposition.h ForFoundationOnly.h CFBurstTrie.h CFICULogging.h MACHINE_TYPE := $(shell uname -p) unicode_data_file_name = $(if $(or $(findstring i386,$(1)),$(findstring i686,$(1)),$(findstring x86_64,$(1))),CFUnicodeData-L.mapping,CFUnicodeData-B.mapping) diff --git a/MakefileLinux b/MakefileLinux index 19e6ee7..ec1f997 100644 --- a/MakefileLinux +++ b/MakefileLinux @@ -1,17 +1,17 @@ include MakefileVersion -MIN_MACOSX_VERSION=10.7 -MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_7 +MIN_MACOSX_VERSION=10.9 +MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_9 OBJECTS = CFCharacterSet.o CFPreferences.o CFApplicationPreferences.o CFXMLPreferencesDomain.o CFStringEncodingConverter.o CFUniChar.o CFArray.o CFOldStylePList.o CFPropertyList.o CFStringEncodingDatabase.o CFUnicodeDecomposition.o CFBag.o CFData.o CFStringEncodings.o CFUnicodePrecomposition.o CFBase.o CFDate.o CFNumber.o CFRuntime.o CFStringScanner.o CFBinaryHeap.o CFDateFormatter.o CFNumberFormatter.o CFSet.o CFStringUtilities.o CFUtilities.o CFBinaryPList.o CFDictionary.o CFPlatform.o CFSystemDirectories.o CFVersion.o CFBitVector.o CFError.o CFPlatformConverters.o CFTimeZone.o CFBuiltinConverters.o CFFileUtilities.o CFSortFunctions.o CFTree.o CFICUConverters.o CFURL.o CFLocale.o CFURLAccess.o CFCalendar.o CFLocaleIdentifier.o CFString.o CFUUID.o CFStorage.o CFLocaleKeys.o OBJECTS += CFBasicHash.o HFILES = $(wildcard *.h) INTERMEDIATE_HFILES = $(addprefix $(OBJBASE)/CoreFoundation/,$(HFILES)) -PUBLIC_HEADERS=CFArray.h CFBag.h CFBase.h CFBinaryHeap.h CFBitVector.h CFByteOrder.h CFCalendar.h CFCharacterSet.h CFData.h CFDate.h CFDateFormatter.h CFDictionary.h CFError.h CFLocale.h CFMachPort.h CFNumber.h CFNumberFormatter.h CFPreferences.h CFPropertyList.h CFSet.h CFString.h CFStringEncodingExt.h CFTimeZone.h CFTree.h CFURL.h CFURLAccess.h CFUUID.h CoreFoundation.h TargetConditionals.h +PUBLIC_HEADERS=CFArray.h CFBag.h CFBase.h CFBinaryHeap.h CFBitVector.h CFByteOrder.h CFCalendar.h CFCharacterSet.h CFData.h CFDate.h CFDateFormatter.h CFDictionary.h CFError.h CFLocale.h CFMachPort.h CFNumber.h CFNumberFormatter.h CFPreferences.h CFPropertyList.h CFSet.h CFString.h CFStringEncodingExt.h CFTimeZone.h CFTree.h CFURL.h CFURLAccess.h CFUUID.h CFAvailability.h CFUtilities.h CoreFoundation.h TargetConditionals.h -PRIVATE_HEADERS= CFCharacterSetPriv.h CFError_Private.h CFLogUtilities.h CFPriv.h CFRuntime.h CFStorage.h CFStringDefaultEncoding.h CFStringEncodingConverter.h CFStringEncodingConverterExt.h CFUniChar.h CFUnicodeDecomposition.h CFUnicodePrecomposition.h ForFoundationOnly.h +PRIVATE_HEADERS= CFCharacterSetPriv.h CFError_Private.h CFLogUtilities.h CFPriv.h CFRuntime.h CFStorage.h CFStringDefaultEncoding.h CFStringEncodingConverter.h CFStringEncodingConverterExt.h CFUniChar.h CFUnicodeDecomposition.h CFUnicodePrecomposition.h ForFoundationOnly.h CFICULogging.h RESOURCES = CFCharacterSetBitmaps.bitmap CFUnicodeData-L.mapping CFUnicodeData-B.mapping diff --git a/MakefileVersion b/MakefileVersion index 261dcb6..5e02d2e 100644 --- a/MakefileVersion +++ b/MakefileVersion @@ -1 +1 @@ -VERSION=744.12 +VERSION=855.11 diff --git a/SymbolAliases b/SymbolAliases index 84b9421..6380cdb 100644 --- a/SymbolAliases +++ b/SymbolAliases @@ -93,4 +93,6 @@ _kCFNumberFormatterSecondaryGroupingSizeKey _kCFNumberFormatterSecondaryGrouping _kCFNumberFormatterUseGroupingSeparatorKey _kCFNumberFormatterUseGroupingSeparator _kCFNumberFormatterUseSignificantDigitsKey _kCFNumberFormatterUseSignificantDigits _kCFNumberFormatterZeroSymbolKey _kCFNumberFormatterZeroSymbol +_kCFNumberFormatterUsesCharacterDirectionKey _kCFNumberFormatterUsesCharacterDirection +_kCFDateFormatterUsesCharacterDirectionKey _kCFDateFormatterUsesCharacterDirection _kCFDateFormatterCalendarIdentifierKey _kCFDateFormatterCalendarName diff --git a/TargetConditionals.h b/TargetConditionals.h index b256dae..80cb7a3 100644 --- a/TargetConditionals.h +++ b/TargetConditionals.h @@ -1,5 +1,5 @@ /* TargetConditionals.h - Copyright (c) 2010-2012, Apple Inc. All rights reserved. + Copyright (c) 2010-2013, Apple Inc. All rights reserved. For CF on Linux ONLY */ diff --git a/plconvert.c b/plconvert.c index 2a886ed..480e63b 100644 --- a/plconvert.c +++ b/plconvert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Apple Inc. All rights reserved. + * Copyright (c) 2013 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * -- 2.45.2